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 layout
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face
44 ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include <sys/types.h>
64 #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, Mcommon;
84 /* Special categories */
85 static MSymbol McatCc, McatCf;
87 static MCharTable *linebreak_table;
88 static MSymbol M_break_at_space, M_break_at_word, M_break_at_any;
89 static MSymbol M_kinsoku_bol, M_kinsoku_eol;
92 /* Glyph-string composer. */
94 static MSymbol MbidiR;
95 static MSymbol MbidiAL;
96 static MSymbol MbidiRLE;
97 static MSymbol MbidiRLO;
98 static MSymbol MbidiBN;
99 static MSymbol MbidiS;
102 visual_order (MGlyphString *gstring)
104 int len = gstring->used - 2;
106 int bidi_sensitive = gstring->control.orientation_reversed;
110 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
111 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
113 FriBidiStrIndex *indices;
114 FriBidiLevel *levels;
115 #else /* not HAVE_FRIBIDI */
116 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
119 #endif /* not HAVE_FRIBIDI */
121 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
126 #endif /* not HAVE_FRIBIDI */
129 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
131 if (bidi == MbidiR || bidi == MbidiAL
132 || bidi == MbidiRLE || bidi == MbidiRLO)
137 #endif /* not HAVE_FRIBIDI */
143 if (! bidi_sensitive)
146 glyphs = alloca (sizeof (MGlyph) * len);
147 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
149 visual = alloca (sizeof (FriBidiChar) * (len + 1));
150 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
151 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
153 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
154 #else /* not HAVE_FRIBIDI */
155 indices = alloca (sizeof (int) * len);
156 for (i = 0; i < len; i++)
162 for (j = i + 1; j < len && levels[j]; j++);
163 for (k = j--; i < k; i++, j--)
170 #endif /* not HAVE_FRIBIDI */
172 for (i = 0; i < len;)
174 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
176 /* Length of grapheme-cluster */
181 if (visual[j] != logical[i])
186 g->code = mfont__encode_char (NULL, (MFont *) g->rface->rfont,
189 #endif /* HAVE_FRIBIDI */
190 g->bidi_level = levels[i];
191 for (seglen = 1, g++;
192 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
193 || glyphs[i + seglen].combining_code);
196 g->bidi_level = levels[i];
197 if (indices[i + seglen] < j)
198 j = indices[i + seglen];
200 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
206 reorder_combining_chars (MGlyphString *gstring, int from, int to)
208 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
214 for (g = gbeg; g != gend; g++)
215 if (COMBINING_CODE_CLASS (g->combining_code) > 0
216 && (COMBINING_CODE_CLASS (g[-1].combining_code)
217 > COMBINING_CODE_CLASS (g->combining_code)))
228 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
229 displaying them on FRAME.
231 This function fills these members:
232 pos, to, c, code, rface, bidi_level, categories, type, combining_code
233 The other members are filled by layout_glyph_string. */
236 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
237 MGlyphString *gstring)
239 MRealizedFace *default_rface = frame->rface;
240 int stop, face_change, language_change, charset_change, font_change;
241 MGlyph g_tmp, *g, *last_g;
243 MSymbol language = Mnil, script = Mnil, charset = Mnil;
244 MSymbol non_latin_script = Mnil;
245 MRealizedFace *rface = default_rface;
246 MRealizedFont *rfont;
247 int size = gstring->control.fixed_width;
250 MLIST_RESET (gstring);
251 gstring->from = from;
253 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
254 <category> and <rface> members.*/
257 /** Put anchor glyphs at the head and tail. */
258 g_tmp.type = GLYPH_ANCHOR;
259 g_tmp.pos = g_tmp.to = from;
260 APPEND_GLYPH (gstring, g_tmp);
261 stop = face_change = font_change = pos = from;
271 if (pos < mtext_nchars (mt))
273 MFont *font = rface->font;
277 if (pos == font_change)
279 font = mtext_get_prop (mt, pos, Mfont);
280 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
281 if (font_change == mtext_nchars (mt))
284 if (pos == face_change)
286 num = mtext_get_prop_values (mt, pos, Mface,
287 (void **) faces, 64);
288 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
289 if (face_change == mtext_nchars (mt))
294 faces[0] = &rface->face;
297 rface = mface__realize (frame, faces, num, size, font);
300 rface = default_rface;
302 if (stop > font_change)
304 if (stop > face_change)
308 if (pos < mtext_nchars (mt))
309 c = mtext_ref_char (mt, pos);
313 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
318 category = mchar_get_prop (c, Mcategory);
319 if (category == McatCf)
320 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
321 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
322 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
324 g_tmp.category = GLYPH_CATEGORY_NORMAL;
326 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
330 ctrl[0] = ctrl[1] = g_tmp;
332 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
333 APPEND_GLYPH (gstring, ctrl[0]);
334 APPEND_GLYPH (gstring, ctrl[1]);
337 APPEND_GLYPH (gstring, g_tmp);
338 if (c == '\n' && gstring->control.two_dimensional)
341 /* Append an anchor glyph. */
343 g_tmp.type = GLYPH_ANCHOR;
344 g_tmp.pos = g_tmp.to = pos;
345 APPEND_GLYPH (gstring, g_tmp);
348 /* The next loop is to change each <rface> member for non-ASCII
349 characters if necessary. */
350 stop = charset_change = language_change = from;
351 rfont = default_rface->rfont;
352 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
358 /* Short cut for the obvious case. */
359 this_script = Mlatin;
362 this_script = (MSymbol) mchar_get_prop (c, Mscript);
363 if (this_script == Minherited || this_script == Mcommon)
364 this_script = script;
365 if (this_script == Mcommon)
366 this_script = non_latin_script;
367 if (this_script == Mcommon)
369 /* Search forward for a character that explicitly
370 specifies a non-latin script. */
374 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
376 && (sym = mchar_get_prop (g1->c, Mscript)) != Mcommon
377 && sym != Minherited)
386 if (pos == stop || script != this_script || g->rface->rfont != rfont)
389 last_g = mface__for_chars (script, language, charset,
391 script = this_script;
392 if (script != Mnil && script != Mlatin)
393 non_latin_script = script;
394 rfont = g->rface->ascii_rface->rfont;
397 if (pos < mtext_nchars (mt) && pos == language_change)
399 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
400 mtext_prop_range (mt, Mlanguage, pos, NULL,
401 &language_change, 0);
403 if (pos < mtext_nchars (mt) && pos == charset_change)
405 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
406 mtext_prop_range (mt, Mcharset, pos, NULL,
410 if (stop > language_change)
411 stop = language_change;
412 if (stop > charset_change)
413 stop = charset_change;
418 last_g = mface__for_chars (script, language, charset, last_g, g, size);
420 /* The next loop is to run FLT or perform the default combining if
422 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
426 if (this->type == GLYPH_CHAR && this->rface->rfont)
430 if (this->rface->layouter != Mnil)
435 for (prev = MGLYPH (start - 1);
436 (prev->type == GLYPH_CHAR
437 && prev->category == GLYPH_CATEGORY_FORMATTER
438 && (code = mfont__encode_char (NULL,
439 (MFont *) this->rface->rfont,
441 != MCHAR_INVALID_CODE));
443 if (prev->rface->rfont != this->rface->rfont)
445 prev->rface->rfont = this->rface->rfont;
450 (g->type == GLYPH_CHAR
451 && g->rface->layouter == this->rface->layouter
452 && (g->rface->rfont == this->rface->rfont
453 || (g->category == GLYPH_CATEGORY_FORMATTER
454 && ((code = mfont__encode_char (NULL,
455 (MFont *) this->rface->rfont,
458 != MCHAR_INVALID_CODE))));
460 if (g->rface->rfont != this->rface->rfont)
462 g->rface->rfont = this->rface->rfont;
465 i = mfont__flt_run (gstring, start, i, this->rface);
469 while (this->type == GLYPH_CHAR
471 && this->category == GLYPH_CATEGORY_MODIFIER
472 && this->rface->rfont
473 && this->rface->rfont->layouter == Mnil)
475 int class = (int) mchar_get_prop (this->c,
478 = MAKE_COMBINING_CODE_BY_CLASS (class);
482 reorder_combining_chars (gstring, start, i);
483 if (this->type == GLYPH_ANCHOR)
492 /* At last, reorder glyphs visually if necessary. */
493 if (gstring->control.enable_bidi)
494 visual_order (gstring);
499 combining_code_from_class (int class)
504 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
505 else if (class == 200) /* below left attached */
506 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
507 else if (class == 202) /* below attached*/
508 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
509 else if (class == 204) /* below right attached */
510 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
511 else if (class == 208) /* left attached */
512 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
513 else if (class == 210) /* right attached */
514 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
515 else if (class == 212) /* above left attached */
516 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
517 else if (class == 214) /* above attached */
518 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
519 else if (class == 216) /* above right attached */
520 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
521 else if (class == 218) /* below left */
522 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
523 else if (class == 220) /* below */
524 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
525 else if (class == 222) /* below right */
526 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
527 else if (class == 224) /* left */
528 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
529 else if (class == 226) /* right */
530 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
531 else if (class == 228) /* above left */
532 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
533 else if (class == 230) /* above */
534 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
535 else if (class == 232) /* above right */
536 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
537 else if (class == 233) /* double below */
538 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
539 else if (class == 234) /* double above */
540 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
541 else if (class == 240) /* iota subscript */
542 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
544 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
550 int width, lbearing, rbearing;
554 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
555 MSubTextExtents *extents)
557 int g_physical_ascent, g_physical_descent;
558 MGlyph *g = MGLYPH (from);
559 MGlyph *last_g = MGLYPH (to);
562 g_physical_ascent = gstring->physical_ascent;
563 g_physical_descent = gstring->physical_descent;
564 extents->width = extents->lbearing = extents->rbearing = 0;
566 for (i = from; i < to;)
568 if ( MGLYPH (i)->otf_encoded)
574 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
575 mfont__get_metric (gstring, j, i);
583 MRealizedFont *rfont = base->rface->rfont;
584 int size = rfont->spec.size;
585 int width, lbearing, rbearing;
587 if (g == last_g || ! g->combining_code)
590 if (base->width == 0 && ! base->left_padding && ! base->right_padding
591 && GLYPH_INDEX (base) > from)
593 MGlyph *prev = base - 1;
595 if (base->pos < prev->pos)
596 prev->pos = base->pos;
598 base->pos = prev->pos;
599 if (base->to > prev->to)
605 if (base->left_padding && base->lbearing < 0)
607 base->xoff = - base->lbearing;
608 if (base->rbearing < 0)
609 base->width = base->rbearing - base->lbearing;
611 base->width += base->xoff;
612 base->rbearing += base->xoff;
615 if (base->right_padding && base->rbearing > base->width)
617 base->width = base->rbearing;
619 lbearing = base->lbearing;
620 rbearing = base->rbearing;
624 /* With combining glyphs. */
625 int left = -base->width;
627 int top = - base->ascent;
628 int bottom = base->descent;
629 int height = bottom - top;
630 int begin = base->pos;
635 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
636 rbearing = base->rbearing;
638 while (g != last_g && g->combining_code)
640 int combining_code = g->combining_code;
644 else if (end < g->to)
647 if (! COMBINING_PRECOMPUTED_P (combining_code))
649 int base_x, base_y, add_x, add_y, off_x, off_y;
651 if (COMBINING_BY_CLASS_P (combining_code))
652 g->combining_code = combining_code
653 = combining_code_from_class (COMBINING_CODE_CLASS
656 rfont = g->rface->rfont;
657 size = rfont->spec.size;
658 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
660 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
662 base_x = COMBINING_CODE_BASE_X (combining_code);
663 base_y = COMBINING_CODE_BASE_Y (combining_code);
664 add_x = COMBINING_CODE_ADD_X (combining_code);
665 add_y = COMBINING_CODE_ADD_Y (combining_code);
667 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
670 if (g->xoff + g->width > right)
671 right = g->xoff + g->width;
672 width = right - left;
675 g->yoff = top + height * base_y / 2;
679 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
683 if (g->xoff + g->lbearing < left + lbearing)
684 lbearing = g->xoff + g->lbearing - left;
685 if (g->xoff + g->rbearing > left + rbearing)
686 rbearing = g->xoff + g->rbearing - left;
687 if (g->yoff - g->ascent < top)
688 top = g->yoff - g->ascent;
689 if (g->yoff + g->descent > bottom)
690 bottom = g->yoff + g->descent;
691 height = bottom - top;
697 base->ascent = - top;
698 base->descent = bottom;
699 base->lbearing = lbearing;
700 base->rbearing = rbearing;
701 if (left < - base->width)
703 base->xoff = - base->width - left;
704 base->width += base->xoff;
705 base->rbearing += base->xoff;
706 base->lbearing += base->xoff;
710 base->width += right;
711 base->rbearing += right;
712 base->right_padding = 1;
713 for (i = 1; base + i != g; i++)
714 base[i].xoff -= right;
717 for (i = 0; base + i != g; i++)
724 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
725 g_physical_descent = MAX (g_physical_descent, base->descent);
726 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
727 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
728 extents->width += base->width;
731 gstring->physical_ascent = g_physical_ascent;
732 gstring->physical_descent = g_physical_descent;
736 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
737 by this function directly. Character glyphs are handled by
738 layouter functions registered in font drivers.
740 This function fill-in all the remaining members of glyphs. */
743 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
745 /* Default width of TAB. */
746 int tab_width = frame->space_width * (gstring->control.tab_width
747 ? gstring->control.tab_width : 8);
751 MDrawControl *control = &(gstring->control);
754 int box_line_height = 0;
755 int ignore_formatting_char = control->ignore_formatting_char;
757 gstring->ascent = gstring->descent = 0;
758 gstring->physical_ascent = gstring->physical_descent = 0;
759 gstring->width = gstring->lbearing = gstring->rbearing = 0;
763 while (g->type != GLYPH_ANCHOR)
765 if (box != g->rface->box)
767 int gidx = GLYPH_INDEX (g);
771 /* Insert the right side of the box. That glyph belongs
772 to the previous grapheme cluster. */
773 MGlyph box_glyph = g[-1];
775 box_glyph.type = GLYPH_BOX;
777 = (control->fixed_width
779 : box->inner_hmargin + box->width + box->outer_hmargin);
780 box_glyph.lbearing = 0;
781 box_glyph.rbearing = box_glyph.width;
783 box_glyph.right_padding = 1;
784 gstring->width += box_glyph.width;
785 gstring->rbearing += box_glyph.width;
786 INSERT_GLYPH (gstring, gidx, box_glyph);
793 /* Insert the left side of the box. That glyph belongs
794 to the following grapheme cluster. */
795 MGlyph box_glyph = *g;
796 int box_height = (box->width
797 + box->inner_vmargin + box->outer_vmargin);
799 if (box_line_height < box_height)
800 box_line_height = box_height;
801 box_glyph.type = GLYPH_BOX;
803 = (control->fixed_width
805 : box->inner_hmargin + box->width + box->outer_hmargin);
806 box_glyph.lbearing = 0;
807 box_glyph.rbearing = box_glyph.width;
809 box_glyph.left_padding = 1;
810 gstring->width += box_glyph.width;
811 gstring->rbearing += box_glyph.width;
812 INSERT_GLYPH (gstring, gidx, box_glyph);
818 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
819 g->type = GLYPH_SPACE;
821 if (g->type == GLYPH_CHAR)
823 MRealizedFace *rface = g->rface;
824 MRealizedFont *rfont = rface->rfont;
826 int from = GLYPH_INDEX (g);
828 for (g++; g->type == GLYPH_CHAR; g++)
829 if (! rfont != ! g->rface->rfont
830 || box != g->rface->box
831 || ((fromg->code == MCHAR_INVALID_CODE)
832 != (g->code == MCHAR_INVALID_CODE))
833 || (g->category == GLYPH_CATEGORY_FORMATTER
834 && ignore_formatting_char))
836 if (rfont && fromg->code != MCHAR_INVALID_CODE)
839 int to = GLYPH_INDEX (g);
840 MSubTextExtents extents;
842 layout_glyphs (frame, gstring, from, to, &extents);
843 extra_width = - extents.lbearing;
845 && ! control->disable_overlapping_adjustment
846 && (! control->orientation_reversed
847 ? ((to > 1 || control->align_head)
848 && g->type != GLYPH_ANCHOR)
849 : (((g->type && GLYPH_ANCHOR) || control->align_head)
854 pad.type = GLYPH_PAD;
857 pad.width = pad.rbearing = extra_width;
858 pad.left_padding = 1;
859 INSERT_GLYPH (gstring, from, pad);
861 extents.lbearing = 0;
862 extents.width += extra_width;
863 extents.rbearing += extra_width;
865 g = MGLYPH (from - 1);
866 if (g->type == GLYPH_SPACE)
868 /* The pad just inserted is absorbed (maybe
869 partially) by the previous space while
870 keeping at least some space width. For the
871 moment, we use the arbitrary width 2-pixel.
872 Perhaps, it should be decided by the current
873 face, or a default value of the current
874 frame, which is, however, not yet
876 if (extra_width + 2 < g->width)
878 g->width -= extra_width;
882 extra_width = g->width - 2;
885 gstring->width -= extra_width;
886 gstring->rbearing -= extra_width;
891 extra_width = extents.rbearing - extents.width;
893 && ! control->disable_overlapping_adjustment
894 && (GLYPH_INDEX (g) < gstring->used - 1
895 || (control->orientation_reversed && control->align_head)))
897 if (g->type == GLYPH_SPACE && box == g->rface->box)
900 pad.type = GLYPH_PAD;
903 pad.width = pad.rbearing = extra_width;
904 INSERT_GLYPH (gstring, to, pad);
909 g[-1].width += extra_width;
910 extents.width += extra_width;
913 if (gstring->lbearing > gstring->width + extents.lbearing)
914 gstring->lbearing = gstring->width + extents.lbearing;
915 if (gstring->rbearing < gstring->width + extents.rbearing)
916 gstring->rbearing = gstring->width + extents.rbearing;
917 gstring->width += extents.width;
918 if (gstring->ascent < rface->ascent)
919 gstring->ascent = rface->ascent;
920 if (gstring->descent < rface->descent)
921 gstring->descent = rface->descent;
925 for (; fromg < g; fromg++)
927 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
928 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
929 fromg->width = fromg->rbearing = 1;
931 fromg->width = fromg->rbearing = rface->space_width;
932 fromg->xoff = fromg->lbearing = 0;
933 fromg->ascent = fromg->descent = 0;
934 gstring->width += fromg->width;
935 gstring->rbearing += fromg->width;
937 if (gstring->ascent < frame->rface->ascent)
938 gstring->ascent = frame->rface->ascent;
939 if (gstring->descent < frame->descent)
940 gstring->descent = frame->rface->descent;
943 else if (g->type == GLYPH_SPACE)
946 g->width = g->rface->space_width;
947 else if (g->c == '\n')
949 g->width = control->cursor_width;
952 if (control->cursor_bidi)
954 else if (g->width < 0)
955 g->width = g->rface->space_width;
958 else if (g->c == '\t')
960 g->width = tab_width - ((gstring->indent + gstring->width)
966 if (g[-1].type == GLYPH_PAD)
968 /* This space glyph absorbs (maybe partially) the
969 previous padding glyph. */
970 g->width -= g[-1].width;
972 /* But, keep at least some space width. For the
973 moment, we use the arbitrary width 2-pixel. */
976 g->rbearing = g->width;
977 gstring->width += g->width;
978 gstring->rbearing += g->width;
981 if (gstring->ascent < g->rface->ascent)
982 gstring->ascent = g->rface->ascent;
983 if (gstring->descent < g->rface->descent)
984 gstring->descent = g->rface->descent;
990 gstring->width += g->width;
991 gstring->rbearing += g->width;
998 /* Insert the right side of the box. */
999 int gidx = GLYPH_INDEX (g);
1000 MGlyph box_glyph = g[-1];
1002 box_glyph.type = GLYPH_BOX;
1004 = (control->fixed_width
1005 ? frame->space_width
1006 : box->inner_hmargin + box->width + box->outer_hmargin);
1007 box_glyph.lbearing = 0;
1008 box_glyph.rbearing = box_glyph.width;
1010 box_glyph.right_padding = 1;
1011 gstring->width += box_glyph.width;
1012 gstring->rbearing += box_glyph.width;
1013 INSERT_GLYPH (gstring, gidx, box_glyph);
1016 gstring->text_ascent = gstring->ascent;
1017 gstring->text_descent = gstring->descent;
1018 if (gstring->text_ascent < gstring->physical_ascent)
1019 gstring->text_ascent = gstring->physical_ascent;
1020 if (gstring->text_descent < gstring->physical_descent)
1021 gstring->text_descent = gstring->physical_descent;
1022 gstring->line_ascent = gstring->text_ascent;
1023 gstring->line_descent = gstring->text_descent;
1024 if (box_line_height > 0)
1026 gstring->line_ascent += box_line_height;
1027 gstring->physical_ascent = gstring->line_ascent;
1028 gstring->line_descent += box_line_height;
1029 gstring->physical_descent = gstring->line_descent;
1032 if (gstring->line_ascent < control->min_line_ascent)
1033 gstring->line_ascent = control->min_line_ascent;
1034 else if (control->max_line_ascent
1035 && control->max_line_ascent > control->min_line_ascent
1036 && gstring->line_ascent > control->max_line_ascent)
1037 gstring->line_ascent = control->max_line_ascent;
1039 if (gstring->line_descent < control->min_line_descent)
1040 gstring->line_descent = control->min_line_descent;
1041 else if (control->max_line_descent
1042 && control->max_line_descent > control->min_line_descent
1043 && gstring->line_descent > control->max_line_descent)
1044 gstring->line_descent = control->max_line_descent;
1045 gstring->height = gstring->line_ascent + gstring->line_descent;
1047 if (control->orientation_reversed
1050 /* We must adjust TAB width for RTL orientation. */
1051 width = gstring->indent;
1053 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1055 if (g->type == GLYPH_CHAR && g->c == '\t')
1057 int this_width = tab_width - (width % tab_width);
1059 if (g[1].type == GLYPH_PAD)
1060 this_width -= g[1].width;
1061 if (g[-1].type == GLYPH_PAD)
1062 this_width -= g[-1].width;
1065 gstring->width += this_width - g->width;
1066 gstring->rbearing += this_width - g->width;
1067 g->width = this_width;
1068 width += this_width;
1078 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1079 MGlyphString *gstring, int from, int to,
1080 int *from_idx, int *to_idx, int *to_x)
1082 MGlyph *g = MGLYPH (1);
1083 MDrawRegion region = (MDrawRegion) NULL;
1084 MDrawControl *control = &gstring->control;
1085 int cursor_pos = -1;
1087 int cursor_bidi = control->cursor_bidi;
1089 if (control->with_cursor && control->cursor_width)
1091 if (gstring->from <= control->cursor_pos
1092 && gstring->to > control->cursor_pos)
1093 cursor_pos = control->cursor_pos;
1096 && gstring->from <= control->cursor_pos - 1
1097 && gstring->to > control->cursor_pos - 1)
1098 prev_pos = control->cursor_pos - 1;
1101 *from_idx = *to_idx = 0;
1102 while (g->type != GLYPH_ANCHOR)
1104 if (g->pos >= from && g->pos < to)
1106 MGlyph *fromg = g, *cursor = NULL;
1107 MRealizedFace *rface = g->rface;
1109 int cursor_width = 0;
1113 *from_idx = GLYPH_INDEX (g);
1114 while (g->pos >= from && g->pos < to
1115 && g->rface == rface)
1118 if (g->type != GLYPH_BOX
1119 && g->pos <= cursor_pos && g->to > cursor_pos)
1122 cursor = g, cursor_x = x + width;
1123 cursor_width += g->width;
1125 width += g++->width;
1128 && (control->as_image
1129 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1131 int this_x = x, this_width = width;
1133 if (fromg->type == GLYPH_BOX)
1134 this_x += fromg->width, this_width -= fromg->width;
1135 if (g[-1].type == GLYPH_BOX)
1136 this_width -= g[-1].width;
1137 (frame->driver->fill_space)
1138 (frame, win, rface, 0,
1139 this_x, y - gstring->text_ascent, this_width,
1140 gstring->text_ascent + gstring->text_descent,
1141 control->clip_region);
1148 rect.y = y - gstring->text_ascent;
1149 rect.height = gstring->text_ascent + gstring->text_descent;
1152 rect.width = ((control->cursor_width > 0
1153 && control->cursor_width < cursor_width)
1154 ? control->cursor_width : cursor_width);
1158 if (cursor->bidi_level % 2)
1159 rect.x += cursor_width - rect.width;
1160 (*frame->driver->fill_space)
1161 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1162 control->clip_region);
1164 region = (*frame->driver->region_from_rect) (&rect);
1166 (*frame->driver->region_add_rect) (region, &rect);
1169 if (cursor->bidi_level % 2)
1172 rect.width = cursor_width < 4 ? cursor_width : 4;
1173 (*frame->driver->fill_space)
1174 (frame, win, rface, 1,
1175 rect.x, rect.y, rect.width, rect.height,
1176 control->clip_region);
1177 (*frame->driver->region_add_rect) (region, &rect);
1189 if (fromg->type != GLYPH_BOX
1190 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1193 cursor = fromg, cursor_x = x + temp_width;
1194 cursor_width += fromg->width;
1196 temp_width += fromg++->width;
1203 if (! (cursor->bidi_level % 2))
1204 rect.x += cursor_width - 1;
1205 rect.y = y - gstring->text_ascent;
1206 rect.height = gstring->text_ascent + gstring->text_descent;
1208 (*frame->driver->fill_space)
1209 (frame, win, rface, 1,
1210 rect.x, rect.y, rect.width, rect.height,
1211 control->clip_region);
1213 region = (*frame->driver->region_from_rect) (&rect);
1215 (*frame->driver->region_add_rect) (region, &rect);
1216 rect.y += rect.height - 2;
1218 rect.width = cursor_width < 4 ? cursor_width : 4;
1219 if (! (cursor->bidi_level % 2))
1220 rect.x -= rect.width - 1;
1221 (*frame->driver->fill_space) (frame, win, rface, 1,
1222 rect.x, rect.y, rect.width, rect.height,
1223 control->clip_region);
1224 (*frame->driver->region_add_rect) (region, &rect);
1228 *to_idx = GLYPH_INDEX (g);
1238 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1239 MGlyphString *gstring, int from_idx, int to_idx,
1240 int reverse, MDrawRegion region)
1242 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1248 (*frame->driver->region_to_rect) (region, &rect);
1251 while (g != gend && x + g->rbearing <= rect.x)
1254 width -= g++->width;
1255 while (! g->enabled && g != gend)
1259 rect.x += rect.width;
1260 if (rect.x < x + width)
1263 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1265 width -= (--gend)->width;
1266 while (! gend->enabled && g != gend)
1270 while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1279 MRealizedFace *rface = g->rface;
1280 int width = g->width;
1281 MGlyph *from_g = g++;
1283 /* Handle the glyphs of the same type/face at once. */
1285 && g->type == from_g->type
1286 && g->rface == rface
1287 && ((g->code == MCHAR_INVALID_CODE)
1288 == (from_g->code == MCHAR_INVALID_CODE))
1290 width += g++->width;
1292 if (from_g->type == GLYPH_CHAR)
1294 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1295 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1298 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1301 else if (from_g->type == GLYPH_BOX)
1303 /* Draw the left or right side of a box. If
1304 from_g->lbearing is nonzero, this is the left side,
1305 else this is the right side. */
1306 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1309 if (from_g->type != GLYPH_BOX)
1312 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1313 x, y, width, region);
1316 /* Draw the top and bottom side of a box. */
1317 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1318 x, y, width, region);
1329 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1330 int *from_x, int *to_x)
1333 int left_idx = *left, right_idx = *right;
1334 int left_x, right_x, x;
1336 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1339 if (x + g->rbearing > 0)
1341 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1343 left_idx = GLYPH_INDEX (g);
1348 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1351 if (x - g->width + g->lbearing < 0)
1353 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1355 right_idx = GLYPH_INDEX (g) + 1;
1360 if (*left == left_idx && *right == right_idx)
1363 if (*left != left_idx)
1365 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1370 if (*right != right_idx)
1372 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1382 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1387 if (from <= gstring->from && to >= gstring->to)
1390 *rbearing = gstring->rbearing;
1391 return gstring->width;
1396 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1397 if (g->pos >= from && g->pos < to)
1399 if (rbearing && width + g->rbearing > *rbearing)
1400 *rbearing = width + g->rbearing;
1408 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1409 MGlyphString *gstring, int from, int to)
1411 MDrawControl *control = &gstring->control;
1413 MDrawRegion clip_region, cursor_region;
1414 int from_idx, to_idx;
1417 if (control->orientation_reversed)
1418 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1420 x += gstring->indent;
1422 /* At first, draw all glyphs without cursor. */
1423 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1424 &from_idx, &to_idx, &to_x);
1426 if (control->partial_update)
1429 rect.width = to_x - x;
1430 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1432 rect.y = y - gstring->line_ascent;
1433 rect.height = gstring->height;
1434 clip_region = (*frame->driver->region_from_rect) (&rect);
1435 if (control->clip_region)
1436 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1439 clip_region = control->clip_region;
1442 clip_region = control->clip_region;
1444 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1449 (*frame->driver->intersect_region) (cursor_region, clip_region);
1450 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1453 if (clip_region != control->clip_region)
1454 (*frame->driver->free_region) (clip_region);
1456 (*frame->driver->free_region) (cursor_region);
1460 static int gstring_num;
1463 free_gstring (void *object)
1465 MGlyphString *gstring = (MGlyphString *) object;
1468 free_gstring (gstring->next);
1469 if (gstring->size > 0)
1470 free (gstring->glyphs);
1476 static MGlyphString scratch_gstring;
1478 static MGlyphString *
1479 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1482 MGlyphString *gstring;
1484 if (pos == mt->nchars)
1488 gstring = &scratch_gstring;
1489 if (gstring->size == 0)
1494 g_tmp.type = GLYPH_ANCHOR;
1495 APPEND_GLYPH (gstring, g_tmp);
1496 APPEND_GLYPH (gstring, g_tmp);
1497 APPEND_GLYPH (gstring, g_tmp);
1498 gstring->glyphs[1].type = GLYPH_SPACE;
1499 gstring->glyphs[1].c = '\n';
1500 gstring->glyphs[1].code = '\n';
1502 gstring->from = pos;
1504 g->rface = frame->rface;
1505 g->pos = g->to = pos;
1507 g->rface = frame->rface;
1508 g->pos = pos++, g->to = pos;
1510 g->rface = frame->rface;
1511 g->pos = g->to = pos;
1516 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1517 MLIST_INIT1 (gstring, glyphs, 128);
1521 gstring->frame = frame;
1522 gstring->tick = frame->tick;
1523 gstring->top = gstring;
1524 gstring->control = *control;
1525 gstring->indent = gstring->width_limit = 0;
1526 if (control->format)
1527 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1529 gstring->width_limit = control->max_line_width;
1530 gstring->anti_alias = control->anti_alias;
1534 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1537 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1540 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1548 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1549 a width of glyphs for the character at I of MT. If I is not a
1550 beginning of a grapheme cluster, the corresponding element is
1552 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1553 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1554 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1555 pos_width[g->pos - gstring->from] += g->width;
1556 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1558 if (pos_width[i] > 0)
1560 if (width + pos_width[i] > gstring->width_limit)
1563 width += pos_width[i];
1566 pos = gstring->from + i;
1567 if (gstring->control.line_break)
1569 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1570 gstring->from, gstring->from + i,
1572 if (pos <= gstring->from)
1574 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1577 else if (pos >= gstring->to)
1582 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1585 if (pos < gstring->to)
1587 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1588 layout_glyph_string (frame, gstring);
1593 /* Return a gstring that covers a character at POS. */
1595 static MGlyphString *
1596 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1598 MGlyphString *gstring = NULL;
1600 if (pos < mtext_nchars (mt))
1602 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1605 && ((prop->start != 0
1606 && mtext_ref_char (mt, prop->start - 1) != '\n')
1607 || (prop->end < mtext_nchars (mt)
1608 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1610 mtext_detach_property (prop);
1615 gstring = prop->val;
1616 if (gstring->frame != frame
1617 || gstring->tick != frame->tick
1618 || memcmp (control, &gstring->control,
1619 (char *) (&control->with_cursor)
1620 - (char *) (control))
1621 || control->cursor_width != gstring->control.cursor_width
1622 || control->cursor_bidi != gstring->control.cursor_bidi)
1624 mtext_detach_property (prop);
1629 else if (! control->cursor_width)
1637 offset = mtext_character (mt, pos, 0, '\n');
1642 offset -= gstring->from;
1644 for (gst = gstring; gst; gst = gst->next)
1648 gst->from += offset;
1650 for (i = 0; i < gst->used; i++)
1652 gst->glyphs[i].pos += offset;
1653 gst->glyphs[i].to += offset;
1656 M17N_OBJECT_REF (gstring);
1661 int line = 0, y = 0;
1663 if (pos < mtext_nchars (mt))
1665 beg = mtext_character (mt, pos, 0, '\n');
1673 end = mtext_nchars (mt) + (control->cursor_width != 0);
1674 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1675 if (beg < mtext_nchars (mt))
1676 compose_glyph_string (frame, mt, beg, end, gstring);
1677 layout_glyph_string (frame, gstring);
1679 if (gstring->width_limit
1680 && gstring->width > gstring->width_limit)
1682 MGlyphString *gst = gstring;
1684 truncate_gstring (frame, mt, gst);
1685 while (gst->to < end)
1687 line++, y += gst->height;
1688 gst->next = alloc_gstring (frame, mt, gst->from, control,
1690 gst->next->top = gstring;
1691 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1693 layout_glyph_string (frame, gst);
1694 if (gst->width <= gst->width_limit)
1696 truncate_gstring (frame, mt, gst);
1700 if (! control->disable_caching && pos < mtext_nchars (mt))
1702 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1703 MTEXTPROP_VOLATILE_STRONG);
1705 if (end > mtext_nchars (mt))
1706 end = mtext_nchars (mt);
1707 mtext_attach_property (mt, beg, end, prop);
1708 M17N_OBJECT_UNREF (prop);
1712 while (gstring->to <= pos)
1714 if (! gstring->next)
1716 gstring = gstring->next;
1718 gstring->control = *control;
1724 static MDrawControl control_noop;
1726 #define ASSURE_CONTROL(control) \
1728 control = &control_noop; \
1733 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1734 MText *mt, int from, int to,
1735 MDrawControl *control)
1737 MGlyphString *gstring;
1739 M_CHECK_POS_X (mt, from, -1);
1740 ASSURE_CONTROL (control);
1741 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1742 to = mtext_nchars (mt) + (control->cursor_width != 0);
1746 gstring = get_gstring (frame, mt, from, to, control);
1748 MERROR (MERROR_DRAW, -1);
1749 render_glyph_string (frame, win, x, y, gstring, from, to);
1753 y += gstring->line_descent;
1754 M17N_OBJECT_UNREF (gstring->top);
1755 gstring = get_gstring (frame, mt, from, to, control);
1756 y += gstring->line_ascent;
1757 render_glyph_string (frame, win, x, y, gstring, from, to);
1760 M17N_OBJECT_UNREF (gstring->top);
1767 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1773 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1774 if (g->pos <= pos && g->to > pos)
1779 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1780 if (g->pos <= pos && g->to > pos)
1787 /* for debugging... */
1791 dump_combining_code (int code)
1793 char *vallign = "tcbB";
1794 char *hallign = "lcr";
1800 if (COMBINING_BY_CLASS_P (code))
1801 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1802 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1803 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1804 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1805 off_x = COMBINING_CODE_OFF_X (code) - 128;
1807 sprintf (work + 2, "+%d", off_y);
1809 sprintf (work + 2, "%d", off_y);
1810 else if (off_x == 0)
1811 sprintf (work + 2, ".");
1812 p = work + strlen (work);
1814 sprintf (p, ">%d", off_x);
1816 sprintf (p, "<%d", -off_x);
1818 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1819 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1825 dump_gstring (MGlyphString *gstring, int indent)
1827 char *prefix = (char *) alloca (indent + 1);
1828 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1830 memset (prefix, 32, indent);
1833 fprintf (stderr, "(glyph-string");
1835 for (g = MGLYPH (0); g < last_g; g++)
1837 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1839 g - gstring->glyphs,
1840 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1841 : g->type == GLYPH_ANCHOR ? "ANC"
1842 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1843 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1844 dump_combining_code (g->combining_code),
1845 g->width, g->bidi_level);
1846 fprintf (stderr, ")");
1850 /* m17n-X internal APIs */
1855 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1857 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1858 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1860 Minherited = msymbol ("inherited");
1861 Mcommon = msymbol ("common");
1863 McatCc = msymbol ("Cc");
1864 McatCf = msymbol ("Cf");
1866 MbidiR = msymbol ("R");
1867 MbidiAL = msymbol ("AL");
1868 MbidiRLE = msymbol ("RLE");
1869 MbidiRLO = msymbol ("RLO");
1870 MbidiBN = msymbol ("BN");
1871 MbidiS = msymbol ("S");
1873 fribidi_set_mirroring (TRUE);
1876 M_break_at_space = msymbol ("bs");
1877 M_break_at_word = msymbol ("bw");
1878 M_break_at_any = msymbol ("ba");
1879 M_kinsoku_bol = msymbol ("kb");
1880 M_kinsoku_eol = msymbol ("ke");
1888 MLIST_FREE1 (&scratch_gstring, glyphs);
1889 M17N_OBJECT_UNREF (linebreak_table);
1890 linebreak_table = NULL;
1894 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1898 /*** @addtogroup m17nDraw */
1903 @brief Draw an M-text on a window.
1905 The mdraw_text () function draws the text between $FROM and $TO of
1906 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1908 The appearance of the text (size, style, color, etc) is specified
1909 by the value of the text property whose key is @c Mface. If the
1910 M-text or a part of the M-text does not have such a text property,
1911 the default face of $FRAME is used.
1913 The font used to draw a character in the M-text is selected from
1914 the value of the fontset property of a face by the following
1919 <li> Search the text properties given to the character for the one
1920 whose key is @c Mcharset; its value should be either a symbol
1921 specifying a charset or #Mnil. If the value is #Mnil,
1922 proceed to the next step.
1924 Otherwise, search the mapping table of the fontset for the
1925 charset. If no entry is found proceed to the next step.
1927 If an entry is found, use one of the fonts in the entry that
1928 has a glyph for the character and that matches best with the
1929 face properties. If no such font exists, proceed to the next
1932 <li> Get the character property "script" of the character. If it is
1933 inherited, get the script property from the previous
1934 characters. If there is no previous character, or none of
1935 them has the script property other than inherited, proceed to
1938 Search the text properties given to the character for the one
1939 whose key is @c Mlanguage; its value should be either a
1940 symbol specifying a language or @c Mnil.
1942 Search the mapping table of the fontset for the combination
1943 of the script and language. If no entry is found, proceed to
1946 If an entry is found, use one of the fonts in the entry that
1947 has a glyph for the character and that matches best with the
1948 face properties. If no such font exists, proceed to the next
1951 <li> Search the fall-back table of the fontset for a font that has
1952 a glyph of the character. If such a font is found, use that
1957 If no font is found by the algorithm above, this function draws an
1958 empty box for the character.
1960 This function draws only the glyph foreground. To specify the
1961 background color, use mdraw_image_text () or
1962 mdraw_text_with_control ().
1964 This function is the counterpart of <tt>XDrawString ()</tt>,
1965 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1966 in the X Window System.
1969 If the operation was successful, mdraw_text () returns 0. If an
1970 error is detected, it returns -1 and assigns an error code to the
1971 external variable #merror_code. */
1973 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1975 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1976 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1978 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1979 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1980 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1981 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1983 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1984 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1988 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1989 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1990 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1991 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1992 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1993 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1995 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1996 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1998 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1999 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2000 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2002 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2003 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2005 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2006 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2008 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2009 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2011 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2012 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2016 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2018 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2019 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2021 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2022 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2025 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2026 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2028 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2035 mdraw_image_text () */
2038 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2039 MText *mt, int from, int to)
2041 MDrawControl control;
2043 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2044 memset (&control, 0, sizeof control);
2045 control.as_image = 0;
2046 return draw_text (frame, win, x, y, mt, from, to, &control);
2053 @brief Draw an M-text on a window as an image.
2055 The mdraw_image_text () function draws the text between $FROM and
2056 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2057 coordinate ($X, $Y).
2059 The way to draw a text is the same as in mdraw_text () except that
2060 this function also draws the background with the color specified
2063 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2064 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2065 functions in the X Window System.
2068 If the operation was successful, mdraw_image_text () returns 0.
2069 If an error is detected, it returns -1 and assigns an error code
2070 to the external variable #merror_code. */
2073 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2075 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2076 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2077 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2079 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2080 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2082 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2083 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2087 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2088 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2090 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2100 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2101 MText *mt, int from, int to)
2103 MDrawControl control;
2105 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2106 memset (&control, 0, sizeof control);
2107 control.as_image = 1;
2108 return draw_text (frame, win, x, y, mt, from, to, &control);
2114 @brief Draw an M-text on a window with fine control.
2116 The mdraw_text_with_control () function draws the text between
2117 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2118 coordinate ($X, $Y).
2120 The way to draw a text is the same as in mdraw_text () except that
2121 this function also follows what specified in the drawing control
2124 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2125 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2126 breaks lines and the following characters are drawn in the next
2127 line. See the documentation of the structure @ MDrawControl for
2131 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2133 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2134 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2137 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2138 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2140 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2141 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2142 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2145 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2146 MText *mt, int from, int to, MDrawControl *control)
2148 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2149 return draw_text (frame, win, x, y, mt, from, to, control);
2155 @brief Compute text pixel width.
2157 The mdraw_text_extents () function computes the width of text
2158 between $FROM and $TO of M-text $MT when it is drawn on a window
2159 of frame $FRAME using the mdraw_text_with_control () function with
2160 the drawing control object $CONTROL.
2162 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2163 the bounding box of character ink of the M-text, and stores the
2164 results in the members of the structure pointed to by
2165 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2166 surrounding box, the box is included in the bounding box.
2168 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2169 computes the bounding box that provides minimum spacing to other
2170 graphical features (such as surrounding box) for the M-text, and
2171 stores the results in the members of the structure pointed to by
2172 $OVERALL_LOGICAL_RETURN.
2174 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2175 computes the bounding box that provides minimum spacing to the
2176 other M-text drawn, and stores the results in the members of the
2177 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2178 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2179 min_line_ascent, min_line_descent, max_line_ascent, and
2180 max_line_descent of $CONTROL are all zero.
2183 This function returns the width of the text to be drawn in the
2184 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2185 text is drawn in multiple physical lines, it returns the width of
2186 the widest line. If an error occurs, it returns -1 and assigns an
2187 error code to the external variable #merror_code. */
2191 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2193 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2194 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2195 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2197 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2198 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2199 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2200 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2202 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2203 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2204 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2205 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2207 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2208 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2209 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2210 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2211 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2212 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2215 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2216 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2217 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2219 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2226 mdraw_text_extents (MFrame *frame,
2227 MText *mt, int from, int to, MDrawControl *control,
2228 MDrawMetric *overall_ink_return,
2229 MDrawMetric *overall_logical_return,
2230 MDrawMetric *overall_line_return)
2232 MGlyphString *gstring;
2234 int width, rbearing;
2236 ASSURE_CONTROL (control);
2237 M_CHECK_POS_X (mt, from, -1);
2238 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2239 to = mtext_nchars (mt) + (control->cursor_width != 0);
2243 gstring = get_gstring (frame, mt, from, to, control);
2245 MERROR (MERROR_DRAW, -1);
2246 width = gstring_width (gstring, from, to, &rbearing);
2247 if (overall_ink_return)
2249 overall_ink_return->y = - gstring->physical_ascent;
2250 overall_ink_return->x = gstring->lbearing;
2252 if (overall_logical_return)
2254 overall_logical_return->y = - gstring->ascent;
2255 overall_logical_return->x = 0;
2257 if (overall_line_return)
2259 overall_line_return->y = - gstring->line_ascent;
2260 overall_line_return->x = gstring->lbearing;
2263 for (from = gstring->to; from < to; from = gstring->to)
2265 int this_width, this_rbearing;
2267 y += gstring->line_descent;
2268 M17N_OBJECT_UNREF (gstring->top);
2269 gstring = get_gstring (frame, mt, from, to, control);
2270 this_width = gstring_width (gstring, from, to, &this_rbearing);
2271 y += gstring->line_ascent;
2272 if (width < this_width)
2274 if (rbearing < this_rbearing)
2275 rbearing = this_rbearing;
2277 if (overall_ink_return)
2279 overall_ink_return->width = rbearing;
2280 overall_ink_return->height
2281 = y + gstring->physical_descent - overall_ink_return->y;
2283 if (overall_logical_return)
2285 overall_logical_return->width = width;
2286 overall_logical_return->height
2287 = y + gstring->descent - overall_logical_return->y;
2289 if (overall_line_return)
2291 overall_line_return->width = MAX (width, rbearing);
2292 overall_line_return->height
2293 = y + gstring->line_descent - overall_line_return->y;
2296 M17N_OBJECT_UNREF (gstring->top);
2303 @brief Compute the text dimensions of each character of M-text.
2305 The mdraw_text_per_char_extents () function computes the drawn
2306 metric of each character between $FROM and $TO of M-text $MT
2307 assuming that they are drawn on a window of frame $FRAME using the
2308 mdraw_text_with_control () function with the drawing control
2311 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2312 $LOGICAL_ARRAY_RETURN. Each successive element of
2313 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2314 ink and logical metrics of successive characters respectively,
2315 relative to the drawing origin of the M-text. The number of
2316 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2317 been set is returned to $NUM_CHARS_RETURN.
2319 If $ARRAY_SIZE is too small to return all metrics, the function
2320 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2321 Otherwise, it returns zero.
2323 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2324 @c NULL, this function also computes the metrics of the overall
2325 text and stores the results in the members of the structure
2326 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2328 If $CONTROL->two_dimensional is nonzero, this function computes
2329 only the metrics of characters in the first line. */
2331 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2333 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2334 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2335 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2337 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2338 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2339 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2340 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2341 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2343 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2344 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2347 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2348 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2349 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2351 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2354 mdraw_text_per_char_extents (MFrame *frame,
2355 MText *mt, int from, int to,
2356 MDrawControl *control,
2357 MDrawMetric *ink_array_return,
2358 MDrawMetric *logical_array_return,
2360 int *num_chars_return,
2361 MDrawMetric *overall_ink_return,
2362 MDrawMetric *overall_logical_return)
2364 MGlyphString *gstring;
2368 ASSURE_CONTROL (control);
2369 *num_chars_return = to - from;
2370 if (array_size < *num_chars_return)
2371 MERROR (MERROR_DRAW, -1);
2372 if (overall_logical_return)
2373 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2374 if (overall_ink_return)
2375 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2377 M_CHECK_RANGE (mt, from, to, -1, 0);
2378 gstring = get_gstring (frame, mt, from, to, control);
2381 *num_chars_return = 0;
2385 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2386 if (g->pos >= from && g->pos < to)
2390 int width = g->width;
2391 int lbearing = g->lbearing;
2392 int rbearing = g->rbearing;
2393 int ascent = g->ascent;
2394 int descent = g->descent;
2396 int logical_descent;
2398 if (g->rface->rfont)
2400 logical_ascent = g->rface->rfont->ascent;
2401 logical_descent = g->rface->rfont->descent;
2405 logical_ascent = g->rface->ascent;
2406 logical_descent = g->rface->descent;
2408 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2410 if (lbearing < width + g->lbearing)
2411 lbearing = width + g->lbearing;
2412 if (rbearing < width + g->rbearing)
2413 rbearing = width + g->rbearing;
2415 if (ascent < g->ascent)
2417 if (descent < g->descent)
2418 descent = g->descent;
2425 if (ink_array_return)
2427 ink_array_return[start - from].x = x + lbearing;
2428 ink_array_return[start - from].y = - ascent;
2429 ink_array_return[start - from].width = rbearing - lbearing;
2430 ink_array_return[start - from].height = ascent + descent;
2432 if (logical_array_return)
2434 logical_array_return[start - from].x = x;
2435 logical_array_return[start - from].y = - logical_descent;
2436 logical_array_return[start - from].height
2437 = logical_ascent + logical_descent;
2438 logical_array_return[start - from].width = width;
2446 if (overall_ink_return)
2448 overall_ink_return->y = - gstring->line_ascent;
2449 overall_ink_return->x = gstring->lbearing;
2450 overall_ink_return->width = x - gstring->lbearing;
2451 overall_ink_return->height = gstring->height;
2453 if (overall_logical_return)
2455 overall_logical_return->y = - gstring->ascent;
2456 overall_logical_return->x = 0;
2457 overall_logical_return->width = x;
2458 overall_logical_return->height = gstring->ascent + gstring->descent;
2461 M17N_OBJECT_UNREF (gstring->top);
2468 @brief Return the character position nearest to the coordinates.
2470 The mdraw_coordinates_position () function checks which character
2471 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2472 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2473 mdraw_text_with_control () function with the drawing control
2474 object $CONTROL. Here, the character position means the number of
2475 characters that precede the character in question in $MT, that is,
2476 the character position of the first character is 0.
2478 $FRAME is used only to get the default face information.
2481 If the glyph image of a character covers coordinate ($X, $Y),
2482 mdraw_coordinates_position () returns the character position of
2484 If $Y is less than the minimum Y-coordinate of the drawn area, it
2486 If $Y is greater than the maximum Y-coordinate of the drawn area,
2488 If $Y fits in with the drawn area but $X is less than the minimum
2489 X-coordinate, it returns the character position of the first
2490 character drawn on the line $Y.\n\n
2491 If $Y fits in with the drawn area but $X is greater than the
2492 maximum X-coordinate, it returns the character position of the
2493 last character drawn on the line $Y. */
2496 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2498 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2499 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2500 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2501 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2502 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2503 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2505 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2508 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2509 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2510 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2511 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2512 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2513 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2514 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2515 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2518 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2519 int x_offset, int y_offset, MDrawControl *control)
2521 MGlyphString *gstring;
2526 M_CHECK_POS_X (mt, from, -1);
2527 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2528 to = mtext_nchars (mt) + (control->cursor_width != 0);
2534 ASSURE_CONTROL (control);
2535 gstring = get_gstring (frame, mt, from, to, control);
2536 while (y + gstring->line_descent <= y_offset
2537 && gstring->to < to)
2540 y += gstring->line_descent;
2541 M17N_OBJECT_UNREF (gstring->top);
2542 gstring = get_gstring (frame, mt, from, to, control);
2543 y += gstring->line_ascent;
2546 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2547 if (! control->orientation_reversed)
2549 width = gstring->indent;
2550 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2551 if (g->pos >= from && g->pos < to)
2554 if (width > x_offset)
2560 width = - gstring->indent;
2561 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2562 if (g->pos >= from && g->pos < to)
2565 if (width < x_offset)
2569 if (g->type == GLYPH_ANCHOR
2570 && control->two_dimensional
2574 M17N_OBJECT_UNREF (gstring->top);
2582 @brief Compute information about a glyph.
2584 The mdraw_glyph_info () function computes information about a
2585 glyph that covers a character at position $POS of the M-text $MT
2586 assuming that the text is drawn from the character at $FROM of $MT
2587 on a window of frame $FRAME using the mdraw_text_with_control ()
2588 function with the drawing control object $CONTROL.
2590 The information is stored in the members of $INFO. */
2592 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2594 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2595 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2596 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2597 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2599 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2607 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2608 MDrawControl *control, MDrawGlyphInfo *info)
2610 MGlyphString *gstring;
2614 M_CHECK_RANGE_X (mt, from, pos, -1);
2616 ASSURE_CONTROL (control);
2617 gstring = get_gstring (frame, mt, from, pos + 1, control);
2619 MERROR (MERROR_DRAW, -1);
2620 while (gstring->to <= pos)
2622 y += gstring->line_descent;
2623 M17N_OBJECT_UNREF (gstring->top);
2624 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2625 y += gstring->line_ascent;
2627 info->line_from = gstring->from;
2628 if (info->line_from < from)
2629 info->line_from = from;
2630 info->line_to = gstring->to;
2633 if (! control->orientation_reversed)
2635 info->x = gstring->indent;
2636 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2637 info->x += g->width;
2641 info->x = - gstring->indent;
2642 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2643 info->x -= g->width;
2644 while (g[-1].to == g->to)
2647 info->from = g->pos;
2649 info->metrics.x = g->lbearing;
2650 info->metrics.y = - gstring->line_ascent;
2651 info->metrics.height = gstring->height;
2652 info->metrics.width = - g->lbearing + g->width;
2653 if (g->rface->rfont)
2654 info->font = (MFont *) g->rface->rfont;
2657 /* info->logical_width is calculated later. */
2659 if (info->from > info->line_from)
2661 /* The logically previous glyph is on this line. */
2662 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2664 info->prev_from = g_tmp->pos;
2666 else if (info->line_from > 0
2667 && gstring->from > 0)
2669 /* The logically previous glyph is on the previous line. */
2670 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2671 gstring->from, control);
2672 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2674 info->prev_from = g_tmp->pos;
2675 M17N_OBJECT_UNREF (gst->top);
2678 info->prev_from = -1;
2680 if (GLYPH_INDEX (g) > 1)
2681 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2682 else if (! control->orientation_reversed)
2684 if (info->line_from > 0)
2688 int p = gstring->from - 1;
2690 gst = get_gstring (frame, mt, p, gstring->from, control);
2691 g_tmp = gst->glyphs + (gst->used - 2);
2692 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2693 M17N_OBJECT_UNREF (gst->top);
2696 info->left_from = info->left_to = -1;
2700 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2704 int p = gstring->to;
2706 gst = get_gstring (frame, mt, p, p + 1, control);
2707 g_tmp = gst->glyphs + (gst->used - 2);
2708 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2709 M17N_OBJECT_UNREF (gst->top);
2712 info->left_from = info->left_to = -1;
2715 if (info->to < gstring->to)
2717 /* The logically next glyph is on this line. */
2718 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2720 info->next_to = g_tmp->to;
2722 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2724 /* The logically next glyph is on the next line. */
2726 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2727 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2729 info->next_to = g_tmp->to;
2730 M17N_OBJECT_UNREF (gst->top);
2735 for (info->logical_width = (g++)->width;
2736 g->pos == pos && g->type != GLYPH_ANCHOR;
2737 info->metrics.width += g->width, info->logical_width += (g++)->width);
2738 info->metrics.width += g[-1].rbearing - g[-1].width;
2740 if (g->type != GLYPH_ANCHOR)
2741 info->right_from = g->pos, info->right_to = g->to;
2742 else if (! control->orientation_reversed)
2744 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2747 M17N_OBJECT_UNREF (gstring->top);
2748 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2750 info->right_from = g->pos, info->right_to = g->to;
2753 info->right_from = info->right_to = -1;
2757 if (info->line_from > 0)
2759 pos = gstring->from - 1;
2760 M17N_OBJECT_UNREF (gstring->top);
2761 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2763 info->right_from = g->pos, info->right_to = g->to;
2766 info->right_from = info->right_to = -1;
2769 M17N_OBJECT_UNREF (gstring->top);
2776 @brief Compute information about glyph sequence.
2778 The mdraw_glyph_list () function computes information about glyphs
2779 corresponding to the text between $FROM and $TO of M-text $MT when
2780 it is drawn on a window of frame $FRAME using the
2781 mdraw_text_with_control () function with the drawing control
2782 object $CONTROL. $GLYPHS is an array of objects to store the
2783 information, and $ARRAY_SIZE is the array size.
2785 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2786 number of actually filled elements in the place pointed by
2787 $NUM_GLYPHS_RETURN, and returns 0.
2789 Otherwise, it stores the required array size in the place pointed
2790 by $NUM_GLYPHS_RETURN, and returns -1. */
2793 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2795 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2796 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2797 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2798 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2800 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2801 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2804 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2814 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2815 MDrawControl *control, MDrawGlyph *glyphs,
2816 int array_size, int *num_glyphs_return)
2818 MGlyphString *gstring;
2823 ASSURE_CONTROL (control);
2824 *num_glyphs_return = 0;
2825 M_CHECK_RANGE (mt, from, to, -1, 0);
2826 gstring = get_gstring (frame, mt, from, to, control);
2829 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2831 if (g->type == GLYPH_BOX
2832 || g->pos < from || g->pos >= to)
2834 if (g->type == GLYPH_PAD)
2836 if (g->left_padding)
2837 pad_width = g->width;
2841 glyphs[-1].x_advance += g->width;
2847 glyphs->from = g->pos;
2849 glyphs->glyph_code = g->code;
2850 glyphs->x_off = g->xoff + pad_width;
2851 glyphs->y_off = g->yoff;
2852 glyphs->lbearing = g->lbearing;
2853 glyphs->rbearing = g->rbearing;
2854 glyphs->ascent = g->ascent;
2855 glyphs->descent = g->descent;
2856 glyphs->x_advance = g->width + pad_width;
2857 glyphs->y_advance = 0;
2858 if (g->rface->rfont)
2860 glyphs->font = (MFont *) g->rface->rfont;
2862 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2863 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2865 glyphs->fontp = g->rface->rfont->fontp;
2869 glyphs->font = NULL;
2870 glyphs->font_type = Mnil;
2871 glyphs->fontp = NULL;
2878 M17N_OBJECT_UNREF (gstring->top);
2880 *num_glyphs_return = n;
2881 return (n <= array_size ? 0 : -1);
2887 @brief Draw one or more textitems.
2889 The mdraw_text_items () function draws one or more M-texts on
2890 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2891 of the textitems to be drawn and $NITEMS is the number of
2892 textitems in the array. */
2895 @brief textitem ¤òɽ¼¨¤¹¤ë.
2897 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2898 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2899 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2901 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2905 MTextItem, mdraw_text (). */
2908 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2909 MDrawTextItem *items, int nitems)
2911 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2913 while (nitems-- > 0)
2916 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2918 mdraw_text_with_control (frame, win, x, y,
2919 items->mt, 0, mtext_nchars (items->mt),
2921 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2922 items->control, NULL, NULL, NULL);
2925 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2931 @brief Option of line breaking for drawing text.
2933 The variable #mdraw_line_break_option specifies line breaking
2934 options by logical-or of the members of #MTextLineBreakOption. It
2935 controls the line breaking algorithm of the function
2936 mdraw_default_line_break (). */
2938 int mdraw_line_break_option;
2942 @brief Calculate a line breaking position.
2944 The function mdraw_default_line_break () calculates a line
2945 breaking position based on the line number $LINE and the
2946 coordinate $Y, when a line is too long to fit within the width
2947 limit. $POS is the position of the character next to the last one
2948 that fits within the limit. $FROM is the position of the first
2949 character of the line, and $TO is the position of the last
2950 character displayed on the line if there were not width limit.
2951 $LINE and $Y are reset to 0 when a line is broken by a newline
2952 character, and incremented each time when a long line is broken
2953 because of the width limit.
2955 @return This function returns a character position to break the
2960 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2962 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2963 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2964 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2965 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2966 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2967 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2968 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2971 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2975 mdraw_default_line_break (MText *mt, int pos,
2976 int from, int to, int line, int y)
2980 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2991 @brief Obtain per character dimension information.
2993 The mdraw_per_char_extents () function computes the text dimension
2994 of each character in M-text $MT. The faces given as text
2995 properties in $MT and the default face of frame $FRAME determine
2996 the fonts to draw the text. Each successive element in
2997 $ARRAY_RETURN is set to the drawn metrics of successive
2998 characters, which is relative to the origin of the drawing, and a
2999 rectangle for each character in $MT. The number of elements of
3000 $ARRAY_RETURN must be equal to or greater than the number of
3003 If pointer $OVERALL_RETURN is not @c NULL, this function also
3004 computes the extents of the overall text and stores the results in
3005 the members of the structure pointed to by $OVERALL_RETURN. */
3008 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3010 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3011 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3012 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3013 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3014 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3015 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3016 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3018 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3019 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3020 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3022 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3025 mdraw_per_char_extents (MFrame *frame, MText *mt,
3026 MDrawMetric *array_return,
3027 MDrawMetric *overall_return)
3029 int n = mtext_nchars (mt);
3031 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3032 n, &n, overall_return, NULL);
3036 @brief clear cached information.
3038 The mdraw_clear_cache () function clear cached information
3039 on M-text $MT that was attached by any of the drawing functions.
3040 When the behavior of `format' or `line_break'
3041 member functions of MDrawControl is changed, the cache must be cleared.
3046 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3048 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3049 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3050 ¤¢¤ë¤¤¤Ï `line_break'
3051 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3057 mdraw_clear_cache (MText *mt)
3059 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);