1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-text on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layouting
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face ¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å
44 ¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É
45 ¤¨¤â face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆó¼¡
48 ¸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
53 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
54 /*** @addtogroup m17nInternal
61 #include <sys/types.h>
65 #include "m17n-misc.h"
69 #include "internal-gui.h"
74 #include <fribidi/fribidi.h>
75 #endif /* HAVE_FRIBIDI */
77 #define MAX(x, y) ((x) > (y) ? (x) : (y))
78 #define MIN(x, y) ((x) < (y) ? (x) : (y))
80 static MSymbol M_glyph_string;
83 static MSymbol Mlatin, Minherited;
84 /* Special categories */
85 static MSymbol McatCc, McatCf;
87 static MSymbol Mdepth;
90 /* Glyph-string composer. */
92 static MSymbol MbidiR;
93 static MSymbol MbidiAL;
94 static MSymbol MbidiRLE;
95 static MSymbol MbidiRLO;
96 static MSymbol MbidiBN;
97 static MSymbol MbidiS;
100 visual_order (MGlyphString *gstring)
102 int len = gstring->used - 2;
104 int *idx = alloca (sizeof (int) * len);
106 int bidi_sensitive = gstring->control.orientation_reversed;
108 MGlyph *g = MGLYPH (1);
111 FriBidiCharType base = (gstring->control.orientation_reversed
112 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
113 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
115 FriBidiStrIndex *indices;
116 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
117 #else /* not HAVE_FRIBIDI */
118 int *logical = alloca (sizeof (int) * len);
120 char *levels = alloca (len);
121 #endif /* not HAVE_FRIBIDI */
123 while (g->type != GLYPH_ANCHOR)
125 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
127 if (bidi == MbidiR || bidi == MbidiAL
128 || bidi == MbidiRLE || bidi == MbidiRLO)
135 idx[size] = GLYPH_INDEX (g);
136 logical[size++] = g++->c;
137 while (g->type != GLYPH_ANCHOR && g->combining_code)
141 if (! bidi_sensitive)
144 glyphs = alloca (sizeof (MGlyph) * gstring->used);
145 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
147 visual = alloca (sizeof (FriBidiChar) * size);
148 indices = alloca (sizeof (FriBidiStrIndex) * size);
150 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
151 #else /* not HAVE_FRIBIDI */
152 indices = alloca (sizeof (int) * size);
153 for (i = 0; i < size; i++)
159 for (j = i + 1; j < size && levels[j]; j++);
160 for (k = j--; i < k; i++, j--)
167 #endif /* not HAVE_FRIBIDI */
169 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
170 starts from gstring->glyphs[IDX[N]].
172 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
173 originally at LOGICAL[INDICES[N]]. */
175 for (i = 0, gidx = 1; i < size; i++)
180 glyphs[k].bidi_level = levels[j];
182 if (visual[i] != logical[j])
185 glyphs[k].c = visual[i];
186 if (glyphs[k].rface->rfont)
187 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
190 #endif /* not HAVE_FRIBIDI */
191 *(MGLYPH (gidx)) = glyphs[k];
193 k < gstring->used - 1 && glyphs[k].combining_code;
196 glyphs[k].bidi_level = levels[j];
197 *(MGLYPH (gidx)) = glyphs[k];
203 reorder_combining_chars (MGlyphString *gstring, int from, int to)
205 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
211 for (g = gbeg; g != gend; g++)
212 if (COMBINING_CODE_CLASS (g->combining_code) > 0
213 && (COMBINING_CODE_CLASS (g[-1].combining_code)
214 > COMBINING_CODE_CLASS (g->combining_code)))
225 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
226 displaying them on FRAME.
228 This function fills members <type>, <rface>, <c>, <pos>, <to>,
229 <code> of glyphs. The other members are filled by
230 layout_glyph_string. */
233 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
234 MGlyphString *gstring)
236 MRealizedFace *default_rface = frame->rface;
237 int stop, face_change, language_change, charset_change;
240 MSymbol language = Mnil, script = Mnil, charset = Mnil;
241 MRealizedFace *rface = default_rface;
243 int size = gstring->control.fixed_width;
247 MLIST_RESET (gstring);
248 gstring->from = from;
250 /* At first generate glyphs while using the member <enabled> as a
251 flag for rface re-checking. */
254 /** Put anchor glyphs at the head and tail. */
255 g_tmp.type = GLYPH_ANCHOR;
256 g_tmp.pos = g_tmp.to = from;
258 APPEND_GLYPH (gstring, g_tmp);
260 stop = face_change = charset_change = language_change = pos = from;
268 if (pos < mtext_nchars (mt))
269 c = mtext_ref_char (mt, pos);
272 g_tmp.category = Mnil;
275 if (c == ' ' || c == '\n' || c == '\t')
276 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
278 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
282 g_tmp.category = mchar_get_prop (c, Mcategory);
283 g_tmp.type = GLYPH_CHAR;
284 this_script = (MSymbol) mchar_get_prop (c, Mscript);
285 if (this_script == Minherited)
286 this_script = script;
289 if (pos == stop || script != this_script
290 || MGLYPH (last)->type != g_tmp.type)
293 if (non_ascii_found && g->type == GLYPH_CHAR)
294 while (g < gstring->glyphs + gstring->used)
295 g = mface__for_chars (script, language, charset,
296 g, gstring->glyphs + gstring->used, size);
297 last = gstring->used;
299 script = this_script;
302 if (pos < mtext_nchars (mt) && pos == language_change)
304 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
305 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
307 if (pos < mtext_nchars (mt) && pos == charset_change)
309 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
310 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
312 if (pos < mtext_nchars (mt) && pos == face_change)
315 int num = mtext_get_prop_values (mt, pos, Mface,
316 (void **) faces, 64);
318 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
320 ? mface__realize (frame, faces, num,
321 language, charset, size)
325 if (stop > language_change)
326 stop = language_change;
327 if (stop > charset_change)
328 stop = charset_change;
329 if (face_change < stop)
333 g_tmp.c = g_tmp.code = c;
340 else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
343 APPEND_GLYPH (gstring, g_tmp);
345 g_tmp.code = g_tmp.c + 0x40;
349 APPEND_GLYPH (gstring, g_tmp);
351 && gstring->control.two_dimensional)
357 /* Append an anchor glyph. */
358 g_tmp.type = GLYPH_ANCHOR;
360 g_tmp.code = MCHAR_INVALID_CODE;
361 g_tmp.pos = g_tmp.to = pos;
363 APPEND_GLYPH (gstring, g_tmp);
367 /* Next, run FLT if necessary. */
368 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
372 if (this->type == GLYPH_CHAR && this->rface->rfont)
376 if (this->rface->rfont->layouter != Mnil)
381 for (prev = MGLYPH (start - 1);
382 (prev->type == GLYPH_CHAR
383 && prev->category == McatCf
384 && (code = mfont__encode_char (this->rface->rfont, prev->c)
385 != MCHAR_INVALID_CODE));
390 (g->type == GLYPH_CHAR
391 && (g->rface->rfont == this->rface->rfont
392 || (g->category == McatCf
393 && ((code = mfont__encode_char (this->rface->rfont,
395 != MCHAR_INVALID_CODE))));
397 if (g->rface->rfont != this->rface->rfont)
399 i = mfont__flt_run (gstring, start, i, this->rface);
403 while (this->type == GLYPH_CHAR
406 && MSYMBOL_NAME (this->category)[0] == 'M'
407 && this->rface->rfont
408 && this->rface->rfont->layouter == Mnil)
410 int class = (int) mchar_get_prop (this->c,
413 = MAKE_COMBINING_CODE_BY_CLASS (class);
417 reorder_combining_chars (gstring, start, i);
425 /* At last, reorder glyphs visually if necessary. */
426 if (gstring->control.enable_bidi)
427 visual_order (gstring);
432 combining_code_from_class (int class)
437 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
438 else if (class == 200) /* below left attached */
439 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
440 else if (class == 202) /* below attached*/
441 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
442 else if (class == 204) /* below right attached */
443 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
444 else if (class == 208) /* left attached */
445 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
446 else if (class == 210) /* right attached */
447 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
448 else if (class == 212) /* above left attached */
449 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
450 else if (class == 214) /* above attached */
451 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
452 else if (class == 216) /* above right attached */
453 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
454 else if (class == 218) /* below left */
455 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
456 else if (class == 220) /* below */
457 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
458 else if (class == 222) /* below right */
459 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
460 else if (class == 224) /* left */
461 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
462 else if (class == 226) /* right */
463 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
464 else if (class == 228) /* above left */
465 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
466 else if (class == 230) /* above */
467 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
468 else if (class == 232) /* above right */
469 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
470 else if (class == 233) /* double below */
471 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
472 else if (class == 234) /* double above */
473 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
474 else if (class == 240) /* iota subscript */
475 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
477 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
483 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
485 int g_physical_ascent, g_physical_descent;
486 int g_width, g_lbearing, g_rbearing;
487 MGlyph *g = MGLYPH (from);
488 MGlyph *last_g = MGLYPH (to);
490 g_physical_ascent = gstring->physical_ascent;
491 g_physical_descent = gstring->physical_descent;
492 g_width = g_lbearing = g_rbearing = 0;
494 mfont__get_metric (gstring, from, to);
499 MRealizedFont *rfont = base->rface->rfont;
500 int size = rfont->font.property[MFONT_SIZE];
501 int width, lbearing, rbearing;
503 if (g == last_g || ! g->combining_code)
506 if (base->left_padding && base->lbearing < 0)
508 base->xoff = - base->lbearing;
509 base->width += base->xoff;
510 base->rbearing += base->xoff;
513 if (base->right_padding && base->rbearing > base->width)
515 base->width = base->rbearing;
517 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
518 rbearing = base->rbearing;
522 /* With combining glyphs. */
523 int left = -base->width;
525 int top = - base->ascent;
526 int bottom = base->descent;
527 int height = bottom - top;
528 int begin = base->pos;
533 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
534 rbearing = base->rbearing;
536 while (g != last_g && g->combining_code)
538 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
540 combining_code = g->combining_code;
541 if (COMBINING_BY_CLASS_P (combining_code))
542 g->combining_code = combining_code
543 = combining_code_from_class (COMBINING_CODE_CLASS
546 rfont = g->rface->rfont;
547 size = rfont->font.property[MFONT_SIZE];
548 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
550 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
552 base_x = COMBINING_CODE_BASE_X (combining_code);
553 base_y = COMBINING_CODE_BASE_Y (combining_code);
554 add_x = COMBINING_CODE_ADD_X (combining_code);
555 add_y = COMBINING_CODE_ADD_Y (combining_code);
559 else if (end < g->to)
562 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
565 if (g->xoff + g->width > right)
566 right = g->xoff + g->width;
567 width = right - left;
568 if (g->xoff + g->lbearing < left + lbearing)
569 lbearing = g->xoff + g->lbearing - left;
570 if (g->xoff + g->rbearing > left + rbearing)
571 rbearing = g->xoff + g->rbearing - left;
574 g->yoff = top + height * base_y / 2;
578 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
580 if (g->yoff - g->ascent < top)
581 top = g->yoff - g->ascent;
582 if (g->yoff + g->descent > bottom)
583 bottom = g->yoff + g->descent;
584 height = bottom - top;
590 base->ascent = - top;
591 base->descent = bottom;
592 base->lbearing = lbearing;
593 base->rbearing = rbearing;
594 if (left < - base->width)
596 base->xoff = - base->width - left;
597 base->width += base->xoff;
598 base->rbearing += base->xoff;
599 base->lbearing += base->xoff;
603 base->width += right;
604 base->rbearing += right;
605 base->right_padding = 1;
606 for (i = 1; base + i != g; i++)
607 base[i].xoff -= right;
610 for (i = 0; base + i != g; i++)
617 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
618 g_physical_descent = MAX (g_physical_descent, base->descent);
619 g_lbearing = MIN (g_lbearing, g_width + lbearing);
620 g_rbearing = MAX (g_rbearing, g_width + rbearing);
621 g_width += base->width;
624 gstring->physical_ascent = g_physical_ascent;
625 gstring->physical_descent = g_physical_descent;
626 gstring->sub_width = g_width;
627 gstring->sub_lbearing = g_lbearing;
628 gstring->sub_rbearing = g_rbearing;
632 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
633 by this function directly. Character glyphs are handled by
634 layouter functions registered in font drivers.
636 This function fill-in all the remaining members of glyphs. */
639 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
641 /* Default width of TAB. */
642 int tab_width = frame->space_width * (gstring->control.tab_width
643 ? gstring->control.tab_width : 8);
647 MDrawControl *control = &(gstring->control);
650 int box_line_height = 0;
651 int ignore_formatting_char = control->ignore_formatting_char;
653 gstring->ascent = gstring->descent = 0;
654 gstring->physical_ascent = gstring->physical_descent = 0;
655 gstring->width = gstring->lbearing = gstring->rbearing = 0;
659 while (g->type != GLYPH_ANCHOR)
661 if (box != g->rface->box)
663 int gidx = GLYPH_INDEX (g);
667 /* Insert the right side of the box. That glyph belongs
668 to the previous grapheme cluster. */
669 MGlyph box_glyph = g[-1];
671 box_glyph.type = GLYPH_BOX;
673 = (control->fixed_width
675 : box->inner_hmargin + box->width + box->outer_hmargin);
676 box_glyph.lbearing = 0;
677 box_glyph.rbearing = box_glyph.width;
679 box_glyph.right_padding = 1;
680 gstring->width += box_glyph.width;
681 gstring->rbearing += box_glyph.width;
682 INSERT_GLYPH (gstring, gidx, box_glyph);
689 /* Insert the left side of the box. That glyph belongs
690 to the following grapheme cluster. */
691 MGlyph box_glyph = *g;
692 int box_height = (box->width
693 + box->inner_vmargin + box->outer_vmargin);
695 if (box_line_height < box_height)
696 box_line_height = box_height;
697 box_glyph.type = GLYPH_BOX;
699 = (control->fixed_width
701 : box->inner_hmargin + box->width + box->outer_hmargin);
702 box_glyph.lbearing = 0;
703 box_glyph.rbearing = box_glyph.width;
705 box_glyph.left_padding = 1;
706 gstring->width += box_glyph.width;
707 gstring->rbearing += box_glyph.width;
708 INSERT_GLYPH (gstring, gidx, box_glyph);
714 if (g->category == McatCf && ignore_formatting_char)
715 g->type = GLYPH_SPACE;
717 if (g->type == GLYPH_CHAR)
719 MRealizedFace *rface = g->rface;
720 MRealizedFont *rfont = rface->rfont;
722 int from = GLYPH_INDEX (g);
724 for (g++; g->type == GLYPH_CHAR; g++)
725 if (! rfont != ! g->rface->rfont
726 || box != g->rface->box
727 || ((fromg->code == MCHAR_INVALID_CODE)
728 != (g->code == MCHAR_INVALID_CODE))
729 || (g->category == McatCf && ignore_formatting_char))
731 if (rfont && fromg->code != MCHAR_INVALID_CODE)
734 int to = GLYPH_INDEX (g);
736 layout_glyphs (frame, gstring, from, to);
737 extra_width = - gstring->sub_lbearing;
739 && (GLYPH_INDEX (g) > 1
740 || control->align_head))
744 pad.type = GLYPH_PAD;
747 pad.width = pad.rbearing = extra_width;
748 INSERT_GLYPH (gstring, from, pad);
750 gstring->sub_lbearing = 0;
751 gstring->sub_width += extra_width;
752 gstring->sub_rbearing += extra_width;
754 g = MGLYPH (from - 1);
755 if (g->type == GLYPH_SPACE)
757 /* The pad just inserted is absorbed (maybe
758 partially) by the previous space while
759 keeping at least some space width. For the
760 moment, we use the arbitrary width 2-pixel.
761 Perhaps, it should be decided by the current
762 face, or a default value of the current
763 frame, which is, however, not yet
765 if (extra_width + 2 < g->width)
767 g->width -= extra_width;
771 extra_width -= g->width - 2;
774 gstring->width -= extra_width;
775 gstring->rbearing -= extra_width;
779 extra_width = gstring->sub_rbearing - gstring->sub_width;
783 if (g->type == GLYPH_SPACE && box == g->rface->box)
787 pad.type = GLYPH_PAD;
790 pad.width = pad.rbearing = extra_width;
791 INSERT_GLYPH (gstring, to, pad);
795 g[-1].width += extra_width;
796 gstring->sub_width += extra_width;
799 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
800 gstring->lbearing = gstring->width + gstring->sub_lbearing;
801 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
802 gstring->rbearing = gstring->width + gstring->sub_rbearing;
803 gstring->width += gstring->sub_width;
804 if (gstring->ascent < rface->ascent)
805 gstring->ascent = rface->ascent;
806 if (gstring->descent < rface->descent)
807 gstring->descent = rface->descent;
812 for (; fromg < g; fromg++)
814 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
815 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
816 fromg->width = fromg->rbearing = 1;
818 fromg->width = fromg->rbearing = rface->space_width;
819 fromg->xoff = fromg->lbearing = 0;
820 fromg->ascent = fromg->descent = 0;
821 gstring->width += fromg->width;
822 gstring->rbearing += fromg->width;
824 if (gstring->ascent < frame->rface->ascent)
825 gstring->ascent = frame->rface->ascent;
826 if (gstring->descent < frame->descent)
827 gstring->descent = frame->rface->descent;
830 else if (g->type == GLYPH_SPACE)
833 g->width = g->rface->space_width;
834 else if (g->c == '\n')
836 g->width = control->cursor_width;
839 if (control->cursor_bidi)
841 else if (g->width < 0)
842 g->width = g->rface->space_width;
845 else if (g->c == '\t')
847 g->width = tab_width - ((gstring->indent + gstring->width)
853 if (g[-1].type == GLYPH_PAD)
855 /* This space glyph absorbs (maybe partially) the
856 previous padding glyph. */
857 g->width -= g[-1].width;
859 /* But, keep at least some space width. For the
860 moment, we use the arbitrary width 2-pixel. */
863 g->rbearing = g->width;
864 gstring->width += g->width;
865 gstring->rbearing += g->width;
868 if (gstring->ascent < g->rface->ascent)
869 gstring->ascent = g->rface->ascent;
870 if (gstring->descent < g->rface->descent)
871 gstring->descent = g->rface->descent;
877 gstring->width += g->width;
878 gstring->rbearing += g->width;
885 /* Insert the right side of the box. */
886 int gidx = GLYPH_INDEX (g);
887 MGlyph box_glyph = g[-1];
889 box_glyph.type = GLYPH_BOX;
891 = (control->fixed_width
893 : box->inner_hmargin + box->width + box->outer_hmargin);
894 box_glyph.lbearing = 0;
895 box_glyph.rbearing = box_glyph.width;
897 box_glyph.right_padding = 1;
898 gstring->width += box_glyph.width;
899 gstring->rbearing += box_glyph.width;
900 INSERT_GLYPH (gstring, gidx, box_glyph);
903 gstring->text_ascent = gstring->ascent;
904 gstring->text_descent = gstring->descent;
905 if (gstring->text_ascent < gstring->physical_ascent)
906 gstring->text_ascent = gstring->physical_ascent;
907 if (gstring->text_descent < gstring->physical_descent)
908 gstring->text_descent = gstring->physical_descent;
909 gstring->line_ascent = gstring->text_ascent;
910 gstring->line_descent = gstring->text_descent;
911 if (box_line_height > 0)
913 gstring->line_ascent += box_line_height;
914 gstring->physical_ascent = gstring->line_ascent;
915 gstring->line_descent += box_line_height;
916 gstring->physical_descent = gstring->line_descent;
919 if (gstring->line_ascent < control->min_line_ascent)
920 gstring->line_ascent = control->min_line_ascent;
921 else if (control->max_line_ascent
922 && control->max_line_ascent > control->min_line_ascent
923 && gstring->line_ascent > control->max_line_ascent)
924 gstring->line_ascent = control->max_line_ascent;
926 if (gstring->line_descent < control->min_line_descent)
927 gstring->line_descent = control->min_line_descent;
928 else if (control->max_line_descent
929 && control->max_line_descent > control->min_line_descent
930 && gstring->line_descent > control->max_line_descent)
931 gstring->line_descent = control->max_line_descent;
932 gstring->height = gstring->line_ascent + gstring->line_descent;
934 if (control->orientation_reversed
937 /* We must adjust TAB width for RTL orientation. */
938 width = gstring->indent;
940 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
942 if (g->type == GLYPH_CHAR && g->c == '\t')
944 int this_width = tab_width - (width % tab_width);
946 if (g[1].type == GLYPH_PAD)
947 this_width -= g[1].width;
948 if (g[-1].type == GLYPH_PAD)
949 this_width -= g[-1].width;
952 gstring->width += this_width - g->width;
953 gstring->rbearing += this_width - g->width;
954 g->width = this_width;
965 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
966 MGlyphString *gstring, int from, int to,
967 int *from_idx, int *to_idx, int *to_x)
969 MGlyph *g = MGLYPH (1);
970 MDrawRegion region = (MDrawRegion) NULL;
971 MDrawControl *control = &gstring->control;
974 int cursor_bidi = control->cursor_bidi;
976 if (control->with_cursor && control->cursor_width)
978 if (gstring->from <= control->cursor_pos
979 && gstring->to > control->cursor_pos)
980 cursor_pos = control->cursor_pos;
982 && gstring->from <= control->cursor_pos - 1
983 && gstring->to > control->cursor_pos - 1)
984 prev_pos = control->cursor_pos - 1;
987 *from_idx = *to_idx = 0;
988 while (g->type != GLYPH_ANCHOR)
990 if (g->pos >= from && g->pos < to)
992 MGlyph *fromg = g, *cursor = NULL;
993 MRealizedFace *rface = g->rface;
995 int cursor_width = 0;
999 *from_idx = GLYPH_INDEX (g);
1000 while (g->pos >= from && g->pos < to
1001 && g->rface == rface)
1004 if (g->type != GLYPH_BOX
1005 && g->pos <= cursor_pos && g->to > cursor_pos)
1008 cursor = g, cursor_x = x + width;
1009 cursor_width += g->width;
1011 width += g++->width;
1014 && (control->as_image
1015 || rface->face.property[MFACE_BACKGROUND] != Mnil
1016 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1018 int this_x = x, this_width = width;
1020 if (fromg->type == GLYPH_BOX)
1021 this_x += fromg->width, this_width -= fromg->width;
1022 if (g[-1].type == GLYPH_BOX)
1023 this_width -= g[-1].width;
1024 mwin__fill_space (frame, win, rface, 0,
1025 this_x, y - gstring->text_ascent, this_width,
1026 gstring->text_ascent + gstring->text_descent,
1027 control->clip_region);
1034 rect.y = y - gstring->text_ascent;
1035 rect.height = gstring->text_ascent + gstring->text_descent;
1038 rect.width = ((control->cursor_width > 0
1039 && control->cursor_width < cursor_width)
1040 ? control->cursor_width : cursor_width);
1044 if (cursor->bidi_level % 2)
1045 rect.x += cursor_width - 1;
1048 mwin__fill_space (frame, win, rface, 1,
1049 rect.x, rect.y, rect.width, rect.height,
1050 control->clip_region);
1052 region = mwin__region_from_rect (&rect);
1054 mwin__region_add_rect (region, &rect);
1055 mwin__verify_region (frame, region);
1058 if (cursor->bidi_level % 2)
1061 rect.width = cursor_width < 4 ? cursor_width : 4;
1062 mwin__fill_space (frame, win, rface, 1,
1063 rect.x, rect.y, rect.width, rect.height,
1064 control->clip_region);
1065 mwin__region_add_rect (region, &rect);
1066 mwin__verify_region (frame, region);
1078 if (fromg->type != GLYPH_BOX
1079 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1082 cursor = fromg, cursor_x = x + temp_width;
1083 cursor_width += fromg->width;
1085 temp_width += fromg++->width;
1092 if (! (cursor->bidi_level % 2))
1093 rect.x += cursor_width - 1;
1094 rect.y = y - gstring->text_ascent;
1095 rect.height = gstring->text_ascent + gstring->text_descent;
1097 mwin__fill_space (frame, win, rface, 1,
1098 rect.x, rect.y, rect.width, rect.height,
1099 control->clip_region);
1101 region = mwin__region_from_rect (&rect);
1103 mwin__region_add_rect (region, &rect);
1104 mwin__verify_region (frame, region);
1105 rect.y += rect.height - 2;
1107 rect.width = cursor_width < 4 ? cursor_width : 4;
1108 if (! (cursor->bidi_level % 2))
1109 rect.x -= rect.width - 1;
1110 mwin__fill_space (frame, win, rface, 1,
1111 rect.x, rect.y, rect.width, rect.height,
1112 control->clip_region);
1113 mwin__region_add_rect (region, &rect);
1114 mwin__verify_region (frame, region);
1118 *to_idx = GLYPH_INDEX (g);
1128 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1129 MGlyphString *gstring, int from_idx, int to_idx,
1130 int reverse, MDrawRegion region)
1132 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1138 mwin__region_to_rect (region, &rect);
1141 while (g != gend && x + g->rbearing <= rect.x)
1144 width -= g++->width;
1145 while (! g->enabled && g != gend)
1149 rect.x += rect.width;
1150 if (rect.x < x + width)
1153 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1155 width -= (--gend)->width;
1156 while (! gend->enabled && g != gend)
1160 while (gend[-1].to == gend->to) gend++;
1168 MRealizedFace *rface = g->rface;
1169 int width = g->width;
1170 MGlyph *from_g = g++;
1172 /* Handle the glyphs of the same type/face at once. */
1174 && g->type == from_g->type
1175 && g->rface == rface
1176 && (g->code < 0) == (from_g->code < 0)
1178 width += g++->width;
1180 if (from_g->type == GLYPH_CHAR)
1182 MFontDriver *driver;
1184 if (rface->rfont && from_g->code >= 0)
1185 driver = rface->rfont->driver;
1187 driver = mfont__driver_list[MFONT_TYPE_WIN];
1188 (driver->render) (win, x, y, gstring, from_g, g,
1191 else if (from_g->type == GLYPH_BOX)
1193 /* Draw the left or right side of a box. If
1194 from_g->lbearing is nonzero, this is the left side,
1195 else this is the right side. */
1196 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1199 if (from_g->type != GLYPH_BOX)
1202 mwin__draw_hline (frame, win, gstring, rface, reverse,
1203 x, y, width, region);
1206 /* Draw the top and bottom side of a box. */
1207 mwin__draw_box (frame, win, gstring, from_g,
1208 x, y, width, region);
1219 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1220 int *from_x, int *to_x)
1223 int left_idx = *left, right_idx = *right;
1224 int left_x, right_x, x;
1226 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1229 if (x + g->rbearing > 0)
1231 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1233 left_idx = GLYPH_INDEX (g);
1238 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1241 if (x - g->width + g->lbearing < 0)
1243 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1245 right_idx = GLYPH_INDEX (g) + 1;
1250 if (*left == left_idx && *right == right_idx)
1253 if (*left != left_idx)
1255 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1260 if (*right != right_idx)
1262 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1272 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1277 if (from <= gstring->from && to >= gstring->to)
1280 *rbearing = gstring->rbearing;
1281 return gstring->width;
1286 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1287 if (g->pos >= from && g->pos < to)
1289 if (rbearing && width + g->rbearing > *rbearing)
1290 *rbearing = width + g->rbearing;
1298 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1299 MGlyphString *gstring, int from, int to)
1301 MDrawControl *control = &gstring->control;
1303 MDrawRegion clip_region, cursor_region;
1304 int from_idx, to_idx;
1307 if (control->orientation_reversed)
1308 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1310 x += gstring->indent;
1312 /* At first, draw all glyphs without cursor. */
1313 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1314 &from_idx, &to_idx, &to_x);
1316 if (control->partial_update)
1319 rect.width = to_x - x;
1320 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1322 rect.y = y - gstring->line_ascent;
1323 rect.height = gstring->height;
1324 clip_region = mwin__region_from_rect (&rect);
1325 if (control->clip_region)
1326 mwin__intersect_region (clip_region, control->clip_region);
1329 clip_region = control->clip_region;
1332 clip_region = control->clip_region;
1334 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1339 mwin__intersect_region (cursor_region, clip_region);
1340 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1343 if (clip_region != control->clip_region)
1344 mwin__free_region (clip_region);
1346 mwin__free_region (cursor_region);
1350 static int gstring_num;
1353 free_gstring (void *object)
1355 MGlyphString *gstring = (MGlyphString *) object;
1358 free_gstring (gstring->next);
1359 if (gstring->size > 0)
1360 free (gstring->glyphs);
1366 static MGlyphString scratch_gstring;
1368 static MGlyphString *
1369 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1372 MGlyphString *gstring;
1374 if (pos == mt->nchars)
1376 gstring = &scratch_gstring;
1380 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1381 MLIST_INIT1 (gstring, glyphs, 128);
1385 gstring->top = gstring;
1387 gstring->control = *control;
1388 gstring->indent = gstring->width_limit = 0;
1389 if (control->format)
1390 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1392 gstring->width_limit = control->max_line_width;
1393 gstring->anti_alias = control->anti_alias;
1394 if (gstring->anti_alias
1395 && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
1396 gstring->anti_alias = 0;
1400 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1403 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1411 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1412 a width of glyphs for the character at I of GSTRING->mt. If I is
1413 not a beginning of a grapheme cluster, the corresponding element
1415 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1416 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1417 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1418 pos_width[g->pos - gstring->from] += g->width;
1419 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1421 if (pos_width[i] > 0)
1423 if (width + pos_width[i] > gstring->width_limit)
1426 width += pos_width[i];
1429 pos = gstring->from + i;
1430 if (gstring->control.line_break)
1432 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1433 gstring->from, gstring->to, 0, 0);
1434 if (pos <= gstring->from || pos >= gstring->to)
1437 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1438 layout_glyph_string (frame, gstring);
1442 /* Return a gstring that covers a character at POS. */
1444 static MGlyphString *
1445 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1447 MGlyphString *gstring = NULL;
1449 if (pos < mtext_nchars (mt))
1451 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1454 && ((prop->start != 0
1455 && mtext_ref_char (mt, prop->start - 1) != '\n')
1456 || (prop->end < mtext_nchars (mt)
1457 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1459 mtext_detach_property (prop);
1464 gstring = prop->val;
1465 if (memcmp (control, &gstring->control,
1466 (char *) (&control->with_cursor)
1467 - (char *) (control)))
1469 mtext_detach_property (prop);
1474 else if (! control->cursor_width)
1482 offset = mtext_character (mt, pos, 0, '\n');
1487 offset -= gstring->from;
1489 for (gst = gstring; gst; gst = gst->next)
1493 gst->from += offset;
1495 for (i = 0; i < gst->used; i++)
1497 gst->glyphs[i].pos += offset;
1498 gst->glyphs[i].to += offset;
1501 M17N_OBJECT_REF (gstring);
1506 int line = 0, y = 0;
1508 if (control->two_dimensional)
1510 beg = mtext_character (mt, pos, 0, '\n');
1515 end = mtext_nchars (mt) + (control->cursor_width != 0);
1522 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1523 compose_glyph_string (frame, mt, beg, end, gstring);
1524 layout_glyph_string (frame, gstring);
1526 if (control->two_dimensional
1527 && gstring->width_limit
1528 && gstring->width > gstring->width_limit)
1530 MGlyphString *gst = gstring;
1532 truncate_gstring (frame, mt, gst);
1533 while (gst->to < end)
1535 line++, y += gst->height;
1536 gst->next = alloc_gstring (frame, mt, gst->from, control,
1538 gst->next->top = gstring;
1539 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1541 layout_glyph_string (frame, gst);
1542 if (gst->width <= gst->width_limit)
1544 truncate_gstring (frame, mt, gst);
1548 if (! control->disable_caching && pos < mtext_nchars (mt))
1550 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1551 MTEXTPROP_VOLATILE_STRONG);
1553 if (end > mtext_nchars (mt))
1554 end = mtext_nchars (mt);
1555 mtext_attach_property (mt, beg, end, prop);
1556 M17N_OBJECT_UNREF (prop);
1560 while (gstring->to <= pos)
1562 if (! gstring->next)
1564 gstring = gstring->next;
1566 gstring->control = *control;
1572 static MDrawControl control_noop;
1574 #define ASSURE_CONTROL(control) \
1576 control = &control_noop; \
1581 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1582 MText *mt, int from, int to,
1583 MDrawControl *control)
1585 MGlyphString *gstring;
1587 M_CHECK_POS_X (mt, from, -1);
1588 ASSURE_CONTROL (control);
1589 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1590 to = mtext_nchars (mt) + (control->cursor_width != 0);
1594 gstring = get_gstring (frame, mt, from, to, control);
1596 MERROR (MERROR_DRAW, -1);
1597 render_glyph_string (frame, win, x, y, gstring, from, to);
1601 y += gstring->line_descent;
1602 M17N_OBJECT_UNREF (gstring->top);
1603 gstring = get_gstring (frame, mt, from, to, control);
1604 y += gstring->line_ascent;
1605 render_glyph_string (frame, win, x, y, gstring, from, to);
1608 M17N_OBJECT_UNREF (gstring->top);
1615 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1621 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1622 if (g->pos <= pos && g->to > pos)
1627 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1628 if (g->pos <= pos && g->to > pos)
1635 /* for debugging... */
1639 dump_combining_code (int code)
1641 char *vallign = "tcbB";
1642 char *hallign = "lcr";
1648 if (COMBINING_BY_CLASS_P (code))
1649 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1650 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1651 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1652 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1653 off_x = COMBINING_CODE_OFF_X (code) - 128;
1655 sprintf (work + 2, "+%d", off_y);
1657 sprintf (work + 2, "%d", off_y);
1658 else if (off_x == 0)
1659 sprintf (work + 2, ".");
1660 p = work + strlen (work);
1662 sprintf (p, ">%d", off_x);
1664 sprintf (p, "<%d", -off_x);
1666 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1667 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1673 dump_gstring (MGlyphString *gstring, int indent)
1675 char *prefix = (char *) alloca (indent + 1);
1676 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1678 memset (prefix, 32, indent);
1681 fprintf (stderr, "(glyph-string");
1683 for (g = MGLYPH (0); g < last_g; g++)
1685 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1687 g - gstring->glyphs,
1688 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1689 : g->type == GLYPH_ANCHOR ? "ANC"
1690 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1691 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1692 dump_combining_code (g->combining_code),
1693 g->width, g->bidi_level);
1694 fprintf (stderr, ")");
1698 /* m17n-X internal APIs */
1703 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1705 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1706 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1708 Mlatin = msymbol ("latin");
1709 Minherited = msymbol ("inherited");
1711 McatCc = msymbol ("Cc");
1712 McatCf = msymbol ("Cf");
1713 Mdepth = msymbol ("depth");
1715 MbidiR = msymbol ("R");
1716 MbidiAL = msymbol ("AL");
1717 MbidiRLE = msymbol ("RLE");
1718 MbidiRLO = msymbol ("RLO");
1719 MbidiBN = msymbol ("BN");
1720 MbidiS = msymbol ("S");
1722 fribidi_set_mirroring (TRUE);
1731 MLIST_FREE1 (&scratch_gstring, glyphs);
1735 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1739 /*** @addtogroup m17nDraw */
1744 @brief Draw an M-text on a window.
1746 The mdraw_text () function draws the text between $FROM and $TO of
1747 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1749 The appearance of the text (size, style, color, etc) is specified
1750 by the value of the text property whose key is @c Mface. If the
1751 M-text or a part of the M-text does not have such a text property,
1752 the default face of $FRAME is used.
1754 The font used to draw a character in the M-text is selected from
1755 the value of the fontset property of a face by the following
1760 <li> Search the text properties given to the character for the one
1761 whose key is @c Mcharset; its value should be either a symbol
1762 specifying a charset or #Mnil. If the value is #Mnil,
1763 proceed to the next step.
1765 Otherwise, search the mapping table of the fontset for the
1766 charset. If no entry is found proceed to the next step.
1768 If an entry is found, use one of the fonts in the entry that
1769 has a glyph for the character and that matches best with the
1770 face properties. If no such font exists, proceed to the next
1773 <li> Get the character property "script" of the character. If it is
1774 inherited, get the script property from the previous
1775 characters. If there is no previous character, or none of
1776 them has the script property other than inherited, proceed to
1779 Search the text properties given to the character for the one
1780 whose key is @c Mlanguage; its value should be either a
1781 symbol specifying a language or @c Mnil.
1783 Search the mapping table of the fontset for the combination
1784 of the script and language. If no entry is found, proceed to
1787 If an entry is found, use one of the fonts in the entry that
1788 has a glyph for the character and that matches best with the
1789 face properties. If no such font exists, proceed to the next
1792 <li> Search the fall-back table of the fontset for a font that has
1793 a glyph of the character. If such a font is found, use that
1798 If no font is found by the algorithm above, this function draws an
1799 empty box for the character.
1801 This function draws only the glyph foreground. To specify the
1802 background color, use mdraw_image_text () or
1803 mdraw_text_with_control ().
1805 This function is the counterpart of <tt>XDrawString ()</tt>,
1806 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1807 in the X Window System.
1810 If the operation was successful, mdraw_text () returns 0. If an
1811 error is detected, it returns -1 and assigns an error code to the
1812 external variable #merror_code. */
1814 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë
1816 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1817 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1820 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1821 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1822 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1823 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1825 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1826 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1830 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1831 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1832 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1833 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1834 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1837 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1838 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1839 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1842 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1843 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1844 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1845 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1847 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1848 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1851 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1852 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1855 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1856 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1857 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1860 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1861 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1865 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1866 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1868 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1869 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1872 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1873 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1876 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1877 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1879 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1886 mdraw_image_text () */
1889 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1890 MText *mt, int from, int to)
1892 MDrawControl control;
1894 memset (&control, 0, sizeof control);
1895 control.as_image = 0;
1896 return draw_text (frame, win, x, y, mt, from, to, &control);
1903 @brief Draw an M-text on a window as an image
1905 The mdraw_image_text () function draws the text between $FROM and
1906 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1907 coordinate ($X, $Y).
1909 The way to draw a text is the same as in mdraw_text () except that
1910 this function also draws the background with the color specified
1913 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1914 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1915 functions in the X Window System.
1918 If the operation was successful, mdraw_image_text () returns 0.
1919 If an error is detected, it returns -1 and assigns an error code
1920 to the external variable #merror_code. */
1923 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯
1925 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1926 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1929 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1930 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1932 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1933 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1937 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1938 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1941 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1951 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1952 MText *mt, int from, int to)
1954 MDrawControl control;
1956 memset (&control, 0, sizeof control);
1957 control.as_image = 1;
1958 return draw_text (frame, win, x, y, mt, from, to, &control);
1964 @brief Draw an M-text on a window with fine control.
1966 The mdraw_text_with_control () function draws the text between
1967 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1968 coordinate ($X, $Y).
1970 The way to draw a text is the same as in mdraw_text () except that
1971 this function also follows what specified in the drawing control
1974 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1975 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1976 breaks lines and the following characters are drawn in the next
1977 line. See the documentation of the structure @ MDrawControl for
1981 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë
1983 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1984 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
1987 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
1988 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1990 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
1991 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
1992 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
1996 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
1997 MText *mt, int from, int to, MDrawControl *control)
1999 return draw_text (frame, win, x, y, mt, from, to, control);
2005 @brief Compute text pixel width.
2007 The mdraw_text_extents () function computes the width of text
2008 between $FROM and $TO of M-text $MT when it is drawn on a window
2009 of frame $FRAME using the mdraw_text_with_control () function with
2010 the drawing control object $CONTROL.
2012 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2013 the bounding box of character ink of the M-text, and stores the
2014 results in the members of the structure pointed to by
2015 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2016 surrounding box, the box is included in the bounding box.
2018 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2019 computes the bounding box that provides mininum spacing to other
2020 graphical features (such as surrounding box) for the M-text, and
2021 stores the results in the members of the structure pointed to by
2022 $OVERALL_LOGICAL_RETURN.
2024 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2025 computes the bounding box that provides mininum spacing to the
2026 other M-text drawn, and stores the results in the members of the
2027 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2028 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2029 min_line_ascent, min_line_descent, max_line_ascent, and
2030 max_line_descent of $CONTROL are all zero.
2033 This function returns the width of the text to be drawn in the
2034 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2035 text is drawn in multiple physical lines, it returns the width of
2036 the widest line. If an error occurs, it returns -1 and assigns an
2037 error code to the external variable #merror_code. */
2041 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë
2043 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2044 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2045 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2047 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2048 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2049 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë surrounding box
2050 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2052 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2053 ¤È¾¤Î graphical feature ¡Êsurrounding box ¤Ê¤É¡Ë¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹
2054 ¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½Â¤ÂÎ
2055 ¤Î¥á¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2057 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2058 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2059 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2060 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2061 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2062 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2064 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2065 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2066 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2067 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2069 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2076 mdraw_text_extents (MFrame *frame,
2077 MText *mt, int from, int to, MDrawControl *control,
2078 MDrawMetric *overall_ink_return,
2079 MDrawMetric *overall_logical_return,
2080 MDrawMetric *overall_line_return)
2082 MGlyphString *gstring;
2084 int width, rbearing;
2086 ASSURE_CONTROL (control);
2087 M_CHECK_POS_X (mt, from, -1);
2088 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2089 to = mtext_nchars (mt) + (control->cursor_width != 0);
2093 gstring = get_gstring (frame, mt, from, to, control);
2095 MERROR (MERROR_DRAW, -1);
2096 width = gstring_width (gstring, from, to, &rbearing);
2097 if (overall_ink_return)
2099 overall_ink_return->y = - gstring->physical_ascent;
2100 overall_ink_return->x = gstring->lbearing;
2102 if (overall_logical_return)
2104 overall_logical_return->y = - gstring->ascent;
2105 overall_logical_return->x = 0;
2107 if (overall_line_return)
2109 overall_line_return->y = - gstring->line_ascent;
2110 overall_line_return->x = gstring->lbearing;
2113 for (from = gstring->to; from < to; from = gstring->to)
2115 int this_width, this_rbearing;
2117 y += gstring->line_descent;
2118 M17N_OBJECT_UNREF (gstring->top);
2119 gstring = get_gstring (frame, mt, from, to, control);
2120 this_width = gstring_width (gstring, from, to, &this_rbearing);
2121 y += gstring->line_ascent;
2122 if (width < this_width)
2124 if (rbearing < this_rbearing)
2125 rbearing = this_rbearing;
2127 if (overall_ink_return)
2129 overall_ink_return->width = rbearing;
2130 overall_ink_return->height
2131 = y + gstring->physical_descent - overall_ink_return->y;
2133 if (overall_logical_return)
2135 overall_logical_return->width = width;
2136 overall_logical_return->height
2137 = y + gstring->descent - overall_logical_return->y;
2139 if (overall_line_return)
2141 overall_line_return->width = MAX (width, rbearing);
2142 overall_line_return->height
2143 = y + gstring->line_descent - overall_line_return->y;
2146 M17N_OBJECT_UNREF (gstring->top);
2153 @brief Compute the text dimensions of each character of M-text.
2155 The mdraw_text_per_char_extents () function computes the drawn
2156 metric of each character between $FROM and $TO of M-text $MT
2157 assuming that they are drawn on a window of frame $FRAME using the
2158 mdraw_text_with_control () function with the drawing control
2161 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2162 $LOGICAL_ARRAY_RETURN. Each successive element of
2163 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2164 ink and logical metrics of successive characters respectively,
2165 relative to the drawing origin of the M-text. The number of
2166 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2167 been set is returned to $NUM_CHARS_RETURN.
2169 If $ARRAY_SIZE is too small to return all metrics, the function
2170 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2171 Otherwise, it returns zero.
2173 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2174 @c NULL, this function also computes the metrics of the overall
2175 text and stores the results in the members of the structure
2176 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2178 If $CONTROL->two_dimensional is nonzero, this function computes
2179 only the metrics of characters in the first line. */
2181 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2182 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2183 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2184 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2185 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2187 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2188 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2189 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2190 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2191 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2193 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2194 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2197 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2198 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2199 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2202 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2203 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2206 mdraw_text_per_char_extents (MFrame *frame,
2207 MText *mt, int from, int to,
2208 MDrawControl *control,
2209 MDrawMetric *ink_array_return,
2210 MDrawMetric *logical_array_return,
2212 int *num_chars_return,
2213 MDrawMetric *overall_ink_return,
2214 MDrawMetric *overall_logical_return)
2216 MGlyphString *gstring;
2220 ASSURE_CONTROL (control);
2221 *num_chars_return = to - from;
2222 if (array_size < *num_chars_return)
2224 if (overall_logical_return)
2225 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2226 if (overall_ink_return)
2227 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2229 M_CHECK_RANGE (mt, from, to, -1, 0);
2230 gstring = get_gstring (frame, mt, from, to, control);
2233 *num_chars_return = 0;
2237 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2238 if (g->pos >= from && g->pos < to)
2242 int width = g->width;
2243 int lbearing = g->lbearing;
2244 int rbearing = g->rbearing;
2245 int ascent = g->ascent;
2246 int descent = g->descent;
2247 int logical_ascent = g->rface->rfont->ascent;
2248 int logical_descent = g->rface->rfont->descent;
2250 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2252 if (lbearing < width + g->lbearing)
2253 lbearing = width + g->lbearing;
2254 if (rbearing < width + g->rbearing)
2255 rbearing = width + g->rbearing;
2257 if (ascent < g->ascent)
2259 if (descent < g->descent)
2260 descent = g->descent;
2267 ink_array_return[start - from].x = x + lbearing;
2268 ink_array_return[start - from].y = - ascent;
2269 ink_array_return[start - from].width = rbearing - lbearing;
2270 ink_array_return[start - from].height = ascent + descent;
2271 logical_array_return[start - from].x = x;
2272 logical_array_return[start - from].y = - logical_descent;
2273 logical_array_return[start - from].height
2274 = logical_ascent + logical_descent;
2275 logical_array_return[start - from].width = width;
2281 if (overall_ink_return)
2283 overall_ink_return->y = - gstring->line_ascent;
2284 overall_ink_return->x = gstring->lbearing;
2285 overall_ink_return->width = x - gstring->lbearing;
2286 overall_ink_return->height = gstring->height;
2288 if (overall_logical_return)
2290 overall_logical_return->y = - gstring->ascent;
2291 overall_logical_return->x = 0;
2292 overall_logical_return->width = x;
2293 overall_logical_return->height = gstring->ascent + gstring->descent;
2296 M17N_OBJECT_UNREF (gstring->top);
2303 @brief Return the character position nearest to the coordinates.
2305 The mdraw_coordinates_position () function checks which character
2306 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2307 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2308 mdraw_text_with_control () function with the drawing control
2309 object $CONTROL. Here, the character position means the number of
2310 characters that precede the character in question in $MT, that is,
2311 the character position of the first character is 0.
2313 $FRAME is used only to get the default face information.
2316 If the glyph image of a character covers coordinate ($X, $Y),
2317 mdraw_coordinates_position () returns the character position of
2319 If $Y is less than the minimum Y-coordinate of the drawn area, it
2320 returns $FROM.\n\n\n
2321 If $Y is greater than the maximum Y-coordinate of the drawn area,
2322 it returns $TO.\n\n\n
2323 If $Y fits in with the drawn area but $X is less than the minimum
2324 X-coordinate, it returns the character position of the first
2325 character drawn on the line $Y.\n\n\n
2326 If $Y fits in with the drawn area but $X is greater than the
2327 maximum X-coordinate, it returns the character position of the
2328 last character drawn on the line $Y. */
2331 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë
2333 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2334 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2335 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2336 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2337 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2338 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2340 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2343 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2344 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2346 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2348 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2350 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2351 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2353 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2354 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2357 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2358 int x_offset, int y_offset, MDrawControl *control)
2360 MGlyphString *gstring;
2365 M_CHECK_POS_X (mt, from, -1);
2366 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2367 to = mtext_nchars (mt) + (control->cursor_width != 0);
2373 ASSURE_CONTROL (control);
2374 gstring = get_gstring (frame, mt, from, to, control);
2375 while (y + gstring->line_descent <= y_offset
2376 && gstring->to < to)
2379 y += gstring->line_descent;
2380 M17N_OBJECT_UNREF (gstring->top);
2381 gstring = get_gstring (frame, mt, from, to, control);
2382 y += gstring->line_ascent;
2385 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2386 if (! control->orientation_reversed)
2388 width = gstring->indent;
2389 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2390 if (g->pos >= from && g->pos < to)
2393 if (width > x_offset)
2399 width = - gstring->indent;
2400 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2401 if (g->pos >= from && g->pos < to)
2404 if (width < x_offset)
2409 M17N_OBJECT_UNREF (gstring->top);
2417 @brief Compute information about a glyph.
2419 The mdraw_glyph_info () function computes information about a
2420 glyph that covers a character at position $POS of the M-text $MT
2421 assuming that the text is drawn from the character at $FROM of $MT
2422 on a window of frame $FRAME using the mdraw_text_with_control ()
2423 function with the drawing control object $CONTROL.
2425 The information is stored in the members of $INFO. */
2427 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2429 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2430 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2431 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2432 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2434 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2442 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2443 MDrawControl *control, MDrawGlyphInfo *info)
2445 MGlyphString *gstring;
2449 M_CHECK_RANGE_X (mt, from, pos, -1);
2451 ASSURE_CONTROL (control);
2452 gstring = get_gstring (frame, mt, from, pos + 1, control);
2454 MERROR (MERROR_DRAW, -1);
2455 while (gstring->to <= pos)
2457 y += gstring->line_descent;
2458 M17N_OBJECT_UNREF (gstring->top);
2459 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2460 y += gstring->line_ascent;
2462 info->line_from = gstring->from;
2463 if (info->line_from < from)
2464 info->line_from = from;
2465 info->line_to = gstring->to;
2468 if (! control->orientation_reversed)
2470 info->x = gstring->indent;
2471 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2472 info->x += g->width;
2476 info->x = - gstring->indent;
2477 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2478 info->x -= g->width;
2479 while (g[-1].to == g->to)
2482 info->from = g->pos;
2484 info->this.x = g->lbearing;
2485 info->this.y = - gstring->line_ascent;
2486 info->this.height = gstring->height;
2487 if (g->rface->rfont)
2488 info->font = &g->rface->rfont->font;
2491 /* info->this.width is calculated later. */
2493 if (info->from > info->line_from)
2495 /* The logically previous glyph is on this line. */
2496 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2498 info->prev_from = g_tmp->pos;
2500 else if (info->line_from > 0)
2502 /* The logically previous glyph is on the previous line. */
2503 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2504 gstring->from, control);
2505 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2507 info->prev_from = g_tmp->pos;
2508 M17N_OBJECT_UNREF (gst->top);
2511 info->prev_from = -1;
2513 if (GLYPH_INDEX (g) > 1)
2514 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2515 else if (! control->orientation_reversed)
2517 if (info->line_from > 0)
2521 int p = gstring->from - 1;
2523 gst = get_gstring (frame, mt, p, gstring->from, control);
2524 g_tmp = gst->glyphs + (gst->used - 2);
2525 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2526 M17N_OBJECT_UNREF (gst->top);
2529 info->left_from = info->left_to = -1;
2533 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2537 int p = gstring->to;
2539 gst = get_gstring (frame, mt, p, p + 1, control);
2540 g_tmp = gst->glyphs + (gst->used - 2);
2541 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2542 M17N_OBJECT_UNREF (gst->top);
2545 info->left_from = info->left_to = -1;
2548 if (info->to < gstring->to)
2550 /* The logically next glyph is on this line. */
2551 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2553 info->next_to = g_tmp->to;
2555 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2557 /* The logically next glyph is on the next line. */
2559 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2560 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2562 info->next_to = g_tmp->to;
2563 M17N_OBJECT_UNREF (gst->top);
2568 for (info->this.width = (g++)->width;
2569 g->pos == pos && g->type != GLYPH_ANCHOR;
2570 info->this.width += (g++)->width);
2572 if (g->type != GLYPH_ANCHOR)
2573 info->right_from = g->pos, info->right_to = g->to;
2574 else if (! control->orientation_reversed)
2576 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2579 M17N_OBJECT_UNREF (gstring->top);
2580 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2582 info->right_from = g->pos, info->right_to = g->to;
2585 info->right_from = info->right_to = -1;
2589 if (info->line_from > 0)
2591 pos = gstring->from - 1;
2592 M17N_OBJECT_UNREF (gstring->top);
2593 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2595 info->right_from = g->pos, info->right_to = g->to;
2598 info->right_from = info->right_to = -1;
2601 M17N_OBJECT_UNREF (gstring->top);
2608 @brief Draw one or more textitems.
2610 The mdraw_text_items () function draws one or more M-texts on
2611 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2612 of the textitems to be drawn and $NITEMS is the number of
2613 textimtems in the array. */
2616 @brief textitem ¤òɽ¼¨¤¹¤ë.
2618 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2619 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2620 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2623 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2627 MTextItem, mdraw_text (). */
2630 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2631 MDrawTextItem *items, int nitems)
2633 while (nitems-- > 0)
2636 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2638 mdraw_text_with_control (frame, win, x, y,
2639 items->mt, 0, mtext_nchars (items->mt),
2641 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2642 items->control, NULL, NULL, NULL);
2645 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2652 mdraw_default_line_break (MText *mt, int pos,
2653 int from, int to, int line, int y)
2655 int c = mtext_ref_char (mt, pos);
2658 if (c == ' ' || c == '\t')
2662 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2669 if (c == ' ' || c == '\t')
2672 c = mtext_ref_char (mt, pos);
2685 @brief Obtain per character dimension information.
2687 The mdraw_per_char_extents () function computes the text dimension
2688 of each character in M-text $MT. The faces given as text
2689 properties in $MT and the default face of frame $FRAME determine
2690 the fonts to draw the text. Each successive element in
2691 $ARRAY_RETURN is set to the drawn metrics of successive
2692 characters, which is relative to the origin of the drawing, and a
2693 rectangle for each character in $MT. The number of elements of
2694 $ARRAY_RETURN must be equal to or greater than the number of
2697 If pointer $OVERALL_RETURN is not @c NULL, this function also
2698 computes the extents of the overall text and stores the results in
2699 the members of the structure pointed to by $OVERALL_RETURN */
2702 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë
2704 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2705 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2706 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è
2707 ¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2708 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2709 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2710 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2712 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2713 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2716 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2719 mdraw_per_char_extents (MFrame *frame, MText *mt,
2720 MDrawMetric *array_return,
2721 MDrawMetric *overall_return)
2726 mdraw_clear_cache (MText *mt)
2728 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);