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., 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;
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;
1115 while (g->type != GLYPH_ANCHOR)
1117 if (g->pos >= from && g->pos < to)
1119 MGlyph *fromg = g, *cursor = NULL;
1120 MRealizedFace *rface = g->rface;
1122 int cursor_width = 0;
1126 *from_idx = GLYPH_INDEX (g);
1127 while (g->pos >= from && g->pos < to
1128 && g->rface == rface)
1131 if (g->type != GLYPH_BOX
1132 && g->pos <= cursor_pos && g->to > cursor_pos)
1135 cursor = g, cursor_x = x + width;
1136 cursor_width += g->width;
1138 width += g++->width;
1141 && (control->as_image
1142 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1144 int this_x = x, this_width = width;
1146 if (fromg->type == GLYPH_BOX)
1147 this_x += fromg->width, this_width -= fromg->width;
1148 if (g[-1].type == GLYPH_BOX)
1149 this_width -= g[-1].width;
1150 (frame->driver->fill_space)
1151 (frame, win, rface, 0,
1152 this_x, y - gstring->text_ascent, this_width,
1153 gstring->text_ascent + gstring->text_descent,
1154 control->clip_region);
1161 rect.y = y - gstring->text_ascent;
1162 rect.height = gstring->text_ascent + gstring->text_descent;
1165 rect.width = ((control->cursor_width > 0
1166 && control->cursor_width < cursor_width)
1167 ? control->cursor_width : cursor_width);
1171 if (cursor->bidi_level % 2)
1172 rect.x += cursor_width - rect.width;
1173 (*frame->driver->fill_space)
1174 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1175 control->clip_region);
1177 region = (*frame->driver->region_from_rect) (&rect);
1179 (*frame->driver->region_add_rect) (region, &rect);
1182 if (cursor->bidi_level % 2)
1185 rect.width = cursor_width < 4 ? cursor_width : 4;
1186 (*frame->driver->fill_space)
1187 (frame, win, rface, 1,
1188 rect.x, rect.y, rect.width, rect.height,
1189 control->clip_region);
1190 (*frame->driver->region_add_rect) (region, &rect);
1202 if (fromg->type != GLYPH_BOX
1203 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1206 cursor = fromg, cursor_x = x + temp_width;
1207 cursor_width += fromg->width;
1209 temp_width += fromg++->width;
1216 if (! (cursor->bidi_level % 2))
1217 rect.x += cursor_width - 1;
1218 rect.y = y - gstring->text_ascent;
1219 rect.height = gstring->text_ascent + gstring->text_descent;
1221 (*frame->driver->fill_space)
1222 (frame, win, rface, 1,
1223 rect.x, rect.y, rect.width, rect.height,
1224 control->clip_region);
1226 region = (*frame->driver->region_from_rect) (&rect);
1228 (*frame->driver->region_add_rect) (region, &rect);
1229 rect.y += rect.height - 2;
1231 rect.width = cursor_width < 4 ? cursor_width : 4;
1232 if (! (cursor->bidi_level % 2))
1233 rect.x -= rect.width - 1;
1234 (*frame->driver->fill_space) (frame, win, rface, 1,
1235 rect.x, rect.y, rect.width, rect.height,
1236 control->clip_region);
1237 (*frame->driver->region_add_rect) (region, &rect);
1241 *to_idx = GLYPH_INDEX (g);
1251 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1252 MGlyphString *gstring, int from_idx, int to_idx,
1253 int reverse, MDrawRegion region)
1255 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1261 (*frame->driver->region_to_rect) (region, &rect);
1264 while (g != gend && x + g->rbearing <= rect.x)
1267 width -= g++->width;
1268 while (! g->enabled && g != gend)
1272 rect.x += rect.width;
1273 if (rect.x < x + width)
1276 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1278 width -= (--gend)->width;
1279 while (! gend->enabled && g != gend)
1283 while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1292 MRealizedFace *rface = g->rface;
1293 int width = g->width;
1294 MGlyph *from_g = g++;
1296 /* Handle the glyphs of the same type/face at once. */
1298 && g->type == from_g->type
1299 && g->rface == rface
1300 && ((g->code == MCHAR_INVALID_CODE)
1301 == (from_g->code == MCHAR_INVALID_CODE))
1303 width += g++->width;
1305 if (from_g->type == GLYPH_CHAR)
1307 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1308 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1311 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1314 else if (from_g->type == GLYPH_BOX)
1316 /* Draw the left or right side of a box. If
1317 from_g->lbearing is nonzero, this is the left side,
1318 else this is the right side. */
1319 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1322 if (from_g->type != GLYPH_BOX)
1325 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1326 x, y, width, region);
1329 /* Draw the top and bottom side of a box. */
1330 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1331 x, y, width, region);
1342 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1343 int *from_x, int *to_x)
1346 int left_idx = *left, right_idx = *right;
1347 int left_x, right_x, x;
1349 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1352 if (x + g->rbearing > 0)
1354 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1356 left_idx = GLYPH_INDEX (g);
1361 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1364 if (x - g->width + g->lbearing < 0)
1366 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1368 right_idx = GLYPH_INDEX (g) + 1;
1373 if (*left == left_idx && *right == right_idx)
1376 if (*left != left_idx)
1378 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1383 if (*right != right_idx)
1385 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1395 gstring_width (MGlyphString *gstring, int from, int to,
1396 int *lbearing, int *rbearing)
1401 if (from <= gstring->from && to >= gstring->to)
1404 *lbearing = gstring->lbearing;
1406 *rbearing = gstring->rbearing;
1407 return gstring->width;
1414 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1415 if (g->pos >= from && g->pos < to)
1417 if (lbearing && width + g->lbearing < *lbearing)
1418 *lbearing = width + g->lbearing;
1419 if (rbearing && width + g->rbearing > *rbearing)
1420 *rbearing = width + g->rbearing;
1428 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1429 MGlyphString *gstring, int from, int to)
1431 MDrawControl *control = &gstring->control;
1433 MDrawRegion clip_region, cursor_region;
1434 int from_idx, to_idx;
1437 if (control->orientation_reversed)
1438 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1440 x += gstring->indent;
1442 /* At first, draw all glyphs without cursor. */
1443 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1444 &from_idx, &to_idx, &to_x);
1446 if (control->partial_update)
1449 rect.width = to_x - x;
1450 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1452 rect.y = y - gstring->line_ascent;
1453 rect.height = gstring->height;
1454 clip_region = (*frame->driver->region_from_rect) (&rect);
1455 if (control->clip_region)
1456 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1459 clip_region = control->clip_region;
1462 clip_region = control->clip_region;
1464 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1469 (*frame->driver->intersect_region) (cursor_region, clip_region);
1470 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1473 if (clip_region != control->clip_region)
1474 (*frame->driver->free_region) (clip_region);
1476 (*frame->driver->free_region) (cursor_region);
1480 static int gstring_num;
1483 free_gstring (void *object)
1485 MGlyphString *gstring = (MGlyphString *) object;
1488 free_gstring (gstring->next);
1489 if (gstring->size > 0)
1490 free (gstring->glyphs);
1496 static MGlyphString scratch_gstring;
1498 static MGlyphString *
1499 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1502 MGlyphString *gstring;
1504 if (pos == mt->nchars)
1508 gstring = &scratch_gstring;
1509 if (gstring->size == 0)
1514 g_tmp.type = GLYPH_ANCHOR;
1515 APPEND_GLYPH (gstring, g_tmp);
1516 APPEND_GLYPH (gstring, g_tmp);
1517 APPEND_GLYPH (gstring, g_tmp);
1518 gstring->glyphs[1].type = GLYPH_SPACE;
1519 gstring->glyphs[1].c = '\n';
1520 gstring->glyphs[1].code = '\n';
1522 gstring->from = pos;
1524 g->rface = frame->rface;
1525 g->pos = g->to = pos;
1527 g->rface = frame->rface;
1528 g->pos = pos++, g->to = pos;
1530 g->rface = frame->rface;
1531 g->pos = g->to = pos;
1536 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1537 MLIST_INIT1 (gstring, glyphs, 128);
1541 gstring->frame = frame;
1542 gstring->tick = frame->tick;
1543 gstring->top = gstring;
1544 gstring->control = *control;
1545 gstring->indent = gstring->width_limit = 0;
1546 if (control->format)
1547 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1549 gstring->width_limit = control->max_line_width;
1550 gstring->anti_alias = control->anti_alias;
1554 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1557 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1560 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1568 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1569 a width of glyphs for the character at I of MT. If I is not a
1570 beginning of a grapheme cluster, the corresponding element is
1572 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1573 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1574 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1575 pos_width[g->pos - gstring->from] += g->width;
1576 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1578 if (pos_width[i] > 0)
1580 if (width + pos_width[i] > gstring->width_limit)
1583 width += pos_width[i];
1586 pos = gstring->from + i;
1587 if (gstring->control.line_break)
1589 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1590 gstring->from, gstring->from + i,
1592 if (pos <= gstring->from)
1594 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1597 else if (pos >= gstring->to)
1602 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1605 if (pos < gstring->to)
1607 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1608 layout_glyph_string (frame, gstring);
1613 /* Return a gstring that covers a character at POS. */
1615 static MGlyphString *
1616 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1618 MGlyphString *gstring = NULL;
1620 if (pos < mtext_nchars (mt))
1622 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1625 && ((prop->start != 0
1626 && mtext_ref_char (mt, prop->start - 1) != '\n')
1627 || (prop->end < mtext_nchars (mt)
1628 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1630 mtext_detach_property (prop);
1635 gstring = prop->val;
1636 if (gstring->frame != frame
1637 || gstring->tick != frame->tick
1638 || memcmp (control, &gstring->control,
1639 (char *) (&control->with_cursor)
1640 - (char *) (control))
1641 || control->cursor_width != gstring->control.cursor_width
1642 || control->cursor_bidi != gstring->control.cursor_bidi)
1644 mtext_detach_property (prop);
1649 else if (! control->cursor_width)
1657 offset = mtext_character (mt, pos, 0, '\n');
1662 offset -= gstring->from;
1664 for (gst = gstring; gst; gst = gst->next)
1668 gst->from += offset;
1670 for (i = 0; i < gst->used; i++)
1672 gst->glyphs[i].pos += offset;
1673 gst->glyphs[i].to += offset;
1676 M17N_OBJECT_REF (gstring);
1681 int line = 0, y = 0;
1683 if (pos < mtext_nchars (mt))
1685 beg = mtext_character (mt, pos, 0, '\n');
1693 end = mtext_nchars (mt) + (control->cursor_width != 0);
1694 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1695 if (beg < mtext_nchars (mt))
1696 compose_glyph_string (frame, mt, beg, end, gstring);
1697 layout_glyph_string (frame, gstring);
1699 if (gstring->width_limit
1700 && gstring->width > gstring->width_limit)
1702 MGlyphString *gst = gstring;
1704 truncate_gstring (frame, mt, gst);
1705 while (gst->to < end)
1707 line++, y += gst->height;
1708 gst->next = alloc_gstring (frame, mt, gst->from, control,
1710 gst->next->top = gstring;
1711 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1713 layout_glyph_string (frame, gst);
1714 if (gst->width <= gst->width_limit)
1716 truncate_gstring (frame, mt, gst);
1720 if (! control->disable_caching && pos < mtext_nchars (mt))
1722 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1723 MTEXTPROP_VOLATILE_STRONG);
1725 if (end > mtext_nchars (mt))
1726 end = mtext_nchars (mt);
1727 mtext_attach_property (mt, beg, end, prop);
1728 M17N_OBJECT_UNREF (prop);
1732 while (gstring->to <= pos)
1734 if (! gstring->next)
1736 gstring = gstring->next;
1738 gstring->control = *control;
1744 static MDrawControl control_noop;
1746 #define ASSURE_CONTROL(control) \
1748 control = &control_noop; \
1753 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1754 MText *mt, int from, int to,
1755 MDrawControl *control)
1757 MGlyphString *gstring;
1759 M_CHECK_POS_X (mt, from, -1);
1760 ASSURE_CONTROL (control);
1761 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1762 to = mtext_nchars (mt) + (control->cursor_width != 0);
1766 gstring = get_gstring (frame, mt, from, to, control);
1768 MERROR (MERROR_DRAW, -1);
1769 render_glyph_string (frame, win, x, y, gstring, from, to);
1773 y += gstring->line_descent;
1774 M17N_OBJECT_UNREF (gstring->top);
1775 gstring = get_gstring (frame, mt, from, to, control);
1776 y += gstring->line_ascent;
1777 render_glyph_string (frame, win, x, y, gstring, from, to);
1780 M17N_OBJECT_UNREF (gstring->top);
1787 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1793 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1794 if (g->pos <= pos && g->to > pos)
1799 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1800 if (g->pos <= pos && g->to > pos)
1807 /* for debugging... */
1811 dump_combining_code (int code)
1813 char *vallign = "tcbB";
1814 char *hallign = "lcr";
1820 if (COMBINING_BY_CLASS_P (code))
1821 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1822 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1823 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1824 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1825 off_x = COMBINING_CODE_OFF_X (code) - 128;
1827 sprintf (work + 2, "+%d", off_y);
1829 sprintf (work + 2, "%d", off_y);
1830 else if (off_x == 0)
1831 sprintf (work + 2, ".");
1832 p = work + strlen (work);
1834 sprintf (p, ">%d", off_x);
1836 sprintf (p, "<%d", -off_x);
1838 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1839 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1845 dump_gstring (MGlyphString *gstring, int indent)
1847 char *prefix = (char *) alloca (indent + 1);
1848 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1850 memset (prefix, 32, indent);
1853 fprintf (stderr, "(glyph-string");
1855 for (g = MGLYPH (0); g < last_g; g++)
1857 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1859 g - gstring->glyphs,
1860 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1861 : g->type == GLYPH_ANCHOR ? "ANC"
1862 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1863 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1864 dump_combining_code (g->combining_code),
1865 g->width, g->bidi_level);
1866 fprintf (stderr, ")");
1870 /* m17n-X internal APIs */
1875 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1877 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1878 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1880 Minherited = msymbol ("inherited");
1881 Mcommon = msymbol ("common");
1883 McatCc = msymbol ("Cc");
1884 McatCf = msymbol ("Cf");
1886 MbidiR = msymbol ("R");
1887 MbidiAL = msymbol ("AL");
1888 MbidiRLE = msymbol ("RLE");
1889 MbidiRLO = msymbol ("RLO");
1890 MbidiBN = msymbol ("BN");
1891 MbidiS = msymbol ("S");
1892 MbidiNSM = msymbol ("NSM");
1894 fribidi_set_mirroring (TRUE);
1897 M_break_at_space = msymbol ("bs");
1898 M_break_at_word = msymbol ("bw");
1899 M_break_at_any = msymbol ("ba");
1900 M_kinsoku_bol = msymbol ("kb");
1901 M_kinsoku_eol = msymbol ("ke");
1909 MLIST_FREE1 (&scratch_gstring, glyphs);
1910 M17N_OBJECT_UNREF (linebreak_table);
1911 linebreak_table = NULL;
1915 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1919 /*** @addtogroup m17nDraw */
1924 @brief Draw an M-text on a window.
1926 The mdraw_text () function draws the text between $FROM and $TO of
1927 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1929 The appearance of the text (size, style, color, etc) is specified
1930 by the value of the text property whose key is @c Mface. If the
1931 M-text or a part of the M-text does not have such a text property,
1932 the default face of $FRAME is used.
1934 The font used to draw a character in the M-text is selected from
1935 the value of the fontset property of a face by the following
1940 <li> Search the text properties given to the character for the one
1941 whose key is @c Mcharset; its value should be either a symbol
1942 specifying a charset or #Mnil. If the value is #Mnil,
1943 proceed to the next step.
1945 Otherwise, search the mapping table of the fontset for the
1946 charset. If no entry is found proceed to the next step.
1948 If an entry is found, use one of the fonts in the entry that
1949 has a glyph for the character and that matches best with the
1950 face properties. If no such font exists, proceed to the next
1953 <li> Get the character property "script" of the character. If it is
1954 inherited, get the script property from the previous
1955 characters. If there is no previous character, or none of
1956 them has the script property other than inherited, proceed to
1959 Search the text properties given to the character for the one
1960 whose key is @c Mlanguage; its value should be either a
1961 symbol specifying a language or @c Mnil.
1963 Search the mapping table of the fontset for the combination
1964 of the script and language. If no entry is found, proceed to
1967 If an entry is found, use one of the fonts in the entry that
1968 has a glyph for the character and that matches best with the
1969 face properties. If no such font exists, proceed to the next
1972 <li> Search the fall-back table of the fontset for a font that has
1973 a glyph of the character. If such a font is found, use that
1978 If no font is found by the algorithm above, this function draws an
1979 empty box for the character.
1981 This function draws only the glyph foreground. To specify the
1982 background color, use mdraw_image_text () or
1983 mdraw_text_with_control ().
1985 This function is the counterpart of <tt>XDrawString ()</tt>,
1986 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1987 in the X Window System.
1990 If the operation was successful, mdraw_text () returns 0. If an
1991 error is detected, it returns -1 and assigns an error code to the
1992 external variable #merror_code. */
1994 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1996 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1997 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1999 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
2000 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
2001 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
2002 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
2004 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
2005 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
2009 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
2010 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
2011 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2012 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
2013 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
2014 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2016 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
2017 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2019 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
2020 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2021 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2023 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2024 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2026 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2027 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2029 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2030 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2032 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2033 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2037 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2039 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2040 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2042 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2043 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2046 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2047 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2049 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2056 mdraw_image_text () */
2059 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2060 MText *mt, int from, int to)
2062 MDrawControl control;
2064 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2065 memset (&control, 0, sizeof control);
2066 control.as_image = 0;
2067 return draw_text (frame, win, x, y, mt, from, to, &control);
2074 @brief Draw an M-text on a window as an image.
2076 The mdraw_image_text () function draws the text between $FROM and
2077 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2078 coordinate ($X, $Y).
2080 The way to draw a text is the same as in mdraw_text () except that
2081 this function also draws the background with the color specified
2084 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2085 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2086 functions in the X Window System.
2089 If the operation was successful, mdraw_image_text () returns 0.
2090 If an error is detected, it returns -1 and assigns an error code
2091 to the external variable #merror_code. */
2094 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2096 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2097 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2098 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2100 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2101 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2103 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2104 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2108 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2109 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2111 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2121 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2122 MText *mt, int from, int to)
2124 MDrawControl control;
2126 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2127 memset (&control, 0, sizeof control);
2128 control.as_image = 1;
2129 return draw_text (frame, win, x, y, mt, from, to, &control);
2135 @brief Draw an M-text on a window with fine control.
2137 The mdraw_text_with_control () function draws the text between
2138 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2139 coordinate ($X, $Y).
2141 The way to draw a text is the same as in mdraw_text () except that
2142 this function also follows what specified in the drawing control
2145 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2146 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2147 breaks lines and the following characters are drawn in the next
2148 line. See the documentation of the structure @ MDrawControl for
2152 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2154 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2155 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2158 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2159 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2161 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2162 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2163 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2166 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2167 MText *mt, int from, int to, MDrawControl *control)
2169 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2170 return draw_text (frame, win, x, y, mt, from, to, control);
2176 @brief Compute text pixel width.
2178 The mdraw_text_extents () function computes the width of text
2179 between $FROM and $TO of M-text $MT when it is drawn on a window
2180 of frame $FRAME using the mdraw_text_with_control () function with
2181 the drawing control object $CONTROL.
2183 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2184 the bounding box of character ink of the M-text, and stores the
2185 results in the members of the structure pointed to by
2186 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2187 surrounding box, the box is included in the bounding box.
2189 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2190 computes the bounding box that provides minimum spacing to other
2191 graphical features (such as surrounding box) for the M-text, and
2192 stores the results in the members of the structure pointed to by
2193 $OVERALL_LOGICAL_RETURN.
2195 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2196 computes the bounding box that provides minimum spacing to the
2197 other M-text drawn, and stores the results in the members of the
2198 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2199 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2200 min_line_ascent, min_line_descent, max_line_ascent, and
2201 max_line_descent of $CONTROL are all zero.
2204 This function returns the width of the text to be drawn in the
2205 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2206 text is drawn in multiple physical lines, it returns the width of
2207 the widest line. If an error occurs, it returns -1 and assigns an
2208 error code to the external variable #merror_code. */
2212 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2214 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2215 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2216 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2218 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2219 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2220 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2221 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2223 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2224 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2225 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2226 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2228 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2229 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2230 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2231 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2232 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2233 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2236 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2237 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2238 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2240 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2247 mdraw_text_extents (MFrame *frame,
2248 MText *mt, int from, int to, MDrawControl *control,
2249 MDrawMetric *overall_ink_return,
2250 MDrawMetric *overall_logical_return,
2251 MDrawMetric *overall_line_return)
2253 MGlyphString *gstring;
2255 int width, lbearing, rbearing;
2257 ASSURE_CONTROL (control);
2258 M_CHECK_POS_X (mt, from, -1);
2259 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2260 to = mtext_nchars (mt) + (control->cursor_width != 0);
2264 gstring = get_gstring (frame, mt, from, to, control);
2266 MERROR (MERROR_DRAW, -1);
2267 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2268 if (overall_ink_return)
2269 overall_ink_return->y = - gstring->physical_ascent;
2270 if (overall_logical_return)
2271 overall_logical_return->y = - gstring->ascent;
2272 if (overall_line_return)
2273 overall_line_return->y = - gstring->line_ascent;
2275 for (from = gstring->to; from < to; from = gstring->to)
2277 int this_width, this_lbearing, this_rbearing;
2279 y += gstring->line_descent;
2280 M17N_OBJECT_UNREF (gstring->top);
2281 gstring = get_gstring (frame, mt, from, to, control);
2282 this_width = gstring_width (gstring, from, to,
2283 &this_lbearing, &this_rbearing);
2284 y += gstring->line_ascent;
2285 if (width < this_width)
2287 if (rbearing < this_rbearing)
2288 rbearing = this_rbearing;
2289 if (lbearing > this_lbearing)
2290 lbearing = this_lbearing;
2292 if (overall_ink_return)
2294 overall_ink_return->x = lbearing;
2295 overall_ink_return->width = rbearing - lbearing;
2296 overall_ink_return->height
2297 = y + gstring->physical_descent - overall_ink_return->y;
2299 if (overall_logical_return)
2301 overall_ink_return->x = 0;
2302 overall_logical_return->width = width;
2303 overall_logical_return->height
2304 = y + gstring->descent - overall_logical_return->y;
2306 if (overall_line_return)
2308 overall_ink_return->x = lbearing;
2309 overall_line_return->width = MAX (width, rbearing - lbearing);
2310 overall_line_return->height
2311 = y + gstring->line_descent - overall_line_return->y;
2314 M17N_OBJECT_UNREF (gstring->top);
2321 @brief Compute the text dimensions of each character of M-text.
2323 The mdraw_text_per_char_extents () function computes the drawn
2324 metric of each character between $FROM and $TO of M-text $MT
2325 assuming that they are drawn on a window of frame $FRAME using the
2326 mdraw_text_with_control () function with the drawing control
2329 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2330 $LOGICAL_ARRAY_RETURN. Each successive element of
2331 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2332 ink and logical metrics of successive characters respectively,
2333 relative to the drawing origin of the M-text. The number of
2334 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2335 been set is returned to $NUM_CHARS_RETURN.
2337 If $ARRAY_SIZE is too small to return all metrics, the function
2338 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2339 Otherwise, it returns zero.
2341 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2342 @c NULL, this function also computes the metrics of the overall
2343 text and stores the results in the members of the structure
2344 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2346 If $CONTROL->two_dimensional is nonzero, this function computes
2347 only the metrics of characters in the first line. */
2349 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2351 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2352 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2353 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2355 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2356 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2357 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2358 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2359 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2361 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2362 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2365 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2366 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2367 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2369 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2372 mdraw_text_per_char_extents (MFrame *frame,
2373 MText *mt, int from, int to,
2374 MDrawControl *control,
2375 MDrawMetric *ink_array_return,
2376 MDrawMetric *logical_array_return,
2378 int *num_chars_return,
2379 MDrawMetric *overall_ink_return,
2380 MDrawMetric *overall_logical_return)
2382 MGlyphString *gstring;
2386 ASSURE_CONTROL (control);
2387 *num_chars_return = to - from;
2388 if (array_size < *num_chars_return)
2389 MERROR (MERROR_DRAW, -1);
2390 if (overall_logical_return)
2391 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2392 if (overall_ink_return)
2393 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2395 M_CHECK_RANGE (mt, from, to, -1, 0);
2396 gstring = get_gstring (frame, mt, from, to, control);
2399 *num_chars_return = 0;
2403 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2404 if (g->pos >= from && g->pos < to)
2408 int width = g->width;
2409 int lbearing = g->lbearing;
2410 int rbearing = g->rbearing;
2411 int ascent = g->ascent;
2412 int descent = g->descent;
2414 int logical_descent;
2416 if (g->rface->rfont)
2418 logical_ascent = g->rface->rfont->ascent;
2419 logical_descent = g->rface->rfont->descent;
2423 logical_ascent = g->rface->ascent;
2424 logical_descent = g->rface->descent;
2426 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2428 if (lbearing < width + g->lbearing)
2429 lbearing = width + g->lbearing;
2430 if (rbearing < width + g->rbearing)
2431 rbearing = width + g->rbearing;
2433 if (ascent < g->ascent)
2435 if (descent < g->descent)
2436 descent = g->descent;
2443 if (ink_array_return)
2445 ink_array_return[start - from].x = x + lbearing;
2446 ink_array_return[start - from].y = - ascent;
2447 ink_array_return[start - from].width = rbearing - lbearing;
2448 ink_array_return[start - from].height = ascent + descent;
2450 if (logical_array_return)
2452 logical_array_return[start - from].x = x;
2453 logical_array_return[start - from].y = - logical_descent;
2454 logical_array_return[start - from].height
2455 = logical_ascent + logical_descent;
2456 logical_array_return[start - from].width = width;
2464 if (overall_ink_return)
2466 overall_ink_return->y = - gstring->line_ascent;
2467 overall_ink_return->x = gstring->lbearing;
2468 overall_ink_return->width = x - gstring->lbearing;
2469 overall_ink_return->height = gstring->height;
2471 if (overall_logical_return)
2473 overall_logical_return->y = - gstring->ascent;
2474 overall_logical_return->x = 0;
2475 overall_logical_return->width = x;
2476 overall_logical_return->height = gstring->ascent + gstring->descent;
2479 M17N_OBJECT_UNREF (gstring->top);
2486 @brief Return the character position nearest to the coordinates.
2488 The mdraw_coordinates_position () function checks which character
2489 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2490 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2491 mdraw_text_with_control () function with the drawing control
2492 object $CONTROL. Here, the character position means the number of
2493 characters that precede the character in question in $MT, that is,
2494 the character position of the first character is 0.
2496 $FRAME is used only to get the default face information.
2499 If the glyph image of a character covers coordinate ($X, $Y),
2500 mdraw_coordinates_position () returns the character position of
2502 If $Y is less than the minimum Y-coordinate of the drawn area, it
2504 If $Y is greater than the maximum Y-coordinate of the drawn area,
2506 If $Y fits in with the drawn area but $X is less than the minimum
2507 X-coordinate, it returns the character position of the first
2508 character drawn on the line $Y.\n\n
2509 If $Y fits in with the drawn area but $X is greater than the
2510 maximum X-coordinate, it returns the character position of the
2511 last character drawn on the line $Y. */
2514 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2516 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2517 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2518 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2519 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2520 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2521 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2523 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2526 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2527 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2528 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2529 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2530 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2531 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2532 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2533 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2536 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2537 int x_offset, int y_offset, MDrawControl *control)
2539 MGlyphString *gstring;
2544 M_CHECK_POS_X (mt, from, -1);
2545 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2546 to = mtext_nchars (mt) + (control->cursor_width != 0);
2552 ASSURE_CONTROL (control);
2553 gstring = get_gstring (frame, mt, from, to, control);
2554 while (y + gstring->line_descent <= y_offset
2555 && gstring->to < to)
2558 y += gstring->line_descent;
2559 M17N_OBJECT_UNREF (gstring->top);
2560 gstring = get_gstring (frame, mt, from, to, control);
2561 y += gstring->line_ascent;
2564 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2565 if (! control->orientation_reversed)
2567 width = gstring->indent;
2568 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2569 if (g->pos >= from && g->pos < to)
2572 if (width > x_offset)
2578 width = - gstring->indent;
2579 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2580 if (g->pos >= from && g->pos < to)
2583 if (width < x_offset)
2587 if (g->type == GLYPH_ANCHOR
2588 && control->two_dimensional
2592 M17N_OBJECT_UNREF (gstring->top);
2600 @brief Compute information about a glyph.
2602 The mdraw_glyph_info () function computes information about a
2603 glyph that covers a character at position $POS of the M-text $MT
2604 assuming that the text is drawn from the character at $FROM of $MT
2605 on a window of frame $FRAME using the mdraw_text_with_control ()
2606 function with the drawing control object $CONTROL.
2608 The information is stored in the members of $INFO. */
2610 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2612 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2613 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2614 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2615 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2617 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2625 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2626 MDrawControl *control, MDrawGlyphInfo *info)
2628 MGlyphString *gstring;
2632 M_CHECK_RANGE_X (mt, from, pos, -1);
2634 ASSURE_CONTROL (control);
2635 gstring = get_gstring (frame, mt, from, pos + 1, control);
2637 MERROR (MERROR_DRAW, -1);
2638 while (gstring->to <= pos)
2640 y += gstring->line_descent;
2641 M17N_OBJECT_UNREF (gstring->top);
2642 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2643 y += gstring->line_ascent;
2645 info->line_from = gstring->from;
2646 if (info->line_from < from)
2647 info->line_from = from;
2648 info->line_to = gstring->to;
2651 if (! control->orientation_reversed)
2653 info->x = gstring->indent;
2654 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2655 info->x += g->width;
2659 info->x = - gstring->indent;
2660 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2661 info->x -= g->width;
2662 while (g[-1].to == g->to)
2665 info->from = g->pos;
2667 info->metrics.x = g->lbearing;
2668 info->metrics.y = - gstring->line_ascent;
2669 info->metrics.height = gstring->height;
2670 info->metrics.width = - g->lbearing + g->width;
2671 if (g->rface->rfont)
2672 info->font = (MFont *) g->rface->rfont;
2675 /* info->logical_width is calculated later. */
2677 if (info->from > info->line_from)
2679 /* The logically previous glyph is on this line. */
2680 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2682 info->prev_from = g_tmp->pos;
2684 else if (info->line_from > 0
2685 && gstring->from > 0)
2687 /* The logically previous glyph is on the previous line. */
2688 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2689 gstring->from, control);
2690 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2692 info->prev_from = g_tmp->pos;
2693 M17N_OBJECT_UNREF (gst->top);
2696 info->prev_from = -1;
2698 if (GLYPH_INDEX (g) > 1)
2699 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2700 else if (! control->orientation_reversed)
2702 if (info->line_from > 0)
2706 int p = gstring->from - 1;
2708 gst = get_gstring (frame, mt, p, gstring->from, control);
2709 g_tmp = gst->glyphs + (gst->used - 2);
2710 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2711 M17N_OBJECT_UNREF (gst->top);
2714 info->left_from = info->left_to = -1;
2718 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2722 int p = gstring->to;
2724 gst = get_gstring (frame, mt, p, p + 1, control);
2725 g_tmp = gst->glyphs + (gst->used - 2);
2726 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2727 M17N_OBJECT_UNREF (gst->top);
2730 info->left_from = info->left_to = -1;
2733 if (info->to < gstring->to)
2735 /* The logically next glyph is on this line. */
2736 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2738 info->next_to = g_tmp->to;
2740 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2742 /* The logically next glyph is on the next line. */
2744 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2745 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2747 info->next_to = g_tmp->to;
2748 M17N_OBJECT_UNREF (gst->top);
2753 for (info->logical_width = (g++)->width;
2754 g->pos == pos && g->type != GLYPH_ANCHOR;
2755 info->metrics.width += g->width, info->logical_width += (g++)->width);
2756 info->metrics.width += g[-1].rbearing - g[-1].width;
2758 if (g->type != GLYPH_ANCHOR)
2759 info->right_from = g->pos, info->right_to = g->to;
2760 else if (! control->orientation_reversed)
2762 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2765 M17N_OBJECT_UNREF (gstring->top);
2766 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2768 info->right_from = g->pos, info->right_to = g->to;
2771 info->right_from = info->right_to = -1;
2775 if (info->line_from > 0)
2777 pos = gstring->from - 1;
2778 M17N_OBJECT_UNREF (gstring->top);
2779 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2781 info->right_from = g->pos, info->right_to = g->to;
2784 info->right_from = info->right_to = -1;
2787 M17N_OBJECT_UNREF (gstring->top);
2794 @brief Compute information about glyph sequence.
2796 The mdraw_glyph_list () function computes information about glyphs
2797 corresponding to the text between $FROM and $TO of M-text $MT when
2798 it is drawn on a window of frame $FRAME using the
2799 mdraw_text_with_control () function with the drawing control
2800 object $CONTROL. $GLYPHS is an array of objects to store the
2801 information, and $ARRAY_SIZE is the array size.
2803 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2804 number of actually filled elements in the place pointed by
2805 $NUM_GLYPHS_RETURN, and returns 0.
2807 Otherwise, it stores the required array size in the place pointed
2808 by $NUM_GLYPHS_RETURN, and returns -1. */
2811 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2813 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2814 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2815 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2816 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2818 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2819 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2822 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2832 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2833 MDrawControl *control, MDrawGlyph *glyphs,
2834 int array_size, int *num_glyphs_return)
2836 MGlyphString *gstring;
2841 ASSURE_CONTROL (control);
2842 *num_glyphs_return = 0;
2843 M_CHECK_RANGE (mt, from, to, -1, 0);
2844 gstring = get_gstring (frame, mt, from, to, control);
2847 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2849 if (g->type == GLYPH_BOX
2850 || g->pos < from || g->pos >= to)
2852 if (g->type == GLYPH_PAD)
2854 if (g->left_padding)
2855 pad_width = g->width;
2859 glyphs[-1].x_advance += g->width;
2865 glyphs->from = g->pos;
2867 glyphs->glyph_code = g->code;
2868 glyphs->x_off = g->xoff + pad_width;
2869 glyphs->y_off = g->yoff;
2870 glyphs->lbearing = g->lbearing;
2871 glyphs->rbearing = g->rbearing;
2872 glyphs->ascent = g->ascent;
2873 glyphs->descent = g->descent;
2874 glyphs->x_advance = g->width + pad_width;
2875 glyphs->y_advance = 0;
2876 if (g->rface->rfont)
2878 glyphs->font = (MFont *) g->rface->rfont;
2880 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2881 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2883 glyphs->fontp = g->rface->rfont->fontp;
2887 glyphs->font = NULL;
2888 glyphs->font_type = Mnil;
2889 glyphs->fontp = NULL;
2896 M17N_OBJECT_UNREF (gstring->top);
2898 *num_glyphs_return = n;
2899 return (n <= array_size ? 0 : -1);
2905 @brief Draw one or more textitems.
2907 The mdraw_text_items () function draws one or more M-texts on
2908 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2909 of the textitems to be drawn and $NITEMS is the number of
2910 textitems in the array. */
2913 @brief textitem ¤òɽ¼¨¤¹¤ë.
2915 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2916 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2917 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2919 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2923 MTextItem, mdraw_text (). */
2926 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2927 MDrawTextItem *items, int nitems)
2929 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2931 while (nitems-- > 0)
2934 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2936 mdraw_text_with_control (frame, win, x, y,
2937 items->mt, 0, mtext_nchars (items->mt),
2939 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2940 items->control, NULL, NULL, NULL);
2943 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2949 @brief Option of line breaking for drawing text.
2951 The variable #mdraw_line_break_option specifies line breaking
2952 options by logical-or of the members of #MTextLineBreakOption. It
2953 controls the line breaking algorithm of the function
2954 mdraw_default_line_break (). */
2956 int mdraw_line_break_option;
2960 @brief Calculate a line breaking position.
2962 The function mdraw_default_line_break () calculates a line
2963 breaking position based on the line number $LINE and the
2964 coordinate $Y, when a line is too long to fit within the width
2965 limit. $POS is the position of the character next to the last one
2966 that fits within the limit. $FROM is the position of the first
2967 character of the line, and $TO is the position of the last
2968 character displayed on the line if there were not width limit.
2969 $LINE and $Y are reset to 0 when a line is broken by a newline
2970 character, and incremented each time when a long line is broken
2971 because of the width limit.
2973 @return This function returns a character position to break the
2978 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2980 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2981 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2982 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2983 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2984 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2985 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2986 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2989 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2993 mdraw_default_line_break (MText *mt, int pos,
2994 int from, int to, int line, int y)
2998 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
3009 @brief Obtain per character dimension information.
3011 The mdraw_per_char_extents () function computes the text dimension
3012 of each character in M-text $MT. The faces given as text
3013 properties in $MT and the default face of frame $FRAME determine
3014 the fonts to draw the text. Each successive element in
3015 $ARRAY_RETURN is set to the drawn metrics of successive
3016 characters, which is relative to the origin of the drawing, and a
3017 rectangle for each character in $MT. The number of elements of
3018 $ARRAY_RETURN must be equal to or greater than the number of
3021 If pointer $OVERALL_RETURN is not @c NULL, this function also
3022 computes the extents of the overall text and stores the results in
3023 the members of the structure pointed to by $OVERALL_RETURN. */
3026 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3028 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3029 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3030 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3031 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3032 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3033 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3034 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3036 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3037 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3038 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3040 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3043 mdraw_per_char_extents (MFrame *frame, MText *mt,
3044 MDrawMetric *array_return,
3045 MDrawMetric *overall_return)
3047 int n = mtext_nchars (mt);
3049 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3050 n, &n, overall_return, NULL);
3054 @brief clear cached information.
3056 The mdraw_clear_cache () function clear cached information
3057 on M-text $MT that was attached by any of the drawing functions.
3058 When the behavior of `format' or `line_break'
3059 member functions of MDrawControl is changed, the cache must be cleared.
3064 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3066 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3067 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3068 ¤¢¤ë¤¤¤Ï `line_break'
3069 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3075 mdraw_clear_cache (MText *mt)
3077 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);