1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004, 2005, 2006
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., 51 Franklin Street, Fifth Floor,
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 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;
100 static MSymbol MbidiNSM;
103 visual_order (MGlyphString *gstring)
105 int len = gstring->used - 2;
107 int bidi_sensitive = gstring->control.orientation_reversed;
111 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
112 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
114 FriBidiStrIndex *indices;
115 FriBidiLevel *levels;
116 #else /* not HAVE_FRIBIDI */
117 int *logical = alloca (sizeof (int) * len);
119 char *levels = alloca (len);
121 memset (levels, 0, sizeof (int) * len);
122 #endif /* not HAVE_FRIBIDI */
124 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
129 #endif /* not HAVE_FRIBIDI */
132 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
134 if (bidi == MbidiR || bidi == MbidiAL
135 || bidi == MbidiRLE || bidi == MbidiRLO)
140 #endif /* not HAVE_FRIBIDI */
143 else if (bidi == MbidiNSM && i > 0 && levels[i - 1])
145 #endif /* not HAVE_FRIBIDI */
150 if (! bidi_sensitive)
153 glyphs = alloca (sizeof (MGlyph) * len);
154 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
156 visual = alloca (sizeof (FriBidiChar) * (len + 1));
157 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
158 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
160 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
161 #else /* not HAVE_FRIBIDI */
162 indices = alloca (sizeof (int) * len);
163 for (i = 0; i < len; i++)
169 for (j = i + 1; j < len && levels[j]; j++);
170 for (k = j--; i < k; i++, j--)
177 #endif /* not HAVE_FRIBIDI */
179 for (i = 0; i < len;)
181 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
183 /* Length of grapheme-cluster */
188 if (visual[j] != logical[i])
193 g->code = mfont__encode_char (NULL, (MFont *) g->rface->rfont,
196 #endif /* HAVE_FRIBIDI */
197 g->bidi_level = levels[i];
198 for (seglen = 1, g++;
199 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
200 || glyphs[i + seglen].combining_code);
203 g->bidi_level = levels[i];
204 if (indices[i + seglen] < j)
205 j = indices[i + seglen];
207 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
213 reorder_combining_chars (MGlyphString *gstring, int from, int to)
215 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
221 for (g = gbeg; g != gend; g++)
222 if (COMBINING_CODE_CLASS (g->combining_code) > 0
223 && (COMBINING_CODE_CLASS (g[-1].combining_code)
224 > COMBINING_CODE_CLASS (g->combining_code)))
235 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
236 displaying them on FRAME.
238 This function fills these members:
239 pos, to, c, code, rface, bidi_level, categories, type, combining_code
240 The other members are filled by layout_glyph_string. */
243 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
244 MGlyphString *gstring)
246 MRealizedFace *default_rface = frame->rface;
247 int stop, face_change, language_change, charset_change, font_change;
248 MGlyph g_tmp, *g, *last_g;
250 MSymbol language = Mnil, script = Mnil, charset = Mnil;
251 MSymbol non_latin_script = Mnil;
252 MRealizedFace *rface = default_rface;
253 MRealizedFont *rfont;
254 int size = gstring->control.fixed_width;
257 MLIST_RESET (gstring);
258 gstring->from = from;
260 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
261 <category> and <rface> members.*/
264 /** Put anchor glyphs at the head and tail. */
265 g_tmp.type = GLYPH_ANCHOR;
266 g_tmp.pos = g_tmp.to = from;
267 APPEND_GLYPH (gstring, g_tmp);
268 stop = face_change = font_change = pos = from;
278 if (pos < mtext_nchars (mt))
280 MFont *font = rface->font;
284 if (pos == font_change)
286 font = mtext_get_prop (mt, pos, Mfont);
287 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
288 if (font_change == mtext_nchars (mt))
291 if (pos == face_change)
293 num = mtext_get_prop_values (mt, pos, Mface,
294 (void **) faces, 64);
295 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
296 if (face_change == mtext_nchars (mt))
301 faces[0] = &rface->face;
304 rface = mface__realize (frame, faces, num, size, font);
307 rface = default_rface;
309 if (stop > font_change)
311 if (stop > face_change)
315 if (pos < mtext_nchars (mt))
316 c = mtext_ref_char (mt, pos);
320 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
325 category = mchar_get_prop (c, Mcategory);
326 if (category == McatCf)
327 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
328 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
329 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
331 g_tmp.category = GLYPH_CATEGORY_NORMAL;
333 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
337 ctrl[0] = ctrl[1] = g_tmp;
339 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
340 APPEND_GLYPH (gstring, ctrl[0]);
341 APPEND_GLYPH (gstring, ctrl[1]);
344 APPEND_GLYPH (gstring, g_tmp);
345 if (c == '\n' && gstring->control.two_dimensional)
348 /* Append an anchor glyph. */
350 g_tmp.type = GLYPH_ANCHOR;
351 g_tmp.pos = g_tmp.to = pos;
352 APPEND_GLYPH (gstring, g_tmp);
355 /* The next loop is to change each <rface> member for non-ASCII
356 characters if necessary. */
357 stop = charset_change = language_change = from;
358 rfont = default_rface->rfont;
359 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
365 /* Short cut for the obvious case. */
366 this_script = Mlatin;
369 this_script = (MSymbol) mchar_get_prop (c, Mscript);
370 if (this_script == Minherited || this_script == Mcommon)
371 this_script = script;
372 if (this_script == Mcommon)
373 this_script = non_latin_script;
374 if (this_script == Mcommon)
376 /* Search forward for a character that explicitly
377 specifies a non-latin script. */
381 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
383 && (sym = mchar_get_prop (g1->c, Mscript)) != Mcommon
384 && sym != Minherited)
393 if (pos == stop || script != this_script || g->rface->rfont != rfont)
396 last_g = mface__for_chars (script, language, charset,
398 script = this_script;
399 if (script != Mnil && script != Mlatin)
400 non_latin_script = script;
401 rfont = g->rface->ascii_rface->rfont;
404 if (pos < mtext_nchars (mt) && pos == language_change)
406 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
407 mtext_prop_range (mt, Mlanguage, pos, NULL,
408 &language_change, 0);
410 if (pos < mtext_nchars (mt) && pos == charset_change)
412 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
413 mtext_prop_range (mt, Mcharset, pos, NULL,
417 if (stop > language_change)
418 stop = language_change;
419 if (stop > charset_change)
420 stop = charset_change;
425 last_g = mface__for_chars (script, language, charset, last_g, g, size);
427 /* The next loop is to run FLT or perform the default combining if
429 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
433 if (this->type == GLYPH_CHAR && this->rface->rfont)
437 if (this->rface->layouter != Mnil)
442 for (prev = MGLYPH (start - 1);
443 (prev->type == GLYPH_CHAR
444 && prev->category == GLYPH_CATEGORY_FORMATTER
445 && (code = mfont__encode_char (NULL,
446 (MFont *) this->rface->rfont,
448 != MCHAR_INVALID_CODE));
450 if (prev->rface->rfont != this->rface->rfont)
452 prev->rface->rfont = this->rface->rfont;
457 (g->type == GLYPH_CHAR
458 && g->rface->layouter == this->rface->layouter
459 && (g->rface->rfont == this->rface->rfont
460 || (g->category == GLYPH_CATEGORY_FORMATTER
461 && ((code = mfont__encode_char (NULL,
462 (MFont *) this->rface->rfont,
465 != MCHAR_INVALID_CODE))));
467 if (g->rface->rfont != this->rface->rfont)
469 g->rface->rfont = this->rface->rfont;
472 i = mfont__flt_run (gstring, start, i, this->rface);
476 while (this->type == GLYPH_CHAR
478 && this->category == GLYPH_CATEGORY_MODIFIER
479 && this->rface->rfont
480 && this->rface->rfont->layouter == Mnil)
482 int class = (int) mchar_get_prop (this->c,
485 = MAKE_COMBINING_CODE_BY_CLASS (class);
489 reorder_combining_chars (gstring, start, i);
490 if (this->type == GLYPH_ANCHOR)
499 /* At last, reorder glyphs visually if necessary. */
500 if (gstring->control.enable_bidi)
501 visual_order (gstring);
506 combining_code_from_class (int class)
511 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
512 else if (class == 200) /* below left attached */
513 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
514 else if (class == 202) /* below attached*/
515 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
516 else if (class == 204) /* below right attached */
517 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
518 else if (class == 208) /* left attached */
519 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
520 else if (class == 210) /* right attached */
521 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
522 else if (class == 212) /* above left attached */
523 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
524 else if (class == 214) /* above attached */
525 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
526 else if (class == 216) /* above right attached */
527 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
528 else if (class == 218) /* below left */
529 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
530 else if (class == 220) /* below */
531 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
532 else if (class == 222) /* below right */
533 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
534 else if (class == 224) /* left */
535 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
536 else if (class == 226) /* right */
537 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
538 else if (class == 228) /* above left */
539 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
540 else if (class == 230) /* above */
541 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
542 else if (class == 232) /* above right */
543 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
544 else if (class == 233) /* double below */
545 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
546 else if (class == 234) /* double above */
547 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
548 else if (class == 240) /* iota subscript */
549 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
551 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
557 int width, lbearing, rbearing;
561 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
562 MSubTextExtents *extents)
564 int g_physical_ascent, g_physical_descent;
565 MGlyph *g = MGLYPH (from);
566 MGlyph *last_g = MGLYPH (to);
569 g_physical_ascent = gstring->physical_ascent;
570 g_physical_descent = gstring->physical_descent;
571 extents->width = extents->lbearing = extents->rbearing = 0;
573 for (i = from; i < to;)
575 if ( MGLYPH (i)->otf_encoded)
581 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
582 mfont__get_metric (gstring, j, i);
590 MRealizedFont *rfont = base->rface->rfont;
591 int size = rfont->spec.size;
592 int width, lbearing, rbearing;
594 if (g == last_g || ! g->combining_code)
597 if (base->width == 0 && ! base->left_padding && ! base->right_padding
598 && GLYPH_INDEX (base) > from)
600 MGlyph *prev = base - 1;
602 if (base->pos < prev->pos)
603 prev->pos = base->pos;
605 base->pos = prev->pos;
606 if (base->to > prev->to)
612 if (base->left_padding && base->lbearing < 0)
614 base->xoff = - base->lbearing;
615 if (base->rbearing < 0)
616 base->width = base->rbearing - base->lbearing;
618 base->width += base->xoff;
619 base->rbearing += base->xoff;
622 if (base->right_padding && base->rbearing > base->width)
624 base->width = base->rbearing;
626 lbearing = base->lbearing;
627 rbearing = base->rbearing;
631 /* With combining glyphs. */
632 int left = -base->width;
634 int top = - base->ascent;
635 int bottom = base->descent;
636 int height = bottom - top;
637 int begin = base->pos;
642 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
643 rbearing = base->rbearing;
645 while (g != last_g && g->combining_code)
647 int combining_code = g->combining_code;
651 else if (end < g->to)
654 if (! COMBINING_PRECOMPUTED_P (combining_code))
656 int base_x, base_y, add_x, add_y, off_x, off_y;
658 if (COMBINING_BY_CLASS_P (combining_code))
659 g->combining_code = combining_code
660 = combining_code_from_class (COMBINING_CODE_CLASS
663 rfont = g->rface->rfont;
664 size = rfont->spec.size;
665 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
667 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
669 base_x = COMBINING_CODE_BASE_X (combining_code);
670 base_y = COMBINING_CODE_BASE_Y (combining_code);
671 add_x = COMBINING_CODE_ADD_X (combining_code);
672 add_y = COMBINING_CODE_ADD_Y (combining_code);
674 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
677 if (g->xoff + g->width > right)
678 right = g->xoff + g->width;
679 width = right - left;
682 g->yoff = top + height * base_y / 2;
686 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
690 if (g->xoff + g->lbearing < left + lbearing)
691 lbearing = g->xoff + g->lbearing - left;
692 if (g->xoff + g->rbearing > left + rbearing)
693 rbearing = g->xoff + g->rbearing - left;
694 if (g->yoff - g->ascent < top)
695 top = g->yoff - g->ascent;
696 if (g->yoff + g->descent > bottom)
697 bottom = g->yoff + g->descent;
698 height = bottom - top;
704 base->ascent = - top;
705 base->descent = bottom;
706 base->lbearing = lbearing;
707 base->rbearing = rbearing;
708 if (left < - base->width)
710 base->xoff = - base->width - left;
711 base->width += base->xoff;
712 base->rbearing += base->xoff;
713 base->lbearing += base->xoff;
717 base->width += right;
718 base->rbearing += right;
719 base->right_padding = 1;
720 for (i = 1; base + i != g; i++)
721 base[i].xoff -= right;
724 for (i = 0; base + i != g; i++)
729 if (base->left_padding && lbearing < 0)
731 base->xoff -= lbearing;
732 base->width -= lbearing;
737 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
738 g_physical_descent = MAX (g_physical_descent, base->descent);
739 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
740 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
741 extents->width += base->width;
744 gstring->physical_ascent = g_physical_ascent;
745 gstring->physical_descent = g_physical_descent;
749 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
750 by this function directly. Character glyphs are handled by
751 layouter functions registered in font drivers.
753 This function fill-in all the remaining members of glyphs. */
756 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
758 /* Default width of TAB. */
759 int tab_width = frame->space_width * (gstring->control.tab_width
760 ? gstring->control.tab_width : 8);
764 MDrawControl *control = &(gstring->control);
767 int box_line_height = 0;
768 int ignore_formatting_char = control->ignore_formatting_char;
770 gstring->ascent = gstring->descent = 0;
771 gstring->physical_ascent = gstring->physical_descent = 0;
772 gstring->width = gstring->lbearing = gstring->rbearing = 0;
776 while (g->type != GLYPH_ANCHOR)
778 if (box != g->rface->box)
780 int gidx = GLYPH_INDEX (g);
784 /* Insert the right side of the box. That glyph belongs
785 to the previous grapheme cluster. */
786 MGlyph box_glyph = g[-1];
788 box_glyph.type = GLYPH_BOX;
790 = (control->fixed_width
792 : box->inner_hmargin + box->width + box->outer_hmargin);
793 box_glyph.lbearing = 0;
794 box_glyph.rbearing = box_glyph.width;
796 box_glyph.right_padding = 1;
797 gstring->width += box_glyph.width;
798 gstring->rbearing += box_glyph.width;
799 INSERT_GLYPH (gstring, gidx, box_glyph);
806 /* Insert the left side of the box. That glyph belongs
807 to the following grapheme cluster. */
808 MGlyph box_glyph = *g;
809 int box_height = (box->width
810 + box->inner_vmargin + box->outer_vmargin);
812 if (box_line_height < box_height)
813 box_line_height = box_height;
814 box_glyph.type = GLYPH_BOX;
816 = (control->fixed_width
818 : box->inner_hmargin + box->width + box->outer_hmargin);
819 box_glyph.lbearing = 0;
820 box_glyph.rbearing = box_glyph.width;
822 box_glyph.left_padding = 1;
823 gstring->width += box_glyph.width;
824 gstring->rbearing += box_glyph.width;
825 INSERT_GLYPH (gstring, gidx, box_glyph);
831 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
832 g->type = GLYPH_SPACE;
834 if (g->type == GLYPH_CHAR)
836 MRealizedFace *rface = g->rface;
837 MRealizedFont *rfont = rface->rfont;
839 int from = GLYPH_INDEX (g);
841 for (g++; g->type == GLYPH_CHAR; g++)
842 if (! rfont != ! g->rface->rfont
843 || box != g->rface->box
844 || ((fromg->code == MCHAR_INVALID_CODE)
845 != (g->code == MCHAR_INVALID_CODE))
846 || (g->category == GLYPH_CATEGORY_FORMATTER
847 && ignore_formatting_char))
849 if (rfont && fromg->code != MCHAR_INVALID_CODE)
852 int to = GLYPH_INDEX (g);
853 MSubTextExtents extents;
855 layout_glyphs (frame, gstring, from, to, &extents);
856 extra_width = - extents.lbearing;
858 && ! control->disable_overlapping_adjustment
859 && (! control->orientation_reversed
860 ? ((to > 1 || control->align_head)
861 && g->type != GLYPH_ANCHOR)
862 : (((g->type && GLYPH_ANCHOR) || control->align_head)
867 pad.type = GLYPH_PAD;
870 pad.width = pad.rbearing = extra_width;
871 pad.left_padding = 1;
872 INSERT_GLYPH (gstring, from, pad);
874 extents.lbearing = 0;
875 extents.width += extra_width;
876 extents.rbearing += extra_width;
878 g = MGLYPH (from - 1);
879 if (g->type == GLYPH_SPACE)
881 /* The pad just inserted is absorbed (maybe
882 partially) by the previous space while
883 keeping at least some space width. For the
884 moment, we use the arbitrary width 2-pixel.
885 Perhaps, it should be decided by the current
886 face, or a default value of the current
887 frame, which is, however, not yet
889 if (extra_width + 2 < g->width)
891 g->width -= extra_width;
895 extra_width = g->width - 2;
898 gstring->width -= extra_width;
899 gstring->rbearing -= extra_width;
904 extra_width = extents.rbearing - extents.width;
906 && ! control->disable_overlapping_adjustment
907 && (GLYPH_INDEX (g) < gstring->used - 1
908 || (control->orientation_reversed && control->align_head)))
910 if (g->type == GLYPH_SPACE && box == g->rface->box)
913 pad.type = GLYPH_PAD;
916 pad.width = pad.rbearing = extra_width;
917 INSERT_GLYPH (gstring, to, pad);
922 g[-1].width += extra_width;
923 extents.width += extra_width;
926 if (gstring->lbearing > gstring->width + extents.lbearing)
927 gstring->lbearing = gstring->width + extents.lbearing;
928 if (gstring->rbearing < gstring->width + extents.rbearing)
929 gstring->rbearing = gstring->width + extents.rbearing;
930 gstring->width += extents.width;
931 if (gstring->ascent < rface->ascent)
932 gstring->ascent = rface->ascent;
933 if (gstring->descent < rface->descent)
934 gstring->descent = rface->descent;
938 for (; fromg < g; fromg++)
940 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
941 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
942 fromg->width = fromg->rbearing = 1;
944 fromg->width = fromg->rbearing = rface->space_width;
945 fromg->xoff = fromg->lbearing = 0;
946 fromg->ascent = fromg->descent = 0;
947 gstring->width += fromg->width;
948 gstring->rbearing += fromg->width;
950 if (gstring->ascent < frame->rface->ascent)
951 gstring->ascent = frame->rface->ascent;
952 if (gstring->descent < frame->descent)
953 gstring->descent = frame->rface->descent;
956 else if (g->type == GLYPH_SPACE)
959 g->width = g->rface->space_width;
960 else if (g->c == '\n')
962 g->width = control->cursor_width;
965 if (control->cursor_bidi)
967 else if (g->width < 0)
968 g->width = g->rface->space_width;
971 else if (g->c == '\t')
973 g->width = tab_width - ((gstring->indent + gstring->width)
979 if (g[-1].type == GLYPH_PAD)
981 /* This space glyph absorbs (maybe partially) the
982 previous padding glyph. */
983 g->width -= g[-1].width;
985 /* But, keep at least some space width. For the
986 moment, we use the arbitrary width 2-pixel. */
989 g->rbearing = g->width;
990 gstring->width += g->width;
991 gstring->rbearing += g->width;
994 if (gstring->ascent < g->rface->ascent)
995 gstring->ascent = g->rface->ascent;
996 if (gstring->descent < g->rface->descent)
997 gstring->descent = g->rface->descent;
1003 gstring->width += g->width;
1004 gstring->rbearing += g->width;
1011 /* Insert the right side of the box. */
1012 int gidx = GLYPH_INDEX (g);
1013 MGlyph box_glyph = g[-1];
1015 box_glyph.type = GLYPH_BOX;
1017 = (control->fixed_width
1018 ? frame->space_width
1019 : box->inner_hmargin + box->width + box->outer_hmargin);
1020 box_glyph.lbearing = 0;
1021 box_glyph.rbearing = box_glyph.width;
1023 box_glyph.right_padding = 1;
1024 gstring->width += box_glyph.width;
1025 gstring->rbearing += box_glyph.width;
1026 INSERT_GLYPH (gstring, gidx, box_glyph);
1029 gstring->text_ascent = gstring->ascent;
1030 gstring->text_descent = gstring->descent;
1031 if (gstring->text_ascent < gstring->physical_ascent)
1032 gstring->text_ascent = gstring->physical_ascent;
1033 if (gstring->text_descent < gstring->physical_descent)
1034 gstring->text_descent = gstring->physical_descent;
1035 gstring->line_ascent = gstring->text_ascent;
1036 gstring->line_descent = gstring->text_descent;
1037 if (box_line_height > 0)
1039 gstring->line_ascent += box_line_height;
1040 gstring->physical_ascent = gstring->line_ascent;
1041 gstring->line_descent += box_line_height;
1042 gstring->physical_descent = gstring->line_descent;
1045 if (gstring->line_ascent < control->min_line_ascent)
1046 gstring->line_ascent = control->min_line_ascent;
1047 else if (control->max_line_ascent
1048 && control->max_line_ascent > control->min_line_ascent
1049 && gstring->line_ascent > control->max_line_ascent)
1050 gstring->line_ascent = control->max_line_ascent;
1052 if (gstring->line_descent < control->min_line_descent)
1053 gstring->line_descent = control->min_line_descent;
1054 else if (control->max_line_descent
1055 && control->max_line_descent > control->min_line_descent
1056 && gstring->line_descent > control->max_line_descent)
1057 gstring->line_descent = control->max_line_descent;
1058 gstring->height = gstring->line_ascent + gstring->line_descent;
1060 if (control->orientation_reversed
1063 /* We must adjust TAB width for RTL orientation. */
1064 width = gstring->indent;
1066 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1068 if (g->type == GLYPH_CHAR && g->c == '\t')
1070 int this_width = tab_width - (width % tab_width);
1072 if (g[1].type == GLYPH_PAD)
1073 this_width -= g[1].width;
1074 if (g[-1].type == GLYPH_PAD)
1075 this_width -= g[-1].width;
1078 gstring->width += this_width - g->width;
1079 gstring->rbearing += this_width - g->width;
1080 g->width = this_width;
1081 width += this_width;
1091 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1092 MGlyphString *gstring, int from, int to,
1093 int *from_idx, int *to_idx, int *to_x)
1095 MGlyph *g = MGLYPH (1);
1096 MDrawRegion region = (MDrawRegion) NULL;
1097 MDrawControl *control = &gstring->control;
1098 int cursor_pos = -1;
1100 int cursor_bidi = control->cursor_bidi;
1102 if (control->with_cursor && control->cursor_width)
1104 if (gstring->from <= control->cursor_pos
1105 && gstring->to > control->cursor_pos)
1106 cursor_pos = control->cursor_pos;
1109 && gstring->from <= control->cursor_pos - 1
1110 && gstring->to > control->cursor_pos - 1)
1111 prev_pos = control->cursor_pos - 1;
1114 *from_idx = *to_idx = 0;
1116 while (g->type != GLYPH_ANCHOR)
1118 if (g->pos >= from && g->pos < to)
1120 MGlyph *fromg = g, *cursor = NULL;
1121 MRealizedFace *rface = g->rface;
1123 int cursor_width = 0;
1127 *from_idx = GLYPH_INDEX (g);
1128 while (g->pos >= from && g->pos < to
1129 && g->rface == rface)
1132 if (g->type != GLYPH_BOX
1133 && g->pos <= cursor_pos && g->to > cursor_pos)
1136 cursor = g, cursor_x = x + width;
1137 cursor_width += g->width;
1139 width += g++->width;
1142 && (control->as_image
1143 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1145 int this_x = x, this_width = width;
1147 if (fromg->type == GLYPH_BOX)
1148 this_x += fromg->width, this_width -= fromg->width;
1149 if (g[-1].type == GLYPH_BOX)
1150 this_width -= g[-1].width;
1151 (frame->driver->fill_space)
1152 (frame, win, rface, 0,
1153 this_x, y - gstring->text_ascent, this_width,
1154 gstring->text_ascent + gstring->text_descent,
1155 control->clip_region);
1162 rect.y = y - gstring->text_ascent;
1163 rect.height = gstring->text_ascent + gstring->text_descent;
1166 rect.width = ((control->cursor_width > 0
1167 && control->cursor_width < cursor_width)
1168 ? control->cursor_width : cursor_width);
1172 if (cursor->bidi_level % 2)
1173 rect.x += cursor_width - rect.width;
1174 (*frame->driver->fill_space)
1175 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1176 control->clip_region);
1178 region = (*frame->driver->region_from_rect) (&rect);
1180 (*frame->driver->region_add_rect) (region, &rect);
1183 if (cursor->bidi_level % 2)
1186 rect.width = cursor_width < 4 ? cursor_width : 4;
1187 (*frame->driver->fill_space)
1188 (frame, win, rface, 1,
1189 rect.x, rect.y, rect.width, rect.height,
1190 control->clip_region);
1191 (*frame->driver->region_add_rect) (region, &rect);
1203 if (fromg->type != GLYPH_BOX
1204 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1207 cursor = fromg, cursor_x = x + temp_width;
1208 cursor_width += fromg->width;
1210 temp_width += fromg++->width;
1217 if (! (cursor->bidi_level % 2))
1218 rect.x += cursor_width - 1;
1219 rect.y = y - gstring->text_ascent;
1220 rect.height = gstring->text_ascent + gstring->text_descent;
1222 (*frame->driver->fill_space)
1223 (frame, win, rface, 1,
1224 rect.x, rect.y, rect.width, rect.height,
1225 control->clip_region);
1227 region = (*frame->driver->region_from_rect) (&rect);
1229 (*frame->driver->region_add_rect) (region, &rect);
1230 rect.y += rect.height - 2;
1232 rect.width = cursor_width < 4 ? cursor_width : 4;
1233 if (! (cursor->bidi_level % 2))
1234 rect.x -= rect.width - 1;
1235 (*frame->driver->fill_space) (frame, win, rface, 1,
1236 rect.x, rect.y, rect.width, rect.height,
1237 control->clip_region);
1238 (*frame->driver->region_add_rect) (region, &rect);
1242 *to_idx = GLYPH_INDEX (g);
1252 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1253 MGlyphString *gstring, int from_idx, int to_idx,
1254 int reverse, MDrawRegion region)
1256 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1262 (*frame->driver->region_to_rect) (region, &rect);
1265 while (g != gend && x + g->rbearing <= rect.x)
1268 width -= g++->width;
1269 while (! g->enabled && g != gend)
1273 rect.x += rect.width;
1274 if (rect.x < x + width)
1277 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1279 width -= (--gend)->width;
1280 while (! gend->enabled && g != gend)
1284 while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1293 MRealizedFace *rface = g->rface;
1294 int width = g->width;
1295 MGlyph *from_g = g++;
1297 /* Handle the glyphs of the same type/face at once. */
1299 && g->type == from_g->type
1300 && g->rface == rface
1301 && ((g->code == MCHAR_INVALID_CODE)
1302 == (from_g->code == MCHAR_INVALID_CODE))
1304 width += g++->width;
1306 if (from_g->type == GLYPH_CHAR)
1308 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1309 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1312 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1315 else if (from_g->type == GLYPH_BOX)
1317 /* Draw the left or right side of a box. If
1318 from_g->lbearing is nonzero, this is the left side,
1319 else this is the right side. */
1320 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1323 if (from_g->type != GLYPH_BOX)
1326 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1327 x, y, width, region);
1330 /* Draw the top and bottom side of a box. */
1331 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1332 x, y, width, region);
1343 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1344 int *from_x, int *to_x)
1347 int left_idx = *left, right_idx = *right;
1348 int left_x, right_x, x;
1350 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1353 if (x + g->rbearing > 0)
1355 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1357 left_idx = GLYPH_INDEX (g);
1362 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1365 if (x - g->width + g->lbearing < 0)
1367 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1369 right_idx = GLYPH_INDEX (g) + 1;
1374 if (*left == left_idx && *right == right_idx)
1377 if (*left != left_idx)
1379 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1384 if (*right != right_idx)
1386 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1396 gstring_width (MGlyphString *gstring, int from, int to,
1397 int *lbearing, int *rbearing)
1402 if (from <= gstring->from && to >= gstring->to)
1405 *lbearing = gstring->lbearing;
1407 *rbearing = gstring->rbearing;
1408 return gstring->width;
1415 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1416 if (g->pos >= from && g->pos < to)
1418 if (lbearing && width + g->lbearing < *lbearing)
1419 *lbearing = width + g->lbearing;
1420 if (rbearing && width + g->rbearing > *rbearing)
1421 *rbearing = width + g->rbearing;
1429 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1430 MGlyphString *gstring, int from, int to)
1432 MDrawControl *control = &gstring->control;
1434 MDrawRegion clip_region, cursor_region;
1435 int from_idx, to_idx;
1440 if (control->orientation_reversed)
1441 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1443 x += gstring->indent;
1445 /* At first, draw all glyphs without cursor. */
1446 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1447 &from_idx, &to_idx, &to_x);
1449 if (control->partial_update)
1452 rect.width = to_x - x;
1453 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1455 rect.y = y - gstring->line_ascent;
1456 rect.height = gstring->height;
1457 clip_region = (*frame->driver->region_from_rect) (&rect);
1458 if (control->clip_region)
1459 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1462 clip_region = control->clip_region;
1465 clip_region = control->clip_region;
1467 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1472 (*frame->driver->intersect_region) (cursor_region, clip_region);
1473 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1476 if (clip_region != control->clip_region)
1477 (*frame->driver->free_region) (clip_region);
1479 (*frame->driver->free_region) (cursor_region);
1483 static int gstring_num;
1486 free_gstring (void *object)
1488 MGlyphString *gstring = (MGlyphString *) object;
1491 free_gstring (gstring->next);
1492 if (gstring->size > 0)
1493 free (gstring->glyphs);
1499 static MGlyphString scratch_gstring;
1501 static MGlyphString *
1502 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1505 MGlyphString *gstring;
1507 if (pos == mt->nchars)
1511 gstring = &scratch_gstring;
1512 if (gstring->size == 0)
1517 g_tmp.type = GLYPH_ANCHOR;
1518 APPEND_GLYPH (gstring, g_tmp);
1519 APPEND_GLYPH (gstring, g_tmp);
1520 APPEND_GLYPH (gstring, g_tmp);
1521 gstring->glyphs[1].type = GLYPH_SPACE;
1522 gstring->glyphs[1].c = '\n';
1523 gstring->glyphs[1].code = '\n';
1525 gstring->from = pos;
1527 g->rface = frame->rface;
1528 g->pos = g->to = pos;
1530 g->rface = frame->rface;
1531 g->pos = pos++, g->to = pos;
1533 g->rface = frame->rface;
1534 g->pos = g->to = pos;
1539 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1540 MLIST_INIT1 (gstring, glyphs, 128);
1544 gstring->frame = frame;
1545 gstring->tick = frame->tick;
1546 gstring->top = gstring;
1547 gstring->control = *control;
1548 gstring->indent = gstring->width_limit = 0;
1549 if (control->format)
1550 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1552 gstring->width_limit = control->max_line_width;
1553 gstring->anti_alias = control->anti_alias;
1557 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1560 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1563 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1571 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1572 a width of glyphs for the character at I of MT. If I is not a
1573 beginning of a grapheme cluster, the corresponding element is
1575 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1576 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1577 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1578 pos_width[g->pos - gstring->from] += g->width;
1579 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1581 if (pos_width[i] > 0)
1583 if (width + pos_width[i] > gstring->width_limit)
1586 width += pos_width[i];
1589 pos = gstring->from + i;
1590 if (gstring->control.line_break)
1592 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1593 gstring->from, gstring->from + i,
1595 if (pos <= gstring->from)
1597 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1600 else if (pos >= gstring->to)
1605 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1608 if (pos < gstring->to)
1610 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1611 layout_glyph_string (frame, gstring);
1616 /* Return a gstring that covers a character at POS. */
1618 static MGlyphString *
1619 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1621 MGlyphString *gstring = NULL;
1623 if (pos < mtext_nchars (mt))
1625 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1628 && ((prop->start != 0
1629 && mtext_ref_char (mt, prop->start - 1) != '\n')
1630 || (prop->end < mtext_nchars (mt)
1631 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1633 mtext_detach_property (prop);
1638 gstring = prop->val;
1639 if (gstring->frame != frame
1640 || gstring->tick != frame->tick
1641 || memcmp (control, &gstring->control,
1642 (char *) (&control->with_cursor)
1643 - (char *) (control))
1644 || control->cursor_width != gstring->control.cursor_width
1645 || control->cursor_bidi != gstring->control.cursor_bidi)
1647 mtext_detach_property (prop);
1652 else if (! control->cursor_width)
1660 offset = mtext_character (mt, pos, 0, '\n');
1665 offset -= gstring->from;
1667 for (gst = gstring; gst; gst = gst->next)
1671 gst->from += offset;
1673 for (i = 0; i < gst->used; i++)
1675 gst->glyphs[i].pos += offset;
1676 gst->glyphs[i].to += offset;
1679 M17N_OBJECT_REF (gstring);
1684 int line = 0, y = 0;
1686 if (pos < mtext_nchars (mt))
1688 beg = mtext_character (mt, pos, 0, '\n');
1696 end = mtext_nchars (mt) + (control->cursor_width != 0);
1697 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1698 if (beg < mtext_nchars (mt))
1699 compose_glyph_string (frame, mt, beg, end, gstring);
1700 layout_glyph_string (frame, gstring);
1702 if (gstring->width_limit
1703 && gstring->width > gstring->width_limit)
1705 MGlyphString *gst = gstring;
1707 truncate_gstring (frame, mt, gst);
1708 while (gst->to < end)
1710 line++, y += gst->height;
1711 gst->next = alloc_gstring (frame, mt, gst->from, control,
1713 gst->next->top = gstring;
1714 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1716 layout_glyph_string (frame, gst);
1717 if (gst->width <= gst->width_limit)
1719 truncate_gstring (frame, mt, gst);
1723 if (! control->disable_caching && pos < mtext_nchars (mt))
1725 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1726 MTEXTPROP_VOLATILE_STRONG);
1728 if (end > mtext_nchars (mt))
1729 end = mtext_nchars (mt);
1730 mtext_attach_property (mt, beg, end, prop);
1731 M17N_OBJECT_UNREF (prop);
1735 while (gstring->to <= pos)
1737 if (! gstring->next)
1739 gstring = gstring->next;
1741 gstring->control = *control;
1747 static MDrawControl control_noop;
1749 #define ASSURE_CONTROL(control) \
1751 control = &control_noop; \
1756 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1757 MText *mt, int from, int to,
1758 MDrawControl *control)
1760 MGlyphString *gstring;
1762 M_CHECK_POS_X (mt, from, -1);
1763 ASSURE_CONTROL (control);
1764 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1765 to = mtext_nchars (mt) + (control->cursor_width != 0);
1769 gstring = get_gstring (frame, mt, from, to, control);
1771 MERROR (MERROR_DRAW, -1);
1772 render_glyph_string (frame, win, x, y, gstring, from, to);
1776 y += gstring->line_descent;
1777 M17N_OBJECT_UNREF (gstring->top);
1778 gstring = get_gstring (frame, mt, from, to, control);
1779 y += gstring->line_ascent;
1780 render_glyph_string (frame, win, x, y, gstring, from, to);
1783 M17N_OBJECT_UNREF (gstring->top);
1790 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1796 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1797 if (g->pos <= pos && g->to > pos)
1802 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1803 if (g->pos <= pos && g->to > pos)
1810 /* for debugging... */
1814 dump_combining_code (int code)
1816 char *vallign = "tcbB";
1817 char *hallign = "lcr";
1823 if (COMBINING_BY_CLASS_P (code))
1824 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1825 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1826 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1827 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1828 off_x = COMBINING_CODE_OFF_X (code) - 128;
1830 sprintf (work + 2, "+%d", off_y);
1832 sprintf (work + 2, "%d", off_y);
1833 else if (off_x == 0)
1834 sprintf (work + 2, ".");
1835 p = work + strlen (work);
1837 sprintf (p, ">%d", off_x);
1839 sprintf (p, "<%d", -off_x);
1841 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1842 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1848 dump_gstring (MGlyphString *gstring, int indent)
1850 char *prefix = (char *) alloca (indent + 1);
1851 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1853 memset (prefix, 32, indent);
1856 fprintf (stderr, "(glyph-string");
1858 for (g = MGLYPH (0); g < last_g; g++)
1860 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1862 g - gstring->glyphs,
1863 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1864 : g->type == GLYPH_ANCHOR ? "ANC"
1865 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1866 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1867 dump_combining_code (g->combining_code),
1868 g->width, g->bidi_level);
1869 fprintf (stderr, ")");
1873 /* m17n-X internal APIs */
1878 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1880 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1881 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1883 Mcommon = msymbol ("common");
1885 McatCc = msymbol ("Cc");
1886 McatCf = msymbol ("Cf");
1888 MbidiR = msymbol ("R");
1889 MbidiAL = msymbol ("AL");
1890 MbidiRLE = msymbol ("RLE");
1891 MbidiRLO = msymbol ("RLO");
1892 MbidiBN = msymbol ("BN");
1893 MbidiS = msymbol ("S");
1894 MbidiNSM = msymbol ("NSM");
1896 fribidi_set_mirroring (TRUE);
1899 M_break_at_space = msymbol ("bs");
1900 M_break_at_word = msymbol ("bw");
1901 M_break_at_any = msymbol ("ba");
1902 M_kinsoku_bol = msymbol ("kb");
1903 M_kinsoku_eol = msymbol ("ke");
1911 MLIST_FREE1 (&scratch_gstring, glyphs);
1912 M17N_OBJECT_UNREF (linebreak_table);
1913 linebreak_table = NULL;
1917 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1921 /*** @addtogroup m17nDraw */
1926 @brief Draw an M-text on a window.
1928 The mdraw_text () function draws the text between $FROM and $TO of
1929 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1931 The appearance of the text (size, style, color, etc) is specified
1932 by the value of the text property whose key is @c Mface. If the
1933 M-text or a part of the M-text does not have such a text property,
1934 the default face of $FRAME is used.
1936 The font used to draw a character in the M-text is selected from
1937 the value of the fontset property of a face by the following
1942 <li> Search the text properties given to the character for the one
1943 whose key is @c Mcharset; its value should be either a symbol
1944 specifying a charset or #Mnil. If the value is #Mnil,
1945 proceed to the next step.
1947 Otherwise, search the mapping table of the fontset for the
1948 charset. If no entry is found proceed to the next step.
1950 If an entry is found, use one of the fonts in the entry that
1951 has a glyph for the character and that matches best with the
1952 face properties. If no such font exists, proceed to the next
1955 <li> Get the character property "script" of the character. If it is
1956 inherited, get the script property from the previous
1957 characters. If there is no previous character, or none of
1958 them has the script property other than inherited, proceed to
1961 Search the text properties given to the character for the one
1962 whose key is @c Mlanguage; its value should be either a
1963 symbol specifying a language or @c Mnil.
1965 Search the mapping table of the fontset for the combination
1966 of the script and language. If no entry is found, proceed to
1969 If an entry is found, use one of the fonts in the entry that
1970 has a glyph for the character and that matches best with the
1971 face properties. If no such font exists, proceed to the next
1974 <li> Search the fall-back table of the fontset for a font that has
1975 a glyph of the character. If such a font is found, use that
1980 If no font is found by the algorithm above, this function draws an
1981 empty box for the character.
1983 This function draws only the glyph foreground. To specify the
1984 background color, use mdraw_image_text () or
1985 mdraw_text_with_control ().
1987 This function is the counterpart of <tt>XDrawString ()</tt>,
1988 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1989 in the X Window System.
1992 If the operation was successful, mdraw_text () returns 0. If an
1993 error is detected, it returns -1 and assigns an error code to the
1994 external variable #merror_code. */
1996 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1998 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1999 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
2001 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
2002 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
2003 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
2004 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
2006 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
2007 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
2011 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
2012 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
2013 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2014 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
2015 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
2016 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2018 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
2019 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2021 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
2022 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2023 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2025 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2026 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2028 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2029 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2031 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2032 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2034 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2035 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2039 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2041 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2042 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2044 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2045 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2048 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2049 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2051 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2058 mdraw_image_text () */
2061 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2062 MText *mt, int from, int to)
2064 MDrawControl control;
2066 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2067 memset (&control, 0, sizeof control);
2068 control.as_image = 0;
2069 return draw_text (frame, win, x, y, mt, from, to, &control);
2076 @brief Draw an M-text on a window as an image.
2078 The mdraw_image_text () function draws the text between $FROM and
2079 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2080 coordinate ($X, $Y).
2082 The way to draw a text is the same as in mdraw_text () except that
2083 this function also draws the background with the color specified
2086 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2087 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2088 functions in the X Window System.
2091 If the operation was successful, mdraw_image_text () returns 0.
2092 If an error is detected, it returns -1 and assigns an error code
2093 to the external variable #merror_code. */
2096 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2098 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2099 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2100 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2102 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2103 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2105 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2106 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2110 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2111 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2113 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2123 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2124 MText *mt, int from, int to)
2126 MDrawControl control;
2128 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2129 memset (&control, 0, sizeof control);
2130 control.as_image = 1;
2131 return draw_text (frame, win, x, y, mt, from, to, &control);
2137 @brief Draw an M-text on a window with fine control.
2139 The mdraw_text_with_control () function draws the text between
2140 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2141 coordinate ($X, $Y).
2143 The way to draw a text is the same as in mdraw_text () except that
2144 this function also follows what specified in the drawing control
2147 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2148 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2149 breaks lines and the following characters are drawn in the next
2150 line. See the documentation of the structure @ MDrawControl for
2154 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2156 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2157 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2160 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2161 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2163 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2164 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2165 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2168 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2169 MText *mt, int from, int to, MDrawControl *control)
2171 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2172 return draw_text (frame, win, x, y, mt, from, to, control);
2178 @brief Compute text pixel width.
2180 The mdraw_text_extents () function computes the width of text
2181 between $FROM and $TO of M-text $MT when it is drawn on a window
2182 of frame $FRAME using the mdraw_text_with_control () function with
2183 the drawing control object $CONTROL.
2185 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2186 the bounding box of character ink of the M-text, and stores the
2187 results in the members of the structure pointed to by
2188 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2189 surrounding box, the box is included in the bounding box.
2191 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2192 computes the bounding box that provides minimum spacing to other
2193 graphical features (such as surrounding box) for the M-text, and
2194 stores the results in the members of the structure pointed to by
2195 $OVERALL_LOGICAL_RETURN.
2197 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2198 computes the bounding box that provides minimum spacing to the
2199 other M-text drawn, and stores the results in the members of the
2200 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2201 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2202 min_line_ascent, min_line_descent, max_line_ascent, and
2203 max_line_descent of $CONTROL are all zero.
2206 This function returns the width of the text to be drawn in the
2207 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2208 text is drawn in multiple physical lines, it returns the width of
2209 the widest line. If an error occurs, it returns -1 and assigns an
2210 error code to the external variable #merror_code. */
2214 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2216 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2217 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2218 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2220 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2221 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2222 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2223 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2225 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2226 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2227 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2228 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2230 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2231 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2232 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2233 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2234 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2235 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2238 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2239 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2240 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2242 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2249 mdraw_text_extents (MFrame *frame,
2250 MText *mt, int from, int to, MDrawControl *control,
2251 MDrawMetric *overall_ink_return,
2252 MDrawMetric *overall_logical_return,
2253 MDrawMetric *overall_line_return)
2255 MGlyphString *gstring;
2257 int width, lbearing, rbearing;
2259 ASSURE_CONTROL (control);
2260 M_CHECK_POS_X (mt, from, -1);
2261 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2262 to = mtext_nchars (mt) + (control->cursor_width != 0);
2266 gstring = get_gstring (frame, mt, from, to, control);
2268 MERROR (MERROR_DRAW, -1);
2269 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2270 if (overall_ink_return)
2271 overall_ink_return->y = - gstring->physical_ascent;
2272 if (overall_logical_return)
2273 overall_logical_return->y = - gstring->ascent;
2274 if (overall_line_return)
2275 overall_line_return->y = - gstring->line_ascent;
2277 for (from = gstring->to; from < to; from = gstring->to)
2279 int this_width, this_lbearing, this_rbearing;
2281 y += gstring->line_descent;
2282 M17N_OBJECT_UNREF (gstring->top);
2283 gstring = get_gstring (frame, mt, from, to, control);
2284 this_width = gstring_width (gstring, from, to,
2285 &this_lbearing, &this_rbearing);
2286 y += gstring->line_ascent;
2287 if (width < this_width)
2289 if (rbearing < this_rbearing)
2290 rbearing = this_rbearing;
2291 if (lbearing > this_lbearing)
2292 lbearing = this_lbearing;
2294 if (overall_ink_return)
2296 overall_ink_return->x = lbearing;
2297 overall_ink_return->width = rbearing - lbearing;
2298 overall_ink_return->height
2299 = y + gstring->physical_descent - overall_ink_return->y;
2301 if (overall_logical_return)
2303 overall_logical_return->x = 0;
2304 overall_logical_return->width = width;
2305 overall_logical_return->height
2306 = y + gstring->descent - overall_logical_return->y;
2308 if (overall_line_return)
2310 overall_line_return->x = lbearing;
2311 overall_line_return->width = MAX (width, rbearing - lbearing);
2312 overall_line_return->height
2313 = y + gstring->line_descent - overall_line_return->y;
2316 M17N_OBJECT_UNREF (gstring->top);
2323 @brief Compute the text dimensions of each character of M-text.
2325 The mdraw_text_per_char_extents () function computes the drawn
2326 metric of each character between $FROM and $TO of M-text $MT
2327 assuming that they are drawn on a window of frame $FRAME using the
2328 mdraw_text_with_control () function with the drawing control
2331 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2332 $LOGICAL_ARRAY_RETURN. Each successive element of
2333 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2334 ink and logical metrics of successive characters respectively,
2335 relative to the drawing origin of the M-text. The number of
2336 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2337 been set is returned to $NUM_CHARS_RETURN.
2339 If $ARRAY_SIZE is too small to return all metrics, the function
2340 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2341 Otherwise, it returns zero.
2343 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2344 @c NULL, this function also computes the metrics of the overall
2345 text and stores the results in the members of the structure
2346 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2348 If $CONTROL->two_dimensional is nonzero, this function computes
2349 only the metrics of characters in the first line. */
2351 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2353 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2354 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2355 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2357 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2358 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2359 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2360 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2361 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2363 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2364 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2367 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2368 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2369 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2371 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2374 mdraw_text_per_char_extents (MFrame *frame,
2375 MText *mt, int from, int to,
2376 MDrawControl *control,
2377 MDrawMetric *ink_array_return,
2378 MDrawMetric *logical_array_return,
2380 int *num_chars_return,
2381 MDrawMetric *overall_ink_return,
2382 MDrawMetric *overall_logical_return)
2384 MGlyphString *gstring;
2388 ASSURE_CONTROL (control);
2389 *num_chars_return = to - from;
2390 if (array_size < *num_chars_return)
2391 MERROR (MERROR_DRAW, -1);
2392 if (overall_logical_return)
2393 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2394 if (overall_ink_return)
2395 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2397 M_CHECK_RANGE (mt, from, to, -1, 0);
2398 gstring = get_gstring (frame, mt, from, to, control);
2401 *num_chars_return = 0;
2405 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2406 if (g->pos >= from && g->pos < to)
2410 int width = g->width;
2411 int lbearing = g->lbearing;
2412 int rbearing = g->rbearing;
2413 int ascent = g->ascent;
2414 int descent = g->descent;
2416 int logical_descent;
2418 if (g->rface->rfont)
2420 logical_ascent = g->rface->rfont->ascent;
2421 logical_descent = g->rface->rfont->descent;
2425 logical_ascent = g->rface->ascent;
2426 logical_descent = g->rface->descent;
2428 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2430 if (lbearing < width + g->lbearing)
2431 lbearing = width + g->lbearing;
2432 if (rbearing < width + g->rbearing)
2433 rbearing = width + g->rbearing;
2435 if (ascent < g->ascent)
2437 if (descent < g->descent)
2438 descent = g->descent;
2445 if (ink_array_return)
2447 ink_array_return[start - from].x = x + lbearing;
2448 ink_array_return[start - from].y = - ascent;
2449 ink_array_return[start - from].width = rbearing - lbearing;
2450 ink_array_return[start - from].height = ascent + descent;
2452 if (logical_array_return)
2454 logical_array_return[start - from].x = x;
2455 logical_array_return[start - from].y = - logical_descent;
2456 logical_array_return[start - from].height
2457 = logical_ascent + logical_descent;
2458 logical_array_return[start - from].width = width;
2466 if (overall_ink_return)
2468 overall_ink_return->y = - gstring->line_ascent;
2469 overall_ink_return->x = gstring->lbearing;
2470 overall_ink_return->width = x - gstring->lbearing;
2471 overall_ink_return->height = gstring->height;
2473 if (overall_logical_return)
2475 overall_logical_return->y = - gstring->ascent;
2476 overall_logical_return->x = 0;
2477 overall_logical_return->width = x;
2478 overall_logical_return->height = gstring->ascent + gstring->descent;
2481 M17N_OBJECT_UNREF (gstring->top);
2488 @brief Return the character position nearest to the coordinates.
2490 The mdraw_coordinates_position () function checks which character
2491 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2492 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2493 mdraw_text_with_control () function with the drawing control
2494 object $CONTROL. Here, the character position means the number of
2495 characters that precede the character in question in $MT, that is,
2496 the character position of the first character is 0.
2498 $FRAME is used only to get the default face information.
2501 If the glyph image of a character covers coordinate ($X, $Y),
2502 mdraw_coordinates_position () returns the character position of
2504 If $Y is less than the minimum Y-coordinate of the drawn area, it
2506 If $Y is greater than the maximum Y-coordinate of the drawn area,
2508 If $Y fits in with the drawn area but $X is less than the minimum
2509 X-coordinate, it returns the character position of the first
2510 character drawn on the line $Y.\n\n
2511 If $Y fits in with the drawn area but $X is greater than the
2512 maximum X-coordinate, it returns the character position of the
2513 last character drawn on the line $Y. */
2516 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2518 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2519 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2520 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2521 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2522 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2523 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2525 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2528 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2529 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2530 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2531 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2532 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2533 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2534 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2535 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2538 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2539 int x_offset, int y_offset, MDrawControl *control)
2541 MGlyphString *gstring;
2546 M_CHECK_POS_X (mt, from, -1);
2547 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2548 to = mtext_nchars (mt) + (control->cursor_width != 0);
2554 ASSURE_CONTROL (control);
2555 gstring = get_gstring (frame, mt, from, to, control);
2556 while (y + gstring->line_descent <= y_offset
2557 && gstring->to < to)
2560 y += gstring->line_descent;
2561 M17N_OBJECT_UNREF (gstring->top);
2562 gstring = get_gstring (frame, mt, from, to, control);
2563 y += gstring->line_ascent;
2566 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2567 if (! control->orientation_reversed)
2569 width = gstring->indent;
2570 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2571 if (g->pos >= from && g->pos < to)
2574 if (width > x_offset)
2580 width = - gstring->indent;
2581 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2582 if (g->pos >= from && g->pos < to)
2585 if (width < x_offset)
2589 if (g->type == GLYPH_ANCHOR
2590 && control->two_dimensional
2594 M17N_OBJECT_UNREF (gstring->top);
2602 @brief Compute information about a glyph.
2604 The mdraw_glyph_info () function computes information about a
2605 glyph that covers a character at position $POS of the M-text $MT
2606 assuming that the text is drawn from the character at $FROM of $MT
2607 on a window of frame $FRAME using the mdraw_text_with_control ()
2608 function with the drawing control object $CONTROL.
2610 The information is stored in the members of $INFO. */
2612 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2614 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2615 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2616 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2617 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2619 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2627 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2628 MDrawControl *control, MDrawGlyphInfo *info)
2630 MGlyphString *gstring;
2634 M_CHECK_RANGE_X (mt, from, pos, -1);
2636 ASSURE_CONTROL (control);
2637 gstring = get_gstring (frame, mt, from, pos + 1, control);
2639 MERROR (MERROR_DRAW, -1);
2640 while (gstring->to <= pos)
2642 y += gstring->line_descent;
2643 M17N_OBJECT_UNREF (gstring->top);
2644 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2645 y += gstring->line_ascent;
2647 info->line_from = gstring->from;
2648 if (info->line_from < from)
2649 info->line_from = from;
2650 info->line_to = gstring->to;
2653 if (! control->orientation_reversed)
2655 info->x = gstring->indent;
2656 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2657 info->x += g->width;
2661 info->x = - gstring->indent;
2662 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2663 info->x -= g->width;
2664 while (g[-1].to == g->to)
2667 info->from = g->pos;
2669 info->metrics.x = g->lbearing;
2670 info->metrics.y = - gstring->line_ascent;
2671 info->metrics.height = gstring->height;
2672 info->metrics.width = - g->lbearing + g->width;
2673 if (g->rface->rfont)
2674 info->font = (MFont *) g->rface->rfont;
2677 /* info->logical_width is calculated later. */
2679 if (info->from > info->line_from)
2681 /* The logically previous glyph is on this line. */
2682 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2684 info->prev_from = g_tmp->pos;
2686 else if (info->line_from > 0
2687 && gstring->from > 0)
2689 /* The logically previous glyph is on the previous line. */
2690 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2691 gstring->from, control);
2692 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2694 info->prev_from = g_tmp->pos;
2695 M17N_OBJECT_UNREF (gst->top);
2698 info->prev_from = -1;
2700 if (GLYPH_INDEX (g) > 1)
2701 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2702 else if (! control->orientation_reversed)
2704 if (info->line_from > 0)
2708 int p = gstring->from - 1;
2710 gst = get_gstring (frame, mt, p, gstring->from, control);
2711 g_tmp = gst->glyphs + (gst->used - 2);
2712 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2713 M17N_OBJECT_UNREF (gst->top);
2716 info->left_from = info->left_to = -1;
2720 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2724 int p = gstring->to;
2726 gst = get_gstring (frame, mt, p, p + 1, control);
2727 g_tmp = gst->glyphs + (gst->used - 2);
2728 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2729 M17N_OBJECT_UNREF (gst->top);
2732 info->left_from = info->left_to = -1;
2735 if (info->to < gstring->to)
2737 /* The logically next glyph is on this line. */
2738 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2740 info->next_to = g_tmp->to;
2742 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2744 /* The logically next glyph is on the next line. */
2746 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2747 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2749 info->next_to = g_tmp->to;
2750 M17N_OBJECT_UNREF (gst->top);
2755 for (info->logical_width = (g++)->width;
2756 g->pos == pos && g->type != GLYPH_ANCHOR;
2757 info->metrics.width += g->width, info->logical_width += (g++)->width);
2758 info->metrics.width += g[-1].rbearing - g[-1].width;
2760 if (g->type != GLYPH_ANCHOR)
2761 info->right_from = g->pos, info->right_to = g->to;
2762 else if (! control->orientation_reversed)
2764 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2767 M17N_OBJECT_UNREF (gstring->top);
2768 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2770 info->right_from = g->pos, info->right_to = g->to;
2773 info->right_from = info->right_to = -1;
2777 if (info->line_from > 0)
2779 pos = gstring->from - 1;
2780 M17N_OBJECT_UNREF (gstring->top);
2781 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2783 info->right_from = g->pos, info->right_to = g->to;
2786 info->right_from = info->right_to = -1;
2789 M17N_OBJECT_UNREF (gstring->top);
2796 @brief Compute information about glyph sequence.
2798 The mdraw_glyph_list () function computes information about glyphs
2799 corresponding to the text between $FROM and $TO of M-text $MT when
2800 it is drawn on a window of frame $FRAME using the
2801 mdraw_text_with_control () function with the drawing control
2802 object $CONTROL. $GLYPHS is an array of objects to store the
2803 information, and $ARRAY_SIZE is the array size.
2805 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2806 number of actually filled elements in the place pointed by
2807 $NUM_GLYPHS_RETURN, and returns 0.
2809 Otherwise, it stores the required array size in the place pointed
2810 by $NUM_GLYPHS_RETURN, and returns -1. */
2813 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2815 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2816 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2817 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2818 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2820 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2821 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2824 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2834 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2835 MDrawControl *control, MDrawGlyph *glyphs,
2836 int array_size, int *num_glyphs_return)
2838 MGlyphString *gstring;
2843 ASSURE_CONTROL (control);
2844 *num_glyphs_return = 0;
2845 M_CHECK_RANGE (mt, from, to, -1, 0);
2846 gstring = get_gstring (frame, mt, from, to, control);
2849 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2851 if (g->type == GLYPH_BOX
2852 || g->pos < from || g->pos >= to)
2854 if (g->type == GLYPH_PAD)
2856 if (g->left_padding)
2857 pad_width = g->width;
2861 glyphs[-1].x_advance += g->width;
2867 glyphs->from = g->pos;
2869 glyphs->glyph_code = g->code;
2870 glyphs->x_off = g->xoff + pad_width;
2871 glyphs->y_off = g->yoff;
2872 glyphs->lbearing = g->lbearing;
2873 glyphs->rbearing = g->rbearing;
2874 glyphs->ascent = g->ascent;
2875 glyphs->descent = g->descent;
2876 glyphs->x_advance = g->width + pad_width;
2877 glyphs->y_advance = 0;
2878 if (g->rface->rfont)
2880 glyphs->font = (MFont *) g->rface->rfont;
2882 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2883 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2885 glyphs->fontp = g->rface->rfont->fontp;
2889 glyphs->font = NULL;
2890 glyphs->font_type = Mnil;
2891 glyphs->fontp = NULL;
2898 M17N_OBJECT_UNREF (gstring->top);
2900 *num_glyphs_return = n;
2901 return (n <= array_size ? 0 : -1);
2907 @brief Draw one or more textitems.
2909 The mdraw_text_items () function draws one or more M-texts on
2910 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2911 of the textitems to be drawn and $NITEMS is the number of
2912 textitems in the array. */
2915 @brief textitem ¤òɽ¼¨¤¹¤ë.
2917 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2918 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2919 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2921 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2925 MTextItem, mdraw_text (). */
2928 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2929 MDrawTextItem *items, int nitems)
2931 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2933 while (nitems-- > 0)
2936 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2938 mdraw_text_with_control (frame, win, x, y,
2939 items->mt, 0, mtext_nchars (items->mt),
2941 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2942 items->control, NULL, NULL, NULL);
2945 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2951 @brief Option of line breaking for drawing text.
2953 The variable #mdraw_line_break_option specifies line breaking
2954 options by logical-or of the members of #MTextLineBreakOption. It
2955 controls the line breaking algorithm of the function
2956 mdraw_default_line_break (). */
2958 int mdraw_line_break_option;
2962 @brief Calculate a line breaking position.
2964 The function mdraw_default_line_break () calculates a line
2965 breaking position based on the line number $LINE and the
2966 coordinate $Y, when a line is too long to fit within the width
2967 limit. $POS is the position of the character next to the last one
2968 that fits within the limit. $FROM is the position of the first
2969 character of the line, and $TO is the position of the last
2970 character displayed on the line if there were not width limit.
2971 $LINE and $Y are reset to 0 when a line is broken by a newline
2972 character, and incremented each time when a long line is broken
2973 because of the width limit.
2975 @return This function returns a character position to break the
2980 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2982 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2983 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2984 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2985 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2986 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2987 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2988 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2991 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2995 mdraw_default_line_break (MText *mt, int pos,
2996 int from, int to, int line, int y)
3000 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
3011 @brief Obtain per character dimension information.
3013 The mdraw_per_char_extents () function computes the text dimension
3014 of each character in M-text $MT. The faces given as text
3015 properties in $MT and the default face of frame $FRAME determine
3016 the fonts to draw the text. Each successive element in
3017 $ARRAY_RETURN is set to the drawn metrics of successive
3018 characters, which is relative to the origin of the drawing, and a
3019 rectangle for each character in $MT. The number of elements of
3020 $ARRAY_RETURN must be equal to or greater than the number of
3023 If pointer $OVERALL_RETURN is not @c NULL, this function also
3024 computes the extents of the overall text and stores the results in
3025 the members of the structure pointed to by $OVERALL_RETURN. */
3028 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3030 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3031 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3032 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3033 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3034 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3035 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3036 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3038 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3039 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3040 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3042 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3045 mdraw_per_char_extents (MFrame *frame, MText *mt,
3046 MDrawMetric *array_return,
3047 MDrawMetric *overall_return)
3049 int n = mtext_nchars (mt);
3051 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3052 n, &n, overall_return, NULL);
3056 @brief clear cached information.
3058 The mdraw_clear_cache () function clear cached information
3059 on M-text $MT that was attached by any of the drawing functions.
3060 When the behavior of `format' or `line_break'
3061 member functions of MDrawControl is changed, the cache must be cleared.
3066 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3068 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3069 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3070 ¤¢¤ë¤¤¤Ï `line_break'
3071 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3077 mdraw_clear_cache (MText *mt)
3079 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);