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) * size);
146 for (i = 0; i < size; i++)
152 for (j = i + 1; j < size && 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;
1031 && gstring->from <= control->cursor_pos - 1
1032 && gstring->to > control->cursor_pos - 1)
1033 prev_pos = control->cursor_pos - 1;
1036 *from_idx = *to_idx = 0;
1037 while (g->type != GLYPH_ANCHOR)
1039 if (g->pos >= from && g->pos < to)
1041 MGlyph *fromg = g, *cursor = NULL;
1042 MRealizedFace *rface = g->rface;
1044 int cursor_width = 0;
1048 *from_idx = GLYPH_INDEX (g);
1049 while (g->pos >= from && g->pos < to
1050 && g->rface == rface)
1053 if (g->type != GLYPH_BOX
1054 && g->pos <= cursor_pos && g->to > cursor_pos)
1057 cursor = g, cursor_x = x + width;
1058 cursor_width += g->width;
1060 width += g++->width;
1063 && (control->as_image
1064 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1066 int this_x = x, this_width = width;
1068 if (fromg->type == GLYPH_BOX)
1069 this_x += fromg->width, this_width -= fromg->width;
1070 if (g[-1].type == GLYPH_BOX)
1071 this_width -= g[-1].width;
1072 (frame->driver->fill_space)
1073 (frame, win, rface, 0,
1074 this_x, y - gstring->text_ascent, this_width,
1075 gstring->text_ascent + gstring->text_descent,
1076 control->clip_region);
1083 rect.y = y - gstring->text_ascent;
1084 rect.height = gstring->text_ascent + gstring->text_descent;
1087 rect.width = ((control->cursor_width > 0
1088 && control->cursor_width < cursor_width)
1089 ? control->cursor_width : cursor_width);
1093 if (cursor->bidi_level % 2)
1094 rect.x += cursor_width - 1;
1097 (*frame->driver->fill_space)
1098 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1099 control->clip_region);
1101 region = (*frame->driver->region_from_rect) (&rect);
1103 (*frame->driver->region_add_rect) (region, &rect);
1106 if (cursor->bidi_level % 2)
1109 rect.width = cursor_width < 4 ? cursor_width : 4;
1110 (*frame->driver->fill_space)
1111 (frame, win, rface, 1,
1112 rect.x, rect.y, rect.width, rect.height,
1113 control->clip_region);
1114 (*frame->driver->region_add_rect) (region, &rect);
1126 if (fromg->type != GLYPH_BOX
1127 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1130 cursor = fromg, cursor_x = x + temp_width;
1131 cursor_width += fromg->width;
1133 temp_width += fromg++->width;
1140 if (! (cursor->bidi_level % 2))
1141 rect.x += cursor_width - 1;
1142 rect.y = y - gstring->text_ascent;
1143 rect.height = gstring->text_ascent + gstring->text_descent;
1145 (*frame->driver->fill_space)
1146 (frame, win, rface, 1,
1147 rect.x, rect.y, rect.width, rect.height,
1148 control->clip_region);
1150 region = (*frame->driver->region_from_rect) (&rect);
1152 (*frame->driver->region_add_rect) (region, &rect);
1153 rect.y += rect.height - 2;
1155 rect.width = cursor_width < 4 ? cursor_width : 4;
1156 if (! (cursor->bidi_level % 2))
1157 rect.x -= rect.width - 1;
1158 (*frame->driver->fill_space) (frame, win, rface, 1,
1159 rect.x, rect.y, rect.width, rect.height,
1160 control->clip_region);
1161 (*frame->driver->region_add_rect) (region, &rect);
1165 *to_idx = GLYPH_INDEX (g);
1175 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1176 MGlyphString *gstring, int from_idx, int to_idx,
1177 int reverse, MDrawRegion region)
1179 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1185 (*frame->driver->region_to_rect) (region, &rect);
1188 while (g != gend && x + g->rbearing <= rect.x)
1191 width -= g++->width;
1192 while (! g->enabled && g != gend)
1196 rect.x += rect.width;
1197 if (rect.x < x + width)
1200 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1202 width -= (--gend)->width;
1203 while (! gend->enabled && g != gend)
1207 while (gend[-1].to == gend->to) gend++;
1215 MRealizedFace *rface = g->rface;
1216 int width = g->width;
1217 MGlyph *from_g = g++;
1219 /* Handle the glyphs of the same type/face at once. */
1221 && g->type == from_g->type
1222 && g->rface == rface
1223 && ((g->code == MCHAR_INVALID_CODE)
1224 == (from_g->code == MCHAR_INVALID_CODE))
1226 width += g++->width;
1228 if (from_g->type == GLYPH_CHAR)
1230 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1231 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1234 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1237 else if (from_g->type == GLYPH_BOX)
1239 /* Draw the left or right side of a box. If
1240 from_g->lbearing is nonzero, this is the left side,
1241 else this is the right side. */
1242 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1245 if (from_g->type != GLYPH_BOX)
1248 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1249 x, y, width, region);
1252 /* Draw the top and bottom side of a box. */
1253 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1254 x, y, width, region);
1265 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1266 int *from_x, int *to_x)
1269 int left_idx = *left, right_idx = *right;
1270 int left_x, right_x, x;
1272 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1275 if (x + g->rbearing > 0)
1277 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1279 left_idx = GLYPH_INDEX (g);
1284 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1287 if (x - g->width + g->lbearing < 0)
1289 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1291 right_idx = GLYPH_INDEX (g) + 1;
1296 if (*left == left_idx && *right == right_idx)
1299 if (*left != left_idx)
1301 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1306 if (*right != right_idx)
1308 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1318 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1323 if (from <= gstring->from && to >= gstring->to)
1326 *rbearing = gstring->rbearing;
1327 return gstring->width;
1332 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1333 if (g->pos >= from && g->pos < to)
1335 if (rbearing && width + g->rbearing > *rbearing)
1336 *rbearing = width + g->rbearing;
1344 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1345 MGlyphString *gstring, int from, int to)
1347 MDrawControl *control = &gstring->control;
1349 MDrawRegion clip_region, cursor_region;
1350 int from_idx, to_idx;
1353 if (control->orientation_reversed)
1354 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1356 x += gstring->indent;
1358 /* At first, draw all glyphs without cursor. */
1359 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1360 &from_idx, &to_idx, &to_x);
1362 if (control->partial_update)
1365 rect.width = to_x - x;
1366 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1368 rect.y = y - gstring->line_ascent;
1369 rect.height = gstring->height;
1370 clip_region = (*frame->driver->region_from_rect) (&rect);
1371 if (control->clip_region)
1372 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1375 clip_region = control->clip_region;
1378 clip_region = control->clip_region;
1380 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1385 (*frame->driver->intersect_region) (cursor_region, clip_region);
1386 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1389 if (clip_region != control->clip_region)
1390 (*frame->driver->free_region) (clip_region);
1392 (*frame->driver->free_region) (cursor_region);
1396 static int gstring_num;
1399 free_gstring (void *object)
1401 MGlyphString *gstring = (MGlyphString *) object;
1404 free_gstring (gstring->next);
1405 if (gstring->size > 0)
1406 free (gstring->glyphs);
1412 static MGlyphString scratch_gstring;
1414 static MGlyphString *
1415 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1418 MGlyphString *gstring;
1420 if (pos == mt->nchars)
1422 gstring = &scratch_gstring;
1426 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1427 MLIST_INIT1 (gstring, glyphs, 128);
1431 gstring->frame = frame;
1432 gstring->tick = frame->tick;
1433 gstring->top = gstring;
1435 gstring->control = *control;
1436 gstring->indent = gstring->width_limit = 0;
1437 if (control->format)
1438 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1440 gstring->width_limit = control->max_line_width;
1441 gstring->anti_alias = control->anti_alias;
1445 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1448 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1456 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1457 a width of glyphs for the character at I of GSTRING->mt. If I is
1458 not a beginning of a grapheme cluster, the corresponding element
1460 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1461 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1462 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1463 pos_width[g->pos - gstring->from] += g->width;
1464 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1466 if (pos_width[i] > 0)
1468 if (width + pos_width[i] > gstring->width_limit)
1471 width += pos_width[i];
1474 pos = gstring->from + i;
1475 if (gstring->control.line_break)
1477 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1478 gstring->from, gstring->to, 0, 0);
1479 if (pos <= gstring->from || pos >= gstring->to)
1482 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1483 layout_glyph_string (frame, gstring);
1487 /* Return a gstring that covers a character at POS. */
1489 static MGlyphString *
1490 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1492 MGlyphString *gstring = NULL;
1494 if (pos < mtext_nchars (mt))
1496 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1499 && ((prop->start != 0
1500 && mtext_ref_char (mt, prop->start - 1) != '\n')
1501 || (prop->end < mtext_nchars (mt)
1502 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1504 mtext_detach_property (prop);
1509 gstring = prop->val;
1510 if (gstring->frame != frame
1511 || gstring->tick != frame->tick
1512 || memcmp (control, &gstring->control,
1513 (char *) (&control->with_cursor)
1514 - (char *) (control)))
1516 mtext_detach_property (prop);
1521 else if (! control->cursor_width)
1529 offset = mtext_character (mt, pos, 0, '\n');
1534 offset -= gstring->from;
1536 for (gst = gstring; gst; gst = gst->next)
1540 gst->from += offset;
1542 for (i = 0; i < gst->used; i++)
1544 gst->glyphs[i].pos += offset;
1545 gst->glyphs[i].to += offset;
1548 M17N_OBJECT_REF (gstring);
1553 int line = 0, y = 0;
1555 if (control->two_dimensional)
1557 beg = mtext_character (mt, pos, 0, '\n');
1562 end = mtext_nchars (mt) + (control->cursor_width != 0);
1569 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1570 compose_glyph_string (frame, mt, beg, end, gstring);
1571 layout_glyph_string (frame, gstring);
1573 if (control->two_dimensional
1574 && gstring->width_limit
1575 && gstring->width > gstring->width_limit)
1577 MGlyphString *gst = gstring;
1579 truncate_gstring (frame, mt, gst);
1580 while (gst->to < end)
1582 line++, y += gst->height;
1583 gst->next = alloc_gstring (frame, mt, gst->from, control,
1585 gst->next->top = gstring;
1586 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1588 layout_glyph_string (frame, gst);
1589 if (gst->width <= gst->width_limit)
1591 truncate_gstring (frame, mt, gst);
1595 if (! control->disable_caching && pos < mtext_nchars (mt))
1597 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1598 MTEXTPROP_VOLATILE_STRONG);
1600 if (end > mtext_nchars (mt))
1601 end = mtext_nchars (mt);
1602 mtext_attach_property (mt, beg, end, prop);
1603 M17N_OBJECT_UNREF (prop);
1607 while (gstring->to <= pos)
1609 if (! gstring->next)
1611 gstring = gstring->next;
1613 gstring->control = *control;
1619 static MDrawControl control_noop;
1621 #define ASSURE_CONTROL(control) \
1623 control = &control_noop; \
1628 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1629 MText *mt, int from, int to,
1630 MDrawControl *control)
1632 MGlyphString *gstring;
1634 M_CHECK_POS_X (mt, from, -1);
1635 ASSURE_CONTROL (control);
1636 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1637 to = mtext_nchars (mt) + (control->cursor_width != 0);
1641 gstring = get_gstring (frame, mt, from, to, control);
1643 MERROR (MERROR_DRAW, -1);
1644 render_glyph_string (frame, win, x, y, gstring, from, to);
1648 y += gstring->line_descent;
1649 M17N_OBJECT_UNREF (gstring->top);
1650 gstring = get_gstring (frame, mt, from, to, control);
1651 y += gstring->line_ascent;
1652 render_glyph_string (frame, win, x, y, gstring, from, to);
1655 M17N_OBJECT_UNREF (gstring->top);
1662 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1668 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1669 if (g->pos <= pos && g->to > pos)
1674 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1675 if (g->pos <= pos && g->to > pos)
1682 /* for debugging... */
1686 dump_combining_code (int code)
1688 char *vallign = "tcbB";
1689 char *hallign = "lcr";
1695 if (COMBINING_BY_CLASS_P (code))
1696 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1697 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1698 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1699 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1700 off_x = COMBINING_CODE_OFF_X (code) - 128;
1702 sprintf (work + 2, "+%d", off_y);
1704 sprintf (work + 2, "%d", off_y);
1705 else if (off_x == 0)
1706 sprintf (work + 2, ".");
1707 p = work + strlen (work);
1709 sprintf (p, ">%d", off_x);
1711 sprintf (p, "<%d", -off_x);
1713 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1714 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1720 dump_gstring (MGlyphString *gstring, int indent)
1722 char *prefix = (char *) alloca (indent + 1);
1723 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1725 memset (prefix, 32, indent);
1728 fprintf (stderr, "(glyph-string");
1730 for (g = MGLYPH (0); g < last_g; g++)
1732 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1734 g - gstring->glyphs,
1735 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1736 : g->type == GLYPH_ANCHOR ? "ANC"
1737 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1738 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1739 dump_combining_code (g->combining_code),
1740 g->width, g->bidi_level);
1741 fprintf (stderr, ")");
1745 /* m17n-X internal APIs */
1750 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1752 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1753 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1755 Mlatin = msymbol ("latin");
1756 Minherited = msymbol ("inherited");
1758 McatCc = msymbol ("Cc");
1759 McatCf = msymbol ("Cf");
1761 MbidiR = msymbol ("R");
1762 MbidiAL = msymbol ("AL");
1763 MbidiRLE = msymbol ("RLE");
1764 MbidiRLO = msymbol ("RLO");
1765 MbidiBN = msymbol ("BN");
1766 MbidiS = msymbol ("S");
1768 fribidi_set_mirroring (TRUE);
1777 MLIST_FREE1 (&scratch_gstring, glyphs);
1781 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1785 /*** @addtogroup m17nDraw */
1790 @brief Draw an M-text on a window.
1792 The mdraw_text () function draws the text between $FROM and $TO of
1793 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1795 The appearance of the text (size, style, color, etc) is specified
1796 by the value of the text property whose key is @c Mface. If the
1797 M-text or a part of the M-text does not have such a text property,
1798 the default face of $FRAME is used.
1800 The font used to draw a character in the M-text is selected from
1801 the value of the fontset property of a face by the following
1806 <li> Search the text properties given to the character for the one
1807 whose key is @c Mcharset; its value should be either a symbol
1808 specifying a charset or #Mnil. If the value is #Mnil,
1809 proceed to the next step.
1811 Otherwise, search the mapping table of the fontset for the
1812 charset. If no entry is found proceed to the next step.
1814 If an entry is found, use one of the fonts in the entry that
1815 has a glyph for the character and that matches best with the
1816 face properties. If no such font exists, proceed to the next
1819 <li> Get the character property "script" of the character. If it is
1820 inherited, get the script property from the previous
1821 characters. If there is no previous character, or none of
1822 them has the script property other than inherited, proceed to
1825 Search the text properties given to the character for the one
1826 whose key is @c Mlanguage; its value should be either a
1827 symbol specifying a language or @c Mnil.
1829 Search the mapping table of the fontset for the combination
1830 of the script and language. If no entry is found, proceed to
1833 If an entry is found, use one of the fonts in the entry that
1834 has a glyph for the character and that matches best with the
1835 face properties. If no such font exists, proceed to the next
1838 <li> Search the fall-back table of the fontset for a font that has
1839 a glyph of the character. If such a font is found, use that
1844 If no font is found by the algorithm above, this function draws an
1845 empty box for the character.
1847 This function draws only the glyph foreground. To specify the
1848 background color, use mdraw_image_text () or
1849 mdraw_text_with_control ().
1851 This function is the counterpart of <tt>XDrawString ()</tt>,
1852 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1853 in the X Window System.
1856 If the operation was successful, mdraw_text () returns 0. If an
1857 error is detected, it returns -1 and assigns an error code to the
1858 external variable #merror_code. */
1860 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1862 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1863 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1866 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1867 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1868 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1869 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1871 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1872 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1876 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1877 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1878 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1879 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1880 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1883 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1884 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1885 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1888 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1889 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1890 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1891 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1893 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1894 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1897 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1898 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1901 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1902 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1903 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1906 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1907 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1911 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1912 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1914 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1915 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1918 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1919 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1922 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1923 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1925 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1932 mdraw_image_text () */
1935 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1936 MText *mt, int from, int to)
1938 MDrawControl control;
1940 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1941 memset (&control, 0, sizeof control);
1942 control.as_image = 0;
1943 return draw_text (frame, win, x, y, mt, from, to, &control);
1950 @brief Draw an M-text on a window as an image.
1952 The mdraw_image_text () function draws the text between $FROM and
1953 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1954 coordinate ($X, $Y).
1956 The way to draw a text is the same as in mdraw_text () except that
1957 this function also draws the background with the color specified
1960 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1961 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1962 functions in the X Window System.
1965 If the operation was successful, mdraw_image_text () returns 0.
1966 If an error is detected, it returns -1 and assigns an error code
1967 to the external variable #merror_code. */
1970 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1972 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1973 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1976 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1977 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1979 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1980 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1984 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1985 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1988 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1998 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1999 MText *mt, int from, int to)
2001 MDrawControl control;
2003 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2004 memset (&control, 0, sizeof control);
2005 control.as_image = 1;
2006 return draw_text (frame, win, x, y, mt, from, to, &control);
2012 @brief Draw an M-text on a window with fine control.
2014 The mdraw_text_with_control () function draws the text between
2015 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2016 coordinate ($X, $Y).
2018 The way to draw a text is the same as in mdraw_text () except that
2019 this function also follows what specified in the drawing control
2022 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2023 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2024 breaks lines and the following characters are drawn in the next
2025 line. See the documentation of the structure @ MDrawControl for
2029 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2031 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2032 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2035 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2036 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2038 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2039 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2040 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2044 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2045 MText *mt, int from, int to, MDrawControl *control)
2047 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2048 return draw_text (frame, win, x, y, mt, from, to, control);
2054 @brief Compute text pixel width.
2056 The mdraw_text_extents () function computes the width of text
2057 between $FROM and $TO of M-text $MT when it is drawn on a window
2058 of frame $FRAME using the mdraw_text_with_control () function with
2059 the drawing control object $CONTROL.
2061 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2062 the bounding box of character ink of the M-text, and stores the
2063 results in the members of the structure pointed to by
2064 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2065 surrounding box, the box is included in the bounding box.
2067 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2068 computes the bounding box that provides mininum spacing to other
2069 graphical features (such as surrounding box) for the M-text, and
2070 stores the results in the members of the structure pointed to by
2071 $OVERALL_LOGICAL_RETURN.
2073 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2074 computes the bounding box that provides mininum spacing to the
2075 other M-text drawn, and stores the results in the members of the
2076 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2077 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2078 min_line_ascent, min_line_descent, max_line_ascent, and
2079 max_line_descent of $CONTROL are all zero.
2082 This function returns the width of the text to be drawn in the
2083 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2084 text is drawn in multiple physical lines, it returns the width of
2085 the widest line. If an error occurs, it returns -1 and assigns an
2086 error code to the external variable #merror_code. */
2090 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2092 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2093 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2094 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2096 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2097 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2098 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2099 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2101 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2102 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2103 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2104 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2106 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2107 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2108 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2109 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2110 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2111 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2113 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2114 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2115 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2116 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2118 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2125 mdraw_text_extents (MFrame *frame,
2126 MText *mt, int from, int to, MDrawControl *control,
2127 MDrawMetric *overall_ink_return,
2128 MDrawMetric *overall_logical_return,
2129 MDrawMetric *overall_line_return)
2131 MGlyphString *gstring;
2133 int width, rbearing;
2135 ASSURE_CONTROL (control);
2136 M_CHECK_POS_X (mt, from, -1);
2137 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2138 to = mtext_nchars (mt) + (control->cursor_width != 0);
2142 gstring = get_gstring (frame, mt, from, to, control);
2144 MERROR (MERROR_DRAW, -1);
2145 width = gstring_width (gstring, from, to, &rbearing);
2146 if (overall_ink_return)
2148 overall_ink_return->y = - gstring->physical_ascent;
2149 overall_ink_return->x = gstring->lbearing;
2151 if (overall_logical_return)
2153 overall_logical_return->y = - gstring->ascent;
2154 overall_logical_return->x = 0;
2156 if (overall_line_return)
2158 overall_line_return->y = - gstring->line_ascent;
2159 overall_line_return->x = gstring->lbearing;
2162 for (from = gstring->to; from < to; from = gstring->to)
2164 int this_width, this_rbearing;
2166 y += gstring->line_descent;
2167 M17N_OBJECT_UNREF (gstring->top);
2168 gstring = get_gstring (frame, mt, from, to, control);
2169 this_width = gstring_width (gstring, from, to, &this_rbearing);
2170 y += gstring->line_ascent;
2171 if (width < this_width)
2173 if (rbearing < this_rbearing)
2174 rbearing = this_rbearing;
2176 if (overall_ink_return)
2178 overall_ink_return->width = rbearing;
2179 overall_ink_return->height
2180 = y + gstring->physical_descent - overall_ink_return->y;
2182 if (overall_logical_return)
2184 overall_logical_return->width = width;
2185 overall_logical_return->height
2186 = y + gstring->descent - overall_logical_return->y;
2188 if (overall_line_return)
2190 overall_line_return->width = MAX (width, rbearing);
2191 overall_line_return->height
2192 = y + gstring->line_descent - overall_line_return->y;
2195 M17N_OBJECT_UNREF (gstring->top);
2202 @brief Compute the text dimensions of each character of M-text.
2204 The mdraw_text_per_char_extents () function computes the drawn
2205 metric of each character between $FROM and $TO of M-text $MT
2206 assuming that they are drawn on a window of frame $FRAME using the
2207 mdraw_text_with_control () function with the drawing control
2210 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2211 $LOGICAL_ARRAY_RETURN. Each successive element of
2212 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2213 ink and logical metrics of successive characters respectively,
2214 relative to the drawing origin of the M-text. The number of
2215 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2216 been set is returned to $NUM_CHARS_RETURN.
2218 If $ARRAY_SIZE is too small to return all metrics, the function
2219 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2220 Otherwise, it returns zero.
2222 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2223 @c NULL, this function also computes the metrics of the overall
2224 text and stores the results in the members of the structure
2225 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2227 If $CONTROL->two_dimensional is nonzero, this function computes
2228 only the metrics of characters in the first line. */
2230 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2232 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2233 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2234 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2235 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2237 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2238 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2239 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2240 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2241 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2243 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2244 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2247 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2248 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2249 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2252 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2253 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2256 mdraw_text_per_char_extents (MFrame *frame,
2257 MText *mt, int from, int to,
2258 MDrawControl *control,
2259 MDrawMetric *ink_array_return,
2260 MDrawMetric *logical_array_return,
2262 int *num_chars_return,
2263 MDrawMetric *overall_ink_return,
2264 MDrawMetric *overall_logical_return)
2266 MGlyphString *gstring;
2270 ASSURE_CONTROL (control);
2271 *num_chars_return = to - from;
2272 if (array_size < *num_chars_return)
2273 MERROR (MERROR_DRAW, -1);
2274 if (overall_logical_return)
2275 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2276 if (overall_ink_return)
2277 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2279 M_CHECK_RANGE (mt, from, to, -1, 0);
2280 gstring = get_gstring (frame, mt, from, to, control);
2283 *num_chars_return = 0;
2287 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2288 if (g->pos >= from && g->pos < to)
2292 int width = g->width;
2293 int lbearing = g->lbearing;
2294 int rbearing = g->rbearing;
2295 int ascent = g->ascent;
2296 int descent = g->descent;
2297 int logical_ascent = g->rface->rfont->ascent;
2298 int logical_descent = g->rface->rfont->descent;
2300 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2302 if (lbearing < width + g->lbearing)
2303 lbearing = width + g->lbearing;
2304 if (rbearing < width + g->rbearing)
2305 rbearing = width + g->rbearing;
2307 if (ascent < g->ascent)
2309 if (descent < g->descent)
2310 descent = g->descent;
2317 ink_array_return[start - from].x = x + lbearing;
2318 ink_array_return[start - from].y = - ascent;
2319 ink_array_return[start - from].width = rbearing - lbearing;
2320 ink_array_return[start - from].height = ascent + descent;
2321 logical_array_return[start - from].x = x;
2322 logical_array_return[start - from].y = - logical_descent;
2323 logical_array_return[start - from].height
2324 = logical_ascent + logical_descent;
2325 logical_array_return[start - from].width = width;
2331 if (overall_ink_return)
2333 overall_ink_return->y = - gstring->line_ascent;
2334 overall_ink_return->x = gstring->lbearing;
2335 overall_ink_return->width = x - gstring->lbearing;
2336 overall_ink_return->height = gstring->height;
2338 if (overall_logical_return)
2340 overall_logical_return->y = - gstring->ascent;
2341 overall_logical_return->x = 0;
2342 overall_logical_return->width = x;
2343 overall_logical_return->height = gstring->ascent + gstring->descent;
2346 M17N_OBJECT_UNREF (gstring->top);
2353 @brief Return the character position nearest to the coordinates.
2355 The mdraw_coordinates_position () function checks which character
2356 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2357 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2358 mdraw_text_with_control () function with the drawing control
2359 object $CONTROL. Here, the character position means the number of
2360 characters that precede the character in question in $MT, that is,
2361 the character position of the first character is 0.
2363 $FRAME is used only to get the default face information.
2366 If the glyph image of a character covers coordinate ($X, $Y),
2367 mdraw_coordinates_position () returns the character position of
2369 If $Y is less than the minimum Y-coordinate of the drawn area, it
2370 returns $FROM.\n\n\n
2371 If $Y is greater than the maximum Y-coordinate of the drawn area,
2372 it returns $TO.\n\n\n
2373 If $Y fits in with the drawn area but $X is less than the minimum
2374 X-coordinate, it returns the character position of the first
2375 character drawn on the line $Y.\n\n\n
2376 If $Y fits in with the drawn area but $X is greater than the
2377 maximum X-coordinate, it returns the character position of the
2378 last character drawn on the line $Y. */
2381 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2383 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2384 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2385 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2386 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2387 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2388 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2390 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2393 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2394 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2396 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2398 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2400 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2401 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2403 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2404 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2407 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2408 int x_offset, int y_offset, MDrawControl *control)
2410 MGlyphString *gstring;
2415 M_CHECK_POS_X (mt, from, -1);
2416 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2417 to = mtext_nchars (mt) + (control->cursor_width != 0);
2423 ASSURE_CONTROL (control);
2424 gstring = get_gstring (frame, mt, from, to, control);
2425 while (y + gstring->line_descent <= y_offset
2426 && gstring->to < to)
2429 y += gstring->line_descent;
2430 M17N_OBJECT_UNREF (gstring->top);
2431 gstring = get_gstring (frame, mt, from, to, control);
2432 y += gstring->line_ascent;
2435 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2436 if (! control->orientation_reversed)
2438 width = gstring->indent;
2439 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2440 if (g->pos >= from && g->pos < to)
2443 if (width > x_offset)
2449 width = - gstring->indent;
2450 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2451 if (g->pos >= from && g->pos < to)
2454 if (width < x_offset)
2459 M17N_OBJECT_UNREF (gstring->top);
2467 @brief Compute information about a glyph.
2469 The mdraw_glyph_info () function computes information about a
2470 glyph that covers a character at position $POS of the M-text $MT
2471 assuming that the text is drawn from the character at $FROM of $MT
2472 on a window of frame $FRAME using the mdraw_text_with_control ()
2473 function with the drawing control object $CONTROL.
2475 The information is stored in the members of $INFO. */
2477 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2479 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2480 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2481 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2482 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2484 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2492 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2493 MDrawControl *control, MDrawGlyphInfo *info)
2495 MGlyphString *gstring;
2499 M_CHECK_RANGE_X (mt, from, pos, -1);
2501 ASSURE_CONTROL (control);
2502 gstring = get_gstring (frame, mt, from, pos + 1, control);
2504 MERROR (MERROR_DRAW, -1);
2505 while (gstring->to <= pos)
2507 y += gstring->line_descent;
2508 M17N_OBJECT_UNREF (gstring->top);
2509 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2510 y += gstring->line_ascent;
2512 info->line_from = gstring->from;
2513 if (info->line_from < from)
2514 info->line_from = from;
2515 info->line_to = gstring->to;
2518 if (! control->orientation_reversed)
2520 info->x = gstring->indent;
2521 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2522 info->x += g->width;
2526 info->x = - gstring->indent;
2527 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2528 info->x -= g->width;
2529 while (g[-1].to == g->to)
2532 info->from = g->pos;
2534 info->glyph_code = g->code;
2535 info->this.x = g->lbearing;
2536 info->this.y = - gstring->line_ascent;
2537 info->this.height = gstring->height;
2538 info->this.width = - g->lbearing + g->width;
2539 if (g->rface->rfont)
2540 info->font = &g->rface->rfont->font;
2543 /* info->logical_width is calculated later. */
2545 if (info->from > info->line_from)
2547 /* The logically previous glyph is on this line. */
2548 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2550 info->prev_from = g_tmp->pos;
2552 else if (info->line_from > 0)
2554 /* The logically previous glyph is on the previous line. */
2555 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2556 gstring->from, control);
2557 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2559 info->prev_from = g_tmp->pos;
2560 M17N_OBJECT_UNREF (gst->top);
2563 info->prev_from = -1;
2565 if (GLYPH_INDEX (g) > 1)
2566 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2567 else if (! control->orientation_reversed)
2569 if (info->line_from > 0)
2573 int p = gstring->from - 1;
2575 gst = get_gstring (frame, mt, p, gstring->from, control);
2576 g_tmp = gst->glyphs + (gst->used - 2);
2577 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2578 M17N_OBJECT_UNREF (gst->top);
2581 info->left_from = info->left_to = -1;
2585 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2589 int p = gstring->to;
2591 gst = get_gstring (frame, mt, p, p + 1, control);
2592 g_tmp = gst->glyphs + (gst->used - 2);
2593 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2594 M17N_OBJECT_UNREF (gst->top);
2597 info->left_from = info->left_to = -1;
2600 if (info->to < gstring->to)
2602 /* The logically next glyph is on this line. */
2603 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2605 info->next_to = g_tmp->to;
2607 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2609 /* The logically next glyph is on the next line. */
2611 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2612 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2614 info->next_to = g_tmp->to;
2615 M17N_OBJECT_UNREF (gst->top);
2620 for (info->logical_width = (g++)->width;
2621 g->pos == pos && g->type != GLYPH_ANCHOR;
2622 info->this.width += g->width, info->logical_width += (g++)->width);
2623 info->this.width += g[-1].rbearing - g[-1].width;
2625 if (g->type != GLYPH_ANCHOR)
2626 info->right_from = g->pos, info->right_to = g->to;
2627 else if (! control->orientation_reversed)
2629 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2632 M17N_OBJECT_UNREF (gstring->top);
2633 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2635 info->right_from = g->pos, info->right_to = g->to;
2638 info->right_from = info->right_to = -1;
2642 if (info->line_from > 0)
2644 pos = gstring->from - 1;
2645 M17N_OBJECT_UNREF (gstring->top);
2646 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2648 info->right_from = g->pos, info->right_to = g->to;
2651 info->right_from = info->right_to = -1;
2654 M17N_OBJECT_UNREF (gstring->top);
2661 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2662 MDrawControl *control, MDrawGlyphInfo *info,
2663 int array_size, int *num_glyphs_return)
2665 MGlyphString *gstring;
2670 ASSURE_CONTROL (control);
2671 *num_glyphs_return = 0;
2672 M_CHECK_RANGE (mt, from, to, -1, 0);
2673 gstring = get_gstring (frame, mt, from, to, control);
2676 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2678 if (g->type == GLYPH_BOX
2679 || g->pos < from || g->pos >= to)
2681 if (g->type == GLYPH_PAD)
2683 if (g->left_padding)
2684 pad_width = g->width;
2688 info[-1].x += g->width;
2689 info[-1].logical_width += g->width;
2695 info->from = g->pos;
2697 info->glyph_code = g->code;
2698 info->x = g->xoff + pad_width;
2700 info->this.x = g->lbearing;
2701 info->this.y = - g->ascent;
2702 info->this.height = g->ascent + g->descent;
2703 info->this.width = g->rbearing - g->lbearing;
2704 info->logical_width = g->width + pad_width;
2705 if (g->rface->rfont)
2706 info->font = &g->rface->rfont->font;
2714 M17N_OBJECT_UNREF (gstring->top);
2716 *num_glyphs_return = n;
2717 return (n <= array_size ? 0 : -1);
2723 @brief Draw one or more textitems.
2725 The mdraw_text_items () function draws one or more M-texts on
2726 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2727 of the textitems to be drawn and $NITEMS is the number of
2728 textimtems in the array. */
2731 @brief textitem ¤òɽ¼¨¤¹¤ë.
2733 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2734 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2735 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2738 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2742 MTextItem, mdraw_text (). */
2745 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2746 MDrawTextItem *items, int nitems)
2748 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2750 while (nitems-- > 0)
2753 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2755 mdraw_text_with_control (frame, win, x, y,
2756 items->mt, 0, mtext_nchars (items->mt),
2758 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2759 items->control, NULL, NULL, NULL);
2762 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2768 @brief calculate a line breaking position.
2770 The function mdraw_default_line_break () calculates a line
2771 breaking position based on the line number $LINE and the
2772 coordinate $Y, when a line is too long to fit within the width
2773 limit. $POS is the position of the character next to the last
2774 one that fits within the limit. $FROM is the position of the
2775 first character of the line, and TO is the position of the last
2776 character displayed on the line if there were not width limit.
2777 LINE and Y are reset to 0 when a line is broken by a newline
2778 character, and incremented each time when a long line is broken
2779 because of the width limit.
2782 This function returns a character position to break the
2787 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2789 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2790 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2791 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2792 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2793 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2794 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2795 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2798 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2802 mdraw_default_line_break (MText *mt, int pos,
2803 int from, int to, int line, int y)
2805 int c = mtext_ref_char (mt, pos);
2808 if (c == ' ' || c == '\t')
2812 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2819 if (c == ' ' || c == '\t')
2822 c = mtext_ref_char (mt, pos);
2835 @brief Obtain per character dimension information.
2837 The mdraw_per_char_extents () function computes the text dimension
2838 of each character in M-text $MT. The faces given as text
2839 properties in $MT and the default face of frame $FRAME determine
2840 the fonts to draw the text. Each successive element in
2841 $ARRAY_RETURN is set to the drawn metrics of successive
2842 characters, which is relative to the origin of the drawing, and a
2843 rectangle for each character in $MT. The number of elements of
2844 $ARRAY_RETURN must be equal to or greater than the number of
2847 If pointer $OVERALL_RETURN is not @c NULL, this function also
2848 computes the extents of the overall text and stores the results in
2849 the members of the structure pointed to by $OVERALL_RETURN. */
2852 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2854 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2855 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2856 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2857 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2858 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2859 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2862 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2863 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2866 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2869 mdraw_per_char_extents (MFrame *frame, MText *mt,
2870 MDrawMetric *array_return,
2871 MDrawMetric *overall_return)
2873 int n = mtext_nchars (mt);
2875 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2876 n, &n, overall_return, NULL);
2880 @brief clear cached information.
2882 The mdraw_clear_cache () function clear cached information
2883 on M-text $MT that was attached by any of the drawing functions.
2884 When the behaviour of `format' or `line_break'
2885 member functions of MDrawControl is changed, the cache must be cleared.
2890 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2892 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2893 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2894 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2895 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2900 mdraw_clear_cache (MText *mt)
2902 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);