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;
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 (g->rface->rfont, g->c);
188 #endif /* HAVE_FRIBIDI */
189 g->bidi_level = levels[i];
190 for (seglen = 1, g++;
191 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
192 || glyphs[i + seglen].combining_code);
195 g->bidi_level = levels[i];
196 if (indices[i + seglen] < j)
197 j = indices[i + seglen];
199 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
205 reorder_combining_chars (MGlyphString *gstring, int from, int to)
207 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
213 for (g = gbeg; g != gend; g++)
214 if (COMBINING_CODE_CLASS (g->combining_code) > 0
215 && (COMBINING_CODE_CLASS (g[-1].combining_code)
216 > COMBINING_CODE_CLASS (g->combining_code)))
227 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
228 displaying them on FRAME.
230 This function fills these members:
231 pos, to, c, code, rface, bidi_level, categories, type, combining_code
232 The other members are filled by layout_glyph_string. */
235 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
236 MGlyphString *gstring)
238 MRealizedFace *default_rface = frame->rface;
239 int stop, face_change, language_change, charset_change;
240 MGlyph g_tmp, *g, *last_g;
242 MSymbol language = Mnil, script = Mnil, charset = Mnil;
243 MSymbol non_latin_script = Mnil;
244 MRealizedFace *rface = default_rface;
245 MRealizedFont *rfont;
246 int size = gstring->control.fixed_width;
249 MLIST_RESET (gstring);
250 gstring->from = from;
252 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
253 <category> and <rface> members.*/
256 /** Put anchor glyphs at the head and tail. */
257 g_tmp.type = GLYPH_ANCHOR;
258 g_tmp.pos = g_tmp.to = from;
259 APPEND_GLYPH (gstring, g_tmp);
260 stop = face_change = pos = from;
270 if (pos == face_change)
272 if (pos < mtext_nchars (mt))
275 int num = mtext_get_prop_values (mt, pos, Mface,
276 (void **) faces, 64);
278 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
279 if (face_change == mtext_nchars (mt))
281 rface = (num > 0 ? mface__realize (frame, faces, num, size)
285 rface = default_rface;
288 if (stop > face_change)
292 if (pos < mtext_nchars (mt))
293 c = mtext_ref_char (mt, pos);
297 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
302 category = mchar_get_prop (c, Mcategory);
303 if (category == McatCf)
304 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
305 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
306 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
308 g_tmp.category = GLYPH_CATEGORY_NORMAL;
310 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
314 ctrl[0] = ctrl[1] = g_tmp;
316 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
317 APPEND_GLYPH (gstring, ctrl[0]);
318 APPEND_GLYPH (gstring, ctrl[1]);
321 APPEND_GLYPH (gstring, g_tmp);
322 if (c == '\n' && gstring->control.two_dimensional)
325 /* Append an anchor glyph. */
327 g_tmp.type = GLYPH_ANCHOR;
328 g_tmp.pos = g_tmp.to = pos;
329 APPEND_GLYPH (gstring, g_tmp);
332 /* The next loop is to change each <rface> member for non-ASCII
333 characters if necessary. */
334 stop = charset_change = language_change = from;
335 rfont = default_rface->rfont;
336 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
342 /* Short cut for the obvious case. */
343 this_script = Mlatin;
346 this_script = (MSymbol) mchar_get_prop (c, Mscript);
347 if (this_script == Minherited || this_script == Mnil)
348 this_script = script;
349 if (this_script == Mnil)
350 this_script = non_latin_script;
351 if (this_script == Mnil)
353 /* Search forward for a character that explicitly
354 specifies a non-latin script. */
358 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
360 && (sym = mchar_get_prop (g1->c, Mscript)) != Mnil
361 && sym != Minherited)
370 if (pos == stop || script != this_script || g->rface->rfont != rfont)
373 last_g = mface__for_chars (script, language, charset,
375 script = this_script;
376 if (script != Mnil && script != Mlatin)
377 non_latin_script = script;
378 rfont = g->rface->ascii_rface->rfont;
381 if (pos < mtext_nchars (mt) && pos == language_change)
383 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
384 mtext_prop_range (mt, Mlanguage, pos, NULL,
385 &language_change, 0);
387 if (pos < mtext_nchars (mt) && pos == charset_change)
389 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
390 mtext_prop_range (mt, Mcharset, pos, NULL,
394 if (stop > language_change)
395 stop = language_change;
396 if (stop > charset_change)
397 stop = charset_change;
402 last_g = mface__for_chars (script, language, charset, last_g, g, size);
404 /* The next loop is to run FLT or perform the default combining if
406 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
410 if (this->type == GLYPH_CHAR && this->rface->rfont)
414 if (this->rface->rfont->layouter != Mnil)
419 for (prev = MGLYPH (start - 1);
420 (prev->type == GLYPH_CHAR
421 && prev->category == GLYPH_CATEGORY_FORMATTER
422 && (code = mfont__encode_char (this->rface->rfont, prev->c)
423 != MCHAR_INVALID_CODE));
428 (g->type == GLYPH_CHAR
429 && (g->rface->rfont == this->rface->rfont
430 || (g->category == GLYPH_CATEGORY_FORMATTER
431 && ((code = mfont__encode_char (this->rface->rfont,
433 != MCHAR_INVALID_CODE))));
435 if (g->rface->rfont != this->rface->rfont)
437 g->rface->rfont = this->rface->rfont;
440 i = mfont__flt_run (gstring, start, i, this->rface);
444 while (this->type == GLYPH_CHAR
446 && this->category == GLYPH_CATEGORY_MODIFIER
447 && this->rface->rfont
448 && this->rface->rfont->layouter == Mnil)
450 int class = (int) mchar_get_prop (this->c,
453 = MAKE_COMBINING_CODE_BY_CLASS (class);
457 reorder_combining_chars (gstring, start, i);
458 if (this->type == GLYPH_ANCHOR)
467 /* At last, reorder glyphs visually if necessary. */
468 if (gstring->control.enable_bidi)
469 visual_order (gstring);
474 combining_code_from_class (int class)
479 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
480 else if (class == 200) /* below left attached */
481 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
482 else if (class == 202) /* below attached*/
483 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
484 else if (class == 204) /* below right attached */
485 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
486 else if (class == 208) /* left attached */
487 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
488 else if (class == 210) /* right attached */
489 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
490 else if (class == 212) /* above left attached */
491 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
492 else if (class == 214) /* above attached */
493 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
494 else if (class == 216) /* above right attached */
495 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
496 else if (class == 218) /* below left */
497 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
498 else if (class == 220) /* below */
499 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
500 else if (class == 222) /* below right */
501 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
502 else if (class == 224) /* left */
503 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
504 else if (class == 226) /* right */
505 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
506 else if (class == 228) /* above left */
507 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
508 else if (class == 230) /* above */
509 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
510 else if (class == 232) /* above right */
511 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
512 else if (class == 233) /* double below */
513 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
514 else if (class == 234) /* double above */
515 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
516 else if (class == 240) /* iota subscript */
517 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
519 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
525 int width, lbearing, rbearing;
529 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
530 MSubTextExtents *extents)
532 int g_physical_ascent, g_physical_descent;
533 MGlyph *g = MGLYPH (from);
534 MGlyph *last_g = MGLYPH (to);
537 g_physical_ascent = gstring->physical_ascent;
538 g_physical_descent = gstring->physical_descent;
539 extents->width = extents->lbearing = extents->rbearing = 0;
541 for (i = from; i < to;)
543 if ( MGLYPH (i)->otf_encoded)
549 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
550 mfont__get_metric (gstring, j, i);
558 MRealizedFont *rfont = base->rface->rfont;
559 int size = rfont->font.property[MFONT_SIZE];
560 int width, lbearing, rbearing;
562 if (g == last_g || ! g->combining_code)
565 if (base->width == 0 && ! base->left_padding && ! base->right_padding
566 && GLYPH_INDEX (base) > from)
568 MGlyph *prev = base - 1;
570 if (base->pos < prev->pos)
571 prev->pos = base->pos;
573 base->pos = prev->pos;
574 if (base->to > prev->to)
580 if (base->left_padding && base->lbearing < 0)
582 base->xoff = - base->lbearing;
583 base->width += base->xoff;
584 base->rbearing += base->xoff;
587 if (base->right_padding && base->rbearing > base->width)
589 base->width = base->rbearing;
591 lbearing = (base->xoff + base->lbearing < 0
592 ? base->xoff + base->lbearing : 0);
593 rbearing = base->xoff + base->rbearing;
597 /* With combining glyphs. */
598 int left = -base->width;
600 int top = - base->ascent;
601 int bottom = base->descent;
602 int height = bottom - top;
603 int begin = base->pos;
608 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
609 rbearing = base->rbearing;
611 while (g != last_g && g->combining_code)
613 int combining_code = g->combining_code;
617 else if (end < g->to)
620 if (! COMBINING_PRECOMPUTED_P (combining_code))
622 int base_x, base_y, add_x, add_y, off_x, off_y;
624 if (COMBINING_BY_CLASS_P (combining_code))
625 g->combining_code = combining_code
626 = combining_code_from_class (COMBINING_CODE_CLASS
629 rfont = g->rface->rfont;
630 size = rfont->font.property[MFONT_SIZE];
631 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
633 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
635 base_x = COMBINING_CODE_BASE_X (combining_code);
636 base_y = COMBINING_CODE_BASE_Y (combining_code);
637 add_x = COMBINING_CODE_ADD_X (combining_code);
638 add_y = COMBINING_CODE_ADD_Y (combining_code);
640 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
643 if (g->xoff + g->width > right)
644 right = g->xoff + g->width;
645 width = right - left;
648 g->yoff = top + height * base_y / 2;
652 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
656 if (g->xoff + g->lbearing < left + lbearing)
657 lbearing = g->xoff + g->lbearing - left;
658 if (g->xoff + g->rbearing > left + rbearing)
659 rbearing = g->xoff + g->rbearing - left;
660 if (g->yoff - g->ascent < top)
661 top = g->yoff - g->ascent;
662 if (g->yoff + g->descent > bottom)
663 bottom = g->yoff + g->descent;
664 height = bottom - top;
670 base->ascent = - top;
671 base->descent = bottom;
672 base->lbearing = lbearing;
673 base->rbearing = rbearing;
674 if (left < - base->width)
676 base->xoff = - base->width - left;
677 base->width += base->xoff;
678 base->rbearing += base->xoff;
679 base->lbearing += base->xoff;
683 base->width += right;
684 base->rbearing += right;
685 base->right_padding = 1;
686 for (i = 1; base + i != g; i++)
687 base[i].xoff -= right;
690 for (i = 0; base + i != g; i++)
697 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
698 g_physical_descent = MAX (g_physical_descent, base->descent);
699 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
700 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
701 extents->width += base->width;
704 gstring->physical_ascent = g_physical_ascent;
705 gstring->physical_descent = g_physical_descent;
709 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
710 by this function directly. Character glyphs are handled by
711 layouter functions registered in font drivers.
713 This function fill-in all the remaining members of glyphs. */
716 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
718 /* Default width of TAB. */
719 int tab_width = frame->space_width * (gstring->control.tab_width
720 ? gstring->control.tab_width : 8);
724 MDrawControl *control = &(gstring->control);
727 int box_line_height = 0;
728 int ignore_formatting_char = control->ignore_formatting_char;
730 gstring->ascent = gstring->descent = 0;
731 gstring->physical_ascent = gstring->physical_descent = 0;
732 gstring->width = gstring->lbearing = gstring->rbearing = 0;
736 while (g->type != GLYPH_ANCHOR)
738 if (box != g->rface->box)
740 int gidx = GLYPH_INDEX (g);
744 /* Insert the right side of the box. That glyph belongs
745 to the previous grapheme cluster. */
746 MGlyph box_glyph = g[-1];
748 box_glyph.type = GLYPH_BOX;
750 = (control->fixed_width
752 : box->inner_hmargin + box->width + box->outer_hmargin);
753 box_glyph.lbearing = 0;
754 box_glyph.rbearing = box_glyph.width;
756 box_glyph.right_padding = 1;
757 gstring->width += box_glyph.width;
758 gstring->rbearing += box_glyph.width;
759 INSERT_GLYPH (gstring, gidx, box_glyph);
766 /* Insert the left side of the box. That glyph belongs
767 to the following grapheme cluster. */
768 MGlyph box_glyph = *g;
769 int box_height = (box->width
770 + box->inner_vmargin + box->outer_vmargin);
772 if (box_line_height < box_height)
773 box_line_height = box_height;
774 box_glyph.type = GLYPH_BOX;
776 = (control->fixed_width
778 : box->inner_hmargin + box->width + box->outer_hmargin);
779 box_glyph.lbearing = 0;
780 box_glyph.rbearing = box_glyph.width;
782 box_glyph.left_padding = 1;
783 gstring->width += box_glyph.width;
784 gstring->rbearing += box_glyph.width;
785 INSERT_GLYPH (gstring, gidx, box_glyph);
791 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
792 g->type = GLYPH_SPACE;
794 if (g->type == GLYPH_CHAR)
796 MRealizedFace *rface = g->rface;
797 MRealizedFont *rfont = rface->rfont;
799 int from = GLYPH_INDEX (g);
801 for (g++; g->type == GLYPH_CHAR; g++)
802 if (! rfont != ! g->rface->rfont
803 || box != g->rface->box
804 || ((fromg->code == MCHAR_INVALID_CODE)
805 != (g->code == MCHAR_INVALID_CODE))
806 || (g->category == GLYPH_CATEGORY_FORMATTER
807 && ignore_formatting_char))
809 if (rfont && fromg->code != MCHAR_INVALID_CODE)
812 int to = GLYPH_INDEX (g);
813 MSubTextExtents extents;
815 layout_glyphs (frame, gstring, from, to, &extents);
816 extra_width = - extents.lbearing;
818 && ! control->disable_overlapping_adjustment
819 && (! control->orientation_reversed
820 ? ((to > 1 || control->align_head)
821 && g->type != GLYPH_ANCHOR)
822 : (((g->type && GLYPH_ANCHOR) || control->align_head)
827 pad.type = GLYPH_PAD;
830 pad.width = pad.rbearing = extra_width;
831 pad.left_padding = 1;
832 INSERT_GLYPH (gstring, from, pad);
834 extents.lbearing = 0;
835 extents.width += extra_width;
836 extents.rbearing += extra_width;
838 g = MGLYPH (from - 1);
839 if (g->type == GLYPH_SPACE)
841 /* The pad just inserted is absorbed (maybe
842 partially) by the previous space while
843 keeping at least some space width. For the
844 moment, we use the arbitrary width 2-pixel.
845 Perhaps, it should be decided by the current
846 face, or a default value of the current
847 frame, which is, however, not yet
849 if (extra_width + 2 < g->width)
851 g->width -= extra_width;
855 extra_width = g->width - 2;
858 gstring->width -= extra_width;
859 gstring->rbearing -= extra_width;
864 extra_width = extents.rbearing - extents.width;
866 && ! control->disable_overlapping_adjustment
867 && (GLYPH_INDEX (g) < gstring->used - 1
868 || (control->orientation_reversed && control->align_head)))
870 if (g->type == GLYPH_SPACE && box == g->rface->box)
873 pad.type = GLYPH_PAD;
876 pad.width = pad.rbearing = extra_width;
877 INSERT_GLYPH (gstring, to, pad);
882 g[-1].width += extra_width;
883 extents.width += extra_width;
886 if (gstring->lbearing > gstring->width + extents.lbearing)
887 gstring->lbearing = gstring->width + extents.lbearing;
888 if (gstring->rbearing < gstring->width + extents.rbearing)
889 gstring->rbearing = gstring->width + extents.rbearing;
890 gstring->width += extents.width;
891 if (gstring->ascent < rface->ascent)
892 gstring->ascent = rface->ascent;
893 if (gstring->descent < rface->descent)
894 gstring->descent = rface->descent;
898 for (; fromg < g; fromg++)
900 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
901 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
902 fromg->width = fromg->rbearing = 1;
904 fromg->width = fromg->rbearing = rface->space_width;
905 fromg->xoff = fromg->lbearing = 0;
906 fromg->ascent = fromg->descent = 0;
907 gstring->width += fromg->width;
908 gstring->rbearing += fromg->width;
910 if (gstring->ascent < frame->rface->ascent)
911 gstring->ascent = frame->rface->ascent;
912 if (gstring->descent < frame->descent)
913 gstring->descent = frame->rface->descent;
916 else if (g->type == GLYPH_SPACE)
919 g->width = g->rface->space_width;
920 else if (g->c == '\n')
922 g->width = control->cursor_width;
925 if (control->cursor_bidi)
927 else if (g->width < 0)
928 g->width = g->rface->space_width;
931 else if (g->c == '\t')
933 g->width = tab_width - ((gstring->indent + gstring->width)
939 if (g[-1].type == GLYPH_PAD)
941 /* This space glyph absorbs (maybe partially) the
942 previous padding glyph. */
943 g->width -= g[-1].width;
945 /* But, keep at least some space width. For the
946 moment, we use the arbitrary width 2-pixel. */
949 g->rbearing = g->width;
950 gstring->width += g->width;
951 gstring->rbearing += g->width;
954 if (gstring->ascent < g->rface->ascent)
955 gstring->ascent = g->rface->ascent;
956 if (gstring->descent < g->rface->descent)
957 gstring->descent = g->rface->descent;
963 gstring->width += g->width;
964 gstring->rbearing += g->width;
971 /* Insert the right side of the box. */
972 int gidx = GLYPH_INDEX (g);
973 MGlyph box_glyph = g[-1];
975 box_glyph.type = GLYPH_BOX;
977 = (control->fixed_width
979 : box->inner_hmargin + box->width + box->outer_hmargin);
980 box_glyph.lbearing = 0;
981 box_glyph.rbearing = box_glyph.width;
983 box_glyph.right_padding = 1;
984 gstring->width += box_glyph.width;
985 gstring->rbearing += box_glyph.width;
986 INSERT_GLYPH (gstring, gidx, box_glyph);
989 gstring->text_ascent = gstring->ascent;
990 gstring->text_descent = gstring->descent;
991 if (gstring->text_ascent < gstring->physical_ascent)
992 gstring->text_ascent = gstring->physical_ascent;
993 if (gstring->text_descent < gstring->physical_descent)
994 gstring->text_descent = gstring->physical_descent;
995 gstring->line_ascent = gstring->text_ascent;
996 gstring->line_descent = gstring->text_descent;
997 if (box_line_height > 0)
999 gstring->line_ascent += box_line_height;
1000 gstring->physical_ascent = gstring->line_ascent;
1001 gstring->line_descent += box_line_height;
1002 gstring->physical_descent = gstring->line_descent;
1005 if (gstring->line_ascent < control->min_line_ascent)
1006 gstring->line_ascent = control->min_line_ascent;
1007 else if (control->max_line_ascent
1008 && control->max_line_ascent > control->min_line_ascent
1009 && gstring->line_ascent > control->max_line_ascent)
1010 gstring->line_ascent = control->max_line_ascent;
1012 if (gstring->line_descent < control->min_line_descent)
1013 gstring->line_descent = control->min_line_descent;
1014 else if (control->max_line_descent
1015 && control->max_line_descent > control->min_line_descent
1016 && gstring->line_descent > control->max_line_descent)
1017 gstring->line_descent = control->max_line_descent;
1018 gstring->height = gstring->line_ascent + gstring->line_descent;
1020 if (control->orientation_reversed
1023 /* We must adjust TAB width for RTL orientation. */
1024 width = gstring->indent;
1026 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1028 if (g->type == GLYPH_CHAR && g->c == '\t')
1030 int this_width = tab_width - (width % tab_width);
1032 if (g[1].type == GLYPH_PAD)
1033 this_width -= g[1].width;
1034 if (g[-1].type == GLYPH_PAD)
1035 this_width -= g[-1].width;
1038 gstring->width += this_width - g->width;
1039 gstring->rbearing += this_width - g->width;
1040 g->width = this_width;
1041 width += this_width;
1051 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1052 MGlyphString *gstring, int from, int to,
1053 int *from_idx, int *to_idx, int *to_x)
1055 MGlyph *g = MGLYPH (1);
1056 MDrawRegion region = (MDrawRegion) NULL;
1057 MDrawControl *control = &gstring->control;
1058 int cursor_pos = -1;
1060 int cursor_bidi = control->cursor_bidi;
1062 if (control->with_cursor && control->cursor_width)
1064 if (gstring->from <= control->cursor_pos
1065 && gstring->to > control->cursor_pos)
1066 cursor_pos = control->cursor_pos;
1069 && gstring->from <= control->cursor_pos - 1
1070 && gstring->to > control->cursor_pos - 1)
1071 prev_pos = control->cursor_pos - 1;
1074 *from_idx = *to_idx = 0;
1075 while (g->type != GLYPH_ANCHOR)
1077 if (g->pos >= from && g->pos < to)
1079 MGlyph *fromg = g, *cursor = NULL;
1080 MRealizedFace *rface = g->rface;
1082 int cursor_width = 0;
1086 *from_idx = GLYPH_INDEX (g);
1087 while (g->pos >= from && g->pos < to
1088 && g->rface == rface)
1091 if (g->type != GLYPH_BOX
1092 && g->pos <= cursor_pos && g->to > cursor_pos)
1095 cursor = g, cursor_x = x + width;
1096 cursor_width += g->width;
1098 width += g++->width;
1101 && (control->as_image
1102 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1104 int this_x = x, this_width = width;
1106 if (fromg->type == GLYPH_BOX)
1107 this_x += fromg->width, this_width -= fromg->width;
1108 if (g[-1].type == GLYPH_BOX)
1109 this_width -= g[-1].width;
1110 (frame->driver->fill_space)
1111 (frame, win, rface, 0,
1112 this_x, y - gstring->text_ascent, this_width,
1113 gstring->text_ascent + gstring->text_descent,
1114 control->clip_region);
1121 rect.y = y - gstring->text_ascent;
1122 rect.height = gstring->text_ascent + gstring->text_descent;
1125 rect.width = ((control->cursor_width > 0
1126 && control->cursor_width < cursor_width)
1127 ? control->cursor_width : cursor_width);
1131 if (cursor->bidi_level % 2)
1132 rect.x += cursor_width - rect.width;
1133 (*frame->driver->fill_space)
1134 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1135 control->clip_region);
1137 region = (*frame->driver->region_from_rect) (&rect);
1139 (*frame->driver->region_add_rect) (region, &rect);
1142 if (cursor->bidi_level % 2)
1145 rect.width = cursor_width < 4 ? cursor_width : 4;
1146 (*frame->driver->fill_space)
1147 (frame, win, rface, 1,
1148 rect.x, rect.y, rect.width, rect.height,
1149 control->clip_region);
1150 (*frame->driver->region_add_rect) (region, &rect);
1162 if (fromg->type != GLYPH_BOX
1163 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1166 cursor = fromg, cursor_x = x + temp_width;
1167 cursor_width += fromg->width;
1169 temp_width += fromg++->width;
1176 if (! (cursor->bidi_level % 2))
1177 rect.x += cursor_width - 1;
1178 rect.y = y - gstring->text_ascent;
1179 rect.height = gstring->text_ascent + gstring->text_descent;
1181 (*frame->driver->fill_space)
1182 (frame, win, rface, 1,
1183 rect.x, rect.y, rect.width, rect.height,
1184 control->clip_region);
1186 region = (*frame->driver->region_from_rect) (&rect);
1188 (*frame->driver->region_add_rect) (region, &rect);
1189 rect.y += rect.height - 2;
1191 rect.width = cursor_width < 4 ? cursor_width : 4;
1192 if (! (cursor->bidi_level % 2))
1193 rect.x -= rect.width - 1;
1194 (*frame->driver->fill_space) (frame, win, rface, 1,
1195 rect.x, rect.y, rect.width, rect.height,
1196 control->clip_region);
1197 (*frame->driver->region_add_rect) (region, &rect);
1201 *to_idx = GLYPH_INDEX (g);
1211 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1212 MGlyphString *gstring, int from_idx, int to_idx,
1213 int reverse, MDrawRegion region)
1215 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1221 (*frame->driver->region_to_rect) (region, &rect);
1224 while (g != gend && x + g->rbearing <= rect.x)
1227 width -= g++->width;
1228 while (! g->enabled && g != gend)
1232 rect.x += rect.width;
1233 if (rect.x < x + width)
1236 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1238 width -= (--gend)->width;
1239 while (! gend->enabled && g != gend)
1243 while (gend[-1].to == gend->to) gend++;
1251 MRealizedFace *rface = g->rface;
1252 int width = g->width;
1253 MGlyph *from_g = g++;
1255 /* Handle the glyphs of the same type/face at once. */
1257 && g->type == from_g->type
1258 && g->rface == rface
1259 && ((g->code == MCHAR_INVALID_CODE)
1260 == (from_g->code == MCHAR_INVALID_CODE))
1262 width += g++->width;
1264 if (from_g->type == GLYPH_CHAR)
1266 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1267 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1270 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1273 else if (from_g->type == GLYPH_BOX)
1275 /* Draw the left or right side of a box. If
1276 from_g->lbearing is nonzero, this is the left side,
1277 else this is the right side. */
1278 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1281 if (from_g->type != GLYPH_BOX)
1284 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1285 x, y, width, region);
1288 /* Draw the top and bottom side of a box. */
1289 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1290 x, y, width, region);
1301 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1302 int *from_x, int *to_x)
1305 int left_idx = *left, right_idx = *right;
1306 int left_x, right_x, x;
1308 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1311 if (x + g->rbearing > 0)
1313 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1315 left_idx = GLYPH_INDEX (g);
1320 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1323 if (x - g->width + g->lbearing < 0)
1325 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1327 right_idx = GLYPH_INDEX (g) + 1;
1332 if (*left == left_idx && *right == right_idx)
1335 if (*left != left_idx)
1337 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1342 if (*right != right_idx)
1344 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1354 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1359 if (from <= gstring->from && to >= gstring->to)
1362 *rbearing = gstring->rbearing;
1363 return gstring->width;
1368 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1369 if (g->pos >= from && g->pos < to)
1371 if (rbearing && width + g->rbearing > *rbearing)
1372 *rbearing = width + g->rbearing;
1380 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1381 MGlyphString *gstring, int from, int to)
1383 MDrawControl *control = &gstring->control;
1385 MDrawRegion clip_region, cursor_region;
1386 int from_idx, to_idx;
1389 if (control->orientation_reversed)
1390 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1392 x += gstring->indent;
1394 /* At first, draw all glyphs without cursor. */
1395 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1396 &from_idx, &to_idx, &to_x);
1398 if (control->partial_update)
1401 rect.width = to_x - x;
1402 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1404 rect.y = y - gstring->line_ascent;
1405 rect.height = gstring->height;
1406 clip_region = (*frame->driver->region_from_rect) (&rect);
1407 if (control->clip_region)
1408 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1411 clip_region = control->clip_region;
1414 clip_region = control->clip_region;
1416 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1421 (*frame->driver->intersect_region) (cursor_region, clip_region);
1422 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1425 if (clip_region != control->clip_region)
1426 (*frame->driver->free_region) (clip_region);
1428 (*frame->driver->free_region) (cursor_region);
1432 static int gstring_num;
1435 free_gstring (void *object)
1437 MGlyphString *gstring = (MGlyphString *) object;
1440 free_gstring (gstring->next);
1441 if (gstring->size > 0)
1442 free (gstring->glyphs);
1448 static MGlyphString scratch_gstring;
1450 static MGlyphString *
1451 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1454 MGlyphString *gstring;
1456 if (pos == mt->nchars)
1460 gstring = &scratch_gstring;
1461 if (gstring->size == 0)
1466 g_tmp.type = GLYPH_ANCHOR;
1467 APPEND_GLYPH (gstring, g_tmp);
1468 APPEND_GLYPH (gstring, g_tmp);
1469 APPEND_GLYPH (gstring, g_tmp);
1470 gstring->glyphs[1].type = GLYPH_SPACE;
1471 gstring->glyphs[1].c = '\n';
1472 gstring->glyphs[1].code = '\n';
1474 gstring->from = pos;
1476 g->rface = frame->rface;
1477 g->pos = g->to = pos;
1479 g->rface = frame->rface;
1480 g->pos = pos++, g->to = pos;
1482 g->rface = frame->rface;
1483 g->pos = g->to = pos;
1488 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1489 MLIST_INIT1 (gstring, glyphs, 128);
1493 gstring->frame = frame;
1494 gstring->tick = frame->tick;
1495 gstring->top = gstring;
1496 gstring->control = *control;
1497 gstring->indent = gstring->width_limit = 0;
1498 if (control->format)
1499 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1501 gstring->width_limit = control->max_line_width;
1502 gstring->anti_alias = control->anti_alias;
1506 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1509 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1517 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1518 a width of glyphs for the character at I of MT. If I is not a
1519 beginning of a grapheme cluster, the corresponding element is
1521 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1522 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1523 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1524 pos_width[g->pos - gstring->from] += g->width;
1525 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1527 if (pos_width[i] > 0)
1529 if (width + pos_width[i] > gstring->width_limit)
1532 width += pos_width[i];
1535 pos = gstring->from + i;
1536 if (gstring->control.line_break)
1538 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1539 gstring->from, gstring->from + i, 0, 0);
1540 if (pos <= gstring->from)
1541 pos = gstring->from + 1;
1542 else if (pos >= gstring->to)
1547 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1548 layout_glyph_string (frame, gstring);
1552 /* Return a gstring that covers a character at POS. */
1554 static MGlyphString *
1555 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1557 MGlyphString *gstring = NULL;
1559 if (pos < mtext_nchars (mt))
1561 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1564 && ((prop->start != 0
1565 && mtext_ref_char (mt, prop->start - 1) != '\n')
1566 || (prop->end < mtext_nchars (mt)
1567 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1569 mtext_detach_property (prop);
1574 gstring = prop->val;
1575 if (gstring->frame != frame
1576 || gstring->tick != frame->tick
1577 || memcmp (control, &gstring->control,
1578 (char *) (&control->with_cursor)
1579 - (char *) (control))
1580 || control->cursor_width != gstring->control.cursor_width
1581 || control->cursor_bidi != gstring->control.cursor_bidi)
1583 mtext_detach_property (prop);
1588 else if (! control->cursor_width)
1596 offset = mtext_character (mt, pos, 0, '\n');
1601 offset -= gstring->from;
1603 for (gst = gstring; gst; gst = gst->next)
1607 gst->from += offset;
1609 for (i = 0; i < gst->used; i++)
1611 gst->glyphs[i].pos += offset;
1612 gst->glyphs[i].to += offset;
1615 M17N_OBJECT_REF (gstring);
1620 int line = 0, y = 0;
1622 if (pos < mtext_nchars (mt))
1624 beg = mtext_character (mt, pos, 0, '\n');
1632 end = mtext_nchars (mt) + (control->cursor_width != 0);
1633 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1634 if (beg < mtext_nchars (mt))
1635 compose_glyph_string (frame, mt, beg, end, gstring);
1636 layout_glyph_string (frame, gstring);
1638 if (gstring->width_limit
1639 && gstring->width > gstring->width_limit)
1641 MGlyphString *gst = gstring;
1643 truncate_gstring (frame, mt, gst);
1644 while (gst->to < end)
1646 line++, y += gst->height;
1647 gst->next = alloc_gstring (frame, mt, gst->from, control,
1649 gst->next->top = gstring;
1650 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1652 layout_glyph_string (frame, gst);
1653 if (gst->width <= gst->width_limit)
1655 truncate_gstring (frame, mt, gst);
1659 if (! control->disable_caching && pos < mtext_nchars (mt))
1661 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1662 MTEXTPROP_VOLATILE_STRONG);
1664 if (end > mtext_nchars (mt))
1665 end = mtext_nchars (mt);
1666 mtext_attach_property (mt, beg, end, prop);
1667 M17N_OBJECT_UNREF (prop);
1671 while (gstring->to <= pos)
1673 if (! gstring->next)
1675 gstring = gstring->next;
1677 gstring->control = *control;
1683 static MDrawControl control_noop;
1685 #define ASSURE_CONTROL(control) \
1687 control = &control_noop; \
1692 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1693 MText *mt, int from, int to,
1694 MDrawControl *control)
1696 MGlyphString *gstring;
1698 M_CHECK_POS_X (mt, from, -1);
1699 ASSURE_CONTROL (control);
1700 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1701 to = mtext_nchars (mt) + (control->cursor_width != 0);
1705 gstring = get_gstring (frame, mt, from, to, control);
1707 MERROR (MERROR_DRAW, -1);
1708 render_glyph_string (frame, win, x, y, gstring, from, to);
1712 y += gstring->line_descent;
1713 M17N_OBJECT_UNREF (gstring->top);
1714 gstring = get_gstring (frame, mt, from, to, control);
1715 y += gstring->line_ascent;
1716 render_glyph_string (frame, win, x, y, gstring, from, to);
1719 M17N_OBJECT_UNREF (gstring->top);
1726 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1732 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1733 if (g->pos <= pos && g->to > pos)
1738 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1739 if (g->pos <= pos && g->to > pos)
1745 #define GET_LB_TYPE(MT, POS, LB_TYPE) \
1747 int c = mtext_ref_char ((MT), (POS)); \
1748 (LB_TYPE) = ((c == ' ' || c == '\t' || c == '\n') ? M_kinsoku_bol \
1749 : mchartable_lookup (linebreak_table, c)); \
1753 find_break_backward (MText *mt, int pos, int limit)
1760 GET_LB_TYPE (mt, pos, lb_type);
1761 if (lb_type == M_kinsoku_bol)
1762 return find_break_backward (mt, pos - 1, limit);
1763 if (lb_type == Mnil)
1767 GET_LB_TYPE (mt, pos - 1, lb_type);
1768 if (lb_type != Mnil)
1773 else if (lb_type == M_break_at_word)
1775 int beg = limit, end = mtext_nchars (mt);
1776 int in_word = mtext__word_segment (mt, pos, &beg, &end);
1780 else if (beg > limit)
1784 mtext__word_segment (mt, beg - 1, &beg, &end);
1790 GET_LB_TYPE (mt, pos - 1, lb_type);
1791 if (lb_type != M_kinsoku_eol)
1799 find_break_forward (MText *mt, int pos, int limit)
1803 GET_LB_TYPE (mt, pos, lb_type);
1804 if (lb_type == Mnil)
1809 GET_LB_TYPE (mt, pos, lb_type);
1812 else if (lb_type == M_break_at_word)
1814 int beg = 0, end = mtext_nchars (mt);
1815 int in_word = mtext__word_segment (mt, pos, &beg, &end);
1819 else if (end < limit)
1822 pos = end = mtext_nchars (mt);
1823 mtext__word_segment (mt, pos, &beg, &end);
1827 else if (lb_type == M_kinsoku_bol)
1831 GET_LB_TYPE (mt, pos, lb_type);
1832 if (lb_type != M_kinsoku_bol)
1840 /* for debugging... */
1844 dump_combining_code (int code)
1846 char *vallign = "tcbB";
1847 char *hallign = "lcr";
1853 if (COMBINING_BY_CLASS_P (code))
1854 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1855 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1856 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1857 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1858 off_x = COMBINING_CODE_OFF_X (code) - 128;
1860 sprintf (work + 2, "+%d", off_y);
1862 sprintf (work + 2, "%d", off_y);
1863 else if (off_x == 0)
1864 sprintf (work + 2, ".");
1865 p = work + strlen (work);
1867 sprintf (p, ">%d", off_x);
1869 sprintf (p, "<%d", -off_x);
1871 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1872 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1878 dump_gstring (MGlyphString *gstring, int indent)
1880 char *prefix = (char *) alloca (indent + 1);
1881 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1883 memset (prefix, 32, indent);
1886 fprintf (stderr, "(glyph-string");
1888 for (g = MGLYPH (0); g < last_g; g++)
1890 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1892 g - gstring->glyphs,
1893 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1894 : g->type == GLYPH_ANCHOR ? "ANC"
1895 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1896 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1897 dump_combining_code (g->combining_code),
1898 g->width, g->bidi_level);
1899 fprintf (stderr, ")");
1903 /* m17n-X internal APIs */
1908 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1910 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1911 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1913 Minherited = msymbol ("inherited");
1915 McatCc = msymbol ("Cc");
1916 McatCf = msymbol ("Cf");
1918 MbidiR = msymbol ("R");
1919 MbidiAL = msymbol ("AL");
1920 MbidiRLE = msymbol ("RLE");
1921 MbidiRLO = msymbol ("RLO");
1922 MbidiBN = msymbol ("BN");
1923 MbidiS = msymbol ("S");
1925 fribidi_set_mirroring (TRUE);
1928 M_break_at_space = msymbol ("bs");
1929 M_break_at_word = msymbol ("bw");
1930 M_break_at_any = msymbol ("ba");
1931 M_kinsoku_bol = msymbol ("kb");
1932 M_kinsoku_eol = msymbol ("ke");
1940 MLIST_FREE1 (&scratch_gstring, glyphs);
1941 M17N_OBJECT_UNREF (linebreak_table);
1942 linebreak_table = NULL;
1946 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1950 /*** @addtogroup m17nDraw */
1955 @brief Draw an M-text on a window.
1957 The mdraw_text () function draws the text between $FROM and $TO of
1958 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1960 The appearance of the text (size, style, color, etc) is specified
1961 by the value of the text property whose key is @c Mface. If the
1962 M-text or a part of the M-text does not have such a text property,
1963 the default face of $FRAME is used.
1965 The font used to draw a character in the M-text is selected from
1966 the value of the fontset property of a face by the following
1971 <li> Search the text properties given to the character for the one
1972 whose key is @c Mcharset; its value should be either a symbol
1973 specifying a charset or #Mnil. If the value is #Mnil,
1974 proceed to the next step.
1976 Otherwise, search the mapping table of the fontset for the
1977 charset. If no entry is found proceed to the next step.
1979 If an entry is found, use one of the fonts in the entry that
1980 has a glyph for the character and that matches best with the
1981 face properties. If no such font exists, proceed to the next
1984 <li> Get the character property "script" of the character. If it is
1985 inherited, get the script property from the previous
1986 characters. If there is no previous character, or none of
1987 them has the script property other than inherited, proceed to
1990 Search the text properties given to the character for the one
1991 whose key is @c Mlanguage; its value should be either a
1992 symbol specifying a language or @c Mnil.
1994 Search the mapping table of the fontset for the combination
1995 of the script and language. If no entry is found, proceed to
1998 If an entry is found, use one of the fonts in the entry that
1999 has a glyph for the character and that matches best with the
2000 face properties. If no such font exists, proceed to the next
2003 <li> Search the fall-back table of the fontset for a font that has
2004 a glyph of the character. If such a font is found, use that
2009 If no font is found by the algorithm above, this function draws an
2010 empty box for the character.
2012 This function draws only the glyph foreground. To specify the
2013 background color, use mdraw_image_text () or
2014 mdraw_text_with_control ().
2016 This function is the counterpart of <tt>XDrawString ()</tt>,
2017 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
2018 in the X Window System.
2021 If the operation was successful, mdraw_text () returns 0. If an
2022 error is detected, it returns -1 and assigns an error code to the
2023 external variable #merror_code. */
2025 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
2027 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
2028 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
2030 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
2031 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
2032 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
2033 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
2035 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
2036 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
2040 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
2041 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
2042 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2043 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
2044 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
2045 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2047 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
2048 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2050 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
2051 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
2052 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2054 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
2055 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
2057 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
2058 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2060 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
2061 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
2063 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
2064 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
2068 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
2070 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
2071 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
2073 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
2074 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
2077 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2078 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2080 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
2087 mdraw_image_text () */
2090 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
2091 MText *mt, int from, int to)
2093 MDrawControl control;
2095 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2096 memset (&control, 0, sizeof control);
2097 control.as_image = 0;
2098 return draw_text (frame, win, x, y, mt, from, to, &control);
2105 @brief Draw an M-text on a window as an image.
2107 The mdraw_image_text () function draws the text between $FROM and
2108 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2109 coordinate ($X, $Y).
2111 The way to draw a text is the same as in mdraw_text () except that
2112 this function also draws the background with the color specified
2115 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2116 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2117 functions in the X Window System.
2120 If the operation was successful, mdraw_image_text () returns 0.
2121 If an error is detected, it returns -1 and assigns an error code
2122 to the external variable #merror_code. */
2125 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2127 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2128 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2129 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2131 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2132 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2134 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2135 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2139 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2140 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2142 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2152 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2153 MText *mt, int from, int to)
2155 MDrawControl control;
2157 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2158 memset (&control, 0, sizeof control);
2159 control.as_image = 1;
2160 return draw_text (frame, win, x, y, mt, from, to, &control);
2166 @brief Draw an M-text on a window with fine control.
2168 The mdraw_text_with_control () function draws the text between
2169 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2170 coordinate ($X, $Y).
2172 The way to draw a text is the same as in mdraw_text () except that
2173 this function also follows what specified in the drawing control
2176 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2177 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2178 breaks lines and the following characters are drawn in the next
2179 line. See the documentation of the structure @ MDrawControl for
2183 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2185 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2186 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2189 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2190 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2192 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2193 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2194 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2197 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2198 MText *mt, int from, int to, MDrawControl *control)
2200 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2201 return draw_text (frame, win, x, y, mt, from, to, control);
2207 @brief Compute text pixel width.
2209 The mdraw_text_extents () function computes the width of text
2210 between $FROM and $TO of M-text $MT when it is drawn on a window
2211 of frame $FRAME using the mdraw_text_with_control () function with
2212 the drawing control object $CONTROL.
2214 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2215 the bounding box of character ink of the M-text, and stores the
2216 results in the members of the structure pointed to by
2217 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2218 surrounding box, the box is included in the bounding box.
2220 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2221 computes the bounding box that provides minimum spacing to other
2222 graphical features (such as surrounding box) for the M-text, and
2223 stores the results in the members of the structure pointed to by
2224 $OVERALL_LOGICAL_RETURN.
2226 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2227 computes the bounding box that provides minimum spacing to the
2228 other M-text drawn, and stores the results in the members of the
2229 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2230 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2231 min_line_ascent, min_line_descent, max_line_ascent, and
2232 max_line_descent of $CONTROL are all zero.
2235 This function returns the width of the text to be drawn in the
2236 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2237 text is drawn in multiple physical lines, it returns the width of
2238 the widest line. If an error occurs, it returns -1 and assigns an
2239 error code to the external variable #merror_code. */
2243 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2245 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2246 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2247 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2249 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2250 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2251 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2252 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2254 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2255 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2256 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2257 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2259 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2260 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2261 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2262 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2263 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2264 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2267 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2268 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2269 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2271 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2278 mdraw_text_extents (MFrame *frame,
2279 MText *mt, int from, int to, MDrawControl *control,
2280 MDrawMetric *overall_ink_return,
2281 MDrawMetric *overall_logical_return,
2282 MDrawMetric *overall_line_return)
2284 MGlyphString *gstring;
2286 int width, rbearing;
2288 ASSURE_CONTROL (control);
2289 M_CHECK_POS_X (mt, from, -1);
2290 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2291 to = mtext_nchars (mt) + (control->cursor_width != 0);
2295 gstring = get_gstring (frame, mt, from, to, control);
2297 MERROR (MERROR_DRAW, -1);
2298 width = gstring_width (gstring, from, to, &rbearing);
2299 if (overall_ink_return)
2301 overall_ink_return->y = - gstring->physical_ascent;
2302 overall_ink_return->x = gstring->lbearing;
2304 if (overall_logical_return)
2306 overall_logical_return->y = - gstring->ascent;
2307 overall_logical_return->x = 0;
2309 if (overall_line_return)
2311 overall_line_return->y = - gstring->line_ascent;
2312 overall_line_return->x = gstring->lbearing;
2315 for (from = gstring->to; from < to; from = gstring->to)
2317 int this_width, this_rbearing;
2319 y += gstring->line_descent;
2320 M17N_OBJECT_UNREF (gstring->top);
2321 gstring = get_gstring (frame, mt, from, to, control);
2322 this_width = gstring_width (gstring, from, to, &this_rbearing);
2323 y += gstring->line_ascent;
2324 if (width < this_width)
2326 if (rbearing < this_rbearing)
2327 rbearing = this_rbearing;
2329 if (overall_ink_return)
2331 overall_ink_return->width = rbearing;
2332 overall_ink_return->height
2333 = y + gstring->physical_descent - overall_ink_return->y;
2335 if (overall_logical_return)
2337 overall_logical_return->width = width;
2338 overall_logical_return->height
2339 = y + gstring->descent - overall_logical_return->y;
2341 if (overall_line_return)
2343 overall_line_return->width = MAX (width, rbearing);
2344 overall_line_return->height
2345 = y + gstring->line_descent - overall_line_return->y;
2348 M17N_OBJECT_UNREF (gstring->top);
2355 @brief Compute the text dimensions of each character of M-text.
2357 The mdraw_text_per_char_extents () function computes the drawn
2358 metric of each character between $FROM and $TO of M-text $MT
2359 assuming that they are drawn on a window of frame $FRAME using the
2360 mdraw_text_with_control () function with the drawing control
2363 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2364 $LOGICAL_ARRAY_RETURN. Each successive element of
2365 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2366 ink and logical metrics of successive characters respectively,
2367 relative to the drawing origin of the M-text. The number of
2368 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2369 been set is returned to $NUM_CHARS_RETURN.
2371 If $ARRAY_SIZE is too small to return all metrics, the function
2372 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2373 Otherwise, it returns zero.
2375 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2376 @c NULL, this function also computes the metrics of the overall
2377 text and stores the results in the members of the structure
2378 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2380 If $CONTROL->two_dimensional is nonzero, this function computes
2381 only the metrics of characters in the first line. */
2383 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2385 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2386 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2387 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2389 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2390 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2391 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2392 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2393 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2395 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2396 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2399 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2400 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2401 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2403 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2406 mdraw_text_per_char_extents (MFrame *frame,
2407 MText *mt, int from, int to,
2408 MDrawControl *control,
2409 MDrawMetric *ink_array_return,
2410 MDrawMetric *logical_array_return,
2412 int *num_chars_return,
2413 MDrawMetric *overall_ink_return,
2414 MDrawMetric *overall_logical_return)
2416 MGlyphString *gstring;
2420 ASSURE_CONTROL (control);
2421 *num_chars_return = to - from;
2422 if (array_size < *num_chars_return)
2423 MERROR (MERROR_DRAW, -1);
2424 if (overall_logical_return)
2425 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2426 if (overall_ink_return)
2427 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2429 M_CHECK_RANGE (mt, from, to, -1, 0);
2430 gstring = get_gstring (frame, mt, from, to, control);
2433 *num_chars_return = 0;
2437 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2438 if (g->pos >= from && g->pos < to)
2442 int width = g->width;
2443 int lbearing = g->lbearing;
2444 int rbearing = g->rbearing;
2445 int ascent = g->ascent;
2446 int descent = g->descent;
2448 int logical_descent;
2450 if (g->rface->rfont)
2452 logical_ascent = g->rface->rfont->ascent;
2453 logical_descent = g->rface->rfont->descent;
2457 logical_ascent = g->rface->ascent;
2458 logical_descent = g->rface->descent;
2460 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2462 if (lbearing < width + g->lbearing)
2463 lbearing = width + g->lbearing;
2464 if (rbearing < width + g->rbearing)
2465 rbearing = width + g->rbearing;
2467 if (ascent < g->ascent)
2469 if (descent < g->descent)
2470 descent = g->descent;
2477 if (ink_array_return)
2479 ink_array_return[start - from].x = x + lbearing;
2480 ink_array_return[start - from].y = - ascent;
2481 ink_array_return[start - from].width = rbearing - lbearing;
2482 ink_array_return[start - from].height = ascent + descent;
2484 if (logical_array_return)
2486 logical_array_return[start - from].x = x;
2487 logical_array_return[start - from].y = - logical_descent;
2488 logical_array_return[start - from].height
2489 = logical_ascent + logical_descent;
2490 logical_array_return[start - from].width = width;
2498 if (overall_ink_return)
2500 overall_ink_return->y = - gstring->line_ascent;
2501 overall_ink_return->x = gstring->lbearing;
2502 overall_ink_return->width = x - gstring->lbearing;
2503 overall_ink_return->height = gstring->height;
2505 if (overall_logical_return)
2507 overall_logical_return->y = - gstring->ascent;
2508 overall_logical_return->x = 0;
2509 overall_logical_return->width = x;
2510 overall_logical_return->height = gstring->ascent + gstring->descent;
2513 M17N_OBJECT_UNREF (gstring->top);
2520 @brief Return the character position nearest to the coordinates.
2522 The mdraw_coordinates_position () function checks which character
2523 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2524 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2525 mdraw_text_with_control () function with the drawing control
2526 object $CONTROL. Here, the character position means the number of
2527 characters that precede the character in question in $MT, that is,
2528 the character position of the first character is 0.
2530 $FRAME is used only to get the default face information.
2533 If the glyph image of a character covers coordinate ($X, $Y),
2534 mdraw_coordinates_position () returns the character position of
2536 If $Y is less than the minimum Y-coordinate of the drawn area, it
2538 If $Y is greater than the maximum Y-coordinate of the drawn area,
2540 If $Y fits in with the drawn area but $X is less than the minimum
2541 X-coordinate, it returns the character position of the first
2542 character drawn on the line $Y.\n\n
2543 If $Y fits in with the drawn area but $X is greater than the
2544 maximum X-coordinate, it returns the character position of the
2545 last character drawn on the line $Y. */
2548 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2550 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2551 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2552 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2553 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2554 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2555 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2557 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2560 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2561 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2562 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2563 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2564 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2565 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2566 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2567 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2570 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2571 int x_offset, int y_offset, MDrawControl *control)
2573 MGlyphString *gstring;
2578 M_CHECK_POS_X (mt, from, -1);
2579 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2580 to = mtext_nchars (mt) + (control->cursor_width != 0);
2586 ASSURE_CONTROL (control);
2587 gstring = get_gstring (frame, mt, from, to, control);
2588 while (y + gstring->line_descent <= y_offset
2589 && gstring->to < to)
2592 y += gstring->line_descent;
2593 M17N_OBJECT_UNREF (gstring->top);
2594 gstring = get_gstring (frame, mt, from, to, control);
2595 y += gstring->line_ascent;
2598 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2599 if (! control->orientation_reversed)
2601 width = gstring->indent;
2602 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2603 if (g->pos >= from && g->pos < to)
2606 if (width > x_offset)
2612 width = - gstring->indent;
2613 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2614 if (g->pos >= from && g->pos < to)
2617 if (width < x_offset)
2621 if (g->type == GLYPH_ANCHOR
2622 && control->two_dimensional
2626 M17N_OBJECT_UNREF (gstring->top);
2634 @brief Compute information about a glyph.
2636 The mdraw_glyph_info () function computes information about a
2637 glyph that covers a character at position $POS of the M-text $MT
2638 assuming that the text is drawn from the character at $FROM of $MT
2639 on a window of frame $FRAME using the mdraw_text_with_control ()
2640 function with the drawing control object $CONTROL.
2642 The information is stored in the members of $INFO. */
2644 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2646 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2647 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2648 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2649 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2651 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2659 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2660 MDrawControl *control, MDrawGlyphInfo *info)
2662 MGlyphString *gstring;
2666 M_CHECK_RANGE_X (mt, from, pos, -1);
2668 ASSURE_CONTROL (control);
2669 gstring = get_gstring (frame, mt, from, pos + 1, control);
2671 MERROR (MERROR_DRAW, -1);
2672 while (gstring->to <= pos)
2674 y += gstring->line_descent;
2675 M17N_OBJECT_UNREF (gstring->top);
2676 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2677 y += gstring->line_ascent;
2679 info->line_from = gstring->from;
2680 if (info->line_from < from)
2681 info->line_from = from;
2682 info->line_to = gstring->to;
2685 if (! control->orientation_reversed)
2687 info->x = gstring->indent;
2688 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2689 info->x += g->width;
2693 info->x = - gstring->indent;
2694 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2695 info->x -= g->width;
2696 while (g[-1].to == g->to)
2699 info->from = g->pos;
2701 info->metrics.x = g->lbearing;
2702 info->metrics.y = - gstring->line_ascent;
2703 info->metrics.height = gstring->height;
2704 info->metrics.width = - g->lbearing + g->width;
2705 if (g->rface->rfont)
2706 info->font = &g->rface->rfont->font;
2709 /* info->logical_width is calculated later. */
2711 if (info->from > info->line_from)
2713 /* The logically previous glyph is on this line. */
2714 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2716 info->prev_from = g_tmp->pos;
2718 else if (info->line_from > 0)
2720 /* The logically previous glyph is on the previous line. */
2721 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2722 gstring->from, control);
2723 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2725 info->prev_from = g_tmp->pos;
2726 M17N_OBJECT_UNREF (gst->top);
2729 info->prev_from = -1;
2731 if (GLYPH_INDEX (g) > 1)
2732 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2733 else if (! control->orientation_reversed)
2735 if (info->line_from > 0)
2739 int p = gstring->from - 1;
2741 gst = get_gstring (frame, mt, p, gstring->from, control);
2742 g_tmp = gst->glyphs + (gst->used - 2);
2743 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2744 M17N_OBJECT_UNREF (gst->top);
2747 info->left_from = info->left_to = -1;
2751 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2755 int p = gstring->to;
2757 gst = get_gstring (frame, mt, p, p + 1, control);
2758 g_tmp = gst->glyphs + (gst->used - 2);
2759 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2760 M17N_OBJECT_UNREF (gst->top);
2763 info->left_from = info->left_to = -1;
2766 if (info->to < gstring->to)
2768 /* The logically next glyph is on this line. */
2769 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2771 info->next_to = g_tmp->to;
2773 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2775 /* The logically next glyph is on the next line. */
2777 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2778 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2780 info->next_to = g_tmp->to;
2781 M17N_OBJECT_UNREF (gst->top);
2786 for (info->logical_width = (g++)->width;
2787 g->pos == pos && g->type != GLYPH_ANCHOR;
2788 info->metrics.width += g->width, info->logical_width += (g++)->width);
2789 info->metrics.width += g[-1].rbearing - g[-1].width;
2791 if (g->type != GLYPH_ANCHOR)
2792 info->right_from = g->pos, info->right_to = g->to;
2793 else if (! control->orientation_reversed)
2795 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2798 M17N_OBJECT_UNREF (gstring->top);
2799 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2801 info->right_from = g->pos, info->right_to = g->to;
2804 info->right_from = info->right_to = -1;
2808 if (info->line_from > 0)
2810 pos = gstring->from - 1;
2811 M17N_OBJECT_UNREF (gstring->top);
2812 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2814 info->right_from = g->pos, info->right_to = g->to;
2817 info->right_from = info->right_to = -1;
2820 M17N_OBJECT_UNREF (gstring->top);
2827 @brief Compute information about glyph sequence.
2829 The mdraw_glyph_list () function computes information about glyphs
2830 corresponding to the text between $FROM and $TO of M-text $MT when
2831 it is drawn on a window of frame $FRAME using the
2832 mdraw_text_with_control () function with the drawing control
2833 object $CONTROL. $GLYPHS is an array of objects to store the
2834 information, and $ARRAY_SIZE is the array size.
2836 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2837 number of actually filled elements in the place pointed by
2838 $NUM_GLYPHS_RETURN, and returns 0.
2840 Otherwise, it stores the required array size in the place pointed
2841 by $NUM_GLYPHS_RETURN, and returns -1. */
2844 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2846 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2847 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2848 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2849 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2851 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2852 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2855 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2865 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2866 MDrawControl *control, MDrawGlyph *glyphs,
2867 int array_size, int *num_glyphs_return)
2869 MGlyphString *gstring;
2874 ASSURE_CONTROL (control);
2875 *num_glyphs_return = 0;
2876 M_CHECK_RANGE (mt, from, to, -1, 0);
2877 gstring = get_gstring (frame, mt, from, to, control);
2880 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2882 if (g->type == GLYPH_BOX
2883 || g->pos < from || g->pos >= to)
2885 if (g->type == GLYPH_PAD)
2887 if (g->left_padding)
2888 pad_width = g->width;
2892 glyphs[-1].x_advance += g->width;
2898 glyphs->from = g->pos;
2900 glyphs->glyph_code = g->code;
2901 glyphs->x_off = g->xoff + pad_width;
2902 glyphs->y_off = g->yoff;
2903 glyphs->lbearing = g->lbearing;
2904 glyphs->rbearing = g->rbearing;
2905 glyphs->ascent = g->ascent;
2906 glyphs->descent = g->descent;
2907 glyphs->x_advance = g->width + pad_width;
2908 glyphs->y_advance = 0;
2909 if (g->rface->rfont)
2911 glyphs->font = &g->rface->rfont->font;
2912 glyphs->font_type = g->rface->rfont->type;
2913 glyphs->fontp = g->rface->rfont->fontp;
2917 glyphs->font = NULL;
2918 glyphs->font_type = Mnil;
2919 glyphs->fontp = NULL;
2926 M17N_OBJECT_UNREF (gstring->top);
2928 *num_glyphs_return = n;
2929 return (n <= array_size ? 0 : -1);
2935 @brief Draw one or more textitems.
2937 The mdraw_text_items () function draws one or more M-texts on
2938 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2939 of the textitems to be drawn and $NITEMS is the number of
2940 textitems in the array. */
2943 @brief textitem ¤òɽ¼¨¤¹¤ë.
2945 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2946 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2947 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2949 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2953 MTextItem, mdraw_text (). */
2956 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2957 MDrawTextItem *items, int nitems)
2959 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2961 while (nitems-- > 0)
2964 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2966 mdraw_text_with_control (frame, win, x, y,
2967 items->mt, 0, mtext_nchars (items->mt),
2969 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2970 items->control, NULL, NULL, NULL);
2973 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2979 @brief calculate a line breaking position.
2981 The function mdraw_default_line_break () calculates a line
2982 breaking position based on the line number $LINE and the
2983 coordinate $Y, when a line is too long to fit within the width
2984 limit. $POS is the position of the character next to the last
2985 one that fits within the limit. $FROM is the position of the
2986 first character of the line, and $TO is the position of the last
2987 character displayed on the line if there were not width limit.
2988 $LINE and $Y are reset to 0 when a line is broken by a newline
2989 character, and incremented each time when a long line is broken
2990 because of the width limit.
2993 This function returns a character position to break the
2998 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
3000 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
3001 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
3002 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
3003 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
3004 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
3005 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
3006 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
3009 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
3013 mdraw_default_line_break (MText *mt, int pos,
3014 int from, int to, int line, int y)
3018 if (! linebreak_table)
3020 MDatabase *mdb = mdatabase_find (Mchar_table, Msymbol,
3021 msymbol ("linebreak"), Mnil);
3024 linebreak_table = mdatabase_load (mdb);
3025 if (! linebreak_table)
3026 linebreak_table = mchartable (Msymbol, Mnil);
3031 p = find_break_backward (mt, pos, from);
3037 p = find_break_forward (mt, pos, to);
3047 @brief Obtain per character dimension information.
3049 The mdraw_per_char_extents () function computes the text dimension
3050 of each character in M-text $MT. The faces given as text
3051 properties in $MT and the default face of frame $FRAME determine
3052 the fonts to draw the text. Each successive element in
3053 $ARRAY_RETURN is set to the drawn metrics of successive
3054 characters, which is relative to the origin of the drawing, and a
3055 rectangle for each character in $MT. The number of elements of
3056 $ARRAY_RETURN must be equal to or greater than the number of
3059 If pointer $OVERALL_RETURN is not @c NULL, this function also
3060 computes the extents of the overall text and stores the results in
3061 the members of the structure pointed to by $OVERALL_RETURN. */
3064 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
3066 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
3067 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
3068 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
3069 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
3070 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
3071 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
3072 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
3074 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
3075 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
3076 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
3078 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
3081 mdraw_per_char_extents (MFrame *frame, MText *mt,
3082 MDrawMetric *array_return,
3083 MDrawMetric *overall_return)
3085 int n = mtext_nchars (mt);
3087 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
3088 n, &n, overall_return, NULL);
3092 @brief clear cached information.
3094 The mdraw_clear_cache () function clear cached information
3095 on M-text $MT that was attached by any of the drawing functions.
3096 When the behavior of `format' or `line_break'
3097 member functions of MDrawControl is changed, the cache must be cleared.
3102 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3104 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
3105 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
3106 ¤¢¤ë¤¤¤Ï `line_break'
3107 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3113 mdraw_clear_cache (MText *mt)
3115 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);