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) * len);
137 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
139 visual = alloca (sizeof (FriBidiChar) * (len + 1));
140 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
141 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
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);
520 if (base->combining_code && (base->bidi_level % 2))
522 MGlyph *g1 = base, *g2, temp;
524 while (g->combining_code)
526 for (g2 = g; g1 < g2; g1++, g2--)
527 temp = *g1, *g1 = *g2, *g2 = temp;
535 MRealizedFont *rfont = base->rface->rfont;
536 int size = rfont->font.property[MFONT_SIZE];
537 int width, lbearing, rbearing;
539 if (g == last_g || ! g->combining_code || g->otf_encoded)
542 if (base->width == 0 && ! base->left_padding && ! base->right_padding
543 && GLYPH_INDEX (base) > from)
545 MGlyph *prev = base - 1;
547 if (base->pos < prev->pos)
548 prev->pos = base->pos;
550 base->pos = prev->pos;
551 if (base->to > prev->to)
557 if (base->left_padding && base->lbearing < 0)
559 base->xoff = - base->lbearing;
560 base->width += base->xoff;
561 base->rbearing += base->xoff;
564 if (base->right_padding && base->rbearing > base->width)
566 base->width = base->rbearing;
568 lbearing = (base->xoff + base->lbearing < 0
569 ? base->xoff + base->lbearing : 0);
570 rbearing = base->xoff + base->rbearing;
574 /* With combining glyphs. */
575 int left = -base->width;
577 int top = - base->ascent;
578 int bottom = base->descent;
579 int height = bottom - top;
580 int begin = base->pos;
585 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
586 rbearing = base->rbearing;
588 while (g != last_g && g->combining_code)
590 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
592 combining_code = g->combining_code;
593 if (COMBINING_BY_CLASS_P (combining_code))
594 g->combining_code = combining_code
595 = combining_code_from_class (COMBINING_CODE_CLASS
598 rfont = g->rface->rfont;
599 size = rfont->font.property[MFONT_SIZE];
600 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
602 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
604 base_x = COMBINING_CODE_BASE_X (combining_code);
605 base_y = COMBINING_CODE_BASE_Y (combining_code);
606 add_x = COMBINING_CODE_ADD_X (combining_code);
607 add_y = COMBINING_CODE_ADD_Y (combining_code);
611 else if (end < g->to)
614 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
617 if (g->xoff + g->width > right)
618 right = g->xoff + g->width;
619 width = right - left;
620 if (g->xoff + g->lbearing < left + lbearing)
621 lbearing = g->xoff + g->lbearing - left;
622 if (g->xoff + g->rbearing > left + rbearing)
623 rbearing = g->xoff + g->rbearing - left;
626 g->yoff = top + height * base_y / 2;
630 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
632 if (g->yoff - g->ascent < top)
633 top = g->yoff - g->ascent;
634 if (g->yoff + g->descent > bottom)
635 bottom = g->yoff + g->descent;
636 height = bottom - top;
642 base->ascent = - top;
643 base->descent = bottom;
644 base->lbearing = lbearing;
645 base->rbearing = rbearing;
646 if (left < - base->width)
648 base->xoff = - base->width - left;
649 base->width += base->xoff;
650 base->rbearing += base->xoff;
651 base->lbearing += base->xoff;
655 base->width += right;
656 base->rbearing += right;
657 base->right_padding = 1;
658 for (i = 1; base + i != g; i++)
659 base[i].xoff -= right;
662 for (i = 0; base + i != g; i++)
669 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
670 g_physical_descent = MAX (g_physical_descent, base->descent);
671 g_lbearing = MIN (g_lbearing, g_width + lbearing);
672 g_rbearing = MAX (g_rbearing, g_width + rbearing);
673 g_width += base->width;
676 gstring->physical_ascent = g_physical_ascent;
677 gstring->physical_descent = g_physical_descent;
678 gstring->sub_width = g_width;
679 gstring->sub_lbearing = g_lbearing;
680 gstring->sub_rbearing = g_rbearing;
684 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
685 by this function directly. Character glyphs are handled by
686 layouter functions registered in font drivers.
688 This function fill-in all the remaining members of glyphs. */
691 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
693 /* Default width of TAB. */
694 int tab_width = frame->space_width * (gstring->control.tab_width
695 ? gstring->control.tab_width : 8);
699 MDrawControl *control = &(gstring->control);
702 int box_line_height = 0;
703 int ignore_formatting_char = control->ignore_formatting_char;
705 gstring->ascent = gstring->descent = 0;
706 gstring->physical_ascent = gstring->physical_descent = 0;
707 gstring->width = gstring->lbearing = gstring->rbearing = 0;
711 while (g->type != GLYPH_ANCHOR)
713 if (box != g->rface->box)
715 int gidx = GLYPH_INDEX (g);
719 /* Insert the right side of the box. That glyph belongs
720 to the previous grapheme cluster. */
721 MGlyph box_glyph = g[-1];
723 box_glyph.type = GLYPH_BOX;
725 = (control->fixed_width
727 : box->inner_hmargin + box->width + box->outer_hmargin);
728 box_glyph.lbearing = 0;
729 box_glyph.rbearing = box_glyph.width;
731 box_glyph.right_padding = 1;
732 gstring->width += box_glyph.width;
733 gstring->rbearing += box_glyph.width;
734 INSERT_GLYPH (gstring, gidx, box_glyph);
741 /* Insert the left side of the box. That glyph belongs
742 to the following grapheme cluster. */
743 MGlyph box_glyph = *g;
744 int box_height = (box->width
745 + box->inner_vmargin + box->outer_vmargin);
747 if (box_line_height < box_height)
748 box_line_height = box_height;
749 box_glyph.type = GLYPH_BOX;
751 = (control->fixed_width
753 : box->inner_hmargin + box->width + box->outer_hmargin);
754 box_glyph.lbearing = 0;
755 box_glyph.rbearing = box_glyph.width;
757 box_glyph.left_padding = 1;
758 gstring->width += box_glyph.width;
759 gstring->rbearing += box_glyph.width;
760 INSERT_GLYPH (gstring, gidx, box_glyph);
766 if (g->category == McatCf && ignore_formatting_char)
767 g->type = GLYPH_SPACE;
769 if (g->type == GLYPH_CHAR)
771 MRealizedFace *rface = g->rface;
772 MRealizedFont *rfont = rface->rfont;
774 int from = GLYPH_INDEX (g);
776 for (g++; g->type == GLYPH_CHAR; g++)
777 if (! rfont != ! g->rface->rfont
778 || box != g->rface->box
779 || ((fromg->code == MCHAR_INVALID_CODE)
780 != (g->code == MCHAR_INVALID_CODE))
781 || (g->category == McatCf && ignore_formatting_char))
783 if (rfont && fromg->code != MCHAR_INVALID_CODE)
786 int to = GLYPH_INDEX (g);
788 layout_glyphs (frame, gstring, from, to);
789 extra_width = - gstring->sub_lbearing;
791 && (GLYPH_INDEX (g) > 1
792 || (! control->orientation_reversed && control->align_head)))
796 pad.type = GLYPH_PAD;
799 pad.width = pad.rbearing = extra_width;
800 pad.left_padding = 1;
801 INSERT_GLYPH (gstring, from, pad);
803 gstring->sub_lbearing = 0;
804 gstring->sub_width += extra_width;
805 gstring->sub_rbearing += extra_width;
807 g = MGLYPH (from - 1);
808 if (g->type == GLYPH_SPACE)
810 /* The pad just inserted is absorbed (maybe
811 partially) by the previous space while
812 keeping at least some space width. For the
813 moment, we use the arbitrary width 2-pixel.
814 Perhaps, it should be decided by the current
815 face, or a default value of the current
816 frame, which is, however, not yet
818 if (extra_width + 2 < g->width)
820 g->width -= extra_width;
824 extra_width = g->width - 2;
827 gstring->width -= extra_width;
828 gstring->rbearing -= extra_width;
833 extra_width = gstring->sub_rbearing - gstring->sub_width;
835 && (GLYPH_INDEX (g) < gstring->used - 1
836 || (control->orientation_reversed && control->align_head)))
838 if (g->type == GLYPH_SPACE && box == g->rface->box)
841 pad.type = GLYPH_PAD;
844 pad.width = pad.rbearing = extra_width;
845 INSERT_GLYPH (gstring, to, pad);
848 g[-1].width += extra_width;
849 gstring->sub_width += extra_width;
852 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
853 gstring->lbearing = gstring->width + gstring->sub_lbearing;
854 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
855 gstring->rbearing = gstring->width + gstring->sub_rbearing;
856 gstring->width += gstring->sub_width;
857 if (gstring->ascent < rface->ascent)
858 gstring->ascent = rface->ascent;
859 if (gstring->descent < rface->descent)
860 gstring->descent = rface->descent;
864 for (; fromg < g; fromg++)
866 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
867 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
868 fromg->width = fromg->rbearing = 1;
870 fromg->width = fromg->rbearing = rface->space_width;
871 fromg->xoff = fromg->lbearing = 0;
872 fromg->ascent = fromg->descent = 0;
873 gstring->width += fromg->width;
874 gstring->rbearing += fromg->width;
876 if (gstring->ascent < frame->rface->ascent)
877 gstring->ascent = frame->rface->ascent;
878 if (gstring->descent < frame->descent)
879 gstring->descent = frame->rface->descent;
882 else if (g->type == GLYPH_SPACE)
885 g->width = g->rface->space_width;
886 else if (g->c == '\n')
888 g->width = control->cursor_width;
891 if (control->cursor_bidi)
893 else if (g->width < 0)
894 g->width = g->rface->space_width;
897 else if (g->c == '\t')
899 g->width = tab_width - ((gstring->indent + gstring->width)
905 if (g[-1].type == GLYPH_PAD)
907 /* This space glyph absorbs (maybe partially) the
908 previous padding glyph. */
909 g->width -= g[-1].width;
911 /* But, keep at least some space width. For the
912 moment, we use the arbitrary width 2-pixel. */
915 g->rbearing = g->width;
916 gstring->width += g->width;
917 gstring->rbearing += g->width;
920 if (gstring->ascent < g->rface->ascent)
921 gstring->ascent = g->rface->ascent;
922 if (gstring->descent < g->rface->descent)
923 gstring->descent = g->rface->descent;
929 gstring->width += g->width;
930 gstring->rbearing += g->width;
937 /* Insert the right side of the box. */
938 int gidx = GLYPH_INDEX (g);
939 MGlyph box_glyph = g[-1];
941 box_glyph.type = GLYPH_BOX;
943 = (control->fixed_width
945 : box->inner_hmargin + box->width + box->outer_hmargin);
946 box_glyph.lbearing = 0;
947 box_glyph.rbearing = box_glyph.width;
949 box_glyph.right_padding = 1;
950 gstring->width += box_glyph.width;
951 gstring->rbearing += box_glyph.width;
952 INSERT_GLYPH (gstring, gidx, box_glyph);
955 gstring->text_ascent = gstring->ascent;
956 gstring->text_descent = gstring->descent;
957 if (gstring->text_ascent < gstring->physical_ascent)
958 gstring->text_ascent = gstring->physical_ascent;
959 if (gstring->text_descent < gstring->physical_descent)
960 gstring->text_descent = gstring->physical_descent;
961 gstring->line_ascent = gstring->text_ascent;
962 gstring->line_descent = gstring->text_descent;
963 if (box_line_height > 0)
965 gstring->line_ascent += box_line_height;
966 gstring->physical_ascent = gstring->line_ascent;
967 gstring->line_descent += box_line_height;
968 gstring->physical_descent = gstring->line_descent;
971 if (gstring->line_ascent < control->min_line_ascent)
972 gstring->line_ascent = control->min_line_ascent;
973 else if (control->max_line_ascent
974 && control->max_line_ascent > control->min_line_ascent
975 && gstring->line_ascent > control->max_line_ascent)
976 gstring->line_ascent = control->max_line_ascent;
978 if (gstring->line_descent < control->min_line_descent)
979 gstring->line_descent = control->min_line_descent;
980 else if (control->max_line_descent
981 && control->max_line_descent > control->min_line_descent
982 && gstring->line_descent > control->max_line_descent)
983 gstring->line_descent = control->max_line_descent;
984 gstring->height = gstring->line_ascent + gstring->line_descent;
986 if (control->orientation_reversed
989 /* We must adjust TAB width for RTL orientation. */
990 width = gstring->indent;
992 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
994 if (g->type == GLYPH_CHAR && g->c == '\t')
996 int this_width = tab_width - (width % tab_width);
998 if (g[1].type == GLYPH_PAD)
999 this_width -= g[1].width;
1000 if (g[-1].type == GLYPH_PAD)
1001 this_width -= g[-1].width;
1004 gstring->width += this_width - g->width;
1005 gstring->rbearing += this_width - g->width;
1006 g->width = this_width;
1007 width += this_width;
1017 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1018 MGlyphString *gstring, int from, int to,
1019 int *from_idx, int *to_idx, int *to_x)
1021 MGlyph *g = MGLYPH (1);
1022 MDrawRegion region = (MDrawRegion) NULL;
1023 MDrawControl *control = &gstring->control;
1024 int cursor_pos = -1;
1026 int cursor_bidi = control->cursor_bidi;
1028 if (control->with_cursor && control->cursor_width)
1030 if (gstring->from <= control->cursor_pos
1031 && gstring->to > control->cursor_pos)
1032 cursor_pos = control->cursor_pos;
1035 && gstring->from <= control->cursor_pos - 1
1036 && gstring->to > control->cursor_pos - 1)
1037 prev_pos = control->cursor_pos - 1;
1040 *from_idx = *to_idx = 0;
1041 while (g->type != GLYPH_ANCHOR)
1043 if (g->pos >= from && g->pos < to)
1045 MGlyph *fromg = g, *cursor = NULL;
1046 MRealizedFace *rface = g->rface;
1048 int cursor_width = 0;
1052 *from_idx = GLYPH_INDEX (g);
1053 while (g->pos >= from && g->pos < to
1054 && g->rface == rface)
1057 if (g->type != GLYPH_BOX
1058 && g->pos <= cursor_pos && g->to > cursor_pos)
1061 cursor = g, cursor_x = x + width;
1062 cursor_width += g->width;
1064 width += g++->width;
1067 && (control->as_image
1068 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1070 int this_x = x, this_width = width;
1072 if (fromg->type == GLYPH_BOX)
1073 this_x += fromg->width, this_width -= fromg->width;
1074 if (g[-1].type == GLYPH_BOX)
1075 this_width -= g[-1].width;
1076 (frame->driver->fill_space)
1077 (frame, win, rface, 0,
1078 this_x, y - gstring->text_ascent, this_width,
1079 gstring->text_ascent + gstring->text_descent,
1080 control->clip_region);
1087 rect.y = y - gstring->text_ascent;
1088 rect.height = gstring->text_ascent + gstring->text_descent;
1091 rect.width = ((control->cursor_width > 0
1092 && control->cursor_width < cursor_width)
1093 ? control->cursor_width : cursor_width);
1097 if (cursor->bidi_level % 2)
1098 rect.x += cursor_width - rect.width;
1099 (*frame->driver->fill_space)
1100 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1101 control->clip_region);
1103 region = (*frame->driver->region_from_rect) (&rect);
1105 (*frame->driver->region_add_rect) (region, &rect);
1108 if (cursor->bidi_level % 2)
1111 rect.width = cursor_width < 4 ? cursor_width : 4;
1112 (*frame->driver->fill_space)
1113 (frame, win, rface, 1,
1114 rect.x, rect.y, rect.width, rect.height,
1115 control->clip_region);
1116 (*frame->driver->region_add_rect) (region, &rect);
1128 if (fromg->type != GLYPH_BOX
1129 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1132 cursor = fromg, cursor_x = x + temp_width;
1133 cursor_width += fromg->width;
1135 temp_width += fromg++->width;
1142 if (! (cursor->bidi_level % 2))
1143 rect.x += cursor_width - 1;
1144 rect.y = y - gstring->text_ascent;
1145 rect.height = gstring->text_ascent + gstring->text_descent;
1147 (*frame->driver->fill_space)
1148 (frame, win, rface, 1,
1149 rect.x, rect.y, rect.width, rect.height,
1150 control->clip_region);
1152 region = (*frame->driver->region_from_rect) (&rect);
1154 (*frame->driver->region_add_rect) (region, &rect);
1155 rect.y += rect.height - 2;
1157 rect.width = cursor_width < 4 ? cursor_width : 4;
1158 if (! (cursor->bidi_level % 2))
1159 rect.x -= rect.width - 1;
1160 (*frame->driver->fill_space) (frame, win, rface, 1,
1161 rect.x, rect.y, rect.width, rect.height,
1162 control->clip_region);
1163 (*frame->driver->region_add_rect) (region, &rect);
1167 *to_idx = GLYPH_INDEX (g);
1177 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1178 MGlyphString *gstring, int from_idx, int to_idx,
1179 int reverse, MDrawRegion region)
1181 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1187 (*frame->driver->region_to_rect) (region, &rect);
1190 while (g != gend && x + g->rbearing <= rect.x)
1193 width -= g++->width;
1194 while (! g->enabled && g != gend)
1198 rect.x += rect.width;
1199 if (rect.x < x + width)
1202 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1204 width -= (--gend)->width;
1205 while (! gend->enabled && g != gend)
1209 while (gend[-1].to == gend->to) gend++;
1217 MRealizedFace *rface = g->rface;
1218 int width = g->width;
1219 MGlyph *from_g = g++;
1221 /* Handle the glyphs of the same type/face at once. */
1223 && g->type == from_g->type
1224 && g->rface == rface
1225 && ((g->code == MCHAR_INVALID_CODE)
1226 == (from_g->code == MCHAR_INVALID_CODE))
1228 width += g++->width;
1230 if (from_g->type == GLYPH_CHAR)
1232 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1233 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1236 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1239 else if (from_g->type == GLYPH_BOX)
1241 /* Draw the left or right side of a box. If
1242 from_g->lbearing is nonzero, this is the left side,
1243 else this is the right side. */
1244 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1247 if (from_g->type != GLYPH_BOX)
1250 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1251 x, y, width, region);
1254 /* Draw the top and bottom side of a box. */
1255 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1256 x, y, width, region);
1267 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1268 int *from_x, int *to_x)
1271 int left_idx = *left, right_idx = *right;
1272 int left_x, right_x, x;
1274 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1277 if (x + g->rbearing > 0)
1279 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1281 left_idx = GLYPH_INDEX (g);
1286 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1289 if (x - g->width + g->lbearing < 0)
1291 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1293 right_idx = GLYPH_INDEX (g) + 1;
1298 if (*left == left_idx && *right == right_idx)
1301 if (*left != left_idx)
1303 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1308 if (*right != right_idx)
1310 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1320 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1325 if (from <= gstring->from && to >= gstring->to)
1328 *rbearing = gstring->rbearing;
1329 return gstring->width;
1334 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1335 if (g->pos >= from && g->pos < to)
1337 if (rbearing && width + g->rbearing > *rbearing)
1338 *rbearing = width + g->rbearing;
1346 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1347 MGlyphString *gstring, int from, int to)
1349 MDrawControl *control = &gstring->control;
1351 MDrawRegion clip_region, cursor_region;
1352 int from_idx, to_idx;
1355 if (control->orientation_reversed)
1356 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1358 x += gstring->indent;
1360 /* At first, draw all glyphs without cursor. */
1361 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1362 &from_idx, &to_idx, &to_x);
1364 if (control->partial_update)
1367 rect.width = to_x - x;
1368 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1370 rect.y = y - gstring->line_ascent;
1371 rect.height = gstring->height;
1372 clip_region = (*frame->driver->region_from_rect) (&rect);
1373 if (control->clip_region)
1374 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1377 clip_region = control->clip_region;
1380 clip_region = control->clip_region;
1382 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1387 (*frame->driver->intersect_region) (cursor_region, clip_region);
1388 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1391 if (clip_region != control->clip_region)
1392 (*frame->driver->free_region) (clip_region);
1394 (*frame->driver->free_region) (cursor_region);
1398 static int gstring_num;
1401 free_gstring (void *object)
1403 MGlyphString *gstring = (MGlyphString *) object;
1406 free_gstring (gstring->next);
1407 if (gstring->size > 0)
1408 free (gstring->glyphs);
1414 static MGlyphString scratch_gstring;
1416 static MGlyphString *
1417 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1420 MGlyphString *gstring;
1422 if (pos == mt->nchars)
1424 gstring = &scratch_gstring;
1428 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1429 MLIST_INIT1 (gstring, glyphs, 128);
1433 gstring->frame = frame;
1434 gstring->tick = frame->tick;
1435 gstring->top = gstring;
1437 gstring->control = *control;
1438 gstring->indent = gstring->width_limit = 0;
1439 if (control->format)
1440 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1442 gstring->width_limit = control->max_line_width;
1443 gstring->anti_alias = control->anti_alias;
1447 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1450 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1458 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1459 a width of glyphs for the character at I of GSTRING->mt. If I is
1460 not a beginning of a grapheme cluster, the corresponding element
1462 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1463 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1464 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1465 pos_width[g->pos - gstring->from] += g->width;
1466 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1468 if (pos_width[i] > 0)
1470 if (width + pos_width[i] > gstring->width_limit)
1473 width += pos_width[i];
1476 pos = gstring->from + i;
1477 if (gstring->control.line_break)
1479 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1480 gstring->from, gstring->to, 0, 0);
1481 if (pos <= gstring->from || pos >= gstring->to)
1484 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1485 layout_glyph_string (frame, gstring);
1489 /* Return a gstring that covers a character at POS. */
1491 static MGlyphString *
1492 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1494 MGlyphString *gstring = NULL;
1496 if (pos < mtext_nchars (mt))
1498 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1501 && ((prop->start != 0
1502 && mtext_ref_char (mt, prop->start - 1) != '\n')
1503 || (prop->end < mtext_nchars (mt)
1504 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1506 mtext_detach_property (prop);
1511 gstring = prop->val;
1512 if (gstring->frame != frame
1513 || gstring->tick != frame->tick
1514 || memcmp (control, &gstring->control,
1515 (char *) (&control->with_cursor)
1516 - (char *) (control))
1517 || control->cursor_width != gstring->control.cursor_width
1518 || control->cursor_bidi != gstring->control.cursor_bidi)
1520 mtext_detach_property (prop);
1525 else if (! control->cursor_width)
1533 offset = mtext_character (mt, pos, 0, '\n');
1538 offset -= gstring->from;
1540 for (gst = gstring; gst; gst = gst->next)
1544 gst->from += offset;
1546 for (i = 0; i < gst->used; i++)
1548 gst->glyphs[i].pos += offset;
1549 gst->glyphs[i].to += offset;
1552 M17N_OBJECT_REF (gstring);
1557 int line = 0, y = 0;
1559 if (control->two_dimensional)
1561 beg = mtext_character (mt, pos, 0, '\n');
1566 end = mtext_nchars (mt) + (control->cursor_width != 0);
1573 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1574 compose_glyph_string (frame, mt, beg, end, gstring);
1575 layout_glyph_string (frame, gstring);
1577 if (control->two_dimensional
1578 && gstring->width_limit
1579 && gstring->width > gstring->width_limit)
1581 MGlyphString *gst = gstring;
1583 truncate_gstring (frame, mt, gst);
1584 while (gst->to < end)
1586 line++, y += gst->height;
1587 gst->next = alloc_gstring (frame, mt, gst->from, control,
1589 gst->next->top = gstring;
1590 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1592 layout_glyph_string (frame, gst);
1593 if (gst->width <= gst->width_limit)
1595 truncate_gstring (frame, mt, gst);
1599 if (! control->disable_caching && pos < mtext_nchars (mt))
1601 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1602 MTEXTPROP_VOLATILE_STRONG);
1604 if (end > mtext_nchars (mt))
1605 end = mtext_nchars (mt);
1606 mtext_attach_property (mt, beg, end, prop);
1607 M17N_OBJECT_UNREF (prop);
1611 while (gstring->to <= pos)
1613 if (! gstring->next)
1615 gstring = gstring->next;
1617 gstring->control = *control;
1623 static MDrawControl control_noop;
1625 #define ASSURE_CONTROL(control) \
1627 control = &control_noop; \
1632 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1633 MText *mt, int from, int to,
1634 MDrawControl *control)
1636 MGlyphString *gstring;
1638 M_CHECK_POS_X (mt, from, -1);
1639 ASSURE_CONTROL (control);
1640 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1641 to = mtext_nchars (mt) + (control->cursor_width != 0);
1645 gstring = get_gstring (frame, mt, from, to, control);
1647 MERROR (MERROR_DRAW, -1);
1648 render_glyph_string (frame, win, x, y, gstring, from, to);
1652 y += gstring->line_descent;
1653 M17N_OBJECT_UNREF (gstring->top);
1654 gstring = get_gstring (frame, mt, from, to, control);
1655 y += gstring->line_ascent;
1656 render_glyph_string (frame, win, x, y, gstring, from, to);
1659 M17N_OBJECT_UNREF (gstring->top);
1666 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1672 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1673 if (g->pos <= pos && g->to > pos)
1678 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1679 if (g->pos <= pos && g->to > pos)
1686 /* for debugging... */
1690 dump_combining_code (int code)
1692 char *vallign = "tcbB";
1693 char *hallign = "lcr";
1699 if (COMBINING_BY_CLASS_P (code))
1700 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1701 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1702 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1703 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1704 off_x = COMBINING_CODE_OFF_X (code) - 128;
1706 sprintf (work + 2, "+%d", off_y);
1708 sprintf (work + 2, "%d", off_y);
1709 else if (off_x == 0)
1710 sprintf (work + 2, ".");
1711 p = work + strlen (work);
1713 sprintf (p, ">%d", off_x);
1715 sprintf (p, "<%d", -off_x);
1717 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1718 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1724 dump_gstring (MGlyphString *gstring, int indent)
1726 char *prefix = (char *) alloca (indent + 1);
1727 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1729 memset (prefix, 32, indent);
1732 fprintf (stderr, "(glyph-string");
1734 for (g = MGLYPH (0); g < last_g; g++)
1736 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1738 g - gstring->glyphs,
1739 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1740 : g->type == GLYPH_ANCHOR ? "ANC"
1741 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1742 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1743 dump_combining_code (g->combining_code),
1744 g->width, g->bidi_level);
1745 fprintf (stderr, ")");
1749 /* m17n-X internal APIs */
1754 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1756 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1757 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1759 Mlatin = msymbol ("latin");
1760 Minherited = msymbol ("inherited");
1762 McatCc = msymbol ("Cc");
1763 McatCf = msymbol ("Cf");
1765 MbidiR = msymbol ("R");
1766 MbidiAL = msymbol ("AL");
1767 MbidiRLE = msymbol ("RLE");
1768 MbidiRLO = msymbol ("RLO");
1769 MbidiBN = msymbol ("BN");
1770 MbidiS = msymbol ("S");
1772 fribidi_set_mirroring (TRUE);
1781 MLIST_FREE1 (&scratch_gstring, glyphs);
1785 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1789 /*** @addtogroup m17nDraw */
1794 @brief Draw an M-text on a window.
1796 The mdraw_text () function draws the text between $FROM and $TO of
1797 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1799 The appearance of the text (size, style, color, etc) is specified
1800 by the value of the text property whose key is @c Mface. If the
1801 M-text or a part of the M-text does not have such a text property,
1802 the default face of $FRAME is used.
1804 The font used to draw a character in the M-text is selected from
1805 the value of the fontset property of a face by the following
1810 <li> Search the text properties given to the character for the one
1811 whose key is @c Mcharset; its value should be either a symbol
1812 specifying a charset or #Mnil. If the value is #Mnil,
1813 proceed to the next step.
1815 Otherwise, search the mapping table of the fontset for the
1816 charset. If no entry is found proceed to the next step.
1818 If an entry is found, use one of the fonts in the entry that
1819 has a glyph for the character and that matches best with the
1820 face properties. If no such font exists, proceed to the next
1823 <li> Get the character property "script" of the character. If it is
1824 inherited, get the script property from the previous
1825 characters. If there is no previous character, or none of
1826 them has the script property other than inherited, proceed to
1829 Search the text properties given to the character for the one
1830 whose key is @c Mlanguage; its value should be either a
1831 symbol specifying a language or @c Mnil.
1833 Search the mapping table of the fontset for the combination
1834 of the script and language. If no entry is found, proceed to
1837 If an entry is found, use one of the fonts in the entry that
1838 has a glyph for the character and that matches best with the
1839 face properties. If no such font exists, proceed to the next
1842 <li> Search the fall-back table of the fontset for a font that has
1843 a glyph of the character. If such a font is found, use that
1848 If no font is found by the algorithm above, this function draws an
1849 empty box for the character.
1851 This function draws only the glyph foreground. To specify the
1852 background color, use mdraw_image_text () or
1853 mdraw_text_with_control ().
1855 This function is the counterpart of <tt>XDrawString ()</tt>,
1856 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1857 in the X Window System.
1860 If the operation was successful, mdraw_text () returns 0. If an
1861 error is detected, it returns -1 and assigns an error code to the
1862 external variable #merror_code. */
1864 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1866 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1867 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1870 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1871 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1872 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1873 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1875 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1876 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1880 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1881 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1882 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1883 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1884 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1887 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1888 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1889 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1892 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1893 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1894 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1895 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1897 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1898 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1901 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1902 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1905 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1906 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1907 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1910 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1911 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1915 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1916 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1918 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1919 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1922 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1923 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1926 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1927 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1929 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1936 mdraw_image_text () */
1939 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1940 MText *mt, int from, int to)
1942 MDrawControl control;
1944 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1945 memset (&control, 0, sizeof control);
1946 control.as_image = 0;
1947 return draw_text (frame, win, x, y, mt, from, to, &control);
1954 @brief Draw an M-text on a window as an image.
1956 The mdraw_image_text () function draws the text between $FROM and
1957 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1958 coordinate ($X, $Y).
1960 The way to draw a text is the same as in mdraw_text () except that
1961 this function also draws the background with the color specified
1964 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1965 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1966 functions in the X Window System.
1969 If the operation was successful, mdraw_image_text () returns 0.
1970 If an error is detected, it returns -1 and assigns an error code
1971 to the external variable #merror_code. */
1974 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1976 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1977 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1980 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1981 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1983 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1984 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1988 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1989 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1992 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2002 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2003 MText *mt, int from, int to)
2005 MDrawControl control;
2007 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2008 memset (&control, 0, sizeof control);
2009 control.as_image = 1;
2010 return draw_text (frame, win, x, y, mt, from, to, &control);
2016 @brief Draw an M-text on a window with fine control.
2018 The mdraw_text_with_control () function draws the text between
2019 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2020 coordinate ($X, $Y).
2022 The way to draw a text is the same as in mdraw_text () except that
2023 this function also follows what specified in the drawing control
2026 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2027 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2028 breaks lines and the following characters are drawn in the next
2029 line. See the documentation of the structure @ MDrawControl for
2033 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2035 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2036 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2039 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2040 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2042 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2043 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2044 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2048 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2049 MText *mt, int from, int to, MDrawControl *control)
2051 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2052 return draw_text (frame, win, x, y, mt, from, to, control);
2058 @brief Compute text pixel width.
2060 The mdraw_text_extents () function computes the width of text
2061 between $FROM and $TO of M-text $MT when it is drawn on a window
2062 of frame $FRAME using the mdraw_text_with_control () function with
2063 the drawing control object $CONTROL.
2065 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2066 the bounding box of character ink of the M-text, and stores the
2067 results in the members of the structure pointed to by
2068 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2069 surrounding box, the box is included in the bounding box.
2071 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2072 computes the bounding box that provides mininum spacing to other
2073 graphical features (such as surrounding box) for the M-text, and
2074 stores the results in the members of the structure pointed to by
2075 $OVERALL_LOGICAL_RETURN.
2077 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2078 computes the bounding box that provides mininum spacing to the
2079 other M-text drawn, and stores the results in the members of the
2080 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2081 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2082 min_line_ascent, min_line_descent, max_line_ascent, and
2083 max_line_descent of $CONTROL are all zero.
2086 This function returns the width of the text to be drawn in the
2087 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2088 text is drawn in multiple physical lines, it returns the width of
2089 the widest line. If an error occurs, it returns -1 and assigns an
2090 error code to the external variable #merror_code. */
2094 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2096 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2097 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2098 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2100 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2101 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2102 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2103 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2105 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2106 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2107 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2108 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2110 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2111 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2112 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2113 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2114 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2115 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2117 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2118 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2119 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2120 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2122 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2129 mdraw_text_extents (MFrame *frame,
2130 MText *mt, int from, int to, MDrawControl *control,
2131 MDrawMetric *overall_ink_return,
2132 MDrawMetric *overall_logical_return,
2133 MDrawMetric *overall_line_return)
2135 MGlyphString *gstring;
2137 int width, rbearing;
2139 ASSURE_CONTROL (control);
2140 M_CHECK_POS_X (mt, from, -1);
2141 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2142 to = mtext_nchars (mt) + (control->cursor_width != 0);
2146 gstring = get_gstring (frame, mt, from, to, control);
2148 MERROR (MERROR_DRAW, -1);
2149 width = gstring_width (gstring, from, to, &rbearing);
2150 if (overall_ink_return)
2152 overall_ink_return->y = - gstring->physical_ascent;
2153 overall_ink_return->x = gstring->lbearing;
2155 if (overall_logical_return)
2157 overall_logical_return->y = - gstring->ascent;
2158 overall_logical_return->x = 0;
2160 if (overall_line_return)
2162 overall_line_return->y = - gstring->line_ascent;
2163 overall_line_return->x = gstring->lbearing;
2166 for (from = gstring->to; from < to; from = gstring->to)
2168 int this_width, this_rbearing;
2170 y += gstring->line_descent;
2171 M17N_OBJECT_UNREF (gstring->top);
2172 gstring = get_gstring (frame, mt, from, to, control);
2173 this_width = gstring_width (gstring, from, to, &this_rbearing);
2174 y += gstring->line_ascent;
2175 if (width < this_width)
2177 if (rbearing < this_rbearing)
2178 rbearing = this_rbearing;
2180 if (overall_ink_return)
2182 overall_ink_return->width = rbearing;
2183 overall_ink_return->height
2184 = y + gstring->physical_descent - overall_ink_return->y;
2186 if (overall_logical_return)
2188 overall_logical_return->width = width;
2189 overall_logical_return->height
2190 = y + gstring->descent - overall_logical_return->y;
2192 if (overall_line_return)
2194 overall_line_return->width = MAX (width, rbearing);
2195 overall_line_return->height
2196 = y + gstring->line_descent - overall_line_return->y;
2199 M17N_OBJECT_UNREF (gstring->top);
2206 @brief Compute the text dimensions of each character of M-text.
2208 The mdraw_text_per_char_extents () function computes the drawn
2209 metric of each character between $FROM and $TO of M-text $MT
2210 assuming that they are drawn on a window of frame $FRAME using the
2211 mdraw_text_with_control () function with the drawing control
2214 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2215 $LOGICAL_ARRAY_RETURN. Each successive element of
2216 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2217 ink and logical metrics of successive characters respectively,
2218 relative to the drawing origin of the M-text. The number of
2219 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2220 been set is returned to $NUM_CHARS_RETURN.
2222 If $ARRAY_SIZE is too small to return all metrics, the function
2223 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2224 Otherwise, it returns zero.
2226 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2227 @c NULL, this function also computes the metrics of the overall
2228 text and stores the results in the members of the structure
2229 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2231 If $CONTROL->two_dimensional is nonzero, this function computes
2232 only the metrics of characters in the first line. */
2234 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2236 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2237 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2238 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2239 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2241 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2242 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2243 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2244 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2245 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2247 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2248 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2251 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2252 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2253 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2256 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2257 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2260 mdraw_text_per_char_extents (MFrame *frame,
2261 MText *mt, int from, int to,
2262 MDrawControl *control,
2263 MDrawMetric *ink_array_return,
2264 MDrawMetric *logical_array_return,
2266 int *num_chars_return,
2267 MDrawMetric *overall_ink_return,
2268 MDrawMetric *overall_logical_return)
2270 MGlyphString *gstring;
2274 ASSURE_CONTROL (control);
2275 *num_chars_return = to - from;
2276 if (array_size < *num_chars_return)
2277 MERROR (MERROR_DRAW, -1);
2278 if (overall_logical_return)
2279 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2280 if (overall_ink_return)
2281 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2283 M_CHECK_RANGE (mt, from, to, -1, 0);
2284 gstring = get_gstring (frame, mt, from, to, control);
2287 *num_chars_return = 0;
2291 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2292 if (g->pos >= from && g->pos < to)
2296 int width = g->width;
2297 int lbearing = g->lbearing;
2298 int rbearing = g->rbearing;
2299 int ascent = g->ascent;
2300 int descent = g->descent;
2301 int logical_ascent = g->rface->rfont->ascent;
2302 int logical_descent = g->rface->rfont->descent;
2304 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2306 if (lbearing < width + g->lbearing)
2307 lbearing = width + g->lbearing;
2308 if (rbearing < width + g->rbearing)
2309 rbearing = width + g->rbearing;
2311 if (ascent < g->ascent)
2313 if (descent < g->descent)
2314 descent = g->descent;
2321 ink_array_return[start - from].x = x + lbearing;
2322 ink_array_return[start - from].y = - ascent;
2323 ink_array_return[start - from].width = rbearing - lbearing;
2324 ink_array_return[start - from].height = ascent + descent;
2325 logical_array_return[start - from].x = x;
2326 logical_array_return[start - from].y = - logical_descent;
2327 logical_array_return[start - from].height
2328 = logical_ascent + logical_descent;
2329 logical_array_return[start - from].width = width;
2335 if (overall_ink_return)
2337 overall_ink_return->y = - gstring->line_ascent;
2338 overall_ink_return->x = gstring->lbearing;
2339 overall_ink_return->width = x - gstring->lbearing;
2340 overall_ink_return->height = gstring->height;
2342 if (overall_logical_return)
2344 overall_logical_return->y = - gstring->ascent;
2345 overall_logical_return->x = 0;
2346 overall_logical_return->width = x;
2347 overall_logical_return->height = gstring->ascent + gstring->descent;
2350 M17N_OBJECT_UNREF (gstring->top);
2357 @brief Return the character position nearest to the coordinates.
2359 The mdraw_coordinates_position () function checks which character
2360 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2361 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2362 mdraw_text_with_control () function with the drawing control
2363 object $CONTROL. Here, the character position means the number of
2364 characters that precede the character in question in $MT, that is,
2365 the character position of the first character is 0.
2367 $FRAME is used only to get the default face information.
2370 If the glyph image of a character covers coordinate ($X, $Y),
2371 mdraw_coordinates_position () returns the character position of
2373 If $Y is less than the minimum Y-coordinate of the drawn area, it
2374 returns $FROM.\n\n\n
2375 If $Y is greater than the maximum Y-coordinate of the drawn area,
2376 it returns $TO.\n\n\n
2377 If $Y fits in with the drawn area but $X is less than the minimum
2378 X-coordinate, it returns the character position of the first
2379 character drawn on the line $Y.\n\n\n
2380 If $Y fits in with the drawn area but $X is greater than the
2381 maximum X-coordinate, it returns the character position of the
2382 last character drawn on the line $Y. */
2385 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2387 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2388 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2389 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2390 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2391 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2392 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2394 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2397 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2398 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2400 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2402 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2404 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2405 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2407 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2408 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2411 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2412 int x_offset, int y_offset, MDrawControl *control)
2414 MGlyphString *gstring;
2419 M_CHECK_POS_X (mt, from, -1);
2420 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2421 to = mtext_nchars (mt) + (control->cursor_width != 0);
2427 ASSURE_CONTROL (control);
2428 gstring = get_gstring (frame, mt, from, to, control);
2429 while (y + gstring->line_descent <= y_offset
2430 && gstring->to < to)
2433 y += gstring->line_descent;
2434 M17N_OBJECT_UNREF (gstring->top);
2435 gstring = get_gstring (frame, mt, from, to, control);
2436 y += gstring->line_ascent;
2439 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2440 if (! control->orientation_reversed)
2442 width = gstring->indent;
2443 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2444 if (g->pos >= from && g->pos < to)
2447 if (width > x_offset)
2453 width = - gstring->indent;
2454 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2455 if (g->pos >= from && g->pos < to)
2458 if (width < x_offset)
2463 M17N_OBJECT_UNREF (gstring->top);
2471 @brief Compute information about a glyph.
2473 The mdraw_glyph_info () function computes information about a
2474 glyph that covers a character at position $POS of the M-text $MT
2475 assuming that the text is drawn from the character at $FROM of $MT
2476 on a window of frame $FRAME using the mdraw_text_with_control ()
2477 function with the drawing control object $CONTROL.
2479 The information is stored in the members of $INFO. */
2481 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2483 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2484 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2485 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2486 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2488 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2496 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2497 MDrawControl *control, MDrawGlyphInfo *info)
2499 MGlyphString *gstring;
2503 M_CHECK_RANGE_X (mt, from, pos, -1);
2505 ASSURE_CONTROL (control);
2506 gstring = get_gstring (frame, mt, from, pos + 1, control);
2508 MERROR (MERROR_DRAW, -1);
2509 while (gstring->to <= pos)
2511 y += gstring->line_descent;
2512 M17N_OBJECT_UNREF (gstring->top);
2513 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2514 y += gstring->line_ascent;
2516 info->line_from = gstring->from;
2517 if (info->line_from < from)
2518 info->line_from = from;
2519 info->line_to = gstring->to;
2522 if (! control->orientation_reversed)
2524 info->x = gstring->indent;
2525 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2526 info->x += g->width;
2530 info->x = - gstring->indent;
2531 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2532 info->x -= g->width;
2533 while (g[-1].to == g->to)
2536 info->from = g->pos;
2538 info->glyph_code = g->code;
2539 info->this.x = g->lbearing;
2540 info->this.y = - gstring->line_ascent;
2541 info->this.height = gstring->height;
2542 info->this.width = - g->lbearing + g->width;
2543 if (g->rface->rfont)
2544 info->font = &g->rface->rfont->font;
2547 /* info->logical_width is calculated later. */
2549 if (info->from > info->line_from)
2551 /* The logically previous glyph is on this line. */
2552 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2554 info->prev_from = g_tmp->pos;
2556 else if (info->line_from > 0)
2558 /* The logically previous glyph is on the previous line. */
2559 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2560 gstring->from, control);
2561 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2563 info->prev_from = g_tmp->pos;
2564 M17N_OBJECT_UNREF (gst->top);
2567 info->prev_from = -1;
2569 if (GLYPH_INDEX (g) > 1)
2570 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2571 else if (! control->orientation_reversed)
2573 if (info->line_from > 0)
2577 int p = gstring->from - 1;
2579 gst = get_gstring (frame, mt, p, gstring->from, control);
2580 g_tmp = gst->glyphs + (gst->used - 2);
2581 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2582 M17N_OBJECT_UNREF (gst->top);
2585 info->left_from = info->left_to = -1;
2589 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2593 int p = gstring->to;
2595 gst = get_gstring (frame, mt, p, p + 1, control);
2596 g_tmp = gst->glyphs + (gst->used - 2);
2597 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2598 M17N_OBJECT_UNREF (gst->top);
2601 info->left_from = info->left_to = -1;
2604 if (info->to < gstring->to)
2606 /* The logically next glyph is on this line. */
2607 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2609 info->next_to = g_tmp->to;
2611 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2613 /* The logically next glyph is on the next line. */
2615 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2616 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2618 info->next_to = g_tmp->to;
2619 M17N_OBJECT_UNREF (gst->top);
2624 for (info->logical_width = (g++)->width;
2625 g->pos == pos && g->type != GLYPH_ANCHOR;
2626 info->this.width += g->width, info->logical_width += (g++)->width);
2627 info->this.width += g[-1].rbearing - g[-1].width;
2629 if (g->type != GLYPH_ANCHOR)
2630 info->right_from = g->pos, info->right_to = g->to;
2631 else if (! control->orientation_reversed)
2633 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2636 M17N_OBJECT_UNREF (gstring->top);
2637 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2639 info->right_from = g->pos, info->right_to = g->to;
2642 info->right_from = info->right_to = -1;
2646 if (info->line_from > 0)
2648 pos = gstring->from - 1;
2649 M17N_OBJECT_UNREF (gstring->top);
2650 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2652 info->right_from = g->pos, info->right_to = g->to;
2655 info->right_from = info->right_to = -1;
2658 M17N_OBJECT_UNREF (gstring->top);
2665 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2666 MDrawControl *control, MDrawGlyph *glyphs,
2667 int array_size, int *num_glyphs_return)
2669 MGlyphString *gstring;
2674 ASSURE_CONTROL (control);
2675 *num_glyphs_return = 0;
2676 M_CHECK_RANGE (mt, from, to, -1, 0);
2677 gstring = get_gstring (frame, mt, from, to, control);
2680 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2682 if (g->type == GLYPH_BOX
2683 || g->pos < from || g->pos >= to)
2685 if (g->type == GLYPH_PAD)
2687 if (g->left_padding)
2688 pad_width = g->width;
2692 glyphs[-1].x_advance += g->width;
2698 glyphs->from = g->pos;
2700 glyphs->glyph_code = g->code;
2701 glyphs->x_off = g->xoff + pad_width;
2702 glyphs->y_off = g->yoff;
2703 glyphs->lbearing = g->lbearing;
2704 glyphs->rbearing = g->rbearing;
2705 glyphs->ascent = g->ascent;
2706 glyphs->descent = g->descent;
2707 glyphs->x_advance = g->width + pad_width;
2708 if (g->rface->rfont)
2710 glyphs->font = &g->rface->rfont->font;
2711 glyphs->font_type = g->rface->rfont->type;
2712 glyphs->fontp = g->rface->rfont->fontp;
2716 glyphs->font = NULL;
2717 glyphs->font_type = Mnil;
2718 glyphs->fontp = NULL;
2725 M17N_OBJECT_UNREF (gstring->top);
2727 *num_glyphs_return = n;
2728 return (n <= array_size ? 0 : -1);
2734 @brief Draw one or more textitems.
2736 The mdraw_text_items () function draws one or more M-texts on
2737 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2738 of the textitems to be drawn and $NITEMS is the number of
2739 textimtems in the array. */
2742 @brief textitem ¤òɽ¼¨¤¹¤ë.
2744 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2745 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2746 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2749 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2753 MTextItem, mdraw_text (). */
2756 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2757 MDrawTextItem *items, int nitems)
2759 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2761 while (nitems-- > 0)
2764 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2766 mdraw_text_with_control (frame, win, x, y,
2767 items->mt, 0, mtext_nchars (items->mt),
2769 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2770 items->control, NULL, NULL, NULL);
2773 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2779 @brief calculate a line breaking position.
2781 The function mdraw_default_line_break () calculates a line
2782 breaking position based on the line number $LINE and the
2783 coordinate $Y, when a line is too long to fit within the width
2784 limit. $POS is the position of the character next to the last
2785 one that fits within the limit. $FROM is the position of the
2786 first character of the line, and TO is the position of the last
2787 character displayed on the line if there were not width limit.
2788 LINE and Y are reset to 0 when a line is broken by a newline
2789 character, and incremented each time when a long line is broken
2790 because of the width limit.
2793 This function returns a character position to break the
2798 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2800 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2801 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2802 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2803 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2804 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2805 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2806 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2809 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2813 mdraw_default_line_break (MText *mt, int pos,
2814 int from, int to, int line, int y)
2816 int c = mtext_ref_char (mt, pos);
2819 if (c == ' ' || c == '\t')
2823 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2830 if (c == ' ' || c == '\t')
2833 c = mtext_ref_char (mt, pos);
2846 @brief Obtain per character dimension information.
2848 The mdraw_per_char_extents () function computes the text dimension
2849 of each character in M-text $MT. The faces given as text
2850 properties in $MT and the default face of frame $FRAME determine
2851 the fonts to draw the text. Each successive element in
2852 $ARRAY_RETURN is set to the drawn metrics of successive
2853 characters, which is relative to the origin of the drawing, and a
2854 rectangle for each character in $MT. The number of elements of
2855 $ARRAY_RETURN must be equal to or greater than the number of
2858 If pointer $OVERALL_RETURN is not @c NULL, this function also
2859 computes the extents of the overall text and stores the results in
2860 the members of the structure pointed to by $OVERALL_RETURN. */
2863 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2865 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2866 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2867 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2868 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2869 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2870 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2873 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2874 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2877 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2880 mdraw_per_char_extents (MFrame *frame, MText *mt,
2881 MDrawMetric *array_return,
2882 MDrawMetric *overall_return)
2884 int n = mtext_nchars (mt);
2886 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2887 n, &n, overall_return, NULL);
2891 @brief clear cached information.
2893 The mdraw_clear_cache () function clear cached information
2894 on M-text $MT that was attached by any of the drawing functions.
2895 When the behaviour of `format' or `line_break'
2896 member functions of MDrawControl is changed, the cache must be cleared.
2901 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2903 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2904 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2905 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2906 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2911 mdraw_clear_cache (MText *mt)
2913 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);