1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-texts on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layout
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face
44 ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include <sys/types.h>
64 #include "m17n-misc.h"
69 #include "internal-gui.h"
74 #include <fribidi/fribidi.h>
75 #endif /* HAVE_FRIBIDI */
77 #define MAX(x, y) ((x) > (y) ? (x) : (y))
78 #define MIN(x, y) ((x) < (y) ? (x) : (y))
80 static MSymbol M_glyph_string;
83 static MSymbol Minherited, Mcommon;
84 /* Special categories */
85 static MSymbol McatCc, McatCf;
87 static MCharTable *linebreak_table;
88 static MSymbol M_break_at_space, M_break_at_word, M_break_at_any;
89 static MSymbol M_kinsoku_bol, M_kinsoku_eol;
92 /* Glyph-string composer. */
94 static MSymbol MbidiR;
95 static MSymbol MbidiAL;
96 static MSymbol MbidiRLE;
97 static MSymbol MbidiRLO;
98 static MSymbol MbidiBN;
99 static MSymbol MbidiS;
102 visual_order (MGlyphString *gstring)
104 int len = gstring->used - 2;
106 int bidi_sensitive = gstring->control.orientation_reversed;
110 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
111 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
113 FriBidiStrIndex *indices;
114 FriBidiLevel *levels;
115 #else /* not HAVE_FRIBIDI */
116 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
119 #endif /* not HAVE_FRIBIDI */
121 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
126 #endif /* not HAVE_FRIBIDI */
129 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
131 if (bidi == MbidiR || bidi == MbidiAL
132 || bidi == MbidiRLE || bidi == MbidiRLO)
137 #endif /* not HAVE_FRIBIDI */
143 if (! bidi_sensitive)
146 glyphs = alloca (sizeof (MGlyph) * len);
147 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
149 visual = alloca (sizeof (FriBidiChar) * (len + 1));
150 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
151 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
153 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
154 #else /* not HAVE_FRIBIDI */
155 indices = alloca (sizeof (int) * len);
156 for (i = 0; i < len; i++)
162 for (j = i + 1; j < len && levels[j]; j++);
163 for (k = j--; i < k; i++, j--)
170 #endif /* not HAVE_FRIBIDI */
172 for (i = 0; i < len;)
174 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
176 /* Length of grapheme-cluster */
181 if (visual[j] != logical[i])
186 g->code = mfont__encode_char (NULL, (MFont *) g->rface->rfont,
189 #endif /* HAVE_FRIBIDI */
190 g->bidi_level = levels[i];
191 for (seglen = 1, g++;
192 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
193 || glyphs[i + seglen].combining_code);
196 g->bidi_level = levels[i];
197 if (indices[i + seglen] < j)
198 j = indices[i + seglen];
200 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
206 reorder_combining_chars (MGlyphString *gstring, int from, int to)
208 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
214 for (g = gbeg; g != gend; g++)
215 if (COMBINING_CODE_CLASS (g->combining_code) > 0
216 && (COMBINING_CODE_CLASS (g[-1].combining_code)
217 > COMBINING_CODE_CLASS (g->combining_code)))
228 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
229 displaying them on FRAME.
231 This function fills these members:
232 pos, to, c, code, rface, bidi_level, categories, type, combining_code
233 The other members are filled by layout_glyph_string. */
236 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
237 MGlyphString *gstring)
239 MRealizedFace *default_rface = frame->rface;
240 int stop, face_change, language_change, charset_change, font_change;
241 MGlyph g_tmp, *g, *last_g;
243 MSymbol language = Mnil, script = Mnil, charset = Mnil;
244 MSymbol non_latin_script = Mnil;
245 MRealizedFace *rface = default_rface;
246 MRealizedFont *rfont;
247 int size = gstring->control.fixed_width;
250 MLIST_RESET (gstring);
251 gstring->from = from;
253 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
254 <category> and <rface> members.*/
257 /** Put anchor glyphs at the head and tail. */
258 g_tmp.type = GLYPH_ANCHOR;
259 g_tmp.pos = g_tmp.to = from;
260 APPEND_GLYPH (gstring, g_tmp);
261 stop = face_change = font_change = pos = from;
271 if (pos < mtext_nchars (mt))
273 MFont *font = rface->font;
277 if (pos == font_change)
279 font = mtext_get_prop (mt, pos, Mfont);
280 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
281 if (font_change == mtext_nchars (mt))
284 if (pos == face_change)
286 num = mtext_get_prop_values (mt, pos, Mface,
287 (void **) faces, 64);
288 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
289 if (face_change == mtext_nchars (mt))
294 faces[0] = &rface->face;
297 rface = mface__realize (frame, faces, num, size, font);
300 rface = default_rface;
302 if (stop > font_change)
304 if (stop > face_change)
308 if (pos < mtext_nchars (mt))
309 c = mtext_ref_char (mt, pos);
313 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
318 category = mchar_get_prop (c, Mcategory);
319 if (category == McatCf)
320 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
321 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
322 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
324 g_tmp.category = GLYPH_CATEGORY_NORMAL;
326 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
330 ctrl[0] = ctrl[1] = g_tmp;
332 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
333 APPEND_GLYPH (gstring, ctrl[0]);
334 APPEND_GLYPH (gstring, ctrl[1]);
337 APPEND_GLYPH (gstring, g_tmp);
338 if (c == '\n' && gstring->control.two_dimensional)
341 /* Append an anchor glyph. */
343 g_tmp.type = GLYPH_ANCHOR;
344 g_tmp.pos = g_tmp.to = pos;
345 APPEND_GLYPH (gstring, g_tmp);
348 /* The next loop is to change each <rface> member for non-ASCII
349 characters if necessary. */
350 stop = charset_change = language_change = from;
351 rfont = default_rface->rfont;
352 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
358 /* Short cut for the obvious case. */
359 this_script = Mlatin;
362 this_script = (MSymbol) mchar_get_prop (c, Mscript);
363 if (this_script == Minherited || this_script == Mcommon)
364 this_script = script;
365 if (this_script == Mcommon)
366 this_script = non_latin_script;
367 if (this_script == Mcommon)
369 /* Search forward for a character that explicitly
370 specifies a non-latin script. */
374 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
376 && (sym = mchar_get_prop (g1->c, Mscript)) != Mcommon
377 && sym != Minherited)
386 if (pos == stop || script != this_script || g->rface->rfont != rfont)
389 last_g = mface__for_chars (script, language, charset,
391 script = this_script;
392 if (script != Mnil && script != Mlatin)
393 non_latin_script = script;
394 rfont = g->rface->ascii_rface->rfont;
397 if (pos < mtext_nchars (mt) && pos == language_change)
399 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
400 mtext_prop_range (mt, Mlanguage, pos, NULL,
401 &language_change, 0);
403 if (pos < mtext_nchars (mt) && pos == charset_change)
405 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
406 mtext_prop_range (mt, Mcharset, pos, NULL,
410 if (stop > language_change)
411 stop = language_change;
412 if (stop > charset_change)
413 stop = charset_change;
418 last_g = mface__for_chars (script, language, charset, last_g, g, size);
420 /* The next loop is to run FLT or perform the default combining if
422 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
426 if (this->type == GLYPH_CHAR && this->rface->rfont)
430 if (this->rface->layouter != Mnil)
435 for (prev = MGLYPH (start - 1);
436 (prev->type == GLYPH_CHAR
437 && prev->category == GLYPH_CATEGORY_FORMATTER
438 && (code = mfont__encode_char (NULL,
439 (MFont *) this->rface->rfont,
441 != MCHAR_INVALID_CODE));
446 (g->type == GLYPH_CHAR
447 && g->rface->layouter == this->rface->layouter
448 && (g->rface->rfont == this->rface->rfont
449 || (g->category == GLYPH_CATEGORY_FORMATTER
450 && ((code = mfont__encode_char (NULL,
451 (MFont *) this->rface->rfont,
454 != MCHAR_INVALID_CODE))));
456 if (g->rface->rfont != this->rface->rfont)
458 g->rface->rfont = this->rface->rfont;
461 i = mfont__flt_run (gstring, start, i, this->rface);
465 while (this->type == GLYPH_CHAR
467 && this->category == GLYPH_CATEGORY_MODIFIER
468 && this->rface->rfont
469 && this->rface->rfont->layouter == Mnil)
471 int class = (int) mchar_get_prop (this->c,
474 = MAKE_COMBINING_CODE_BY_CLASS (class);
478 reorder_combining_chars (gstring, start, i);
479 if (this->type == GLYPH_ANCHOR)
488 /* At last, reorder glyphs visually if necessary. */
489 if (gstring->control.enable_bidi)
490 visual_order (gstring);
495 combining_code_from_class (int class)
500 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
501 else if (class == 200) /* below left attached */
502 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
503 else if (class == 202) /* below attached*/
504 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
505 else if (class == 204) /* below right attached */
506 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
507 else if (class == 208) /* left attached */
508 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
509 else if (class == 210) /* right attached */
510 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
511 else if (class == 212) /* above left attached */
512 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
513 else if (class == 214) /* above attached */
514 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
515 else if (class == 216) /* above right attached */
516 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
517 else if (class == 218) /* below left */
518 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
519 else if (class == 220) /* below */
520 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
521 else if (class == 222) /* below right */
522 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
523 else if (class == 224) /* left */
524 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
525 else if (class == 226) /* right */
526 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
527 else if (class == 228) /* above left */
528 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
529 else if (class == 230) /* above */
530 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
531 else if (class == 232) /* above right */
532 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
533 else if (class == 233) /* double below */
534 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
535 else if (class == 234) /* double above */
536 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
537 else if (class == 240) /* iota subscript */
538 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
540 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
546 int width, lbearing, rbearing;
550 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
551 MSubTextExtents *extents)
553 int g_physical_ascent, g_physical_descent;
554 MGlyph *g = MGLYPH (from);
555 MGlyph *last_g = MGLYPH (to);
558 g_physical_ascent = gstring->physical_ascent;
559 g_physical_descent = gstring->physical_descent;
560 extents->width = extents->lbearing = extents->rbearing = 0;
562 for (i = from; i < to;)
564 if ( MGLYPH (i)->otf_encoded)
570 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
571 mfont__get_metric (gstring, j, i);
579 MRealizedFont *rfont = base->rface->rfont;
580 int size = rfont->spec.size;
581 int width, lbearing, rbearing;
583 if (g == last_g || ! g->combining_code)
586 if (base->width == 0 && ! base->left_padding && ! base->right_padding
587 && GLYPH_INDEX (base) > from)
589 MGlyph *prev = base - 1;
591 if (base->pos < prev->pos)
592 prev->pos = base->pos;
594 base->pos = prev->pos;
595 if (base->to > prev->to)
601 if (base->left_padding && base->lbearing < 0)
603 base->xoff = - base->lbearing;
604 base->width += base->xoff;
605 base->rbearing += base->xoff;
608 if (base->right_padding && base->rbearing > base->width)
610 base->width = base->rbearing;
612 lbearing = (base->xoff + base->lbearing < 0
613 ? base->xoff + base->lbearing : 0);
614 rbearing = base->xoff + base->rbearing;
618 /* With combining glyphs. */
619 int left = -base->width;
621 int top = - base->ascent;
622 int bottom = base->descent;
623 int height = bottom - top;
624 int begin = base->pos;
629 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
630 rbearing = base->rbearing;
632 while (g != last_g && g->combining_code)
634 int combining_code = g->combining_code;
638 else if (end < g->to)
641 if (! COMBINING_PRECOMPUTED_P (combining_code))
643 int base_x, base_y, add_x, add_y, off_x, off_y;
645 if (COMBINING_BY_CLASS_P (combining_code))
646 g->combining_code = combining_code
647 = combining_code_from_class (COMBINING_CODE_CLASS
650 rfont = g->rface->rfont;
651 size = rfont->spec.size;
652 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
654 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
656 base_x = COMBINING_CODE_BASE_X (combining_code);
657 base_y = COMBINING_CODE_BASE_Y (combining_code);
658 add_x = COMBINING_CODE_ADD_X (combining_code);
659 add_y = COMBINING_CODE_ADD_Y (combining_code);
661 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
664 if (g->xoff + g->width > right)
665 right = g->xoff + g->width;
666 width = right - left;
669 g->yoff = top + height * base_y / 2;
673 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
677 if (g->xoff + g->lbearing < left + lbearing)
678 lbearing = g->xoff + g->lbearing - left;
679 if (g->xoff + g->rbearing > left + rbearing)
680 rbearing = g->xoff + g->rbearing - left;
681 if (g->yoff - g->ascent < top)
682 top = g->yoff - g->ascent;
683 if (g->yoff + g->descent > bottom)
684 bottom = g->yoff + g->descent;
685 height = bottom - top;
691 base->ascent = - top;
692 base->descent = bottom;
693 base->lbearing = lbearing;
694 base->rbearing = rbearing;
695 if (left < - base->width)
697 base->xoff = - base->width - left;
698 base->width += base->xoff;
699 base->rbearing += base->xoff;
700 base->lbearing += base->xoff;
704 base->width += right;
705 base->rbearing += right;
706 base->right_padding = 1;
707 for (i = 1; base + i != g; i++)
708 base[i].xoff -= right;
711 for (i = 0; base + i != g; i++)
718 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
719 g_physical_descent = MAX (g_physical_descent, base->descent);
720 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
721 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
722 extents->width += base->width;
725 gstring->physical_ascent = g_physical_ascent;
726 gstring->physical_descent = g_physical_descent;
730 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
731 by this function directly. Character glyphs are handled by
732 layouter functions registered in font drivers.
734 This function fill-in all the remaining members of glyphs. */
737 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
739 /* Default width of TAB. */
740 int tab_width = frame->space_width * (gstring->control.tab_width
741 ? gstring->control.tab_width : 8);
745 MDrawControl *control = &(gstring->control);
748 int box_line_height = 0;
749 int ignore_formatting_char = control->ignore_formatting_char;
751 gstring->ascent = gstring->descent = 0;
752 gstring->physical_ascent = gstring->physical_descent = 0;
753 gstring->width = gstring->lbearing = gstring->rbearing = 0;
757 while (g->type != GLYPH_ANCHOR)
759 if (box != g->rface->box)
761 int gidx = GLYPH_INDEX (g);
765 /* Insert the right side of the box. That glyph belongs
766 to the previous grapheme cluster. */
767 MGlyph box_glyph = g[-1];
769 box_glyph.type = GLYPH_BOX;
771 = (control->fixed_width
773 : box->inner_hmargin + box->width + box->outer_hmargin);
774 box_glyph.lbearing = 0;
775 box_glyph.rbearing = box_glyph.width;
777 box_glyph.right_padding = 1;
778 gstring->width += box_glyph.width;
779 gstring->rbearing += box_glyph.width;
780 INSERT_GLYPH (gstring, gidx, box_glyph);
787 /* Insert the left side of the box. That glyph belongs
788 to the following grapheme cluster. */
789 MGlyph box_glyph = *g;
790 int box_height = (box->width
791 + box->inner_vmargin + box->outer_vmargin);
793 if (box_line_height < box_height)
794 box_line_height = box_height;
795 box_glyph.type = GLYPH_BOX;
797 = (control->fixed_width
799 : box->inner_hmargin + box->width + box->outer_hmargin);
800 box_glyph.lbearing = 0;
801 box_glyph.rbearing = box_glyph.width;
803 box_glyph.left_padding = 1;
804 gstring->width += box_glyph.width;
805 gstring->rbearing += box_glyph.width;
806 INSERT_GLYPH (gstring, gidx, box_glyph);
812 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
813 g->type = GLYPH_SPACE;
815 if (g->type == GLYPH_CHAR)
817 MRealizedFace *rface = g->rface;
818 MRealizedFont *rfont = rface->rfont;
820 int from = GLYPH_INDEX (g);
822 for (g++; g->type == GLYPH_CHAR; g++)
823 if (! rfont != ! g->rface->rfont
824 || box != g->rface->box
825 || ((fromg->code == MCHAR_INVALID_CODE)
826 != (g->code == MCHAR_INVALID_CODE))
827 || (g->category == GLYPH_CATEGORY_FORMATTER
828 && ignore_formatting_char))
830 if (rfont && fromg->code != MCHAR_INVALID_CODE)
833 int to = GLYPH_INDEX (g);
834 MSubTextExtents extents;
836 layout_glyphs (frame, gstring, from, to, &extents);
837 extra_width = - extents.lbearing;
839 && ! control->disable_overlapping_adjustment
840 && (! control->orientation_reversed
841 ? ((to > 1 || control->align_head)
842 && g->type != GLYPH_ANCHOR)
843 : (((g->type && GLYPH_ANCHOR) || control->align_head)
848 pad.type = GLYPH_PAD;
851 pad.width = pad.rbearing = extra_width;
852 pad.left_padding = 1;
853 INSERT_GLYPH (gstring, from, pad);
855 extents.lbearing = 0;
856 extents.width += extra_width;
857 extents.rbearing += extra_width;
859 g = MGLYPH (from - 1);
860 if (g->type == GLYPH_SPACE)
862 /* The pad just inserted is absorbed (maybe
863 partially) by the previous space while
864 keeping at least some space width. For the
865 moment, we use the arbitrary width 2-pixel.
866 Perhaps, it should be decided by the current
867 face, or a default value of the current
868 frame, which is, however, not yet
870 if (extra_width + 2 < g->width)
872 g->width -= extra_width;
876 extra_width = g->width - 2;
879 gstring->width -= extra_width;
880 gstring->rbearing -= extra_width;
885 extra_width = extents.rbearing - extents.width;
887 && ! control->disable_overlapping_adjustment
888 && (GLYPH_INDEX (g) < gstring->used - 1
889 || (control->orientation_reversed && control->align_head)))
891 if (g->type == GLYPH_SPACE && box == g->rface->box)
894 pad.type = GLYPH_PAD;
897 pad.width = pad.rbearing = extra_width;
898 INSERT_GLYPH (gstring, to, pad);
903 g[-1].width += extra_width;
904 extents.width += extra_width;
907 if (gstring->lbearing > gstring->width + extents.lbearing)
908 gstring->lbearing = gstring->width + extents.lbearing;
909 if (gstring->rbearing < gstring->width + extents.rbearing)
910 gstring->rbearing = gstring->width + extents.rbearing;
911 gstring->width += extents.width;
912 if (gstring->ascent < rface->ascent)
913 gstring->ascent = rface->ascent;
914 if (gstring->descent < rface->descent)
915 gstring->descent = rface->descent;
919 for (; fromg < g; fromg++)
921 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
922 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
923 fromg->width = fromg->rbearing = 1;
925 fromg->width = fromg->rbearing = rface->space_width;
926 fromg->xoff = fromg->lbearing = 0;
927 fromg->ascent = fromg->descent = 0;
928 gstring->width += fromg->width;
929 gstring->rbearing += fromg->width;
931 if (gstring->ascent < frame->rface->ascent)
932 gstring->ascent = frame->rface->ascent;
933 if (gstring->descent < frame->descent)
934 gstring->descent = frame->rface->descent;
937 else if (g->type == GLYPH_SPACE)
940 g->width = g->rface->space_width;
941 else if (g->c == '\n')
943 g->width = control->cursor_width;
946 if (control->cursor_bidi)
948 else if (g->width < 0)
949 g->width = g->rface->space_width;
952 else if (g->c == '\t')
954 g->width = tab_width - ((gstring->indent + gstring->width)
960 if (g[-1].type == GLYPH_PAD)
962 /* This space glyph absorbs (maybe partially) the
963 previous padding glyph. */
964 g->width -= g[-1].width;
966 /* But, keep at least some space width. For the
967 moment, we use the arbitrary width 2-pixel. */
970 g->rbearing = g->width;
971 gstring->width += g->width;
972 gstring->rbearing += g->width;
975 if (gstring->ascent < g->rface->ascent)
976 gstring->ascent = g->rface->ascent;
977 if (gstring->descent < g->rface->descent)
978 gstring->descent = g->rface->descent;
984 gstring->width += g->width;
985 gstring->rbearing += g->width;
992 /* Insert the right side of the box. */
993 int gidx = GLYPH_INDEX (g);
994 MGlyph box_glyph = g[-1];
996 box_glyph.type = GLYPH_BOX;
998 = (control->fixed_width
1000 : box->inner_hmargin + box->width + box->outer_hmargin);
1001 box_glyph.lbearing = 0;
1002 box_glyph.rbearing = box_glyph.width;
1004 box_glyph.right_padding = 1;
1005 gstring->width += box_glyph.width;
1006 gstring->rbearing += box_glyph.width;
1007 INSERT_GLYPH (gstring, gidx, box_glyph);
1010 gstring->text_ascent = gstring->ascent;
1011 gstring->text_descent = gstring->descent;
1012 if (gstring->text_ascent < gstring->physical_ascent)
1013 gstring->text_ascent = gstring->physical_ascent;
1014 if (gstring->text_descent < gstring->physical_descent)
1015 gstring->text_descent = gstring->physical_descent;
1016 gstring->line_ascent = gstring->text_ascent;
1017 gstring->line_descent = gstring->text_descent;
1018 if (box_line_height > 0)
1020 gstring->line_ascent += box_line_height;
1021 gstring->physical_ascent = gstring->line_ascent;
1022 gstring->line_descent += box_line_height;
1023 gstring->physical_descent = gstring->line_descent;
1026 if (gstring->line_ascent < control->min_line_ascent)
1027 gstring->line_ascent = control->min_line_ascent;
1028 else if (control->max_line_ascent
1029 && control->max_line_ascent > control->min_line_ascent
1030 && gstring->line_ascent > control->max_line_ascent)
1031 gstring->line_ascent = control->max_line_ascent;
1033 if (gstring->line_descent < control->min_line_descent)
1034 gstring->line_descent = control->min_line_descent;
1035 else if (control->max_line_descent
1036 && control->max_line_descent > control->min_line_descent
1037 && gstring->line_descent > control->max_line_descent)
1038 gstring->line_descent = control->max_line_descent;
1039 gstring->height = gstring->line_ascent + gstring->line_descent;
1041 if (control->orientation_reversed
1044 /* We must adjust TAB width for RTL orientation. */
1045 width = gstring->indent;
1047 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1049 if (g->type == GLYPH_CHAR && g->c == '\t')
1051 int this_width = tab_width - (width % tab_width);
1053 if (g[1].type == GLYPH_PAD)
1054 this_width -= g[1].width;
1055 if (g[-1].type == GLYPH_PAD)
1056 this_width -= g[-1].width;
1059 gstring->width += this_width - g->width;
1060 gstring->rbearing += this_width - g->width;
1061 g->width = this_width;
1062 width += this_width;
1072 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1073 MGlyphString *gstring, int from, int to,
1074 int *from_idx, int *to_idx, int *to_x)
1076 MGlyph *g = MGLYPH (1);
1077 MDrawRegion region = (MDrawRegion) NULL;
1078 MDrawControl *control = &gstring->control;
1079 int cursor_pos = -1;
1081 int cursor_bidi = control->cursor_bidi;
1083 if (control->with_cursor && control->cursor_width)
1085 if (gstring->from <= control->cursor_pos
1086 && gstring->to > control->cursor_pos)
1087 cursor_pos = control->cursor_pos;
1090 && gstring->from <= control->cursor_pos - 1
1091 && gstring->to > control->cursor_pos - 1)
1092 prev_pos = control->cursor_pos - 1;
1095 *from_idx = *to_idx = 0;
1096 while (g->type != GLYPH_ANCHOR)
1098 if (g->pos >= from && g->pos < to)
1100 MGlyph *fromg = g, *cursor = NULL;
1101 MRealizedFace *rface = g->rface;
1103 int cursor_width = 0;
1107 *from_idx = GLYPH_INDEX (g);
1108 while (g->pos >= from && g->pos < to
1109 && g->rface == rface)
1112 if (g->type != GLYPH_BOX
1113 && g->pos <= cursor_pos && g->to > cursor_pos)
1116 cursor = g, cursor_x = x + width;
1117 cursor_width += g->width;
1119 width += g++->width;
1122 && (control->as_image
1123 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1125 int this_x = x, this_width = width;
1127 if (fromg->type == GLYPH_BOX)
1128 this_x += fromg->width, this_width -= fromg->width;
1129 if (g[-1].type == GLYPH_BOX)
1130 this_width -= g[-1].width;
1131 (frame->driver->fill_space)
1132 (frame, win, rface, 0,
1133 this_x, y - gstring->text_ascent, this_width,
1134 gstring->text_ascent + gstring->text_descent,
1135 control->clip_region);
1142 rect.y = y - gstring->text_ascent;
1143 rect.height = gstring->text_ascent + gstring->text_descent;
1146 rect.width = ((control->cursor_width > 0
1147 && control->cursor_width < cursor_width)
1148 ? control->cursor_width : cursor_width);
1152 if (cursor->bidi_level % 2)
1153 rect.x += cursor_width - rect.width;
1154 (*frame->driver->fill_space)
1155 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1156 control->clip_region);
1158 region = (*frame->driver->region_from_rect) (&rect);
1160 (*frame->driver->region_add_rect) (region, &rect);
1163 if (cursor->bidi_level % 2)
1166 rect.width = cursor_width < 4 ? cursor_width : 4;
1167 (*frame->driver->fill_space)
1168 (frame, win, rface, 1,
1169 rect.x, rect.y, rect.width, rect.height,
1170 control->clip_region);
1171 (*frame->driver->region_add_rect) (region, &rect);
1183 if (fromg->type != GLYPH_BOX
1184 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1187 cursor = fromg, cursor_x = x + temp_width;
1188 cursor_width += fromg->width;
1190 temp_width += fromg++->width;
1197 if (! (cursor->bidi_level % 2))
1198 rect.x += cursor_width - 1;
1199 rect.y = y - gstring->text_ascent;
1200 rect.height = gstring->text_ascent + gstring->text_descent;
1202 (*frame->driver->fill_space)
1203 (frame, win, rface, 1,
1204 rect.x, rect.y, rect.width, rect.height,
1205 control->clip_region);
1207 region = (*frame->driver->region_from_rect) (&rect);
1209 (*frame->driver->region_add_rect) (region, &rect);
1210 rect.y += rect.height - 2;
1212 rect.width = cursor_width < 4 ? cursor_width : 4;
1213 if (! (cursor->bidi_level % 2))
1214 rect.x -= rect.width - 1;
1215 (*frame->driver->fill_space) (frame, win, rface, 1,
1216 rect.x, rect.y, rect.width, rect.height,
1217 control->clip_region);
1218 (*frame->driver->region_add_rect) (region, &rect);
1222 *to_idx = GLYPH_INDEX (g);
1232 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1233 MGlyphString *gstring, int from_idx, int to_idx,
1234 int reverse, MDrawRegion region)
1236 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1242 (*frame->driver->region_to_rect) (region, &rect);
1245 while (g != gend && x + g->rbearing <= rect.x)
1248 width -= g++->width;
1249 while (! g->enabled && g != gend)
1253 rect.x += rect.width;
1254 if (rect.x < x + width)
1257 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1259 width -= (--gend)->width;
1260 while (! gend->enabled && g != gend)
1264 while (gend[-1].to == gend->to) gend++;
1272 MRealizedFace *rface = g->rface;
1273 int width = g->width;
1274 MGlyph *from_g = g++;
1276 /* Handle the glyphs of the same type/face at once. */
1278 && g->type == from_g->type
1279 && g->rface == rface
1280 && ((g->code == MCHAR_INVALID_CODE)
1281 == (from_g->code == MCHAR_INVALID_CODE))
1283 width += g++->width;
1285 if (from_g->type == GLYPH_CHAR)
1287 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1288 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1291 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1294 else if (from_g->type == GLYPH_BOX)
1296 /* Draw the left or right side of a box. If
1297 from_g->lbearing is nonzero, this is the left side,
1298 else this is the right side. */
1299 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1302 if (from_g->type != GLYPH_BOX)
1305 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1306 x, y, width, region);
1309 /* Draw the top and bottom side of a box. */
1310 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1311 x, y, width, region);
1322 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1323 int *from_x, int *to_x)
1326 int left_idx = *left, right_idx = *right;
1327 int left_x, right_x, x;
1329 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1332 if (x + g->rbearing > 0)
1334 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1336 left_idx = GLYPH_INDEX (g);
1341 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1344 if (x - g->width + g->lbearing < 0)
1346 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1348 right_idx = GLYPH_INDEX (g) + 1;
1353 if (*left == left_idx && *right == right_idx)
1356 if (*left != left_idx)
1358 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1363 if (*right != right_idx)
1365 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1375 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1380 if (from <= gstring->from && to >= gstring->to)
1383 *rbearing = gstring->rbearing;
1384 return gstring->width;
1389 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1390 if (g->pos >= from && g->pos < to)
1392 if (rbearing && width + g->rbearing > *rbearing)
1393 *rbearing = width + g->rbearing;
1401 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1402 MGlyphString *gstring, int from, int to)
1404 MDrawControl *control = &gstring->control;
1406 MDrawRegion clip_region, cursor_region;
1407 int from_idx, to_idx;
1410 if (control->orientation_reversed)
1411 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1413 x += gstring->indent;
1415 /* At first, draw all glyphs without cursor. */
1416 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1417 &from_idx, &to_idx, &to_x);
1419 if (control->partial_update)
1422 rect.width = to_x - x;
1423 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1425 rect.y = y - gstring->line_ascent;
1426 rect.height = gstring->height;
1427 clip_region = (*frame->driver->region_from_rect) (&rect);
1428 if (control->clip_region)
1429 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1432 clip_region = control->clip_region;
1435 clip_region = control->clip_region;
1437 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1442 (*frame->driver->intersect_region) (cursor_region, clip_region);
1443 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1446 if (clip_region != control->clip_region)
1447 (*frame->driver->free_region) (clip_region);
1449 (*frame->driver->free_region) (cursor_region);
1453 static int gstring_num;
1456 free_gstring (void *object)
1458 MGlyphString *gstring = (MGlyphString *) object;
1461 free_gstring (gstring->next);
1462 if (gstring->size > 0)
1463 free (gstring->glyphs);
1469 static MGlyphString scratch_gstring;
1471 static MGlyphString *
1472 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1475 MGlyphString *gstring;
1477 if (pos == mt->nchars)
1481 gstring = &scratch_gstring;
1482 if (gstring->size == 0)
1487 g_tmp.type = GLYPH_ANCHOR;
1488 APPEND_GLYPH (gstring, g_tmp);
1489 APPEND_GLYPH (gstring, g_tmp);
1490 APPEND_GLYPH (gstring, g_tmp);
1491 gstring->glyphs[1].type = GLYPH_SPACE;
1492 gstring->glyphs[1].c = '\n';
1493 gstring->glyphs[1].code = '\n';
1495 gstring->from = pos;
1497 g->rface = frame->rface;
1498 g->pos = g->to = pos;
1500 g->rface = frame->rface;
1501 g->pos = pos++, g->to = pos;
1503 g->rface = frame->rface;
1504 g->pos = g->to = pos;
1509 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1510 MLIST_INIT1 (gstring, glyphs, 128);
1514 gstring->frame = frame;
1515 gstring->tick = frame->tick;
1516 gstring->top = gstring;
1517 gstring->control = *control;
1518 gstring->indent = gstring->width_limit = 0;
1519 if (control->format)
1520 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1522 gstring->width_limit = control->max_line_width;
1523 gstring->anti_alias = control->anti_alias;
1527 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1530 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1538 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1539 a width of glyphs for the character at I of MT. If I is not a
1540 beginning of a grapheme cluster, the corresponding element is
1542 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1543 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1544 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1545 pos_width[g->pos - gstring->from] += g->width;
1546 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1548 if (pos_width[i] > 0)
1550 if (width + pos_width[i] > gstring->width_limit)
1553 width += pos_width[i];
1556 pos = gstring->from + i;
1557 if (gstring->control.line_break)
1559 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1560 gstring->from, gstring->from + i, 0, 0);
1561 if (pos <= gstring->from)
1562 pos = gstring->from + 1;
1563 else if (pos >= gstring->to)
1568 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1569 layout_glyph_string (frame, gstring);
1573 /* Return a gstring that covers a character at POS. */
1575 static MGlyphString *
1576 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1578 MGlyphString *gstring = NULL;
1580 if (pos < mtext_nchars (mt))
1582 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1585 && ((prop->start != 0
1586 && mtext_ref_char (mt, prop->start - 1) != '\n')
1587 || (prop->end < mtext_nchars (mt)
1588 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1590 mtext_detach_property (prop);
1595 gstring = prop->val;
1596 if (gstring->frame != frame
1597 || gstring->tick != frame->tick
1598 || memcmp (control, &gstring->control,
1599 (char *) (&control->with_cursor)
1600 - (char *) (control))
1601 || control->cursor_width != gstring->control.cursor_width
1602 || control->cursor_bidi != gstring->control.cursor_bidi)
1604 mtext_detach_property (prop);
1609 else if (! control->cursor_width)
1617 offset = mtext_character (mt, pos, 0, '\n');
1622 offset -= gstring->from;
1624 for (gst = gstring; gst; gst = gst->next)
1628 gst->from += offset;
1630 for (i = 0; i < gst->used; i++)
1632 gst->glyphs[i].pos += offset;
1633 gst->glyphs[i].to += offset;
1636 M17N_OBJECT_REF (gstring);
1641 int line = 0, y = 0;
1643 if (pos < mtext_nchars (mt))
1645 beg = mtext_character (mt, pos, 0, '\n');
1653 end = mtext_nchars (mt) + (control->cursor_width != 0);
1654 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1655 if (beg < mtext_nchars (mt))
1656 compose_glyph_string (frame, mt, beg, end, gstring);
1657 layout_glyph_string (frame, gstring);
1659 if (gstring->width_limit
1660 && gstring->width > gstring->width_limit)
1662 MGlyphString *gst = gstring;
1664 truncate_gstring (frame, mt, gst);
1665 while (gst->to < end)
1667 line++, y += gst->height;
1668 gst->next = alloc_gstring (frame, mt, gst->from, control,
1670 gst->next->top = gstring;
1671 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1673 layout_glyph_string (frame, gst);
1674 if (gst->width <= gst->width_limit)
1676 truncate_gstring (frame, mt, gst);
1680 if (! control->disable_caching && pos < mtext_nchars (mt))
1682 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1683 MTEXTPROP_VOLATILE_STRONG);
1685 if (end > mtext_nchars (mt))
1686 end = mtext_nchars (mt);
1687 mtext_attach_property (mt, beg, end, prop);
1688 M17N_OBJECT_UNREF (prop);
1692 while (gstring->to <= pos)
1694 if (! gstring->next)
1696 gstring = gstring->next;
1698 gstring->control = *control;
1704 static MDrawControl control_noop;
1706 #define ASSURE_CONTROL(control) \
1708 control = &control_noop; \
1713 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1714 MText *mt, int from, int to,
1715 MDrawControl *control)
1717 MGlyphString *gstring;
1719 M_CHECK_POS_X (mt, from, -1);
1720 ASSURE_CONTROL (control);
1721 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1722 to = mtext_nchars (mt) + (control->cursor_width != 0);
1726 gstring = get_gstring (frame, mt, from, to, control);
1728 MERROR (MERROR_DRAW, -1);
1729 render_glyph_string (frame, win, x, y, gstring, from, to);
1733 y += gstring->line_descent;
1734 M17N_OBJECT_UNREF (gstring->top);
1735 gstring = get_gstring (frame, mt, from, to, control);
1736 y += gstring->line_ascent;
1737 render_glyph_string (frame, win, x, y, gstring, from, to);
1740 M17N_OBJECT_UNREF (gstring->top);
1747 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1753 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1754 if (g->pos <= pos && g->to > pos)
1759 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1760 if (g->pos <= pos && g->to > pos)
1766 #define GET_LB_TYPE(MT, POS, LB_TYPE) \
1768 int c = mtext_ref_char ((MT), (POS)); \
1769 (LB_TYPE) = ((c == ' ' || c == '\t' || c == '\n') ? M_kinsoku_bol \
1770 : mchartable_lookup (linebreak_table, c)); \
1774 find_break_backward (MText *mt, int pos, int limit)
1781 GET_LB_TYPE (mt, pos, lb_type);
1782 if (lb_type == M_kinsoku_bol)
1783 return find_break_backward (mt, pos - 1, limit);
1784 if (lb_type == Mnil)
1788 GET_LB_TYPE (mt, pos - 1, lb_type);
1789 if (lb_type != Mnil)
1794 else if (lb_type == M_break_at_word)
1796 int beg = limit, end = mtext_nchars (mt);
1797 int in_word = mtext__word_segment (mt, pos, &beg, &end);
1801 else if (beg > limit)
1805 mtext__word_segment (mt, beg - 1, &beg, &end);
1811 GET_LB_TYPE (mt, pos - 1, lb_type);
1812 if (lb_type != M_kinsoku_eol)
1820 find_break_forward (MText *mt, int pos, int limit)
1824 GET_LB_TYPE (mt, pos, lb_type);
1825 if (lb_type == Mnil)
1830 GET_LB_TYPE (mt, pos, lb_type);
1833 else if (lb_type == M_break_at_word)
1835 int beg = 0, end = mtext_nchars (mt);
1836 int in_word = mtext__word_segment (mt, pos, &beg, &end);
1840 else if (end < limit)
1843 pos = end = mtext_nchars (mt);
1844 mtext__word_segment (mt, pos, &beg, &end);
1848 else if (lb_type == M_kinsoku_bol)
1852 GET_LB_TYPE (mt, pos, lb_type);
1853 if (lb_type != M_kinsoku_bol)
1861 /* for debugging... */
1865 dump_combining_code (int code)
1867 char *vallign = "tcbB";
1868 char *hallign = "lcr";
1874 if (COMBINING_BY_CLASS_P (code))
1875 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1876 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1877 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1878 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1879 off_x = COMBINING_CODE_OFF_X (code) - 128;
1881 sprintf (work + 2, "+%d", off_y);
1883 sprintf (work + 2, "%d", off_y);
1884 else if (off_x == 0)
1885 sprintf (work + 2, ".");
1886 p = work + strlen (work);
1888 sprintf (p, ">%d", off_x);
1890 sprintf (p, "<%d", -off_x);
1892 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1893 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1899 dump_gstring (MGlyphString *gstring, int indent)
1901 char *prefix = (char *) alloca (indent + 1);
1902 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1904 memset (prefix, 32, indent);
1907 fprintf (stderr, "(glyph-string");
1909 for (g = MGLYPH (0); g < last_g; g++)
1911 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1913 g - gstring->glyphs,
1914 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1915 : g->type == GLYPH_ANCHOR ? "ANC"
1916 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1917 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1918 dump_combining_code (g->combining_code),
1919 g->width, g->bidi_level);
1920 fprintf (stderr, ")");
1924 /* m17n-X internal APIs */
1929 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1931 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1932 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1934 Minherited = msymbol ("inherited");
1935 Mcommon = msymbol ("common");
1937 McatCc = msymbol ("Cc");
1938 McatCf = msymbol ("Cf");
1940 MbidiR = msymbol ("R");
1941 MbidiAL = msymbol ("AL");
1942 MbidiRLE = msymbol ("RLE");
1943 MbidiRLO = msymbol ("RLO");
1944 MbidiBN = msymbol ("BN");
1945 MbidiS = msymbol ("S");
1947 fribidi_set_mirroring (TRUE);
1950 M_break_at_space = msymbol ("bs");
1951 M_break_at_word = msymbol ("bw");
1952 M_break_at_any = msymbol ("ba");
1953 M_kinsoku_bol = msymbol ("kb");
1954 M_kinsoku_eol = msymbol ("ke");
1962 MLIST_FREE1 (&scratch_gstring, glyphs);
1963 M17N_OBJECT_UNREF (linebreak_table);
1964 linebreak_table = NULL;
1968 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1972 /*** @addtogroup m17nDraw */
1977 @brief Draw an M-text on a window.
1979 The mdraw_text () function draws the text between $FROM and $TO of
1980 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1982 The appearance of the text (size, style, color, etc) is specified
1983 by the value of the text property whose key is @c Mface. If the
1984 M-text or a part of the M-text does not have such a text property,
1985 the default face of $FRAME is used.
1987 The font used to draw a character in the M-text is selected from
1988 the value of the fontset property of a face by the following
1993 <li> Search the text properties given to the character for the one
1994 whose key is @c Mcharset; its value should be either a symbol
1995 specifying a charset or #Mnil. If the value is #Mnil,
1996 proceed to the next step.
1998 Otherwise, search the mapping table of the fontset for the
1999 charset. If no entry is found proceed to the next step.
2001 If an entry is found, use one of the fonts in the entry that
2002 has a glyph for the character and that matches best with the
2003 face properties. If no such font exists, proceed to the next
2006 <li> Get the character property "script" of the character. If it is
2007 inherited, get the script property from the previous
2008 characters. If there is no previous character, or none of
2009 them has the script property other than inherited, proceed to
2012 Search the text properties given to the character for the one
2013 whose key is @c Mlanguage; its value should be either a
2014 symbol specifying a language or @c Mnil.
2016 Search the mapping table of the fontset for the combination
2017 of the script and language. If no entry is found, proceed to
2020 If an entry is found, use one of the fonts in the entry that
2021 has a glyph for the character and that matches best with the
2022 face properties. If no such font exists, proceed to the next
2025 <li> Search the fall-back table of the fontset for a font that has
2026 a glyph of the character. If such a font is found, use that
2031 If no font is found by the algorithm above, this function draws an
2032 empty box for the character.
2034 This function draws only the glyph foreground. To specify the
2035 background color, use mdraw_image_text () or
2036 mdraw_text_with_control ().
2038 This function is the counterpart of <tt>XDrawString ()</tt>,
2039 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
2040 in the X Window System.
2043 If the operation was successful, mdraw_text () returns 0. If an
2044 error is detected, it returns -1 and assigns an error code to the
2045 external variable #merror_code. */
2047 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
2049 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
2050 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
2052 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
2053 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
2054 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
2055 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
2057 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
2058 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
2062 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
2063 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
2064 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2065 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
2066 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
2067 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2069 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
2070 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2072 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
2073 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2074 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2076 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2077 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2079 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2080 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2082 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2083 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2085 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2086 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2090 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2092 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2093 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2095 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2096 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2099 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2100 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2102 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2109 mdraw_image_text () */
2112 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2113 MText *mt, int from, int to)
2115 MDrawControl control;
2117 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2118 memset (&control, 0, sizeof control);
2119 control.as_image = 0;
2120 return draw_text (frame, win, x, y, mt, from, to, &control);
2127 @brief Draw an M-text on a window as an image.
2129 The mdraw_image_text () function draws the text between $FROM and
2130 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2131 coordinate ($X, $Y).
2133 The way to draw a text is the same as in mdraw_text () except that
2134 this function also draws the background with the color specified
2137 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2138 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2139 functions in the X Window System.
2142 If the operation was successful, mdraw_image_text () returns 0.
2143 If an error is detected, it returns -1 and assigns an error code
2144 to the external variable #merror_code. */
2147 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2149 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2150 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2151 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2153 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2154 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2156 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2157 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2161 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2162 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2164 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2174 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2175 MText *mt, int from, int to)
2177 MDrawControl control;
2179 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2180 memset (&control, 0, sizeof control);
2181 control.as_image = 1;
2182 return draw_text (frame, win, x, y, mt, from, to, &control);
2188 @brief Draw an M-text on a window with fine control.
2190 The mdraw_text_with_control () function draws the text between
2191 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2192 coordinate ($X, $Y).
2194 The way to draw a text is the same as in mdraw_text () except that
2195 this function also follows what specified in the drawing control
2198 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2199 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2200 breaks lines and the following characters are drawn in the next
2201 line. See the documentation of the structure @ MDrawControl for
2205 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2207 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2208 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2211 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2212 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2214 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2215 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2216 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2219 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2220 MText *mt, int from, int to, MDrawControl *control)
2222 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2223 return draw_text (frame, win, x, y, mt, from, to, control);
2229 @brief Compute text pixel width.
2231 The mdraw_text_extents () function computes the width of text
2232 between $FROM and $TO of M-text $MT when it is drawn on a window
2233 of frame $FRAME using the mdraw_text_with_control () function with
2234 the drawing control object $CONTROL.
2236 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2237 the bounding box of character ink of the M-text, and stores the
2238 results in the members of the structure pointed to by
2239 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2240 surrounding box, the box is included in the bounding box.
2242 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2243 computes the bounding box that provides minimum spacing to other
2244 graphical features (such as surrounding box) for the M-text, and
2245 stores the results in the members of the structure pointed to by
2246 $OVERALL_LOGICAL_RETURN.
2248 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2249 computes the bounding box that provides minimum spacing to the
2250 other M-text drawn, and stores the results in the members of the
2251 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2252 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2253 min_line_ascent, min_line_descent, max_line_ascent, and
2254 max_line_descent of $CONTROL are all zero.
2257 This function returns the width of the text to be drawn in the
2258 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2259 text is drawn in multiple physical lines, it returns the width of
2260 the widest line. If an error occurs, it returns -1 and assigns an
2261 error code to the external variable #merror_code. */
2265 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2267 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2268 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2269 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2271 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2272 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2273 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2274 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2276 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2277 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2278 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2279 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2281 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2282 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2283 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2284 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2285 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2286 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2289 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2290 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2291 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2293 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2300 mdraw_text_extents (MFrame *frame,
2301 MText *mt, int from, int to, MDrawControl *control,
2302 MDrawMetric *overall_ink_return,
2303 MDrawMetric *overall_logical_return,
2304 MDrawMetric *overall_line_return)
2306 MGlyphString *gstring;
2308 int width, rbearing;
2310 ASSURE_CONTROL (control);
2311 M_CHECK_POS_X (mt, from, -1);
2312 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2313 to = mtext_nchars (mt) + (control->cursor_width != 0);
2317 gstring = get_gstring (frame, mt, from, to, control);
2319 MERROR (MERROR_DRAW, -1);
2320 width = gstring_width (gstring, from, to, &rbearing);
2321 if (overall_ink_return)
2323 overall_ink_return->y = - gstring->physical_ascent;
2324 overall_ink_return->x = gstring->lbearing;
2326 if (overall_logical_return)
2328 overall_logical_return->y = - gstring->ascent;
2329 overall_logical_return->x = 0;
2331 if (overall_line_return)
2333 overall_line_return->y = - gstring->line_ascent;
2334 overall_line_return->x = gstring->lbearing;
2337 for (from = gstring->to; from < to; from = gstring->to)
2339 int this_width, this_rbearing;
2341 y += gstring->line_descent;
2342 M17N_OBJECT_UNREF (gstring->top);
2343 gstring = get_gstring (frame, mt, from, to, control);
2344 this_width = gstring_width (gstring, from, to, &this_rbearing);
2345 y += gstring->line_ascent;
2346 if (width < this_width)
2348 if (rbearing < this_rbearing)
2349 rbearing = this_rbearing;
2351 if (overall_ink_return)
2353 overall_ink_return->width = rbearing;
2354 overall_ink_return->height
2355 = y + gstring->physical_descent - overall_ink_return->y;
2357 if (overall_logical_return)
2359 overall_logical_return->width = width;
2360 overall_logical_return->height
2361 = y + gstring->descent - overall_logical_return->y;
2363 if (overall_line_return)
2365 overall_line_return->width = MAX (width, rbearing);
2366 overall_line_return->height
2367 = y + gstring->line_descent - overall_line_return->y;
2370 M17N_OBJECT_UNREF (gstring->top);
2377 @brief Compute the text dimensions of each character of M-text.
2379 The mdraw_text_per_char_extents () function computes the drawn
2380 metric of each character between $FROM and $TO of M-text $MT
2381 assuming that they are drawn on a window of frame $FRAME using the
2382 mdraw_text_with_control () function with the drawing control
2385 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2386 $LOGICAL_ARRAY_RETURN. Each successive element of
2387 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2388 ink and logical metrics of successive characters respectively,
2389 relative to the drawing origin of the M-text. The number of
2390 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2391 been set is returned to $NUM_CHARS_RETURN.
2393 If $ARRAY_SIZE is too small to return all metrics, the function
2394 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2395 Otherwise, it returns zero.
2397 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2398 @c NULL, this function also computes the metrics of the overall
2399 text and stores the results in the members of the structure
2400 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2402 If $CONTROL->two_dimensional is nonzero, this function computes
2403 only the metrics of characters in the first line. */
2405 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2407 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2408 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2409 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2411 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2412 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2413 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2414 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2415 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2417 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2418 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2421 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2422 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2423 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2425 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2428 mdraw_text_per_char_extents (MFrame *frame,
2429 MText *mt, int from, int to,
2430 MDrawControl *control,
2431 MDrawMetric *ink_array_return,
2432 MDrawMetric *logical_array_return,
2434 int *num_chars_return,
2435 MDrawMetric *overall_ink_return,
2436 MDrawMetric *overall_logical_return)
2438 MGlyphString *gstring;
2442 ASSURE_CONTROL (control);
2443 *num_chars_return = to - from;
2444 if (array_size < *num_chars_return)
2445 MERROR (MERROR_DRAW, -1);
2446 if (overall_logical_return)
2447 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2448 if (overall_ink_return)
2449 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2451 M_CHECK_RANGE (mt, from, to, -1, 0);
2452 gstring = get_gstring (frame, mt, from, to, control);
2455 *num_chars_return = 0;
2459 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2460 if (g->pos >= from && g->pos < to)
2464 int width = g->width;
2465 int lbearing = g->lbearing;
2466 int rbearing = g->rbearing;
2467 int ascent = g->ascent;
2468 int descent = g->descent;
2470 int logical_descent;
2472 if (g->rface->rfont)
2474 logical_ascent = g->rface->rfont->ascent;
2475 logical_descent = g->rface->rfont->descent;
2479 logical_ascent = g->rface->ascent;
2480 logical_descent = g->rface->descent;
2482 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2484 if (lbearing < width + g->lbearing)
2485 lbearing = width + g->lbearing;
2486 if (rbearing < width + g->rbearing)
2487 rbearing = width + g->rbearing;
2489 if (ascent < g->ascent)
2491 if (descent < g->descent)
2492 descent = g->descent;
2499 if (ink_array_return)
2501 ink_array_return[start - from].x = x + lbearing;
2502 ink_array_return[start - from].y = - ascent;
2503 ink_array_return[start - from].width = rbearing - lbearing;
2504 ink_array_return[start - from].height = ascent + descent;
2506 if (logical_array_return)
2508 logical_array_return[start - from].x = x;
2509 logical_array_return[start - from].y = - logical_descent;
2510 logical_array_return[start - from].height
2511 = logical_ascent + logical_descent;
2512 logical_array_return[start - from].width = width;
2520 if (overall_ink_return)
2522 overall_ink_return->y = - gstring->line_ascent;
2523 overall_ink_return->x = gstring->lbearing;
2524 overall_ink_return->width = x - gstring->lbearing;
2525 overall_ink_return->height = gstring->height;
2527 if (overall_logical_return)
2529 overall_logical_return->y = - gstring->ascent;
2530 overall_logical_return->x = 0;
2531 overall_logical_return->width = x;
2532 overall_logical_return->height = gstring->ascent + gstring->descent;
2535 M17N_OBJECT_UNREF (gstring->top);
2542 @brief Return the character position nearest to the coordinates.
2544 The mdraw_coordinates_position () function checks which character
2545 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2546 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2547 mdraw_text_with_control () function with the drawing control
2548 object $CONTROL. Here, the character position means the number of
2549 characters that precede the character in question in $MT, that is,
2550 the character position of the first character is 0.
2552 $FRAME is used only to get the default face information.
2555 If the glyph image of a character covers coordinate ($X, $Y),
2556 mdraw_coordinates_position () returns the character position of
2558 If $Y is less than the minimum Y-coordinate of the drawn area, it
2560 If $Y is greater than the maximum Y-coordinate of the drawn area,
2562 If $Y fits in with the drawn area but $X is less than the minimum
2563 X-coordinate, it returns the character position of the first
2564 character drawn on the line $Y.\n\n
2565 If $Y fits in with the drawn area but $X is greater than the
2566 maximum X-coordinate, it returns the character position of the
2567 last character drawn on the line $Y. */
2570 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2572 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2573 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2574 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2575 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2576 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2577 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2579 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2582 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2583 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2584 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2585 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2586 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2587 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2588 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2589 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2592 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2593 int x_offset, int y_offset, MDrawControl *control)
2595 MGlyphString *gstring;
2600 M_CHECK_POS_X (mt, from, -1);
2601 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2602 to = mtext_nchars (mt) + (control->cursor_width != 0);
2608 ASSURE_CONTROL (control);
2609 gstring = get_gstring (frame, mt, from, to, control);
2610 while (y + gstring->line_descent <= y_offset
2611 && gstring->to < to)
2614 y += gstring->line_descent;
2615 M17N_OBJECT_UNREF (gstring->top);
2616 gstring = get_gstring (frame, mt, from, to, control);
2617 y += gstring->line_ascent;
2620 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2621 if (! control->orientation_reversed)
2623 width = gstring->indent;
2624 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2625 if (g->pos >= from && g->pos < to)
2628 if (width > x_offset)
2634 width = - gstring->indent;
2635 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2636 if (g->pos >= from && g->pos < to)
2639 if (width < x_offset)
2643 if (g->type == GLYPH_ANCHOR
2644 && control->two_dimensional
2648 M17N_OBJECT_UNREF (gstring->top);
2656 @brief Compute information about a glyph.
2658 The mdraw_glyph_info () function computes information about a
2659 glyph that covers a character at position $POS of the M-text $MT
2660 assuming that the text is drawn from the character at $FROM of $MT
2661 on a window of frame $FRAME using the mdraw_text_with_control ()
2662 function with the drawing control object $CONTROL.
2664 The information is stored in the members of $INFO. */
2666 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2668 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2669 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2670 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2671 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2673 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2681 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2682 MDrawControl *control, MDrawGlyphInfo *info)
2684 MGlyphString *gstring;
2688 M_CHECK_RANGE_X (mt, from, pos, -1);
2690 ASSURE_CONTROL (control);
2691 gstring = get_gstring (frame, mt, from, pos + 1, control);
2693 MERROR (MERROR_DRAW, -1);
2694 while (gstring->to <= pos)
2696 y += gstring->line_descent;
2697 M17N_OBJECT_UNREF (gstring->top);
2698 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2699 y += gstring->line_ascent;
2701 info->line_from = gstring->from;
2702 if (info->line_from < from)
2703 info->line_from = from;
2704 info->line_to = gstring->to;
2707 if (! control->orientation_reversed)
2709 info->x = gstring->indent;
2710 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2711 info->x += g->width;
2715 info->x = - gstring->indent;
2716 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2717 info->x -= g->width;
2718 while (g[-1].to == g->to)
2721 info->from = g->pos;
2723 info->metrics.x = g->lbearing;
2724 info->metrics.y = - gstring->line_ascent;
2725 info->metrics.height = gstring->height;
2726 info->metrics.width = - g->lbearing + g->width;
2727 if (g->rface->rfont)
2728 info->font = (MFont *) g->rface->rfont;
2731 /* info->logical_width is calculated later. */
2733 if (info->from > info->line_from)
2735 /* The logically previous glyph is on this line. */
2736 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2738 info->prev_from = g_tmp->pos;
2740 else if (info->line_from > 0)
2742 /* The logically previous glyph is on the previous line. */
2743 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2744 gstring->from, control);
2745 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2747 info->prev_from = g_tmp->pos;
2748 M17N_OBJECT_UNREF (gst->top);
2751 info->prev_from = -1;
2753 if (GLYPH_INDEX (g) > 1)
2754 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2755 else if (! control->orientation_reversed)
2757 if (info->line_from > 0)
2761 int p = gstring->from - 1;
2763 gst = get_gstring (frame, mt, p, gstring->from, control);
2764 g_tmp = gst->glyphs + (gst->used - 2);
2765 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2766 M17N_OBJECT_UNREF (gst->top);
2769 info->left_from = info->left_to = -1;
2773 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2777 int p = gstring->to;
2779 gst = get_gstring (frame, mt, p, p + 1, control);
2780 g_tmp = gst->glyphs + (gst->used - 2);
2781 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2782 M17N_OBJECT_UNREF (gst->top);
2785 info->left_from = info->left_to = -1;
2788 if (info->to < gstring->to)
2790 /* The logically next glyph is on this line. */
2791 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2793 info->next_to = g_tmp->to;
2795 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2797 /* The logically next glyph is on the next line. */
2799 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2800 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2802 info->next_to = g_tmp->to;
2803 M17N_OBJECT_UNREF (gst->top);
2808 for (info->logical_width = (g++)->width;
2809 g->pos == pos && g->type != GLYPH_ANCHOR;
2810 info->metrics.width += g->width, info->logical_width += (g++)->width);
2811 info->metrics.width += g[-1].rbearing - g[-1].width;
2813 if (g->type != GLYPH_ANCHOR)
2814 info->right_from = g->pos, info->right_to = g->to;
2815 else if (! control->orientation_reversed)
2817 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2820 M17N_OBJECT_UNREF (gstring->top);
2821 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2823 info->right_from = g->pos, info->right_to = g->to;
2826 info->right_from = info->right_to = -1;
2830 if (info->line_from > 0)
2832 pos = gstring->from - 1;
2833 M17N_OBJECT_UNREF (gstring->top);
2834 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2836 info->right_from = g->pos, info->right_to = g->to;
2839 info->right_from = info->right_to = -1;
2842 M17N_OBJECT_UNREF (gstring->top);
2849 @brief Compute information about glyph sequence.
2851 The mdraw_glyph_list () function computes information about glyphs
2852 corresponding to the text between $FROM and $TO of M-text $MT when
2853 it is drawn on a window of frame $FRAME using the
2854 mdraw_text_with_control () function with the drawing control
2855 object $CONTROL. $GLYPHS is an array of objects to store the
2856 information, and $ARRAY_SIZE is the array size.
2858 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2859 number of actually filled elements in the place pointed by
2860 $NUM_GLYPHS_RETURN, and returns 0.
2862 Otherwise, it stores the required array size in the place pointed
2863 by $NUM_GLYPHS_RETURN, and returns -1. */
2866 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2868 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2869 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2870 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2871 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2873 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2874 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2877 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2887 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2888 MDrawControl *control, MDrawGlyph *glyphs,
2889 int array_size, int *num_glyphs_return)
2891 MGlyphString *gstring;
2896 ASSURE_CONTROL (control);
2897 *num_glyphs_return = 0;
2898 M_CHECK_RANGE (mt, from, to, -1, 0);
2899 gstring = get_gstring (frame, mt, from, to, control);
2902 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2904 if (g->type == GLYPH_BOX
2905 || g->pos < from || g->pos >= to)
2907 if (g->type == GLYPH_PAD)
2909 if (g->left_padding)
2910 pad_width = g->width;
2914 glyphs[-1].x_advance += g->width;
2920 glyphs->from = g->pos;
2922 glyphs->glyph_code = g->code;
2923 glyphs->x_off = g->xoff + pad_width;
2924 glyphs->y_off = g->yoff;
2925 glyphs->lbearing = g->lbearing;
2926 glyphs->rbearing = g->rbearing;
2927 glyphs->ascent = g->ascent;
2928 glyphs->descent = g->descent;
2929 glyphs->x_advance = g->width + pad_width;
2930 glyphs->y_advance = 0;
2931 if (g->rface->rfont)
2933 glyphs->font = (MFont *) g->rface->rfont;
2935 = (g->rface->rfont->font->type == MFONT_SOURCE_X ? Mx
2936 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2938 glyphs->fontp = g->rface->rfont->fontp;
2942 glyphs->font = NULL;
2943 glyphs->font_type = Mnil;
2944 glyphs->fontp = NULL;
2951 M17N_OBJECT_UNREF (gstring->top);
2953 *num_glyphs_return = n;
2954 return (n <= array_size ? 0 : -1);
2960 @brief Draw one or more textitems.
2962 The mdraw_text_items () function draws one or more M-texts on
2963 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2964 of the textitems to be drawn and $NITEMS is the number of
2965 textitems in the array. */
2968 @brief textitem ¤òɽ¼¨¤¹¤ë.
2970 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2971 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2972 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2974 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2978 MTextItem, mdraw_text (). */
2981 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2982 MDrawTextItem *items, int nitems)
2984 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2986 while (nitems-- > 0)
2989 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2991 mdraw_text_with_control (frame, win, x, y,
2992 items->mt, 0, mtext_nchars (items->mt),
2994 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2995 items->control, NULL, NULL, NULL);
2998 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
3004 @brief calculate a line breaking position.
3006 The function mdraw_default_line_break () calculates a line
3007 breaking position based on the line number $LINE and the
3008 coordinate $Y, when a line is too long to fit within the width
3009 limit. $POS is the position of the character next to the last
3010 one that fits within the limit. $FROM is the position of the
3011 first character of the line, and $TO is the position of the last
3012 character displayed on the line if there were not width limit.
3013 $LINE and $Y are reset to 0 when a line is broken by a newline
3014 character, and incremented each time when a long line is broken
3015 because of the width limit.
3018 This function returns a character position to break the
3023 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
3025 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
3026 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
3027 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
3028 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
3029 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
3030 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
3031 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
3034 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
3038 mdraw_default_line_break (MText *mt, int pos,
3039 int from, int to, int line, int y)
3043 if (! linebreak_table)
3045 MDatabase *mdb = mdatabase_find (Mchar_table, Msymbol,
3046 msymbol ("linebreak"), Mnil);
3049 linebreak_table = mdatabase_load (mdb);
3050 if (! linebreak_table)
3051 linebreak_table = mchartable (Msymbol, Mnil);
3056 p = find_break_backward (mt, pos, from);
3062 p = find_break_forward (mt, pos, to);
3072 @brief Obtain per character dimension information.
3074 The mdraw_per_char_extents () function computes the text dimension
3075 of each character in M-text $MT. The faces given as text
3076 properties in $MT and the default face of frame $FRAME determine
3077 the fonts to draw the text. Each successive element in
3078 $ARRAY_RETURN is set to the drawn metrics of successive
3079 characters, which is relative to the origin of the drawing, and a
3080 rectangle for each character in $MT. The number of elements of
3081 $ARRAY_RETURN must be equal to or greater than the number of
3084 If pointer $OVERALL_RETURN is not @c NULL, this function also
3085 computes the extents of the overall text and stores the results in
3086 the members of the structure pointed to by $OVERALL_RETURN. */
3089 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3091 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3092 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3093 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3094 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3095 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3096 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3097 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3099 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3100 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3101 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3103 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3106 mdraw_per_char_extents (MFrame *frame, MText *mt,
3107 MDrawMetric *array_return,
3108 MDrawMetric *overall_return)
3110 int n = mtext_nchars (mt);
3112 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3113 n, &n, overall_return, NULL);
3117 @brief clear cached information.
3119 The mdraw_clear_cache () function clear cached information
3120 on M-text $MT that was attached by any of the drawing functions.
3121 When the behavior of `format' or `line_break'
3122 member functions of MDrawControl is changed, the cache must be cleared.
3127 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3129 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3130 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3131 ¤¢¤ë¤¤¤Ï `line_break'
3132 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3138 mdraw_clear_cache (MText *mt)
3140 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);