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 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1530 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1533 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1541 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1542 a width of glyphs for the character at I of MT. If I is not a
1543 beginning of a grapheme cluster, the corresponding element is
1545 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1546 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1547 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1548 pos_width[g->pos - gstring->from] += g->width;
1549 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1551 if (pos_width[i] > 0)
1553 if (width + pos_width[i] > gstring->width_limit)
1556 width += pos_width[i];
1559 pos = gstring->from + i;
1560 if (gstring->control.line_break)
1562 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1563 gstring->from, gstring->from + i,
1565 if (pos <= gstring->from)
1567 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1570 else if (pos >= gstring->to)
1575 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1576 layout_glyph_string (frame, gstring);
1580 /* Return a gstring that covers a character at POS. */
1582 static MGlyphString *
1583 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1585 MGlyphString *gstring = NULL;
1587 if (pos < mtext_nchars (mt))
1589 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1592 && ((prop->start != 0
1593 && mtext_ref_char (mt, prop->start - 1) != '\n')
1594 || (prop->end < mtext_nchars (mt)
1595 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1597 mtext_detach_property (prop);
1602 gstring = prop->val;
1603 if (gstring->frame != frame
1604 || gstring->tick != frame->tick
1605 || memcmp (control, &gstring->control,
1606 (char *) (&control->with_cursor)
1607 - (char *) (control))
1608 || control->cursor_width != gstring->control.cursor_width
1609 || control->cursor_bidi != gstring->control.cursor_bidi)
1611 mtext_detach_property (prop);
1616 else if (! control->cursor_width)
1624 offset = mtext_character (mt, pos, 0, '\n');
1629 offset -= gstring->from;
1631 for (gst = gstring; gst; gst = gst->next)
1635 gst->from += offset;
1637 for (i = 0; i < gst->used; i++)
1639 gst->glyphs[i].pos += offset;
1640 gst->glyphs[i].to += offset;
1643 M17N_OBJECT_REF (gstring);
1648 int line = 0, y = 0;
1650 if (pos < mtext_nchars (mt))
1652 beg = mtext_character (mt, pos, 0, '\n');
1660 end = mtext_nchars (mt) + (control->cursor_width != 0);
1661 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1662 if (beg < mtext_nchars (mt))
1663 compose_glyph_string (frame, mt, beg, end, gstring);
1664 layout_glyph_string (frame, gstring);
1666 if (gstring->width_limit
1667 && gstring->width > gstring->width_limit)
1669 MGlyphString *gst = gstring;
1671 truncate_gstring (frame, mt, gst);
1672 while (gst->to < end)
1674 line++, y += gst->height;
1675 gst->next = alloc_gstring (frame, mt, gst->from, control,
1677 gst->next->top = gstring;
1678 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1680 layout_glyph_string (frame, gst);
1681 if (gst->width <= gst->width_limit)
1683 truncate_gstring (frame, mt, gst);
1687 if (! control->disable_caching && pos < mtext_nchars (mt))
1689 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1690 MTEXTPROP_VOLATILE_STRONG);
1692 if (end > mtext_nchars (mt))
1693 end = mtext_nchars (mt);
1694 mtext_attach_property (mt, beg, end, prop);
1695 M17N_OBJECT_UNREF (prop);
1699 while (gstring->to <= pos)
1701 if (! gstring->next)
1703 gstring = gstring->next;
1705 gstring->control = *control;
1711 static MDrawControl control_noop;
1713 #define ASSURE_CONTROL(control) \
1715 control = &control_noop; \
1720 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1721 MText *mt, int from, int to,
1722 MDrawControl *control)
1724 MGlyphString *gstring;
1726 M_CHECK_POS_X (mt, from, -1);
1727 ASSURE_CONTROL (control);
1728 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1729 to = mtext_nchars (mt) + (control->cursor_width != 0);
1733 gstring = get_gstring (frame, mt, from, to, control);
1735 MERROR (MERROR_DRAW, -1);
1736 render_glyph_string (frame, win, x, y, gstring, from, to);
1740 y += gstring->line_descent;
1741 M17N_OBJECT_UNREF (gstring->top);
1742 gstring = get_gstring (frame, mt, from, to, control);
1743 y += gstring->line_ascent;
1744 render_glyph_string (frame, win, x, y, gstring, from, to);
1747 M17N_OBJECT_UNREF (gstring->top);
1754 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1760 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1761 if (g->pos <= pos && g->to > pos)
1766 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1767 if (g->pos <= pos && g->to > pos)
1774 /* for debugging... */
1778 dump_combining_code (int code)
1780 char *vallign = "tcbB";
1781 char *hallign = "lcr";
1787 if (COMBINING_BY_CLASS_P (code))
1788 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1789 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1790 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1791 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1792 off_x = COMBINING_CODE_OFF_X (code) - 128;
1794 sprintf (work + 2, "+%d", off_y);
1796 sprintf (work + 2, "%d", off_y);
1797 else if (off_x == 0)
1798 sprintf (work + 2, ".");
1799 p = work + strlen (work);
1801 sprintf (p, ">%d", off_x);
1803 sprintf (p, "<%d", -off_x);
1805 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1806 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1812 dump_gstring (MGlyphString *gstring, int indent)
1814 char *prefix = (char *) alloca (indent + 1);
1815 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1817 memset (prefix, 32, indent);
1820 fprintf (stderr, "(glyph-string");
1822 for (g = MGLYPH (0); g < last_g; g++)
1824 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1826 g - gstring->glyphs,
1827 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1828 : g->type == GLYPH_ANCHOR ? "ANC"
1829 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1830 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1831 dump_combining_code (g->combining_code),
1832 g->width, g->bidi_level);
1833 fprintf (stderr, ")");
1837 /* m17n-X internal APIs */
1842 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1844 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1845 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1847 Minherited = msymbol ("inherited");
1848 Mcommon = msymbol ("common");
1850 McatCc = msymbol ("Cc");
1851 McatCf = msymbol ("Cf");
1853 MbidiR = msymbol ("R");
1854 MbidiAL = msymbol ("AL");
1855 MbidiRLE = msymbol ("RLE");
1856 MbidiRLO = msymbol ("RLO");
1857 MbidiBN = msymbol ("BN");
1858 MbidiS = msymbol ("S");
1860 fribidi_set_mirroring (TRUE);
1863 M_break_at_space = msymbol ("bs");
1864 M_break_at_word = msymbol ("bw");
1865 M_break_at_any = msymbol ("ba");
1866 M_kinsoku_bol = msymbol ("kb");
1867 M_kinsoku_eol = msymbol ("ke");
1875 MLIST_FREE1 (&scratch_gstring, glyphs);
1876 M17N_OBJECT_UNREF (linebreak_table);
1877 linebreak_table = NULL;
1881 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1885 /*** @addtogroup m17nDraw */
1890 @brief Draw an M-text on a window.
1892 The mdraw_text () function draws the text between $FROM and $TO of
1893 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1895 The appearance of the text (size, style, color, etc) is specified
1896 by the value of the text property whose key is @c Mface. If the
1897 M-text or a part of the M-text does not have such a text property,
1898 the default face of $FRAME is used.
1900 The font used to draw a character in the M-text is selected from
1901 the value of the fontset property of a face by the following
1906 <li> Search the text properties given to the character for the one
1907 whose key is @c Mcharset; its value should be either a symbol
1908 specifying a charset or #Mnil. If the value is #Mnil,
1909 proceed to the next step.
1911 Otherwise, search the mapping table of the fontset for the
1912 charset. If no entry is found proceed to the next step.
1914 If an entry is found, use one of the fonts in the entry that
1915 has a glyph for the character and that matches best with the
1916 face properties. If no such font exists, proceed to the next
1919 <li> Get the character property "script" of the character. If it is
1920 inherited, get the script property from the previous
1921 characters. If there is no previous character, or none of
1922 them has the script property other than inherited, proceed to
1925 Search the text properties given to the character for the one
1926 whose key is @c Mlanguage; its value should be either a
1927 symbol specifying a language or @c Mnil.
1929 Search the mapping table of the fontset for the combination
1930 of the script and language. If no entry is found, proceed to
1933 If an entry is found, use one of the fonts in the entry that
1934 has a glyph for the character and that matches best with the
1935 face properties. If no such font exists, proceed to the next
1938 <li> Search the fall-back table of the fontset for a font that has
1939 a glyph of the character. If such a font is found, use that
1944 If no font is found by the algorithm above, this function draws an
1945 empty box for the character.
1947 This function draws only the glyph foreground. To specify the
1948 background color, use mdraw_image_text () or
1949 mdraw_text_with_control ().
1951 This function is the counterpart of <tt>XDrawString ()</tt>,
1952 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1953 in the X Window System.
1956 If the operation was successful, mdraw_text () returns 0. If an
1957 error is detected, it returns -1 and assigns an error code to the
1958 external variable #merror_code. */
1960 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1962 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1963 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1965 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1966 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1967 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1968 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1970 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1971 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1975 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1976 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1977 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1978 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1979 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1980 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1982 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1983 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1985 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1986 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1987 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1989 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1990 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1992 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1993 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1995 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1996 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1998 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1999 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2003 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2005 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2006 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2008 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2009 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2012 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2013 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2015 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2022 mdraw_image_text () */
2025 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2026 MText *mt, int from, int to)
2028 MDrawControl control;
2030 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2031 memset (&control, 0, sizeof control);
2032 control.as_image = 0;
2033 return draw_text (frame, win, x, y, mt, from, to, &control);
2040 @brief Draw an M-text on a window as an image.
2042 The mdraw_image_text () function draws the text between $FROM and
2043 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2044 coordinate ($X, $Y).
2046 The way to draw a text is the same as in mdraw_text () except that
2047 this function also draws the background with the color specified
2050 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2051 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2052 functions in the X Window System.
2055 If the operation was successful, mdraw_image_text () returns 0.
2056 If an error is detected, it returns -1 and assigns an error code
2057 to the external variable #merror_code. */
2060 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2062 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2063 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2064 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2066 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2067 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2069 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2070 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2074 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2075 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2077 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2087 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2088 MText *mt, int from, int to)
2090 MDrawControl control;
2092 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2093 memset (&control, 0, sizeof control);
2094 control.as_image = 1;
2095 return draw_text (frame, win, x, y, mt, from, to, &control);
2101 @brief Draw an M-text on a window with fine control.
2103 The mdraw_text_with_control () function draws the text between
2104 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2105 coordinate ($X, $Y).
2107 The way to draw a text is the same as in mdraw_text () except that
2108 this function also follows what specified in the drawing control
2111 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2112 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2113 breaks lines and the following characters are drawn in the next
2114 line. See the documentation of the structure @ MDrawControl for
2118 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2120 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2121 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2124 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2125 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2127 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2128 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2129 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2132 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2133 MText *mt, int from, int to, MDrawControl *control)
2135 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2136 return draw_text (frame, win, x, y, mt, from, to, control);
2142 @brief Compute text pixel width.
2144 The mdraw_text_extents () function computes the width of text
2145 between $FROM and $TO of M-text $MT when it is drawn on a window
2146 of frame $FRAME using the mdraw_text_with_control () function with
2147 the drawing control object $CONTROL.
2149 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2150 the bounding box of character ink of the M-text, and stores the
2151 results in the members of the structure pointed to by
2152 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2153 surrounding box, the box is included in the bounding box.
2155 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2156 computes the bounding box that provides minimum spacing to other
2157 graphical features (such as surrounding box) for the M-text, and
2158 stores the results in the members of the structure pointed to by
2159 $OVERALL_LOGICAL_RETURN.
2161 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2162 computes the bounding box that provides minimum spacing to the
2163 other M-text drawn, and stores the results in the members of the
2164 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2165 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2166 min_line_ascent, min_line_descent, max_line_ascent, and
2167 max_line_descent of $CONTROL are all zero.
2170 This function returns the width of the text to be drawn in the
2171 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2172 text is drawn in multiple physical lines, it returns the width of
2173 the widest line. If an error occurs, it returns -1 and assigns an
2174 error code to the external variable #merror_code. */
2178 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2180 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2181 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2182 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2184 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2185 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2186 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2187 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2189 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2190 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2191 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2192 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2194 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2195 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2196 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2197 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2198 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2199 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2202 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2203 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2204 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2206 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2213 mdraw_text_extents (MFrame *frame,
2214 MText *mt, int from, int to, MDrawControl *control,
2215 MDrawMetric *overall_ink_return,
2216 MDrawMetric *overall_logical_return,
2217 MDrawMetric *overall_line_return)
2219 MGlyphString *gstring;
2221 int width, rbearing;
2223 ASSURE_CONTROL (control);
2224 M_CHECK_POS_X (mt, from, -1);
2225 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2226 to = mtext_nchars (mt) + (control->cursor_width != 0);
2230 gstring = get_gstring (frame, mt, from, to, control);
2232 MERROR (MERROR_DRAW, -1);
2233 width = gstring_width (gstring, from, to, &rbearing);
2234 if (overall_ink_return)
2236 overall_ink_return->y = - gstring->physical_ascent;
2237 overall_ink_return->x = gstring->lbearing;
2239 if (overall_logical_return)
2241 overall_logical_return->y = - gstring->ascent;
2242 overall_logical_return->x = 0;
2244 if (overall_line_return)
2246 overall_line_return->y = - gstring->line_ascent;
2247 overall_line_return->x = gstring->lbearing;
2250 for (from = gstring->to; from < to; from = gstring->to)
2252 int this_width, this_rbearing;
2254 y += gstring->line_descent;
2255 M17N_OBJECT_UNREF (gstring->top);
2256 gstring = get_gstring (frame, mt, from, to, control);
2257 this_width = gstring_width (gstring, from, to, &this_rbearing);
2258 y += gstring->line_ascent;
2259 if (width < this_width)
2261 if (rbearing < this_rbearing)
2262 rbearing = this_rbearing;
2264 if (overall_ink_return)
2266 overall_ink_return->width = rbearing;
2267 overall_ink_return->height
2268 = y + gstring->physical_descent - overall_ink_return->y;
2270 if (overall_logical_return)
2272 overall_logical_return->width = width;
2273 overall_logical_return->height
2274 = y + gstring->descent - overall_logical_return->y;
2276 if (overall_line_return)
2278 overall_line_return->width = MAX (width, rbearing);
2279 overall_line_return->height
2280 = y + gstring->line_descent - overall_line_return->y;
2283 M17N_OBJECT_UNREF (gstring->top);
2290 @brief Compute the text dimensions of each character of M-text.
2292 The mdraw_text_per_char_extents () function computes the drawn
2293 metric of each character between $FROM and $TO of M-text $MT
2294 assuming that they are drawn on a window of frame $FRAME using the
2295 mdraw_text_with_control () function with the drawing control
2298 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2299 $LOGICAL_ARRAY_RETURN. Each successive element of
2300 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2301 ink and logical metrics of successive characters respectively,
2302 relative to the drawing origin of the M-text. The number of
2303 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2304 been set is returned to $NUM_CHARS_RETURN.
2306 If $ARRAY_SIZE is too small to return all metrics, the function
2307 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2308 Otherwise, it returns zero.
2310 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2311 @c NULL, this function also computes the metrics of the overall
2312 text and stores the results in the members of the structure
2313 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2315 If $CONTROL->two_dimensional is nonzero, this function computes
2316 only the metrics of characters in the first line. */
2318 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2320 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2321 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2322 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2324 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2325 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2326 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2327 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2328 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2330 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2331 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2334 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2335 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2336 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2338 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2341 mdraw_text_per_char_extents (MFrame *frame,
2342 MText *mt, int from, int to,
2343 MDrawControl *control,
2344 MDrawMetric *ink_array_return,
2345 MDrawMetric *logical_array_return,
2347 int *num_chars_return,
2348 MDrawMetric *overall_ink_return,
2349 MDrawMetric *overall_logical_return)
2351 MGlyphString *gstring;
2355 ASSURE_CONTROL (control);
2356 *num_chars_return = to - from;
2357 if (array_size < *num_chars_return)
2358 MERROR (MERROR_DRAW, -1);
2359 if (overall_logical_return)
2360 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2361 if (overall_ink_return)
2362 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2364 M_CHECK_RANGE (mt, from, to, -1, 0);
2365 gstring = get_gstring (frame, mt, from, to, control);
2368 *num_chars_return = 0;
2372 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2373 if (g->pos >= from && g->pos < to)
2377 int width = g->width;
2378 int lbearing = g->lbearing;
2379 int rbearing = g->rbearing;
2380 int ascent = g->ascent;
2381 int descent = g->descent;
2383 int logical_descent;
2385 if (g->rface->rfont)
2387 logical_ascent = g->rface->rfont->ascent;
2388 logical_descent = g->rface->rfont->descent;
2392 logical_ascent = g->rface->ascent;
2393 logical_descent = g->rface->descent;
2395 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2397 if (lbearing < width + g->lbearing)
2398 lbearing = width + g->lbearing;
2399 if (rbearing < width + g->rbearing)
2400 rbearing = width + g->rbearing;
2402 if (ascent < g->ascent)
2404 if (descent < g->descent)
2405 descent = g->descent;
2412 if (ink_array_return)
2414 ink_array_return[start - from].x = x + lbearing;
2415 ink_array_return[start - from].y = - ascent;
2416 ink_array_return[start - from].width = rbearing - lbearing;
2417 ink_array_return[start - from].height = ascent + descent;
2419 if (logical_array_return)
2421 logical_array_return[start - from].x = x;
2422 logical_array_return[start - from].y = - logical_descent;
2423 logical_array_return[start - from].height
2424 = logical_ascent + logical_descent;
2425 logical_array_return[start - from].width = width;
2433 if (overall_ink_return)
2435 overall_ink_return->y = - gstring->line_ascent;
2436 overall_ink_return->x = gstring->lbearing;
2437 overall_ink_return->width = x - gstring->lbearing;
2438 overall_ink_return->height = gstring->height;
2440 if (overall_logical_return)
2442 overall_logical_return->y = - gstring->ascent;
2443 overall_logical_return->x = 0;
2444 overall_logical_return->width = x;
2445 overall_logical_return->height = gstring->ascent + gstring->descent;
2448 M17N_OBJECT_UNREF (gstring->top);
2455 @brief Return the character position nearest to the coordinates.
2457 The mdraw_coordinates_position () function checks which character
2458 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2459 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2460 mdraw_text_with_control () function with the drawing control
2461 object $CONTROL. Here, the character position means the number of
2462 characters that precede the character in question in $MT, that is,
2463 the character position of the first character is 0.
2465 $FRAME is used only to get the default face information.
2468 If the glyph image of a character covers coordinate ($X, $Y),
2469 mdraw_coordinates_position () returns the character position of
2471 If $Y is less than the minimum Y-coordinate of the drawn area, it
2473 If $Y is greater than the maximum Y-coordinate of the drawn area,
2475 If $Y fits in with the drawn area but $X is less than the minimum
2476 X-coordinate, it returns the character position of the first
2477 character drawn on the line $Y.\n\n
2478 If $Y fits in with the drawn area but $X is greater than the
2479 maximum X-coordinate, it returns the character position of the
2480 last character drawn on the line $Y. */
2483 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2485 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2486 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2487 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2488 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2489 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2490 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2492 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2495 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2496 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2497 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2498 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2499 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2500 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2501 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2502 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2505 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2506 int x_offset, int y_offset, MDrawControl *control)
2508 MGlyphString *gstring;
2513 M_CHECK_POS_X (mt, from, -1);
2514 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2515 to = mtext_nchars (mt) + (control->cursor_width != 0);
2521 ASSURE_CONTROL (control);
2522 gstring = get_gstring (frame, mt, from, to, control);
2523 while (y + gstring->line_descent <= y_offset
2524 && gstring->to < to)
2527 y += gstring->line_descent;
2528 M17N_OBJECT_UNREF (gstring->top);
2529 gstring = get_gstring (frame, mt, from, to, control);
2530 y += gstring->line_ascent;
2533 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2534 if (! control->orientation_reversed)
2536 width = gstring->indent;
2537 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2538 if (g->pos >= from && g->pos < to)
2541 if (width > x_offset)
2547 width = - gstring->indent;
2548 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2549 if (g->pos >= from && g->pos < to)
2552 if (width < x_offset)
2556 if (g->type == GLYPH_ANCHOR
2557 && control->two_dimensional
2561 M17N_OBJECT_UNREF (gstring->top);
2569 @brief Compute information about a glyph.
2571 The mdraw_glyph_info () function computes information about a
2572 glyph that covers a character at position $POS of the M-text $MT
2573 assuming that the text is drawn from the character at $FROM of $MT
2574 on a window of frame $FRAME using the mdraw_text_with_control ()
2575 function with the drawing control object $CONTROL.
2577 The information is stored in the members of $INFO. */
2579 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2581 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2582 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2583 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2584 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2586 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2594 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2595 MDrawControl *control, MDrawGlyphInfo *info)
2597 MGlyphString *gstring;
2601 M_CHECK_RANGE_X (mt, from, pos, -1);
2603 ASSURE_CONTROL (control);
2604 gstring = get_gstring (frame, mt, from, pos + 1, control);
2606 MERROR (MERROR_DRAW, -1);
2607 while (gstring->to <= pos)
2609 y += gstring->line_descent;
2610 M17N_OBJECT_UNREF (gstring->top);
2611 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2612 y += gstring->line_ascent;
2614 info->line_from = gstring->from;
2615 if (info->line_from < from)
2616 info->line_from = from;
2617 info->line_to = gstring->to;
2620 if (! control->orientation_reversed)
2622 info->x = gstring->indent;
2623 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2624 info->x += g->width;
2628 info->x = - gstring->indent;
2629 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2630 info->x -= g->width;
2631 while (g[-1].to == g->to)
2634 info->from = g->pos;
2636 info->metrics.x = g->lbearing;
2637 info->metrics.y = - gstring->line_ascent;
2638 info->metrics.height = gstring->height;
2639 info->metrics.width = - g->lbearing + g->width;
2640 if (g->rface->rfont)
2641 info->font = (MFont *) g->rface->rfont;
2644 /* info->logical_width is calculated later. */
2646 if (info->from > info->line_from)
2648 /* The logically previous glyph is on this line. */
2649 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2651 info->prev_from = g_tmp->pos;
2653 else if (info->line_from > 0
2654 && gstring->from > 0)
2656 /* The logically previous glyph is on the previous line. */
2657 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2658 gstring->from, control);
2659 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2661 info->prev_from = g_tmp->pos;
2662 M17N_OBJECT_UNREF (gst->top);
2665 info->prev_from = -1;
2667 if (GLYPH_INDEX (g) > 1)
2668 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2669 else if (! control->orientation_reversed)
2671 if (info->line_from > 0)
2675 int p = gstring->from - 1;
2677 gst = get_gstring (frame, mt, p, gstring->from, control);
2678 g_tmp = gst->glyphs + (gst->used - 2);
2679 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2680 M17N_OBJECT_UNREF (gst->top);
2683 info->left_from = info->left_to = -1;
2687 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2691 int p = gstring->to;
2693 gst = get_gstring (frame, mt, p, p + 1, control);
2694 g_tmp = gst->glyphs + (gst->used - 2);
2695 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2696 M17N_OBJECT_UNREF (gst->top);
2699 info->left_from = info->left_to = -1;
2702 if (info->to < gstring->to)
2704 /* The logically next glyph is on this line. */
2705 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2707 info->next_to = g_tmp->to;
2709 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2711 /* The logically next glyph is on the next line. */
2713 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2714 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2716 info->next_to = g_tmp->to;
2717 M17N_OBJECT_UNREF (gst->top);
2722 for (info->logical_width = (g++)->width;
2723 g->pos == pos && g->type != GLYPH_ANCHOR;
2724 info->metrics.width += g->width, info->logical_width += (g++)->width);
2725 info->metrics.width += g[-1].rbearing - g[-1].width;
2727 if (g->type != GLYPH_ANCHOR)
2728 info->right_from = g->pos, info->right_to = g->to;
2729 else if (! control->orientation_reversed)
2731 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2734 M17N_OBJECT_UNREF (gstring->top);
2735 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2737 info->right_from = g->pos, info->right_to = g->to;
2740 info->right_from = info->right_to = -1;
2744 if (info->line_from > 0)
2746 pos = gstring->from - 1;
2747 M17N_OBJECT_UNREF (gstring->top);
2748 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2750 info->right_from = g->pos, info->right_to = g->to;
2753 info->right_from = info->right_to = -1;
2756 M17N_OBJECT_UNREF (gstring->top);
2763 @brief Compute information about glyph sequence.
2765 The mdraw_glyph_list () function computes information about glyphs
2766 corresponding to the text between $FROM and $TO of M-text $MT when
2767 it is drawn on a window of frame $FRAME using the
2768 mdraw_text_with_control () function with the drawing control
2769 object $CONTROL. $GLYPHS is an array of objects to store the
2770 information, and $ARRAY_SIZE is the array size.
2772 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2773 number of actually filled elements in the place pointed by
2774 $NUM_GLYPHS_RETURN, and returns 0.
2776 Otherwise, it stores the required array size in the place pointed
2777 by $NUM_GLYPHS_RETURN, and returns -1. */
2780 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2782 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2783 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2784 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2785 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2787 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2788 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2791 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2801 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2802 MDrawControl *control, MDrawGlyph *glyphs,
2803 int array_size, int *num_glyphs_return)
2805 MGlyphString *gstring;
2810 ASSURE_CONTROL (control);
2811 *num_glyphs_return = 0;
2812 M_CHECK_RANGE (mt, from, to, -1, 0);
2813 gstring = get_gstring (frame, mt, from, to, control);
2816 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2818 if (g->type == GLYPH_BOX
2819 || g->pos < from || g->pos >= to)
2821 if (g->type == GLYPH_PAD)
2823 if (g->left_padding)
2824 pad_width = g->width;
2828 glyphs[-1].x_advance += g->width;
2834 glyphs->from = g->pos;
2836 glyphs->glyph_code = g->code;
2837 glyphs->x_off = g->xoff + pad_width;
2838 glyphs->y_off = g->yoff;
2839 glyphs->lbearing = g->lbearing;
2840 glyphs->rbearing = g->rbearing;
2841 glyphs->ascent = g->ascent;
2842 glyphs->descent = g->descent;
2843 glyphs->x_advance = g->width + pad_width;
2844 glyphs->y_advance = 0;
2845 if (g->rface->rfont)
2847 glyphs->font = (MFont *) g->rface->rfont;
2849 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2850 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2852 glyphs->fontp = g->rface->rfont->fontp;
2856 glyphs->font = NULL;
2857 glyphs->font_type = Mnil;
2858 glyphs->fontp = NULL;
2865 M17N_OBJECT_UNREF (gstring->top);
2867 *num_glyphs_return = n;
2868 return (n <= array_size ? 0 : -1);
2874 @brief Draw one or more textitems.
2876 The mdraw_text_items () function draws one or more M-texts on
2877 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2878 of the textitems to be drawn and $NITEMS is the number of
2879 textitems in the array. */
2882 @brief textitem ¤òɽ¼¨¤¹¤ë.
2884 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2885 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2886 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2888 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2892 MTextItem, mdraw_text (). */
2895 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2896 MDrawTextItem *items, int nitems)
2898 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2900 while (nitems-- > 0)
2903 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2905 mdraw_text_with_control (frame, win, x, y,
2906 items->mt, 0, mtext_nchars (items->mt),
2908 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2909 items->control, NULL, NULL, NULL);
2912 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2918 @brief Option of line breaking for drawing text.
2920 The variable #mdraw_line_break_option specifies line breaking
2921 options by logical-or of the members of #MTextLineBreakOption. It
2922 controls the line breaking algorithm of the function
2923 mdraw_default_line_break (). */
2925 int mdraw_line_break_option;
2929 @brief Calculate a line breaking position.
2931 The function mdraw_default_line_break () calculates a line
2932 breaking position based on the line number $LINE and the
2933 coordinate $Y, when a line is too long to fit within the width
2934 limit. $POS is the position of the character next to the last one
2935 that fits within the limit. $FROM is the position of the first
2936 character of the line, and $TO is the position of the last
2937 character displayed on the line if there were not width limit.
2938 $LINE and $Y are reset to 0 when a line is broken by a newline
2939 character, and incremented each time when a long line is broken
2940 because of the width limit.
2942 @return This function returns a character position to break the
2947 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2949 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2950 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2951 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2952 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2953 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2954 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2955 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2958 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2962 mdraw_default_line_break (MText *mt, int pos,
2963 int from, int to, int line, int y)
2967 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2978 @brief Obtain per character dimension information.
2980 The mdraw_per_char_extents () function computes the text dimension
2981 of each character in M-text $MT. The faces given as text
2982 properties in $MT and the default face of frame $FRAME determine
2983 the fonts to draw the text. Each successive element in
2984 $ARRAY_RETURN is set to the drawn metrics of successive
2985 characters, which is relative to the origin of the drawing, and a
2986 rectangle for each character in $MT. The number of elements of
2987 $ARRAY_RETURN must be equal to or greater than the number of
2990 If pointer $OVERALL_RETURN is not @c NULL, this function also
2991 computes the extents of the overall text and stores the results in
2992 the members of the structure pointed to by $OVERALL_RETURN. */
2995 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2997 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2998 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2999 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3000 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3001 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3002 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3003 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3005 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3006 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3007 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3009 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3012 mdraw_per_char_extents (MFrame *frame, MText *mt,
3013 MDrawMetric *array_return,
3014 MDrawMetric *overall_return)
3016 int n = mtext_nchars (mt);
3018 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3019 n, &n, overall_return, NULL);
3023 @brief clear cached information.
3025 The mdraw_clear_cache () function clear cached information
3026 on M-text $MT that was attached by any of the drawing functions.
3027 When the behavior of `format' or `line_break'
3028 member functions of MDrawControl is changed, the cache must be cleared.
3033 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3035 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3036 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3037 ¤¢¤ë¤¤¤Ï `line_break'
3038 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3044 mdraw_clear_cache (MText *mt)
3046 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);