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 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 = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
107 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
109 FriBidiStrIndex *indices;
110 FriBidiLevel *levels;
111 #else /* not HAVE_FRIBIDI */
112 int *logical = alloca (sizeof (int) * len);
114 char *levels = alloca (len);
115 #endif /* not HAVE_FRIBIDI */
117 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
122 #endif /* not HAVE_FRIBIDI */
125 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
127 if (bidi == MbidiR || bidi == MbidiAL
128 || bidi == MbidiRLE || bidi == MbidiRLO)
133 #endif /* not HAVE_FRIBIDI */
139 if (! bidi_sensitive)
142 glyphs = alloca (sizeof (MGlyph) * len);
143 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
145 visual = alloca (sizeof (FriBidiChar) * (len + 1));
146 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
147 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
149 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
150 #else /* not HAVE_FRIBIDI */
151 indices = alloca (sizeof (int) * len);
152 for (i = 0; i < len; i++)
158 for (j = i + 1; j < len && levels[j]; j++);
159 for (k = j--; i < k; i++, j--)
166 #endif /* not HAVE_FRIBIDI */
168 for (i = 0; i < len;)
170 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
172 /* Length of grapheme-cluster */
177 if (visual[j] != logical[i])
182 g->code = mfont__encode_char (g->rface->rfont, g->c);
184 #endif /* HAVE_FRIBIDI */
185 g->bidi_level = levels[i];
186 for (seglen = 1, g++;
187 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
188 || glyphs[i + seglen].combining_code);
191 g->bidi_level = levels[i];
192 if (indices[i + seglen] < j)
193 j = indices[i + seglen];
195 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
201 reorder_combining_chars (MGlyphString *gstring, int from, int to)
203 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
209 for (g = gbeg; g != gend; g++)
210 if (COMBINING_CODE_CLASS (g->combining_code) > 0
211 && (COMBINING_CODE_CLASS (g[-1].combining_code)
212 > COMBINING_CODE_CLASS (g->combining_code)))
223 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
224 displaying them on FRAME.
226 This function fills members <type>, <rface>, <c>, <pos>, <to>,
227 <code> of glyphs. The other members are filled by
228 layout_glyph_string. */
231 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
232 MGlyphString *gstring)
234 MRealizedFace *default_rface = frame->rface;
235 int stop, face_change, language_change, charset_change;
238 MSymbol language = Mnil, script = Mnil, charset = Mnil;
239 MSymbol non_latin_script = Mnil;
240 MRealizedFace *rface = default_rface;
241 int size = gstring->control.fixed_width;
245 MLIST_RESET (gstring);
246 gstring->from = from;
248 /* At first generate glyphs while using the member <enabled> as a
249 flag for rface re-checking. */
252 /** Put anchor glyphs at the head and tail. */
253 g_tmp.type = GLYPH_ANCHOR;
254 g_tmp.pos = g_tmp.to = from;
256 APPEND_GLYPH (gstring, g_tmp);
258 stop = face_change = charset_change = language_change = pos = from;
265 if (pos < mtext_nchars (mt))
266 c = mtext_ref_char (mt, pos);
269 g_tmp.category = mchar_get_prop (c, Mcategory);
272 /* Short cut for the obvious case. */
273 g_tmp.type = (c == ' ' || c == '\n' || c == '\t'
274 ? GLYPH_SPACE : GLYPH_CHAR);
275 this_script = Mlatin;
279 g_tmp.type = GLYPH_CHAR;
280 this_script = (MSymbol) mchar_get_prop (c, Mscript);
281 if (this_script == Minherited || this_script == Mnil)
282 this_script = script;
283 if (this_script == Mnil)
284 this_script = non_latin_script;
285 if (this_script == Mnil)
287 /* Search forward for a character that explicitly
288 specifies a non-latin script. */
292 for (i = pos + 1; i < to; i++)
293 if ((c1 = mtext_ref_char (mt, i)) >= 0x100
294 && (sym = mchar_get_prop (c1, Mscript)) != Mnil
295 && sym != Minherited)
303 if (pos == stop || script != this_script
304 || MGLYPH (last)->type != g_tmp.type)
307 if (g->type != GLYPH_ANCHOR)
308 while (g < gstring->glyphs + gstring->used)
309 g = mface__for_chars (script, language, charset,
310 g, gstring->glyphs + gstring->used, size);
313 last = gstring->used;
314 script = this_script;
315 if (script != Mnil && script != Mlatin)
316 non_latin_script = script;
319 if (pos < mtext_nchars (mt) && pos == language_change)
321 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
322 mtext_prop_range (mt, Mlanguage, pos, NULL,
323 &language_change, 0);
325 if (pos < mtext_nchars (mt) && pos == charset_change)
327 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
328 mtext_prop_range (mt, Mcharset, pos, NULL,
331 if (pos < mtext_nchars (mt) && pos == face_change)
334 int num = mtext_get_prop_values (mt, pos, Mface,
335 (void **) faces, 64);
337 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
339 ? mface__realize (frame, faces, num,
340 language, charset, size)
344 if (stop > language_change)
345 stop = language_change;
346 if (stop > charset_change)
347 stop = charset_change;
348 if (face_change < stop)
358 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
362 ctrl[0] = ctrl[1] = g_tmp;
364 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
365 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
366 APPEND_GLYPH (gstring, ctrl[0]);
367 APPEND_GLYPH (gstring, ctrl[1]);
370 APPEND_GLYPH (gstring, g_tmp);
372 && gstring->control.two_dimensional)
376 /* Append an anchor glyph. */
377 g_tmp.type = GLYPH_ANCHOR;
379 g_tmp.code = MCHAR_INVALID_CODE;
380 g_tmp.pos = g_tmp.to = pos;
382 APPEND_GLYPH (gstring, g_tmp);
386 /* Next, run FLT if necessary. */
387 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
391 if (this->type == GLYPH_CHAR && this->rface->rfont)
395 if (this->rface->rfont->layouter != Mnil)
400 for (prev = MGLYPH (start - 1);
401 (prev->type == GLYPH_CHAR
402 && prev->category == McatCf
403 && (code = mfont__encode_char (this->rface->rfont, prev->c)
404 != MCHAR_INVALID_CODE));
409 (g->type == GLYPH_CHAR
410 && (g->rface->rfont == this->rface->rfont
411 || (g->category == McatCf
412 && ((code = mfont__encode_char (this->rface->rfont,
414 != MCHAR_INVALID_CODE))));
416 if (g->rface->rfont != this->rface->rfont)
418 g->rface->rfont = this->rface->rfont;
421 i = mfont__flt_run (gstring, start, i, this->rface);
425 while (this->type == GLYPH_CHAR
428 && MSYMBOL_NAME (this->category)[0] == 'M'
429 && this->rface->rfont
430 && this->rface->rfont->layouter == Mnil)
432 int class = (int) mchar_get_prop (this->c,
435 = MAKE_COMBINING_CODE_BY_CLASS (class);
439 reorder_combining_chars (gstring, start, i);
440 if (this->type == GLYPH_ANCHOR)
449 /* At last, reorder glyphs visually if necessary. */
450 if (gstring->control.enable_bidi)
451 visual_order (gstring);
456 combining_code_from_class (int class)
461 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
462 else if (class == 200) /* below left attached */
463 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
464 else if (class == 202) /* below attached*/
465 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
466 else if (class == 204) /* below right attached */
467 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
468 else if (class == 208) /* left attached */
469 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
470 else if (class == 210) /* right attached */
471 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
472 else if (class == 212) /* above left attached */
473 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
474 else if (class == 214) /* above attached */
475 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
476 else if (class == 216) /* above right attached */
477 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
478 else if (class == 218) /* below left */
479 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
480 else if (class == 220) /* below */
481 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
482 else if (class == 222) /* below right */
483 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
484 else if (class == 224) /* left */
485 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
486 else if (class == 226) /* right */
487 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
488 else if (class == 228) /* above left */
489 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
490 else if (class == 230) /* above */
491 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
492 else if (class == 232) /* above right */
493 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
494 else if (class == 233) /* double below */
495 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
496 else if (class == 234) /* double above */
497 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
498 else if (class == 240) /* iota subscript */
499 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
501 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
507 int width, lbearing, rbearing;
511 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
512 MSubTextExtents *extents)
514 int g_physical_ascent, g_physical_descent;
515 MGlyph *g = MGLYPH (from);
516 MGlyph *last_g = MGLYPH (to);
519 g_physical_ascent = gstring->physical_ascent;
520 g_physical_descent = gstring->physical_descent;
521 extents->width = extents->lbearing = extents->rbearing = 0;
523 for (i = from; i < to;)
525 if ( MGLYPH (i)->otf_encoded)
531 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
532 mfont__get_metric (gstring, j, i);
540 MRealizedFont *rfont = base->rface->rfont;
541 int size = rfont->font.property[MFONT_SIZE];
542 int width, lbearing, rbearing;
544 if (g == last_g || ! g->combining_code)
547 if (base->width == 0 && ! base->left_padding && ! base->right_padding
548 && GLYPH_INDEX (base) > from)
550 MGlyph *prev = base - 1;
552 if (base->pos < prev->pos)
553 prev->pos = base->pos;
555 base->pos = prev->pos;
556 if (base->to > prev->to)
562 if (base->left_padding && base->lbearing < 0)
564 base->xoff = - base->lbearing;
565 base->width += base->xoff;
566 base->rbearing += base->xoff;
569 if (base->right_padding && base->rbearing > base->width)
571 base->width = base->rbearing;
573 lbearing = (base->xoff + base->lbearing < 0
574 ? base->xoff + base->lbearing : 0);
575 rbearing = base->xoff + base->rbearing;
579 /* With combining glyphs. */
580 int left = -base->width;
582 int top = - base->ascent;
583 int bottom = base->descent;
584 int height = bottom - top;
585 int begin = base->pos;
590 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
591 rbearing = base->rbearing;
593 while (g != last_g && g->combining_code)
595 int combining_code = g->combining_code;
599 else if (end < g->to)
602 if (! COMBINING_PRECOMPUTED_P (combining_code))
604 int base_x, base_y, add_x, add_y, off_x, off_y;
606 if (COMBINING_BY_CLASS_P (combining_code))
607 g->combining_code = combining_code
608 = combining_code_from_class (COMBINING_CODE_CLASS
611 rfont = g->rface->rfont;
612 size = rfont->font.property[MFONT_SIZE];
613 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
615 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
617 base_x = COMBINING_CODE_BASE_X (combining_code);
618 base_y = COMBINING_CODE_BASE_Y (combining_code);
619 add_x = COMBINING_CODE_ADD_X (combining_code);
620 add_y = COMBINING_CODE_ADD_Y (combining_code);
622 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
625 if (g->xoff + g->width > right)
626 right = g->xoff + g->width;
627 width = right - left;
630 g->yoff = top + height * base_y / 2;
634 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
638 if (g->xoff + g->lbearing < left + lbearing)
639 lbearing = g->xoff + g->lbearing - left;
640 if (g->xoff + g->rbearing > left + rbearing)
641 rbearing = g->xoff + g->rbearing - left;
642 if (g->yoff - g->ascent < top)
643 top = g->yoff - g->ascent;
644 if (g->yoff + g->descent > bottom)
645 bottom = g->yoff + g->descent;
646 height = bottom - top;
652 base->ascent = - top;
653 base->descent = bottom;
654 base->lbearing = lbearing;
655 base->rbearing = rbearing;
656 if (left < - base->width)
658 base->xoff = - base->width - left;
659 base->width += base->xoff;
660 base->rbearing += base->xoff;
661 base->lbearing += base->xoff;
665 base->width += right;
666 base->rbearing += right;
667 base->right_padding = 1;
668 for (i = 1; base + i != g; i++)
669 base[i].xoff -= right;
672 for (i = 0; base + i != g; i++)
679 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
680 g_physical_descent = MAX (g_physical_descent, base->descent);
681 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
682 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
683 extents->width += base->width;
686 gstring->physical_ascent = g_physical_ascent;
687 gstring->physical_descent = g_physical_descent;
691 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
692 by this function directly. Character glyphs are handled by
693 layouter functions registered in font drivers.
695 This function fill-in all the remaining members of glyphs. */
698 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
700 /* Default width of TAB. */
701 int tab_width = frame->space_width * (gstring->control.tab_width
702 ? gstring->control.tab_width : 8);
706 MDrawControl *control = &(gstring->control);
709 int box_line_height = 0;
710 int ignore_formatting_char = control->ignore_formatting_char;
712 gstring->ascent = gstring->descent = 0;
713 gstring->physical_ascent = gstring->physical_descent = 0;
714 gstring->width = gstring->lbearing = gstring->rbearing = 0;
718 while (g->type != GLYPH_ANCHOR)
720 if (box != g->rface->box)
722 int gidx = GLYPH_INDEX (g);
726 /* Insert the right side of the box. That glyph belongs
727 to the previous grapheme cluster. */
728 MGlyph box_glyph = g[-1];
730 box_glyph.type = GLYPH_BOX;
732 = (control->fixed_width
734 : box->inner_hmargin + box->width + box->outer_hmargin);
735 box_glyph.lbearing = 0;
736 box_glyph.rbearing = box_glyph.width;
738 box_glyph.right_padding = 1;
739 gstring->width += box_glyph.width;
740 gstring->rbearing += box_glyph.width;
741 INSERT_GLYPH (gstring, gidx, box_glyph);
748 /* Insert the left side of the box. That glyph belongs
749 to the following grapheme cluster. */
750 MGlyph box_glyph = *g;
751 int box_height = (box->width
752 + box->inner_vmargin + box->outer_vmargin);
754 if (box_line_height < box_height)
755 box_line_height = box_height;
756 box_glyph.type = GLYPH_BOX;
758 = (control->fixed_width
760 : box->inner_hmargin + box->width + box->outer_hmargin);
761 box_glyph.lbearing = 0;
762 box_glyph.rbearing = box_glyph.width;
764 box_glyph.left_padding = 1;
765 gstring->width += box_glyph.width;
766 gstring->rbearing += box_glyph.width;
767 INSERT_GLYPH (gstring, gidx, box_glyph);
773 if (g->category == McatCf && ignore_formatting_char)
774 g->type = GLYPH_SPACE;
776 if (g->type == GLYPH_CHAR)
778 MRealizedFace *rface = g->rface;
779 MRealizedFont *rfont = rface->rfont;
781 int from = GLYPH_INDEX (g);
783 for (g++; g->type == GLYPH_CHAR; g++)
784 if (! rfont != ! g->rface->rfont
785 || box != g->rface->box
786 || ((fromg->code == MCHAR_INVALID_CODE)
787 != (g->code == MCHAR_INVALID_CODE))
788 || (g->category == McatCf && ignore_formatting_char))
790 if (rfont && fromg->code != MCHAR_INVALID_CODE)
793 int to = GLYPH_INDEX (g);
794 MSubTextExtents extents;
796 layout_glyphs (frame, gstring, from, to, &extents);
797 extra_width = - extents.lbearing;
799 && ! control->disable_overlapping_adjustment
800 && (! control->orientation_reversed
801 ? ((to > 1 || control->align_head)
802 && g->type != GLYPH_ANCHOR)
803 : (((g->type && GLYPH_ANCHOR) || control->align_head)
808 pad.type = GLYPH_PAD;
811 pad.width = pad.rbearing = extra_width;
812 pad.left_padding = 1;
813 INSERT_GLYPH (gstring, from, pad);
815 extents.lbearing = 0;
816 extents.width += extra_width;
817 extents.rbearing += extra_width;
819 g = MGLYPH (from - 1);
820 if (g->type == GLYPH_SPACE)
822 /* The pad just inserted is absorbed (maybe
823 partially) by the previous space while
824 keeping at least some space width. For the
825 moment, we use the arbitrary width 2-pixel.
826 Perhaps, it should be decided by the current
827 face, or a default value of the current
828 frame, which is, however, not yet
830 if (extra_width + 2 < g->width)
832 g->width -= extra_width;
836 extra_width = g->width - 2;
839 gstring->width -= extra_width;
840 gstring->rbearing -= extra_width;
845 extra_width = extents.rbearing - extents.width;
847 && ! control->disable_overlapping_adjustment
848 && (GLYPH_INDEX (g) < gstring->used - 1
849 || (control->orientation_reversed && control->align_head)))
851 if (g->type == GLYPH_SPACE && box == g->rface->box)
854 pad.type = GLYPH_PAD;
857 pad.width = pad.rbearing = extra_width;
858 INSERT_GLYPH (gstring, to, pad);
863 g[-1].width += extra_width;
864 extents.width += extra_width;
867 if (gstring->lbearing > gstring->width + extents.lbearing)
868 gstring->lbearing = gstring->width + extents.lbearing;
869 if (gstring->rbearing < gstring->width + extents.rbearing)
870 gstring->rbearing = gstring->width + extents.rbearing;
871 gstring->width += extents.width;
872 if (gstring->ascent < rface->ascent)
873 gstring->ascent = rface->ascent;
874 if (gstring->descent < rface->descent)
875 gstring->descent = rface->descent;
879 for (; fromg < g; fromg++)
881 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
882 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
883 fromg->width = fromg->rbearing = 1;
885 fromg->width = fromg->rbearing = rface->space_width;
886 fromg->xoff = fromg->lbearing = 0;
887 fromg->ascent = fromg->descent = 0;
888 gstring->width += fromg->width;
889 gstring->rbearing += fromg->width;
891 if (gstring->ascent < frame->rface->ascent)
892 gstring->ascent = frame->rface->ascent;
893 if (gstring->descent < frame->descent)
894 gstring->descent = frame->rface->descent;
897 else if (g->type == GLYPH_SPACE)
900 g->width = g->rface->space_width;
901 else if (g->c == '\n')
903 g->width = control->cursor_width;
906 if (control->cursor_bidi)
908 else if (g->width < 0)
909 g->width = g->rface->space_width;
912 else if (g->c == '\t')
914 g->width = tab_width - ((gstring->indent + gstring->width)
920 if (g[-1].type == GLYPH_PAD)
922 /* This space glyph absorbs (maybe partially) the
923 previous padding glyph. */
924 g->width -= g[-1].width;
926 /* But, keep at least some space width. For the
927 moment, we use the arbitrary width 2-pixel. */
930 g->rbearing = g->width;
931 gstring->width += g->width;
932 gstring->rbearing += g->width;
935 if (gstring->ascent < g->rface->ascent)
936 gstring->ascent = g->rface->ascent;
937 if (gstring->descent < g->rface->descent)
938 gstring->descent = g->rface->descent;
944 gstring->width += g->width;
945 gstring->rbearing += g->width;
952 /* Insert the right side of the box. */
953 int gidx = GLYPH_INDEX (g);
954 MGlyph box_glyph = g[-1];
956 box_glyph.type = GLYPH_BOX;
958 = (control->fixed_width
960 : box->inner_hmargin + box->width + box->outer_hmargin);
961 box_glyph.lbearing = 0;
962 box_glyph.rbearing = box_glyph.width;
964 box_glyph.right_padding = 1;
965 gstring->width += box_glyph.width;
966 gstring->rbearing += box_glyph.width;
967 INSERT_GLYPH (gstring, gidx, box_glyph);
970 gstring->text_ascent = gstring->ascent;
971 gstring->text_descent = gstring->descent;
972 if (gstring->text_ascent < gstring->physical_ascent)
973 gstring->text_ascent = gstring->physical_ascent;
974 if (gstring->text_descent < gstring->physical_descent)
975 gstring->text_descent = gstring->physical_descent;
976 gstring->line_ascent = gstring->text_ascent;
977 gstring->line_descent = gstring->text_descent;
978 if (box_line_height > 0)
980 gstring->line_ascent += box_line_height;
981 gstring->physical_ascent = gstring->line_ascent;
982 gstring->line_descent += box_line_height;
983 gstring->physical_descent = gstring->line_descent;
986 if (gstring->line_ascent < control->min_line_ascent)
987 gstring->line_ascent = control->min_line_ascent;
988 else if (control->max_line_ascent
989 && control->max_line_ascent > control->min_line_ascent
990 && gstring->line_ascent > control->max_line_ascent)
991 gstring->line_ascent = control->max_line_ascent;
993 if (gstring->line_descent < control->min_line_descent)
994 gstring->line_descent = control->min_line_descent;
995 else if (control->max_line_descent
996 && control->max_line_descent > control->min_line_descent
997 && gstring->line_descent > control->max_line_descent)
998 gstring->line_descent = control->max_line_descent;
999 gstring->height = gstring->line_ascent + gstring->line_descent;
1001 if (control->orientation_reversed
1004 /* We must adjust TAB width for RTL orientation. */
1005 width = gstring->indent;
1007 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1009 if (g->type == GLYPH_CHAR && g->c == '\t')
1011 int this_width = tab_width - (width % tab_width);
1013 if (g[1].type == GLYPH_PAD)
1014 this_width -= g[1].width;
1015 if (g[-1].type == GLYPH_PAD)
1016 this_width -= g[-1].width;
1019 gstring->width += this_width - g->width;
1020 gstring->rbearing += this_width - g->width;
1021 g->width = this_width;
1022 width += this_width;
1032 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1033 MGlyphString *gstring, int from, int to,
1034 int *from_idx, int *to_idx, int *to_x)
1036 MGlyph *g = MGLYPH (1);
1037 MDrawRegion region = (MDrawRegion) NULL;
1038 MDrawControl *control = &gstring->control;
1039 int cursor_pos = -1;
1041 int cursor_bidi = control->cursor_bidi;
1043 if (control->with_cursor && control->cursor_width)
1045 if (gstring->from <= control->cursor_pos
1046 && gstring->to > control->cursor_pos)
1047 cursor_pos = control->cursor_pos;
1050 && gstring->from <= control->cursor_pos - 1
1051 && gstring->to > control->cursor_pos - 1)
1052 prev_pos = control->cursor_pos - 1;
1055 *from_idx = *to_idx = 0;
1056 while (g->type != GLYPH_ANCHOR)
1058 if (g->pos >= from && g->pos < to)
1060 MGlyph *fromg = g, *cursor = NULL;
1061 MRealizedFace *rface = g->rface;
1063 int cursor_width = 0;
1067 *from_idx = GLYPH_INDEX (g);
1068 while (g->pos >= from && g->pos < to
1069 && g->rface == rface)
1072 if (g->type != GLYPH_BOX
1073 && g->pos <= cursor_pos && g->to > cursor_pos)
1076 cursor = g, cursor_x = x + width;
1077 cursor_width += g->width;
1079 width += g++->width;
1082 && (control->as_image
1083 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1085 int this_x = x, this_width = width;
1087 if (fromg->type == GLYPH_BOX)
1088 this_x += fromg->width, this_width -= fromg->width;
1089 if (g[-1].type == GLYPH_BOX)
1090 this_width -= g[-1].width;
1091 (frame->driver->fill_space)
1092 (frame, win, rface, 0,
1093 this_x, y - gstring->text_ascent, this_width,
1094 gstring->text_ascent + gstring->text_descent,
1095 control->clip_region);
1102 rect.y = y - gstring->text_ascent;
1103 rect.height = gstring->text_ascent + gstring->text_descent;
1106 rect.width = ((control->cursor_width > 0
1107 && control->cursor_width < cursor_width)
1108 ? control->cursor_width : cursor_width);
1112 if (cursor->bidi_level % 2)
1113 rect.x += cursor_width - rect.width;
1114 (*frame->driver->fill_space)
1115 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1116 control->clip_region);
1118 region = (*frame->driver->region_from_rect) (&rect);
1120 (*frame->driver->region_add_rect) (region, &rect);
1123 if (cursor->bidi_level % 2)
1126 rect.width = cursor_width < 4 ? cursor_width : 4;
1127 (*frame->driver->fill_space)
1128 (frame, win, rface, 1,
1129 rect.x, rect.y, rect.width, rect.height,
1130 control->clip_region);
1131 (*frame->driver->region_add_rect) (region, &rect);
1143 if (fromg->type != GLYPH_BOX
1144 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1147 cursor = fromg, cursor_x = x + temp_width;
1148 cursor_width += fromg->width;
1150 temp_width += fromg++->width;
1157 if (! (cursor->bidi_level % 2))
1158 rect.x += cursor_width - 1;
1159 rect.y = y - gstring->text_ascent;
1160 rect.height = gstring->text_ascent + gstring->text_descent;
1162 (*frame->driver->fill_space)
1163 (frame, win, rface, 1,
1164 rect.x, rect.y, rect.width, rect.height,
1165 control->clip_region);
1167 region = (*frame->driver->region_from_rect) (&rect);
1169 (*frame->driver->region_add_rect) (region, &rect);
1170 rect.y += rect.height - 2;
1172 rect.width = cursor_width < 4 ? cursor_width : 4;
1173 if (! (cursor->bidi_level % 2))
1174 rect.x -= rect.width - 1;
1175 (*frame->driver->fill_space) (frame, win, rface, 1,
1176 rect.x, rect.y, rect.width, rect.height,
1177 control->clip_region);
1178 (*frame->driver->region_add_rect) (region, &rect);
1182 *to_idx = GLYPH_INDEX (g);
1192 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1193 MGlyphString *gstring, int from_idx, int to_idx,
1194 int reverse, MDrawRegion region)
1196 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1202 (*frame->driver->region_to_rect) (region, &rect);
1205 while (g != gend && x + g->rbearing <= rect.x)
1208 width -= g++->width;
1209 while (! g->enabled && g != gend)
1213 rect.x += rect.width;
1214 if (rect.x < x + width)
1217 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1219 width -= (--gend)->width;
1220 while (! gend->enabled && g != gend)
1224 while (gend[-1].to == gend->to) gend++;
1232 MRealizedFace *rface = g->rface;
1233 int width = g->width;
1234 MGlyph *from_g = g++;
1236 /* Handle the glyphs of the same type/face at once. */
1238 && g->type == from_g->type
1239 && g->rface == rface
1240 && ((g->code == MCHAR_INVALID_CODE)
1241 == (from_g->code == MCHAR_INVALID_CODE))
1243 width += g++->width;
1245 if (from_g->type == GLYPH_CHAR)
1247 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1248 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1251 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1254 else if (from_g->type == GLYPH_BOX)
1256 /* Draw the left or right side of a box. If
1257 from_g->lbearing is nonzero, this is the left side,
1258 else this is the right side. */
1259 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1262 if (from_g->type != GLYPH_BOX)
1265 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1266 x, y, width, region);
1269 /* Draw the top and bottom side of a box. */
1270 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1271 x, y, width, region);
1282 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1283 int *from_x, int *to_x)
1286 int left_idx = *left, right_idx = *right;
1287 int left_x, right_x, x;
1289 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1292 if (x + g->rbearing > 0)
1294 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1296 left_idx = GLYPH_INDEX (g);
1301 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1304 if (x - g->width + g->lbearing < 0)
1306 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1308 right_idx = GLYPH_INDEX (g) + 1;
1313 if (*left == left_idx && *right == right_idx)
1316 if (*left != left_idx)
1318 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1323 if (*right != right_idx)
1325 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1335 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1340 if (from <= gstring->from && to >= gstring->to)
1343 *rbearing = gstring->rbearing;
1344 return gstring->width;
1349 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1350 if (g->pos >= from && g->pos < to)
1352 if (rbearing && width + g->rbearing > *rbearing)
1353 *rbearing = width + g->rbearing;
1361 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1362 MGlyphString *gstring, int from, int to)
1364 MDrawControl *control = &gstring->control;
1366 MDrawRegion clip_region, cursor_region;
1367 int from_idx, to_idx;
1370 if (control->orientation_reversed)
1371 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1373 x += gstring->indent;
1375 /* At first, draw all glyphs without cursor. */
1376 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1377 &from_idx, &to_idx, &to_x);
1379 if (control->partial_update)
1382 rect.width = to_x - x;
1383 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1385 rect.y = y - gstring->line_ascent;
1386 rect.height = gstring->height;
1387 clip_region = (*frame->driver->region_from_rect) (&rect);
1388 if (control->clip_region)
1389 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1392 clip_region = control->clip_region;
1395 clip_region = control->clip_region;
1397 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1402 (*frame->driver->intersect_region) (cursor_region, clip_region);
1403 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1406 if (clip_region != control->clip_region)
1407 (*frame->driver->free_region) (clip_region);
1409 (*frame->driver->free_region) (cursor_region);
1413 static int gstring_num;
1416 free_gstring (void *object)
1418 MGlyphString *gstring = (MGlyphString *) object;
1421 free_gstring (gstring->next);
1422 if (gstring->size > 0)
1423 free (gstring->glyphs);
1429 static MGlyphString scratch_gstring;
1431 static MGlyphString *
1432 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1435 MGlyphString *gstring;
1437 if (pos == mt->nchars)
1439 gstring = &scratch_gstring;
1443 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1444 MLIST_INIT1 (gstring, glyphs, 128);
1448 gstring->frame = frame;
1449 gstring->tick = frame->tick;
1450 gstring->top = gstring;
1451 gstring->control = *control;
1452 gstring->indent = gstring->width_limit = 0;
1453 if (control->format)
1454 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1456 gstring->width_limit = control->max_line_width;
1457 gstring->anti_alias = control->anti_alias;
1461 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1464 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1472 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1473 a width of glyphs for the character at I of MT. If I is not a
1474 beginning of a grapheme cluster, the corresponding element is
1476 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1477 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1478 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1479 pos_width[g->pos - gstring->from] += g->width;
1480 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1482 if (pos_width[i] > 0)
1484 if (width + pos_width[i] > gstring->width_limit)
1487 width += pos_width[i];
1490 pos = gstring->from + i;
1491 if (gstring->control.line_break)
1493 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1494 gstring->from, gstring->to, 0, 0);
1495 if (pos <= gstring->from)
1496 pos = gstring->from + 1;
1497 else if (pos >= gstring->to)
1502 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1503 layout_glyph_string (frame, gstring);
1507 /* Return a gstring that covers a character at POS. */
1509 static MGlyphString *
1510 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1512 MGlyphString *gstring = NULL;
1514 if (pos < mtext_nchars (mt))
1516 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1519 && ((prop->start != 0
1520 && mtext_ref_char (mt, prop->start - 1) != '\n')
1521 || (prop->end < mtext_nchars (mt)
1522 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1524 mtext_detach_property (prop);
1529 gstring = prop->val;
1530 if (gstring->frame != frame
1531 || gstring->tick != frame->tick
1532 || memcmp (control, &gstring->control,
1533 (char *) (&control->with_cursor)
1534 - (char *) (control))
1535 || control->cursor_width != gstring->control.cursor_width
1536 || control->cursor_bidi != gstring->control.cursor_bidi)
1538 mtext_detach_property (prop);
1543 else if (! control->cursor_width)
1551 offset = mtext_character (mt, pos, 0, '\n');
1556 offset -= gstring->from;
1558 for (gst = gstring; gst; gst = gst->next)
1562 gst->from += offset;
1564 for (i = 0; i < gst->used; i++)
1566 gst->glyphs[i].pos += offset;
1567 gst->glyphs[i].to += offset;
1570 M17N_OBJECT_REF (gstring);
1575 int line = 0, y = 0;
1577 beg = mtext_character (mt, pos, 0, '\n');
1582 end = mtext_nchars (mt) + (control->cursor_width != 0);
1584 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1585 compose_glyph_string (frame, mt, beg, end, gstring);
1586 layout_glyph_string (frame, gstring);
1588 if (gstring->width_limit
1589 && gstring->width > gstring->width_limit)
1591 MGlyphString *gst = gstring;
1593 truncate_gstring (frame, mt, gst);
1594 while (gst->to < end)
1596 line++, y += gst->height;
1597 gst->next = alloc_gstring (frame, mt, gst->from, control,
1599 gst->next->top = gstring;
1600 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1602 layout_glyph_string (frame, gst);
1603 if (gst->width <= gst->width_limit)
1605 truncate_gstring (frame, mt, gst);
1609 if (! control->disable_caching && pos < mtext_nchars (mt))
1611 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1612 MTEXTPROP_VOLATILE_STRONG);
1614 if (end > mtext_nchars (mt))
1615 end = mtext_nchars (mt);
1616 mtext_attach_property (mt, beg, end, prop);
1617 M17N_OBJECT_UNREF (prop);
1621 while (gstring->to <= pos)
1623 if (! gstring->next)
1625 gstring = gstring->next;
1627 gstring->control = *control;
1633 static MDrawControl control_noop;
1635 #define ASSURE_CONTROL(control) \
1637 control = &control_noop; \
1642 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1643 MText *mt, int from, int to,
1644 MDrawControl *control)
1646 MGlyphString *gstring;
1648 M_CHECK_POS_X (mt, from, -1);
1649 ASSURE_CONTROL (control);
1650 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1651 to = mtext_nchars (mt) + (control->cursor_width != 0);
1655 gstring = get_gstring (frame, mt, from, to, control);
1657 MERROR (MERROR_DRAW, -1);
1658 render_glyph_string (frame, win, x, y, gstring, from, to);
1662 y += gstring->line_descent;
1663 M17N_OBJECT_UNREF (gstring->top);
1664 gstring = get_gstring (frame, mt, from, to, control);
1665 y += gstring->line_ascent;
1666 render_glyph_string (frame, win, x, y, gstring, from, to);
1669 M17N_OBJECT_UNREF (gstring->top);
1676 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1682 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1683 if (g->pos <= pos && g->to > pos)
1688 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1689 if (g->pos <= pos && g->to > pos)
1696 /* for debugging... */
1700 dump_combining_code (int code)
1702 char *vallign = "tcbB";
1703 char *hallign = "lcr";
1709 if (COMBINING_BY_CLASS_P (code))
1710 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1711 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1712 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1713 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1714 off_x = COMBINING_CODE_OFF_X (code) - 128;
1716 sprintf (work + 2, "+%d", off_y);
1718 sprintf (work + 2, "%d", off_y);
1719 else if (off_x == 0)
1720 sprintf (work + 2, ".");
1721 p = work + strlen (work);
1723 sprintf (p, ">%d", off_x);
1725 sprintf (p, "<%d", -off_x);
1727 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1728 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1734 dump_gstring (MGlyphString *gstring, int indent)
1736 char *prefix = (char *) alloca (indent + 1);
1737 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1739 memset (prefix, 32, indent);
1742 fprintf (stderr, "(glyph-string");
1744 for (g = MGLYPH (0); g < last_g; g++)
1746 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1748 g - gstring->glyphs,
1749 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1750 : g->type == GLYPH_ANCHOR ? "ANC"
1751 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1752 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1753 dump_combining_code (g->combining_code),
1754 g->width, g->bidi_level);
1755 fprintf (stderr, ")");
1759 /* m17n-X internal APIs */
1764 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1766 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1767 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1769 Minherited = msymbol ("inherited");
1771 McatCc = msymbol ("Cc");
1772 McatCf = msymbol ("Cf");
1774 MbidiR = msymbol ("R");
1775 MbidiAL = msymbol ("AL");
1776 MbidiRLE = msymbol ("RLE");
1777 MbidiRLO = msymbol ("RLO");
1778 MbidiBN = msymbol ("BN");
1779 MbidiS = msymbol ("S");
1781 fribidi_set_mirroring (TRUE);
1790 MLIST_FREE1 (&scratch_gstring, glyphs);
1794 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1798 /*** @addtogroup m17nDraw */
1803 @brief Draw an M-text on a window.
1805 The mdraw_text () function draws the text between $FROM and $TO of
1806 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1808 The appearance of the text (size, style, color, etc) is specified
1809 by the value of the text property whose key is @c Mface. If the
1810 M-text or a part of the M-text does not have such a text property,
1811 the default face of $FRAME is used.
1813 The font used to draw a character in the M-text is selected from
1814 the value of the fontset property of a face by the following
1819 <li> Search the text properties given to the character for the one
1820 whose key is @c Mcharset; its value should be either a symbol
1821 specifying a charset or #Mnil. If the value is #Mnil,
1822 proceed to the next step.
1824 Otherwise, search the mapping table of the fontset for the
1825 charset. If no entry is found proceed to the next step.
1827 If an entry is found, use one of the fonts in the entry that
1828 has a glyph for the character and that matches best with the
1829 face properties. If no such font exists, proceed to the next
1832 <li> Get the character property "script" of the character. If it is
1833 inherited, get the script property from the previous
1834 characters. If there is no previous character, or none of
1835 them has the script property other than inherited, proceed to
1838 Search the text properties given to the character for the one
1839 whose key is @c Mlanguage; its value should be either a
1840 symbol specifying a language or @c Mnil.
1842 Search the mapping table of the fontset for the combination
1843 of the script and language. If no entry is found, proceed to
1846 If an entry is found, use one of the fonts in the entry that
1847 has a glyph for the character and that matches best with the
1848 face properties. If no such font exists, proceed to the next
1851 <li> Search the fall-back table of the fontset for a font that has
1852 a glyph of the character. If such a font is found, use that
1857 If no font is found by the algorithm above, this function draws an
1858 empty box for the character.
1860 This function draws only the glyph foreground. To specify the
1861 background color, use mdraw_image_text () or
1862 mdraw_text_with_control ().
1864 This function is the counterpart of <tt>XDrawString ()</tt>,
1865 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1866 in the X Window System.
1869 If the operation was successful, mdraw_text () returns 0. If an
1870 error is detected, it returns -1 and assigns an error code to the
1871 external variable #merror_code. */
1873 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1875 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1876 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1879 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1880 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1881 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1882 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1884 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1885 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1889 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1890 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1891 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1892 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1893 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1896 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1897 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1898 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1901 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1902 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1903 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1904 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1906 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1907 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1910 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1911 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1914 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1915 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1916 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1919 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1920 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1924 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1925 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1927 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1928 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1931 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1932 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1935 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1936 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1938 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1945 mdraw_image_text () */
1948 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1949 MText *mt, int from, int to)
1951 MDrawControl control;
1953 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1954 memset (&control, 0, sizeof control);
1955 control.as_image = 0;
1956 return draw_text (frame, win, x, y, mt, from, to, &control);
1963 @brief Draw an M-text on a window as an image.
1965 The mdraw_image_text () function draws the text between $FROM and
1966 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1967 coordinate ($X, $Y).
1969 The way to draw a text is the same as in mdraw_text () except that
1970 this function also draws the background with the color specified
1973 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1974 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1975 functions in the X Window System.
1978 If the operation was successful, mdraw_image_text () returns 0.
1979 If an error is detected, it returns -1 and assigns an error code
1980 to the external variable #merror_code. */
1983 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1985 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1986 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1989 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1990 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1992 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1993 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1997 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1998 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
2001 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2011 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2012 MText *mt, int from, int to)
2014 MDrawControl control;
2016 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2017 memset (&control, 0, sizeof control);
2018 control.as_image = 1;
2019 return draw_text (frame, win, x, y, mt, from, to, &control);
2025 @brief Draw an M-text on a window with fine control.
2027 The mdraw_text_with_control () function draws the text between
2028 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2029 coordinate ($X, $Y).
2031 The way to draw a text is the same as in mdraw_text () except that
2032 this function also follows what specified in the drawing control
2035 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2036 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2037 breaks lines and the following characters are drawn in the next
2038 line. See the documentation of the structure @ MDrawControl for
2042 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2044 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2045 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2048 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2049 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2051 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2052 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2053 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2057 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2058 MText *mt, int from, int to, MDrawControl *control)
2060 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2061 return draw_text (frame, win, x, y, mt, from, to, control);
2067 @brief Compute text pixel width.
2069 The mdraw_text_extents () function computes the width of text
2070 between $FROM and $TO of M-text $MT when it is drawn on a window
2071 of frame $FRAME using the mdraw_text_with_control () function with
2072 the drawing control object $CONTROL.
2074 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2075 the bounding box of character ink of the M-text, and stores the
2076 results in the members of the structure pointed to by
2077 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2078 surrounding box, the box is included in the bounding box.
2080 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2081 computes the bounding box that provides mininum spacing to other
2082 graphical features (such as surrounding box) for the M-text, and
2083 stores the results in the members of the structure pointed to by
2084 $OVERALL_LOGICAL_RETURN.
2086 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2087 computes the bounding box that provides mininum spacing to the
2088 other M-text drawn, and stores the results in the members of the
2089 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2090 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2091 min_line_ascent, min_line_descent, max_line_ascent, and
2092 max_line_descent of $CONTROL are all zero.
2095 This function returns the width of the text to be drawn in the
2096 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2097 text is drawn in multiple physical lines, it returns the width of
2098 the widest line. If an error occurs, it returns -1 and assigns an
2099 error code to the external variable #merror_code. */
2103 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2105 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2106 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2107 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2109 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2110 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2111 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2112 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2114 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2115 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2116 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2117 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2119 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2120 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2121 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2122 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2123 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2124 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2126 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2127 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2128 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2129 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2131 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2138 mdraw_text_extents (MFrame *frame,
2139 MText *mt, int from, int to, MDrawControl *control,
2140 MDrawMetric *overall_ink_return,
2141 MDrawMetric *overall_logical_return,
2142 MDrawMetric *overall_line_return)
2144 MGlyphString *gstring;
2146 int width, rbearing;
2148 ASSURE_CONTROL (control);
2149 M_CHECK_POS_X (mt, from, -1);
2150 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2151 to = mtext_nchars (mt) + (control->cursor_width != 0);
2155 gstring = get_gstring (frame, mt, from, to, control);
2157 MERROR (MERROR_DRAW, -1);
2158 width = gstring_width (gstring, from, to, &rbearing);
2159 if (overall_ink_return)
2161 overall_ink_return->y = - gstring->physical_ascent;
2162 overall_ink_return->x = gstring->lbearing;
2164 if (overall_logical_return)
2166 overall_logical_return->y = - gstring->ascent;
2167 overall_logical_return->x = 0;
2169 if (overall_line_return)
2171 overall_line_return->y = - gstring->line_ascent;
2172 overall_line_return->x = gstring->lbearing;
2175 for (from = gstring->to; from < to; from = gstring->to)
2177 int this_width, this_rbearing;
2179 y += gstring->line_descent;
2180 M17N_OBJECT_UNREF (gstring->top);
2181 gstring = get_gstring (frame, mt, from, to, control);
2182 this_width = gstring_width (gstring, from, to, &this_rbearing);
2183 y += gstring->line_ascent;
2184 if (width < this_width)
2186 if (rbearing < this_rbearing)
2187 rbearing = this_rbearing;
2189 if (overall_ink_return)
2191 overall_ink_return->width = rbearing;
2192 overall_ink_return->height
2193 = y + gstring->physical_descent - overall_ink_return->y;
2195 if (overall_logical_return)
2197 overall_logical_return->width = width;
2198 overall_logical_return->height
2199 = y + gstring->descent - overall_logical_return->y;
2201 if (overall_line_return)
2203 overall_line_return->width = MAX (width, rbearing);
2204 overall_line_return->height
2205 = y + gstring->line_descent - overall_line_return->y;
2208 M17N_OBJECT_UNREF (gstring->top);
2215 @brief Compute the text dimensions of each character of M-text.
2217 The mdraw_text_per_char_extents () function computes the drawn
2218 metric of each character between $FROM and $TO of M-text $MT
2219 assuming that they are drawn on a window of frame $FRAME using the
2220 mdraw_text_with_control () function with the drawing control
2223 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2224 $LOGICAL_ARRAY_RETURN. Each successive element of
2225 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2226 ink and logical metrics of successive characters respectively,
2227 relative to the drawing origin of the M-text. The number of
2228 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2229 been set is returned to $NUM_CHARS_RETURN.
2231 If $ARRAY_SIZE is too small to return all metrics, the function
2232 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2233 Otherwise, it returns zero.
2235 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2236 @c NULL, this function also computes the metrics of the overall
2237 text and stores the results in the members of the structure
2238 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2240 If $CONTROL->two_dimensional is nonzero, this function computes
2241 only the metrics of characters in the first line. */
2243 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2245 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2246 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2247 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2248 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2250 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2251 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2252 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2253 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2254 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2256 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2257 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2260 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2261 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2262 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2265 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2266 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2269 mdraw_text_per_char_extents (MFrame *frame,
2270 MText *mt, int from, int to,
2271 MDrawControl *control,
2272 MDrawMetric *ink_array_return,
2273 MDrawMetric *logical_array_return,
2275 int *num_chars_return,
2276 MDrawMetric *overall_ink_return,
2277 MDrawMetric *overall_logical_return)
2279 MGlyphString *gstring;
2283 ASSURE_CONTROL (control);
2284 *num_chars_return = to - from;
2285 if (array_size < *num_chars_return)
2286 MERROR (MERROR_DRAW, -1);
2287 if (overall_logical_return)
2288 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2289 if (overall_ink_return)
2290 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2292 M_CHECK_RANGE (mt, from, to, -1, 0);
2293 gstring = get_gstring (frame, mt, from, to, control);
2296 *num_chars_return = 0;
2300 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2301 if (g->pos >= from && g->pos < to)
2305 int width = g->width;
2306 int lbearing = g->lbearing;
2307 int rbearing = g->rbearing;
2308 int ascent = g->ascent;
2309 int descent = g->descent;
2311 int logical_descent;
2313 if (g->rface->rfont)
2315 logical_ascent = g->rface->rfont->ascent;
2316 logical_descent = g->rface->rfont->descent;
2320 logical_ascent = g->rface->ascent;
2321 logical_descent = g->rface->descent;
2323 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2325 if (lbearing < width + g->lbearing)
2326 lbearing = width + g->lbearing;
2327 if (rbearing < width + g->rbearing)
2328 rbearing = width + g->rbearing;
2330 if (ascent < g->ascent)
2332 if (descent < g->descent)
2333 descent = g->descent;
2340 if (ink_array_return)
2342 ink_array_return[start - from].x = x + lbearing;
2343 ink_array_return[start - from].y = - ascent;
2344 ink_array_return[start - from].width = rbearing - lbearing;
2345 ink_array_return[start - from].height = ascent + descent;
2347 if (logical_array_return)
2349 logical_array_return[start - from].x = x;
2350 logical_array_return[start - from].y = - logical_descent;
2351 logical_array_return[start - from].height
2352 = logical_ascent + logical_descent;
2353 logical_array_return[start - from].width = width;
2361 if (overall_ink_return)
2363 overall_ink_return->y = - gstring->line_ascent;
2364 overall_ink_return->x = gstring->lbearing;
2365 overall_ink_return->width = x - gstring->lbearing;
2366 overall_ink_return->height = gstring->height;
2368 if (overall_logical_return)
2370 overall_logical_return->y = - gstring->ascent;
2371 overall_logical_return->x = 0;
2372 overall_logical_return->width = x;
2373 overall_logical_return->height = gstring->ascent + gstring->descent;
2376 M17N_OBJECT_UNREF (gstring->top);
2383 @brief Return the character position nearest to the coordinates.
2385 The mdraw_coordinates_position () function checks which character
2386 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2387 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2388 mdraw_text_with_control () function with the drawing control
2389 object $CONTROL. Here, the character position means the number of
2390 characters that precede the character in question in $MT, that is,
2391 the character position of the first character is 0.
2393 $FRAME is used only to get the default face information.
2396 If the glyph image of a character covers coordinate ($X, $Y),
2397 mdraw_coordinates_position () returns the character position of
2399 If $Y is less than the minimum Y-coordinate of the drawn area, it
2400 returns $FROM.\n\n\n
2401 If $Y is greater than the maximum Y-coordinate of the drawn area,
2402 it returns $TO.\n\n\n
2403 If $Y fits in with the drawn area but $X is less than the minimum
2404 X-coordinate, it returns the character position of the first
2405 character drawn on the line $Y.\n\n\n
2406 If $Y fits in with the drawn area but $X is greater than the
2407 maximum X-coordinate, it returns the character position of the
2408 last character drawn on the line $Y. */
2411 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2413 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2414 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2415 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2416 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2417 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2418 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2420 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2423 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2424 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2426 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2428 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2430 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2431 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2433 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2434 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2437 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2438 int x_offset, int y_offset, MDrawControl *control)
2440 MGlyphString *gstring;
2445 M_CHECK_POS_X (mt, from, -1);
2446 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2447 to = mtext_nchars (mt) + (control->cursor_width != 0);
2453 ASSURE_CONTROL (control);
2454 gstring = get_gstring (frame, mt, from, to, control);
2455 while (y + gstring->line_descent <= y_offset
2456 && gstring->to < to)
2459 y += gstring->line_descent;
2460 M17N_OBJECT_UNREF (gstring->top);
2461 gstring = get_gstring (frame, mt, from, to, control);
2462 y += gstring->line_ascent;
2465 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2466 if (! control->orientation_reversed)
2468 width = gstring->indent;
2469 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2470 if (g->pos >= from && g->pos < to)
2473 if (width > x_offset)
2479 width = - gstring->indent;
2480 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2481 if (g->pos >= from && g->pos < to)
2484 if (width < x_offset)
2489 M17N_OBJECT_UNREF (gstring->top);
2497 @brief Compute information about a glyph.
2499 The mdraw_glyph_info () function computes information about a
2500 glyph that covers a character at position $POS of the M-text $MT
2501 assuming that the text is drawn from the character at $FROM of $MT
2502 on a window of frame $FRAME using the mdraw_text_with_control ()
2503 function with the drawing control object $CONTROL.
2505 The information is stored in the members of $INFO. */
2507 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2509 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2510 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2511 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2512 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2514 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2522 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2523 MDrawControl *control, MDrawGlyphInfo *info)
2525 MGlyphString *gstring;
2529 M_CHECK_RANGE_X (mt, from, pos, -1);
2531 ASSURE_CONTROL (control);
2532 gstring = get_gstring (frame, mt, from, pos + 1, control);
2534 MERROR (MERROR_DRAW, -1);
2535 while (gstring->to <= pos)
2537 y += gstring->line_descent;
2538 M17N_OBJECT_UNREF (gstring->top);
2539 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2540 y += gstring->line_ascent;
2542 info->line_from = gstring->from;
2543 if (info->line_from < from)
2544 info->line_from = from;
2545 info->line_to = gstring->to;
2548 if (! control->orientation_reversed)
2550 info->x = gstring->indent;
2551 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2552 info->x += g->width;
2556 info->x = - gstring->indent;
2557 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2558 info->x -= g->width;
2559 while (g[-1].to == g->to)
2562 info->from = g->pos;
2564 info->metrics.x = g->lbearing;
2565 info->metrics.y = - gstring->line_ascent;
2566 info->metrics.height = gstring->height;
2567 info->metrics.width = - g->lbearing + g->width;
2568 if (g->rface->rfont)
2569 info->font = &g->rface->rfont->font;
2572 /* info->logical_width is calculated later. */
2574 if (info->from > info->line_from)
2576 /* The logically previous glyph is on this line. */
2577 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2579 info->prev_from = g_tmp->pos;
2581 else if (info->line_from > 0)
2583 /* The logically previous glyph is on the previous line. */
2584 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2585 gstring->from, control);
2586 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2588 info->prev_from = g_tmp->pos;
2589 M17N_OBJECT_UNREF (gst->top);
2592 info->prev_from = -1;
2594 if (GLYPH_INDEX (g) > 1)
2595 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2596 else if (! control->orientation_reversed)
2598 if (info->line_from > 0)
2602 int p = gstring->from - 1;
2604 gst = get_gstring (frame, mt, p, gstring->from, control);
2605 g_tmp = gst->glyphs + (gst->used - 2);
2606 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2607 M17N_OBJECT_UNREF (gst->top);
2610 info->left_from = info->left_to = -1;
2614 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2618 int p = gstring->to;
2620 gst = get_gstring (frame, mt, p, p + 1, control);
2621 g_tmp = gst->glyphs + (gst->used - 2);
2622 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2623 M17N_OBJECT_UNREF (gst->top);
2626 info->left_from = info->left_to = -1;
2629 if (info->to < gstring->to)
2631 /* The logically next glyph is on this line. */
2632 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2634 info->next_to = g_tmp->to;
2636 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2638 /* The logically next glyph is on the next line. */
2640 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2641 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2643 info->next_to = g_tmp->to;
2644 M17N_OBJECT_UNREF (gst->top);
2649 for (info->logical_width = (g++)->width;
2650 g->pos == pos && g->type != GLYPH_ANCHOR;
2651 info->metrics.width += g->width, info->logical_width += (g++)->width);
2652 info->metrics.width += g[-1].rbearing - g[-1].width;
2654 if (g->type != GLYPH_ANCHOR)
2655 info->right_from = g->pos, info->right_to = g->to;
2656 else if (! control->orientation_reversed)
2658 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2661 M17N_OBJECT_UNREF (gstring->top);
2662 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2664 info->right_from = g->pos, info->right_to = g->to;
2667 info->right_from = info->right_to = -1;
2671 if (info->line_from > 0)
2673 pos = gstring->from - 1;
2674 M17N_OBJECT_UNREF (gstring->top);
2675 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2677 info->right_from = g->pos, info->right_to = g->to;
2680 info->right_from = info->right_to = -1;
2683 M17N_OBJECT_UNREF (gstring->top);
2690 @brief Compute information about glyph sequence.
2692 The mdraw_glyph_list () function computes information about glyphs
2693 corresponding to the text between $FROM and $TO of M-text $MT when
2694 it is drawn on a window of frame $FRAME using the
2695 mdraw_text_with_control () function with the drawing control
2696 object $CONTROL. $GLYPHS is an array of objects to store the
2697 information, and $ARRAY_SIZE is the array size.
2699 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2700 number of actually filled elements in the place pointed by
2701 $NUM_GLYPHS_RETURN, and returns 0.
2703 Otherwise, it stores the required array size in the place pointed
2704 by $NUM_GLYPHS_RETURN, and returns -1. */
2707 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2709 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
2710 À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
2711 ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
2712 ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2714 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
2715 ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
2724 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2725 MDrawControl *control, MDrawGlyph *glyphs,
2726 int array_size, int *num_glyphs_return)
2728 MGlyphString *gstring;
2733 ASSURE_CONTROL (control);
2734 *num_glyphs_return = 0;
2735 M_CHECK_RANGE (mt, from, to, -1, 0);
2736 gstring = get_gstring (frame, mt, from, to, control);
2739 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2741 if (g->type == GLYPH_BOX
2742 || g->pos < from || g->pos >= to)
2744 if (g->type == GLYPH_PAD)
2746 if (g->left_padding)
2747 pad_width = g->width;
2751 glyphs[-1].x_advance += g->width;
2757 glyphs->from = g->pos;
2759 glyphs->glyph_code = g->code;
2760 glyphs->x_off = g->xoff + pad_width;
2761 glyphs->y_off = g->yoff;
2762 glyphs->lbearing = g->lbearing;
2763 glyphs->rbearing = g->rbearing;
2764 glyphs->ascent = g->ascent;
2765 glyphs->descent = g->descent;
2766 glyphs->x_advance = g->width + pad_width;
2767 glyphs->y_advance = 0;
2768 if (g->rface->rfont)
2770 glyphs->font = &g->rface->rfont->font;
2771 glyphs->font_type = g->rface->rfont->type;
2772 glyphs->fontp = g->rface->rfont->fontp;
2776 glyphs->font = NULL;
2777 glyphs->font_type = Mnil;
2778 glyphs->fontp = NULL;
2785 M17N_OBJECT_UNREF (gstring->top);
2787 *num_glyphs_return = n;
2788 return (n <= array_size ? 0 : -1);
2794 @brief Draw one or more textitems.
2796 The mdraw_text_items () function draws one or more M-texts on
2797 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2798 of the textitems to be drawn and $NITEMS is the number of
2799 textimtems in the array. */
2802 @brief textitem ¤òɽ¼¨¤¹¤ë.
2804 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2805 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2806 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2809 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2813 MTextItem, mdraw_text (). */
2816 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2817 MDrawTextItem *items, int nitems)
2819 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2821 while (nitems-- > 0)
2824 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2826 mdraw_text_with_control (frame, win, x, y,
2827 items->mt, 0, mtext_nchars (items->mt),
2829 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2830 items->control, NULL, NULL, NULL);
2833 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2839 @brief calculate a line breaking position.
2841 The function mdraw_default_line_break () calculates a line
2842 breaking position based on the line number $LINE and the
2843 coordinate $Y, when a line is too long to fit within the width
2844 limit. $POS is the position of the character next to the last
2845 one that fits within the limit. $FROM is the position of the
2846 first character of the line, and TO is the position of the last
2847 character displayed on the line if there were not width limit.
2848 LINE and Y are reset to 0 when a line is broken by a newline
2849 character, and incremented each time when a long line is broken
2850 because of the width limit.
2853 This function returns a character position to break the
2858 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2860 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2861 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2862 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2863 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2864 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2865 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2866 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2869 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2873 mdraw_default_line_break (MText *mt, int pos,
2874 int from, int to, int line, int y)
2876 int c = mtext_ref_char (mt, pos);
2879 if (c == ' ' || c == '\t')
2883 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2890 if (c == ' ' || c == '\t')
2893 c = mtext_ref_char (mt, pos);
2906 @brief Obtain per character dimension information.
2908 The mdraw_per_char_extents () function computes the text dimension
2909 of each character in M-text $MT. The faces given as text
2910 properties in $MT and the default face of frame $FRAME determine
2911 the fonts to draw the text. Each successive element in
2912 $ARRAY_RETURN is set to the drawn metrics of successive
2913 characters, which is relative to the origin of the drawing, and a
2914 rectangle for each character in $MT. The number of elements of
2915 $ARRAY_RETURN must be equal to or greater than the number of
2918 If pointer $OVERALL_RETURN is not @c NULL, this function also
2919 computes the extents of the overall text and stores the results in
2920 the members of the structure pointed to by $OVERALL_RETURN. */
2923 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2925 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2926 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2927 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2928 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2929 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2930 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2933 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2934 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2937 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2940 mdraw_per_char_extents (MFrame *frame, MText *mt,
2941 MDrawMetric *array_return,
2942 MDrawMetric *overall_return)
2944 int n = mtext_nchars (mt);
2946 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2947 n, &n, overall_return, NULL);
2951 @brief clear cached information.
2953 The mdraw_clear_cache () function clear cached information
2954 on M-text $MT that was attached by any of the drawing functions.
2955 When the behaviour of `format' or `line_break'
2956 member functions of MDrawControl is changed, the cache must be cleared.
2961 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2963 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2964 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2965 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2966 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2971 mdraw_clear_cache (MText *mt)
2973 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);