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->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1273 MRealizedFace *rface = g->rface;
1274 int width = g->width;
1275 MGlyph *from_g = g++;
1277 /* Handle the glyphs of the same type/face at once. */
1279 && g->type == from_g->type
1280 && g->rface == rface
1281 && ((g->code == MCHAR_INVALID_CODE)
1282 == (from_g->code == MCHAR_INVALID_CODE))
1284 width += g++->width;
1286 if (from_g->type == GLYPH_CHAR)
1288 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1289 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1292 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1295 else if (from_g->type == GLYPH_BOX)
1297 /* Draw the left or right side of a box. If
1298 from_g->lbearing is nonzero, this is the left side,
1299 else this is the right side. */
1300 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1303 if (from_g->type != GLYPH_BOX)
1306 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1307 x, y, width, region);
1310 /* Draw the top and bottom side of a box. */
1311 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1312 x, y, width, region);
1323 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1324 int *from_x, int *to_x)
1327 int left_idx = *left, right_idx = *right;
1328 int left_x, right_x, x;
1330 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1333 if (x + g->rbearing > 0)
1335 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1337 left_idx = GLYPH_INDEX (g);
1342 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1345 if (x - g->width + g->lbearing < 0)
1347 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1349 right_idx = GLYPH_INDEX (g) + 1;
1354 if (*left == left_idx && *right == right_idx)
1357 if (*left != left_idx)
1359 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1364 if (*right != right_idx)
1366 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1376 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1381 if (from <= gstring->from && to >= gstring->to)
1384 *rbearing = gstring->rbearing;
1385 return gstring->width;
1390 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1391 if (g->pos >= from && g->pos < to)
1393 if (rbearing && width + g->rbearing > *rbearing)
1394 *rbearing = width + g->rbearing;
1402 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1403 MGlyphString *gstring, int from, int to)
1405 MDrawControl *control = &gstring->control;
1407 MDrawRegion clip_region, cursor_region;
1408 int from_idx, to_idx;
1411 if (control->orientation_reversed)
1412 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1414 x += gstring->indent;
1416 /* At first, draw all glyphs without cursor. */
1417 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1418 &from_idx, &to_idx, &to_x);
1420 if (control->partial_update)
1423 rect.width = to_x - x;
1424 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1426 rect.y = y - gstring->line_ascent;
1427 rect.height = gstring->height;
1428 clip_region = (*frame->driver->region_from_rect) (&rect);
1429 if (control->clip_region)
1430 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1433 clip_region = control->clip_region;
1436 clip_region = control->clip_region;
1438 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1443 (*frame->driver->intersect_region) (cursor_region, clip_region);
1444 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1447 if (clip_region != control->clip_region)
1448 (*frame->driver->free_region) (clip_region);
1450 (*frame->driver->free_region) (cursor_region);
1454 static int gstring_num;
1457 free_gstring (void *object)
1459 MGlyphString *gstring = (MGlyphString *) object;
1462 free_gstring (gstring->next);
1463 if (gstring->size > 0)
1464 free (gstring->glyphs);
1470 static MGlyphString scratch_gstring;
1472 static MGlyphString *
1473 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1476 MGlyphString *gstring;
1478 if (pos == mt->nchars)
1482 gstring = &scratch_gstring;
1483 if (gstring->size == 0)
1488 g_tmp.type = GLYPH_ANCHOR;
1489 APPEND_GLYPH (gstring, g_tmp);
1490 APPEND_GLYPH (gstring, g_tmp);
1491 APPEND_GLYPH (gstring, g_tmp);
1492 gstring->glyphs[1].type = GLYPH_SPACE;
1493 gstring->glyphs[1].c = '\n';
1494 gstring->glyphs[1].code = '\n';
1496 gstring->from = pos;
1498 g->rface = frame->rface;
1499 g->pos = g->to = pos;
1501 g->rface = frame->rface;
1502 g->pos = pos++, g->to = pos;
1504 g->rface = frame->rface;
1505 g->pos = g->to = pos;
1510 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1511 MLIST_INIT1 (gstring, glyphs, 128);
1515 gstring->frame = frame;
1516 gstring->tick = frame->tick;
1517 gstring->top = gstring;
1518 gstring->control = *control;
1519 gstring->indent = gstring->width_limit = 0;
1520 if (control->format)
1521 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1523 gstring->width_limit = control->max_line_width;
1524 gstring->anti_alias = control->anti_alias;
1528 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1531 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1534 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1542 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1543 a width of glyphs for the character at I of MT. If I is not a
1544 beginning of a grapheme cluster, the corresponding element is
1546 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1547 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1548 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1549 pos_width[g->pos - gstring->from] += g->width;
1550 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1552 if (pos_width[i] > 0)
1554 if (width + pos_width[i] > gstring->width_limit)
1557 width += pos_width[i];
1560 pos = gstring->from + i;
1561 if (gstring->control.line_break)
1563 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1564 gstring->from, gstring->from + i,
1566 if (pos <= gstring->from)
1568 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1571 else if (pos >= gstring->to)
1576 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1577 layout_glyph_string (frame, gstring);
1581 /* Return a gstring that covers a character at POS. */
1583 static MGlyphString *
1584 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1586 MGlyphString *gstring = NULL;
1588 if (pos < mtext_nchars (mt))
1590 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1593 && ((prop->start != 0
1594 && mtext_ref_char (mt, prop->start - 1) != '\n')
1595 || (prop->end < mtext_nchars (mt)
1596 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1598 mtext_detach_property (prop);
1603 gstring = prop->val;
1604 if (gstring->frame != frame
1605 || gstring->tick != frame->tick
1606 || memcmp (control, &gstring->control,
1607 (char *) (&control->with_cursor)
1608 - (char *) (control))
1609 || control->cursor_width != gstring->control.cursor_width
1610 || control->cursor_bidi != gstring->control.cursor_bidi)
1612 mtext_detach_property (prop);
1617 else if (! control->cursor_width)
1625 offset = mtext_character (mt, pos, 0, '\n');
1630 offset -= gstring->from;
1632 for (gst = gstring; gst; gst = gst->next)
1636 gst->from += offset;
1638 for (i = 0; i < gst->used; i++)
1640 gst->glyphs[i].pos += offset;
1641 gst->glyphs[i].to += offset;
1644 M17N_OBJECT_REF (gstring);
1649 int line = 0, y = 0;
1651 if (pos < mtext_nchars (mt))
1653 beg = mtext_character (mt, pos, 0, '\n');
1661 end = mtext_nchars (mt) + (control->cursor_width != 0);
1662 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1663 if (beg < mtext_nchars (mt))
1664 compose_glyph_string (frame, mt, beg, end, gstring);
1665 layout_glyph_string (frame, gstring);
1667 if (gstring->width_limit
1668 && gstring->width > gstring->width_limit)
1670 MGlyphString *gst = gstring;
1672 truncate_gstring (frame, mt, gst);
1673 while (gst->to < end)
1675 line++, y += gst->height;
1676 gst->next = alloc_gstring (frame, mt, gst->from, control,
1678 gst->next->top = gstring;
1679 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1681 layout_glyph_string (frame, gst);
1682 if (gst->width <= gst->width_limit)
1684 truncate_gstring (frame, mt, gst);
1688 if (! control->disable_caching && pos < mtext_nchars (mt))
1690 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1691 MTEXTPROP_VOLATILE_STRONG);
1693 if (end > mtext_nchars (mt))
1694 end = mtext_nchars (mt);
1695 mtext_attach_property (mt, beg, end, prop);
1696 M17N_OBJECT_UNREF (prop);
1700 while (gstring->to <= pos)
1702 if (! gstring->next)
1704 gstring = gstring->next;
1706 gstring->control = *control;
1712 static MDrawControl control_noop;
1714 #define ASSURE_CONTROL(control) \
1716 control = &control_noop; \
1721 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1722 MText *mt, int from, int to,
1723 MDrawControl *control)
1725 MGlyphString *gstring;
1727 M_CHECK_POS_X (mt, from, -1);
1728 ASSURE_CONTROL (control);
1729 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1730 to = mtext_nchars (mt) + (control->cursor_width != 0);
1734 gstring = get_gstring (frame, mt, from, to, control);
1736 MERROR (MERROR_DRAW, -1);
1737 render_glyph_string (frame, win, x, y, gstring, from, to);
1741 y += gstring->line_descent;
1742 M17N_OBJECT_UNREF (gstring->top);
1743 gstring = get_gstring (frame, mt, from, to, control);
1744 y += gstring->line_ascent;
1745 render_glyph_string (frame, win, x, y, gstring, from, to);
1748 M17N_OBJECT_UNREF (gstring->top);
1755 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1761 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1762 if (g->pos <= pos && g->to > pos)
1767 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1768 if (g->pos <= pos && g->to > pos)
1775 /* for debugging... */
1779 dump_combining_code (int code)
1781 char *vallign = "tcbB";
1782 char *hallign = "lcr";
1788 if (COMBINING_BY_CLASS_P (code))
1789 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1790 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1791 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1792 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1793 off_x = COMBINING_CODE_OFF_X (code) - 128;
1795 sprintf (work + 2, "+%d", off_y);
1797 sprintf (work + 2, "%d", off_y);
1798 else if (off_x == 0)
1799 sprintf (work + 2, ".");
1800 p = work + strlen (work);
1802 sprintf (p, ">%d", off_x);
1804 sprintf (p, "<%d", -off_x);
1806 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1807 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1813 dump_gstring (MGlyphString *gstring, int indent)
1815 char *prefix = (char *) alloca (indent + 1);
1816 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1818 memset (prefix, 32, indent);
1821 fprintf (stderr, "(glyph-string");
1823 for (g = MGLYPH (0); g < last_g; g++)
1825 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1827 g - gstring->glyphs,
1828 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1829 : g->type == GLYPH_ANCHOR ? "ANC"
1830 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1831 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1832 dump_combining_code (g->combining_code),
1833 g->width, g->bidi_level);
1834 fprintf (stderr, ")");
1838 /* m17n-X internal APIs */
1843 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1845 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1846 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1848 Minherited = msymbol ("inherited");
1849 Mcommon = msymbol ("common");
1851 McatCc = msymbol ("Cc");
1852 McatCf = msymbol ("Cf");
1854 MbidiR = msymbol ("R");
1855 MbidiAL = msymbol ("AL");
1856 MbidiRLE = msymbol ("RLE");
1857 MbidiRLO = msymbol ("RLO");
1858 MbidiBN = msymbol ("BN");
1859 MbidiS = msymbol ("S");
1861 fribidi_set_mirroring (TRUE);
1864 M_break_at_space = msymbol ("bs");
1865 M_break_at_word = msymbol ("bw");
1866 M_break_at_any = msymbol ("ba");
1867 M_kinsoku_bol = msymbol ("kb");
1868 M_kinsoku_eol = msymbol ("ke");
1876 MLIST_FREE1 (&scratch_gstring, glyphs);
1877 M17N_OBJECT_UNREF (linebreak_table);
1878 linebreak_table = NULL;
1882 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1886 /*** @addtogroup m17nDraw */
1891 @brief Draw an M-text on a window.
1893 The mdraw_text () function draws the text between $FROM and $TO of
1894 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1896 The appearance of the text (size, style, color, etc) is specified
1897 by the value of the text property whose key is @c Mface. If the
1898 M-text or a part of the M-text does not have such a text property,
1899 the default face of $FRAME is used.
1901 The font used to draw a character in the M-text is selected from
1902 the value of the fontset property of a face by the following
1907 <li> Search the text properties given to the character for the one
1908 whose key is @c Mcharset; its value should be either a symbol
1909 specifying a charset or #Mnil. If the value is #Mnil,
1910 proceed to the next step.
1912 Otherwise, search the mapping table of the fontset for the
1913 charset. If no entry is found proceed to the next step.
1915 If an entry is found, use one of the fonts in the entry that
1916 has a glyph for the character and that matches best with the
1917 face properties. If no such font exists, proceed to the next
1920 <li> Get the character property "script" of the character. If it is
1921 inherited, get the script property from the previous
1922 characters. If there is no previous character, or none of
1923 them has the script property other than inherited, proceed to
1926 Search the text properties given to the character for the one
1927 whose key is @c Mlanguage; its value should be either a
1928 symbol specifying a language or @c Mnil.
1930 Search the mapping table of the fontset for the combination
1931 of the script and language. If no entry is found, proceed to
1934 If an entry is found, use one of the fonts in the entry that
1935 has a glyph for the character and that matches best with the
1936 face properties. If no such font exists, proceed to the next
1939 <li> Search the fall-back table of the fontset for a font that has
1940 a glyph of the character. If such a font is found, use that
1945 If no font is found by the algorithm above, this function draws an
1946 empty box for the character.
1948 This function draws only the glyph foreground. To specify the
1949 background color, use mdraw_image_text () or
1950 mdraw_text_with_control ().
1952 This function is the counterpart of <tt>XDrawString ()</tt>,
1953 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1954 in the X Window System.
1957 If the operation was successful, mdraw_text () returns 0. If an
1958 error is detected, it returns -1 and assigns an error code to the
1959 external variable #merror_code. */
1961 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1963 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1964 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1966 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1967 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1968 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1969 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1971 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1972 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1976 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1977 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1978 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1979 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1980 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1981 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1983 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1984 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1986 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1987 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1988 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1990 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1991 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1993 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1994 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1996 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1997 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1999 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2000 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2004 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2006 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2007 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2009 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2010 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2013 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2014 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2016 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2023 mdraw_image_text () */
2026 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2027 MText *mt, int from, int to)
2029 MDrawControl control;
2031 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2032 memset (&control, 0, sizeof control);
2033 control.as_image = 0;
2034 return draw_text (frame, win, x, y, mt, from, to, &control);
2041 @brief Draw an M-text on a window as an image.
2043 The mdraw_image_text () function draws the text between $FROM and
2044 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2045 coordinate ($X, $Y).
2047 The way to draw a text is the same as in mdraw_text () except that
2048 this function also draws the background with the color specified
2051 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2052 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2053 functions in the X Window System.
2056 If the operation was successful, mdraw_image_text () returns 0.
2057 If an error is detected, it returns -1 and assigns an error code
2058 to the external variable #merror_code. */
2061 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2063 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2064 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2065 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2067 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2068 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2070 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2071 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2075 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2076 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2078 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2088 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2089 MText *mt, int from, int to)
2091 MDrawControl control;
2093 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2094 memset (&control, 0, sizeof control);
2095 control.as_image = 1;
2096 return draw_text (frame, win, x, y, mt, from, to, &control);
2102 @brief Draw an M-text on a window with fine control.
2104 The mdraw_text_with_control () function draws the text between
2105 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2106 coordinate ($X, $Y).
2108 The way to draw a text is the same as in mdraw_text () except that
2109 this function also follows what specified in the drawing control
2112 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2113 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2114 breaks lines and the following characters are drawn in the next
2115 line. See the documentation of the structure @ MDrawControl for
2119 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2121 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2122 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2125 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2126 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2128 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2129 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2130 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2133 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2134 MText *mt, int from, int to, MDrawControl *control)
2136 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2137 return draw_text (frame, win, x, y, mt, from, to, control);
2143 @brief Compute text pixel width.
2145 The mdraw_text_extents () function computes the width of text
2146 between $FROM and $TO of M-text $MT when it is drawn on a window
2147 of frame $FRAME using the mdraw_text_with_control () function with
2148 the drawing control object $CONTROL.
2150 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2151 the bounding box of character ink of the M-text, and stores the
2152 results in the members of the structure pointed to by
2153 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2154 surrounding box, the box is included in the bounding box.
2156 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2157 computes the bounding box that provides minimum spacing to other
2158 graphical features (such as surrounding box) for the M-text, and
2159 stores the results in the members of the structure pointed to by
2160 $OVERALL_LOGICAL_RETURN.
2162 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2163 computes the bounding box that provides minimum spacing to the
2164 other M-text drawn, and stores the results in the members of the
2165 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2166 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2167 min_line_ascent, min_line_descent, max_line_ascent, and
2168 max_line_descent of $CONTROL are all zero.
2171 This function returns the width of the text to be drawn in the
2172 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2173 text is drawn in multiple physical lines, it returns the width of
2174 the widest line. If an error occurs, it returns -1 and assigns an
2175 error code to the external variable #merror_code. */
2179 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2181 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2182 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2183 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2185 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2186 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2187 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2188 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2190 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2191 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2192 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2193 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2195 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2196 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2197 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2198 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2199 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2200 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2203 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2204 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2205 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2207 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2214 mdraw_text_extents (MFrame *frame,
2215 MText *mt, int from, int to, MDrawControl *control,
2216 MDrawMetric *overall_ink_return,
2217 MDrawMetric *overall_logical_return,
2218 MDrawMetric *overall_line_return)
2220 MGlyphString *gstring;
2222 int width, rbearing;
2224 ASSURE_CONTROL (control);
2225 M_CHECK_POS_X (mt, from, -1);
2226 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2227 to = mtext_nchars (mt) + (control->cursor_width != 0);
2231 gstring = get_gstring (frame, mt, from, to, control);
2233 MERROR (MERROR_DRAW, -1);
2234 width = gstring_width (gstring, from, to, &rbearing);
2235 if (overall_ink_return)
2237 overall_ink_return->y = - gstring->physical_ascent;
2238 overall_ink_return->x = gstring->lbearing;
2240 if (overall_logical_return)
2242 overall_logical_return->y = - gstring->ascent;
2243 overall_logical_return->x = 0;
2245 if (overall_line_return)
2247 overall_line_return->y = - gstring->line_ascent;
2248 overall_line_return->x = gstring->lbearing;
2251 for (from = gstring->to; from < to; from = gstring->to)
2253 int this_width, this_rbearing;
2255 y += gstring->line_descent;
2256 M17N_OBJECT_UNREF (gstring->top);
2257 gstring = get_gstring (frame, mt, from, to, control);
2258 this_width = gstring_width (gstring, from, to, &this_rbearing);
2259 y += gstring->line_ascent;
2260 if (width < this_width)
2262 if (rbearing < this_rbearing)
2263 rbearing = this_rbearing;
2265 if (overall_ink_return)
2267 overall_ink_return->width = rbearing;
2268 overall_ink_return->height
2269 = y + gstring->physical_descent - overall_ink_return->y;
2271 if (overall_logical_return)
2273 overall_logical_return->width = width;
2274 overall_logical_return->height
2275 = y + gstring->descent - overall_logical_return->y;
2277 if (overall_line_return)
2279 overall_line_return->width = MAX (width, rbearing);
2280 overall_line_return->height
2281 = y + gstring->line_descent - overall_line_return->y;
2284 M17N_OBJECT_UNREF (gstring->top);
2291 @brief Compute the text dimensions of each character of M-text.
2293 The mdraw_text_per_char_extents () function computes the drawn
2294 metric of each character between $FROM and $TO of M-text $MT
2295 assuming that they are drawn on a window of frame $FRAME using the
2296 mdraw_text_with_control () function with the drawing control
2299 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2300 $LOGICAL_ARRAY_RETURN. Each successive element of
2301 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2302 ink and logical metrics of successive characters respectively,
2303 relative to the drawing origin of the M-text. The number of
2304 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2305 been set is returned to $NUM_CHARS_RETURN.
2307 If $ARRAY_SIZE is too small to return all metrics, the function
2308 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2309 Otherwise, it returns zero.
2311 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2312 @c NULL, this function also computes the metrics of the overall
2313 text and stores the results in the members of the structure
2314 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2316 If $CONTROL->two_dimensional is nonzero, this function computes
2317 only the metrics of characters in the first line. */
2319 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2321 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2322 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2323 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2325 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2326 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2327 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2328 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2329 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2331 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2332 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2335 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2336 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2337 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2339 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2342 mdraw_text_per_char_extents (MFrame *frame,
2343 MText *mt, int from, int to,
2344 MDrawControl *control,
2345 MDrawMetric *ink_array_return,
2346 MDrawMetric *logical_array_return,
2348 int *num_chars_return,
2349 MDrawMetric *overall_ink_return,
2350 MDrawMetric *overall_logical_return)
2352 MGlyphString *gstring;
2356 ASSURE_CONTROL (control);
2357 *num_chars_return = to - from;
2358 if (array_size < *num_chars_return)
2359 MERROR (MERROR_DRAW, -1);
2360 if (overall_logical_return)
2361 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2362 if (overall_ink_return)
2363 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2365 M_CHECK_RANGE (mt, from, to, -1, 0);
2366 gstring = get_gstring (frame, mt, from, to, control);
2369 *num_chars_return = 0;
2373 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2374 if (g->pos >= from && g->pos < to)
2378 int width = g->width;
2379 int lbearing = g->lbearing;
2380 int rbearing = g->rbearing;
2381 int ascent = g->ascent;
2382 int descent = g->descent;
2384 int logical_descent;
2386 if (g->rface->rfont)
2388 logical_ascent = g->rface->rfont->ascent;
2389 logical_descent = g->rface->rfont->descent;
2393 logical_ascent = g->rface->ascent;
2394 logical_descent = g->rface->descent;
2396 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2398 if (lbearing < width + g->lbearing)
2399 lbearing = width + g->lbearing;
2400 if (rbearing < width + g->rbearing)
2401 rbearing = width + g->rbearing;
2403 if (ascent < g->ascent)
2405 if (descent < g->descent)
2406 descent = g->descent;
2413 if (ink_array_return)
2415 ink_array_return[start - from].x = x + lbearing;
2416 ink_array_return[start - from].y = - ascent;
2417 ink_array_return[start - from].width = rbearing - lbearing;
2418 ink_array_return[start - from].height = ascent + descent;
2420 if (logical_array_return)
2422 logical_array_return[start - from].x = x;
2423 logical_array_return[start - from].y = - logical_descent;
2424 logical_array_return[start - from].height
2425 = logical_ascent + logical_descent;
2426 logical_array_return[start - from].width = width;
2434 if (overall_ink_return)
2436 overall_ink_return->y = - gstring->line_ascent;
2437 overall_ink_return->x = gstring->lbearing;
2438 overall_ink_return->width = x - gstring->lbearing;
2439 overall_ink_return->height = gstring->height;
2441 if (overall_logical_return)
2443 overall_logical_return->y = - gstring->ascent;
2444 overall_logical_return->x = 0;
2445 overall_logical_return->width = x;
2446 overall_logical_return->height = gstring->ascent + gstring->descent;
2449 M17N_OBJECT_UNREF (gstring->top);
2456 @brief Return the character position nearest to the coordinates.
2458 The mdraw_coordinates_position () function checks which character
2459 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2460 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2461 mdraw_text_with_control () function with the drawing control
2462 object $CONTROL. Here, the character position means the number of
2463 characters that precede the character in question in $MT, that is,
2464 the character position of the first character is 0.
2466 $FRAME is used only to get the default face information.
2469 If the glyph image of a character covers coordinate ($X, $Y),
2470 mdraw_coordinates_position () returns the character position of
2472 If $Y is less than the minimum Y-coordinate of the drawn area, it
2474 If $Y is greater than the maximum Y-coordinate of the drawn area,
2476 If $Y fits in with the drawn area but $X is less than the minimum
2477 X-coordinate, it returns the character position of the first
2478 character drawn on the line $Y.\n\n
2479 If $Y fits in with the drawn area but $X is greater than the
2480 maximum X-coordinate, it returns the character position of the
2481 last character drawn on the line $Y. */
2484 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2486 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2487 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2488 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2489 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2490 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2491 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2493 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2496 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2497 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2498 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2499 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2500 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2501 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2502 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2503 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2506 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2507 int x_offset, int y_offset, MDrawControl *control)
2509 MGlyphString *gstring;
2514 M_CHECK_POS_X (mt, from, -1);
2515 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2516 to = mtext_nchars (mt) + (control->cursor_width != 0);
2522 ASSURE_CONTROL (control);
2523 gstring = get_gstring (frame, mt, from, to, control);
2524 while (y + gstring->line_descent <= y_offset
2525 && gstring->to < to)
2528 y += gstring->line_descent;
2529 M17N_OBJECT_UNREF (gstring->top);
2530 gstring = get_gstring (frame, mt, from, to, control);
2531 y += gstring->line_ascent;
2534 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2535 if (! control->orientation_reversed)
2537 width = gstring->indent;
2538 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2539 if (g->pos >= from && g->pos < to)
2542 if (width > x_offset)
2548 width = - gstring->indent;
2549 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2550 if (g->pos >= from && g->pos < to)
2553 if (width < x_offset)
2557 if (g->type == GLYPH_ANCHOR
2558 && control->two_dimensional
2562 M17N_OBJECT_UNREF (gstring->top);
2570 @brief Compute information about a glyph.
2572 The mdraw_glyph_info () function computes information about a
2573 glyph that covers a character at position $POS of the M-text $MT
2574 assuming that the text is drawn from the character at $FROM of $MT
2575 on a window of frame $FRAME using the mdraw_text_with_control ()
2576 function with the drawing control object $CONTROL.
2578 The information is stored in the members of $INFO. */
2580 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2582 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2583 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2584 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2585 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2587 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2595 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2596 MDrawControl *control, MDrawGlyphInfo *info)
2598 MGlyphString *gstring;
2602 M_CHECK_RANGE_X (mt, from, pos, -1);
2604 ASSURE_CONTROL (control);
2605 gstring = get_gstring (frame, mt, from, pos + 1, control);
2607 MERROR (MERROR_DRAW, -1);
2608 while (gstring->to <= pos)
2610 y += gstring->line_descent;
2611 M17N_OBJECT_UNREF (gstring->top);
2612 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2613 y += gstring->line_ascent;
2615 info->line_from = gstring->from;
2616 if (info->line_from < from)
2617 info->line_from = from;
2618 info->line_to = gstring->to;
2621 if (! control->orientation_reversed)
2623 info->x = gstring->indent;
2624 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2625 info->x += g->width;
2629 info->x = - gstring->indent;
2630 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2631 info->x -= g->width;
2632 while (g[-1].to == g->to)
2635 info->from = g->pos;
2637 info->metrics.x = g->lbearing;
2638 info->metrics.y = - gstring->line_ascent;
2639 info->metrics.height = gstring->height;
2640 info->metrics.width = - g->lbearing + g->width;
2641 if (g->rface->rfont)
2642 info->font = (MFont *) g->rface->rfont;
2645 /* info->logical_width is calculated later. */
2647 if (info->from > info->line_from)
2649 /* The logically previous glyph is on this line. */
2650 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2652 info->prev_from = g_tmp->pos;
2654 else if (info->line_from > 0
2655 && gstring->from > 0)
2657 /* The logically previous glyph is on the previous line. */
2658 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2659 gstring->from, control);
2660 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2662 info->prev_from = g_tmp->pos;
2663 M17N_OBJECT_UNREF (gst->top);
2666 info->prev_from = -1;
2668 if (GLYPH_INDEX (g) > 1)
2669 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2670 else if (! control->orientation_reversed)
2672 if (info->line_from > 0)
2676 int p = gstring->from - 1;
2678 gst = get_gstring (frame, mt, p, gstring->from, control);
2679 g_tmp = gst->glyphs + (gst->used - 2);
2680 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2681 M17N_OBJECT_UNREF (gst->top);
2684 info->left_from = info->left_to = -1;
2688 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2692 int p = gstring->to;
2694 gst = get_gstring (frame, mt, p, p + 1, control);
2695 g_tmp = gst->glyphs + (gst->used - 2);
2696 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2697 M17N_OBJECT_UNREF (gst->top);
2700 info->left_from = info->left_to = -1;
2703 if (info->to < gstring->to)
2705 /* The logically next glyph is on this line. */
2706 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2708 info->next_to = g_tmp->to;
2710 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2712 /* The logically next glyph is on the next line. */
2714 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2715 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2717 info->next_to = g_tmp->to;
2718 M17N_OBJECT_UNREF (gst->top);
2723 for (info->logical_width = (g++)->width;
2724 g->pos == pos && g->type != GLYPH_ANCHOR;
2725 info->metrics.width += g->width, info->logical_width += (g++)->width);
2726 info->metrics.width += g[-1].rbearing - g[-1].width;
2728 if (g->type != GLYPH_ANCHOR)
2729 info->right_from = g->pos, info->right_to = g->to;
2730 else if (! control->orientation_reversed)
2732 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2735 M17N_OBJECT_UNREF (gstring->top);
2736 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2738 info->right_from = g->pos, info->right_to = g->to;
2741 info->right_from = info->right_to = -1;
2745 if (info->line_from > 0)
2747 pos = gstring->from - 1;
2748 M17N_OBJECT_UNREF (gstring->top);
2749 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2751 info->right_from = g->pos, info->right_to = g->to;
2754 info->right_from = info->right_to = -1;
2757 M17N_OBJECT_UNREF (gstring->top);
2764 @brief Compute information about glyph sequence.
2766 The mdraw_glyph_list () function computes information about glyphs
2767 corresponding to the text between $FROM and $TO of M-text $MT when
2768 it is drawn on a window of frame $FRAME using the
2769 mdraw_text_with_control () function with the drawing control
2770 object $CONTROL. $GLYPHS is an array of objects to store the
2771 information, and $ARRAY_SIZE is the array size.
2773 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2774 number of actually filled elements in the place pointed by
2775 $NUM_GLYPHS_RETURN, and returns 0.
2777 Otherwise, it stores the required array size in the place pointed
2778 by $NUM_GLYPHS_RETURN, and returns -1. */
2781 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2783 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2784 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2785 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2786 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2788 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2789 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2792 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2802 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2803 MDrawControl *control, MDrawGlyph *glyphs,
2804 int array_size, int *num_glyphs_return)
2806 MGlyphString *gstring;
2811 ASSURE_CONTROL (control);
2812 *num_glyphs_return = 0;
2813 M_CHECK_RANGE (mt, from, to, -1, 0);
2814 gstring = get_gstring (frame, mt, from, to, control);
2817 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2819 if (g->type == GLYPH_BOX
2820 || g->pos < from || g->pos >= to)
2822 if (g->type == GLYPH_PAD)
2824 if (g->left_padding)
2825 pad_width = g->width;
2829 glyphs[-1].x_advance += g->width;
2835 glyphs->from = g->pos;
2837 glyphs->glyph_code = g->code;
2838 glyphs->x_off = g->xoff + pad_width;
2839 glyphs->y_off = g->yoff;
2840 glyphs->lbearing = g->lbearing;
2841 glyphs->rbearing = g->rbearing;
2842 glyphs->ascent = g->ascent;
2843 glyphs->descent = g->descent;
2844 glyphs->x_advance = g->width + pad_width;
2845 glyphs->y_advance = 0;
2846 if (g->rface->rfont)
2848 glyphs->font = (MFont *) g->rface->rfont;
2850 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2851 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2853 glyphs->fontp = g->rface->rfont->fontp;
2857 glyphs->font = NULL;
2858 glyphs->font_type = Mnil;
2859 glyphs->fontp = NULL;
2866 M17N_OBJECT_UNREF (gstring->top);
2868 *num_glyphs_return = n;
2869 return (n <= array_size ? 0 : -1);
2875 @brief Draw one or more textitems.
2877 The mdraw_text_items () function draws one or more M-texts on
2878 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2879 of the textitems to be drawn and $NITEMS is the number of
2880 textitems in the array. */
2883 @brief textitem ¤òɽ¼¨¤¹¤ë.
2885 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2886 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2887 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2889 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2893 MTextItem, mdraw_text (). */
2896 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2897 MDrawTextItem *items, int nitems)
2899 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2901 while (nitems-- > 0)
2904 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2906 mdraw_text_with_control (frame, win, x, y,
2907 items->mt, 0, mtext_nchars (items->mt),
2909 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2910 items->control, NULL, NULL, NULL);
2913 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2919 @brief Option of line breaking for drawing text.
2921 The variable #mdraw_line_break_option specifies line breaking
2922 options by logical-or of the members of #MTextLineBreakOption. It
2923 controls the line breaking algorithm of the function
2924 mdraw_default_line_break (). */
2926 int mdraw_line_break_option;
2930 @brief Calculate a line breaking position.
2932 The function mdraw_default_line_break () calculates a line
2933 breaking position based on the line number $LINE and the
2934 coordinate $Y, when a line is too long to fit within the width
2935 limit. $POS is the position of the character next to the last one
2936 that fits within the limit. $FROM is the position of the first
2937 character of the line, and $TO is the position of the last
2938 character displayed on the line if there were not width limit.
2939 $LINE and $Y are reset to 0 when a line is broken by a newline
2940 character, and incremented each time when a long line is broken
2941 because of the width limit.
2943 @return This function returns a character position to break the
2948 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2950 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2951 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2952 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2953 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2954 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2955 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2956 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2959 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2963 mdraw_default_line_break (MText *mt, int pos,
2964 int from, int to, int line, int y)
2968 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2979 @brief Obtain per character dimension information.
2981 The mdraw_per_char_extents () function computes the text dimension
2982 of each character in M-text $MT. The faces given as text
2983 properties in $MT and the default face of frame $FRAME determine
2984 the fonts to draw the text. Each successive element in
2985 $ARRAY_RETURN is set to the drawn metrics of successive
2986 characters, which is relative to the origin of the drawing, and a
2987 rectangle for each character in $MT. The number of elements of
2988 $ARRAY_RETURN must be equal to or greater than the number of
2991 If pointer $OVERALL_RETURN is not @c NULL, this function also
2992 computes the extents of the overall text and stores the results in
2993 the members of the structure pointed to by $OVERALL_RETURN. */
2996 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2998 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2999 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3000 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3001 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3002 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3003 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3004 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3006 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3007 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3008 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3010 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3013 mdraw_per_char_extents (MFrame *frame, MText *mt,
3014 MDrawMetric *array_return,
3015 MDrawMetric *overall_return)
3017 int n = mtext_nchars (mt);
3019 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3020 n, &n, overall_return, NULL);
3024 @brief clear cached information.
3026 The mdraw_clear_cache () function clear cached information
3027 on M-text $MT that was attached by any of the drawing functions.
3028 When the behavior of `format' or `line_break'
3029 member functions of MDrawControl is changed, the cache must be cleared.
3034 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3036 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3037 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3038 ¤¢¤ë¤¤¤Ï `line_break'
3039 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3045 mdraw_clear_cache (MText *mt)
3047 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);