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 layouting
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face ¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å
44 ¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É
45 ¤¨¤â face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆó¼¡
48 ¸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
53 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
54 /*** @addtogroup m17nInternal
61 #include <sys/types.h>
65 #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;
88 /* Glyph-string composer. */
90 static MSymbol MbidiR;
91 static MSymbol MbidiAL;
92 static MSymbol MbidiRLE;
93 static MSymbol MbidiRLO;
94 static MSymbol MbidiBN;
95 static MSymbol MbidiS;
98 visual_order (MGlyphString *gstring)
100 int len = gstring->used - 2;
102 int bidi_sensitive = gstring->control.orientation_reversed;
106 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
107 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
109 FriBidiStrIndex *indices;
110 FriBidiLevel *levels;
111 #else /* not HAVE_FRIBIDI */
112 int *logical = alloca (sizeof (int) * len);
114 char *levels = alloca (len);
115 #endif /* not HAVE_FRIBIDI */
117 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
122 #endif /* not HAVE_FRIBIDI */
125 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
127 if (bidi == MbidiR || bidi == MbidiAL
128 || bidi == MbidiRLE || bidi == MbidiRLO)
133 #endif /* not HAVE_FRIBIDI */
139 if (! bidi_sensitive)
142 glyphs = alloca (sizeof (MGlyph) * len);
143 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
145 visual = alloca (sizeof (FriBidiChar) * (len + 1));
146 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
147 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
149 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
150 #else /* not HAVE_FRIBIDI */
151 indices = alloca (sizeof (int) * len);
152 for (i = 0; i < len; i++)
158 for (j = i + 1; j < len && levels[j]; j++);
159 for (k = j--; i < k; i++, j--)
166 #endif /* not HAVE_FRIBIDI */
168 for (i = 0; i < len;)
170 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
172 /* Length of grapheme-cluster */
177 if (visual[j] != logical[i])
182 g->code = mfont__encode_char (g->rface->rfont, g->c);
184 #endif /* HAVE_FRIBIDI */
185 g->bidi_level = levels[i];
186 for (seglen = 1, g++;
187 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
188 || glyphs[i + seglen].combining_code);
191 g->bidi_level = levels[i];
192 if (indices[i + seglen] < j)
193 j = indices[i + seglen];
195 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
201 reorder_combining_chars (MGlyphString *gstring, int from, int to)
203 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
209 for (g = gbeg; g != gend; g++)
210 if (COMBINING_CODE_CLASS (g->combining_code) > 0
211 && (COMBINING_CODE_CLASS (g[-1].combining_code)
212 > COMBINING_CODE_CLASS (g->combining_code)))
223 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
224 displaying them on FRAME.
226 This function fills these members:
227 pos, to, c, code, rface, bidi_level, categories, type, combining_code
228 The other members are filled by layout_glyph_string. */
231 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
232 MGlyphString *gstring)
234 MRealizedFace *default_rface = frame->rface;
235 int stop, face_change, language_change, charset_change;
236 MGlyph g_tmp, *g, *last_g;
238 MSymbol language = Mnil, script = Mnil, charset = Mnil;
239 MSymbol non_latin_script = Mnil;
240 MRealizedFace *rface = default_rface;
241 MRealizedFont *rfont;
242 int size = gstring->control.fixed_width;
245 MLIST_RESET (gstring);
246 gstring->from = from;
248 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
249 <category> and <rface> members.*/
252 /** Put anchor glyphs at the head and tail. */
253 g_tmp.type = GLYPH_ANCHOR;
254 g_tmp.pos = g_tmp.to = from;
255 APPEND_GLYPH (gstring, g_tmp);
256 stop = face_change = pos = from;
266 if (pos == face_change)
269 int num = mtext_get_prop_values (mt, pos, Mface,
270 (void **) faces, 64);
272 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
273 rface = (num > 0 ? mface__realize (frame, faces, num, size)
277 if (stop > face_change)
281 if (pos < mtext_nchars (mt))
282 c = mtext_ref_char (mt, pos);
286 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
291 category = mchar_get_prop (c, Mcategory);
292 if (category == McatCf)
293 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
294 else if (MSYMBOL_NAME (category)[0] == 'M')
295 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
297 g_tmp.category = GLYPH_CATEGORY_NORMAL;
299 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
303 ctrl[0] = ctrl[1] = g_tmp;
305 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
306 APPEND_GLYPH (gstring, ctrl[0]);
307 APPEND_GLYPH (gstring, ctrl[1]);
310 APPEND_GLYPH (gstring, g_tmp);
311 if (c == '\n' && gstring->control.two_dimensional)
314 /* Append an anchor glyph. */
316 g_tmp.type = GLYPH_ANCHOR;
317 g_tmp.pos = g_tmp.to = pos;
318 APPEND_GLYPH (gstring, g_tmp);
321 /* The next loop is to change each <rface> member for non-ASCII
322 characters if necessary. */
323 stop = charset_change = language_change = from;
324 rfont = default_rface->rfont;
325 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
331 /* Short cut for the obvious case. */
332 this_script = Mlatin;
335 this_script = (MSymbol) mchar_get_prop (c, Mscript);
336 if (this_script == Minherited || this_script == Mnil)
337 this_script = script;
338 if (this_script == Mnil)
339 this_script = non_latin_script;
340 if (this_script == Mnil)
342 /* Search forward for a character that explicitly
343 specifies a non-latin script. */
347 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
349 && (sym = mchar_get_prop (g1->c, Mscript)) != Mnil
350 && sym != Minherited)
359 if (pos == stop || script != this_script || g->rface->rfont != rfont)
362 last_g = mface__for_chars (script, language, charset,
364 script = this_script;
365 if (script != Mnil && script != Mlatin)
366 non_latin_script = script;
367 rfont = g->rface->ascii_rface->rfont;
370 if (pos < mtext_nchars (mt) && pos == language_change)
372 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
373 mtext_prop_range (mt, Mlanguage, pos, NULL,
374 &language_change, 0);
376 if (pos < mtext_nchars (mt) && pos == charset_change)
378 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
379 mtext_prop_range (mt, Mcharset, pos, NULL,
383 if (stop > language_change)
384 stop = language_change;
385 if (stop > charset_change)
386 stop = charset_change;
391 last_g = mface__for_chars (script, language, charset, last_g, g, size);
393 /* The next loop is to run FLT or perform the default combining if
395 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
399 if (this->type == GLYPH_CHAR && this->rface->rfont)
403 if (this->rface->rfont->layouter != Mnil)
408 for (prev = MGLYPH (start - 1);
409 (prev->type == GLYPH_CHAR
410 && prev->category == GLYPH_CATEGORY_FORMATTER
411 && (code = mfont__encode_char (this->rface->rfont, prev->c)
412 != MCHAR_INVALID_CODE));
417 (g->type == GLYPH_CHAR
418 && (g->rface->rfont == this->rface->rfont
419 || (g->category == GLYPH_CATEGORY_FORMATTER
420 && ((code = mfont__encode_char (this->rface->rfont,
422 != MCHAR_INVALID_CODE))));
424 if (g->rface->rfont != this->rface->rfont)
426 g->rface->rfont = this->rface->rfont;
429 i = mfont__flt_run (gstring, start, i, this->rface);
433 while (this->type == GLYPH_CHAR
435 && this->category == GLYPH_CATEGORY_MODIFIER
436 && this->rface->rfont
437 && this->rface->rfont->layouter == Mnil)
439 int class = (int) mchar_get_prop (this->c,
442 = MAKE_COMBINING_CODE_BY_CLASS (class);
446 reorder_combining_chars (gstring, start, i);
447 if (this->type == GLYPH_ANCHOR)
456 /* At last, reorder glyphs visually if necessary. */
457 if (gstring->control.enable_bidi)
458 visual_order (gstring);
463 combining_code_from_class (int class)
468 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
469 else if (class == 200) /* below left attached */
470 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
471 else if (class == 202) /* below attached*/
472 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
473 else if (class == 204) /* below right attached */
474 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
475 else if (class == 208) /* left attached */
476 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
477 else if (class == 210) /* right attached */
478 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
479 else if (class == 212) /* above left attached */
480 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
481 else if (class == 214) /* above attached */
482 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
483 else if (class == 216) /* above right attached */
484 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
485 else if (class == 218) /* below left */
486 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
487 else if (class == 220) /* below */
488 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
489 else if (class == 222) /* below right */
490 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
491 else if (class == 224) /* left */
492 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
493 else if (class == 226) /* right */
494 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
495 else if (class == 228) /* above left */
496 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
497 else if (class == 230) /* above */
498 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
499 else if (class == 232) /* above right */
500 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
501 else if (class == 233) /* double below */
502 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
503 else if (class == 234) /* double above */
504 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
505 else if (class == 240) /* iota subscript */
506 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
508 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
514 int width, lbearing, rbearing;
518 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
519 MSubTextExtents *extents)
521 int g_physical_ascent, g_physical_descent;
522 MGlyph *g = MGLYPH (from);
523 MGlyph *last_g = MGLYPH (to);
526 g_physical_ascent = gstring->physical_ascent;
527 g_physical_descent = gstring->physical_descent;
528 extents->width = extents->lbearing = extents->rbearing = 0;
530 for (i = from; i < to;)
532 if ( MGLYPH (i)->otf_encoded)
538 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
539 mfont__get_metric (gstring, j, i);
547 MRealizedFont *rfont = base->rface->rfont;
548 int size = rfont->font.property[MFONT_SIZE];
549 int width, lbearing, rbearing;
551 if (g == last_g || ! g->combining_code)
554 if (base->width == 0 && ! base->left_padding && ! base->right_padding
555 && GLYPH_INDEX (base) > from)
557 MGlyph *prev = base - 1;
559 if (base->pos < prev->pos)
560 prev->pos = base->pos;
562 base->pos = prev->pos;
563 if (base->to > prev->to)
569 if (base->left_padding && base->lbearing < 0)
571 base->xoff = - base->lbearing;
572 base->width += base->xoff;
573 base->rbearing += base->xoff;
576 if (base->right_padding && base->rbearing > base->width)
578 base->width = base->rbearing;
580 lbearing = (base->xoff + base->lbearing < 0
581 ? base->xoff + base->lbearing : 0);
582 rbearing = base->xoff + base->rbearing;
586 /* With combining glyphs. */
587 int left = -base->width;
589 int top = - base->ascent;
590 int bottom = base->descent;
591 int height = bottom - top;
592 int begin = base->pos;
597 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
598 rbearing = base->rbearing;
600 while (g != last_g && g->combining_code)
602 int combining_code = g->combining_code;
606 else if (end < g->to)
609 if (! COMBINING_PRECOMPUTED_P (combining_code))
611 int base_x, base_y, add_x, add_y, off_x, off_y;
613 if (COMBINING_BY_CLASS_P (combining_code))
614 g->combining_code = combining_code
615 = combining_code_from_class (COMBINING_CODE_CLASS
618 rfont = g->rface->rfont;
619 size = rfont->font.property[MFONT_SIZE];
620 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
622 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
624 base_x = COMBINING_CODE_BASE_X (combining_code);
625 base_y = COMBINING_CODE_BASE_Y (combining_code);
626 add_x = COMBINING_CODE_ADD_X (combining_code);
627 add_y = COMBINING_CODE_ADD_Y (combining_code);
629 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
632 if (g->xoff + g->width > right)
633 right = g->xoff + g->width;
634 width = right - left;
637 g->yoff = top + height * base_y / 2;
641 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
645 if (g->xoff + g->lbearing < left + lbearing)
646 lbearing = g->xoff + g->lbearing - left;
647 if (g->xoff + g->rbearing > left + rbearing)
648 rbearing = g->xoff + g->rbearing - left;
649 if (g->yoff - g->ascent < top)
650 top = g->yoff - g->ascent;
651 if (g->yoff + g->descent > bottom)
652 bottom = g->yoff + g->descent;
653 height = bottom - top;
659 base->ascent = - top;
660 base->descent = bottom;
661 base->lbearing = lbearing;
662 base->rbearing = rbearing;
663 if (left < - base->width)
665 base->xoff = - base->width - left;
666 base->width += base->xoff;
667 base->rbearing += base->xoff;
668 base->lbearing += base->xoff;
672 base->width += right;
673 base->rbearing += right;
674 base->right_padding = 1;
675 for (i = 1; base + i != g; i++)
676 base[i].xoff -= right;
679 for (i = 0; base + i != g; i++)
686 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
687 g_physical_descent = MAX (g_physical_descent, base->descent);
688 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
689 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
690 extents->width += base->width;
693 gstring->physical_ascent = g_physical_ascent;
694 gstring->physical_descent = g_physical_descent;
698 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
699 by this function directly. Character glyphs are handled by
700 layouter functions registered in font drivers.
702 This function fill-in all the remaining members of glyphs. */
705 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
707 /* Default width of TAB. */
708 int tab_width = frame->space_width * (gstring->control.tab_width
709 ? gstring->control.tab_width : 8);
713 MDrawControl *control = &(gstring->control);
716 int box_line_height = 0;
717 int ignore_formatting_char = control->ignore_formatting_char;
719 gstring->ascent = gstring->descent = 0;
720 gstring->physical_ascent = gstring->physical_descent = 0;
721 gstring->width = gstring->lbearing = gstring->rbearing = 0;
725 while (g->type != GLYPH_ANCHOR)
727 if (box != g->rface->box)
729 int gidx = GLYPH_INDEX (g);
733 /* Insert the right side of the box. That glyph belongs
734 to the previous grapheme cluster. */
735 MGlyph box_glyph = g[-1];
737 box_glyph.type = GLYPH_BOX;
739 = (control->fixed_width
741 : box->inner_hmargin + box->width + box->outer_hmargin);
742 box_glyph.lbearing = 0;
743 box_glyph.rbearing = box_glyph.width;
745 box_glyph.right_padding = 1;
746 gstring->width += box_glyph.width;
747 gstring->rbearing += box_glyph.width;
748 INSERT_GLYPH (gstring, gidx, box_glyph);
755 /* Insert the left side of the box. That glyph belongs
756 to the following grapheme cluster. */
757 MGlyph box_glyph = *g;
758 int box_height = (box->width
759 + box->inner_vmargin + box->outer_vmargin);
761 if (box_line_height < box_height)
762 box_line_height = box_height;
763 box_glyph.type = GLYPH_BOX;
765 = (control->fixed_width
767 : box->inner_hmargin + box->width + box->outer_hmargin);
768 box_glyph.lbearing = 0;
769 box_glyph.rbearing = box_glyph.width;
771 box_glyph.left_padding = 1;
772 gstring->width += box_glyph.width;
773 gstring->rbearing += box_glyph.width;
774 INSERT_GLYPH (gstring, gidx, box_glyph);
780 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
781 g->type = GLYPH_SPACE;
783 if (g->type == GLYPH_CHAR)
785 MRealizedFace *rface = g->rface;
786 MRealizedFont *rfont = rface->rfont;
788 int from = GLYPH_INDEX (g);
790 for (g++; g->type == GLYPH_CHAR; g++)
791 if (! rfont != ! g->rface->rfont
792 || box != g->rface->box
793 || ((fromg->code == MCHAR_INVALID_CODE)
794 != (g->code == MCHAR_INVALID_CODE))
795 || (g->category == GLYPH_CATEGORY_FORMATTER
796 && ignore_formatting_char))
798 if (rfont && fromg->code != MCHAR_INVALID_CODE)
801 int to = GLYPH_INDEX (g);
802 MSubTextExtents extents;
804 layout_glyphs (frame, gstring, from, to, &extents);
805 extra_width = - extents.lbearing;
807 && ! control->disable_overlapping_adjustment
808 && (! control->orientation_reversed
809 ? ((to > 1 || control->align_head)
810 && g->type != GLYPH_ANCHOR)
811 : (((g->type && GLYPH_ANCHOR) || control->align_head)
816 pad.type = GLYPH_PAD;
819 pad.width = pad.rbearing = extra_width;
820 pad.left_padding = 1;
821 INSERT_GLYPH (gstring, from, pad);
823 extents.lbearing = 0;
824 extents.width += extra_width;
825 extents.rbearing += extra_width;
827 g = MGLYPH (from - 1);
828 if (g->type == GLYPH_SPACE)
830 /* The pad just inserted is absorbed (maybe
831 partially) by the previous space while
832 keeping at least some space width. For the
833 moment, we use the arbitrary width 2-pixel.
834 Perhaps, it should be decided by the current
835 face, or a default value of the current
836 frame, which is, however, not yet
838 if (extra_width + 2 < g->width)
840 g->width -= extra_width;
844 extra_width = g->width - 2;
847 gstring->width -= extra_width;
848 gstring->rbearing -= extra_width;
853 extra_width = extents.rbearing - extents.width;
855 && ! control->disable_overlapping_adjustment
856 && (GLYPH_INDEX (g) < gstring->used - 1
857 || (control->orientation_reversed && control->align_head)))
859 if (g->type == GLYPH_SPACE && box == g->rface->box)
862 pad.type = GLYPH_PAD;
865 pad.width = pad.rbearing = extra_width;
866 INSERT_GLYPH (gstring, to, pad);
871 g[-1].width += extra_width;
872 extents.width += extra_width;
875 if (gstring->lbearing > gstring->width + extents.lbearing)
876 gstring->lbearing = gstring->width + extents.lbearing;
877 if (gstring->rbearing < gstring->width + extents.rbearing)
878 gstring->rbearing = gstring->width + extents.rbearing;
879 gstring->width += extents.width;
880 if (gstring->ascent < rface->ascent)
881 gstring->ascent = rface->ascent;
882 if (gstring->descent < rface->descent)
883 gstring->descent = rface->descent;
887 for (; fromg < g; fromg++)
889 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
890 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
891 fromg->width = fromg->rbearing = 1;
893 fromg->width = fromg->rbearing = rface->space_width;
894 fromg->xoff = fromg->lbearing = 0;
895 fromg->ascent = fromg->descent = 0;
896 gstring->width += fromg->width;
897 gstring->rbearing += fromg->width;
899 if (gstring->ascent < frame->rface->ascent)
900 gstring->ascent = frame->rface->ascent;
901 if (gstring->descent < frame->descent)
902 gstring->descent = frame->rface->descent;
905 else if (g->type == GLYPH_SPACE)
908 g->width = g->rface->space_width;
909 else if (g->c == '\n')
911 g->width = control->cursor_width;
914 if (control->cursor_bidi)
916 else if (g->width < 0)
917 g->width = g->rface->space_width;
920 else if (g->c == '\t')
922 g->width = tab_width - ((gstring->indent + gstring->width)
928 if (g[-1].type == GLYPH_PAD)
930 /* This space glyph absorbs (maybe partially) the
931 previous padding glyph. */
932 g->width -= g[-1].width;
934 /* But, keep at least some space width. For the
935 moment, we use the arbitrary width 2-pixel. */
938 g->rbearing = g->width;
939 gstring->width += g->width;
940 gstring->rbearing += g->width;
943 if (gstring->ascent < g->rface->ascent)
944 gstring->ascent = g->rface->ascent;
945 if (gstring->descent < g->rface->descent)
946 gstring->descent = g->rface->descent;
952 gstring->width += g->width;
953 gstring->rbearing += g->width;
960 /* Insert the right side of the box. */
961 int gidx = GLYPH_INDEX (g);
962 MGlyph box_glyph = g[-1];
964 box_glyph.type = GLYPH_BOX;
966 = (control->fixed_width
968 : box->inner_hmargin + box->width + box->outer_hmargin);
969 box_glyph.lbearing = 0;
970 box_glyph.rbearing = box_glyph.width;
972 box_glyph.right_padding = 1;
973 gstring->width += box_glyph.width;
974 gstring->rbearing += box_glyph.width;
975 INSERT_GLYPH (gstring, gidx, box_glyph);
978 gstring->text_ascent = gstring->ascent;
979 gstring->text_descent = gstring->descent;
980 if (gstring->text_ascent < gstring->physical_ascent)
981 gstring->text_ascent = gstring->physical_ascent;
982 if (gstring->text_descent < gstring->physical_descent)
983 gstring->text_descent = gstring->physical_descent;
984 gstring->line_ascent = gstring->text_ascent;
985 gstring->line_descent = gstring->text_descent;
986 if (box_line_height > 0)
988 gstring->line_ascent += box_line_height;
989 gstring->physical_ascent = gstring->line_ascent;
990 gstring->line_descent += box_line_height;
991 gstring->physical_descent = gstring->line_descent;
994 if (gstring->line_ascent < control->min_line_ascent)
995 gstring->line_ascent = control->min_line_ascent;
996 else if (control->max_line_ascent
997 && control->max_line_ascent > control->min_line_ascent
998 && gstring->line_ascent > control->max_line_ascent)
999 gstring->line_ascent = control->max_line_ascent;
1001 if (gstring->line_descent < control->min_line_descent)
1002 gstring->line_descent = control->min_line_descent;
1003 else if (control->max_line_descent
1004 && control->max_line_descent > control->min_line_descent
1005 && gstring->line_descent > control->max_line_descent)
1006 gstring->line_descent = control->max_line_descent;
1007 gstring->height = gstring->line_ascent + gstring->line_descent;
1009 if (control->orientation_reversed
1012 /* We must adjust TAB width for RTL orientation. */
1013 width = gstring->indent;
1015 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1017 if (g->type == GLYPH_CHAR && g->c == '\t')
1019 int this_width = tab_width - (width % tab_width);
1021 if (g[1].type == GLYPH_PAD)
1022 this_width -= g[1].width;
1023 if (g[-1].type == GLYPH_PAD)
1024 this_width -= g[-1].width;
1027 gstring->width += this_width - g->width;
1028 gstring->rbearing += this_width - g->width;
1029 g->width = this_width;
1030 width += this_width;
1040 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1041 MGlyphString *gstring, int from, int to,
1042 int *from_idx, int *to_idx, int *to_x)
1044 MGlyph *g = MGLYPH (1);
1045 MDrawRegion region = (MDrawRegion) NULL;
1046 MDrawControl *control = &gstring->control;
1047 int cursor_pos = -1;
1049 int cursor_bidi = control->cursor_bidi;
1051 if (control->with_cursor && control->cursor_width)
1053 if (gstring->from <= control->cursor_pos
1054 && gstring->to > control->cursor_pos)
1055 cursor_pos = control->cursor_pos;
1058 && gstring->from <= control->cursor_pos - 1
1059 && gstring->to > control->cursor_pos - 1)
1060 prev_pos = control->cursor_pos - 1;
1063 *from_idx = *to_idx = 0;
1064 while (g->type != GLYPH_ANCHOR)
1066 if (g->pos >= from && g->pos < to)
1068 MGlyph *fromg = g, *cursor = NULL;
1069 MRealizedFace *rface = g->rface;
1071 int cursor_width = 0;
1075 *from_idx = GLYPH_INDEX (g);
1076 while (g->pos >= from && g->pos < to
1077 && g->rface == rface)
1080 if (g->type != GLYPH_BOX
1081 && g->pos <= cursor_pos && g->to > cursor_pos)
1084 cursor = g, cursor_x = x + width;
1085 cursor_width += g->width;
1087 width += g++->width;
1090 && (control->as_image
1091 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1093 int this_x = x, this_width = width;
1095 if (fromg->type == GLYPH_BOX)
1096 this_x += fromg->width, this_width -= fromg->width;
1097 if (g[-1].type == GLYPH_BOX)
1098 this_width -= g[-1].width;
1099 (frame->driver->fill_space)
1100 (frame, win, rface, 0,
1101 this_x, y - gstring->text_ascent, this_width,
1102 gstring->text_ascent + gstring->text_descent,
1103 control->clip_region);
1110 rect.y = y - gstring->text_ascent;
1111 rect.height = gstring->text_ascent + gstring->text_descent;
1114 rect.width = ((control->cursor_width > 0
1115 && control->cursor_width < cursor_width)
1116 ? control->cursor_width : cursor_width);
1120 if (cursor->bidi_level % 2)
1121 rect.x += cursor_width - rect.width;
1122 (*frame->driver->fill_space)
1123 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1124 control->clip_region);
1126 region = (*frame->driver->region_from_rect) (&rect);
1128 (*frame->driver->region_add_rect) (region, &rect);
1131 if (cursor->bidi_level % 2)
1134 rect.width = cursor_width < 4 ? cursor_width : 4;
1135 (*frame->driver->fill_space)
1136 (frame, win, rface, 1,
1137 rect.x, rect.y, rect.width, rect.height,
1138 control->clip_region);
1139 (*frame->driver->region_add_rect) (region, &rect);
1151 if (fromg->type != GLYPH_BOX
1152 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1155 cursor = fromg, cursor_x = x + temp_width;
1156 cursor_width += fromg->width;
1158 temp_width += fromg++->width;
1165 if (! (cursor->bidi_level % 2))
1166 rect.x += cursor_width - 1;
1167 rect.y = y - gstring->text_ascent;
1168 rect.height = gstring->text_ascent + gstring->text_descent;
1170 (*frame->driver->fill_space)
1171 (frame, win, rface, 1,
1172 rect.x, rect.y, rect.width, rect.height,
1173 control->clip_region);
1175 region = (*frame->driver->region_from_rect) (&rect);
1177 (*frame->driver->region_add_rect) (region, &rect);
1178 rect.y += rect.height - 2;
1180 rect.width = cursor_width < 4 ? cursor_width : 4;
1181 if (! (cursor->bidi_level % 2))
1182 rect.x -= rect.width - 1;
1183 (*frame->driver->fill_space) (frame, win, rface, 1,
1184 rect.x, rect.y, rect.width, rect.height,
1185 control->clip_region);
1186 (*frame->driver->region_add_rect) (region, &rect);
1190 *to_idx = GLYPH_INDEX (g);
1200 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1201 MGlyphString *gstring, int from_idx, int to_idx,
1202 int reverse, MDrawRegion region)
1204 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1210 (*frame->driver->region_to_rect) (region, &rect);
1213 while (g != gend && x + g->rbearing <= rect.x)
1216 width -= g++->width;
1217 while (! g->enabled && g != gend)
1221 rect.x += rect.width;
1222 if (rect.x < x + width)
1225 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1227 width -= (--gend)->width;
1228 while (! gend->enabled && g != gend)
1232 while (gend[-1].to == gend->to) gend++;
1240 MRealizedFace *rface = g->rface;
1241 int width = g->width;
1242 MGlyph *from_g = g++;
1244 /* Handle the glyphs of the same type/face at once. */
1246 && g->type == from_g->type
1247 && g->rface == rface
1248 && ((g->code == MCHAR_INVALID_CODE)
1249 == (from_g->code == MCHAR_INVALID_CODE))
1251 width += g++->width;
1253 if (from_g->type == GLYPH_CHAR)
1255 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1256 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1259 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1262 else if (from_g->type == GLYPH_BOX)
1264 /* Draw the left or right side of a box. If
1265 from_g->lbearing is nonzero, this is the left side,
1266 else this is the right side. */
1267 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1270 if (from_g->type != GLYPH_BOX)
1273 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1274 x, y, width, region);
1277 /* Draw the top and bottom side of a box. */
1278 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1279 x, y, width, region);
1290 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1291 int *from_x, int *to_x)
1294 int left_idx = *left, right_idx = *right;
1295 int left_x, right_x, x;
1297 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1300 if (x + g->rbearing > 0)
1302 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1304 left_idx = GLYPH_INDEX (g);
1309 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1312 if (x - g->width + g->lbearing < 0)
1314 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1316 right_idx = GLYPH_INDEX (g) + 1;
1321 if (*left == left_idx && *right == right_idx)
1324 if (*left != left_idx)
1326 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1331 if (*right != right_idx)
1333 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1343 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1348 if (from <= gstring->from && to >= gstring->to)
1351 *rbearing = gstring->rbearing;
1352 return gstring->width;
1357 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1358 if (g->pos >= from && g->pos < to)
1360 if (rbearing && width + g->rbearing > *rbearing)
1361 *rbearing = width + g->rbearing;
1369 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1370 MGlyphString *gstring, int from, int to)
1372 MDrawControl *control = &gstring->control;
1374 MDrawRegion clip_region, cursor_region;
1375 int from_idx, to_idx;
1378 if (control->orientation_reversed)
1379 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1381 x += gstring->indent;
1383 /* At first, draw all glyphs without cursor. */
1384 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1385 &from_idx, &to_idx, &to_x);
1387 if (control->partial_update)
1390 rect.width = to_x - x;
1391 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1393 rect.y = y - gstring->line_ascent;
1394 rect.height = gstring->height;
1395 clip_region = (*frame->driver->region_from_rect) (&rect);
1396 if (control->clip_region)
1397 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1400 clip_region = control->clip_region;
1403 clip_region = control->clip_region;
1405 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1410 (*frame->driver->intersect_region) (cursor_region, clip_region);
1411 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1414 if (clip_region != control->clip_region)
1415 (*frame->driver->free_region) (clip_region);
1417 (*frame->driver->free_region) (cursor_region);
1421 static int gstring_num;
1424 free_gstring (void *object)
1426 MGlyphString *gstring = (MGlyphString *) object;
1429 free_gstring (gstring->next);
1430 if (gstring->size > 0)
1431 free (gstring->glyphs);
1437 static MGlyphString scratch_gstring;
1439 static MGlyphString *
1440 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1443 MGlyphString *gstring;
1445 if (pos == mt->nchars)
1449 gstring = &scratch_gstring;
1450 if (gstring->size == 0)
1455 g_tmp.type = GLYPH_ANCHOR;
1456 APPEND_GLYPH (gstring, g_tmp);
1457 APPEND_GLYPH (gstring, g_tmp);
1458 APPEND_GLYPH (gstring, g_tmp);
1459 gstring->glyphs[1].type = GLYPH_SPACE;
1460 gstring->glyphs[1].c = '\n';
1461 gstring->glyphs[1].code = '\n';
1463 gstring->from = pos;
1465 g->rface = frame->rface;
1466 g->pos = g->to = pos;
1468 g->rface = frame->rface;
1469 g->pos = pos++, g->to = pos;
1471 g->rface = frame->rface;
1472 g->pos = g->to = pos;
1477 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1478 MLIST_INIT1 (gstring, glyphs, 128);
1482 gstring->frame = frame;
1483 gstring->tick = frame->tick;
1484 gstring->top = gstring;
1485 gstring->control = *control;
1486 gstring->indent = gstring->width_limit = 0;
1487 if (control->format)
1488 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1490 gstring->width_limit = control->max_line_width;
1491 gstring->anti_alias = control->anti_alias;
1495 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1498 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1506 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1507 a width of glyphs for the character at I of MT. If I is not a
1508 beginning of a grapheme cluster, the corresponding element is
1510 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1511 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1512 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1513 pos_width[g->pos - gstring->from] += g->width;
1514 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1516 if (pos_width[i] > 0)
1518 if (width + pos_width[i] > gstring->width_limit)
1521 width += pos_width[i];
1524 pos = gstring->from + i;
1525 if (gstring->control.line_break)
1527 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1528 gstring->from, gstring->to, 0, 0);
1529 if (pos <= gstring->from)
1530 pos = gstring->from + 1;
1531 else if (pos >= gstring->to)
1536 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1537 layout_glyph_string (frame, gstring);
1541 /* Return a gstring that covers a character at POS. */
1543 static MGlyphString *
1544 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1546 MGlyphString *gstring = NULL;
1548 if (pos < mtext_nchars (mt))
1550 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1553 && ((prop->start != 0
1554 && mtext_ref_char (mt, prop->start - 1) != '\n')
1555 || (prop->end < mtext_nchars (mt)
1556 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1558 mtext_detach_property (prop);
1563 gstring = prop->val;
1564 if (gstring->frame != frame
1565 || gstring->tick != frame->tick
1566 || memcmp (control, &gstring->control,
1567 (char *) (&control->with_cursor)
1568 - (char *) (control))
1569 || control->cursor_width != gstring->control.cursor_width
1570 || control->cursor_bidi != gstring->control.cursor_bidi)
1572 mtext_detach_property (prop);
1577 else if (! control->cursor_width)
1585 offset = mtext_character (mt, pos, 0, '\n');
1590 offset -= gstring->from;
1592 for (gst = gstring; gst; gst = gst->next)
1596 gst->from += offset;
1598 for (i = 0; i < gst->used; i++)
1600 gst->glyphs[i].pos += offset;
1601 gst->glyphs[i].to += offset;
1604 M17N_OBJECT_REF (gstring);
1609 int line = 0, y = 0;
1611 if (pos < mtext_nchars (mt))
1613 beg = mtext_character (mt, pos, 0, '\n');
1621 end = mtext_nchars (mt) + (control->cursor_width != 0);
1622 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1623 if (beg < mtext_nchars (mt))
1624 compose_glyph_string (frame, mt, beg, end, gstring);
1625 layout_glyph_string (frame, gstring);
1627 if (gstring->width_limit
1628 && gstring->width > gstring->width_limit)
1630 MGlyphString *gst = gstring;
1632 truncate_gstring (frame, mt, gst);
1633 while (gst->to < end)
1635 line++, y += gst->height;
1636 gst->next = alloc_gstring (frame, mt, gst->from, control,
1638 gst->next->top = gstring;
1639 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1641 layout_glyph_string (frame, gst);
1642 if (gst->width <= gst->width_limit)
1644 truncate_gstring (frame, mt, gst);
1648 if (! control->disable_caching && pos < mtext_nchars (mt))
1650 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1651 MTEXTPROP_VOLATILE_STRONG);
1653 if (end > mtext_nchars (mt))
1654 end = mtext_nchars (mt);
1655 mtext_attach_property (mt, beg, end, prop);
1656 M17N_OBJECT_UNREF (prop);
1660 while (gstring->to <= pos)
1662 if (! gstring->next)
1664 gstring = gstring->next;
1666 gstring->control = *control;
1672 static MDrawControl control_noop;
1674 #define ASSURE_CONTROL(control) \
1676 control = &control_noop; \
1681 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1682 MText *mt, int from, int to,
1683 MDrawControl *control)
1685 MGlyphString *gstring;
1687 M_CHECK_POS_X (mt, from, -1);
1688 ASSURE_CONTROL (control);
1689 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1690 to = mtext_nchars (mt) + (control->cursor_width != 0);
1694 gstring = get_gstring (frame, mt, from, to, control);
1696 MERROR (MERROR_DRAW, -1);
1697 render_glyph_string (frame, win, x, y, gstring, from, to);
1701 y += gstring->line_descent;
1702 M17N_OBJECT_UNREF (gstring->top);
1703 gstring = get_gstring (frame, mt, from, to, control);
1704 y += gstring->line_ascent;
1705 render_glyph_string (frame, win, x, y, gstring, from, to);
1708 M17N_OBJECT_UNREF (gstring->top);
1715 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1721 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1722 if (g->pos <= pos && g->to > pos)
1727 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1728 if (g->pos <= pos && g->to > pos)
1735 /* for debugging... */
1739 dump_combining_code (int code)
1741 char *vallign = "tcbB";
1742 char *hallign = "lcr";
1748 if (COMBINING_BY_CLASS_P (code))
1749 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1750 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1751 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1752 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1753 off_x = COMBINING_CODE_OFF_X (code) - 128;
1755 sprintf (work + 2, "+%d", off_y);
1757 sprintf (work + 2, "%d", off_y);
1758 else if (off_x == 0)
1759 sprintf (work + 2, ".");
1760 p = work + strlen (work);
1762 sprintf (p, ">%d", off_x);
1764 sprintf (p, "<%d", -off_x);
1766 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1767 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1773 dump_gstring (MGlyphString *gstring, int indent)
1775 char *prefix = (char *) alloca (indent + 1);
1776 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1778 memset (prefix, 32, indent);
1781 fprintf (stderr, "(glyph-string");
1783 for (g = MGLYPH (0); g < last_g; g++)
1785 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1787 g - gstring->glyphs,
1788 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1789 : g->type == GLYPH_ANCHOR ? "ANC"
1790 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1791 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1792 dump_combining_code (g->combining_code),
1793 g->width, g->bidi_level);
1794 fprintf (stderr, ")");
1798 /* m17n-X internal APIs */
1803 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1805 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1806 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1808 Minherited = msymbol ("inherited");
1810 McatCc = msymbol ("Cc");
1811 McatCf = msymbol ("Cf");
1813 MbidiR = msymbol ("R");
1814 MbidiAL = msymbol ("AL");
1815 MbidiRLE = msymbol ("RLE");
1816 MbidiRLO = msymbol ("RLO");
1817 MbidiBN = msymbol ("BN");
1818 MbidiS = msymbol ("S");
1820 fribidi_set_mirroring (TRUE);
1829 MLIST_FREE1 (&scratch_gstring, glyphs);
1833 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1837 /*** @addtogroup m17nDraw */
1842 @brief Draw an M-text on a window.
1844 The mdraw_text () function draws the text between $FROM and $TO of
1845 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1847 The appearance of the text (size, style, color, etc) is specified
1848 by the value of the text property whose key is @c Mface. If the
1849 M-text or a part of the M-text does not have such a text property,
1850 the default face of $FRAME is used.
1852 The font used to draw a character in the M-text is selected from
1853 the value of the fontset property of a face by the following
1858 <li> Search the text properties given to the character for the one
1859 whose key is @c Mcharset; its value should be either a symbol
1860 specifying a charset or #Mnil. If the value is #Mnil,
1861 proceed to the next step.
1863 Otherwise, search the mapping table of the fontset for the
1864 charset. If no entry is found proceed to the next step.
1866 If an entry is found, use one of the fonts in the entry that
1867 has a glyph for the character and that matches best with the
1868 face properties. If no such font exists, proceed to the next
1871 <li> Get the character property "script" of the character. If it is
1872 inherited, get the script property from the previous
1873 characters. If there is no previous character, or none of
1874 them has the script property other than inherited, proceed to
1877 Search the text properties given to the character for the one
1878 whose key is @c Mlanguage; its value should be either a
1879 symbol specifying a language or @c Mnil.
1881 Search the mapping table of the fontset for the combination
1882 of the script and language. If no entry is found, proceed to
1885 If an entry is found, use one of the fonts in the entry that
1886 has a glyph for the character and that matches best with the
1887 face properties. If no such font exists, proceed to the next
1890 <li> Search the fall-back table of the fontset for a font that has
1891 a glyph of the character. If such a font is found, use that
1896 If no font is found by the algorithm above, this function draws an
1897 empty box for the character.
1899 This function draws only the glyph foreground. To specify the
1900 background color, use mdraw_image_text () or
1901 mdraw_text_with_control ().
1903 This function is the counterpart of <tt>XDrawString ()</tt>,
1904 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1905 in the X Window System.
1908 If the operation was successful, mdraw_text () returns 0. If an
1909 error is detected, it returns -1 and assigns an error code to the
1910 external variable #merror_code. */
1912 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1914 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1915 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1918 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1919 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1920 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1921 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1923 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1924 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1928 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1929 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1930 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1931 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1932 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1935 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1936 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1937 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1940 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1941 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1942 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1943 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1945 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1946 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1949 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1950 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1953 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1954 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1955 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1958 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1959 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1963 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1964 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1966 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1967 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1970 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1971 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1974 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1975 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1977 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1984 mdraw_image_text () */
1987 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1988 MText *mt, int from, int to)
1990 MDrawControl control;
1992 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1993 memset (&control, 0, sizeof control);
1994 control.as_image = 0;
1995 return draw_text (frame, win, x, y, mt, from, to, &control);
2002 @brief Draw an M-text on a window as an image.
2004 The mdraw_image_text () function draws the text between $FROM and
2005 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2006 coordinate ($X, $Y).
2008 The way to draw a text is the same as in mdraw_text () except that
2009 this function also draws the background with the color specified
2012 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2013 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2014 functions in the X Window System.
2017 If the operation was successful, mdraw_image_text () returns 0.
2018 If an error is detected, it returns -1 and assigns an error code
2019 to the external variable #merror_code. */
2022 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2024 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
2025 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
2028 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
2029 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2031 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2032 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
2036 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2037 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
2040 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2050 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2051 MText *mt, int from, int to)
2053 MDrawControl control;
2055 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2056 memset (&control, 0, sizeof control);
2057 control.as_image = 1;
2058 return draw_text (frame, win, x, y, mt, from, to, &control);
2064 @brief Draw an M-text on a window with fine control.
2066 The mdraw_text_with_control () function draws the text between
2067 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2068 coordinate ($X, $Y).
2070 The way to draw a text is the same as in mdraw_text () except that
2071 this function also follows what specified in the drawing control
2074 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2075 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2076 breaks lines and the following characters are drawn in the next
2077 line. See the documentation of the structure @ MDrawControl for
2081 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2083 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2084 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2087 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2088 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2090 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2091 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2092 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2096 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2097 MText *mt, int from, int to, MDrawControl *control)
2099 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2100 return draw_text (frame, win, x, y, mt, from, to, control);
2106 @brief Compute text pixel width.
2108 The mdraw_text_extents () function computes the width of text
2109 between $FROM and $TO of M-text $MT when it is drawn on a window
2110 of frame $FRAME using the mdraw_text_with_control () function with
2111 the drawing control object $CONTROL.
2113 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2114 the bounding box of character ink of the M-text, and stores the
2115 results in the members of the structure pointed to by
2116 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2117 surrounding box, the box is included in the bounding box.
2119 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2120 computes the bounding box that provides mininum spacing to other
2121 graphical features (such as surrounding box) for the M-text, and
2122 stores the results in the members of the structure pointed to by
2123 $OVERALL_LOGICAL_RETURN.
2125 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2126 computes the bounding box that provides mininum spacing to the
2127 other M-text drawn, and stores the results in the members of the
2128 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2129 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2130 min_line_ascent, min_line_descent, max_line_ascent, and
2131 max_line_descent of $CONTROL are all zero.
2134 This function returns the width of the text to be drawn in the
2135 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2136 text is drawn in multiple physical lines, it returns the width of
2137 the widest line. If an error occurs, it returns -1 and assigns an
2138 error code to the external variable #merror_code. */
2142 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2144 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2145 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2146 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2148 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2149 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2150 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2151 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2153 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2154 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2155 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2156 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2158 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2159 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2160 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2161 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2162 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2163 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2165 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2166 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2167 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2168 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2170 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2177 mdraw_text_extents (MFrame *frame,
2178 MText *mt, int from, int to, MDrawControl *control,
2179 MDrawMetric *overall_ink_return,
2180 MDrawMetric *overall_logical_return,
2181 MDrawMetric *overall_line_return)
2183 MGlyphString *gstring;
2185 int width, rbearing;
2187 ASSURE_CONTROL (control);
2188 M_CHECK_POS_X (mt, from, -1);
2189 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2190 to = mtext_nchars (mt) + (control->cursor_width != 0);
2194 gstring = get_gstring (frame, mt, from, to, control);
2196 MERROR (MERROR_DRAW, -1);
2197 width = gstring_width (gstring, from, to, &rbearing);
2198 if (overall_ink_return)
2200 overall_ink_return->y = - gstring->physical_ascent;
2201 overall_ink_return->x = gstring->lbearing;
2203 if (overall_logical_return)
2205 overall_logical_return->y = - gstring->ascent;
2206 overall_logical_return->x = 0;
2208 if (overall_line_return)
2210 overall_line_return->y = - gstring->line_ascent;
2211 overall_line_return->x = gstring->lbearing;
2214 for (from = gstring->to; from < to; from = gstring->to)
2216 int this_width, this_rbearing;
2218 y += gstring->line_descent;
2219 M17N_OBJECT_UNREF (gstring->top);
2220 gstring = get_gstring (frame, mt, from, to, control);
2221 this_width = gstring_width (gstring, from, to, &this_rbearing);
2222 y += gstring->line_ascent;
2223 if (width < this_width)
2225 if (rbearing < this_rbearing)
2226 rbearing = this_rbearing;
2228 if (overall_ink_return)
2230 overall_ink_return->width = rbearing;
2231 overall_ink_return->height
2232 = y + gstring->physical_descent - overall_ink_return->y;
2234 if (overall_logical_return)
2236 overall_logical_return->width = width;
2237 overall_logical_return->height
2238 = y + gstring->descent - overall_logical_return->y;
2240 if (overall_line_return)
2242 overall_line_return->width = MAX (width, rbearing);
2243 overall_line_return->height
2244 = y + gstring->line_descent - overall_line_return->y;
2247 M17N_OBJECT_UNREF (gstring->top);
2254 @brief Compute the text dimensions of each character of M-text.
2256 The mdraw_text_per_char_extents () function computes the drawn
2257 metric of each character between $FROM and $TO of M-text $MT
2258 assuming that they are drawn on a window of frame $FRAME using the
2259 mdraw_text_with_control () function with the drawing control
2262 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2263 $LOGICAL_ARRAY_RETURN. Each successive element of
2264 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2265 ink and logical metrics of successive characters respectively,
2266 relative to the drawing origin of the M-text. The number of
2267 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2268 been set is returned to $NUM_CHARS_RETURN.
2270 If $ARRAY_SIZE is too small to return all metrics, the function
2271 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2272 Otherwise, it returns zero.
2274 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2275 @c NULL, this function also computes the metrics of the overall
2276 text and stores the results in the members of the structure
2277 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2279 If $CONTROL->two_dimensional is nonzero, this function computes
2280 only the metrics of characters in the first line. */
2282 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2284 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2285 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2286 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2287 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2289 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2290 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2291 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2292 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2293 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2295 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2296 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2299 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2300 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2301 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2304 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2305 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2308 mdraw_text_per_char_extents (MFrame *frame,
2309 MText *mt, int from, int to,
2310 MDrawControl *control,
2311 MDrawMetric *ink_array_return,
2312 MDrawMetric *logical_array_return,
2314 int *num_chars_return,
2315 MDrawMetric *overall_ink_return,
2316 MDrawMetric *overall_logical_return)
2318 MGlyphString *gstring;
2322 ASSURE_CONTROL (control);
2323 *num_chars_return = to - from;
2324 if (array_size < *num_chars_return)
2325 MERROR (MERROR_DRAW, -1);
2326 if (overall_logical_return)
2327 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2328 if (overall_ink_return)
2329 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2331 M_CHECK_RANGE (mt, from, to, -1, 0);
2332 gstring = get_gstring (frame, mt, from, to, control);
2335 *num_chars_return = 0;
2339 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2340 if (g->pos >= from && g->pos < to)
2344 int width = g->width;
2345 int lbearing = g->lbearing;
2346 int rbearing = g->rbearing;
2347 int ascent = g->ascent;
2348 int descent = g->descent;
2350 int logical_descent;
2352 if (g->rface->rfont)
2354 logical_ascent = g->rface->rfont->ascent;
2355 logical_descent = g->rface->rfont->descent;
2359 logical_ascent = g->rface->ascent;
2360 logical_descent = g->rface->descent;
2362 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2364 if (lbearing < width + g->lbearing)
2365 lbearing = width + g->lbearing;
2366 if (rbearing < width + g->rbearing)
2367 rbearing = width + g->rbearing;
2369 if (ascent < g->ascent)
2371 if (descent < g->descent)
2372 descent = g->descent;
2379 if (ink_array_return)
2381 ink_array_return[start - from].x = x + lbearing;
2382 ink_array_return[start - from].y = - ascent;
2383 ink_array_return[start - from].width = rbearing - lbearing;
2384 ink_array_return[start - from].height = ascent + descent;
2386 if (logical_array_return)
2388 logical_array_return[start - from].x = x;
2389 logical_array_return[start - from].y = - logical_descent;
2390 logical_array_return[start - from].height
2391 = logical_ascent + logical_descent;
2392 logical_array_return[start - from].width = width;
2400 if (overall_ink_return)
2402 overall_ink_return->y = - gstring->line_ascent;
2403 overall_ink_return->x = gstring->lbearing;
2404 overall_ink_return->width = x - gstring->lbearing;
2405 overall_ink_return->height = gstring->height;
2407 if (overall_logical_return)
2409 overall_logical_return->y = - gstring->ascent;
2410 overall_logical_return->x = 0;
2411 overall_logical_return->width = x;
2412 overall_logical_return->height = gstring->ascent + gstring->descent;
2415 M17N_OBJECT_UNREF (gstring->top);
2422 @brief Return the character position nearest to the coordinates.
2424 The mdraw_coordinates_position () function checks which character
2425 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2426 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2427 mdraw_text_with_control () function with the drawing control
2428 object $CONTROL. Here, the character position means the number of
2429 characters that precede the character in question in $MT, that is,
2430 the character position of the first character is 0.
2432 $FRAME is used only to get the default face information.
2435 If the glyph image of a character covers coordinate ($X, $Y),
2436 mdraw_coordinates_position () returns the character position of
2438 If $Y is less than the minimum Y-coordinate of the drawn area, it
2439 returns $FROM.\n\n\n
2440 If $Y is greater than the maximum Y-coordinate of the drawn area,
2441 it returns $TO.\n\n\n
2442 If $Y fits in with the drawn area but $X is less than the minimum
2443 X-coordinate, it returns the character position of the first
2444 character drawn on the line $Y.\n\n\n
2445 If $Y fits in with the drawn area but $X is greater than the
2446 maximum X-coordinate, it returns the character position of the
2447 last character drawn on the line $Y. */
2450 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2452 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2453 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2454 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2455 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2456 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2457 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2459 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2462 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2463 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2465 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2467 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2469 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2470 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2472 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2473 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2476 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2477 int x_offset, int y_offset, MDrawControl *control)
2479 MGlyphString *gstring;
2484 M_CHECK_POS_X (mt, from, -1);
2485 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2486 to = mtext_nchars (mt) + (control->cursor_width != 0);
2492 ASSURE_CONTROL (control);
2493 gstring = get_gstring (frame, mt, from, to, control);
2494 while (y + gstring->line_descent <= y_offset
2495 && gstring->to < to)
2498 y += gstring->line_descent;
2499 M17N_OBJECT_UNREF (gstring->top);
2500 gstring = get_gstring (frame, mt, from, to, control);
2501 y += gstring->line_ascent;
2504 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2505 if (! control->orientation_reversed)
2507 width = gstring->indent;
2508 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2509 if (g->pos >= from && g->pos < to)
2512 if (width > x_offset)
2518 width = - gstring->indent;
2519 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2520 if (g->pos >= from && g->pos < to)
2523 if (width < x_offset)
2527 if (g->type == GLYPH_ANCHOR
2528 && control->two_dimensional
2532 M17N_OBJECT_UNREF (gstring->top);
2540 @brief Compute information about a glyph.
2542 The mdraw_glyph_info () function computes information about a
2543 glyph that covers a character at position $POS of the M-text $MT
2544 assuming that the text is drawn from the character at $FROM of $MT
2545 on a window of frame $FRAME using the mdraw_text_with_control ()
2546 function with the drawing control object $CONTROL.
2548 The information is stored in the members of $INFO. */
2550 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2552 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2553 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2554 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2555 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2557 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2565 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2566 MDrawControl *control, MDrawGlyphInfo *info)
2568 MGlyphString *gstring;
2572 M_CHECK_RANGE_X (mt, from, pos, -1);
2574 ASSURE_CONTROL (control);
2575 gstring = get_gstring (frame, mt, from, pos + 1, control);
2577 MERROR (MERROR_DRAW, -1);
2578 while (gstring->to <= pos)
2580 y += gstring->line_descent;
2581 M17N_OBJECT_UNREF (gstring->top);
2582 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2583 y += gstring->line_ascent;
2585 info->line_from = gstring->from;
2586 if (info->line_from < from)
2587 info->line_from = from;
2588 info->line_to = gstring->to;
2591 if (! control->orientation_reversed)
2593 info->x = gstring->indent;
2594 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2595 info->x += g->width;
2599 info->x = - gstring->indent;
2600 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2601 info->x -= g->width;
2602 while (g[-1].to == g->to)
2605 info->from = g->pos;
2607 info->metrics.x = g->lbearing;
2608 info->metrics.y = - gstring->line_ascent;
2609 info->metrics.height = gstring->height;
2610 info->metrics.width = - g->lbearing + g->width;
2611 if (g->rface->rfont)
2612 info->font = &g->rface->rfont->font;
2615 /* info->logical_width is calculated later. */
2617 if (info->from > info->line_from)
2619 /* The logically previous glyph is on this line. */
2620 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2622 info->prev_from = g_tmp->pos;
2624 else if (info->line_from > 0)
2626 /* The logically previous glyph is on the previous line. */
2627 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2628 gstring->from, control);
2629 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2631 info->prev_from = g_tmp->pos;
2632 M17N_OBJECT_UNREF (gst->top);
2635 info->prev_from = -1;
2637 if (GLYPH_INDEX (g) > 1)
2638 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2639 else if (! control->orientation_reversed)
2641 if (info->line_from > 0)
2645 int p = gstring->from - 1;
2647 gst = get_gstring (frame, mt, p, gstring->from, control);
2648 g_tmp = gst->glyphs + (gst->used - 2);
2649 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2650 M17N_OBJECT_UNREF (gst->top);
2653 info->left_from = info->left_to = -1;
2657 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2661 int p = gstring->to;
2663 gst = get_gstring (frame, mt, p, p + 1, control);
2664 g_tmp = gst->glyphs + (gst->used - 2);
2665 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2666 M17N_OBJECT_UNREF (gst->top);
2669 info->left_from = info->left_to = -1;
2672 if (info->to < gstring->to)
2674 /* The logically next glyph is on this line. */
2675 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2677 info->next_to = g_tmp->to;
2679 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2681 /* The logically next glyph is on the next line. */
2683 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2684 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2686 info->next_to = g_tmp->to;
2687 M17N_OBJECT_UNREF (gst->top);
2692 for (info->logical_width = (g++)->width;
2693 g->pos == pos && g->type != GLYPH_ANCHOR;
2694 info->metrics.width += g->width, info->logical_width += (g++)->width);
2695 info->metrics.width += g[-1].rbearing - g[-1].width;
2697 if (g->type != GLYPH_ANCHOR)
2698 info->right_from = g->pos, info->right_to = g->to;
2699 else if (! control->orientation_reversed)
2701 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2704 M17N_OBJECT_UNREF (gstring->top);
2705 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2707 info->right_from = g->pos, info->right_to = g->to;
2710 info->right_from = info->right_to = -1;
2714 if (info->line_from > 0)
2716 pos = gstring->from - 1;
2717 M17N_OBJECT_UNREF (gstring->top);
2718 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2720 info->right_from = g->pos, info->right_to = g->to;
2723 info->right_from = info->right_to = -1;
2726 M17N_OBJECT_UNREF (gstring->top);
2733 @brief Compute information about glyph sequence.
2735 The mdraw_glyph_list () function computes information about glyphs
2736 corresponding to the text between $FROM and $TO of M-text $MT when
2737 it is drawn on a window of frame $FRAME using the
2738 mdraw_text_with_control () function with the drawing control
2739 object $CONTROL. $GLYPHS is an array of objects to store the
2740 information, and $ARRAY_SIZE is the array size.
2742 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2743 number of actually filled elements in the place pointed by
2744 $NUM_GLYPHS_RETURN, and returns 0.
2746 Otherwise, it stores the required array size in the place pointed
2747 by $NUM_GLYPHS_RETURN, and returns -1. */
2750 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2752 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
2753 À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
2754 ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
2755 ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2757 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
2758 ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
2767 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2768 MDrawControl *control, MDrawGlyph *glyphs,
2769 int array_size, int *num_glyphs_return)
2771 MGlyphString *gstring;
2776 ASSURE_CONTROL (control);
2777 *num_glyphs_return = 0;
2778 M_CHECK_RANGE (mt, from, to, -1, 0);
2779 gstring = get_gstring (frame, mt, from, to, control);
2782 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2784 if (g->type == GLYPH_BOX
2785 || g->pos < from || g->pos >= to)
2787 if (g->type == GLYPH_PAD)
2789 if (g->left_padding)
2790 pad_width = g->width;
2794 glyphs[-1].x_advance += g->width;
2800 glyphs->from = g->pos;
2802 glyphs->glyph_code = g->code;
2803 glyphs->x_off = g->xoff + pad_width;
2804 glyphs->y_off = g->yoff;
2805 glyphs->lbearing = g->lbearing;
2806 glyphs->rbearing = g->rbearing;
2807 glyphs->ascent = g->ascent;
2808 glyphs->descent = g->descent;
2809 glyphs->x_advance = g->width + pad_width;
2810 glyphs->y_advance = 0;
2811 if (g->rface->rfont)
2813 glyphs->font = &g->rface->rfont->font;
2814 glyphs->font_type = g->rface->rfont->type;
2815 glyphs->fontp = g->rface->rfont->fontp;
2819 glyphs->font = NULL;
2820 glyphs->font_type = Mnil;
2821 glyphs->fontp = NULL;
2828 M17N_OBJECT_UNREF (gstring->top);
2830 *num_glyphs_return = n;
2831 return (n <= array_size ? 0 : -1);
2837 @brief Draw one or more textitems.
2839 The mdraw_text_items () function draws one or more M-texts on
2840 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2841 of the textitems to be drawn and $NITEMS is the number of
2842 textimtems in the array. */
2845 @brief textitem ¤òɽ¼¨¤¹¤ë.
2847 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2848 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2849 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2852 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2856 MTextItem, mdraw_text (). */
2859 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2860 MDrawTextItem *items, int nitems)
2862 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2864 while (nitems-- > 0)
2867 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2869 mdraw_text_with_control (frame, win, x, y,
2870 items->mt, 0, mtext_nchars (items->mt),
2872 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2873 items->control, NULL, NULL, NULL);
2876 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2882 @brief calculate a line breaking position.
2884 The function mdraw_default_line_break () calculates a line
2885 breaking position based on the line number $LINE and the
2886 coordinate $Y, when a line is too long to fit within the width
2887 limit. $POS is the position of the character next to the last
2888 one that fits within the limit. $FROM is the position of the
2889 first character of the line, and TO is the position of the last
2890 character displayed on the line if there were not width limit.
2891 LINE and Y are reset to 0 when a line is broken by a newline
2892 character, and incremented each time when a long line is broken
2893 because of the width limit.
2896 This function returns a character position to break the
2901 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2903 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2904 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2905 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2906 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2907 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2908 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2909 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2912 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2916 mdraw_default_line_break (MText *mt, int pos,
2917 int from, int to, int line, int y)
2919 int c = mtext_ref_char (mt, pos);
2922 if (c == ' ' || c == '\t')
2926 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2933 if (c == ' ' || c == '\t')
2936 c = mtext_ref_char (mt, pos);
2949 @brief Obtain per character dimension information.
2951 The mdraw_per_char_extents () function computes the text dimension
2952 of each character in M-text $MT. The faces given as text
2953 properties in $MT and the default face of frame $FRAME determine
2954 the fonts to draw the text. Each successive element in
2955 $ARRAY_RETURN is set to the drawn metrics of successive
2956 characters, which is relative to the origin of the drawing, and a
2957 rectangle for each character in $MT. The number of elements of
2958 $ARRAY_RETURN must be equal to or greater than the number of
2961 If pointer $OVERALL_RETURN is not @c NULL, this function also
2962 computes the extents of the overall text and stores the results in
2963 the members of the structure pointed to by $OVERALL_RETURN. */
2966 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2968 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2969 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2970 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2971 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2972 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2973 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2976 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2977 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2980 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2983 mdraw_per_char_extents (MFrame *frame, MText *mt,
2984 MDrawMetric *array_return,
2985 MDrawMetric *overall_return)
2987 int n = mtext_nchars (mt);
2989 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2990 n, &n, overall_return, NULL);
2994 @brief clear cached information.
2996 The mdraw_clear_cache () function clear cached information
2997 on M-text $MT that was attached by any of the drawing functions.
2998 When the behaviour of `format' or `line_break'
2999 member functions of MDrawControl is changed, the cache must be cleared.
3004 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3006 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
3007 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
3008 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
3009 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3014 mdraw_clear_cache (MText *mt)
3016 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);