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++)
722 if (base->left_padding && lbearing < 0)
724 base->xoff -= lbearing;
725 base->width -= lbearing;
730 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
731 g_physical_descent = MAX (g_physical_descent, base->descent);
732 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
733 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
734 extents->width += base->width;
737 gstring->physical_ascent = g_physical_ascent;
738 gstring->physical_descent = g_physical_descent;
742 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
743 by this function directly. Character glyphs are handled by
744 layouter functions registered in font drivers.
746 This function fill-in all the remaining members of glyphs. */
749 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
751 /* Default width of TAB. */
752 int tab_width = frame->space_width * (gstring->control.tab_width
753 ? gstring->control.tab_width : 8);
757 MDrawControl *control = &(gstring->control);
760 int box_line_height = 0;
761 int ignore_formatting_char = control->ignore_formatting_char;
763 gstring->ascent = gstring->descent = 0;
764 gstring->physical_ascent = gstring->physical_descent = 0;
765 gstring->width = gstring->lbearing = gstring->rbearing = 0;
769 while (g->type != GLYPH_ANCHOR)
771 if (box != g->rface->box)
773 int gidx = GLYPH_INDEX (g);
777 /* Insert the right side of the box. That glyph belongs
778 to the previous grapheme cluster. */
779 MGlyph box_glyph = g[-1];
781 box_glyph.type = GLYPH_BOX;
783 = (control->fixed_width
785 : box->inner_hmargin + box->width + box->outer_hmargin);
786 box_glyph.lbearing = 0;
787 box_glyph.rbearing = box_glyph.width;
789 box_glyph.right_padding = 1;
790 gstring->width += box_glyph.width;
791 gstring->rbearing += box_glyph.width;
792 INSERT_GLYPH (gstring, gidx, box_glyph);
799 /* Insert the left side of the box. That glyph belongs
800 to the following grapheme cluster. */
801 MGlyph box_glyph = *g;
802 int box_height = (box->width
803 + box->inner_vmargin + box->outer_vmargin);
805 if (box_line_height < box_height)
806 box_line_height = box_height;
807 box_glyph.type = GLYPH_BOX;
809 = (control->fixed_width
811 : box->inner_hmargin + box->width + box->outer_hmargin);
812 box_glyph.lbearing = 0;
813 box_glyph.rbearing = box_glyph.width;
815 box_glyph.left_padding = 1;
816 gstring->width += box_glyph.width;
817 gstring->rbearing += box_glyph.width;
818 INSERT_GLYPH (gstring, gidx, box_glyph);
824 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
825 g->type = GLYPH_SPACE;
827 if (g->type == GLYPH_CHAR)
829 MRealizedFace *rface = g->rface;
830 MRealizedFont *rfont = rface->rfont;
832 int from = GLYPH_INDEX (g);
834 for (g++; g->type == GLYPH_CHAR; g++)
835 if (! rfont != ! g->rface->rfont
836 || box != g->rface->box
837 || ((fromg->code == MCHAR_INVALID_CODE)
838 != (g->code == MCHAR_INVALID_CODE))
839 || (g->category == GLYPH_CATEGORY_FORMATTER
840 && ignore_formatting_char))
842 if (rfont && fromg->code != MCHAR_INVALID_CODE)
845 int to = GLYPH_INDEX (g);
846 MSubTextExtents extents;
848 layout_glyphs (frame, gstring, from, to, &extents);
849 extra_width = - extents.lbearing;
851 && ! control->disable_overlapping_adjustment
852 && (! control->orientation_reversed
853 ? ((to > 1 || control->align_head)
854 && g->type != GLYPH_ANCHOR)
855 : (((g->type && GLYPH_ANCHOR) || control->align_head)
860 pad.type = GLYPH_PAD;
863 pad.width = pad.rbearing = extra_width;
864 pad.left_padding = 1;
865 INSERT_GLYPH (gstring, from, pad);
867 extents.lbearing = 0;
868 extents.width += extra_width;
869 extents.rbearing += extra_width;
871 g = MGLYPH (from - 1);
872 if (g->type == GLYPH_SPACE)
874 /* The pad just inserted is absorbed (maybe
875 partially) by the previous space while
876 keeping at least some space width. For the
877 moment, we use the arbitrary width 2-pixel.
878 Perhaps, it should be decided by the current
879 face, or a default value of the current
880 frame, which is, however, not yet
882 if (extra_width + 2 < g->width)
884 g->width -= extra_width;
888 extra_width = g->width - 2;
891 gstring->width -= extra_width;
892 gstring->rbearing -= extra_width;
897 extra_width = extents.rbearing - extents.width;
899 && ! control->disable_overlapping_adjustment
900 && (GLYPH_INDEX (g) < gstring->used - 1
901 || (control->orientation_reversed && control->align_head)))
903 if (g->type == GLYPH_SPACE && box == g->rface->box)
906 pad.type = GLYPH_PAD;
909 pad.width = pad.rbearing = extra_width;
910 INSERT_GLYPH (gstring, to, pad);
915 g[-1].width += extra_width;
916 extents.width += extra_width;
919 if (gstring->lbearing > gstring->width + extents.lbearing)
920 gstring->lbearing = gstring->width + extents.lbearing;
921 if (gstring->rbearing < gstring->width + extents.rbearing)
922 gstring->rbearing = gstring->width + extents.rbearing;
923 gstring->width += extents.width;
924 if (gstring->ascent < rface->ascent)
925 gstring->ascent = rface->ascent;
926 if (gstring->descent < rface->descent)
927 gstring->descent = rface->descent;
931 for (; fromg < g; fromg++)
933 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
934 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
935 fromg->width = fromg->rbearing = 1;
937 fromg->width = fromg->rbearing = rface->space_width;
938 fromg->xoff = fromg->lbearing = 0;
939 fromg->ascent = fromg->descent = 0;
940 gstring->width += fromg->width;
941 gstring->rbearing += fromg->width;
943 if (gstring->ascent < frame->rface->ascent)
944 gstring->ascent = frame->rface->ascent;
945 if (gstring->descent < frame->descent)
946 gstring->descent = frame->rface->descent;
949 else if (g->type == GLYPH_SPACE)
952 g->width = g->rface->space_width;
953 else if (g->c == '\n')
955 g->width = control->cursor_width;
958 if (control->cursor_bidi)
960 else if (g->width < 0)
961 g->width = g->rface->space_width;
964 else if (g->c == '\t')
966 g->width = tab_width - ((gstring->indent + gstring->width)
972 if (g[-1].type == GLYPH_PAD)
974 /* This space glyph absorbs (maybe partially) the
975 previous padding glyph. */
976 g->width -= g[-1].width;
978 /* But, keep at least some space width. For the
979 moment, we use the arbitrary width 2-pixel. */
982 g->rbearing = g->width;
983 gstring->width += g->width;
984 gstring->rbearing += g->width;
987 if (gstring->ascent < g->rface->ascent)
988 gstring->ascent = g->rface->ascent;
989 if (gstring->descent < g->rface->descent)
990 gstring->descent = g->rface->descent;
996 gstring->width += g->width;
997 gstring->rbearing += g->width;
1004 /* Insert the right side of the box. */
1005 int gidx = GLYPH_INDEX (g);
1006 MGlyph box_glyph = g[-1];
1008 box_glyph.type = GLYPH_BOX;
1010 = (control->fixed_width
1011 ? frame->space_width
1012 : box->inner_hmargin + box->width + box->outer_hmargin);
1013 box_glyph.lbearing = 0;
1014 box_glyph.rbearing = box_glyph.width;
1016 box_glyph.right_padding = 1;
1017 gstring->width += box_glyph.width;
1018 gstring->rbearing += box_glyph.width;
1019 INSERT_GLYPH (gstring, gidx, box_glyph);
1022 gstring->text_ascent = gstring->ascent;
1023 gstring->text_descent = gstring->descent;
1024 if (gstring->text_ascent < gstring->physical_ascent)
1025 gstring->text_ascent = gstring->physical_ascent;
1026 if (gstring->text_descent < gstring->physical_descent)
1027 gstring->text_descent = gstring->physical_descent;
1028 gstring->line_ascent = gstring->text_ascent;
1029 gstring->line_descent = gstring->text_descent;
1030 if (box_line_height > 0)
1032 gstring->line_ascent += box_line_height;
1033 gstring->physical_ascent = gstring->line_ascent;
1034 gstring->line_descent += box_line_height;
1035 gstring->physical_descent = gstring->line_descent;
1038 if (gstring->line_ascent < control->min_line_ascent)
1039 gstring->line_ascent = control->min_line_ascent;
1040 else if (control->max_line_ascent
1041 && control->max_line_ascent > control->min_line_ascent
1042 && gstring->line_ascent > control->max_line_ascent)
1043 gstring->line_ascent = control->max_line_ascent;
1045 if (gstring->line_descent < control->min_line_descent)
1046 gstring->line_descent = control->min_line_descent;
1047 else if (control->max_line_descent
1048 && control->max_line_descent > control->min_line_descent
1049 && gstring->line_descent > control->max_line_descent)
1050 gstring->line_descent = control->max_line_descent;
1051 gstring->height = gstring->line_ascent + gstring->line_descent;
1053 if (control->orientation_reversed
1056 /* We must adjust TAB width for RTL orientation. */
1057 width = gstring->indent;
1059 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1061 if (g->type == GLYPH_CHAR && g->c == '\t')
1063 int this_width = tab_width - (width % tab_width);
1065 if (g[1].type == GLYPH_PAD)
1066 this_width -= g[1].width;
1067 if (g[-1].type == GLYPH_PAD)
1068 this_width -= g[-1].width;
1071 gstring->width += this_width - g->width;
1072 gstring->rbearing += this_width - g->width;
1073 g->width = this_width;
1074 width += this_width;
1084 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1085 MGlyphString *gstring, int from, int to,
1086 int *from_idx, int *to_idx, int *to_x)
1088 MGlyph *g = MGLYPH (1);
1089 MDrawRegion region = (MDrawRegion) NULL;
1090 MDrawControl *control = &gstring->control;
1091 int cursor_pos = -1;
1093 int cursor_bidi = control->cursor_bidi;
1095 if (control->with_cursor && control->cursor_width)
1097 if (gstring->from <= control->cursor_pos
1098 && gstring->to > control->cursor_pos)
1099 cursor_pos = control->cursor_pos;
1102 && gstring->from <= control->cursor_pos - 1
1103 && gstring->to > control->cursor_pos - 1)
1104 prev_pos = control->cursor_pos - 1;
1107 *from_idx = *to_idx = 0;
1108 while (g->type != GLYPH_ANCHOR)
1110 if (g->pos >= from && g->pos < to)
1112 MGlyph *fromg = g, *cursor = NULL;
1113 MRealizedFace *rface = g->rface;
1115 int cursor_width = 0;
1119 *from_idx = GLYPH_INDEX (g);
1120 while (g->pos >= from && g->pos < to
1121 && g->rface == rface)
1124 if (g->type != GLYPH_BOX
1125 && g->pos <= cursor_pos && g->to > cursor_pos)
1128 cursor = g, cursor_x = x + width;
1129 cursor_width += g->width;
1131 width += g++->width;
1134 && (control->as_image
1135 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1137 int this_x = x, this_width = width;
1139 if (fromg->type == GLYPH_BOX)
1140 this_x += fromg->width, this_width -= fromg->width;
1141 if (g[-1].type == GLYPH_BOX)
1142 this_width -= g[-1].width;
1143 (frame->driver->fill_space)
1144 (frame, win, rface, 0,
1145 this_x, y - gstring->text_ascent, this_width,
1146 gstring->text_ascent + gstring->text_descent,
1147 control->clip_region);
1154 rect.y = y - gstring->text_ascent;
1155 rect.height = gstring->text_ascent + gstring->text_descent;
1158 rect.width = ((control->cursor_width > 0
1159 && control->cursor_width < cursor_width)
1160 ? control->cursor_width : cursor_width);
1164 if (cursor->bidi_level % 2)
1165 rect.x += cursor_width - rect.width;
1166 (*frame->driver->fill_space)
1167 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1168 control->clip_region);
1170 region = (*frame->driver->region_from_rect) (&rect);
1172 (*frame->driver->region_add_rect) (region, &rect);
1175 if (cursor->bidi_level % 2)
1178 rect.width = cursor_width < 4 ? cursor_width : 4;
1179 (*frame->driver->fill_space)
1180 (frame, win, rface, 1,
1181 rect.x, rect.y, rect.width, rect.height,
1182 control->clip_region);
1183 (*frame->driver->region_add_rect) (region, &rect);
1195 if (fromg->type != GLYPH_BOX
1196 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1199 cursor = fromg, cursor_x = x + temp_width;
1200 cursor_width += fromg->width;
1202 temp_width += fromg++->width;
1209 if (! (cursor->bidi_level % 2))
1210 rect.x += cursor_width - 1;
1211 rect.y = y - gstring->text_ascent;
1212 rect.height = gstring->text_ascent + gstring->text_descent;
1214 (*frame->driver->fill_space)
1215 (frame, win, rface, 1,
1216 rect.x, rect.y, rect.width, rect.height,
1217 control->clip_region);
1219 region = (*frame->driver->region_from_rect) (&rect);
1221 (*frame->driver->region_add_rect) (region, &rect);
1222 rect.y += rect.height - 2;
1224 rect.width = cursor_width < 4 ? cursor_width : 4;
1225 if (! (cursor->bidi_level % 2))
1226 rect.x -= rect.width - 1;
1227 (*frame->driver->fill_space) (frame, win, rface, 1,
1228 rect.x, rect.y, rect.width, rect.height,
1229 control->clip_region);
1230 (*frame->driver->region_add_rect) (region, &rect);
1234 *to_idx = GLYPH_INDEX (g);
1244 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1245 MGlyphString *gstring, int from_idx, int to_idx,
1246 int reverse, MDrawRegion region)
1248 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1254 (*frame->driver->region_to_rect) (region, &rect);
1257 while (g != gend && x + g->rbearing <= rect.x)
1260 width -= g++->width;
1261 while (! g->enabled && g != gend)
1265 rect.x += rect.width;
1266 if (rect.x < x + width)
1269 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1271 width -= (--gend)->width;
1272 while (! gend->enabled && g != gend)
1276 while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1285 MRealizedFace *rface = g->rface;
1286 int width = g->width;
1287 MGlyph *from_g = g++;
1289 /* Handle the glyphs of the same type/face at once. */
1291 && g->type == from_g->type
1292 && g->rface == rface
1293 && ((g->code == MCHAR_INVALID_CODE)
1294 == (from_g->code == MCHAR_INVALID_CODE))
1296 width += g++->width;
1298 if (from_g->type == GLYPH_CHAR)
1300 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1301 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1304 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1307 else if (from_g->type == GLYPH_BOX)
1309 /* Draw the left or right side of a box. If
1310 from_g->lbearing is nonzero, this is the left side,
1311 else this is the right side. */
1312 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1315 if (from_g->type != GLYPH_BOX)
1318 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1319 x, y, width, region);
1322 /* Draw the top and bottom side of a box. */
1323 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1324 x, y, width, region);
1335 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1336 int *from_x, int *to_x)
1339 int left_idx = *left, right_idx = *right;
1340 int left_x, right_x, x;
1342 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1345 if (x + g->rbearing > 0)
1347 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1349 left_idx = GLYPH_INDEX (g);
1354 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1357 if (x - g->width + g->lbearing < 0)
1359 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1361 right_idx = GLYPH_INDEX (g) + 1;
1366 if (*left == left_idx && *right == right_idx)
1369 if (*left != left_idx)
1371 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1376 if (*right != right_idx)
1378 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1388 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1393 if (from <= gstring->from && to >= gstring->to)
1396 *rbearing = gstring->rbearing;
1397 return gstring->width;
1402 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1403 if (g->pos >= from && g->pos < to)
1405 if (rbearing && width + g->rbearing > *rbearing)
1406 *rbearing = width + g->rbearing;
1414 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1415 MGlyphString *gstring, int from, int to)
1417 MDrawControl *control = &gstring->control;
1419 MDrawRegion clip_region, cursor_region;
1420 int from_idx, to_idx;
1423 if (control->orientation_reversed)
1424 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1426 x += gstring->indent;
1428 /* At first, draw all glyphs without cursor. */
1429 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1430 &from_idx, &to_idx, &to_x);
1432 if (control->partial_update)
1435 rect.width = to_x - x;
1436 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1438 rect.y = y - gstring->line_ascent;
1439 rect.height = gstring->height;
1440 clip_region = (*frame->driver->region_from_rect) (&rect);
1441 if (control->clip_region)
1442 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1445 clip_region = control->clip_region;
1448 clip_region = control->clip_region;
1450 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1455 (*frame->driver->intersect_region) (cursor_region, clip_region);
1456 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1459 if (clip_region != control->clip_region)
1460 (*frame->driver->free_region) (clip_region);
1462 (*frame->driver->free_region) (cursor_region);
1466 static int gstring_num;
1469 free_gstring (void *object)
1471 MGlyphString *gstring = (MGlyphString *) object;
1474 free_gstring (gstring->next);
1475 if (gstring->size > 0)
1476 free (gstring->glyphs);
1482 static MGlyphString scratch_gstring;
1484 static MGlyphString *
1485 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1488 MGlyphString *gstring;
1490 if (pos == mt->nchars)
1494 gstring = &scratch_gstring;
1495 if (gstring->size == 0)
1500 g_tmp.type = GLYPH_ANCHOR;
1501 APPEND_GLYPH (gstring, g_tmp);
1502 APPEND_GLYPH (gstring, g_tmp);
1503 APPEND_GLYPH (gstring, g_tmp);
1504 gstring->glyphs[1].type = GLYPH_SPACE;
1505 gstring->glyphs[1].c = '\n';
1506 gstring->glyphs[1].code = '\n';
1508 gstring->from = pos;
1510 g->rface = frame->rface;
1511 g->pos = g->to = pos;
1513 g->rface = frame->rface;
1514 g->pos = pos++, g->to = pos;
1516 g->rface = frame->rface;
1517 g->pos = g->to = pos;
1522 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1523 MLIST_INIT1 (gstring, glyphs, 128);
1527 gstring->frame = frame;
1528 gstring->tick = frame->tick;
1529 gstring->top = gstring;
1530 gstring->control = *control;
1531 gstring->indent = gstring->width_limit = 0;
1532 if (control->format)
1533 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1535 gstring->width_limit = control->max_line_width;
1536 gstring->anti_alias = control->anti_alias;
1540 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1543 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1546 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1554 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1555 a width of glyphs for the character at I of MT. If I is not a
1556 beginning of a grapheme cluster, the corresponding element is
1558 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1559 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1560 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1561 pos_width[g->pos - gstring->from] += g->width;
1562 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1564 if (pos_width[i] > 0)
1566 if (width + pos_width[i] > gstring->width_limit)
1569 width += pos_width[i];
1572 pos = gstring->from + i;
1573 if (gstring->control.line_break)
1575 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1576 gstring->from, gstring->from + i,
1578 if (pos <= gstring->from)
1580 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1583 else if (pos >= gstring->to)
1588 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1591 if (pos < gstring->to)
1593 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1594 layout_glyph_string (frame, gstring);
1599 /* Return a gstring that covers a character at POS. */
1601 static MGlyphString *
1602 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1604 MGlyphString *gstring = NULL;
1606 if (pos < mtext_nchars (mt))
1608 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1611 && ((prop->start != 0
1612 && mtext_ref_char (mt, prop->start - 1) != '\n')
1613 || (prop->end < mtext_nchars (mt)
1614 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1616 mtext_detach_property (prop);
1621 gstring = prop->val;
1622 if (gstring->frame != frame
1623 || gstring->tick != frame->tick
1624 || memcmp (control, &gstring->control,
1625 (char *) (&control->with_cursor)
1626 - (char *) (control))
1627 || control->cursor_width != gstring->control.cursor_width
1628 || control->cursor_bidi != gstring->control.cursor_bidi)
1630 mtext_detach_property (prop);
1635 else if (! control->cursor_width)
1643 offset = mtext_character (mt, pos, 0, '\n');
1648 offset -= gstring->from;
1650 for (gst = gstring; gst; gst = gst->next)
1654 gst->from += offset;
1656 for (i = 0; i < gst->used; i++)
1658 gst->glyphs[i].pos += offset;
1659 gst->glyphs[i].to += offset;
1662 M17N_OBJECT_REF (gstring);
1667 int line = 0, y = 0;
1669 if (pos < mtext_nchars (mt))
1671 beg = mtext_character (mt, pos, 0, '\n');
1679 end = mtext_nchars (mt) + (control->cursor_width != 0);
1680 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1681 if (beg < mtext_nchars (mt))
1682 compose_glyph_string (frame, mt, beg, end, gstring);
1683 layout_glyph_string (frame, gstring);
1685 if (gstring->width_limit
1686 && gstring->width > gstring->width_limit)
1688 MGlyphString *gst = gstring;
1690 truncate_gstring (frame, mt, gst);
1691 while (gst->to < end)
1693 line++, y += gst->height;
1694 gst->next = alloc_gstring (frame, mt, gst->from, control,
1696 gst->next->top = gstring;
1697 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1699 layout_glyph_string (frame, gst);
1700 if (gst->width <= gst->width_limit)
1702 truncate_gstring (frame, mt, gst);
1706 if (! control->disable_caching && pos < mtext_nchars (mt))
1708 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1709 MTEXTPROP_VOLATILE_STRONG);
1711 if (end > mtext_nchars (mt))
1712 end = mtext_nchars (mt);
1713 mtext_attach_property (mt, beg, end, prop);
1714 M17N_OBJECT_UNREF (prop);
1718 while (gstring->to <= pos)
1720 if (! gstring->next)
1722 gstring = gstring->next;
1724 gstring->control = *control;
1730 static MDrawControl control_noop;
1732 #define ASSURE_CONTROL(control) \
1734 control = &control_noop; \
1739 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1740 MText *mt, int from, int to,
1741 MDrawControl *control)
1743 MGlyphString *gstring;
1745 M_CHECK_POS_X (mt, from, -1);
1746 ASSURE_CONTROL (control);
1747 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1748 to = mtext_nchars (mt) + (control->cursor_width != 0);
1752 gstring = get_gstring (frame, mt, from, to, control);
1754 MERROR (MERROR_DRAW, -1);
1755 render_glyph_string (frame, win, x, y, gstring, from, to);
1759 y += gstring->line_descent;
1760 M17N_OBJECT_UNREF (gstring->top);
1761 gstring = get_gstring (frame, mt, from, to, control);
1762 y += gstring->line_ascent;
1763 render_glyph_string (frame, win, x, y, gstring, from, to);
1766 M17N_OBJECT_UNREF (gstring->top);
1773 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1779 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1780 if (g->pos <= pos && g->to > pos)
1785 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1786 if (g->pos <= pos && g->to > pos)
1793 /* for debugging... */
1797 dump_combining_code (int code)
1799 char *vallign = "tcbB";
1800 char *hallign = "lcr";
1806 if (COMBINING_BY_CLASS_P (code))
1807 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1808 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1809 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1810 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1811 off_x = COMBINING_CODE_OFF_X (code) - 128;
1813 sprintf (work + 2, "+%d", off_y);
1815 sprintf (work + 2, "%d", off_y);
1816 else if (off_x == 0)
1817 sprintf (work + 2, ".");
1818 p = work + strlen (work);
1820 sprintf (p, ">%d", off_x);
1822 sprintf (p, "<%d", -off_x);
1824 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1825 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1831 dump_gstring (MGlyphString *gstring, int indent)
1833 char *prefix = (char *) alloca (indent + 1);
1834 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1836 memset (prefix, 32, indent);
1839 fprintf (stderr, "(glyph-string");
1841 for (g = MGLYPH (0); g < last_g; g++)
1843 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1845 g - gstring->glyphs,
1846 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1847 : g->type == GLYPH_ANCHOR ? "ANC"
1848 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1849 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1850 dump_combining_code (g->combining_code),
1851 g->width, g->bidi_level);
1852 fprintf (stderr, ")");
1856 /* m17n-X internal APIs */
1861 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1863 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1864 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1866 Minherited = msymbol ("inherited");
1867 Mcommon = msymbol ("common");
1869 McatCc = msymbol ("Cc");
1870 McatCf = msymbol ("Cf");
1872 MbidiR = msymbol ("R");
1873 MbidiAL = msymbol ("AL");
1874 MbidiRLE = msymbol ("RLE");
1875 MbidiRLO = msymbol ("RLO");
1876 MbidiBN = msymbol ("BN");
1877 MbidiS = msymbol ("S");
1879 fribidi_set_mirroring (TRUE);
1882 M_break_at_space = msymbol ("bs");
1883 M_break_at_word = msymbol ("bw");
1884 M_break_at_any = msymbol ("ba");
1885 M_kinsoku_bol = msymbol ("kb");
1886 M_kinsoku_eol = msymbol ("ke");
1894 MLIST_FREE1 (&scratch_gstring, glyphs);
1895 M17N_OBJECT_UNREF (linebreak_table);
1896 linebreak_table = NULL;
1900 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1904 /*** @addtogroup m17nDraw */
1909 @brief Draw an M-text on a window.
1911 The mdraw_text () function draws the text between $FROM and $TO of
1912 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1914 The appearance of the text (size, style, color, etc) is specified
1915 by the value of the text property whose key is @c Mface. If the
1916 M-text or a part of the M-text does not have such a text property,
1917 the default face of $FRAME is used.
1919 The font used to draw a character in the M-text is selected from
1920 the value of the fontset property of a face by the following
1925 <li> Search the text properties given to the character for the one
1926 whose key is @c Mcharset; its value should be either a symbol
1927 specifying a charset or #Mnil. If the value is #Mnil,
1928 proceed to the next step.
1930 Otherwise, search the mapping table of the fontset for the
1931 charset. If no entry is found proceed to the next step.
1933 If an entry is found, use one of the fonts in the entry that
1934 has a glyph for the character and that matches best with the
1935 face properties. If no such font exists, proceed to the next
1938 <li> Get the character property "script" of the character. If it is
1939 inherited, get the script property from the previous
1940 characters. If there is no previous character, or none of
1941 them has the script property other than inherited, proceed to
1944 Search the text properties given to the character for the one
1945 whose key is @c Mlanguage; its value should be either a
1946 symbol specifying a language or @c Mnil.
1948 Search the mapping table of the fontset for the combination
1949 of the script and language. If no entry is found, proceed to
1952 If an entry is found, use one of the fonts in the entry that
1953 has a glyph for the character and that matches best with the
1954 face properties. If no such font exists, proceed to the next
1957 <li> Search the fall-back table of the fontset for a font that has
1958 a glyph of the character. If such a font is found, use that
1963 If no font is found by the algorithm above, this function draws an
1964 empty box for the character.
1966 This function draws only the glyph foreground. To specify the
1967 background color, use mdraw_image_text () or
1968 mdraw_text_with_control ().
1970 This function is the counterpart of <tt>XDrawString ()</tt>,
1971 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1972 in the X Window System.
1975 If the operation was successful, mdraw_text () returns 0. If an
1976 error is detected, it returns -1 and assigns an error code to the
1977 external variable #merror_code. */
1979 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1981 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1982 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1984 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1985 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1986 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1987 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1989 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1990 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1994 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1995 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1996 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1997 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1998 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1999 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2001 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
2002 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2004 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
2005 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2006 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2008 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2009 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2011 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2012 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2014 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2015 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2017 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2018 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2022 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2024 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2025 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2027 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2028 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2031 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2032 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2034 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2041 mdraw_image_text () */
2044 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2045 MText *mt, int from, int to)
2047 MDrawControl control;
2049 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2050 memset (&control, 0, sizeof control);
2051 control.as_image = 0;
2052 return draw_text (frame, win, x, y, mt, from, to, &control);
2059 @brief Draw an M-text on a window as an image.
2061 The mdraw_image_text () function draws the text between $FROM and
2062 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2063 coordinate ($X, $Y).
2065 The way to draw a text is the same as in mdraw_text () except that
2066 this function also draws the background with the color specified
2069 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2070 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2071 functions in the X Window System.
2074 If the operation was successful, mdraw_image_text () returns 0.
2075 If an error is detected, it returns -1 and assigns an error code
2076 to the external variable #merror_code. */
2079 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2081 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2082 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2083 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2085 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2086 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2088 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2089 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2093 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2094 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2096 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2106 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2107 MText *mt, int from, int to)
2109 MDrawControl control;
2111 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2112 memset (&control, 0, sizeof control);
2113 control.as_image = 1;
2114 return draw_text (frame, win, x, y, mt, from, to, &control);
2120 @brief Draw an M-text on a window with fine control.
2122 The mdraw_text_with_control () function draws the text between
2123 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2124 coordinate ($X, $Y).
2126 The way to draw a text is the same as in mdraw_text () except that
2127 this function also follows what specified in the drawing control
2130 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2131 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2132 breaks lines and the following characters are drawn in the next
2133 line. See the documentation of the structure @ MDrawControl for
2137 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2139 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2140 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2143 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2144 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2146 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2147 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2148 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2151 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2152 MText *mt, int from, int to, MDrawControl *control)
2154 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2155 return draw_text (frame, win, x, y, mt, from, to, control);
2161 @brief Compute text pixel width.
2163 The mdraw_text_extents () function computes the width of text
2164 between $FROM and $TO of M-text $MT when it is drawn on a window
2165 of frame $FRAME using the mdraw_text_with_control () function with
2166 the drawing control object $CONTROL.
2168 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2169 the bounding box of character ink of the M-text, and stores the
2170 results in the members of the structure pointed to by
2171 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2172 surrounding box, the box is included in the bounding box.
2174 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2175 computes the bounding box that provides minimum spacing to other
2176 graphical features (such as surrounding box) for the M-text, and
2177 stores the results in the members of the structure pointed to by
2178 $OVERALL_LOGICAL_RETURN.
2180 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2181 computes the bounding box that provides minimum spacing to the
2182 other M-text drawn, and stores the results in the members of the
2183 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2184 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2185 min_line_ascent, min_line_descent, max_line_ascent, and
2186 max_line_descent of $CONTROL are all zero.
2189 This function returns the width of the text to be drawn in the
2190 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2191 text is drawn in multiple physical lines, it returns the width of
2192 the widest line. If an error occurs, it returns -1 and assigns an
2193 error code to the external variable #merror_code. */
2197 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2199 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2200 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2201 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2203 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2204 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2205 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2206 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2208 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2209 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2210 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2211 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2213 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2214 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2215 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2216 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2217 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2218 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2221 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2222 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2223 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2225 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2232 mdraw_text_extents (MFrame *frame,
2233 MText *mt, int from, int to, MDrawControl *control,
2234 MDrawMetric *overall_ink_return,
2235 MDrawMetric *overall_logical_return,
2236 MDrawMetric *overall_line_return)
2238 MGlyphString *gstring;
2240 int width, rbearing;
2242 ASSURE_CONTROL (control);
2243 M_CHECK_POS_X (mt, from, -1);
2244 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2245 to = mtext_nchars (mt) + (control->cursor_width != 0);
2249 gstring = get_gstring (frame, mt, from, to, control);
2251 MERROR (MERROR_DRAW, -1);
2252 width = gstring_width (gstring, from, to, &rbearing);
2253 if (overall_ink_return)
2255 overall_ink_return->y = - gstring->physical_ascent;
2256 overall_ink_return->x = gstring->lbearing;
2258 if (overall_logical_return)
2260 overall_logical_return->y = - gstring->ascent;
2261 overall_logical_return->x = 0;
2263 if (overall_line_return)
2265 overall_line_return->y = - gstring->line_ascent;
2266 overall_line_return->x = gstring->lbearing;
2269 for (from = gstring->to; from < to; from = gstring->to)
2271 int this_width, this_rbearing;
2273 y += gstring->line_descent;
2274 M17N_OBJECT_UNREF (gstring->top);
2275 gstring = get_gstring (frame, mt, from, to, control);
2276 this_width = gstring_width (gstring, from, to, &this_rbearing);
2277 y += gstring->line_ascent;
2278 if (width < this_width)
2280 if (rbearing < this_rbearing)
2281 rbearing = this_rbearing;
2283 if (overall_ink_return)
2285 overall_ink_return->width = rbearing;
2286 overall_ink_return->height
2287 = y + gstring->physical_descent - overall_ink_return->y;
2289 if (overall_logical_return)
2291 overall_logical_return->width = width;
2292 overall_logical_return->height
2293 = y + gstring->descent - overall_logical_return->y;
2295 if (overall_line_return)
2297 overall_line_return->width = MAX (width, rbearing);
2298 overall_line_return->height
2299 = y + gstring->line_descent - overall_line_return->y;
2302 M17N_OBJECT_UNREF (gstring->top);
2309 @brief Compute the text dimensions of each character of M-text.
2311 The mdraw_text_per_char_extents () function computes the drawn
2312 metric of each character between $FROM and $TO of M-text $MT
2313 assuming that they are drawn on a window of frame $FRAME using the
2314 mdraw_text_with_control () function with the drawing control
2317 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2318 $LOGICAL_ARRAY_RETURN. Each successive element of
2319 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2320 ink and logical metrics of successive characters respectively,
2321 relative to the drawing origin of the M-text. The number of
2322 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2323 been set is returned to $NUM_CHARS_RETURN.
2325 If $ARRAY_SIZE is too small to return all metrics, the function
2326 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2327 Otherwise, it returns zero.
2329 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2330 @c NULL, this function also computes the metrics of the overall
2331 text and stores the results in the members of the structure
2332 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2334 If $CONTROL->two_dimensional is nonzero, this function computes
2335 only the metrics of characters in the first line. */
2337 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2339 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2340 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2341 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2343 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2344 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2345 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2346 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2347 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2349 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2350 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2353 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2354 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2355 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2357 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2360 mdraw_text_per_char_extents (MFrame *frame,
2361 MText *mt, int from, int to,
2362 MDrawControl *control,
2363 MDrawMetric *ink_array_return,
2364 MDrawMetric *logical_array_return,
2366 int *num_chars_return,
2367 MDrawMetric *overall_ink_return,
2368 MDrawMetric *overall_logical_return)
2370 MGlyphString *gstring;
2374 ASSURE_CONTROL (control);
2375 *num_chars_return = to - from;
2376 if (array_size < *num_chars_return)
2377 MERROR (MERROR_DRAW, -1);
2378 if (overall_logical_return)
2379 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2380 if (overall_ink_return)
2381 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2383 M_CHECK_RANGE (mt, from, to, -1, 0);
2384 gstring = get_gstring (frame, mt, from, to, control);
2387 *num_chars_return = 0;
2391 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2392 if (g->pos >= from && g->pos < to)
2396 int width = g->width;
2397 int lbearing = g->lbearing;
2398 int rbearing = g->rbearing;
2399 int ascent = g->ascent;
2400 int descent = g->descent;
2402 int logical_descent;
2404 if (g->rface->rfont)
2406 logical_ascent = g->rface->rfont->ascent;
2407 logical_descent = g->rface->rfont->descent;
2411 logical_ascent = g->rface->ascent;
2412 logical_descent = g->rface->descent;
2414 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2416 if (lbearing < width + g->lbearing)
2417 lbearing = width + g->lbearing;
2418 if (rbearing < width + g->rbearing)
2419 rbearing = width + g->rbearing;
2421 if (ascent < g->ascent)
2423 if (descent < g->descent)
2424 descent = g->descent;
2431 if (ink_array_return)
2433 ink_array_return[start - from].x = x + lbearing;
2434 ink_array_return[start - from].y = - ascent;
2435 ink_array_return[start - from].width = rbearing - lbearing;
2436 ink_array_return[start - from].height = ascent + descent;
2438 if (logical_array_return)
2440 logical_array_return[start - from].x = x;
2441 logical_array_return[start - from].y = - logical_descent;
2442 logical_array_return[start - from].height
2443 = logical_ascent + logical_descent;
2444 logical_array_return[start - from].width = width;
2452 if (overall_ink_return)
2454 overall_ink_return->y = - gstring->line_ascent;
2455 overall_ink_return->x = gstring->lbearing;
2456 overall_ink_return->width = x - gstring->lbearing;
2457 overall_ink_return->height = gstring->height;
2459 if (overall_logical_return)
2461 overall_logical_return->y = - gstring->ascent;
2462 overall_logical_return->x = 0;
2463 overall_logical_return->width = x;
2464 overall_logical_return->height = gstring->ascent + gstring->descent;
2467 M17N_OBJECT_UNREF (gstring->top);
2474 @brief Return the character position nearest to the coordinates.
2476 The mdraw_coordinates_position () function checks which character
2477 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2478 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2479 mdraw_text_with_control () function with the drawing control
2480 object $CONTROL. Here, the character position means the number of
2481 characters that precede the character in question in $MT, that is,
2482 the character position of the first character is 0.
2484 $FRAME is used only to get the default face information.
2487 If the glyph image of a character covers coordinate ($X, $Y),
2488 mdraw_coordinates_position () returns the character position of
2490 If $Y is less than the minimum Y-coordinate of the drawn area, it
2492 If $Y is greater than the maximum Y-coordinate of the drawn area,
2494 If $Y fits in with the drawn area but $X is less than the minimum
2495 X-coordinate, it returns the character position of the first
2496 character drawn on the line $Y.\n\n
2497 If $Y fits in with the drawn area but $X is greater than the
2498 maximum X-coordinate, it returns the character position of the
2499 last character drawn on the line $Y. */
2502 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2504 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2505 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2506 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2507 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2508 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2509 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2511 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2514 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2515 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2516 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2517 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2518 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2519 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2520 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2521 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2524 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2525 int x_offset, int y_offset, MDrawControl *control)
2527 MGlyphString *gstring;
2532 M_CHECK_POS_X (mt, from, -1);
2533 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2534 to = mtext_nchars (mt) + (control->cursor_width != 0);
2540 ASSURE_CONTROL (control);
2541 gstring = get_gstring (frame, mt, from, to, control);
2542 while (y + gstring->line_descent <= y_offset
2543 && gstring->to < to)
2546 y += gstring->line_descent;
2547 M17N_OBJECT_UNREF (gstring->top);
2548 gstring = get_gstring (frame, mt, from, to, control);
2549 y += gstring->line_ascent;
2552 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2553 if (! control->orientation_reversed)
2555 width = gstring->indent;
2556 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2557 if (g->pos >= from && g->pos < to)
2560 if (width > x_offset)
2566 width = - gstring->indent;
2567 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2568 if (g->pos >= from && g->pos < to)
2571 if (width < x_offset)
2575 if (g->type == GLYPH_ANCHOR
2576 && control->two_dimensional
2580 M17N_OBJECT_UNREF (gstring->top);
2588 @brief Compute information about a glyph.
2590 The mdraw_glyph_info () function computes information about a
2591 glyph that covers a character at position $POS of the M-text $MT
2592 assuming that the text is drawn from the character at $FROM of $MT
2593 on a window of frame $FRAME using the mdraw_text_with_control ()
2594 function with the drawing control object $CONTROL.
2596 The information is stored in the members of $INFO. */
2598 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2600 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2601 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2602 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2603 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2605 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2613 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2614 MDrawControl *control, MDrawGlyphInfo *info)
2616 MGlyphString *gstring;
2620 M_CHECK_RANGE_X (mt, from, pos, -1);
2622 ASSURE_CONTROL (control);
2623 gstring = get_gstring (frame, mt, from, pos + 1, control);
2625 MERROR (MERROR_DRAW, -1);
2626 while (gstring->to <= pos)
2628 y += gstring->line_descent;
2629 M17N_OBJECT_UNREF (gstring->top);
2630 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2631 y += gstring->line_ascent;
2633 info->line_from = gstring->from;
2634 if (info->line_from < from)
2635 info->line_from = from;
2636 info->line_to = gstring->to;
2639 if (! control->orientation_reversed)
2641 info->x = gstring->indent;
2642 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2643 info->x += g->width;
2647 info->x = - gstring->indent;
2648 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2649 info->x -= g->width;
2650 while (g[-1].to == g->to)
2653 info->from = g->pos;
2655 info->metrics.x = g->lbearing;
2656 info->metrics.y = - gstring->line_ascent;
2657 info->metrics.height = gstring->height;
2658 info->metrics.width = - g->lbearing + g->width;
2659 if (g->rface->rfont)
2660 info->font = (MFont *) g->rface->rfont;
2663 /* info->logical_width is calculated later. */
2665 if (info->from > info->line_from)
2667 /* The logically previous glyph is on this line. */
2668 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2670 info->prev_from = g_tmp->pos;
2672 else if (info->line_from > 0
2673 && gstring->from > 0)
2675 /* The logically previous glyph is on the previous line. */
2676 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2677 gstring->from, control);
2678 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2680 info->prev_from = g_tmp->pos;
2681 M17N_OBJECT_UNREF (gst->top);
2684 info->prev_from = -1;
2686 if (GLYPH_INDEX (g) > 1)
2687 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2688 else if (! control->orientation_reversed)
2690 if (info->line_from > 0)
2694 int p = gstring->from - 1;
2696 gst = get_gstring (frame, mt, p, gstring->from, control);
2697 g_tmp = gst->glyphs + (gst->used - 2);
2698 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2699 M17N_OBJECT_UNREF (gst->top);
2702 info->left_from = info->left_to = -1;
2706 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2710 int p = gstring->to;
2712 gst = get_gstring (frame, mt, p, p + 1, control);
2713 g_tmp = gst->glyphs + (gst->used - 2);
2714 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2715 M17N_OBJECT_UNREF (gst->top);
2718 info->left_from = info->left_to = -1;
2721 if (info->to < gstring->to)
2723 /* The logically next glyph is on this line. */
2724 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2726 info->next_to = g_tmp->to;
2728 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2730 /* The logically next glyph is on the next line. */
2732 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2733 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2735 info->next_to = g_tmp->to;
2736 M17N_OBJECT_UNREF (gst->top);
2741 for (info->logical_width = (g++)->width;
2742 g->pos == pos && g->type != GLYPH_ANCHOR;
2743 info->metrics.width += g->width, info->logical_width += (g++)->width);
2744 info->metrics.width += g[-1].rbearing - g[-1].width;
2746 if (g->type != GLYPH_ANCHOR)
2747 info->right_from = g->pos, info->right_to = g->to;
2748 else if (! control->orientation_reversed)
2750 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2753 M17N_OBJECT_UNREF (gstring->top);
2754 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2756 info->right_from = g->pos, info->right_to = g->to;
2759 info->right_from = info->right_to = -1;
2763 if (info->line_from > 0)
2765 pos = gstring->from - 1;
2766 M17N_OBJECT_UNREF (gstring->top);
2767 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2769 info->right_from = g->pos, info->right_to = g->to;
2772 info->right_from = info->right_to = -1;
2775 M17N_OBJECT_UNREF (gstring->top);
2782 @brief Compute information about glyph sequence.
2784 The mdraw_glyph_list () function computes information about glyphs
2785 corresponding to the text between $FROM and $TO of M-text $MT when
2786 it is drawn on a window of frame $FRAME using the
2787 mdraw_text_with_control () function with the drawing control
2788 object $CONTROL. $GLYPHS is an array of objects to store the
2789 information, and $ARRAY_SIZE is the array size.
2791 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2792 number of actually filled elements in the place pointed by
2793 $NUM_GLYPHS_RETURN, and returns 0.
2795 Otherwise, it stores the required array size in the place pointed
2796 by $NUM_GLYPHS_RETURN, and returns -1. */
2799 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2801 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2802 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2803 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2804 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2806 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2807 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2810 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2820 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2821 MDrawControl *control, MDrawGlyph *glyphs,
2822 int array_size, int *num_glyphs_return)
2824 MGlyphString *gstring;
2829 ASSURE_CONTROL (control);
2830 *num_glyphs_return = 0;
2831 M_CHECK_RANGE (mt, from, to, -1, 0);
2832 gstring = get_gstring (frame, mt, from, to, control);
2835 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2837 if (g->type == GLYPH_BOX
2838 || g->pos < from || g->pos >= to)
2840 if (g->type == GLYPH_PAD)
2842 if (g->left_padding)
2843 pad_width = g->width;
2847 glyphs[-1].x_advance += g->width;
2853 glyphs->from = g->pos;
2855 glyphs->glyph_code = g->code;
2856 glyphs->x_off = g->xoff + pad_width;
2857 glyphs->y_off = g->yoff;
2858 glyphs->lbearing = g->lbearing;
2859 glyphs->rbearing = g->rbearing;
2860 glyphs->ascent = g->ascent;
2861 glyphs->descent = g->descent;
2862 glyphs->x_advance = g->width + pad_width;
2863 glyphs->y_advance = 0;
2864 if (g->rface->rfont)
2866 glyphs->font = (MFont *) g->rface->rfont;
2868 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2869 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2871 glyphs->fontp = g->rface->rfont->fontp;
2875 glyphs->font = NULL;
2876 glyphs->font_type = Mnil;
2877 glyphs->fontp = NULL;
2884 M17N_OBJECT_UNREF (gstring->top);
2886 *num_glyphs_return = n;
2887 return (n <= array_size ? 0 : -1);
2893 @brief Draw one or more textitems.
2895 The mdraw_text_items () function draws one or more M-texts on
2896 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2897 of the textitems to be drawn and $NITEMS is the number of
2898 textitems in the array. */
2901 @brief textitem ¤òɽ¼¨¤¹¤ë.
2903 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2904 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2905 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2907 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2911 MTextItem, mdraw_text (). */
2914 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2915 MDrawTextItem *items, int nitems)
2917 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2919 while (nitems-- > 0)
2922 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2924 mdraw_text_with_control (frame, win, x, y,
2925 items->mt, 0, mtext_nchars (items->mt),
2927 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2928 items->control, NULL, NULL, NULL);
2931 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2937 @brief Option of line breaking for drawing text.
2939 The variable #mdraw_line_break_option specifies line breaking
2940 options by logical-or of the members of #MTextLineBreakOption. It
2941 controls the line breaking algorithm of the function
2942 mdraw_default_line_break (). */
2944 int mdraw_line_break_option;
2948 @brief Calculate a line breaking position.
2950 The function mdraw_default_line_break () calculates a line
2951 breaking position based on the line number $LINE and the
2952 coordinate $Y, when a line is too long to fit within the width
2953 limit. $POS is the position of the character next to the last one
2954 that fits within the limit. $FROM is the position of the first
2955 character of the line, and $TO is the position of the last
2956 character displayed on the line if there were not width limit.
2957 $LINE and $Y are reset to 0 when a line is broken by a newline
2958 character, and incremented each time when a long line is broken
2959 because of the width limit.
2961 @return This function returns a character position to break the
2966 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2968 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2969 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2970 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2971 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2972 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2973 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2974 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2977 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2981 mdraw_default_line_break (MText *mt, int pos,
2982 int from, int to, int line, int y)
2986 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2997 @brief Obtain per character dimension information.
2999 The mdraw_per_char_extents () function computes the text dimension
3000 of each character in M-text $MT. The faces given as text
3001 properties in $MT and the default face of frame $FRAME determine
3002 the fonts to draw the text. Each successive element in
3003 $ARRAY_RETURN is set to the drawn metrics of successive
3004 characters, which is relative to the origin of the drawing, and a
3005 rectangle for each character in $MT. The number of elements of
3006 $ARRAY_RETURN must be equal to or greater than the number of
3009 If pointer $OVERALL_RETURN is not @c NULL, this function also
3010 computes the extents of the overall text and stores the results in
3011 the members of the structure pointed to by $OVERALL_RETURN. */
3014 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3016 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3017 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3018 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3019 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3020 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3021 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3022 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3024 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3025 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3026 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3028 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3031 mdraw_per_char_extents (MFrame *frame, MText *mt,
3032 MDrawMetric *array_return,
3033 MDrawMetric *overall_return)
3035 int n = mtext_nchars (mt);
3037 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3038 n, &n, overall_return, NULL);
3042 @brief clear cached information.
3044 The mdraw_clear_cache () function clear cached information
3045 on M-text $MT that was attached by any of the drawing functions.
3046 When the behavior of `format' or `line_break'
3047 member functions of MDrawControl is changed, the cache must be cleared.
3052 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3054 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3055 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3056 ¤¢¤ë¤¤¤Ï `line_break'
3057 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3063 mdraw_clear_cache (MText *mt)
3065 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);