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_CHAR;
1460 gstring->glyphs[1].c = ' ';
1461 gstring->glyphs[1].code = ' ';
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;
1470 g->c = '\n', g->code = '\n';
1472 g->rface = frame->rface;
1473 g->pos = g->to = pos;
1478 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1479 MLIST_INIT1 (gstring, glyphs, 128);
1483 gstring->frame = frame;
1484 gstring->tick = frame->tick;
1485 gstring->top = gstring;
1486 gstring->control = *control;
1487 gstring->indent = gstring->width_limit = 0;
1488 if (control->format)
1489 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1491 gstring->width_limit = control->max_line_width;
1492 gstring->anti_alias = control->anti_alias;
1496 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1499 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1507 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1508 a width of glyphs for the character at I of MT. If I is not a
1509 beginning of a grapheme cluster, the corresponding element is
1511 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1512 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1513 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1514 pos_width[g->pos - gstring->from] += g->width;
1515 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1517 if (pos_width[i] > 0)
1519 if (width + pos_width[i] > gstring->width_limit)
1522 width += pos_width[i];
1525 pos = gstring->from + i;
1526 if (gstring->control.line_break)
1528 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1529 gstring->from, gstring->to, 0, 0);
1530 if (pos <= gstring->from)
1531 pos = gstring->from + 1;
1532 else if (pos >= gstring->to)
1537 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1538 layout_glyph_string (frame, gstring);
1542 /* Return a gstring that covers a character at POS. */
1544 static MGlyphString *
1545 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1547 MGlyphString *gstring = NULL;
1549 if (pos < mtext_nchars (mt))
1551 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1554 && ((prop->start != 0
1555 && mtext_ref_char (mt, prop->start - 1) != '\n')
1556 || (prop->end < mtext_nchars (mt)
1557 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1559 mtext_detach_property (prop);
1564 gstring = prop->val;
1565 if (gstring->frame != frame
1566 || gstring->tick != frame->tick
1567 || memcmp (control, &gstring->control,
1568 (char *) (&control->with_cursor)
1569 - (char *) (control))
1570 || control->cursor_width != gstring->control.cursor_width
1571 || control->cursor_bidi != gstring->control.cursor_bidi)
1573 mtext_detach_property (prop);
1578 else if (! control->cursor_width)
1586 offset = mtext_character (mt, pos, 0, '\n');
1591 offset -= gstring->from;
1593 for (gst = gstring; gst; gst = gst->next)
1597 gst->from += offset;
1599 for (i = 0; i < gst->used; i++)
1601 gst->glyphs[i].pos += offset;
1602 gst->glyphs[i].to += offset;
1605 M17N_OBJECT_REF (gstring);
1610 int line = 0, y = 0;
1612 if (pos < mtext_nchars (mt))
1614 beg = mtext_character (mt, pos, 0, '\n');
1622 end = mtext_nchars (mt) + (control->cursor_width != 0);
1623 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1624 if (beg < mtext_nchars (mt))
1625 compose_glyph_string (frame, mt, beg, end, gstring);
1626 layout_glyph_string (frame, gstring);
1628 if (gstring->width_limit
1629 && gstring->width > gstring->width_limit)
1631 MGlyphString *gst = gstring;
1633 truncate_gstring (frame, mt, gst);
1634 while (gst->to < end)
1636 line++, y += gst->height;
1637 gst->next = alloc_gstring (frame, mt, gst->from, control,
1639 gst->next->top = gstring;
1640 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1642 layout_glyph_string (frame, gst);
1643 if (gst->width <= gst->width_limit)
1645 truncate_gstring (frame, mt, gst);
1649 if (! control->disable_caching && pos < mtext_nchars (mt))
1651 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1652 MTEXTPROP_VOLATILE_STRONG);
1654 if (end > mtext_nchars (mt))
1655 end = mtext_nchars (mt);
1656 mtext_attach_property (mt, beg, end, prop);
1657 M17N_OBJECT_UNREF (prop);
1661 while (gstring->to <= pos)
1663 if (! gstring->next)
1665 gstring = gstring->next;
1667 gstring->control = *control;
1673 static MDrawControl control_noop;
1675 #define ASSURE_CONTROL(control) \
1677 control = &control_noop; \
1682 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1683 MText *mt, int from, int to,
1684 MDrawControl *control)
1686 MGlyphString *gstring;
1688 M_CHECK_POS_X (mt, from, -1);
1689 ASSURE_CONTROL (control);
1690 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1691 to = mtext_nchars (mt) + (control->cursor_width != 0);
1695 gstring = get_gstring (frame, mt, from, to, control);
1697 MERROR (MERROR_DRAW, -1);
1698 render_glyph_string (frame, win, x, y, gstring, from, to);
1702 y += gstring->line_descent;
1703 M17N_OBJECT_UNREF (gstring->top);
1704 gstring = get_gstring (frame, mt, from, to, control);
1705 y += gstring->line_ascent;
1706 render_glyph_string (frame, win, x, y, gstring, from, to);
1709 M17N_OBJECT_UNREF (gstring->top);
1716 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1722 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1723 if (g->pos <= pos && g->to > pos)
1728 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1729 if (g->pos <= pos && g->to > pos)
1736 /* for debugging... */
1740 dump_combining_code (int code)
1742 char *vallign = "tcbB";
1743 char *hallign = "lcr";
1749 if (COMBINING_BY_CLASS_P (code))
1750 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1751 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1752 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1753 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1754 off_x = COMBINING_CODE_OFF_X (code) - 128;
1756 sprintf (work + 2, "+%d", off_y);
1758 sprintf (work + 2, "%d", off_y);
1759 else if (off_x == 0)
1760 sprintf (work + 2, ".");
1761 p = work + strlen (work);
1763 sprintf (p, ">%d", off_x);
1765 sprintf (p, "<%d", -off_x);
1767 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1768 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1774 dump_gstring (MGlyphString *gstring, int indent)
1776 char *prefix = (char *) alloca (indent + 1);
1777 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1779 memset (prefix, 32, indent);
1782 fprintf (stderr, "(glyph-string");
1784 for (g = MGLYPH (0); g < last_g; g++)
1786 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1788 g - gstring->glyphs,
1789 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1790 : g->type == GLYPH_ANCHOR ? "ANC"
1791 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1792 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1793 dump_combining_code (g->combining_code),
1794 g->width, g->bidi_level);
1795 fprintf (stderr, ")");
1799 /* m17n-X internal APIs */
1804 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1806 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1807 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1809 Minherited = msymbol ("inherited");
1811 McatCc = msymbol ("Cc");
1812 McatCf = msymbol ("Cf");
1814 MbidiR = msymbol ("R");
1815 MbidiAL = msymbol ("AL");
1816 MbidiRLE = msymbol ("RLE");
1817 MbidiRLO = msymbol ("RLO");
1818 MbidiBN = msymbol ("BN");
1819 MbidiS = msymbol ("S");
1821 fribidi_set_mirroring (TRUE);
1830 MLIST_FREE1 (&scratch_gstring, glyphs);
1834 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1838 /*** @addtogroup m17nDraw */
1843 @brief Draw an M-text on a window.
1845 The mdraw_text () function draws the text between $FROM and $TO of
1846 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1848 The appearance of the text (size, style, color, etc) is specified
1849 by the value of the text property whose key is @c Mface. If the
1850 M-text or a part of the M-text does not have such a text property,
1851 the default face of $FRAME is used.
1853 The font used to draw a character in the M-text is selected from
1854 the value of the fontset property of a face by the following
1859 <li> Search the text properties given to the character for the one
1860 whose key is @c Mcharset; its value should be either a symbol
1861 specifying a charset or #Mnil. If the value is #Mnil,
1862 proceed to the next step.
1864 Otherwise, search the mapping table of the fontset for the
1865 charset. If no entry is found proceed to the next step.
1867 If an entry is found, use one of the fonts in the entry that
1868 has a glyph for the character and that matches best with the
1869 face properties. If no such font exists, proceed to the next
1872 <li> Get the character property "script" of the character. If it is
1873 inherited, get the script property from the previous
1874 characters. If there is no previous character, or none of
1875 them has the script property other than inherited, proceed to
1878 Search the text properties given to the character for the one
1879 whose key is @c Mlanguage; its value should be either a
1880 symbol specifying a language or @c Mnil.
1882 Search the mapping table of the fontset for the combination
1883 of the script and language. If no entry is found, proceed to
1886 If an entry is found, use one of the fonts in the entry that
1887 has a glyph for the character and that matches best with the
1888 face properties. If no such font exists, proceed to the next
1891 <li> Search the fall-back table of the fontset for a font that has
1892 a glyph of the character. If such a font is found, use that
1897 If no font is found by the algorithm above, this function draws an
1898 empty box for the character.
1900 This function draws only the glyph foreground. To specify the
1901 background color, use mdraw_image_text () or
1902 mdraw_text_with_control ().
1904 This function is the counterpart of <tt>XDrawString ()</tt>,
1905 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1906 in the X Window System.
1909 If the operation was successful, mdraw_text () returns 0. If an
1910 error is detected, it returns -1 and assigns an error code to the
1911 external variable #merror_code. */
1913 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1915 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1916 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1919 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1920 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1921 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1922 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1924 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1925 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1929 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1930 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1931 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1932 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1933 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1936 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1937 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1938 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1941 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1942 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1943 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1944 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1946 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1947 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1950 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1951 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1954 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1955 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1956 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1959 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1960 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1964 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1965 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1967 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1968 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1971 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1972 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1975 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1976 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1978 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1985 mdraw_image_text () */
1988 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1989 MText *mt, int from, int to)
1991 MDrawControl control;
1993 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1994 memset (&control, 0, sizeof control);
1995 control.as_image = 0;
1996 return draw_text (frame, win, x, y, mt, from, to, &control);
2003 @brief Draw an M-text on a window as an image.
2005 The mdraw_image_text () function draws the text between $FROM and
2006 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2007 coordinate ($X, $Y).
2009 The way to draw a text is the same as in mdraw_text () except that
2010 this function also draws the background with the color specified
2013 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2014 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2015 functions in the X Window System.
2018 If the operation was successful, mdraw_image_text () returns 0.
2019 If an error is detected, it returns -1 and assigns an error code
2020 to the external variable #merror_code. */
2023 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2025 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
2026 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
2029 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
2030 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2032 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2033 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
2037 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2038 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
2041 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2051 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2052 MText *mt, int from, int to)
2054 MDrawControl control;
2056 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2057 memset (&control, 0, sizeof control);
2058 control.as_image = 1;
2059 return draw_text (frame, win, x, y, mt, from, to, &control);
2065 @brief Draw an M-text on a window with fine control.
2067 The mdraw_text_with_control () function draws the text between
2068 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2069 coordinate ($X, $Y).
2071 The way to draw a text is the same as in mdraw_text () except that
2072 this function also follows what specified in the drawing control
2075 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2076 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2077 breaks lines and the following characters are drawn in the next
2078 line. See the documentation of the structure @ MDrawControl for
2082 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2084 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2085 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2088 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2089 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2091 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2092 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2093 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2097 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2098 MText *mt, int from, int to, MDrawControl *control)
2100 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2101 return draw_text (frame, win, x, y, mt, from, to, control);
2107 @brief Compute text pixel width.
2109 The mdraw_text_extents () function computes the width of text
2110 between $FROM and $TO of M-text $MT when it is drawn on a window
2111 of frame $FRAME using the mdraw_text_with_control () function with
2112 the drawing control object $CONTROL.
2114 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2115 the bounding box of character ink of the M-text, and stores the
2116 results in the members of the structure pointed to by
2117 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2118 surrounding box, the box is included in the bounding box.
2120 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2121 computes the bounding box that provides mininum spacing to other
2122 graphical features (such as surrounding box) for the M-text, and
2123 stores the results in the members of the structure pointed to by
2124 $OVERALL_LOGICAL_RETURN.
2126 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2127 computes the bounding box that provides mininum spacing to the
2128 other M-text drawn, and stores the results in the members of the
2129 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2130 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2131 min_line_ascent, min_line_descent, max_line_ascent, and
2132 max_line_descent of $CONTROL are all zero.
2135 This function returns the width of the text to be drawn in the
2136 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2137 text is drawn in multiple physical lines, it returns the width of
2138 the widest line. If an error occurs, it returns -1 and assigns an
2139 error code to the external variable #merror_code. */
2143 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2145 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2146 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2147 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2149 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2150 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2151 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2152 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2154 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2155 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2156 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2157 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2159 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2160 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2161 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2162 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2163 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2164 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2166 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2167 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2168 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2169 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2171 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2178 mdraw_text_extents (MFrame *frame,
2179 MText *mt, int from, int to, MDrawControl *control,
2180 MDrawMetric *overall_ink_return,
2181 MDrawMetric *overall_logical_return,
2182 MDrawMetric *overall_line_return)
2184 MGlyphString *gstring;
2186 int width, rbearing;
2188 ASSURE_CONTROL (control);
2189 M_CHECK_POS_X (mt, from, -1);
2190 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2191 to = mtext_nchars (mt) + (control->cursor_width != 0);
2195 gstring = get_gstring (frame, mt, from, to, control);
2197 MERROR (MERROR_DRAW, -1);
2198 width = gstring_width (gstring, from, to, &rbearing);
2199 if (overall_ink_return)
2201 overall_ink_return->y = - gstring->physical_ascent;
2202 overall_ink_return->x = gstring->lbearing;
2204 if (overall_logical_return)
2206 overall_logical_return->y = - gstring->ascent;
2207 overall_logical_return->x = 0;
2209 if (overall_line_return)
2211 overall_line_return->y = - gstring->line_ascent;
2212 overall_line_return->x = gstring->lbearing;
2215 for (from = gstring->to; from < to; from = gstring->to)
2217 int this_width, this_rbearing;
2219 y += gstring->line_descent;
2220 M17N_OBJECT_UNREF (gstring->top);
2221 gstring = get_gstring (frame, mt, from, to, control);
2222 this_width = gstring_width (gstring, from, to, &this_rbearing);
2223 y += gstring->line_ascent;
2224 if (width < this_width)
2226 if (rbearing < this_rbearing)
2227 rbearing = this_rbearing;
2229 if (overall_ink_return)
2231 overall_ink_return->width = rbearing;
2232 overall_ink_return->height
2233 = y + gstring->physical_descent - overall_ink_return->y;
2235 if (overall_logical_return)
2237 overall_logical_return->width = width;
2238 overall_logical_return->height
2239 = y + gstring->descent - overall_logical_return->y;
2241 if (overall_line_return)
2243 overall_line_return->width = MAX (width, rbearing);
2244 overall_line_return->height
2245 = y + gstring->line_descent - overall_line_return->y;
2248 M17N_OBJECT_UNREF (gstring->top);
2255 @brief Compute the text dimensions of each character of M-text.
2257 The mdraw_text_per_char_extents () function computes the drawn
2258 metric of each character between $FROM and $TO of M-text $MT
2259 assuming that they are drawn on a window of frame $FRAME using the
2260 mdraw_text_with_control () function with the drawing control
2263 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2264 $LOGICAL_ARRAY_RETURN. Each successive element of
2265 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2266 ink and logical metrics of successive characters respectively,
2267 relative to the drawing origin of the M-text. The number of
2268 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2269 been set is returned to $NUM_CHARS_RETURN.
2271 If $ARRAY_SIZE is too small to return all metrics, the function
2272 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2273 Otherwise, it returns zero.
2275 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2276 @c NULL, this function also computes the metrics of the overall
2277 text and stores the results in the members of the structure
2278 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2280 If $CONTROL->two_dimensional is nonzero, this function computes
2281 only the metrics of characters in the first line. */
2283 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2285 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2286 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2287 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2288 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2290 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2291 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2292 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2293 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2294 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2296 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2297 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2300 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2301 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2302 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2305 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2306 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2309 mdraw_text_per_char_extents (MFrame *frame,
2310 MText *mt, int from, int to,
2311 MDrawControl *control,
2312 MDrawMetric *ink_array_return,
2313 MDrawMetric *logical_array_return,
2315 int *num_chars_return,
2316 MDrawMetric *overall_ink_return,
2317 MDrawMetric *overall_logical_return)
2319 MGlyphString *gstring;
2323 ASSURE_CONTROL (control);
2324 *num_chars_return = to - from;
2325 if (array_size < *num_chars_return)
2326 MERROR (MERROR_DRAW, -1);
2327 if (overall_logical_return)
2328 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2329 if (overall_ink_return)
2330 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2332 M_CHECK_RANGE (mt, from, to, -1, 0);
2333 gstring = get_gstring (frame, mt, from, to, control);
2336 *num_chars_return = 0;
2340 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2341 if (g->pos >= from && g->pos < to)
2345 int width = g->width;
2346 int lbearing = g->lbearing;
2347 int rbearing = g->rbearing;
2348 int ascent = g->ascent;
2349 int descent = g->descent;
2351 int logical_descent;
2353 if (g->rface->rfont)
2355 logical_ascent = g->rface->rfont->ascent;
2356 logical_descent = g->rface->rfont->descent;
2360 logical_ascent = g->rface->ascent;
2361 logical_descent = g->rface->descent;
2363 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2365 if (lbearing < width + g->lbearing)
2366 lbearing = width + g->lbearing;
2367 if (rbearing < width + g->rbearing)
2368 rbearing = width + g->rbearing;
2370 if (ascent < g->ascent)
2372 if (descent < g->descent)
2373 descent = g->descent;
2380 if (ink_array_return)
2382 ink_array_return[start - from].x = x + lbearing;
2383 ink_array_return[start - from].y = - ascent;
2384 ink_array_return[start - from].width = rbearing - lbearing;
2385 ink_array_return[start - from].height = ascent + descent;
2387 if (logical_array_return)
2389 logical_array_return[start - from].x = x;
2390 logical_array_return[start - from].y = - logical_descent;
2391 logical_array_return[start - from].height
2392 = logical_ascent + logical_descent;
2393 logical_array_return[start - from].width = width;
2401 if (overall_ink_return)
2403 overall_ink_return->y = - gstring->line_ascent;
2404 overall_ink_return->x = gstring->lbearing;
2405 overall_ink_return->width = x - gstring->lbearing;
2406 overall_ink_return->height = gstring->height;
2408 if (overall_logical_return)
2410 overall_logical_return->y = - gstring->ascent;
2411 overall_logical_return->x = 0;
2412 overall_logical_return->width = x;
2413 overall_logical_return->height = gstring->ascent + gstring->descent;
2416 M17N_OBJECT_UNREF (gstring->top);
2423 @brief Return the character position nearest to the coordinates.
2425 The mdraw_coordinates_position () function checks which character
2426 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2427 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2428 mdraw_text_with_control () function with the drawing control
2429 object $CONTROL. Here, the character position means the number of
2430 characters that precede the character in question in $MT, that is,
2431 the character position of the first character is 0.
2433 $FRAME is used only to get the default face information.
2436 If the glyph image of a character covers coordinate ($X, $Y),
2437 mdraw_coordinates_position () returns the character position of
2439 If $Y is less than the minimum Y-coordinate of the drawn area, it
2440 returns $FROM.\n\n\n
2441 If $Y is greater than the maximum Y-coordinate of the drawn area,
2442 it returns $TO.\n\n\n
2443 If $Y fits in with the drawn area but $X is less than the minimum
2444 X-coordinate, it returns the character position of the first
2445 character drawn on the line $Y.\n\n\n
2446 If $Y fits in with the drawn area but $X is greater than the
2447 maximum X-coordinate, it returns the character position of the
2448 last character drawn on the line $Y. */
2451 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2453 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2454 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2455 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2456 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2457 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2458 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2460 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2463 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2464 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2466 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2468 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2470 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2471 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2473 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2474 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2477 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2478 int x_offset, int y_offset, MDrawControl *control)
2480 MGlyphString *gstring;
2485 M_CHECK_POS_X (mt, from, -1);
2486 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2487 to = mtext_nchars (mt) + (control->cursor_width != 0);
2493 ASSURE_CONTROL (control);
2494 gstring = get_gstring (frame, mt, from, to, control);
2495 while (y + gstring->line_descent <= y_offset
2496 && gstring->to < to)
2499 y += gstring->line_descent;
2500 M17N_OBJECT_UNREF (gstring->top);
2501 gstring = get_gstring (frame, mt, from, to, control);
2502 y += gstring->line_ascent;
2505 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2506 if (! control->orientation_reversed)
2508 width = gstring->indent;
2509 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2510 if (g->pos >= from && g->pos < to)
2513 if (width > x_offset)
2519 width = - gstring->indent;
2520 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2521 if (g->pos >= from && g->pos < to)
2524 if (width < x_offset)
2528 if (g->type == GLYPH_ANCHOR
2529 && control->two_dimensional
2533 M17N_OBJECT_UNREF (gstring->top);
2541 @brief Compute information about a glyph.
2543 The mdraw_glyph_info () function computes information about a
2544 glyph that covers a character at position $POS of the M-text $MT
2545 assuming that the text is drawn from the character at $FROM of $MT
2546 on a window of frame $FRAME using the mdraw_text_with_control ()
2547 function with the drawing control object $CONTROL.
2549 The information is stored in the members of $INFO. */
2551 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2553 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2554 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2555 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2556 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2558 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2566 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2567 MDrawControl *control, MDrawGlyphInfo *info)
2569 MGlyphString *gstring;
2573 M_CHECK_RANGE_X (mt, from, pos, -1);
2575 ASSURE_CONTROL (control);
2576 gstring = get_gstring (frame, mt, from, pos + 1, control);
2578 MERROR (MERROR_DRAW, -1);
2579 while (gstring->to <= pos)
2581 y += gstring->line_descent;
2582 M17N_OBJECT_UNREF (gstring->top);
2583 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2584 y += gstring->line_ascent;
2586 info->line_from = gstring->from;
2587 if (info->line_from < from)
2588 info->line_from = from;
2589 info->line_to = gstring->to;
2592 if (! control->orientation_reversed)
2594 info->x = gstring->indent;
2595 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2596 info->x += g->width;
2600 info->x = - gstring->indent;
2601 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2602 info->x -= g->width;
2603 while (g[-1].to == g->to)
2606 info->from = g->pos;
2608 info->metrics.x = g->lbearing;
2609 info->metrics.y = - gstring->line_ascent;
2610 info->metrics.height = gstring->height;
2611 info->metrics.width = - g->lbearing + g->width;
2612 if (g->rface->rfont)
2613 info->font = &g->rface->rfont->font;
2616 /* info->logical_width is calculated later. */
2618 if (info->from > info->line_from)
2620 /* The logically previous glyph is on this line. */
2621 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2623 info->prev_from = g_tmp->pos;
2625 else if (info->line_from > 0)
2627 /* The logically previous glyph is on the previous line. */
2628 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2629 gstring->from, control);
2630 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2632 info->prev_from = g_tmp->pos;
2633 M17N_OBJECT_UNREF (gst->top);
2636 info->prev_from = -1;
2638 if (GLYPH_INDEX (g) > 1)
2639 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2640 else if (! control->orientation_reversed)
2642 if (info->line_from > 0)
2646 int p = gstring->from - 1;
2648 gst = get_gstring (frame, mt, p, gstring->from, control);
2649 g_tmp = gst->glyphs + (gst->used - 2);
2650 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2651 M17N_OBJECT_UNREF (gst->top);
2654 info->left_from = info->left_to = -1;
2658 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2662 int p = gstring->to;
2664 gst = get_gstring (frame, mt, p, p + 1, control);
2665 g_tmp = gst->glyphs + (gst->used - 2);
2666 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2667 M17N_OBJECT_UNREF (gst->top);
2670 info->left_from = info->left_to = -1;
2673 if (info->to < gstring->to)
2675 /* The logically next glyph is on this line. */
2676 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2678 info->next_to = g_tmp->to;
2680 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2682 /* The logically next glyph is on the next line. */
2684 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2685 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2687 info->next_to = g_tmp->to;
2688 M17N_OBJECT_UNREF (gst->top);
2693 for (info->logical_width = (g++)->width;
2694 g->pos == pos && g->type != GLYPH_ANCHOR;
2695 info->metrics.width += g->width, info->logical_width += (g++)->width);
2696 info->metrics.width += g[-1].rbearing - g[-1].width;
2698 if (g->type != GLYPH_ANCHOR)
2699 info->right_from = g->pos, info->right_to = g->to;
2700 else if (! control->orientation_reversed)
2702 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2705 M17N_OBJECT_UNREF (gstring->top);
2706 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2708 info->right_from = g->pos, info->right_to = g->to;
2711 info->right_from = info->right_to = -1;
2715 if (info->line_from > 0)
2717 pos = gstring->from - 1;
2718 M17N_OBJECT_UNREF (gstring->top);
2719 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2721 info->right_from = g->pos, info->right_to = g->to;
2724 info->right_from = info->right_to = -1;
2727 M17N_OBJECT_UNREF (gstring->top);
2734 @brief Compute information about glyph sequence.
2736 The mdraw_glyph_list () function computes information about glyphs
2737 corresponding to the text between $FROM and $TO of M-text $MT when
2738 it is drawn on a window of frame $FRAME using the
2739 mdraw_text_with_control () function with the drawing control
2740 object $CONTROL. $GLYPHS is an array of objects to store the
2741 information, and $ARRAY_SIZE is the array size.
2743 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2744 number of actually filled elements in the place pointed by
2745 $NUM_GLYPHS_RETURN, and returns 0.
2747 Otherwise, it stores the required array size in the place pointed
2748 by $NUM_GLYPHS_RETURN, and returns -1. */
2751 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2753 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
2754 À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
2755 ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
2756 ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2758 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
2759 ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
2768 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2769 MDrawControl *control, MDrawGlyph *glyphs,
2770 int array_size, int *num_glyphs_return)
2772 MGlyphString *gstring;
2777 ASSURE_CONTROL (control);
2778 *num_glyphs_return = 0;
2779 M_CHECK_RANGE (mt, from, to, -1, 0);
2780 gstring = get_gstring (frame, mt, from, to, control);
2783 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2785 if (g->type == GLYPH_BOX
2786 || g->pos < from || g->pos >= to)
2788 if (g->type == GLYPH_PAD)
2790 if (g->left_padding)
2791 pad_width = g->width;
2795 glyphs[-1].x_advance += g->width;
2801 glyphs->from = g->pos;
2803 glyphs->glyph_code = g->code;
2804 glyphs->x_off = g->xoff + pad_width;
2805 glyphs->y_off = g->yoff;
2806 glyphs->lbearing = g->lbearing;
2807 glyphs->rbearing = g->rbearing;
2808 glyphs->ascent = g->ascent;
2809 glyphs->descent = g->descent;
2810 glyphs->x_advance = g->width + pad_width;
2811 glyphs->y_advance = 0;
2812 if (g->rface->rfont)
2814 glyphs->font = &g->rface->rfont->font;
2815 glyphs->font_type = g->rface->rfont->type;
2816 glyphs->fontp = g->rface->rfont->fontp;
2820 glyphs->font = NULL;
2821 glyphs->font_type = Mnil;
2822 glyphs->fontp = NULL;
2829 M17N_OBJECT_UNREF (gstring->top);
2831 *num_glyphs_return = n;
2832 return (n <= array_size ? 0 : -1);
2838 @brief Draw one or more textitems.
2840 The mdraw_text_items () function draws one or more M-texts on
2841 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2842 of the textitems to be drawn and $NITEMS is the number of
2843 textimtems in the array. */
2846 @brief textitem ¤òɽ¼¨¤¹¤ë.
2848 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2849 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2850 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2853 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2857 MTextItem, mdraw_text (). */
2860 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2861 MDrawTextItem *items, int nitems)
2863 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2865 while (nitems-- > 0)
2868 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2870 mdraw_text_with_control (frame, win, x, y,
2871 items->mt, 0, mtext_nchars (items->mt),
2873 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2874 items->control, NULL, NULL, NULL);
2877 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2883 @brief calculate a line breaking position.
2885 The function mdraw_default_line_break () calculates a line
2886 breaking position based on the line number $LINE and the
2887 coordinate $Y, when a line is too long to fit within the width
2888 limit. $POS is the position of the character next to the last
2889 one that fits within the limit. $FROM is the position of the
2890 first character of the line, and TO is the position of the last
2891 character displayed on the line if there were not width limit.
2892 LINE and Y are reset to 0 when a line is broken by a newline
2893 character, and incremented each time when a long line is broken
2894 because of the width limit.
2897 This function returns a character position to break the
2902 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2904 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2905 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2906 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2907 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2908 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2909 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2910 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2913 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2917 mdraw_default_line_break (MText *mt, int pos,
2918 int from, int to, int line, int y)
2920 int c = mtext_ref_char (mt, pos);
2923 if (c == ' ' || c == '\t')
2927 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2934 if (c == ' ' || c == '\t')
2937 c = mtext_ref_char (mt, pos);
2950 @brief Obtain per character dimension information.
2952 The mdraw_per_char_extents () function computes the text dimension
2953 of each character in M-text $MT. The faces given as text
2954 properties in $MT and the default face of frame $FRAME determine
2955 the fonts to draw the text. Each successive element in
2956 $ARRAY_RETURN is set to the drawn metrics of successive
2957 characters, which is relative to the origin of the drawing, and a
2958 rectangle for each character in $MT. The number of elements of
2959 $ARRAY_RETURN must be equal to or greater than the number of
2962 If pointer $OVERALL_RETURN is not @c NULL, this function also
2963 computes the extents of the overall text and stores the results in
2964 the members of the structure pointed to by $OVERALL_RETURN. */
2967 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2969 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2970 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2971 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2972 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2973 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2974 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2977 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2978 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2981 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2984 mdraw_per_char_extents (MFrame *frame, MText *mt,
2985 MDrawMetric *array_return,
2986 MDrawMetric *overall_return)
2988 int n = mtext_nchars (mt);
2990 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2991 n, &n, overall_return, NULL);
2995 @brief clear cached information.
2997 The mdraw_clear_cache () function clear cached information
2998 on M-text $MT that was attached by any of the drawing functions.
2999 When the behaviour of `format' or `line_break'
3000 member functions of MDrawControl is changed, the cache must be cleared.
3005 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3007 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
3008 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
3009 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
3010 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3015 mdraw_clear_cache (MText *mt)
3017 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);