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 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
509 int g_physical_ascent, g_physical_descent;
510 int g_width, g_lbearing, g_rbearing;
511 MGlyph *g = MGLYPH (from);
512 MGlyph *last_g = MGLYPH (to);
515 g_physical_ascent = gstring->physical_ascent;
516 g_physical_descent = gstring->physical_descent;
517 g_width = g_lbearing = g_rbearing = 0;
519 for (i = from; i < to;)
521 if ( MGLYPH (i)->otf_encoded)
527 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
528 mfont__get_metric (gstring, j, i);
536 MRealizedFont *rfont = base->rface->rfont;
537 int size = rfont->font.property[MFONT_SIZE];
538 int width, lbearing, rbearing;
540 if (g == last_g || ! g->combining_code)
543 if (base->width == 0 && ! base->left_padding && ! base->right_padding
544 && GLYPH_INDEX (base) > from)
546 MGlyph *prev = base - 1;
548 if (base->pos < prev->pos)
549 prev->pos = base->pos;
551 base->pos = prev->pos;
552 if (base->to > prev->to)
558 if (base->left_padding && base->lbearing < 0)
560 base->xoff = - base->lbearing;
561 base->width += base->xoff;
562 base->rbearing += base->xoff;
565 if (base->right_padding && base->rbearing > base->width)
567 base->width = base->rbearing;
569 lbearing = (base->xoff + base->lbearing < 0
570 ? base->xoff + base->lbearing : 0);
571 rbearing = base->xoff + base->rbearing;
575 /* With combining glyphs. */
576 int left = -base->width;
578 int top = - base->ascent;
579 int bottom = base->descent;
580 int height = bottom - top;
581 int begin = base->pos;
586 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
587 rbearing = base->rbearing;
589 while (g != last_g && g->combining_code)
591 int combining_code = g->combining_code;
595 else if (end < g->to)
598 if (! COMBINING_PRECOMPUTED_P (combining_code))
600 int base_x, base_y, add_x, add_y, off_x, off_y;
602 if (COMBINING_BY_CLASS_P (combining_code))
603 g->combining_code = combining_code
604 = combining_code_from_class (COMBINING_CODE_CLASS
607 rfont = g->rface->rfont;
608 size = rfont->font.property[MFONT_SIZE];
609 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
611 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
613 base_x = COMBINING_CODE_BASE_X (combining_code);
614 base_y = COMBINING_CODE_BASE_Y (combining_code);
615 add_x = COMBINING_CODE_ADD_X (combining_code);
616 add_y = COMBINING_CODE_ADD_Y (combining_code);
618 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
621 if (g->xoff + g->width > right)
622 right = g->xoff + g->width;
623 width = right - left;
626 g->yoff = top + height * base_y / 2;
630 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
634 if (g->xoff + g->lbearing < left + lbearing)
635 lbearing = g->xoff + g->lbearing - left;
636 if (g->xoff + g->rbearing > left + rbearing)
637 rbearing = g->xoff + g->rbearing - left;
638 if (g->yoff - g->ascent < top)
639 top = g->yoff - g->ascent;
640 if (g->yoff + g->descent > bottom)
641 bottom = g->yoff + g->descent;
642 height = bottom - top;
648 base->ascent = - top;
649 base->descent = bottom;
650 base->lbearing = lbearing;
651 base->rbearing = rbearing;
652 if (left < - base->width)
654 base->xoff = - base->width - left;
655 base->width += base->xoff;
656 base->rbearing += base->xoff;
657 base->lbearing += base->xoff;
661 base->width += right;
662 base->rbearing += right;
663 base->right_padding = 1;
664 for (i = 1; base + i != g; i++)
665 base[i].xoff -= right;
668 for (i = 0; base + i != g; i++)
675 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
676 g_physical_descent = MAX (g_physical_descent, base->descent);
677 g_lbearing = MIN (g_lbearing, g_width + lbearing);
678 g_rbearing = MAX (g_rbearing, g_width + rbearing);
679 g_width += base->width;
682 gstring->physical_ascent = g_physical_ascent;
683 gstring->physical_descent = g_physical_descent;
684 gstring->sub_width = g_width;
685 gstring->sub_lbearing = g_lbearing;
686 gstring->sub_rbearing = g_rbearing;
690 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
691 by this function directly. Character glyphs are handled by
692 layouter functions registered in font drivers.
694 This function fill-in all the remaining members of glyphs. */
697 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
699 /* Default width of TAB. */
700 int tab_width = frame->space_width * (gstring->control.tab_width
701 ? gstring->control.tab_width : 8);
705 MDrawControl *control = &(gstring->control);
708 int box_line_height = 0;
709 int ignore_formatting_char = control->ignore_formatting_char;
711 gstring->ascent = gstring->descent = 0;
712 gstring->physical_ascent = gstring->physical_descent = 0;
713 gstring->width = gstring->lbearing = gstring->rbearing = 0;
717 while (g->type != GLYPH_ANCHOR)
719 if (box != g->rface->box)
721 int gidx = GLYPH_INDEX (g);
725 /* Insert the right side of the box. That glyph belongs
726 to the previous grapheme cluster. */
727 MGlyph box_glyph = g[-1];
729 box_glyph.type = GLYPH_BOX;
731 = (control->fixed_width
733 : box->inner_hmargin + box->width + box->outer_hmargin);
734 box_glyph.lbearing = 0;
735 box_glyph.rbearing = box_glyph.width;
737 box_glyph.right_padding = 1;
738 gstring->width += box_glyph.width;
739 gstring->rbearing += box_glyph.width;
740 INSERT_GLYPH (gstring, gidx, box_glyph);
747 /* Insert the left side of the box. That glyph belongs
748 to the following grapheme cluster. */
749 MGlyph box_glyph = *g;
750 int box_height = (box->width
751 + box->inner_vmargin + box->outer_vmargin);
753 if (box_line_height < box_height)
754 box_line_height = box_height;
755 box_glyph.type = GLYPH_BOX;
757 = (control->fixed_width
759 : box->inner_hmargin + box->width + box->outer_hmargin);
760 box_glyph.lbearing = 0;
761 box_glyph.rbearing = box_glyph.width;
763 box_glyph.left_padding = 1;
764 gstring->width += box_glyph.width;
765 gstring->rbearing += box_glyph.width;
766 INSERT_GLYPH (gstring, gidx, box_glyph);
772 if (g->category == McatCf && ignore_formatting_char)
773 g->type = GLYPH_SPACE;
775 if (g->type == GLYPH_CHAR)
777 MRealizedFace *rface = g->rface;
778 MRealizedFont *rfont = rface->rfont;
780 int from = GLYPH_INDEX (g);
782 for (g++; g->type == GLYPH_CHAR; g++)
783 if (! rfont != ! g->rface->rfont
784 || box != g->rface->box
785 || ((fromg->code == MCHAR_INVALID_CODE)
786 != (g->code == MCHAR_INVALID_CODE))
787 || (g->category == McatCf && ignore_formatting_char))
789 if (rfont && fromg->code != MCHAR_INVALID_CODE)
792 int to = GLYPH_INDEX (g);
794 layout_glyphs (frame, gstring, from, to);
795 extra_width = - gstring->sub_lbearing;
797 && ! control->disable_overlapping_adjustment
798 && (! control->orientation_reversed
799 ? ((to > 1 || control->align_head)
800 && g->type != GLYPH_ANCHOR)
801 : (((g->type && GLYPH_ANCHOR) || control->align_head)
806 pad.type = GLYPH_PAD;
809 pad.width = pad.rbearing = extra_width;
810 pad.left_padding = 1;
811 INSERT_GLYPH (gstring, from, pad);
813 gstring->sub_lbearing = 0;
814 gstring->sub_width += extra_width;
815 gstring->sub_rbearing += extra_width;
817 g = MGLYPH (from - 1);
818 if (g->type == GLYPH_SPACE)
820 /* The pad just inserted is absorbed (maybe
821 partially) by the previous space while
822 keeping at least some space width. For the
823 moment, we use the arbitrary width 2-pixel.
824 Perhaps, it should be decided by the current
825 face, or a default value of the current
826 frame, which is, however, not yet
828 if (extra_width + 2 < g->width)
830 g->width -= extra_width;
834 extra_width = g->width - 2;
837 gstring->width -= extra_width;
838 gstring->rbearing -= extra_width;
843 extra_width = gstring->sub_rbearing - gstring->sub_width;
845 && ! control->disable_overlapping_adjustment
846 && (GLYPH_INDEX (g) < gstring->used - 1
847 || (control->orientation_reversed && control->align_head)))
849 if (g->type == GLYPH_SPACE && box == g->rface->box)
852 pad.type = GLYPH_PAD;
855 pad.width = pad.rbearing = extra_width;
856 INSERT_GLYPH (gstring, to, pad);
861 g[-1].width += extra_width;
862 gstring->sub_width += extra_width;
865 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
866 gstring->lbearing = gstring->width + gstring->sub_lbearing;
867 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
868 gstring->rbearing = gstring->width + gstring->sub_rbearing;
869 gstring->width += gstring->sub_width;
870 if (gstring->ascent < rface->ascent)
871 gstring->ascent = rface->ascent;
872 if (gstring->descent < rface->descent)
873 gstring->descent = rface->descent;
877 for (; fromg < g; fromg++)
879 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
880 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
881 fromg->width = fromg->rbearing = 1;
883 fromg->width = fromg->rbearing = rface->space_width;
884 fromg->xoff = fromg->lbearing = 0;
885 fromg->ascent = fromg->descent = 0;
886 gstring->width += fromg->width;
887 gstring->rbearing += fromg->width;
889 if (gstring->ascent < frame->rface->ascent)
890 gstring->ascent = frame->rface->ascent;
891 if (gstring->descent < frame->descent)
892 gstring->descent = frame->rface->descent;
895 else if (g->type == GLYPH_SPACE)
898 g->width = g->rface->space_width;
899 else if (g->c == '\n')
901 g->width = control->cursor_width;
904 if (control->cursor_bidi)
906 else if (g->width < 0)
907 g->width = g->rface->space_width;
910 else if (g->c == '\t')
912 g->width = tab_width - ((gstring->indent + gstring->width)
918 if (g[-1].type == GLYPH_PAD)
920 /* This space glyph absorbs (maybe partially) the
921 previous padding glyph. */
922 g->width -= g[-1].width;
924 /* But, keep at least some space width. For the
925 moment, we use the arbitrary width 2-pixel. */
928 g->rbearing = g->width;
929 gstring->width += g->width;
930 gstring->rbearing += g->width;
933 if (gstring->ascent < g->rface->ascent)
934 gstring->ascent = g->rface->ascent;
935 if (gstring->descent < g->rface->descent)
936 gstring->descent = g->rface->descent;
942 gstring->width += g->width;
943 gstring->rbearing += g->width;
950 /* Insert the right side of the box. */
951 int gidx = GLYPH_INDEX (g);
952 MGlyph box_glyph = g[-1];
954 box_glyph.type = GLYPH_BOX;
956 = (control->fixed_width
958 : box->inner_hmargin + box->width + box->outer_hmargin);
959 box_glyph.lbearing = 0;
960 box_glyph.rbearing = box_glyph.width;
962 box_glyph.right_padding = 1;
963 gstring->width += box_glyph.width;
964 gstring->rbearing += box_glyph.width;
965 INSERT_GLYPH (gstring, gidx, box_glyph);
968 gstring->text_ascent = gstring->ascent;
969 gstring->text_descent = gstring->descent;
970 if (gstring->text_ascent < gstring->physical_ascent)
971 gstring->text_ascent = gstring->physical_ascent;
972 if (gstring->text_descent < gstring->physical_descent)
973 gstring->text_descent = gstring->physical_descent;
974 gstring->line_ascent = gstring->text_ascent;
975 gstring->line_descent = gstring->text_descent;
976 if (box_line_height > 0)
978 gstring->line_ascent += box_line_height;
979 gstring->physical_ascent = gstring->line_ascent;
980 gstring->line_descent += box_line_height;
981 gstring->physical_descent = gstring->line_descent;
984 if (gstring->line_ascent < control->min_line_ascent)
985 gstring->line_ascent = control->min_line_ascent;
986 else if (control->max_line_ascent
987 && control->max_line_ascent > control->min_line_ascent
988 && gstring->line_ascent > control->max_line_ascent)
989 gstring->line_ascent = control->max_line_ascent;
991 if (gstring->line_descent < control->min_line_descent)
992 gstring->line_descent = control->min_line_descent;
993 else if (control->max_line_descent
994 && control->max_line_descent > control->min_line_descent
995 && gstring->line_descent > control->max_line_descent)
996 gstring->line_descent = control->max_line_descent;
997 gstring->height = gstring->line_ascent + gstring->line_descent;
999 if (control->orientation_reversed
1002 /* We must adjust TAB width for RTL orientation. */
1003 width = gstring->indent;
1005 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1007 if (g->type == GLYPH_CHAR && g->c == '\t')
1009 int this_width = tab_width - (width % tab_width);
1011 if (g[1].type == GLYPH_PAD)
1012 this_width -= g[1].width;
1013 if (g[-1].type == GLYPH_PAD)
1014 this_width -= g[-1].width;
1017 gstring->width += this_width - g->width;
1018 gstring->rbearing += this_width - g->width;
1019 g->width = this_width;
1020 width += this_width;
1030 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1031 MGlyphString *gstring, int from, int to,
1032 int *from_idx, int *to_idx, int *to_x)
1034 MGlyph *g = MGLYPH (1);
1035 MDrawRegion region = (MDrawRegion) NULL;
1036 MDrawControl *control = &gstring->control;
1037 int cursor_pos = -1;
1039 int cursor_bidi = control->cursor_bidi;
1041 if (control->with_cursor && control->cursor_width)
1043 if (gstring->from <= control->cursor_pos
1044 && gstring->to > control->cursor_pos)
1045 cursor_pos = control->cursor_pos;
1048 && gstring->from <= control->cursor_pos - 1
1049 && gstring->to > control->cursor_pos - 1)
1050 prev_pos = control->cursor_pos - 1;
1053 *from_idx = *to_idx = 0;
1054 while (g->type != GLYPH_ANCHOR)
1056 if (g->pos >= from && g->pos < to)
1058 MGlyph *fromg = g, *cursor = NULL;
1059 MRealizedFace *rface = g->rface;
1061 int cursor_width = 0;
1065 *from_idx = GLYPH_INDEX (g);
1066 while (g->pos >= from && g->pos < to
1067 && g->rface == rface)
1070 if (g->type != GLYPH_BOX
1071 && g->pos <= cursor_pos && g->to > cursor_pos)
1074 cursor = g, cursor_x = x + width;
1075 cursor_width += g->width;
1077 width += g++->width;
1080 && (control->as_image
1081 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1083 int this_x = x, this_width = width;
1085 if (fromg->type == GLYPH_BOX)
1086 this_x += fromg->width, this_width -= fromg->width;
1087 if (g[-1].type == GLYPH_BOX)
1088 this_width -= g[-1].width;
1089 (frame->driver->fill_space)
1090 (frame, win, rface, 0,
1091 this_x, y - gstring->text_ascent, this_width,
1092 gstring->text_ascent + gstring->text_descent,
1093 control->clip_region);
1100 rect.y = y - gstring->text_ascent;
1101 rect.height = gstring->text_ascent + gstring->text_descent;
1104 rect.width = ((control->cursor_width > 0
1105 && control->cursor_width < cursor_width)
1106 ? control->cursor_width : cursor_width);
1110 if (cursor->bidi_level % 2)
1111 rect.x += cursor_width - rect.width;
1112 (*frame->driver->fill_space)
1113 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1114 control->clip_region);
1116 region = (*frame->driver->region_from_rect) (&rect);
1118 (*frame->driver->region_add_rect) (region, &rect);
1121 if (cursor->bidi_level % 2)
1124 rect.width = cursor_width < 4 ? cursor_width : 4;
1125 (*frame->driver->fill_space)
1126 (frame, win, rface, 1,
1127 rect.x, rect.y, rect.width, rect.height,
1128 control->clip_region);
1129 (*frame->driver->region_add_rect) (region, &rect);
1141 if (fromg->type != GLYPH_BOX
1142 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1145 cursor = fromg, cursor_x = x + temp_width;
1146 cursor_width += fromg->width;
1148 temp_width += fromg++->width;
1155 if (! (cursor->bidi_level % 2))
1156 rect.x += cursor_width - 1;
1157 rect.y = y - gstring->text_ascent;
1158 rect.height = gstring->text_ascent + gstring->text_descent;
1160 (*frame->driver->fill_space)
1161 (frame, win, rface, 1,
1162 rect.x, rect.y, rect.width, rect.height,
1163 control->clip_region);
1165 region = (*frame->driver->region_from_rect) (&rect);
1167 (*frame->driver->region_add_rect) (region, &rect);
1168 rect.y += rect.height - 2;
1170 rect.width = cursor_width < 4 ? cursor_width : 4;
1171 if (! (cursor->bidi_level % 2))
1172 rect.x -= rect.width - 1;
1173 (*frame->driver->fill_space) (frame, win, rface, 1,
1174 rect.x, rect.y, rect.width, rect.height,
1175 control->clip_region);
1176 (*frame->driver->region_add_rect) (region, &rect);
1180 *to_idx = GLYPH_INDEX (g);
1190 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1191 MGlyphString *gstring, int from_idx, int to_idx,
1192 int reverse, MDrawRegion region)
1194 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1200 (*frame->driver->region_to_rect) (region, &rect);
1203 while (g != gend && x + g->rbearing <= rect.x)
1206 width -= g++->width;
1207 while (! g->enabled && g != gend)
1211 rect.x += rect.width;
1212 if (rect.x < x + width)
1215 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1217 width -= (--gend)->width;
1218 while (! gend->enabled && g != gend)
1222 while (gend[-1].to == gend->to) gend++;
1230 MRealizedFace *rface = g->rface;
1231 int width = g->width;
1232 MGlyph *from_g = g++;
1234 /* Handle the glyphs of the same type/face at once. */
1236 && g->type == from_g->type
1237 && g->rface == rface
1238 && ((g->code == MCHAR_INVALID_CODE)
1239 == (from_g->code == MCHAR_INVALID_CODE))
1241 width += g++->width;
1243 if (from_g->type == GLYPH_CHAR)
1245 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1246 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1249 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1252 else if (from_g->type == GLYPH_BOX)
1254 /* Draw the left or right side of a box. If
1255 from_g->lbearing is nonzero, this is the left side,
1256 else this is the right side. */
1257 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1260 if (from_g->type != GLYPH_BOX)
1263 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1264 x, y, width, region);
1267 /* Draw the top and bottom side of a box. */
1268 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1269 x, y, width, region);
1280 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1281 int *from_x, int *to_x)
1284 int left_idx = *left, right_idx = *right;
1285 int left_x, right_x, x;
1287 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1290 if (x + g->rbearing > 0)
1292 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1294 left_idx = GLYPH_INDEX (g);
1299 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1302 if (x - g->width + g->lbearing < 0)
1304 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1306 right_idx = GLYPH_INDEX (g) + 1;
1311 if (*left == left_idx && *right == right_idx)
1314 if (*left != left_idx)
1316 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1321 if (*right != right_idx)
1323 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1333 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1338 if (from <= gstring->from && to >= gstring->to)
1341 *rbearing = gstring->rbearing;
1342 return gstring->width;
1347 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1348 if (g->pos >= from && g->pos < to)
1350 if (rbearing && width + g->rbearing > *rbearing)
1351 *rbearing = width + g->rbearing;
1359 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1360 MGlyphString *gstring, int from, int to)
1362 MDrawControl *control = &gstring->control;
1364 MDrawRegion clip_region, cursor_region;
1365 int from_idx, to_idx;
1368 if (control->orientation_reversed)
1369 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1371 x += gstring->indent;
1373 /* At first, draw all glyphs without cursor. */
1374 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1375 &from_idx, &to_idx, &to_x);
1377 if (control->partial_update)
1380 rect.width = to_x - x;
1381 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1383 rect.y = y - gstring->line_ascent;
1384 rect.height = gstring->height;
1385 clip_region = (*frame->driver->region_from_rect) (&rect);
1386 if (control->clip_region)
1387 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1390 clip_region = control->clip_region;
1393 clip_region = control->clip_region;
1395 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1400 (*frame->driver->intersect_region) (cursor_region, clip_region);
1401 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1404 if (clip_region != control->clip_region)
1405 (*frame->driver->free_region) (clip_region);
1407 (*frame->driver->free_region) (cursor_region);
1411 static int gstring_num;
1414 free_gstring (void *object)
1416 MGlyphString *gstring = (MGlyphString *) object;
1419 free_gstring (gstring->next);
1420 if (gstring->size > 0)
1421 free (gstring->glyphs);
1427 static MGlyphString scratch_gstring;
1429 static MGlyphString *
1430 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1433 MGlyphString *gstring;
1435 if (pos == mt->nchars)
1437 gstring = &scratch_gstring;
1441 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1442 MLIST_INIT1 (gstring, glyphs, 128);
1446 gstring->frame = frame;
1447 gstring->tick = frame->tick;
1448 gstring->top = gstring;
1450 gstring->control = *control;
1451 gstring->indent = gstring->width_limit = 0;
1452 if (control->format)
1453 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1455 gstring->width_limit = control->max_line_width;
1456 gstring->anti_alias = control->anti_alias;
1460 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1463 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1471 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1472 a width of glyphs for the character at I of GSTRING->mt. If I is
1473 not a beginning of a grapheme cluster, the corresponding element
1475 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1476 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1477 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1478 pos_width[g->pos - gstring->from] += g->width;
1479 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1481 if (pos_width[i] > 0)
1483 if (width + pos_width[i] > gstring->width_limit)
1486 width += pos_width[i];
1489 pos = gstring->from + i;
1490 if (gstring->control.line_break)
1492 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1493 gstring->from, gstring->to, 0, 0);
1494 if (pos <= gstring->from)
1495 pos = gstring->from + 1;
1496 else if (pos >= gstring->to)
1501 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1502 layout_glyph_string (frame, gstring);
1506 /* Return a gstring that covers a character at POS. */
1508 static MGlyphString *
1509 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1511 MGlyphString *gstring = NULL;
1513 if (pos < mtext_nchars (mt))
1515 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1518 && ((prop->start != 0
1519 && mtext_ref_char (mt, prop->start - 1) != '\n')
1520 || (prop->end < mtext_nchars (mt)
1521 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1523 mtext_detach_property (prop);
1528 gstring = prop->val;
1529 if (gstring->frame != frame
1530 || gstring->tick != frame->tick
1531 || memcmp (control, &gstring->control,
1532 (char *) (&control->with_cursor)
1533 - (char *) (control))
1534 || control->cursor_width != gstring->control.cursor_width
1535 || control->cursor_bidi != gstring->control.cursor_bidi)
1537 mtext_detach_property (prop);
1542 else if (! control->cursor_width)
1550 offset = mtext_character (mt, pos, 0, '\n');
1555 offset -= gstring->from;
1557 for (gst = gstring; gst; gst = gst->next)
1561 gst->from += offset;
1563 for (i = 0; i < gst->used; i++)
1565 gst->glyphs[i].pos += offset;
1566 gst->glyphs[i].to += offset;
1569 M17N_OBJECT_REF (gstring);
1574 int line = 0, y = 0;
1576 beg = mtext_character (mt, pos, 0, '\n');
1581 end = mtext_nchars (mt) + (control->cursor_width != 0);
1583 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1584 compose_glyph_string (frame, mt, beg, end, gstring);
1585 layout_glyph_string (frame, gstring);
1587 if (gstring->width_limit
1588 && gstring->width > gstring->width_limit)
1590 MGlyphString *gst = gstring;
1592 truncate_gstring (frame, mt, gst);
1593 while (gst->to < end)
1595 line++, y += gst->height;
1596 gst->next = alloc_gstring (frame, mt, gst->from, control,
1598 gst->next->top = gstring;
1599 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1601 layout_glyph_string (frame, gst);
1602 if (gst->width <= gst->width_limit)
1604 truncate_gstring (frame, mt, gst);
1608 if (! control->disable_caching && pos < mtext_nchars (mt))
1610 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1611 MTEXTPROP_VOLATILE_STRONG);
1613 if (end > mtext_nchars (mt))
1614 end = mtext_nchars (mt);
1615 mtext_attach_property (mt, beg, end, prop);
1616 M17N_OBJECT_UNREF (prop);
1620 while (gstring->to <= pos)
1622 if (! gstring->next)
1624 gstring = gstring->next;
1626 gstring->control = *control;
1632 static MDrawControl control_noop;
1634 #define ASSURE_CONTROL(control) \
1636 control = &control_noop; \
1641 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1642 MText *mt, int from, int to,
1643 MDrawControl *control)
1645 MGlyphString *gstring;
1647 M_CHECK_POS_X (mt, from, -1);
1648 ASSURE_CONTROL (control);
1649 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1650 to = mtext_nchars (mt) + (control->cursor_width != 0);
1654 gstring = get_gstring (frame, mt, from, to, control);
1656 MERROR (MERROR_DRAW, -1);
1657 render_glyph_string (frame, win, x, y, gstring, from, to);
1661 y += gstring->line_descent;
1662 M17N_OBJECT_UNREF (gstring->top);
1663 gstring = get_gstring (frame, mt, from, to, control);
1664 y += gstring->line_ascent;
1665 render_glyph_string (frame, win, x, y, gstring, from, to);
1668 M17N_OBJECT_UNREF (gstring->top);
1675 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1681 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1682 if (g->pos <= pos && g->to > pos)
1687 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1688 if (g->pos <= pos && g->to > pos)
1695 /* for debugging... */
1699 dump_combining_code (int code)
1701 char *vallign = "tcbB";
1702 char *hallign = "lcr";
1708 if (COMBINING_BY_CLASS_P (code))
1709 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1710 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1711 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1712 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1713 off_x = COMBINING_CODE_OFF_X (code) - 128;
1715 sprintf (work + 2, "+%d", off_y);
1717 sprintf (work + 2, "%d", off_y);
1718 else if (off_x == 0)
1719 sprintf (work + 2, ".");
1720 p = work + strlen (work);
1722 sprintf (p, ">%d", off_x);
1724 sprintf (p, "<%d", -off_x);
1726 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1727 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1733 dump_gstring (MGlyphString *gstring, int indent)
1735 char *prefix = (char *) alloca (indent + 1);
1736 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1738 memset (prefix, 32, indent);
1741 fprintf (stderr, "(glyph-string");
1743 for (g = MGLYPH (0); g < last_g; g++)
1745 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1747 g - gstring->glyphs,
1748 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1749 : g->type == GLYPH_ANCHOR ? "ANC"
1750 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1751 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1752 dump_combining_code (g->combining_code),
1753 g->width, g->bidi_level);
1754 fprintf (stderr, ")");
1758 /* m17n-X internal APIs */
1763 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1765 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1766 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1768 Minherited = msymbol ("inherited");
1770 McatCc = msymbol ("Cc");
1771 McatCf = msymbol ("Cf");
1773 MbidiR = msymbol ("R");
1774 MbidiAL = msymbol ("AL");
1775 MbidiRLE = msymbol ("RLE");
1776 MbidiRLO = msymbol ("RLO");
1777 MbidiBN = msymbol ("BN");
1778 MbidiS = msymbol ("S");
1780 fribidi_set_mirroring (TRUE);
1789 MLIST_FREE1 (&scratch_gstring, glyphs);
1793 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1797 /*** @addtogroup m17nDraw */
1802 @brief Draw an M-text on a window.
1804 The mdraw_text () function draws the text between $FROM and $TO of
1805 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1807 The appearance of the text (size, style, color, etc) is specified
1808 by the value of the text property whose key is @c Mface. If the
1809 M-text or a part of the M-text does not have such a text property,
1810 the default face of $FRAME is used.
1812 The font used to draw a character in the M-text is selected from
1813 the value of the fontset property of a face by the following
1818 <li> Search the text properties given to the character for the one
1819 whose key is @c Mcharset; its value should be either a symbol
1820 specifying a charset or #Mnil. If the value is #Mnil,
1821 proceed to the next step.
1823 Otherwise, search the mapping table of the fontset for the
1824 charset. If no entry is found proceed to the next step.
1826 If an entry is found, use one of the fonts in the entry that
1827 has a glyph for the character and that matches best with the
1828 face properties. If no such font exists, proceed to the next
1831 <li> Get the character property "script" of the character. If it is
1832 inherited, get the script property from the previous
1833 characters. If there is no previous character, or none of
1834 them has the script property other than inherited, proceed to
1837 Search the text properties given to the character for the one
1838 whose key is @c Mlanguage; its value should be either a
1839 symbol specifying a language or @c Mnil.
1841 Search the mapping table of the fontset for the combination
1842 of the script and language. If no entry is found, proceed to
1845 If an entry is found, use one of the fonts in the entry that
1846 has a glyph for the character and that matches best with the
1847 face properties. If no such font exists, proceed to the next
1850 <li> Search the fall-back table of the fontset for a font that has
1851 a glyph of the character. If such a font is found, use that
1856 If no font is found by the algorithm above, this function draws an
1857 empty box for the character.
1859 This function draws only the glyph foreground. To specify the
1860 background color, use mdraw_image_text () or
1861 mdraw_text_with_control ().
1863 This function is the counterpart of <tt>XDrawString ()</tt>,
1864 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1865 in the X Window System.
1868 If the operation was successful, mdraw_text () returns 0. If an
1869 error is detected, it returns -1 and assigns an error code to the
1870 external variable #merror_code. */
1872 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1874 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1875 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1878 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1879 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1880 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1881 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1883 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1884 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1888 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1889 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1890 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1891 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1892 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1895 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1896 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1897 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1900 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1901 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1902 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1903 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1905 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1906 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1909 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1910 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1913 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1914 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1915 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1918 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1919 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1923 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1924 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1926 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1927 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1930 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1931 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1934 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1935 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1937 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1944 mdraw_image_text () */
1947 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1948 MText *mt, int from, int to)
1950 MDrawControl control;
1952 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1953 memset (&control, 0, sizeof control);
1954 control.as_image = 0;
1955 return draw_text (frame, win, x, y, mt, from, to, &control);
1962 @brief Draw an M-text on a window as an image.
1964 The mdraw_image_text () function draws the text between $FROM and
1965 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1966 coordinate ($X, $Y).
1968 The way to draw a text is the same as in mdraw_text () except that
1969 this function also draws the background with the color specified
1972 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1973 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1974 functions in the X Window System.
1977 If the operation was successful, mdraw_image_text () returns 0.
1978 If an error is detected, it returns -1 and assigns an error code
1979 to the external variable #merror_code. */
1982 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1984 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1985 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1988 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1989 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1991 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1992 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1996 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1997 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
2000 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2010 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2011 MText *mt, int from, int to)
2013 MDrawControl control;
2015 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2016 memset (&control, 0, sizeof control);
2017 control.as_image = 1;
2018 return draw_text (frame, win, x, y, mt, from, to, &control);
2024 @brief Draw an M-text on a window with fine control.
2026 The mdraw_text_with_control () function draws the text between
2027 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2028 coordinate ($X, $Y).
2030 The way to draw a text is the same as in mdraw_text () except that
2031 this function also follows what specified in the drawing control
2034 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2035 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2036 breaks lines and the following characters are drawn in the next
2037 line. See the documentation of the structure @ MDrawControl for
2041 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2043 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2044 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2047 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2048 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2050 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2051 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2052 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2056 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2057 MText *mt, int from, int to, MDrawControl *control)
2059 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2060 return draw_text (frame, win, x, y, mt, from, to, control);
2066 @brief Compute text pixel width.
2068 The mdraw_text_extents () function computes the width of text
2069 between $FROM and $TO of M-text $MT when it is drawn on a window
2070 of frame $FRAME using the mdraw_text_with_control () function with
2071 the drawing control object $CONTROL.
2073 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2074 the bounding box of character ink of the M-text, and stores the
2075 results in the members of the structure pointed to by
2076 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2077 surrounding box, the box is included in the bounding box.
2079 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2080 computes the bounding box that provides mininum spacing to other
2081 graphical features (such as surrounding box) for the M-text, and
2082 stores the results in the members of the structure pointed to by
2083 $OVERALL_LOGICAL_RETURN.
2085 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2086 computes the bounding box that provides mininum spacing to the
2087 other M-text drawn, and stores the results in the members of the
2088 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2089 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2090 min_line_ascent, min_line_descent, max_line_ascent, and
2091 max_line_descent of $CONTROL are all zero.
2094 This function returns the width of the text to be drawn in the
2095 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2096 text is drawn in multiple physical lines, it returns the width of
2097 the widest line. If an error occurs, it returns -1 and assigns an
2098 error code to the external variable #merror_code. */
2102 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2104 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2105 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2106 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2108 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2109 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2110 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2111 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2113 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2114 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2115 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2116 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2118 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2119 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2120 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2121 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2122 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2123 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2125 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2126 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2127 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2128 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2130 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2137 mdraw_text_extents (MFrame *frame,
2138 MText *mt, int from, int to, MDrawControl *control,
2139 MDrawMetric *overall_ink_return,
2140 MDrawMetric *overall_logical_return,
2141 MDrawMetric *overall_line_return)
2143 MGlyphString *gstring;
2145 int width, rbearing;
2147 ASSURE_CONTROL (control);
2148 M_CHECK_POS_X (mt, from, -1);
2149 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2150 to = mtext_nchars (mt) + (control->cursor_width != 0);
2154 gstring = get_gstring (frame, mt, from, to, control);
2156 MERROR (MERROR_DRAW, -1);
2157 width = gstring_width (gstring, from, to, &rbearing);
2158 if (overall_ink_return)
2160 overall_ink_return->y = - gstring->physical_ascent;
2161 overall_ink_return->x = gstring->lbearing;
2163 if (overall_logical_return)
2165 overall_logical_return->y = - gstring->ascent;
2166 overall_logical_return->x = 0;
2168 if (overall_line_return)
2170 overall_line_return->y = - gstring->line_ascent;
2171 overall_line_return->x = gstring->lbearing;
2174 for (from = gstring->to; from < to; from = gstring->to)
2176 int this_width, this_rbearing;
2178 y += gstring->line_descent;
2179 M17N_OBJECT_UNREF (gstring->top);
2180 gstring = get_gstring (frame, mt, from, to, control);
2181 this_width = gstring_width (gstring, from, to, &this_rbearing);
2182 y += gstring->line_ascent;
2183 if (width < this_width)
2185 if (rbearing < this_rbearing)
2186 rbearing = this_rbearing;
2188 if (overall_ink_return)
2190 overall_ink_return->width = rbearing;
2191 overall_ink_return->height
2192 = y + gstring->physical_descent - overall_ink_return->y;
2194 if (overall_logical_return)
2196 overall_logical_return->width = width;
2197 overall_logical_return->height
2198 = y + gstring->descent - overall_logical_return->y;
2200 if (overall_line_return)
2202 overall_line_return->width = MAX (width, rbearing);
2203 overall_line_return->height
2204 = y + gstring->line_descent - overall_line_return->y;
2207 M17N_OBJECT_UNREF (gstring->top);
2214 @brief Compute the text dimensions of each character of M-text.
2216 The mdraw_text_per_char_extents () function computes the drawn
2217 metric of each character between $FROM and $TO of M-text $MT
2218 assuming that they are drawn on a window of frame $FRAME using the
2219 mdraw_text_with_control () function with the drawing control
2222 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2223 $LOGICAL_ARRAY_RETURN. Each successive element of
2224 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2225 ink and logical metrics of successive characters respectively,
2226 relative to the drawing origin of the M-text. The number of
2227 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2228 been set is returned to $NUM_CHARS_RETURN.
2230 If $ARRAY_SIZE is too small to return all metrics, the function
2231 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2232 Otherwise, it returns zero.
2234 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2235 @c NULL, this function also computes the metrics of the overall
2236 text and stores the results in the members of the structure
2237 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2239 If $CONTROL->two_dimensional is nonzero, this function computes
2240 only the metrics of characters in the first line. */
2242 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2244 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2245 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2246 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2247 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2249 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2250 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2251 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2252 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2253 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2255 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2256 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2259 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2260 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2261 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2264 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2265 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2268 mdraw_text_per_char_extents (MFrame *frame,
2269 MText *mt, int from, int to,
2270 MDrawControl *control,
2271 MDrawMetric *ink_array_return,
2272 MDrawMetric *logical_array_return,
2274 int *num_chars_return,
2275 MDrawMetric *overall_ink_return,
2276 MDrawMetric *overall_logical_return)
2278 MGlyphString *gstring;
2282 ASSURE_CONTROL (control);
2283 *num_chars_return = to - from;
2284 if (array_size < *num_chars_return)
2285 MERROR (MERROR_DRAW, -1);
2286 if (overall_logical_return)
2287 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2288 if (overall_ink_return)
2289 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2291 M_CHECK_RANGE (mt, from, to, -1, 0);
2292 gstring = get_gstring (frame, mt, from, to, control);
2295 *num_chars_return = 0;
2299 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2300 if (g->pos >= from && g->pos < to)
2304 int width = g->width;
2305 int lbearing = g->lbearing;
2306 int rbearing = g->rbearing;
2307 int ascent = g->ascent;
2308 int descent = g->descent;
2310 int logical_descent;
2312 if (g->rface->rfont)
2314 logical_ascent = g->rface->rfont->ascent;
2315 logical_descent = g->rface->rfont->descent;
2319 logical_ascent = g->rface->ascent;
2320 logical_descent = g->rface->descent;
2322 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2324 if (lbearing < width + g->lbearing)
2325 lbearing = width + g->lbearing;
2326 if (rbearing < width + g->rbearing)
2327 rbearing = width + g->rbearing;
2329 if (ascent < g->ascent)
2331 if (descent < g->descent)
2332 descent = g->descent;
2339 if (ink_array_return)
2341 ink_array_return[start - from].x = x + lbearing;
2342 ink_array_return[start - from].y = - ascent;
2343 ink_array_return[start - from].width = rbearing - lbearing;
2344 ink_array_return[start - from].height = ascent + descent;
2346 if (logical_array_return)
2348 logical_array_return[start - from].x = x;
2349 logical_array_return[start - from].y = - logical_descent;
2350 logical_array_return[start - from].height
2351 = logical_ascent + logical_descent;
2352 logical_array_return[start - from].width = width;
2360 if (overall_ink_return)
2362 overall_ink_return->y = - gstring->line_ascent;
2363 overall_ink_return->x = gstring->lbearing;
2364 overall_ink_return->width = x - gstring->lbearing;
2365 overall_ink_return->height = gstring->height;
2367 if (overall_logical_return)
2369 overall_logical_return->y = - gstring->ascent;
2370 overall_logical_return->x = 0;
2371 overall_logical_return->width = x;
2372 overall_logical_return->height = gstring->ascent + gstring->descent;
2375 M17N_OBJECT_UNREF (gstring->top);
2382 @brief Return the character position nearest to the coordinates.
2384 The mdraw_coordinates_position () function checks which character
2385 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2386 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2387 mdraw_text_with_control () function with the drawing control
2388 object $CONTROL. Here, the character position means the number of
2389 characters that precede the character in question in $MT, that is,
2390 the character position of the first character is 0.
2392 $FRAME is used only to get the default face information.
2395 If the glyph image of a character covers coordinate ($X, $Y),
2396 mdraw_coordinates_position () returns the character position of
2398 If $Y is less than the minimum Y-coordinate of the drawn area, it
2399 returns $FROM.\n\n\n
2400 If $Y is greater than the maximum Y-coordinate of the drawn area,
2401 it returns $TO.\n\n\n
2402 If $Y fits in with the drawn area but $X is less than the minimum
2403 X-coordinate, it returns the character position of the first
2404 character drawn on the line $Y.\n\n\n
2405 If $Y fits in with the drawn area but $X is greater than the
2406 maximum X-coordinate, it returns the character position of the
2407 last character drawn on the line $Y. */
2410 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2412 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2413 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2414 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2415 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2416 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2417 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2419 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2422 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2423 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2425 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2427 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2429 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2430 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2432 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2433 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2436 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2437 int x_offset, int y_offset, MDrawControl *control)
2439 MGlyphString *gstring;
2444 M_CHECK_POS_X (mt, from, -1);
2445 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2446 to = mtext_nchars (mt) + (control->cursor_width != 0);
2452 ASSURE_CONTROL (control);
2453 gstring = get_gstring (frame, mt, from, to, control);
2454 while (y + gstring->line_descent <= y_offset
2455 && gstring->to < to)
2458 y += gstring->line_descent;
2459 M17N_OBJECT_UNREF (gstring->top);
2460 gstring = get_gstring (frame, mt, from, to, control);
2461 y += gstring->line_ascent;
2464 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2465 if (! control->orientation_reversed)
2467 width = gstring->indent;
2468 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2469 if (g->pos >= from && g->pos < to)
2472 if (width > x_offset)
2478 width = - gstring->indent;
2479 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2480 if (g->pos >= from && g->pos < to)
2483 if (width < x_offset)
2488 M17N_OBJECT_UNREF (gstring->top);
2496 @brief Compute information about a glyph.
2498 The mdraw_glyph_info () function computes information about a
2499 glyph that covers a character at position $POS of the M-text $MT
2500 assuming that the text is drawn from the character at $FROM of $MT
2501 on a window of frame $FRAME using the mdraw_text_with_control ()
2502 function with the drawing control object $CONTROL.
2504 The information is stored in the members of $INFO. */
2506 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2508 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2509 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2510 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2511 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2513 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2521 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2522 MDrawControl *control, MDrawGlyphInfo *info)
2524 MGlyphString *gstring;
2528 M_CHECK_RANGE_X (mt, from, pos, -1);
2530 ASSURE_CONTROL (control);
2531 gstring = get_gstring (frame, mt, from, pos + 1, control);
2533 MERROR (MERROR_DRAW, -1);
2534 while (gstring->to <= pos)
2536 y += gstring->line_descent;
2537 M17N_OBJECT_UNREF (gstring->top);
2538 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2539 y += gstring->line_ascent;
2541 info->line_from = gstring->from;
2542 if (info->line_from < from)
2543 info->line_from = from;
2544 info->line_to = gstring->to;
2547 if (! control->orientation_reversed)
2549 info->x = gstring->indent;
2550 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2551 info->x += g->width;
2555 info->x = - gstring->indent;
2556 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2557 info->x -= g->width;
2558 while (g[-1].to == g->to)
2561 info->from = g->pos;
2563 info->metrics.x = g->lbearing;
2564 info->metrics.y = - gstring->line_ascent;
2565 info->metrics.height = gstring->height;
2566 info->metrics.width = - g->lbearing + g->width;
2567 if (g->rface->rfont)
2568 info->font = &g->rface->rfont->font;
2571 /* info->logical_width is calculated later. */
2573 if (info->from > info->line_from)
2575 /* The logically previous glyph is on this line. */
2576 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2578 info->prev_from = g_tmp->pos;
2580 else if (info->line_from > 0)
2582 /* The logically previous glyph is on the previous line. */
2583 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2584 gstring->from, control);
2585 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2587 info->prev_from = g_tmp->pos;
2588 M17N_OBJECT_UNREF (gst->top);
2591 info->prev_from = -1;
2593 if (GLYPH_INDEX (g) > 1)
2594 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2595 else if (! control->orientation_reversed)
2597 if (info->line_from > 0)
2601 int p = gstring->from - 1;
2603 gst = get_gstring (frame, mt, p, gstring->from, control);
2604 g_tmp = gst->glyphs + (gst->used - 2);
2605 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2606 M17N_OBJECT_UNREF (gst->top);
2609 info->left_from = info->left_to = -1;
2613 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2617 int p = gstring->to;
2619 gst = get_gstring (frame, mt, p, p + 1, control);
2620 g_tmp = gst->glyphs + (gst->used - 2);
2621 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2622 M17N_OBJECT_UNREF (gst->top);
2625 info->left_from = info->left_to = -1;
2628 if (info->to < gstring->to)
2630 /* The logically next glyph is on this line. */
2631 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2633 info->next_to = g_tmp->to;
2635 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2637 /* The logically next glyph is on the next line. */
2639 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2640 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2642 info->next_to = g_tmp->to;
2643 M17N_OBJECT_UNREF (gst->top);
2648 for (info->logical_width = (g++)->width;
2649 g->pos == pos && g->type != GLYPH_ANCHOR;
2650 info->metrics.width += g->width, info->logical_width += (g++)->width);
2651 info->metrics.width += g[-1].rbearing - g[-1].width;
2653 if (g->type != GLYPH_ANCHOR)
2654 info->right_from = g->pos, info->right_to = g->to;
2655 else if (! control->orientation_reversed)
2657 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2660 M17N_OBJECT_UNREF (gstring->top);
2661 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2663 info->right_from = g->pos, info->right_to = g->to;
2666 info->right_from = info->right_to = -1;
2670 if (info->line_from > 0)
2672 pos = gstring->from - 1;
2673 M17N_OBJECT_UNREF (gstring->top);
2674 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2676 info->right_from = g->pos, info->right_to = g->to;
2679 info->right_from = info->right_to = -1;
2682 M17N_OBJECT_UNREF (gstring->top);
2689 @brief Compute information about glyph sequence.
2691 The mdraw_glyph_list () function computes information about glyphs
2692 corresponding to the text between $FROM and $TO of M-text $MT when
2693 it is drawn on a window of frame $FRAME using the
2694 mdraw_text_with_control () function with the drawing control
2695 object $CONTROL. $GLYPHS is an array of objects to store the
2696 information, and $ARRAY_SIZE is the array size.
2698 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2699 number of actually filled elements in the place pointed by
2700 $NUM_GLYPHS_RETURN, and returns 0.
2702 Otherwise, it stores the required array size in the place pointed
2703 by $NUM_GLYPHS_RETURN, and returns -1. */
2706 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2708 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
2709 À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
2710 ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
2711 ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2713 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
2714 ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
2723 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2724 MDrawControl *control, MDrawGlyph *glyphs,
2725 int array_size, int *num_glyphs_return)
2727 MGlyphString *gstring;
2732 ASSURE_CONTROL (control);
2733 *num_glyphs_return = 0;
2734 M_CHECK_RANGE (mt, from, to, -1, 0);
2735 gstring = get_gstring (frame, mt, from, to, control);
2738 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2740 if (g->type == GLYPH_BOX
2741 || g->pos < from || g->pos >= to)
2743 if (g->type == GLYPH_PAD)
2745 if (g->left_padding)
2746 pad_width = g->width;
2750 glyphs[-1].x_advance += g->width;
2756 glyphs->from = g->pos;
2758 glyphs->glyph_code = g->code;
2759 glyphs->x_off = g->xoff + pad_width;
2760 glyphs->y_off = g->yoff;
2761 glyphs->lbearing = g->lbearing;
2762 glyphs->rbearing = g->rbearing;
2763 glyphs->ascent = g->ascent;
2764 glyphs->descent = g->descent;
2765 glyphs->x_advance = g->width + pad_width;
2766 glyphs->y_advance = 0;
2767 if (g->rface->rfont)
2769 glyphs->font = &g->rface->rfont->font;
2770 glyphs->font_type = g->rface->rfont->type;
2771 glyphs->fontp = g->rface->rfont->fontp;
2775 glyphs->font = NULL;
2776 glyphs->font_type = Mnil;
2777 glyphs->fontp = NULL;
2784 M17N_OBJECT_UNREF (gstring->top);
2786 *num_glyphs_return = n;
2787 return (n <= array_size ? 0 : -1);
2793 @brief Draw one or more textitems.
2795 The mdraw_text_items () function draws one or more M-texts on
2796 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2797 of the textitems to be drawn and $NITEMS is the number of
2798 textimtems in the array. */
2801 @brief textitem ¤òɽ¼¨¤¹¤ë.
2803 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2804 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2805 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2808 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2812 MTextItem, mdraw_text (). */
2815 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2816 MDrawTextItem *items, int nitems)
2818 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2820 while (nitems-- > 0)
2823 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2825 mdraw_text_with_control (frame, win, x, y,
2826 items->mt, 0, mtext_nchars (items->mt),
2828 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2829 items->control, NULL, NULL, NULL);
2832 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2838 @brief calculate a line breaking position.
2840 The function mdraw_default_line_break () calculates a line
2841 breaking position based on the line number $LINE and the
2842 coordinate $Y, when a line is too long to fit within the width
2843 limit. $POS is the position of the character next to the last
2844 one that fits within the limit. $FROM is the position of the
2845 first character of the line, and TO is the position of the last
2846 character displayed on the line if there were not width limit.
2847 LINE and Y are reset to 0 when a line is broken by a newline
2848 character, and incremented each time when a long line is broken
2849 because of the width limit.
2852 This function returns a character position to break the
2857 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2859 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2860 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2861 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2862 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2863 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2864 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2865 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2868 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2872 mdraw_default_line_break (MText *mt, int pos,
2873 int from, int to, int line, int y)
2875 int c = mtext_ref_char (mt, pos);
2878 if (c == ' ' || c == '\t')
2882 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2889 if (c == ' ' || c == '\t')
2892 c = mtext_ref_char (mt, pos);
2905 @brief Obtain per character dimension information.
2907 The mdraw_per_char_extents () function computes the text dimension
2908 of each character in M-text $MT. The faces given as text
2909 properties in $MT and the default face of frame $FRAME determine
2910 the fonts to draw the text. Each successive element in
2911 $ARRAY_RETURN is set to the drawn metrics of successive
2912 characters, which is relative to the origin of the drawing, and a
2913 rectangle for each character in $MT. The number of elements of
2914 $ARRAY_RETURN must be equal to or greater than the number of
2917 If pointer $OVERALL_RETURN is not @c NULL, this function also
2918 computes the extents of the overall text and stores the results in
2919 the members of the structure pointed to by $OVERALL_RETURN. */
2922 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2924 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2925 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2926 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2927 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2928 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2929 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2932 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2933 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2936 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2939 mdraw_per_char_extents (MFrame *frame, MText *mt,
2940 MDrawMetric *array_return,
2941 MDrawMetric *overall_return)
2943 int n = mtext_nchars (mt);
2945 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2946 n, &n, overall_return, NULL);
2950 @brief clear cached information.
2952 The mdraw_clear_cache () function clear cached information
2953 on M-text $MT that was attached by any of the drawing functions.
2954 When the behaviour of `format' or `line_break'
2955 member functions of MDrawControl is changed, the cache must be cleared.
2960 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2962 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2963 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2964 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2965 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2970 mdraw_clear_cache (MText *mt)
2972 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);