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));
443 if (prev->rface->rfont != this->rface->rfont)
445 prev->rface->rfont = this->rface->rfont;
450 (g->type == GLYPH_CHAR
451 && g->rface->layouter == this->rface->layouter
452 && (g->rface->rfont == this->rface->rfont
453 || (g->category == GLYPH_CATEGORY_FORMATTER
454 && ((code = mfont__encode_char (NULL,
455 (MFont *) this->rface->rfont,
458 != MCHAR_INVALID_CODE))));
460 if (g->rface->rfont != this->rface->rfont)
462 g->rface->rfont = this->rface->rfont;
465 i = mfont__flt_run (gstring, start, i, this->rface);
469 while (this->type == GLYPH_CHAR
471 && this->category == GLYPH_CATEGORY_MODIFIER
472 && this->rface->rfont
473 && this->rface->rfont->layouter == Mnil)
475 int class = (int) mchar_get_prop (this->c,
478 = MAKE_COMBINING_CODE_BY_CLASS (class);
482 reorder_combining_chars (gstring, start, i);
483 if (this->type == GLYPH_ANCHOR)
492 /* At last, reorder glyphs visually if necessary. */
493 if (gstring->control.enable_bidi)
494 visual_order (gstring);
499 combining_code_from_class (int class)
504 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
505 else if (class == 200) /* below left attached */
506 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
507 else if (class == 202) /* below attached*/
508 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
509 else if (class == 204) /* below right attached */
510 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
511 else if (class == 208) /* left attached */
512 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
513 else if (class == 210) /* right attached */
514 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
515 else if (class == 212) /* above left attached */
516 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
517 else if (class == 214) /* above attached */
518 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
519 else if (class == 216) /* above right attached */
520 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
521 else if (class == 218) /* below left */
522 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
523 else if (class == 220) /* below */
524 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
525 else if (class == 222) /* below right */
526 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
527 else if (class == 224) /* left */
528 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
529 else if (class == 226) /* right */
530 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
531 else if (class == 228) /* above left */
532 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
533 else if (class == 230) /* above */
534 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
535 else if (class == 232) /* above right */
536 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
537 else if (class == 233) /* double below */
538 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
539 else if (class == 234) /* double above */
540 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
541 else if (class == 240) /* iota subscript */
542 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
544 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
550 int width, lbearing, rbearing;
554 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
555 MSubTextExtents *extents)
557 int g_physical_ascent, g_physical_descent;
558 MGlyph *g = MGLYPH (from);
559 MGlyph *last_g = MGLYPH (to);
562 g_physical_ascent = gstring->physical_ascent;
563 g_physical_descent = gstring->physical_descent;
564 extents->width = extents->lbearing = extents->rbearing = 0;
566 for (i = from; i < to;)
568 if ( MGLYPH (i)->otf_encoded)
574 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
575 mfont__get_metric (gstring, j, i);
583 MRealizedFont *rfont = base->rface->rfont;
584 int size = rfont->spec.size;
585 int width, lbearing, rbearing;
587 if (g == last_g || ! g->combining_code)
590 if (base->width == 0 && ! base->left_padding && ! base->right_padding
591 && GLYPH_INDEX (base) > from)
593 MGlyph *prev = base - 1;
595 if (base->pos < prev->pos)
596 prev->pos = base->pos;
598 base->pos = prev->pos;
599 if (base->to > prev->to)
605 if (base->left_padding && base->lbearing < 0)
607 base->xoff = - base->lbearing;
608 base->width += base->xoff;
609 base->rbearing += base->xoff;
612 if (base->right_padding && base->rbearing > base->width)
614 base->width = base->rbearing;
616 lbearing = (base->xoff + base->lbearing < 0
617 ? base->xoff + base->lbearing : 0);
618 rbearing = base->xoff + base->rbearing;
622 /* With combining glyphs. */
623 int left = -base->width;
625 int top = - base->ascent;
626 int bottom = base->descent;
627 int height = bottom - top;
628 int begin = base->pos;
633 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
634 rbearing = base->rbearing;
636 while (g != last_g && g->combining_code)
638 int combining_code = g->combining_code;
642 else if (end < g->to)
645 if (! COMBINING_PRECOMPUTED_P (combining_code))
647 int base_x, base_y, add_x, add_y, off_x, off_y;
649 if (COMBINING_BY_CLASS_P (combining_code))
650 g->combining_code = combining_code
651 = combining_code_from_class (COMBINING_CODE_CLASS
654 rfont = g->rface->rfont;
655 size = rfont->spec.size;
656 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
658 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
660 base_x = COMBINING_CODE_BASE_X (combining_code);
661 base_y = COMBINING_CODE_BASE_Y (combining_code);
662 add_x = COMBINING_CODE_ADD_X (combining_code);
663 add_y = COMBINING_CODE_ADD_Y (combining_code);
665 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
668 if (g->xoff + g->width > right)
669 right = g->xoff + g->width;
670 width = right - left;
673 g->yoff = top + height * base_y / 2;
677 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
681 if (g->xoff + g->lbearing < left + lbearing)
682 lbearing = g->xoff + g->lbearing - left;
683 if (g->xoff + g->rbearing > left + rbearing)
684 rbearing = g->xoff + g->rbearing - left;
685 if (g->yoff - g->ascent < top)
686 top = g->yoff - g->ascent;
687 if (g->yoff + g->descent > bottom)
688 bottom = g->yoff + g->descent;
689 height = bottom - top;
695 base->ascent = - top;
696 base->descent = bottom;
697 base->lbearing = lbearing;
698 base->rbearing = rbearing;
699 if (left < - base->width)
701 base->xoff = - base->width - left;
702 base->width += base->xoff;
703 base->rbearing += base->xoff;
704 base->lbearing += base->xoff;
708 base->width += right;
709 base->rbearing += right;
710 base->right_padding = 1;
711 for (i = 1; base + i != g; i++)
712 base[i].xoff -= right;
715 for (i = 0; base + i != g; i++)
722 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
723 g_physical_descent = MAX (g_physical_descent, base->descent);
724 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
725 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
726 extents->width += base->width;
729 gstring->physical_ascent = g_physical_ascent;
730 gstring->physical_descent = g_physical_descent;
734 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
735 by this function directly. Character glyphs are handled by
736 layouter functions registered in font drivers.
738 This function fill-in all the remaining members of glyphs. */
741 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
743 /* Default width of TAB. */
744 int tab_width = frame->space_width * (gstring->control.tab_width
745 ? gstring->control.tab_width : 8);
749 MDrawControl *control = &(gstring->control);
752 int box_line_height = 0;
753 int ignore_formatting_char = control->ignore_formatting_char;
755 gstring->ascent = gstring->descent = 0;
756 gstring->physical_ascent = gstring->physical_descent = 0;
757 gstring->width = gstring->lbearing = gstring->rbearing = 0;
761 while (g->type != GLYPH_ANCHOR)
763 if (box != g->rface->box)
765 int gidx = GLYPH_INDEX (g);
769 /* Insert the right side of the box. That glyph belongs
770 to the previous grapheme cluster. */
771 MGlyph box_glyph = g[-1];
773 box_glyph.type = GLYPH_BOX;
775 = (control->fixed_width
777 : box->inner_hmargin + box->width + box->outer_hmargin);
778 box_glyph.lbearing = 0;
779 box_glyph.rbearing = box_glyph.width;
781 box_glyph.right_padding = 1;
782 gstring->width += box_glyph.width;
783 gstring->rbearing += box_glyph.width;
784 INSERT_GLYPH (gstring, gidx, box_glyph);
791 /* Insert the left side of the box. That glyph belongs
792 to the following grapheme cluster. */
793 MGlyph box_glyph = *g;
794 int box_height = (box->width
795 + box->inner_vmargin + box->outer_vmargin);
797 if (box_line_height < box_height)
798 box_line_height = box_height;
799 box_glyph.type = GLYPH_BOX;
801 = (control->fixed_width
803 : box->inner_hmargin + box->width + box->outer_hmargin);
804 box_glyph.lbearing = 0;
805 box_glyph.rbearing = box_glyph.width;
807 box_glyph.left_padding = 1;
808 gstring->width += box_glyph.width;
809 gstring->rbearing += box_glyph.width;
810 INSERT_GLYPH (gstring, gidx, box_glyph);
816 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
817 g->type = GLYPH_SPACE;
819 if (g->type == GLYPH_CHAR)
821 MRealizedFace *rface = g->rface;
822 MRealizedFont *rfont = rface->rfont;
824 int from = GLYPH_INDEX (g);
826 for (g++; g->type == GLYPH_CHAR; g++)
827 if (! rfont != ! g->rface->rfont
828 || box != g->rface->box
829 || ((fromg->code == MCHAR_INVALID_CODE)
830 != (g->code == MCHAR_INVALID_CODE))
831 || (g->category == GLYPH_CATEGORY_FORMATTER
832 && ignore_formatting_char))
834 if (rfont && fromg->code != MCHAR_INVALID_CODE)
837 int to = GLYPH_INDEX (g);
838 MSubTextExtents extents;
840 layout_glyphs (frame, gstring, from, to, &extents);
841 extra_width = - extents.lbearing;
843 && ! control->disable_overlapping_adjustment
844 && (! control->orientation_reversed
845 ? ((to > 1 || control->align_head)
846 && g->type != GLYPH_ANCHOR)
847 : (((g->type && GLYPH_ANCHOR) || control->align_head)
852 pad.type = GLYPH_PAD;
855 pad.width = pad.rbearing = extra_width;
856 pad.left_padding = 1;
857 INSERT_GLYPH (gstring, from, pad);
859 extents.lbearing = 0;
860 extents.width += extra_width;
861 extents.rbearing += extra_width;
863 g = MGLYPH (from - 1);
864 if (g->type == GLYPH_SPACE)
866 /* The pad just inserted is absorbed (maybe
867 partially) by the previous space while
868 keeping at least some space width. For the
869 moment, we use the arbitrary width 2-pixel.
870 Perhaps, it should be decided by the current
871 face, or a default value of the current
872 frame, which is, however, not yet
874 if (extra_width + 2 < g->width)
876 g->width -= extra_width;
880 extra_width = g->width - 2;
883 gstring->width -= extra_width;
884 gstring->rbearing -= extra_width;
889 extra_width = extents.rbearing - extents.width;
891 && ! control->disable_overlapping_adjustment
892 && (GLYPH_INDEX (g) < gstring->used - 1
893 || (control->orientation_reversed && control->align_head)))
895 if (g->type == GLYPH_SPACE && box == g->rface->box)
898 pad.type = GLYPH_PAD;
901 pad.width = pad.rbearing = extra_width;
902 INSERT_GLYPH (gstring, to, pad);
907 g[-1].width += extra_width;
908 extents.width += extra_width;
911 if (gstring->lbearing > gstring->width + extents.lbearing)
912 gstring->lbearing = gstring->width + extents.lbearing;
913 if (gstring->rbearing < gstring->width + extents.rbearing)
914 gstring->rbearing = gstring->width + extents.rbearing;
915 gstring->width += extents.width;
916 if (gstring->ascent < rface->ascent)
917 gstring->ascent = rface->ascent;
918 if (gstring->descent < rface->descent)
919 gstring->descent = rface->descent;
923 for (; fromg < g; fromg++)
925 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
926 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
927 fromg->width = fromg->rbearing = 1;
929 fromg->width = fromg->rbearing = rface->space_width;
930 fromg->xoff = fromg->lbearing = 0;
931 fromg->ascent = fromg->descent = 0;
932 gstring->width += fromg->width;
933 gstring->rbearing += fromg->width;
935 if (gstring->ascent < frame->rface->ascent)
936 gstring->ascent = frame->rface->ascent;
937 if (gstring->descent < frame->descent)
938 gstring->descent = frame->rface->descent;
941 else if (g->type == GLYPH_SPACE)
944 g->width = g->rface->space_width;
945 else if (g->c == '\n')
947 g->width = control->cursor_width;
950 if (control->cursor_bidi)
952 else if (g->width < 0)
953 g->width = g->rface->space_width;
956 else if (g->c == '\t')
958 g->width = tab_width - ((gstring->indent + gstring->width)
964 if (g[-1].type == GLYPH_PAD)
966 /* This space glyph absorbs (maybe partially) the
967 previous padding glyph. */
968 g->width -= g[-1].width;
970 /* But, keep at least some space width. For the
971 moment, we use the arbitrary width 2-pixel. */
974 g->rbearing = g->width;
975 gstring->width += g->width;
976 gstring->rbearing += g->width;
979 if (gstring->ascent < g->rface->ascent)
980 gstring->ascent = g->rface->ascent;
981 if (gstring->descent < g->rface->descent)
982 gstring->descent = g->rface->descent;
988 gstring->width += g->width;
989 gstring->rbearing += g->width;
996 /* Insert the right side of the box. */
997 int gidx = GLYPH_INDEX (g);
998 MGlyph box_glyph = g[-1];
1000 box_glyph.type = GLYPH_BOX;
1002 = (control->fixed_width
1003 ? frame->space_width
1004 : box->inner_hmargin + box->width + box->outer_hmargin);
1005 box_glyph.lbearing = 0;
1006 box_glyph.rbearing = box_glyph.width;
1008 box_glyph.right_padding = 1;
1009 gstring->width += box_glyph.width;
1010 gstring->rbearing += box_glyph.width;
1011 INSERT_GLYPH (gstring, gidx, box_glyph);
1014 gstring->text_ascent = gstring->ascent;
1015 gstring->text_descent = gstring->descent;
1016 if (gstring->text_ascent < gstring->physical_ascent)
1017 gstring->text_ascent = gstring->physical_ascent;
1018 if (gstring->text_descent < gstring->physical_descent)
1019 gstring->text_descent = gstring->physical_descent;
1020 gstring->line_ascent = gstring->text_ascent;
1021 gstring->line_descent = gstring->text_descent;
1022 if (box_line_height > 0)
1024 gstring->line_ascent += box_line_height;
1025 gstring->physical_ascent = gstring->line_ascent;
1026 gstring->line_descent += box_line_height;
1027 gstring->physical_descent = gstring->line_descent;
1030 if (gstring->line_ascent < control->min_line_ascent)
1031 gstring->line_ascent = control->min_line_ascent;
1032 else if (control->max_line_ascent
1033 && control->max_line_ascent > control->min_line_ascent
1034 && gstring->line_ascent > control->max_line_ascent)
1035 gstring->line_ascent = control->max_line_ascent;
1037 if (gstring->line_descent < control->min_line_descent)
1038 gstring->line_descent = control->min_line_descent;
1039 else if (control->max_line_descent
1040 && control->max_line_descent > control->min_line_descent
1041 && gstring->line_descent > control->max_line_descent)
1042 gstring->line_descent = control->max_line_descent;
1043 gstring->height = gstring->line_ascent + gstring->line_descent;
1045 if (control->orientation_reversed
1048 /* We must adjust TAB width for RTL orientation. */
1049 width = gstring->indent;
1051 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1053 if (g->type == GLYPH_CHAR && g->c == '\t')
1055 int this_width = tab_width - (width % tab_width);
1057 if (g[1].type == GLYPH_PAD)
1058 this_width -= g[1].width;
1059 if (g[-1].type == GLYPH_PAD)
1060 this_width -= g[-1].width;
1063 gstring->width += this_width - g->width;
1064 gstring->rbearing += this_width - g->width;
1065 g->width = this_width;
1066 width += this_width;
1076 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1077 MGlyphString *gstring, int from, int to,
1078 int *from_idx, int *to_idx, int *to_x)
1080 MGlyph *g = MGLYPH (1);
1081 MDrawRegion region = (MDrawRegion) NULL;
1082 MDrawControl *control = &gstring->control;
1083 int cursor_pos = -1;
1085 int cursor_bidi = control->cursor_bidi;
1087 if (control->with_cursor && control->cursor_width)
1089 if (gstring->from <= control->cursor_pos
1090 && gstring->to > control->cursor_pos)
1091 cursor_pos = control->cursor_pos;
1094 && gstring->from <= control->cursor_pos - 1
1095 && gstring->to > control->cursor_pos - 1)
1096 prev_pos = control->cursor_pos - 1;
1099 *from_idx = *to_idx = 0;
1100 while (g->type != GLYPH_ANCHOR)
1102 if (g->pos >= from && g->pos < to)
1104 MGlyph *fromg = g, *cursor = NULL;
1105 MRealizedFace *rface = g->rface;
1107 int cursor_width = 0;
1111 *from_idx = GLYPH_INDEX (g);
1112 while (g->pos >= from && g->pos < to
1113 && g->rface == rface)
1116 if (g->type != GLYPH_BOX
1117 && g->pos <= cursor_pos && g->to > cursor_pos)
1120 cursor = g, cursor_x = x + width;
1121 cursor_width += g->width;
1123 width += g++->width;
1126 && (control->as_image
1127 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1129 int this_x = x, this_width = width;
1131 if (fromg->type == GLYPH_BOX)
1132 this_x += fromg->width, this_width -= fromg->width;
1133 if (g[-1].type == GLYPH_BOX)
1134 this_width -= g[-1].width;
1135 (frame->driver->fill_space)
1136 (frame, win, rface, 0,
1137 this_x, y - gstring->text_ascent, this_width,
1138 gstring->text_ascent + gstring->text_descent,
1139 control->clip_region);
1146 rect.y = y - gstring->text_ascent;
1147 rect.height = gstring->text_ascent + gstring->text_descent;
1150 rect.width = ((control->cursor_width > 0
1151 && control->cursor_width < cursor_width)
1152 ? control->cursor_width : cursor_width);
1156 if (cursor->bidi_level % 2)
1157 rect.x += cursor_width - rect.width;
1158 (*frame->driver->fill_space)
1159 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1160 control->clip_region);
1162 region = (*frame->driver->region_from_rect) (&rect);
1164 (*frame->driver->region_add_rect) (region, &rect);
1167 if (cursor->bidi_level % 2)
1170 rect.width = cursor_width < 4 ? cursor_width : 4;
1171 (*frame->driver->fill_space)
1172 (frame, win, rface, 1,
1173 rect.x, rect.y, rect.width, rect.height,
1174 control->clip_region);
1175 (*frame->driver->region_add_rect) (region, &rect);
1187 if (fromg->type != GLYPH_BOX
1188 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1191 cursor = fromg, cursor_x = x + temp_width;
1192 cursor_width += fromg->width;
1194 temp_width += fromg++->width;
1201 if (! (cursor->bidi_level % 2))
1202 rect.x += cursor_width - 1;
1203 rect.y = y - gstring->text_ascent;
1204 rect.height = gstring->text_ascent + gstring->text_descent;
1206 (*frame->driver->fill_space)
1207 (frame, win, rface, 1,
1208 rect.x, rect.y, rect.width, rect.height,
1209 control->clip_region);
1211 region = (*frame->driver->region_from_rect) (&rect);
1213 (*frame->driver->region_add_rect) (region, &rect);
1214 rect.y += rect.height - 2;
1216 rect.width = cursor_width < 4 ? cursor_width : 4;
1217 if (! (cursor->bidi_level % 2))
1218 rect.x -= rect.width - 1;
1219 (*frame->driver->fill_space) (frame, win, rface, 1,
1220 rect.x, rect.y, rect.width, rect.height,
1221 control->clip_region);
1222 (*frame->driver->region_add_rect) (region, &rect);
1226 *to_idx = GLYPH_INDEX (g);
1236 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1237 MGlyphString *gstring, int from_idx, int to_idx,
1238 int reverse, MDrawRegion region)
1240 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1246 (*frame->driver->region_to_rect) (region, &rect);
1249 while (g != gend && x + g->rbearing <= rect.x)
1252 width -= g++->width;
1253 while (! g->enabled && g != gend)
1257 rect.x += rect.width;
1258 if (rect.x < x + width)
1261 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1263 width -= (--gend)->width;
1264 while (! gend->enabled && g != gend)
1268 while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
1277 MRealizedFace *rface = g->rface;
1278 int width = g->width;
1279 MGlyph *from_g = g++;
1281 /* Handle the glyphs of the same type/face at once. */
1283 && g->type == from_g->type
1284 && g->rface == rface
1285 && ((g->code == MCHAR_INVALID_CODE)
1286 == (from_g->code == MCHAR_INVALID_CODE))
1288 width += g++->width;
1290 if (from_g->type == GLYPH_CHAR)
1292 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1293 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1296 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1299 else if (from_g->type == GLYPH_BOX)
1301 /* Draw the left or right side of a box. If
1302 from_g->lbearing is nonzero, this is the left side,
1303 else this is the right side. */
1304 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1307 if (from_g->type != GLYPH_BOX)
1310 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1311 x, y, width, region);
1314 /* Draw the top and bottom side of a box. */
1315 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1316 x, y, width, region);
1327 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1328 int *from_x, int *to_x)
1331 int left_idx = *left, right_idx = *right;
1332 int left_x, right_x, x;
1334 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1337 if (x + g->rbearing > 0)
1339 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1341 left_idx = GLYPH_INDEX (g);
1346 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1349 if (x - g->width + g->lbearing < 0)
1351 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1353 right_idx = GLYPH_INDEX (g) + 1;
1358 if (*left == left_idx && *right == right_idx)
1361 if (*left != left_idx)
1363 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1368 if (*right != right_idx)
1370 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1380 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1385 if (from <= gstring->from && to >= gstring->to)
1388 *rbearing = gstring->rbearing;
1389 return gstring->width;
1394 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1395 if (g->pos >= from && g->pos < to)
1397 if (rbearing && width + g->rbearing > *rbearing)
1398 *rbearing = width + g->rbearing;
1406 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1407 MGlyphString *gstring, int from, int to)
1409 MDrawControl *control = &gstring->control;
1411 MDrawRegion clip_region, cursor_region;
1412 int from_idx, to_idx;
1415 if (control->orientation_reversed)
1416 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1418 x += gstring->indent;
1420 /* At first, draw all glyphs without cursor. */
1421 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1422 &from_idx, &to_idx, &to_x);
1424 if (control->partial_update)
1427 rect.width = to_x - x;
1428 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1430 rect.y = y - gstring->line_ascent;
1431 rect.height = gstring->height;
1432 clip_region = (*frame->driver->region_from_rect) (&rect);
1433 if (control->clip_region)
1434 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1437 clip_region = control->clip_region;
1440 clip_region = control->clip_region;
1442 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1447 (*frame->driver->intersect_region) (cursor_region, clip_region);
1448 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1451 if (clip_region != control->clip_region)
1452 (*frame->driver->free_region) (clip_region);
1454 (*frame->driver->free_region) (cursor_region);
1458 static int gstring_num;
1461 free_gstring (void *object)
1463 MGlyphString *gstring = (MGlyphString *) object;
1466 free_gstring (gstring->next);
1467 if (gstring->size > 0)
1468 free (gstring->glyphs);
1474 static MGlyphString scratch_gstring;
1476 static MGlyphString *
1477 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1480 MGlyphString *gstring;
1482 if (pos == mt->nchars)
1486 gstring = &scratch_gstring;
1487 if (gstring->size == 0)
1492 g_tmp.type = GLYPH_ANCHOR;
1493 APPEND_GLYPH (gstring, g_tmp);
1494 APPEND_GLYPH (gstring, g_tmp);
1495 APPEND_GLYPH (gstring, g_tmp);
1496 gstring->glyphs[1].type = GLYPH_SPACE;
1497 gstring->glyphs[1].c = '\n';
1498 gstring->glyphs[1].code = '\n';
1500 gstring->from = pos;
1502 g->rface = frame->rface;
1503 g->pos = g->to = pos;
1505 g->rface = frame->rface;
1506 g->pos = pos++, g->to = pos;
1508 g->rface = frame->rface;
1509 g->pos = g->to = pos;
1514 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1515 MLIST_INIT1 (gstring, glyphs, 128);
1519 gstring->frame = frame;
1520 gstring->tick = frame->tick;
1521 gstring->top = gstring;
1522 gstring->control = *control;
1523 gstring->indent = gstring->width_limit = 0;
1524 if (control->format)
1525 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1527 gstring->width_limit = control->max_line_width;
1528 gstring->anti_alias = control->anti_alias;
1532 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1535 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1538 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1546 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1547 a width of glyphs for the character at I of MT. If I is not a
1548 beginning of a grapheme cluster, the corresponding element is
1550 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1551 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1552 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1553 pos_width[g->pos - gstring->from] += g->width;
1554 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1556 if (pos_width[i] > 0)
1558 if (width + pos_width[i] > gstring->width_limit)
1561 width += pos_width[i];
1564 pos = gstring->from + i;
1565 if (gstring->control.line_break)
1567 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1568 gstring->from, gstring->from + i,
1570 if (pos <= gstring->from)
1572 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1575 else if (pos >= gstring->to)
1580 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1583 if (pos < gstring->to)
1585 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1586 layout_glyph_string (frame, gstring);
1591 /* Return a gstring that covers a character at POS. */
1593 static MGlyphString *
1594 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1596 MGlyphString *gstring = NULL;
1598 if (pos < mtext_nchars (mt))
1600 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1603 && ((prop->start != 0
1604 && mtext_ref_char (mt, prop->start - 1) != '\n')
1605 || (prop->end < mtext_nchars (mt)
1606 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1608 mtext_detach_property (prop);
1613 gstring = prop->val;
1614 if (gstring->frame != frame
1615 || gstring->tick != frame->tick
1616 || memcmp (control, &gstring->control,
1617 (char *) (&control->with_cursor)
1618 - (char *) (control))
1619 || control->cursor_width != gstring->control.cursor_width
1620 || control->cursor_bidi != gstring->control.cursor_bidi)
1622 mtext_detach_property (prop);
1627 else if (! control->cursor_width)
1635 offset = mtext_character (mt, pos, 0, '\n');
1640 offset -= gstring->from;
1642 for (gst = gstring; gst; gst = gst->next)
1646 gst->from += offset;
1648 for (i = 0; i < gst->used; i++)
1650 gst->glyphs[i].pos += offset;
1651 gst->glyphs[i].to += offset;
1654 M17N_OBJECT_REF (gstring);
1659 int line = 0, y = 0;
1661 if (pos < mtext_nchars (mt))
1663 beg = mtext_character (mt, pos, 0, '\n');
1671 end = mtext_nchars (mt) + (control->cursor_width != 0);
1672 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1673 if (beg < mtext_nchars (mt))
1674 compose_glyph_string (frame, mt, beg, end, gstring);
1675 layout_glyph_string (frame, gstring);
1677 if (gstring->width_limit
1678 && gstring->width > gstring->width_limit)
1680 MGlyphString *gst = gstring;
1682 truncate_gstring (frame, mt, gst);
1683 while (gst->to < end)
1685 line++, y += gst->height;
1686 gst->next = alloc_gstring (frame, mt, gst->from, control,
1688 gst->next->top = gstring;
1689 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1691 layout_glyph_string (frame, gst);
1692 if (gst->width <= gst->width_limit)
1694 truncate_gstring (frame, mt, gst);
1698 if (! control->disable_caching && pos < mtext_nchars (mt))
1700 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1701 MTEXTPROP_VOLATILE_STRONG);
1703 if (end > mtext_nchars (mt))
1704 end = mtext_nchars (mt);
1705 mtext_attach_property (mt, beg, end, prop);
1706 M17N_OBJECT_UNREF (prop);
1710 while (gstring->to <= pos)
1712 if (! gstring->next)
1714 gstring = gstring->next;
1716 gstring->control = *control;
1722 static MDrawControl control_noop;
1724 #define ASSURE_CONTROL(control) \
1726 control = &control_noop; \
1731 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1732 MText *mt, int from, int to,
1733 MDrawControl *control)
1735 MGlyphString *gstring;
1737 M_CHECK_POS_X (mt, from, -1);
1738 ASSURE_CONTROL (control);
1739 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1740 to = mtext_nchars (mt) + (control->cursor_width != 0);
1744 gstring = get_gstring (frame, mt, from, to, control);
1746 MERROR (MERROR_DRAW, -1);
1747 render_glyph_string (frame, win, x, y, gstring, from, to);
1751 y += gstring->line_descent;
1752 M17N_OBJECT_UNREF (gstring->top);
1753 gstring = get_gstring (frame, mt, from, to, control);
1754 y += gstring->line_ascent;
1755 render_glyph_string (frame, win, x, y, gstring, from, to);
1758 M17N_OBJECT_UNREF (gstring->top);
1765 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1771 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1772 if (g->pos <= pos && g->to > pos)
1777 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1778 if (g->pos <= pos && g->to > pos)
1785 /* for debugging... */
1789 dump_combining_code (int code)
1791 char *vallign = "tcbB";
1792 char *hallign = "lcr";
1798 if (COMBINING_BY_CLASS_P (code))
1799 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1800 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1801 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1802 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1803 off_x = COMBINING_CODE_OFF_X (code) - 128;
1805 sprintf (work + 2, "+%d", off_y);
1807 sprintf (work + 2, "%d", off_y);
1808 else if (off_x == 0)
1809 sprintf (work + 2, ".");
1810 p = work + strlen (work);
1812 sprintf (p, ">%d", off_x);
1814 sprintf (p, "<%d", -off_x);
1816 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1817 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1823 dump_gstring (MGlyphString *gstring, int indent)
1825 char *prefix = (char *) alloca (indent + 1);
1826 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1828 memset (prefix, 32, indent);
1831 fprintf (stderr, "(glyph-string");
1833 for (g = MGLYPH (0); g < last_g; g++)
1835 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1837 g - gstring->glyphs,
1838 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1839 : g->type == GLYPH_ANCHOR ? "ANC"
1840 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1841 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1842 dump_combining_code (g->combining_code),
1843 g->width, g->bidi_level);
1844 fprintf (stderr, ")");
1848 /* m17n-X internal APIs */
1853 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1855 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1856 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1858 Minherited = msymbol ("inherited");
1859 Mcommon = msymbol ("common");
1861 McatCc = msymbol ("Cc");
1862 McatCf = msymbol ("Cf");
1864 MbidiR = msymbol ("R");
1865 MbidiAL = msymbol ("AL");
1866 MbidiRLE = msymbol ("RLE");
1867 MbidiRLO = msymbol ("RLO");
1868 MbidiBN = msymbol ("BN");
1869 MbidiS = msymbol ("S");
1871 fribidi_set_mirroring (TRUE);
1874 M_break_at_space = msymbol ("bs");
1875 M_break_at_word = msymbol ("bw");
1876 M_break_at_any = msymbol ("ba");
1877 M_kinsoku_bol = msymbol ("kb");
1878 M_kinsoku_eol = msymbol ("ke");
1886 MLIST_FREE1 (&scratch_gstring, glyphs);
1887 M17N_OBJECT_UNREF (linebreak_table);
1888 linebreak_table = NULL;
1892 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1896 /*** @addtogroup m17nDraw */
1901 @brief Draw an M-text on a window.
1903 The mdraw_text () function draws the text between $FROM and $TO of
1904 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1906 The appearance of the text (size, style, color, etc) is specified
1907 by the value of the text property whose key is @c Mface. If the
1908 M-text or a part of the M-text does not have such a text property,
1909 the default face of $FRAME is used.
1911 The font used to draw a character in the M-text is selected from
1912 the value of the fontset property of a face by the following
1917 <li> Search the text properties given to the character for the one
1918 whose key is @c Mcharset; its value should be either a symbol
1919 specifying a charset or #Mnil. If the value is #Mnil,
1920 proceed to the next step.
1922 Otherwise, search the mapping table of the fontset for the
1923 charset. If no entry is found proceed to the next step.
1925 If an entry is found, use one of the fonts in the entry that
1926 has a glyph for the character and that matches best with the
1927 face properties. If no such font exists, proceed to the next
1930 <li> Get the character property "script" of the character. If it is
1931 inherited, get the script property from the previous
1932 characters. If there is no previous character, or none of
1933 them has the script property other than inherited, proceed to
1936 Search the text properties given to the character for the one
1937 whose key is @c Mlanguage; its value should be either a
1938 symbol specifying a language or @c Mnil.
1940 Search the mapping table of the fontset for the combination
1941 of the script and language. If no entry is found, proceed to
1944 If an entry is found, use one of the fonts in the entry that
1945 has a glyph for the character and that matches best with the
1946 face properties. If no such font exists, proceed to the next
1949 <li> Search the fall-back table of the fontset for a font that has
1950 a glyph of the character. If such a font is found, use that
1955 If no font is found by the algorithm above, this function draws an
1956 empty box for the character.
1958 This function draws only the glyph foreground. To specify the
1959 background color, use mdraw_image_text () or
1960 mdraw_text_with_control ().
1962 This function is the counterpart of <tt>XDrawString ()</tt>,
1963 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1964 in the X Window System.
1967 If the operation was successful, mdraw_text () returns 0. If an
1968 error is detected, it returns -1 and assigns an error code to the
1969 external variable #merror_code. */
1971 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1973 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1974 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1976 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1977 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1978 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1979 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1981 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1982 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1986 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1987 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1988 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1989 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1990 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1991 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1993 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1994 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1996 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1997 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1998 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2000 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2001 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2003 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2004 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2006 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2007 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2009 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2010 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2014 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2016 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2017 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2019 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2020 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2023 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2024 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2026 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2033 mdraw_image_text () */
2036 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2037 MText *mt, int from, int to)
2039 MDrawControl control;
2041 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2042 memset (&control, 0, sizeof control);
2043 control.as_image = 0;
2044 return draw_text (frame, win, x, y, mt, from, to, &control);
2051 @brief Draw an M-text on a window as an image.
2053 The mdraw_image_text () function draws the text between $FROM and
2054 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2055 coordinate ($X, $Y).
2057 The way to draw a text is the same as in mdraw_text () except that
2058 this function also draws the background with the color specified
2061 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2062 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2063 functions in the X Window System.
2066 If the operation was successful, mdraw_image_text () returns 0.
2067 If an error is detected, it returns -1 and assigns an error code
2068 to the external variable #merror_code. */
2071 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2073 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2074 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2075 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2077 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2078 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2080 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2081 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2085 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2086 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2088 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2098 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2099 MText *mt, int from, int to)
2101 MDrawControl control;
2103 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2104 memset (&control, 0, sizeof control);
2105 control.as_image = 1;
2106 return draw_text (frame, win, x, y, mt, from, to, &control);
2112 @brief Draw an M-text on a window with fine control.
2114 The mdraw_text_with_control () function draws the text between
2115 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2116 coordinate ($X, $Y).
2118 The way to draw a text is the same as in mdraw_text () except that
2119 this function also follows what specified in the drawing control
2122 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2123 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2124 breaks lines and the following characters are drawn in the next
2125 line. See the documentation of the structure @ MDrawControl for
2129 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2131 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2132 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2135 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2136 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2138 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2139 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2140 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2143 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2144 MText *mt, int from, int to, MDrawControl *control)
2146 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2147 return draw_text (frame, win, x, y, mt, from, to, control);
2153 @brief Compute text pixel width.
2155 The mdraw_text_extents () function computes the width of text
2156 between $FROM and $TO of M-text $MT when it is drawn on a window
2157 of frame $FRAME using the mdraw_text_with_control () function with
2158 the drawing control object $CONTROL.
2160 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2161 the bounding box of character ink of the M-text, and stores the
2162 results in the members of the structure pointed to by
2163 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2164 surrounding box, the box is included in the bounding box.
2166 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2167 computes the bounding box that provides minimum spacing to other
2168 graphical features (such as surrounding box) for the M-text, and
2169 stores the results in the members of the structure pointed to by
2170 $OVERALL_LOGICAL_RETURN.
2172 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2173 computes the bounding box that provides minimum spacing to the
2174 other M-text drawn, and stores the results in the members of the
2175 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2176 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2177 min_line_ascent, min_line_descent, max_line_ascent, and
2178 max_line_descent of $CONTROL are all zero.
2181 This function returns the width of the text to be drawn in the
2182 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2183 text is drawn in multiple physical lines, it returns the width of
2184 the widest line. If an error occurs, it returns -1 and assigns an
2185 error code to the external variable #merror_code. */
2189 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2191 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2192 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2193 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2195 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2196 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2197 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2198 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2200 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2201 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2202 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2203 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2205 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2206 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2207 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2208 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2209 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2210 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2213 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2214 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2215 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2217 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2224 mdraw_text_extents (MFrame *frame,
2225 MText *mt, int from, int to, MDrawControl *control,
2226 MDrawMetric *overall_ink_return,
2227 MDrawMetric *overall_logical_return,
2228 MDrawMetric *overall_line_return)
2230 MGlyphString *gstring;
2232 int width, rbearing;
2234 ASSURE_CONTROL (control);
2235 M_CHECK_POS_X (mt, from, -1);
2236 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2237 to = mtext_nchars (mt) + (control->cursor_width != 0);
2241 gstring = get_gstring (frame, mt, from, to, control);
2243 MERROR (MERROR_DRAW, -1);
2244 width = gstring_width (gstring, from, to, &rbearing);
2245 if (overall_ink_return)
2247 overall_ink_return->y = - gstring->physical_ascent;
2248 overall_ink_return->x = gstring->lbearing;
2250 if (overall_logical_return)
2252 overall_logical_return->y = - gstring->ascent;
2253 overall_logical_return->x = 0;
2255 if (overall_line_return)
2257 overall_line_return->y = - gstring->line_ascent;
2258 overall_line_return->x = gstring->lbearing;
2261 for (from = gstring->to; from < to; from = gstring->to)
2263 int this_width, this_rbearing;
2265 y += gstring->line_descent;
2266 M17N_OBJECT_UNREF (gstring->top);
2267 gstring = get_gstring (frame, mt, from, to, control);
2268 this_width = gstring_width (gstring, from, to, &this_rbearing);
2269 y += gstring->line_ascent;
2270 if (width < this_width)
2272 if (rbearing < this_rbearing)
2273 rbearing = this_rbearing;
2275 if (overall_ink_return)
2277 overall_ink_return->width = rbearing;
2278 overall_ink_return->height
2279 = y + gstring->physical_descent - overall_ink_return->y;
2281 if (overall_logical_return)
2283 overall_logical_return->width = width;
2284 overall_logical_return->height
2285 = y + gstring->descent - overall_logical_return->y;
2287 if (overall_line_return)
2289 overall_line_return->width = MAX (width, rbearing);
2290 overall_line_return->height
2291 = y + gstring->line_descent - overall_line_return->y;
2294 M17N_OBJECT_UNREF (gstring->top);
2301 @brief Compute the text dimensions of each character of M-text.
2303 The mdraw_text_per_char_extents () function computes the drawn
2304 metric of each character between $FROM and $TO of M-text $MT
2305 assuming that they are drawn on a window of frame $FRAME using the
2306 mdraw_text_with_control () function with the drawing control
2309 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2310 $LOGICAL_ARRAY_RETURN. Each successive element of
2311 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2312 ink and logical metrics of successive characters respectively,
2313 relative to the drawing origin of the M-text. The number of
2314 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2315 been set is returned to $NUM_CHARS_RETURN.
2317 If $ARRAY_SIZE is too small to return all metrics, the function
2318 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2319 Otherwise, it returns zero.
2321 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2322 @c NULL, this function also computes the metrics of the overall
2323 text and stores the results in the members of the structure
2324 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2326 If $CONTROL->two_dimensional is nonzero, this function computes
2327 only the metrics of characters in the first line. */
2329 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2331 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2332 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2333 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2335 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2336 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2337 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2338 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2339 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2341 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2342 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2345 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2346 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2347 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2349 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2352 mdraw_text_per_char_extents (MFrame *frame,
2353 MText *mt, int from, int to,
2354 MDrawControl *control,
2355 MDrawMetric *ink_array_return,
2356 MDrawMetric *logical_array_return,
2358 int *num_chars_return,
2359 MDrawMetric *overall_ink_return,
2360 MDrawMetric *overall_logical_return)
2362 MGlyphString *gstring;
2366 ASSURE_CONTROL (control);
2367 *num_chars_return = to - from;
2368 if (array_size < *num_chars_return)
2369 MERROR (MERROR_DRAW, -1);
2370 if (overall_logical_return)
2371 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2372 if (overall_ink_return)
2373 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2375 M_CHECK_RANGE (mt, from, to, -1, 0);
2376 gstring = get_gstring (frame, mt, from, to, control);
2379 *num_chars_return = 0;
2383 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2384 if (g->pos >= from && g->pos < to)
2388 int width = g->width;
2389 int lbearing = g->lbearing;
2390 int rbearing = g->rbearing;
2391 int ascent = g->ascent;
2392 int descent = g->descent;
2394 int logical_descent;
2396 if (g->rface->rfont)
2398 logical_ascent = g->rface->rfont->ascent;
2399 logical_descent = g->rface->rfont->descent;
2403 logical_ascent = g->rface->ascent;
2404 logical_descent = g->rface->descent;
2406 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2408 if (lbearing < width + g->lbearing)
2409 lbearing = width + g->lbearing;
2410 if (rbearing < width + g->rbearing)
2411 rbearing = width + g->rbearing;
2413 if (ascent < g->ascent)
2415 if (descent < g->descent)
2416 descent = g->descent;
2423 if (ink_array_return)
2425 ink_array_return[start - from].x = x + lbearing;
2426 ink_array_return[start - from].y = - ascent;
2427 ink_array_return[start - from].width = rbearing - lbearing;
2428 ink_array_return[start - from].height = ascent + descent;
2430 if (logical_array_return)
2432 logical_array_return[start - from].x = x;
2433 logical_array_return[start - from].y = - logical_descent;
2434 logical_array_return[start - from].height
2435 = logical_ascent + logical_descent;
2436 logical_array_return[start - from].width = width;
2444 if (overall_ink_return)
2446 overall_ink_return->y = - gstring->line_ascent;
2447 overall_ink_return->x = gstring->lbearing;
2448 overall_ink_return->width = x - gstring->lbearing;
2449 overall_ink_return->height = gstring->height;
2451 if (overall_logical_return)
2453 overall_logical_return->y = - gstring->ascent;
2454 overall_logical_return->x = 0;
2455 overall_logical_return->width = x;
2456 overall_logical_return->height = gstring->ascent + gstring->descent;
2459 M17N_OBJECT_UNREF (gstring->top);
2466 @brief Return the character position nearest to the coordinates.
2468 The mdraw_coordinates_position () function checks which character
2469 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2470 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2471 mdraw_text_with_control () function with the drawing control
2472 object $CONTROL. Here, the character position means the number of
2473 characters that precede the character in question in $MT, that is,
2474 the character position of the first character is 0.
2476 $FRAME is used only to get the default face information.
2479 If the glyph image of a character covers coordinate ($X, $Y),
2480 mdraw_coordinates_position () returns the character position of
2482 If $Y is less than the minimum Y-coordinate of the drawn area, it
2484 If $Y is greater than the maximum Y-coordinate of the drawn area,
2486 If $Y fits in with the drawn area but $X is less than the minimum
2487 X-coordinate, it returns the character position of the first
2488 character drawn on the line $Y.\n\n
2489 If $Y fits in with the drawn area but $X is greater than the
2490 maximum X-coordinate, it returns the character position of the
2491 last character drawn on the line $Y. */
2494 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2496 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2497 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2498 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2499 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2500 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2501 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2503 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2506 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2507 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2508 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2509 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2510 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2511 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2512 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2513 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2516 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2517 int x_offset, int y_offset, MDrawControl *control)
2519 MGlyphString *gstring;
2524 M_CHECK_POS_X (mt, from, -1);
2525 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2526 to = mtext_nchars (mt) + (control->cursor_width != 0);
2532 ASSURE_CONTROL (control);
2533 gstring = get_gstring (frame, mt, from, to, control);
2534 while (y + gstring->line_descent <= y_offset
2535 && gstring->to < to)
2538 y += gstring->line_descent;
2539 M17N_OBJECT_UNREF (gstring->top);
2540 gstring = get_gstring (frame, mt, from, to, control);
2541 y += gstring->line_ascent;
2544 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2545 if (! control->orientation_reversed)
2547 width = gstring->indent;
2548 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2549 if (g->pos >= from && g->pos < to)
2552 if (width > x_offset)
2558 width = - gstring->indent;
2559 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2560 if (g->pos >= from && g->pos < to)
2563 if (width < x_offset)
2567 if (g->type == GLYPH_ANCHOR
2568 && control->two_dimensional
2572 M17N_OBJECT_UNREF (gstring->top);
2580 @brief Compute information about a glyph.
2582 The mdraw_glyph_info () function computes information about a
2583 glyph that covers a character at position $POS of the M-text $MT
2584 assuming that the text is drawn from the character at $FROM of $MT
2585 on a window of frame $FRAME using the mdraw_text_with_control ()
2586 function with the drawing control object $CONTROL.
2588 The information is stored in the members of $INFO. */
2590 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2592 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2593 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2594 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2595 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2597 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2605 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2606 MDrawControl *control, MDrawGlyphInfo *info)
2608 MGlyphString *gstring;
2612 M_CHECK_RANGE_X (mt, from, pos, -1);
2614 ASSURE_CONTROL (control);
2615 gstring = get_gstring (frame, mt, from, pos + 1, control);
2617 MERROR (MERROR_DRAW, -1);
2618 while (gstring->to <= pos)
2620 y += gstring->line_descent;
2621 M17N_OBJECT_UNREF (gstring->top);
2622 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2623 y += gstring->line_ascent;
2625 info->line_from = gstring->from;
2626 if (info->line_from < from)
2627 info->line_from = from;
2628 info->line_to = gstring->to;
2631 if (! control->orientation_reversed)
2633 info->x = gstring->indent;
2634 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2635 info->x += g->width;
2639 info->x = - gstring->indent;
2640 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2641 info->x -= g->width;
2642 while (g[-1].to == g->to)
2645 info->from = g->pos;
2647 info->metrics.x = g->lbearing;
2648 info->metrics.y = - gstring->line_ascent;
2649 info->metrics.height = gstring->height;
2650 info->metrics.width = - g->lbearing + g->width;
2651 if (g->rface->rfont)
2652 info->font = (MFont *) g->rface->rfont;
2655 /* info->logical_width is calculated later. */
2657 if (info->from > info->line_from)
2659 /* The logically previous glyph is on this line. */
2660 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2662 info->prev_from = g_tmp->pos;
2664 else if (info->line_from > 0
2665 && gstring->from > 0)
2667 /* The logically previous glyph is on the previous line. */
2668 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2669 gstring->from, control);
2670 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2672 info->prev_from = g_tmp->pos;
2673 M17N_OBJECT_UNREF (gst->top);
2676 info->prev_from = -1;
2678 if (GLYPH_INDEX (g) > 1)
2679 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2680 else if (! control->orientation_reversed)
2682 if (info->line_from > 0)
2686 int p = gstring->from - 1;
2688 gst = get_gstring (frame, mt, p, gstring->from, control);
2689 g_tmp = gst->glyphs + (gst->used - 2);
2690 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2691 M17N_OBJECT_UNREF (gst->top);
2694 info->left_from = info->left_to = -1;
2698 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2702 int p = gstring->to;
2704 gst = get_gstring (frame, mt, p, p + 1, control);
2705 g_tmp = gst->glyphs + (gst->used - 2);
2706 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2707 M17N_OBJECT_UNREF (gst->top);
2710 info->left_from = info->left_to = -1;
2713 if (info->to < gstring->to)
2715 /* The logically next glyph is on this line. */
2716 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2718 info->next_to = g_tmp->to;
2720 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2722 /* The logically next glyph is on the next line. */
2724 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2725 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2727 info->next_to = g_tmp->to;
2728 M17N_OBJECT_UNREF (gst->top);
2733 for (info->logical_width = (g++)->width;
2734 g->pos == pos && g->type != GLYPH_ANCHOR;
2735 info->metrics.width += g->width, info->logical_width += (g++)->width);
2736 info->metrics.width += g[-1].rbearing - g[-1].width;
2738 if (g->type != GLYPH_ANCHOR)
2739 info->right_from = g->pos, info->right_to = g->to;
2740 else if (! control->orientation_reversed)
2742 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2745 M17N_OBJECT_UNREF (gstring->top);
2746 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2748 info->right_from = g->pos, info->right_to = g->to;
2751 info->right_from = info->right_to = -1;
2755 if (info->line_from > 0)
2757 pos = gstring->from - 1;
2758 M17N_OBJECT_UNREF (gstring->top);
2759 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2761 info->right_from = g->pos, info->right_to = g->to;
2764 info->right_from = info->right_to = -1;
2767 M17N_OBJECT_UNREF (gstring->top);
2774 @brief Compute information about glyph sequence.
2776 The mdraw_glyph_list () function computes information about glyphs
2777 corresponding to the text between $FROM and $TO of M-text $MT when
2778 it is drawn on a window of frame $FRAME using the
2779 mdraw_text_with_control () function with the drawing control
2780 object $CONTROL. $GLYPHS is an array of objects to store the
2781 information, and $ARRAY_SIZE is the array size.
2783 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2784 number of actually filled elements in the place pointed by
2785 $NUM_GLYPHS_RETURN, and returns 0.
2787 Otherwise, it stores the required array size in the place pointed
2788 by $NUM_GLYPHS_RETURN, and returns -1. */
2791 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2793 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2794 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2795 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2796 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2798 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2799 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2802 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2812 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2813 MDrawControl *control, MDrawGlyph *glyphs,
2814 int array_size, int *num_glyphs_return)
2816 MGlyphString *gstring;
2821 ASSURE_CONTROL (control);
2822 *num_glyphs_return = 0;
2823 M_CHECK_RANGE (mt, from, to, -1, 0);
2824 gstring = get_gstring (frame, mt, from, to, control);
2827 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2829 if (g->type == GLYPH_BOX
2830 || g->pos < from || g->pos >= to)
2832 if (g->type == GLYPH_PAD)
2834 if (g->left_padding)
2835 pad_width = g->width;
2839 glyphs[-1].x_advance += g->width;
2845 glyphs->from = g->pos;
2847 glyphs->glyph_code = g->code;
2848 glyphs->x_off = g->xoff + pad_width;
2849 glyphs->y_off = g->yoff;
2850 glyphs->lbearing = g->lbearing;
2851 glyphs->rbearing = g->rbearing;
2852 glyphs->ascent = g->ascent;
2853 glyphs->descent = g->descent;
2854 glyphs->x_advance = g->width + pad_width;
2855 glyphs->y_advance = 0;
2856 if (g->rface->rfont)
2858 glyphs->font = (MFont *) g->rface->rfont;
2860 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2861 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2863 glyphs->fontp = g->rface->rfont->fontp;
2867 glyphs->font = NULL;
2868 glyphs->font_type = Mnil;
2869 glyphs->fontp = NULL;
2876 M17N_OBJECT_UNREF (gstring->top);
2878 *num_glyphs_return = n;
2879 return (n <= array_size ? 0 : -1);
2885 @brief Draw one or more textitems.
2887 The mdraw_text_items () function draws one or more M-texts on
2888 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2889 of the textitems to be drawn and $NITEMS is the number of
2890 textitems in the array. */
2893 @brief textitem ¤òɽ¼¨¤¹¤ë.
2895 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2896 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2897 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2899 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2903 MTextItem, mdraw_text (). */
2906 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2907 MDrawTextItem *items, int nitems)
2909 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2911 while (nitems-- > 0)
2914 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2916 mdraw_text_with_control (frame, win, x, y,
2917 items->mt, 0, mtext_nchars (items->mt),
2919 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2920 items->control, NULL, NULL, NULL);
2923 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2929 @brief Option of line breaking for drawing text.
2931 The variable #mdraw_line_break_option specifies line breaking
2932 options by logical-or of the members of #MTextLineBreakOption. It
2933 controls the line breaking algorithm of the function
2934 mdraw_default_line_break (). */
2936 int mdraw_line_break_option;
2940 @brief Calculate a line breaking position.
2942 The function mdraw_default_line_break () calculates a line
2943 breaking position based on the line number $LINE and the
2944 coordinate $Y, when a line is too long to fit within the width
2945 limit. $POS is the position of the character next to the last one
2946 that fits within the limit. $FROM is the position of the first
2947 character of the line, and $TO is the position of the last
2948 character displayed on the line if there were not width limit.
2949 $LINE and $Y are reset to 0 when a line is broken by a newline
2950 character, and incremented each time when a long line is broken
2951 because of the width limit.
2953 @return This function returns a character position to break the
2958 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2960 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2961 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2962 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2963 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2964 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2965 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2966 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2969 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2973 mdraw_default_line_break (MText *mt, int pos,
2974 int from, int to, int line, int y)
2978 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2989 @brief Obtain per character dimension information.
2991 The mdraw_per_char_extents () function computes the text dimension
2992 of each character in M-text $MT. The faces given as text
2993 properties in $MT and the default face of frame $FRAME determine
2994 the fonts to draw the text. Each successive element in
2995 $ARRAY_RETURN is set to the drawn metrics of successive
2996 characters, which is relative to the origin of the drawing, and a
2997 rectangle for each character in $MT. The number of elements of
2998 $ARRAY_RETURN must be equal to or greater than the number of
3001 If pointer $OVERALL_RETURN is not @c NULL, this function also
3002 computes the extents of the overall text and stores the results in
3003 the members of the structure pointed to by $OVERALL_RETURN. */
3006 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3008 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3009 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3010 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3011 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3012 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3013 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3014 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3016 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3017 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3018 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3020 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3023 mdraw_per_char_extents (MFrame *frame, MText *mt,
3024 MDrawMetric *array_return,
3025 MDrawMetric *overall_return)
3027 int n = mtext_nchars (mt);
3029 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3030 n, &n, overall_return, NULL);
3034 @brief clear cached information.
3036 The mdraw_clear_cache () function clear cached information
3037 on M-text $MT that was attached by any of the drawing functions.
3038 When the behavior of `format' or `line_break'
3039 member functions of MDrawControl is changed, the cache must be cleared.
3044 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3046 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3047 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3048 ¤¢¤ë¤¤¤Ï `line_break'
3049 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3055 mdraw_clear_cache (MText *mt)
3057 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);