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-texts 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;
88 /* Glyph-string composer. */
90 static MSymbol MbidiR;
91 static MSymbol MbidiAL;
92 static MSymbol MbidiRLE;
93 static MSymbol MbidiRLO;
94 static MSymbol MbidiBN;
95 static MSymbol MbidiS;
98 visual_order (MGlyphString *gstring)
100 int len = gstring->used - 2;
102 int bidi_sensitive = gstring->control.orientation_reversed;
106 FriBidiCharType base = (gstring->control.orientation_reversed
107 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
108 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
110 FriBidiStrIndex *indices;
111 FriBidiLevel *levels;
112 #else /* not HAVE_FRIBIDI */
113 int *logical = alloca (sizeof (int) * len);
115 char *levels = alloca (len);
116 #endif /* not HAVE_FRIBIDI */
118 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
120 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
122 if (bidi == MbidiR || bidi == MbidiAL
123 || bidi == MbidiRLE || bidi == MbidiRLO)
128 #endif /* not HAVE_FRIBIDI */
133 if (! bidi_sensitive)
136 glyphs = alloca (sizeof (MGlyph) * gstring->used - 2);
137 memcpy (glyphs, gstring->glyphs + 1, (sizeof (MGlyph) * gstring->used - 2));
139 visual = alloca (sizeof (FriBidiChar) * len);
140 indices = alloca (sizeof (FriBidiStrIndex) * len);
141 levels = alloca (sizeof (FriBidiLevel) * len);
143 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
144 #else /* not HAVE_FRIBIDI */
145 indices = alloca (sizeof (int) * len);
146 for (i = 0; i < len; i++)
152 for (j = i + 1; j < len && levels[j]; j++);
153 for (k = j--; i < k; i++, j--)
160 #endif /* not HAVE_FRIBIDI */
162 for (i = 0; i < len; i++)
169 g->bidi_level = levels[i];
171 if (visual[j] != logical[i])
176 g->code = mfont__encode_char (g->rface->rfont, g->c);
178 #endif /* HAVE_FRIBIDI */
183 reorder_combining_chars (MGlyphString *gstring, int from, int to)
185 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
191 for (g = gbeg; g != gend; g++)
192 if (COMBINING_CODE_CLASS (g->combining_code) > 0
193 && (COMBINING_CODE_CLASS (g[-1].combining_code)
194 > COMBINING_CODE_CLASS (g->combining_code)))
205 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
206 displaying them on FRAME.
208 This function fills members <type>, <rface>, <c>, <pos>, <to>,
209 <code> of glyphs. The other members are filled by
210 layout_glyph_string. */
213 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
214 MGlyphString *gstring)
216 MRealizedFace *default_rface = frame->rface;
217 int stop, face_change, language_change, charset_change;
220 MSymbol language = Mnil, script = Mnil, charset = Mnil;
221 MSymbol non_latin_script = Mnil;
222 MRealizedFace *rface = default_rface;
223 int size = gstring->control.fixed_width;
227 MLIST_RESET (gstring);
228 gstring->from = from;
230 /* At first generate glyphs while using the member <enabled> as a
231 flag for rface re-checking. */
234 /** Put anchor glyphs at the head and tail. */
235 g_tmp.type = GLYPH_ANCHOR;
236 g_tmp.pos = g_tmp.to = from;
238 APPEND_GLYPH (gstring, g_tmp);
240 stop = face_change = charset_change = language_change = pos = from;
247 if (pos < mtext_nchars (mt))
248 c = mtext_ref_char (mt, pos);
251 g_tmp.category = mchar_get_prop (c, Mcategory);
254 /* Short cut for the obvious case. */
255 g_tmp.type = (c == ' ' || c == '\n' || c == '\t'
256 ? GLYPH_SPACE : GLYPH_CHAR);
257 this_script = (MSYMBOL_NAME (g_tmp.category)[0] == 'L'
262 g_tmp.type = GLYPH_CHAR;
263 this_script = (MSymbol) mchar_get_prop (c, Mscript);
264 if (this_script == Minherited || this_script == Mnil)
265 this_script = script;
266 if (this_script == Mnil)
267 this_script = non_latin_script;
268 if (this_script == Mnil)
270 /* Search forward for a character that explicitly
271 specifies a non-latin script. */
275 for (i = pos + 1; i < to; i++)
276 if ((c1 = mtext_ref_char (mt, i)) >= 0x100
277 && (sym = mchar_get_prop (c1, Mscript)) != Mnil
278 && sym != Minherited)
286 if (pos == stop || script != this_script
287 || MGLYPH (last)->type != g_tmp.type)
290 if (g->type != GLYPH_ANCHOR)
291 while (g < gstring->glyphs + gstring->used)
292 g = mface__for_chars (script == Mnil ? Mlatin : script,
294 g, gstring->glyphs + gstring->used, size);
297 last = gstring->used;
298 script = this_script;
299 if (script != Mnil && script != Mlatin)
300 non_latin_script = script;
303 if (pos < mtext_nchars (mt) && pos == language_change)
305 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
306 mtext_prop_range (mt, Mlanguage, pos, NULL,
307 &language_change, 0);
309 if (pos < mtext_nchars (mt) && pos == charset_change)
311 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
312 mtext_prop_range (mt, Mcharset, pos, NULL,
315 if (pos < mtext_nchars (mt) && pos == face_change)
318 int num = mtext_get_prop_values (mt, pos, Mface,
319 (void **) faces, 64);
321 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
323 ? mface__realize (frame, faces, num,
324 language, charset, size)
328 if (stop > language_change)
329 stop = language_change;
330 if (stop > charset_change)
331 stop = charset_change;
332 if (face_change < stop)
342 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
346 ctrl[0] = ctrl[1] = g_tmp;
348 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
349 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
350 APPEND_GLYPH (gstring, ctrl[0]);
351 APPEND_GLYPH (gstring, ctrl[1]);
354 APPEND_GLYPH (gstring, g_tmp);
356 && gstring->control.two_dimensional)
360 /* Append an anchor glyph. */
361 g_tmp.type = GLYPH_ANCHOR;
363 g_tmp.code = MCHAR_INVALID_CODE;
364 g_tmp.pos = g_tmp.to = pos;
366 APPEND_GLYPH (gstring, g_tmp);
370 /* Next, run FLT if necessary. */
371 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
375 if (this->type == GLYPH_CHAR && this->rface->rfont)
379 if (this->rface->rfont->layouter != Mnil)
384 for (prev = MGLYPH (start - 1);
385 (prev->type == GLYPH_CHAR
386 && prev->category == McatCf
387 && (code = mfont__encode_char (this->rface->rfont, prev->c)
388 != MCHAR_INVALID_CODE));
393 (g->type == GLYPH_CHAR
394 && (g->rface->rfont == this->rface->rfont
395 || (g->category == McatCf
396 && ((code = mfont__encode_char (this->rface->rfont,
398 != MCHAR_INVALID_CODE))));
400 if (g->rface->rfont != this->rface->rfont)
402 g->rface->rfont = this->rface->rfont;
405 i = mfont__flt_run (gstring, start, i, this->rface);
409 while (this->type == GLYPH_CHAR
412 && MSYMBOL_NAME (this->category)[0] == 'M'
413 && this->rface->rfont
414 && this->rface->rfont->layouter == Mnil)
416 int class = (int) mchar_get_prop (this->c,
419 = MAKE_COMBINING_CODE_BY_CLASS (class);
423 reorder_combining_chars (gstring, start, i);
424 if (this->type == GLYPH_ANCHOR)
433 /* At last, reorder glyphs visually if necessary. */
434 if (gstring->control.enable_bidi)
435 visual_order (gstring);
440 combining_code_from_class (int class)
445 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
446 else if (class == 200) /* below left attached */
447 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
448 else if (class == 202) /* below attached*/
449 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
450 else if (class == 204) /* below right attached */
451 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
452 else if (class == 208) /* left attached */
453 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
454 else if (class == 210) /* right attached */
455 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
456 else if (class == 212) /* above left attached */
457 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
458 else if (class == 214) /* above attached */
459 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
460 else if (class == 216) /* above right attached */
461 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
462 else if (class == 218) /* below left */
463 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
464 else if (class == 220) /* below */
465 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
466 else if (class == 222) /* below right */
467 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
468 else if (class == 224) /* left */
469 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
470 else if (class == 226) /* right */
471 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
472 else if (class == 228) /* above left */
473 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
474 else if (class == 230) /* above */
475 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
476 else if (class == 232) /* above right */
477 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
478 else if (class == 233) /* double below */
479 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
480 else if (class == 234) /* double above */
481 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
482 else if (class == 240) /* iota subscript */
483 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
485 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
491 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
493 int g_physical_ascent, g_physical_descent;
494 int g_width, g_lbearing, g_rbearing;
495 MGlyph *g = MGLYPH (from);
496 MGlyph *last_g = MGLYPH (to);
499 g_physical_ascent = gstring->physical_ascent;
500 g_physical_descent = gstring->physical_descent;
501 g_width = g_lbearing = g_rbearing = 0;
503 for (i = from; i < to;)
505 if ( MGLYPH (i)->otf_encoded)
511 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
512 mfont__get_metric (gstring, j, i);
519 MRealizedFont *rfont = base->rface->rfont;
520 int size = rfont->font.property[MFONT_SIZE];
521 int width, lbearing, rbearing;
523 if (base->bidi_sensitive && (base->bidi_level % 2))
525 MGlyph *g1 = base, temp;
527 base->bidi_sensitive = 0;
528 while (g->bidi_sensitive && (g->bidi_level % 2))
529 g++->bidi_sensitive = 0;
531 temp = *g1, *g1++ = *g, *g-- = temp;
535 if (g == last_g || ! g->combining_code)
538 if (base->width == 0 && GLYPH_INDEX (base) > from)
540 MGlyph *prev = base - 1;
542 if (base->pos < prev->pos)
543 prev->pos = base->pos;
545 base->pos = prev->pos;
546 if (base->to > prev->to)
552 if (base->left_padding && base->lbearing < 0)
554 base->xoff = - base->lbearing;
555 base->width += base->xoff;
556 base->rbearing += base->xoff;
559 if (base->right_padding && base->rbearing > base->width)
561 base->width = base->rbearing;
563 lbearing = (base->xoff + base->lbearing < 0
564 ? base->xoff + base->lbearing : 0);
565 rbearing = base->xoff + base->rbearing;
569 /* With combining glyphs. */
570 int left = -base->width;
572 int top = - base->ascent;
573 int bottom = base->descent;
574 int height = bottom - top;
575 int begin = base->pos;
580 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
581 rbearing = base->rbearing;
583 while (g != last_g && g->combining_code)
585 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
587 combining_code = g->combining_code;
588 if (COMBINING_BY_CLASS_P (combining_code))
589 g->combining_code = combining_code
590 = combining_code_from_class (COMBINING_CODE_CLASS
593 rfont = g->rface->rfont;
594 size = rfont->font.property[MFONT_SIZE];
595 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
597 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
599 base_x = COMBINING_CODE_BASE_X (combining_code);
600 base_y = COMBINING_CODE_BASE_Y (combining_code);
601 add_x = COMBINING_CODE_ADD_X (combining_code);
602 add_y = COMBINING_CODE_ADD_Y (combining_code);
606 else if (end < g->to)
609 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
612 if (g->xoff + g->width > right)
613 right = g->xoff + g->width;
614 width = right - left;
615 if (g->xoff + g->lbearing < left + lbearing)
616 lbearing = g->xoff + g->lbearing - left;
617 if (g->xoff + g->rbearing > left + rbearing)
618 rbearing = g->xoff + g->rbearing - left;
621 g->yoff = top + height * base_y / 2;
625 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
627 if (g->yoff - g->ascent < top)
628 top = g->yoff - g->ascent;
629 if (g->yoff + g->descent > bottom)
630 bottom = g->yoff + g->descent;
631 height = bottom - top;
637 base->ascent = - top;
638 base->descent = bottom;
639 base->lbearing = lbearing;
640 base->rbearing = rbearing;
641 if (left < - base->width)
643 base->xoff = - base->width - left;
644 base->width += base->xoff;
645 base->rbearing += base->xoff;
646 base->lbearing += base->xoff;
650 base->width += right;
651 base->rbearing += right;
652 base->right_padding = 1;
653 for (i = 1; base + i != g; i++)
654 base[i].xoff -= right;
657 for (i = 0; base + i != g; i++)
664 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
665 g_physical_descent = MAX (g_physical_descent, base->descent);
666 g_lbearing = MIN (g_lbearing, g_width + lbearing);
667 g_rbearing = MAX (g_rbearing, g_width + rbearing);
668 g_width += base->width;
671 gstring->physical_ascent = g_physical_ascent;
672 gstring->physical_descent = g_physical_descent;
673 gstring->sub_width = g_width;
674 gstring->sub_lbearing = g_lbearing;
675 gstring->sub_rbearing = g_rbearing;
679 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
680 by this function directly. Character glyphs are handled by
681 layouter functions registered in font drivers.
683 This function fill-in all the remaining members of glyphs. */
686 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
688 /* Default width of TAB. */
689 int tab_width = frame->space_width * (gstring->control.tab_width
690 ? gstring->control.tab_width : 8);
694 MDrawControl *control = &(gstring->control);
697 int box_line_height = 0;
698 int ignore_formatting_char = control->ignore_formatting_char;
700 gstring->ascent = gstring->descent = 0;
701 gstring->physical_ascent = gstring->physical_descent = 0;
702 gstring->width = gstring->lbearing = gstring->rbearing = 0;
706 while (g->type != GLYPH_ANCHOR)
708 if (box != g->rface->box)
710 int gidx = GLYPH_INDEX (g);
714 /* Insert the right side of the box. That glyph belongs
715 to the previous grapheme cluster. */
716 MGlyph box_glyph = g[-1];
718 box_glyph.type = GLYPH_BOX;
720 = (control->fixed_width
722 : box->inner_hmargin + box->width + box->outer_hmargin);
723 box_glyph.lbearing = 0;
724 box_glyph.rbearing = box_glyph.width;
726 box_glyph.right_padding = 1;
727 gstring->width += box_glyph.width;
728 gstring->rbearing += box_glyph.width;
729 INSERT_GLYPH (gstring, gidx, box_glyph);
736 /* Insert the left side of the box. That glyph belongs
737 to the following grapheme cluster. */
738 MGlyph box_glyph = *g;
739 int box_height = (box->width
740 + box->inner_vmargin + box->outer_vmargin);
742 if (box_line_height < box_height)
743 box_line_height = box_height;
744 box_glyph.type = GLYPH_BOX;
746 = (control->fixed_width
748 : box->inner_hmargin + box->width + box->outer_hmargin);
749 box_glyph.lbearing = 0;
750 box_glyph.rbearing = box_glyph.width;
752 box_glyph.left_padding = 1;
753 gstring->width += box_glyph.width;
754 gstring->rbearing += box_glyph.width;
755 INSERT_GLYPH (gstring, gidx, box_glyph);
761 if (g->category == McatCf && ignore_formatting_char)
762 g->type = GLYPH_SPACE;
764 if (g->type == GLYPH_CHAR)
766 MRealizedFace *rface = g->rface;
767 MRealizedFont *rfont = rface->rfont;
769 int from = GLYPH_INDEX (g);
771 for (g++; g->type == GLYPH_CHAR; g++)
772 if (! rfont != ! g->rface->rfont
773 || box != g->rface->box
774 || ((fromg->code == MCHAR_INVALID_CODE)
775 != (g->code == MCHAR_INVALID_CODE))
776 || (g->category == McatCf && ignore_formatting_char))
778 if (rfont && fromg->code != MCHAR_INVALID_CODE)
781 int to = GLYPH_INDEX (g);
783 layout_glyphs (frame, gstring, from, to);
784 extra_width = - gstring->sub_lbearing;
786 && (GLYPH_INDEX (g) > 1
787 || control->align_head))
791 pad.type = GLYPH_PAD;
794 pad.width = pad.rbearing = extra_width;
795 pad.left_padding = 1;
796 INSERT_GLYPH (gstring, from, pad);
798 gstring->sub_lbearing = 0;
799 gstring->sub_width += extra_width;
800 gstring->sub_rbearing += extra_width;
802 g = MGLYPH (from - 1);
803 if (g->type == GLYPH_SPACE)
805 /* The pad just inserted is absorbed (maybe
806 partially) by the previous space while
807 keeping at least some space width. For the
808 moment, we use the arbitrary width 2-pixel.
809 Perhaps, it should be decided by the current
810 face, or a default value of the current
811 frame, which is, however, not yet
813 if (extra_width + 2 < g->width)
815 g->width -= extra_width;
819 extra_width -= g->width - 2;
822 gstring->width -= extra_width;
823 gstring->rbearing -= extra_width;
827 extra_width = gstring->sub_rbearing - gstring->sub_width;
831 if (g->type == GLYPH_SPACE && box == g->rface->box)
835 pad.type = GLYPH_PAD;
838 pad.width = pad.rbearing = extra_width;
840 INSERT_GLYPH (gstring, to, pad);
844 g[-1].width += extra_width;
845 gstring->sub_width += extra_width;
848 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
849 gstring->lbearing = gstring->width + gstring->sub_lbearing;
850 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
851 gstring->rbearing = gstring->width + gstring->sub_rbearing;
852 gstring->width += gstring->sub_width;
853 if (gstring->ascent < rface->ascent)
854 gstring->ascent = rface->ascent;
855 if (gstring->descent < rface->descent)
856 gstring->descent = rface->descent;
861 for (; fromg < g; fromg++)
863 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
864 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
865 fromg->width = fromg->rbearing = 1;
867 fromg->width = fromg->rbearing = rface->space_width;
868 fromg->xoff = fromg->lbearing = 0;
869 fromg->ascent = fromg->descent = 0;
870 gstring->width += fromg->width;
871 gstring->rbearing += fromg->width;
873 if (gstring->ascent < frame->rface->ascent)
874 gstring->ascent = frame->rface->ascent;
875 if (gstring->descent < frame->descent)
876 gstring->descent = frame->rface->descent;
879 else if (g->type == GLYPH_SPACE)
882 g->width = g->rface->space_width;
883 else if (g->c == '\n')
885 g->width = control->cursor_width;
888 if (control->cursor_bidi)
890 else if (g->width < 0)
891 g->width = g->rface->space_width;
894 else if (g->c == '\t')
896 g->width = tab_width - ((gstring->indent + gstring->width)
902 if (g[-1].type == GLYPH_PAD)
904 /* This space glyph absorbs (maybe partially) the
905 previous padding glyph. */
906 g->width -= g[-1].width;
908 /* But, keep at least some space width. For the
909 moment, we use the arbitrary width 2-pixel. */
912 g->rbearing = g->width;
913 gstring->width += g->width;
914 gstring->rbearing += g->width;
917 if (gstring->ascent < g->rface->ascent)
918 gstring->ascent = g->rface->ascent;
919 if (gstring->descent < g->rface->descent)
920 gstring->descent = g->rface->descent;
926 gstring->width += g->width;
927 gstring->rbearing += g->width;
934 /* Insert the right side of the box. */
935 int gidx = GLYPH_INDEX (g);
936 MGlyph box_glyph = g[-1];
938 box_glyph.type = GLYPH_BOX;
940 = (control->fixed_width
942 : box->inner_hmargin + box->width + box->outer_hmargin);
943 box_glyph.lbearing = 0;
944 box_glyph.rbearing = box_glyph.width;
946 box_glyph.right_padding = 1;
947 gstring->width += box_glyph.width;
948 gstring->rbearing += box_glyph.width;
949 INSERT_GLYPH (gstring, gidx, box_glyph);
952 gstring->text_ascent = gstring->ascent;
953 gstring->text_descent = gstring->descent;
954 if (gstring->text_ascent < gstring->physical_ascent)
955 gstring->text_ascent = gstring->physical_ascent;
956 if (gstring->text_descent < gstring->physical_descent)
957 gstring->text_descent = gstring->physical_descent;
958 gstring->line_ascent = gstring->text_ascent;
959 gstring->line_descent = gstring->text_descent;
960 if (box_line_height > 0)
962 gstring->line_ascent += box_line_height;
963 gstring->physical_ascent = gstring->line_ascent;
964 gstring->line_descent += box_line_height;
965 gstring->physical_descent = gstring->line_descent;
968 if (gstring->line_ascent < control->min_line_ascent)
969 gstring->line_ascent = control->min_line_ascent;
970 else if (control->max_line_ascent
971 && control->max_line_ascent > control->min_line_ascent
972 && gstring->line_ascent > control->max_line_ascent)
973 gstring->line_ascent = control->max_line_ascent;
975 if (gstring->line_descent < control->min_line_descent)
976 gstring->line_descent = control->min_line_descent;
977 else if (control->max_line_descent
978 && control->max_line_descent > control->min_line_descent
979 && gstring->line_descent > control->max_line_descent)
980 gstring->line_descent = control->max_line_descent;
981 gstring->height = gstring->line_ascent + gstring->line_descent;
983 if (control->orientation_reversed
986 /* We must adjust TAB width for RTL orientation. */
987 width = gstring->indent;
989 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
991 if (g->type == GLYPH_CHAR && g->c == '\t')
993 int this_width = tab_width - (width % tab_width);
995 if (g[1].type == GLYPH_PAD)
996 this_width -= g[1].width;
997 if (g[-1].type == GLYPH_PAD)
998 this_width -= g[-1].width;
1001 gstring->width += this_width - g->width;
1002 gstring->rbearing += this_width - g->width;
1003 g->width = this_width;
1004 width += this_width;
1014 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1015 MGlyphString *gstring, int from, int to,
1016 int *from_idx, int *to_idx, int *to_x)
1018 MGlyph *g = MGLYPH (1);
1019 MDrawRegion region = (MDrawRegion) NULL;
1020 MDrawControl *control = &gstring->control;
1021 int cursor_pos = -1;
1023 int cursor_bidi = control->cursor_bidi;
1025 if (control->with_cursor && control->cursor_width)
1027 if (gstring->from <= control->cursor_pos
1028 && gstring->to > control->cursor_pos)
1029 cursor_pos = control->cursor_pos;
1032 && gstring->from <= control->cursor_pos - 1
1033 && gstring->to > control->cursor_pos - 1)
1034 prev_pos = control->cursor_pos - 1;
1037 *from_idx = *to_idx = 0;
1038 while (g->type != GLYPH_ANCHOR)
1040 if (g->pos >= from && g->pos < to)
1042 MGlyph *fromg = g, *cursor = NULL;
1043 MRealizedFace *rface = g->rface;
1045 int cursor_width = 0;
1049 *from_idx = GLYPH_INDEX (g);
1050 while (g->pos >= from && g->pos < to
1051 && g->rface == rface)
1054 if (g->type != GLYPH_BOX
1055 && g->pos <= cursor_pos && g->to > cursor_pos)
1058 cursor = g, cursor_x = x + width;
1059 cursor_width += g->width;
1061 width += g++->width;
1064 && (control->as_image
1065 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1067 int this_x = x, this_width = width;
1069 if (fromg->type == GLYPH_BOX)
1070 this_x += fromg->width, this_width -= fromg->width;
1071 if (g[-1].type == GLYPH_BOX)
1072 this_width -= g[-1].width;
1073 (frame->driver->fill_space)
1074 (frame, win, rface, 0,
1075 this_x, y - gstring->text_ascent, this_width,
1076 gstring->text_ascent + gstring->text_descent,
1077 control->clip_region);
1084 rect.y = y - gstring->text_ascent;
1085 rect.height = gstring->text_ascent + gstring->text_descent;
1088 rect.width = ((control->cursor_width > 0
1089 && control->cursor_width < cursor_width)
1090 ? control->cursor_width : cursor_width);
1094 if (cursor->bidi_level % 2)
1095 rect.x += cursor_width - rect.width;
1096 (*frame->driver->fill_space)
1097 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1098 control->clip_region);
1100 region = (*frame->driver->region_from_rect) (&rect);
1102 (*frame->driver->region_add_rect) (region, &rect);
1105 if (cursor->bidi_level % 2)
1108 rect.width = cursor_width < 4 ? cursor_width : 4;
1109 (*frame->driver->fill_space)
1110 (frame, win, rface, 1,
1111 rect.x, rect.y, rect.width, rect.height,
1112 control->clip_region);
1113 (*frame->driver->region_add_rect) (region, &rect);
1125 if (fromg->type != GLYPH_BOX
1126 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1129 cursor = fromg, cursor_x = x + temp_width;
1130 cursor_width += fromg->width;
1132 temp_width += fromg++->width;
1139 if (! (cursor->bidi_level % 2))
1140 rect.x += cursor_width - 1;
1141 rect.y = y - gstring->text_ascent;
1142 rect.height = gstring->text_ascent + gstring->text_descent;
1144 (*frame->driver->fill_space)
1145 (frame, win, rface, 1,
1146 rect.x, rect.y, rect.width, rect.height,
1147 control->clip_region);
1149 region = (*frame->driver->region_from_rect) (&rect);
1151 (*frame->driver->region_add_rect) (region, &rect);
1152 rect.y += rect.height - 2;
1154 rect.width = cursor_width < 4 ? cursor_width : 4;
1155 if (! (cursor->bidi_level % 2))
1156 rect.x -= rect.width - 1;
1157 (*frame->driver->fill_space) (frame, win, rface, 1,
1158 rect.x, rect.y, rect.width, rect.height,
1159 control->clip_region);
1160 (*frame->driver->region_add_rect) (region, &rect);
1164 *to_idx = GLYPH_INDEX (g);
1174 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1175 MGlyphString *gstring, int from_idx, int to_idx,
1176 int reverse, MDrawRegion region)
1178 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1184 (*frame->driver->region_to_rect) (region, &rect);
1187 while (g != gend && x + g->rbearing <= rect.x)
1190 width -= g++->width;
1191 while (! g->enabled && g != gend)
1195 rect.x += rect.width;
1196 if (rect.x < x + width)
1199 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1201 width -= (--gend)->width;
1202 while (! gend->enabled && g != gend)
1206 while (gend[-1].to == gend->to) gend++;
1214 MRealizedFace *rface = g->rface;
1215 int width = g->width;
1216 MGlyph *from_g = g++;
1218 /* Handle the glyphs of the same type/face at once. */
1220 && g->type == from_g->type
1221 && g->rface == rface
1222 && ((g->code == MCHAR_INVALID_CODE)
1223 == (from_g->code == MCHAR_INVALID_CODE))
1225 width += g++->width;
1227 if (from_g->type == GLYPH_CHAR)
1229 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1230 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1233 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1236 else if (from_g->type == GLYPH_BOX)
1238 /* Draw the left or right side of a box. If
1239 from_g->lbearing is nonzero, this is the left side,
1240 else this is the right side. */
1241 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1244 if (from_g->type != GLYPH_BOX)
1247 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1248 x, y, width, region);
1251 /* Draw the top and bottom side of a box. */
1252 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1253 x, y, width, region);
1264 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1265 int *from_x, int *to_x)
1268 int left_idx = *left, right_idx = *right;
1269 int left_x, right_x, x;
1271 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1274 if (x + g->rbearing > 0)
1276 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1278 left_idx = GLYPH_INDEX (g);
1283 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1286 if (x - g->width + g->lbearing < 0)
1288 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1290 right_idx = GLYPH_INDEX (g) + 1;
1295 if (*left == left_idx && *right == right_idx)
1298 if (*left != left_idx)
1300 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1305 if (*right != right_idx)
1307 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1317 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1322 if (from <= gstring->from && to >= gstring->to)
1325 *rbearing = gstring->rbearing;
1326 return gstring->width;
1331 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1332 if (g->pos >= from && g->pos < to)
1334 if (rbearing && width + g->rbearing > *rbearing)
1335 *rbearing = width + g->rbearing;
1343 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1344 MGlyphString *gstring, int from, int to)
1346 MDrawControl *control = &gstring->control;
1348 MDrawRegion clip_region, cursor_region;
1349 int from_idx, to_idx;
1352 if (control->orientation_reversed)
1353 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1355 x += gstring->indent;
1357 /* At first, draw all glyphs without cursor. */
1358 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1359 &from_idx, &to_idx, &to_x);
1361 if (control->partial_update)
1364 rect.width = to_x - x;
1365 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1367 rect.y = y - gstring->line_ascent;
1368 rect.height = gstring->height;
1369 clip_region = (*frame->driver->region_from_rect) (&rect);
1370 if (control->clip_region)
1371 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1374 clip_region = control->clip_region;
1377 clip_region = control->clip_region;
1379 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1384 (*frame->driver->intersect_region) (cursor_region, clip_region);
1385 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1388 if (clip_region != control->clip_region)
1389 (*frame->driver->free_region) (clip_region);
1391 (*frame->driver->free_region) (cursor_region);
1395 static int gstring_num;
1398 free_gstring (void *object)
1400 MGlyphString *gstring = (MGlyphString *) object;
1403 free_gstring (gstring->next);
1404 if (gstring->size > 0)
1405 free (gstring->glyphs);
1411 static MGlyphString scratch_gstring;
1413 static MGlyphString *
1414 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1417 MGlyphString *gstring;
1419 if (pos == mt->nchars)
1421 gstring = &scratch_gstring;
1425 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1426 MLIST_INIT1 (gstring, glyphs, 128);
1430 gstring->frame = frame;
1431 gstring->tick = frame->tick;
1432 gstring->top = gstring;
1434 gstring->control = *control;
1435 gstring->indent = gstring->width_limit = 0;
1436 if (control->format)
1437 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1439 gstring->width_limit = control->max_line_width;
1440 gstring->anti_alias = control->anti_alias;
1444 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1447 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1455 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1456 a width of glyphs for the character at I of GSTRING->mt. If I is
1457 not a beginning of a grapheme cluster, the corresponding element
1459 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1460 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1461 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1462 pos_width[g->pos - gstring->from] += g->width;
1463 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1465 if (pos_width[i] > 0)
1467 if (width + pos_width[i] > gstring->width_limit)
1470 width += pos_width[i];
1473 pos = gstring->from + i;
1474 if (gstring->control.line_break)
1476 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1477 gstring->from, gstring->to, 0, 0);
1478 if (pos <= gstring->from || pos >= gstring->to)
1481 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1482 layout_glyph_string (frame, gstring);
1486 /* Return a gstring that covers a character at POS. */
1488 static MGlyphString *
1489 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1491 MGlyphString *gstring = NULL;
1493 if (pos < mtext_nchars (mt))
1495 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1498 && ((prop->start != 0
1499 && mtext_ref_char (mt, prop->start - 1) != '\n')
1500 || (prop->end < mtext_nchars (mt)
1501 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1503 mtext_detach_property (prop);
1508 gstring = prop->val;
1509 if (gstring->frame != frame
1510 || gstring->tick != frame->tick
1511 || memcmp (control, &gstring->control,
1512 (char *) (&control->with_cursor)
1513 - (char *) (control)))
1515 mtext_detach_property (prop);
1520 else if (! control->cursor_width)
1528 offset = mtext_character (mt, pos, 0, '\n');
1533 offset -= gstring->from;
1535 for (gst = gstring; gst; gst = gst->next)
1539 gst->from += offset;
1541 for (i = 0; i < gst->used; i++)
1543 gst->glyphs[i].pos += offset;
1544 gst->glyphs[i].to += offset;
1547 M17N_OBJECT_REF (gstring);
1552 int line = 0, y = 0;
1554 if (control->two_dimensional)
1556 beg = mtext_character (mt, pos, 0, '\n');
1561 end = mtext_nchars (mt) + (control->cursor_width != 0);
1568 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1569 compose_glyph_string (frame, mt, beg, end, gstring);
1570 layout_glyph_string (frame, gstring);
1572 if (control->two_dimensional
1573 && gstring->width_limit
1574 && gstring->width > gstring->width_limit)
1576 MGlyphString *gst = gstring;
1578 truncate_gstring (frame, mt, gst);
1579 while (gst->to < end)
1581 line++, y += gst->height;
1582 gst->next = alloc_gstring (frame, mt, gst->from, control,
1584 gst->next->top = gstring;
1585 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1587 layout_glyph_string (frame, gst);
1588 if (gst->width <= gst->width_limit)
1590 truncate_gstring (frame, mt, gst);
1594 if (! control->disable_caching && pos < mtext_nchars (mt))
1596 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1597 MTEXTPROP_VOLATILE_STRONG);
1599 if (end > mtext_nchars (mt))
1600 end = mtext_nchars (mt);
1601 mtext_attach_property (mt, beg, end, prop);
1602 M17N_OBJECT_UNREF (prop);
1606 while (gstring->to <= pos)
1608 if (! gstring->next)
1610 gstring = gstring->next;
1612 gstring->control = *control;
1618 static MDrawControl control_noop;
1620 #define ASSURE_CONTROL(control) \
1622 control = &control_noop; \
1627 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1628 MText *mt, int from, int to,
1629 MDrawControl *control)
1631 MGlyphString *gstring;
1633 M_CHECK_POS_X (mt, from, -1);
1634 ASSURE_CONTROL (control);
1635 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1636 to = mtext_nchars (mt) + (control->cursor_width != 0);
1640 gstring = get_gstring (frame, mt, from, to, control);
1642 MERROR (MERROR_DRAW, -1);
1643 render_glyph_string (frame, win, x, y, gstring, from, to);
1647 y += gstring->line_descent;
1648 M17N_OBJECT_UNREF (gstring->top);
1649 gstring = get_gstring (frame, mt, from, to, control);
1650 y += gstring->line_ascent;
1651 render_glyph_string (frame, win, x, y, gstring, from, to);
1654 M17N_OBJECT_UNREF (gstring->top);
1661 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1667 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1668 if (g->pos <= pos && g->to > pos)
1673 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1674 if (g->pos <= pos && g->to > pos)
1681 /* for debugging... */
1685 dump_combining_code (int code)
1687 char *vallign = "tcbB";
1688 char *hallign = "lcr";
1694 if (COMBINING_BY_CLASS_P (code))
1695 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1696 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1697 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1698 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1699 off_x = COMBINING_CODE_OFF_X (code) - 128;
1701 sprintf (work + 2, "+%d", off_y);
1703 sprintf (work + 2, "%d", off_y);
1704 else if (off_x == 0)
1705 sprintf (work + 2, ".");
1706 p = work + strlen (work);
1708 sprintf (p, ">%d", off_x);
1710 sprintf (p, "<%d", -off_x);
1712 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1713 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1719 dump_gstring (MGlyphString *gstring, int indent)
1721 char *prefix = (char *) alloca (indent + 1);
1722 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1724 memset (prefix, 32, indent);
1727 fprintf (stderr, "(glyph-string");
1729 for (g = MGLYPH (0); g < last_g; g++)
1731 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1733 g - gstring->glyphs,
1734 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1735 : g->type == GLYPH_ANCHOR ? "ANC"
1736 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1737 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1738 dump_combining_code (g->combining_code),
1739 g->width, g->bidi_level);
1740 fprintf (stderr, ")");
1744 /* m17n-X internal APIs */
1749 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1751 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1752 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1754 Mlatin = msymbol ("latin");
1755 Minherited = msymbol ("inherited");
1757 McatCc = msymbol ("Cc");
1758 McatCf = msymbol ("Cf");
1760 MbidiR = msymbol ("R");
1761 MbidiAL = msymbol ("AL");
1762 MbidiRLE = msymbol ("RLE");
1763 MbidiRLO = msymbol ("RLO");
1764 MbidiBN = msymbol ("BN");
1765 MbidiS = msymbol ("S");
1767 fribidi_set_mirroring (TRUE);
1776 MLIST_FREE1 (&scratch_gstring, glyphs);
1780 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1784 /*** @addtogroup m17nDraw */
1789 @brief Draw an M-text on a window.
1791 The mdraw_text () function draws the text between $FROM and $TO of
1792 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1794 The appearance of the text (size, style, color, etc) is specified
1795 by the value of the text property whose key is @c Mface. If the
1796 M-text or a part of the M-text does not have such a text property,
1797 the default face of $FRAME is used.
1799 The font used to draw a character in the M-text is selected from
1800 the value of the fontset property of a face by the following
1805 <li> Search the text properties given to the character for the one
1806 whose key is @c Mcharset; its value should be either a symbol
1807 specifying a charset or #Mnil. If the value is #Mnil,
1808 proceed to the next step.
1810 Otherwise, search the mapping table of the fontset for the
1811 charset. If no entry is found proceed to the next step.
1813 If an entry is found, use one of the fonts in the entry that
1814 has a glyph for the character and that matches best with the
1815 face properties. If no such font exists, proceed to the next
1818 <li> Get the character property "script" of the character. If it is
1819 inherited, get the script property from the previous
1820 characters. If there is no previous character, or none of
1821 them has the script property other than inherited, proceed to
1824 Search the text properties given to the character for the one
1825 whose key is @c Mlanguage; its value should be either a
1826 symbol specifying a language or @c Mnil.
1828 Search the mapping table of the fontset for the combination
1829 of the script and language. If no entry is found, proceed to
1832 If an entry is found, use one of the fonts in the entry that
1833 has a glyph for the character and that matches best with the
1834 face properties. If no such font exists, proceed to the next
1837 <li> Search the fall-back table of the fontset for a font that has
1838 a glyph of the character. If such a font is found, use that
1843 If no font is found by the algorithm above, this function draws an
1844 empty box for the character.
1846 This function draws only the glyph foreground. To specify the
1847 background color, use mdraw_image_text () or
1848 mdraw_text_with_control ().
1850 This function is the counterpart of <tt>XDrawString ()</tt>,
1851 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1852 in the X Window System.
1855 If the operation was successful, mdraw_text () returns 0. If an
1856 error is detected, it returns -1 and assigns an error code to the
1857 external variable #merror_code. */
1859 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1861 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1862 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1865 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1866 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1867 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1868 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1870 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1871 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1875 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1876 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1877 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1878 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1879 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1882 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1883 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1884 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1887 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1888 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1889 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1890 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1892 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1893 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1896 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1897 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1900 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1901 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1902 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1905 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1906 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1910 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1911 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1913 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1914 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1917 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1918 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1921 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1922 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1924 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1931 mdraw_image_text () */
1934 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1935 MText *mt, int from, int to)
1937 MDrawControl control;
1939 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1940 memset (&control, 0, sizeof control);
1941 control.as_image = 0;
1942 return draw_text (frame, win, x, y, mt, from, to, &control);
1949 @brief Draw an M-text on a window as an image.
1951 The mdraw_image_text () function draws the text between $FROM and
1952 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1953 coordinate ($X, $Y).
1955 The way to draw a text is the same as in mdraw_text () except that
1956 this function also draws the background with the color specified
1959 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1960 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1961 functions in the X Window System.
1964 If the operation was successful, mdraw_image_text () returns 0.
1965 If an error is detected, it returns -1 and assigns an error code
1966 to the external variable #merror_code. */
1969 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1971 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1972 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1975 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1976 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1978 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1979 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1983 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1984 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1987 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1997 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1998 MText *mt, int from, int to)
2000 MDrawControl control;
2002 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2003 memset (&control, 0, sizeof control);
2004 control.as_image = 1;
2005 return draw_text (frame, win, x, y, mt, from, to, &control);
2011 @brief Draw an M-text on a window with fine control.
2013 The mdraw_text_with_control () function draws the text between
2014 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2015 coordinate ($X, $Y).
2017 The way to draw a text is the same as in mdraw_text () except that
2018 this function also follows what specified in the drawing control
2021 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2022 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2023 breaks lines and the following characters are drawn in the next
2024 line. See the documentation of the structure @ MDrawControl for
2028 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2030 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2031 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2034 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2035 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2037 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2038 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2039 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2043 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2044 MText *mt, int from, int to, MDrawControl *control)
2046 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2047 return draw_text (frame, win, x, y, mt, from, to, control);
2053 @brief Compute text pixel width.
2055 The mdraw_text_extents () function computes the width of text
2056 between $FROM and $TO of M-text $MT when it is drawn on a window
2057 of frame $FRAME using the mdraw_text_with_control () function with
2058 the drawing control object $CONTROL.
2060 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2061 the bounding box of character ink of the M-text, and stores the
2062 results in the members of the structure pointed to by
2063 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2064 surrounding box, the box is included in the bounding box.
2066 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2067 computes the bounding box that provides mininum spacing to other
2068 graphical features (such as surrounding box) for the M-text, and
2069 stores the results in the members of the structure pointed to by
2070 $OVERALL_LOGICAL_RETURN.
2072 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2073 computes the bounding box that provides mininum spacing to the
2074 other M-text drawn, and stores the results in the members of the
2075 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2076 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2077 min_line_ascent, min_line_descent, max_line_ascent, and
2078 max_line_descent of $CONTROL are all zero.
2081 This function returns the width of the text to be drawn in the
2082 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2083 text is drawn in multiple physical lines, it returns the width of
2084 the widest line. If an error occurs, it returns -1 and assigns an
2085 error code to the external variable #merror_code. */
2089 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2091 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2092 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2093 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2095 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2096 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2097 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2098 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2100 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2101 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2102 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2103 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2105 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2106 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2107 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2108 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2109 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2110 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2112 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2113 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2114 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2115 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2117 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2124 mdraw_text_extents (MFrame *frame,
2125 MText *mt, int from, int to, MDrawControl *control,
2126 MDrawMetric *overall_ink_return,
2127 MDrawMetric *overall_logical_return,
2128 MDrawMetric *overall_line_return)
2130 MGlyphString *gstring;
2132 int width, rbearing;
2134 ASSURE_CONTROL (control);
2135 M_CHECK_POS_X (mt, from, -1);
2136 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2137 to = mtext_nchars (mt) + (control->cursor_width != 0);
2141 gstring = get_gstring (frame, mt, from, to, control);
2143 MERROR (MERROR_DRAW, -1);
2144 width = gstring_width (gstring, from, to, &rbearing);
2145 if (overall_ink_return)
2147 overall_ink_return->y = - gstring->physical_ascent;
2148 overall_ink_return->x = gstring->lbearing;
2150 if (overall_logical_return)
2152 overall_logical_return->y = - gstring->ascent;
2153 overall_logical_return->x = 0;
2155 if (overall_line_return)
2157 overall_line_return->y = - gstring->line_ascent;
2158 overall_line_return->x = gstring->lbearing;
2161 for (from = gstring->to; from < to; from = gstring->to)
2163 int this_width, this_rbearing;
2165 y += gstring->line_descent;
2166 M17N_OBJECT_UNREF (gstring->top);
2167 gstring = get_gstring (frame, mt, from, to, control);
2168 this_width = gstring_width (gstring, from, to, &this_rbearing);
2169 y += gstring->line_ascent;
2170 if (width < this_width)
2172 if (rbearing < this_rbearing)
2173 rbearing = this_rbearing;
2175 if (overall_ink_return)
2177 overall_ink_return->width = rbearing;
2178 overall_ink_return->height
2179 = y + gstring->physical_descent - overall_ink_return->y;
2181 if (overall_logical_return)
2183 overall_logical_return->width = width;
2184 overall_logical_return->height
2185 = y + gstring->descent - overall_logical_return->y;
2187 if (overall_line_return)
2189 overall_line_return->width = MAX (width, rbearing);
2190 overall_line_return->height
2191 = y + gstring->line_descent - overall_line_return->y;
2194 M17N_OBJECT_UNREF (gstring->top);
2201 @brief Compute the text dimensions of each character of M-text.
2203 The mdraw_text_per_char_extents () function computes the drawn
2204 metric of each character between $FROM and $TO of M-text $MT
2205 assuming that they are drawn on a window of frame $FRAME using the
2206 mdraw_text_with_control () function with the drawing control
2209 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2210 $LOGICAL_ARRAY_RETURN. Each successive element of
2211 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2212 ink and logical metrics of successive characters respectively,
2213 relative to the drawing origin of the M-text. The number of
2214 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2215 been set is returned to $NUM_CHARS_RETURN.
2217 If $ARRAY_SIZE is too small to return all metrics, the function
2218 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2219 Otherwise, it returns zero.
2221 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2222 @c NULL, this function also computes the metrics of the overall
2223 text and stores the results in the members of the structure
2224 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2226 If $CONTROL->two_dimensional is nonzero, this function computes
2227 only the metrics of characters in the first line. */
2229 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2231 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2232 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2233 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2234 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2236 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2237 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2238 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2239 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2240 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2242 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2243 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2246 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2247 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2248 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2251 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2252 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2255 mdraw_text_per_char_extents (MFrame *frame,
2256 MText *mt, int from, int to,
2257 MDrawControl *control,
2258 MDrawMetric *ink_array_return,
2259 MDrawMetric *logical_array_return,
2261 int *num_chars_return,
2262 MDrawMetric *overall_ink_return,
2263 MDrawMetric *overall_logical_return)
2265 MGlyphString *gstring;
2269 ASSURE_CONTROL (control);
2270 *num_chars_return = to - from;
2271 if (array_size < *num_chars_return)
2272 MERROR (MERROR_DRAW, -1);
2273 if (overall_logical_return)
2274 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2275 if (overall_ink_return)
2276 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2278 M_CHECK_RANGE (mt, from, to, -1, 0);
2279 gstring = get_gstring (frame, mt, from, to, control);
2282 *num_chars_return = 0;
2286 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2287 if (g->pos >= from && g->pos < to)
2291 int width = g->width;
2292 int lbearing = g->lbearing;
2293 int rbearing = g->rbearing;
2294 int ascent = g->ascent;
2295 int descent = g->descent;
2296 int logical_ascent = g->rface->rfont->ascent;
2297 int logical_descent = g->rface->rfont->descent;
2299 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2301 if (lbearing < width + g->lbearing)
2302 lbearing = width + g->lbearing;
2303 if (rbearing < width + g->rbearing)
2304 rbearing = width + g->rbearing;
2306 if (ascent < g->ascent)
2308 if (descent < g->descent)
2309 descent = g->descent;
2316 ink_array_return[start - from].x = x + lbearing;
2317 ink_array_return[start - from].y = - ascent;
2318 ink_array_return[start - from].width = rbearing - lbearing;
2319 ink_array_return[start - from].height = ascent + descent;
2320 logical_array_return[start - from].x = x;
2321 logical_array_return[start - from].y = - logical_descent;
2322 logical_array_return[start - from].height
2323 = logical_ascent + logical_descent;
2324 logical_array_return[start - from].width = width;
2330 if (overall_ink_return)
2332 overall_ink_return->y = - gstring->line_ascent;
2333 overall_ink_return->x = gstring->lbearing;
2334 overall_ink_return->width = x - gstring->lbearing;
2335 overall_ink_return->height = gstring->height;
2337 if (overall_logical_return)
2339 overall_logical_return->y = - gstring->ascent;
2340 overall_logical_return->x = 0;
2341 overall_logical_return->width = x;
2342 overall_logical_return->height = gstring->ascent + gstring->descent;
2345 M17N_OBJECT_UNREF (gstring->top);
2352 @brief Return the character position nearest to the coordinates.
2354 The mdraw_coordinates_position () function checks which character
2355 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2356 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2357 mdraw_text_with_control () function with the drawing control
2358 object $CONTROL. Here, the character position means the number of
2359 characters that precede the character in question in $MT, that is,
2360 the character position of the first character is 0.
2362 $FRAME is used only to get the default face information.
2365 If the glyph image of a character covers coordinate ($X, $Y),
2366 mdraw_coordinates_position () returns the character position of
2368 If $Y is less than the minimum Y-coordinate of the drawn area, it
2369 returns $FROM.\n\n\n
2370 If $Y is greater than the maximum Y-coordinate of the drawn area,
2371 it returns $TO.\n\n\n
2372 If $Y fits in with the drawn area but $X is less than the minimum
2373 X-coordinate, it returns the character position of the first
2374 character drawn on the line $Y.\n\n\n
2375 If $Y fits in with the drawn area but $X is greater than the
2376 maximum X-coordinate, it returns the character position of the
2377 last character drawn on the line $Y. */
2380 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2382 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2383 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2384 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2385 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2386 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2387 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2389 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2392 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2393 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2395 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2397 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2399 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2400 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2402 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2403 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2406 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2407 int x_offset, int y_offset, MDrawControl *control)
2409 MGlyphString *gstring;
2414 M_CHECK_POS_X (mt, from, -1);
2415 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2416 to = mtext_nchars (mt) + (control->cursor_width != 0);
2422 ASSURE_CONTROL (control);
2423 gstring = get_gstring (frame, mt, from, to, control);
2424 while (y + gstring->line_descent <= y_offset
2425 && gstring->to < to)
2428 y += gstring->line_descent;
2429 M17N_OBJECT_UNREF (gstring->top);
2430 gstring = get_gstring (frame, mt, from, to, control);
2431 y += gstring->line_ascent;
2434 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2435 if (! control->orientation_reversed)
2437 width = gstring->indent;
2438 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2439 if (g->pos >= from && g->pos < to)
2442 if (width > x_offset)
2448 width = - gstring->indent;
2449 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2450 if (g->pos >= from && g->pos < to)
2453 if (width < x_offset)
2458 M17N_OBJECT_UNREF (gstring->top);
2466 @brief Compute information about a glyph.
2468 The mdraw_glyph_info () function computes information about a
2469 glyph that covers a character at position $POS of the M-text $MT
2470 assuming that the text is drawn from the character at $FROM of $MT
2471 on a window of frame $FRAME using the mdraw_text_with_control ()
2472 function with the drawing control object $CONTROL.
2474 The information is stored in the members of $INFO. */
2476 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2478 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2479 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2480 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2481 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2483 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2491 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2492 MDrawControl *control, MDrawGlyphInfo *info)
2494 MGlyphString *gstring;
2498 M_CHECK_RANGE_X (mt, from, pos, -1);
2500 ASSURE_CONTROL (control);
2501 gstring = get_gstring (frame, mt, from, pos + 1, control);
2503 MERROR (MERROR_DRAW, -1);
2504 while (gstring->to <= pos)
2506 y += gstring->line_descent;
2507 M17N_OBJECT_UNREF (gstring->top);
2508 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2509 y += gstring->line_ascent;
2511 info->line_from = gstring->from;
2512 if (info->line_from < from)
2513 info->line_from = from;
2514 info->line_to = gstring->to;
2517 if (! control->orientation_reversed)
2519 info->x = gstring->indent;
2520 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2521 info->x += g->width;
2525 info->x = - gstring->indent;
2526 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2527 info->x -= g->width;
2528 while (g[-1].to == g->to)
2531 info->from = g->pos;
2533 info->glyph_code = g->code;
2534 info->this.x = g->lbearing;
2535 info->this.y = - gstring->line_ascent;
2536 info->this.height = gstring->height;
2537 info->this.width = - g->lbearing + g->width;
2538 if (g->rface->rfont)
2539 info->font = &g->rface->rfont->font;
2542 /* info->logical_width is calculated later. */
2544 if (info->from > info->line_from)
2546 /* The logically previous glyph is on this line. */
2547 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2549 info->prev_from = g_tmp->pos;
2551 else if (info->line_from > 0)
2553 /* The logically previous glyph is on the previous line. */
2554 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2555 gstring->from, control);
2556 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2558 info->prev_from = g_tmp->pos;
2559 M17N_OBJECT_UNREF (gst->top);
2562 info->prev_from = -1;
2564 if (GLYPH_INDEX (g) > 1)
2565 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2566 else if (! control->orientation_reversed)
2568 if (info->line_from > 0)
2572 int p = gstring->from - 1;
2574 gst = get_gstring (frame, mt, p, gstring->from, control);
2575 g_tmp = gst->glyphs + (gst->used - 2);
2576 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2577 M17N_OBJECT_UNREF (gst->top);
2580 info->left_from = info->left_to = -1;
2584 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2588 int p = gstring->to;
2590 gst = get_gstring (frame, mt, p, p + 1, control);
2591 g_tmp = gst->glyphs + (gst->used - 2);
2592 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2593 M17N_OBJECT_UNREF (gst->top);
2596 info->left_from = info->left_to = -1;
2599 if (info->to < gstring->to)
2601 /* The logically next glyph is on this line. */
2602 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2604 info->next_to = g_tmp->to;
2606 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2608 /* The logically next glyph is on the next line. */
2610 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2611 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2613 info->next_to = g_tmp->to;
2614 M17N_OBJECT_UNREF (gst->top);
2619 for (info->logical_width = (g++)->width;
2620 g->pos == pos && g->type != GLYPH_ANCHOR;
2621 info->this.width += g->width, info->logical_width += (g++)->width);
2622 info->this.width += g[-1].rbearing - g[-1].width;
2624 if (g->type != GLYPH_ANCHOR)
2625 info->right_from = g->pos, info->right_to = g->to;
2626 else if (! control->orientation_reversed)
2628 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2631 M17N_OBJECT_UNREF (gstring->top);
2632 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2634 info->right_from = g->pos, info->right_to = g->to;
2637 info->right_from = info->right_to = -1;
2641 if (info->line_from > 0)
2643 pos = gstring->from - 1;
2644 M17N_OBJECT_UNREF (gstring->top);
2645 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2647 info->right_from = g->pos, info->right_to = g->to;
2650 info->right_from = info->right_to = -1;
2653 M17N_OBJECT_UNREF (gstring->top);
2660 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2661 MDrawControl *control, MDrawGlyphInfo *info,
2662 int array_size, int *num_glyphs_return)
2664 MGlyphString *gstring;
2669 ASSURE_CONTROL (control);
2670 *num_glyphs_return = 0;
2671 M_CHECK_RANGE (mt, from, to, -1, 0);
2672 gstring = get_gstring (frame, mt, from, to, control);
2675 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2677 if (g->type == GLYPH_BOX
2678 || g->pos < from || g->pos >= to)
2680 if (g->type == GLYPH_PAD)
2682 if (g->left_padding)
2683 pad_width = g->width;
2687 info[-1].x += g->width;
2688 info[-1].logical_width += g->width;
2694 info->from = g->pos;
2696 info->glyph_code = g->code;
2697 info->x = g->xoff + pad_width;
2699 info->this.x = g->lbearing;
2700 info->this.y = - g->ascent;
2701 info->this.height = g->ascent + g->descent;
2702 info->this.width = g->rbearing - g->lbearing;
2703 info->logical_width = g->width + pad_width;
2704 if (g->rface->rfont)
2705 info->font = &g->rface->rfont->font;
2713 M17N_OBJECT_UNREF (gstring->top);
2715 *num_glyphs_return = n;
2716 return (n <= array_size ? 0 : -1);
2722 @brief Draw one or more textitems.
2724 The mdraw_text_items () function draws one or more M-texts on
2725 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2726 of the textitems to be drawn and $NITEMS is the number of
2727 textimtems in the array. */
2730 @brief textitem ¤òɽ¼¨¤¹¤ë.
2732 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2733 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2734 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2737 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2741 MTextItem, mdraw_text (). */
2744 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2745 MDrawTextItem *items, int nitems)
2747 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2749 while (nitems-- > 0)
2752 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2754 mdraw_text_with_control (frame, win, x, y,
2755 items->mt, 0, mtext_nchars (items->mt),
2757 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2758 items->control, NULL, NULL, NULL);
2761 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2767 @brief calculate a line breaking position.
2769 The function mdraw_default_line_break () calculates a line
2770 breaking position based on the line number $LINE and the
2771 coordinate $Y, when a line is too long to fit within the width
2772 limit. $POS is the position of the character next to the last
2773 one that fits within the limit. $FROM is the position of the
2774 first character of the line, and TO is the position of the last
2775 character displayed on the line if there were not width limit.
2776 LINE and Y are reset to 0 when a line is broken by a newline
2777 character, and incremented each time when a long line is broken
2778 because of the width limit.
2781 This function returns a character position to break the
2786 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2788 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2789 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2790 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2791 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2792 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2793 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2794 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2797 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2801 mdraw_default_line_break (MText *mt, int pos,
2802 int from, int to, int line, int y)
2804 int c = mtext_ref_char (mt, pos);
2807 if (c == ' ' || c == '\t')
2811 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2818 if (c == ' ' || c == '\t')
2821 c = mtext_ref_char (mt, pos);
2834 @brief Obtain per character dimension information.
2836 The mdraw_per_char_extents () function computes the text dimension
2837 of each character in M-text $MT. The faces given as text
2838 properties in $MT and the default face of frame $FRAME determine
2839 the fonts to draw the text. Each successive element in
2840 $ARRAY_RETURN is set to the drawn metrics of successive
2841 characters, which is relative to the origin of the drawing, and a
2842 rectangle for each character in $MT. The number of elements of
2843 $ARRAY_RETURN must be equal to or greater than the number of
2846 If pointer $OVERALL_RETURN is not @c NULL, this function also
2847 computes the extents of the overall text and stores the results in
2848 the members of the structure pointed to by $OVERALL_RETURN. */
2851 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2853 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2854 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2855 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2856 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2857 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2858 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2861 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2862 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2865 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2868 mdraw_per_char_extents (MFrame *frame, MText *mt,
2869 MDrawMetric *array_return,
2870 MDrawMetric *overall_return)
2872 int n = mtext_nchars (mt);
2874 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2875 n, &n, overall_return, NULL);
2879 @brief clear cached information.
2881 The mdraw_clear_cache () function clear cached information
2882 on M-text $MT that was attached by any of the drawing functions.
2883 When the behaviour of `format' or `line_break'
2884 member functions of MDrawControl is changed, the cache must be cleared.
2889 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2891 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2892 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2893 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2894 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2899 mdraw_clear_cache (MText *mt)
2901 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);