1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-texts on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layout
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face
44 ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include <sys/types.h>
64 #include "m17n-misc.h"
68 #include "internal-gui.h"
73 #include <fribidi/fribidi.h>
74 #endif /* HAVE_FRIBIDI */
76 #define MAX(x, y) ((x) > (y) ? (x) : (y))
77 #define MIN(x, y) ((x) < (y) ? (x) : (y))
79 static MSymbol M_glyph_string;
82 static MSymbol Minherited;
83 /* Special categories */
84 static MSymbol McatCc, McatCf;
87 /* Glyph-string composer. */
89 static MSymbol MbidiR;
90 static MSymbol MbidiAL;
91 static MSymbol MbidiRLE;
92 static MSymbol MbidiRLO;
93 static MSymbol MbidiBN;
94 static MSymbol MbidiS;
97 visual_order (MGlyphString *gstring)
99 int len = gstring->used - 2;
101 int bidi_sensitive = gstring->control.orientation_reversed;
105 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
106 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
108 FriBidiStrIndex *indices;
109 FriBidiLevel *levels;
110 #else /* not HAVE_FRIBIDI */
111 int *logical = alloca (sizeof (int) * len);
113 char *levels = alloca (len);
114 #endif /* not HAVE_FRIBIDI */
116 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
121 #endif /* not HAVE_FRIBIDI */
124 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
126 if (bidi == MbidiR || bidi == MbidiAL
127 || bidi == MbidiRLE || bidi == MbidiRLO)
132 #endif /* not HAVE_FRIBIDI */
138 if (! bidi_sensitive)
141 glyphs = alloca (sizeof (MGlyph) * len);
142 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
144 visual = alloca (sizeof (FriBidiChar) * (len + 1));
145 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
146 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
148 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
149 #else /* not HAVE_FRIBIDI */
150 indices = alloca (sizeof (int) * len);
151 for (i = 0; i < len; i++)
157 for (j = i + 1; j < len && levels[j]; j++);
158 for (k = j--; i < k; i++, j--)
165 #endif /* not HAVE_FRIBIDI */
167 for (i = 0; i < len;)
169 /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
171 /* Length of grapheme-cluster */
176 if (visual[j] != logical[i])
181 g->code = mfont__encode_char (g->rface->rfont, g->c);
183 #endif /* HAVE_FRIBIDI */
184 g->bidi_level = levels[i];
185 for (seglen = 1, g++;
186 i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
187 || glyphs[i + seglen].combining_code);
190 g->bidi_level = levels[i];
191 if (indices[i + seglen] < j)
192 j = indices[i + seglen];
194 memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
200 reorder_combining_chars (MGlyphString *gstring, int from, int to)
202 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
208 for (g = gbeg; g != gend; g++)
209 if (COMBINING_CODE_CLASS (g->combining_code) > 0
210 && (COMBINING_CODE_CLASS (g[-1].combining_code)
211 > COMBINING_CODE_CLASS (g->combining_code)))
222 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
223 displaying them on FRAME.
225 This function fills these members:
226 pos, to, c, code, rface, bidi_level, categories, type, combining_code
227 The other members are filled by layout_glyph_string. */
230 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
231 MGlyphString *gstring)
233 MRealizedFace *default_rface = frame->rface;
234 int stop, face_change, language_change, charset_change;
235 MGlyph g_tmp, *g, *last_g;
237 MSymbol language = Mnil, script = Mnil, charset = Mnil;
238 MSymbol non_latin_script = Mnil;
239 MRealizedFace *rface = default_rface;
240 MRealizedFont *rfont;
241 int size = gstring->control.fixed_width;
244 MLIST_RESET (gstring);
245 gstring->from = from;
247 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
248 <category> and <rface> members.*/
251 /** Put anchor glyphs at the head and tail. */
252 g_tmp.type = GLYPH_ANCHOR;
253 g_tmp.pos = g_tmp.to = from;
254 APPEND_GLYPH (gstring, g_tmp);
255 stop = face_change = pos = from;
265 if (pos == face_change)
268 int num = mtext_get_prop_values (mt, pos, Mface,
269 (void **) faces, 64);
271 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
272 if (face_change == mtext_nchars (mt))
274 rface = (num > 0 ? mface__realize (frame, faces, num, size)
278 if (stop > face_change)
282 if (pos < mtext_nchars (mt))
283 c = mtext_ref_char (mt, pos);
287 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
292 category = mchar_get_prop (c, Mcategory);
293 if (category == McatCf)
294 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
295 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
296 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
298 g_tmp.category = GLYPH_CATEGORY_NORMAL;
300 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
304 ctrl[0] = ctrl[1] = g_tmp;
306 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
307 APPEND_GLYPH (gstring, ctrl[0]);
308 APPEND_GLYPH (gstring, ctrl[1]);
311 APPEND_GLYPH (gstring, g_tmp);
312 if (c == '\n' && gstring->control.two_dimensional)
315 /* Append an anchor glyph. */
317 g_tmp.type = GLYPH_ANCHOR;
318 g_tmp.pos = g_tmp.to = pos;
319 APPEND_GLYPH (gstring, g_tmp);
322 /* The next loop is to change each <rface> member for non-ASCII
323 characters if necessary. */
324 stop = charset_change = language_change = from;
325 rfont = default_rface->rfont;
326 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
332 /* Short cut for the obvious case. */
333 this_script = Mlatin;
336 this_script = (MSymbol) mchar_get_prop (c, Mscript);
337 if (this_script == Minherited || this_script == Mnil)
338 this_script = script;
339 if (this_script == Mnil)
340 this_script = non_latin_script;
341 if (this_script == Mnil)
343 /* Search forward for a character that explicitly
344 specifies a non-latin script. */
348 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
350 && (sym = mchar_get_prop (g1->c, Mscript)) != Mnil
351 && sym != Minherited)
360 if (pos == stop || script != this_script || g->rface->rfont != rfont)
363 last_g = mface__for_chars (script, language, charset,
365 script = this_script;
366 if (script != Mnil && script != Mlatin)
367 non_latin_script = script;
368 rfont = g->rface->ascii_rface->rfont;
371 if (pos < mtext_nchars (mt) && pos == language_change)
373 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
374 mtext_prop_range (mt, Mlanguage, pos, NULL,
375 &language_change, 0);
377 if (pos < mtext_nchars (mt) && pos == charset_change)
379 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
380 mtext_prop_range (mt, Mcharset, pos, NULL,
384 if (stop > language_change)
385 stop = language_change;
386 if (stop > charset_change)
387 stop = charset_change;
392 last_g = mface__for_chars (script, language, charset, last_g, g, size);
394 /* The next loop is to run FLT or perform the default combining if
396 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
400 if (this->type == GLYPH_CHAR && this->rface->rfont)
404 if (this->rface->rfont->layouter != Mnil)
409 for (prev = MGLYPH (start - 1);
410 (prev->type == GLYPH_CHAR
411 && prev->category == GLYPH_CATEGORY_FORMATTER
412 && (code = mfont__encode_char (this->rface->rfont, prev->c)
413 != MCHAR_INVALID_CODE));
418 (g->type == GLYPH_CHAR
419 && (g->rface->rfont == this->rface->rfont
420 || (g->category == GLYPH_CATEGORY_FORMATTER
421 && ((code = mfont__encode_char (this->rface->rfont,
423 != MCHAR_INVALID_CODE))));
425 if (g->rface->rfont != this->rface->rfont)
427 g->rface->rfont = this->rface->rfont;
430 i = mfont__flt_run (gstring, start, i, this->rface);
434 while (this->type == GLYPH_CHAR
436 && this->category == GLYPH_CATEGORY_MODIFIER
437 && this->rface->rfont
438 && this->rface->rfont->layouter == Mnil)
440 int class = (int) mchar_get_prop (this->c,
443 = MAKE_COMBINING_CODE_BY_CLASS (class);
447 reorder_combining_chars (gstring, start, i);
448 if (this->type == GLYPH_ANCHOR)
457 /* At last, reorder glyphs visually if necessary. */
458 if (gstring->control.enable_bidi)
459 visual_order (gstring);
464 combining_code_from_class (int class)
469 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
470 else if (class == 200) /* below left attached */
471 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
472 else if (class == 202) /* below attached*/
473 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
474 else if (class == 204) /* below right attached */
475 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
476 else if (class == 208) /* left attached */
477 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
478 else if (class == 210) /* right attached */
479 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
480 else if (class == 212) /* above left attached */
481 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
482 else if (class == 214) /* above attached */
483 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
484 else if (class == 216) /* above right attached */
485 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
486 else if (class == 218) /* below left */
487 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
488 else if (class == 220) /* below */
489 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
490 else if (class == 222) /* below right */
491 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
492 else if (class == 224) /* left */
493 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
494 else if (class == 226) /* right */
495 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
496 else if (class == 228) /* above left */
497 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
498 else if (class == 230) /* above */
499 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
500 else if (class == 232) /* above right */
501 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
502 else if (class == 233) /* double below */
503 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
504 else if (class == 234) /* double above */
505 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
506 else if (class == 240) /* iota subscript */
507 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
509 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
515 int width, lbearing, rbearing;
519 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
520 MSubTextExtents *extents)
522 int g_physical_ascent, g_physical_descent;
523 MGlyph *g = MGLYPH (from);
524 MGlyph *last_g = MGLYPH (to);
527 g_physical_ascent = gstring->physical_ascent;
528 g_physical_descent = gstring->physical_descent;
529 extents->width = extents->lbearing = extents->rbearing = 0;
531 for (i = from; i < to;)
533 if ( MGLYPH (i)->otf_encoded)
539 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
540 mfont__get_metric (gstring, j, i);
548 MRealizedFont *rfont = base->rface->rfont;
549 int size = rfont->font.property[MFONT_SIZE];
550 int width, lbearing, rbearing;
552 if (g == last_g || ! g->combining_code)
555 if (base->width == 0 && ! base->left_padding && ! base->right_padding
556 && GLYPH_INDEX (base) > from)
558 MGlyph *prev = base - 1;
560 if (base->pos < prev->pos)
561 prev->pos = base->pos;
563 base->pos = prev->pos;
564 if (base->to > prev->to)
570 if (base->left_padding && base->lbearing < 0)
572 base->xoff = - base->lbearing;
573 base->width += base->xoff;
574 base->rbearing += base->xoff;
577 if (base->right_padding && base->rbearing > base->width)
579 base->width = base->rbearing;
581 lbearing = (base->xoff + base->lbearing < 0
582 ? base->xoff + base->lbearing : 0);
583 rbearing = base->xoff + base->rbearing;
587 /* With combining glyphs. */
588 int left = -base->width;
590 int top = - base->ascent;
591 int bottom = base->descent;
592 int height = bottom - top;
593 int begin = base->pos;
598 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
599 rbearing = base->rbearing;
601 while (g != last_g && g->combining_code)
603 int combining_code = g->combining_code;
607 else if (end < g->to)
610 if (! COMBINING_PRECOMPUTED_P (combining_code))
612 int base_x, base_y, add_x, add_y, off_x, off_y;
614 if (COMBINING_BY_CLASS_P (combining_code))
615 g->combining_code = combining_code
616 = combining_code_from_class (COMBINING_CODE_CLASS
619 rfont = g->rface->rfont;
620 size = rfont->font.property[MFONT_SIZE];
621 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
623 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
625 base_x = COMBINING_CODE_BASE_X (combining_code);
626 base_y = COMBINING_CODE_BASE_Y (combining_code);
627 add_x = COMBINING_CODE_ADD_X (combining_code);
628 add_y = COMBINING_CODE_ADD_Y (combining_code);
630 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
633 if (g->xoff + g->width > right)
634 right = g->xoff + g->width;
635 width = right - left;
638 g->yoff = top + height * base_y / 2;
642 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
646 if (g->xoff + g->lbearing < left + lbearing)
647 lbearing = g->xoff + g->lbearing - left;
648 if (g->xoff + g->rbearing > left + rbearing)
649 rbearing = g->xoff + g->rbearing - left;
650 if (g->yoff - g->ascent < top)
651 top = g->yoff - g->ascent;
652 if (g->yoff + g->descent > bottom)
653 bottom = g->yoff + g->descent;
654 height = bottom - top;
660 base->ascent = - top;
661 base->descent = bottom;
662 base->lbearing = lbearing;
663 base->rbearing = rbearing;
664 if (left < - base->width)
666 base->xoff = - base->width - left;
667 base->width += base->xoff;
668 base->rbearing += base->xoff;
669 base->lbearing += base->xoff;
673 base->width += right;
674 base->rbearing += right;
675 base->right_padding = 1;
676 for (i = 1; base + i != g; i++)
677 base[i].xoff -= right;
680 for (i = 0; base + i != g; i++)
687 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
688 g_physical_descent = MAX (g_physical_descent, base->descent);
689 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
690 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
691 extents->width += base->width;
694 gstring->physical_ascent = g_physical_ascent;
695 gstring->physical_descent = g_physical_descent;
699 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
700 by this function directly. Character glyphs are handled by
701 layouter functions registered in font drivers.
703 This function fill-in all the remaining members of glyphs. */
706 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
708 /* Default width of TAB. */
709 int tab_width = frame->space_width * (gstring->control.tab_width
710 ? gstring->control.tab_width : 8);
714 MDrawControl *control = &(gstring->control);
717 int box_line_height = 0;
718 int ignore_formatting_char = control->ignore_formatting_char;
720 gstring->ascent = gstring->descent = 0;
721 gstring->physical_ascent = gstring->physical_descent = 0;
722 gstring->width = gstring->lbearing = gstring->rbearing = 0;
726 while (g->type != GLYPH_ANCHOR)
728 if (box != g->rface->box)
730 int gidx = GLYPH_INDEX (g);
734 /* Insert the right side of the box. That glyph belongs
735 to the previous grapheme cluster. */
736 MGlyph box_glyph = g[-1];
738 box_glyph.type = GLYPH_BOX;
740 = (control->fixed_width
742 : box->inner_hmargin + box->width + box->outer_hmargin);
743 box_glyph.lbearing = 0;
744 box_glyph.rbearing = box_glyph.width;
746 box_glyph.right_padding = 1;
747 gstring->width += box_glyph.width;
748 gstring->rbearing += box_glyph.width;
749 INSERT_GLYPH (gstring, gidx, box_glyph);
756 /* Insert the left side of the box. That glyph belongs
757 to the following grapheme cluster. */
758 MGlyph box_glyph = *g;
759 int box_height = (box->width
760 + box->inner_vmargin + box->outer_vmargin);
762 if (box_line_height < box_height)
763 box_line_height = box_height;
764 box_glyph.type = GLYPH_BOX;
766 = (control->fixed_width
768 : box->inner_hmargin + box->width + box->outer_hmargin);
769 box_glyph.lbearing = 0;
770 box_glyph.rbearing = box_glyph.width;
772 box_glyph.left_padding = 1;
773 gstring->width += box_glyph.width;
774 gstring->rbearing += box_glyph.width;
775 INSERT_GLYPH (gstring, gidx, box_glyph);
781 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
782 g->type = GLYPH_SPACE;
784 if (g->type == GLYPH_CHAR)
786 MRealizedFace *rface = g->rface;
787 MRealizedFont *rfont = rface->rfont;
789 int from = GLYPH_INDEX (g);
791 for (g++; g->type == GLYPH_CHAR; g++)
792 if (! rfont != ! g->rface->rfont
793 || box != g->rface->box
794 || ((fromg->code == MCHAR_INVALID_CODE)
795 != (g->code == MCHAR_INVALID_CODE))
796 || (g->category == GLYPH_CATEGORY_FORMATTER
797 && ignore_formatting_char))
799 if (rfont && fromg->code != MCHAR_INVALID_CODE)
802 int to = GLYPH_INDEX (g);
803 MSubTextExtents extents;
805 layout_glyphs (frame, gstring, from, to, &extents);
806 extra_width = - extents.lbearing;
808 && ! control->disable_overlapping_adjustment
809 && (! control->orientation_reversed
810 ? ((to > 1 || control->align_head)
811 && g->type != GLYPH_ANCHOR)
812 : (((g->type && GLYPH_ANCHOR) || control->align_head)
817 pad.type = GLYPH_PAD;
820 pad.width = pad.rbearing = extra_width;
821 pad.left_padding = 1;
822 INSERT_GLYPH (gstring, from, pad);
824 extents.lbearing = 0;
825 extents.width += extra_width;
826 extents.rbearing += extra_width;
828 g = MGLYPH (from - 1);
829 if (g->type == GLYPH_SPACE)
831 /* The pad just inserted is absorbed (maybe
832 partially) by the previous space while
833 keeping at least some space width. For the
834 moment, we use the arbitrary width 2-pixel.
835 Perhaps, it should be decided by the current
836 face, or a default value of the current
837 frame, which is, however, not yet
839 if (extra_width + 2 < g->width)
841 g->width -= extra_width;
845 extra_width = g->width - 2;
848 gstring->width -= extra_width;
849 gstring->rbearing -= extra_width;
854 extra_width = extents.rbearing - extents.width;
856 && ! control->disable_overlapping_adjustment
857 && (GLYPH_INDEX (g) < gstring->used - 1
858 || (control->orientation_reversed && control->align_head)))
860 if (g->type == GLYPH_SPACE && box == g->rface->box)
863 pad.type = GLYPH_PAD;
866 pad.width = pad.rbearing = extra_width;
867 INSERT_GLYPH (gstring, to, pad);
872 g[-1].width += extra_width;
873 extents.width += extra_width;
876 if (gstring->lbearing > gstring->width + extents.lbearing)
877 gstring->lbearing = gstring->width + extents.lbearing;
878 if (gstring->rbearing < gstring->width + extents.rbearing)
879 gstring->rbearing = gstring->width + extents.rbearing;
880 gstring->width += extents.width;
881 if (gstring->ascent < rface->ascent)
882 gstring->ascent = rface->ascent;
883 if (gstring->descent < rface->descent)
884 gstring->descent = rface->descent;
888 for (; fromg < g; fromg++)
890 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
891 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
892 fromg->width = fromg->rbearing = 1;
894 fromg->width = fromg->rbearing = rface->space_width;
895 fromg->xoff = fromg->lbearing = 0;
896 fromg->ascent = fromg->descent = 0;
897 gstring->width += fromg->width;
898 gstring->rbearing += fromg->width;
900 if (gstring->ascent < frame->rface->ascent)
901 gstring->ascent = frame->rface->ascent;
902 if (gstring->descent < frame->descent)
903 gstring->descent = frame->rface->descent;
906 else if (g->type == GLYPH_SPACE)
909 g->width = g->rface->space_width;
910 else if (g->c == '\n')
912 g->width = control->cursor_width;
915 if (control->cursor_bidi)
917 else if (g->width < 0)
918 g->width = g->rface->space_width;
921 else if (g->c == '\t')
923 g->width = tab_width - ((gstring->indent + gstring->width)
929 if (g[-1].type == GLYPH_PAD)
931 /* This space glyph absorbs (maybe partially) the
932 previous padding glyph. */
933 g->width -= g[-1].width;
935 /* But, keep at least some space width. For the
936 moment, we use the arbitrary width 2-pixel. */
939 g->rbearing = g->width;
940 gstring->width += g->width;
941 gstring->rbearing += g->width;
944 if (gstring->ascent < g->rface->ascent)
945 gstring->ascent = g->rface->ascent;
946 if (gstring->descent < g->rface->descent)
947 gstring->descent = g->rface->descent;
953 gstring->width += g->width;
954 gstring->rbearing += g->width;
961 /* Insert the right side of the box. */
962 int gidx = GLYPH_INDEX (g);
963 MGlyph box_glyph = g[-1];
965 box_glyph.type = GLYPH_BOX;
967 = (control->fixed_width
969 : box->inner_hmargin + box->width + box->outer_hmargin);
970 box_glyph.lbearing = 0;
971 box_glyph.rbearing = box_glyph.width;
973 box_glyph.right_padding = 1;
974 gstring->width += box_glyph.width;
975 gstring->rbearing += box_glyph.width;
976 INSERT_GLYPH (gstring, gidx, box_glyph);
979 gstring->text_ascent = gstring->ascent;
980 gstring->text_descent = gstring->descent;
981 if (gstring->text_ascent < gstring->physical_ascent)
982 gstring->text_ascent = gstring->physical_ascent;
983 if (gstring->text_descent < gstring->physical_descent)
984 gstring->text_descent = gstring->physical_descent;
985 gstring->line_ascent = gstring->text_ascent;
986 gstring->line_descent = gstring->text_descent;
987 if (box_line_height > 0)
989 gstring->line_ascent += box_line_height;
990 gstring->physical_ascent = gstring->line_ascent;
991 gstring->line_descent += box_line_height;
992 gstring->physical_descent = gstring->line_descent;
995 if (gstring->line_ascent < control->min_line_ascent)
996 gstring->line_ascent = control->min_line_ascent;
997 else if (control->max_line_ascent
998 && control->max_line_ascent > control->min_line_ascent
999 && gstring->line_ascent > control->max_line_ascent)
1000 gstring->line_ascent = control->max_line_ascent;
1002 if (gstring->line_descent < control->min_line_descent)
1003 gstring->line_descent = control->min_line_descent;
1004 else if (control->max_line_descent
1005 && control->max_line_descent > control->min_line_descent
1006 && gstring->line_descent > control->max_line_descent)
1007 gstring->line_descent = control->max_line_descent;
1008 gstring->height = gstring->line_ascent + gstring->line_descent;
1010 if (control->orientation_reversed
1013 /* We must adjust TAB width for RTL orientation. */
1014 width = gstring->indent;
1016 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1018 if (g->type == GLYPH_CHAR && g->c == '\t')
1020 int this_width = tab_width - (width % tab_width);
1022 if (g[1].type == GLYPH_PAD)
1023 this_width -= g[1].width;
1024 if (g[-1].type == GLYPH_PAD)
1025 this_width -= g[-1].width;
1028 gstring->width += this_width - g->width;
1029 gstring->rbearing += this_width - g->width;
1030 g->width = this_width;
1031 width += this_width;
1041 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1042 MGlyphString *gstring, int from, int to,
1043 int *from_idx, int *to_idx, int *to_x)
1045 MGlyph *g = MGLYPH (1);
1046 MDrawRegion region = (MDrawRegion) NULL;
1047 MDrawControl *control = &gstring->control;
1048 int cursor_pos = -1;
1050 int cursor_bidi = control->cursor_bidi;
1052 if (control->with_cursor && control->cursor_width)
1054 if (gstring->from <= control->cursor_pos
1055 && gstring->to > control->cursor_pos)
1056 cursor_pos = control->cursor_pos;
1059 && gstring->from <= control->cursor_pos - 1
1060 && gstring->to > control->cursor_pos - 1)
1061 prev_pos = control->cursor_pos - 1;
1064 *from_idx = *to_idx = 0;
1065 while (g->type != GLYPH_ANCHOR)
1067 if (g->pos >= from && g->pos < to)
1069 MGlyph *fromg = g, *cursor = NULL;
1070 MRealizedFace *rface = g->rface;
1072 int cursor_width = 0;
1076 *from_idx = GLYPH_INDEX (g);
1077 while (g->pos >= from && g->pos < to
1078 && g->rface == rface)
1081 if (g->type != GLYPH_BOX
1082 && g->pos <= cursor_pos && g->to > cursor_pos)
1085 cursor = g, cursor_x = x + width;
1086 cursor_width += g->width;
1088 width += g++->width;
1091 && (control->as_image
1092 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1094 int this_x = x, this_width = width;
1096 if (fromg->type == GLYPH_BOX)
1097 this_x += fromg->width, this_width -= fromg->width;
1098 if (g[-1].type == GLYPH_BOX)
1099 this_width -= g[-1].width;
1100 (frame->driver->fill_space)
1101 (frame, win, rface, 0,
1102 this_x, y - gstring->text_ascent, this_width,
1103 gstring->text_ascent + gstring->text_descent,
1104 control->clip_region);
1111 rect.y = y - gstring->text_ascent;
1112 rect.height = gstring->text_ascent + gstring->text_descent;
1115 rect.width = ((control->cursor_width > 0
1116 && control->cursor_width < cursor_width)
1117 ? control->cursor_width : cursor_width);
1121 if (cursor->bidi_level % 2)
1122 rect.x += cursor_width - rect.width;
1123 (*frame->driver->fill_space)
1124 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1125 control->clip_region);
1127 region = (*frame->driver->region_from_rect) (&rect);
1129 (*frame->driver->region_add_rect) (region, &rect);
1132 if (cursor->bidi_level % 2)
1135 rect.width = cursor_width < 4 ? cursor_width : 4;
1136 (*frame->driver->fill_space)
1137 (frame, win, rface, 1,
1138 rect.x, rect.y, rect.width, rect.height,
1139 control->clip_region);
1140 (*frame->driver->region_add_rect) (region, &rect);
1152 if (fromg->type != GLYPH_BOX
1153 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1156 cursor = fromg, cursor_x = x + temp_width;
1157 cursor_width += fromg->width;
1159 temp_width += fromg++->width;
1166 if (! (cursor->bidi_level % 2))
1167 rect.x += cursor_width - 1;
1168 rect.y = y - gstring->text_ascent;
1169 rect.height = gstring->text_ascent + gstring->text_descent;
1171 (*frame->driver->fill_space)
1172 (frame, win, rface, 1,
1173 rect.x, rect.y, rect.width, rect.height,
1174 control->clip_region);
1176 region = (*frame->driver->region_from_rect) (&rect);
1178 (*frame->driver->region_add_rect) (region, &rect);
1179 rect.y += rect.height - 2;
1181 rect.width = cursor_width < 4 ? cursor_width : 4;
1182 if (! (cursor->bidi_level % 2))
1183 rect.x -= rect.width - 1;
1184 (*frame->driver->fill_space) (frame, win, rface, 1,
1185 rect.x, rect.y, rect.width, rect.height,
1186 control->clip_region);
1187 (*frame->driver->region_add_rect) (region, &rect);
1191 *to_idx = GLYPH_INDEX (g);
1201 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1202 MGlyphString *gstring, int from_idx, int to_idx,
1203 int reverse, MDrawRegion region)
1205 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1211 (*frame->driver->region_to_rect) (region, &rect);
1214 while (g != gend && x + g->rbearing <= rect.x)
1217 width -= g++->width;
1218 while (! g->enabled && g != gend)
1222 rect.x += rect.width;
1223 if (rect.x < x + width)
1226 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1228 width -= (--gend)->width;
1229 while (! gend->enabled && g != gend)
1233 while (gend[-1].to == gend->to) gend++;
1241 MRealizedFace *rface = g->rface;
1242 int width = g->width;
1243 MGlyph *from_g = g++;
1245 /* Handle the glyphs of the same type/face at once. */
1247 && g->type == from_g->type
1248 && g->rface == rface
1249 && ((g->code == MCHAR_INVALID_CODE)
1250 == (from_g->code == MCHAR_INVALID_CODE))
1252 width += g++->width;
1254 if (from_g->type == GLYPH_CHAR)
1256 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1257 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1260 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1263 else if (from_g->type == GLYPH_BOX)
1265 /* Draw the left or right side of a box. If
1266 from_g->lbearing is nonzero, this is the left side,
1267 else this is the right side. */
1268 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1271 if (from_g->type != GLYPH_BOX)
1274 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1275 x, y, width, region);
1278 /* Draw the top and bottom side of a box. */
1279 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1280 x, y, width, region);
1291 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1292 int *from_x, int *to_x)
1295 int left_idx = *left, right_idx = *right;
1296 int left_x, right_x, x;
1298 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1301 if (x + g->rbearing > 0)
1303 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1305 left_idx = GLYPH_INDEX (g);
1310 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1313 if (x - g->width + g->lbearing < 0)
1315 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1317 right_idx = GLYPH_INDEX (g) + 1;
1322 if (*left == left_idx && *right == right_idx)
1325 if (*left != left_idx)
1327 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1332 if (*right != right_idx)
1334 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1344 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1349 if (from <= gstring->from && to >= gstring->to)
1352 *rbearing = gstring->rbearing;
1353 return gstring->width;
1358 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1359 if (g->pos >= from && g->pos < to)
1361 if (rbearing && width + g->rbearing > *rbearing)
1362 *rbearing = width + g->rbearing;
1370 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1371 MGlyphString *gstring, int from, int to)
1373 MDrawControl *control = &gstring->control;
1375 MDrawRegion clip_region, cursor_region;
1376 int from_idx, to_idx;
1379 if (control->orientation_reversed)
1380 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1382 x += gstring->indent;
1384 /* At first, draw all glyphs without cursor. */
1385 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1386 &from_idx, &to_idx, &to_x);
1388 if (control->partial_update)
1391 rect.width = to_x - x;
1392 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1394 rect.y = y - gstring->line_ascent;
1395 rect.height = gstring->height;
1396 clip_region = (*frame->driver->region_from_rect) (&rect);
1397 if (control->clip_region)
1398 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1401 clip_region = control->clip_region;
1404 clip_region = control->clip_region;
1406 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1411 (*frame->driver->intersect_region) (cursor_region, clip_region);
1412 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1415 if (clip_region != control->clip_region)
1416 (*frame->driver->free_region) (clip_region);
1418 (*frame->driver->free_region) (cursor_region);
1422 static int gstring_num;
1425 free_gstring (void *object)
1427 MGlyphString *gstring = (MGlyphString *) object;
1430 free_gstring (gstring->next);
1431 if (gstring->size > 0)
1432 free (gstring->glyphs);
1438 static MGlyphString scratch_gstring;
1440 static MGlyphString *
1441 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1444 MGlyphString *gstring;
1446 if (pos == mt->nchars)
1450 gstring = &scratch_gstring;
1451 if (gstring->size == 0)
1456 g_tmp.type = GLYPH_ANCHOR;
1457 APPEND_GLYPH (gstring, g_tmp);
1458 APPEND_GLYPH (gstring, g_tmp);
1459 APPEND_GLYPH (gstring, g_tmp);
1460 gstring->glyphs[1].type = GLYPH_SPACE;
1461 gstring->glyphs[1].c = '\n';
1462 gstring->glyphs[1].code = '\n';
1464 gstring->from = pos;
1466 g->rface = frame->rface;
1467 g->pos = g->to = pos;
1469 g->rface = frame->rface;
1470 g->pos = pos++, g->to = pos;
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 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1918 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1919 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1920 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1921 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1923 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1924 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1928 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1929 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1930 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1931 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1932 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1933 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1935 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1936 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1938 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1939 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1940 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1942 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1943 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1945 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1946 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1948 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1949 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1951 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1952 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1956 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1958 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1959 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1961 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1962 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1965 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1966 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1968 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1975 mdraw_image_text () */
1978 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1979 MText *mt, int from, int to)
1981 MDrawControl control;
1983 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1984 memset (&control, 0, sizeof control);
1985 control.as_image = 0;
1986 return draw_text (frame, win, x, y, mt, from, to, &control);
1993 @brief Draw an M-text on a window as an image.
1995 The mdraw_image_text () function draws the text between $FROM and
1996 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1997 coordinate ($X, $Y).
1999 The way to draw a text is the same as in mdraw_text () except that
2000 this function also draws the background with the color specified
2003 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2004 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2005 functions in the X Window System.
2008 If the operation was successful, mdraw_image_text () returns 0.
2009 If an error is detected, it returns -1 and assigns an error code
2010 to the external variable #merror_code. */
2013 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2015 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
2016 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
2017 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
2019 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
2020 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2022 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2023 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
2027 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
2028 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2030 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2040 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2041 MText *mt, int from, int to)
2043 MDrawControl control;
2045 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2046 memset (&control, 0, sizeof control);
2047 control.as_image = 1;
2048 return draw_text (frame, win, x, y, mt, from, to, &control);
2054 @brief Draw an M-text on a window with fine control.
2056 The mdraw_text_with_control () function draws the text between
2057 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2058 coordinate ($X, $Y).
2060 The way to draw a text is the same as in mdraw_text () except that
2061 this function also follows what specified in the drawing control
2064 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2065 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2066 breaks lines and the following characters are drawn in the next
2067 line. See the documentation of the structure @ MDrawControl for
2071 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2073 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2074 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2077 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2078 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2080 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2081 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2082 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2085 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2086 MText *mt, int from, int to, MDrawControl *control)
2088 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2089 return draw_text (frame, win, x, y, mt, from, to, control);
2095 @brief Compute text pixel width.
2097 The mdraw_text_extents () function computes the width of text
2098 between $FROM and $TO of M-text $MT when it is drawn on a window
2099 of frame $FRAME using the mdraw_text_with_control () function with
2100 the drawing control object $CONTROL.
2102 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2103 the bounding box of character ink of the M-text, and stores the
2104 results in the members of the structure pointed to by
2105 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2106 surrounding box, the box is included in the bounding box.
2108 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2109 computes the bounding box that provides minimum spacing to other
2110 graphical features (such as surrounding box) for the M-text, and
2111 stores the results in the members of the structure pointed to by
2112 $OVERALL_LOGICAL_RETURN.
2114 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2115 computes the bounding box that provides minimum spacing to the
2116 other M-text drawn, and stores the results in the members of the
2117 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2118 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2119 min_line_ascent, min_line_descent, max_line_ascent, and
2120 max_line_descent of $CONTROL are all zero.
2123 This function returns the width of the text to be drawn in the
2124 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2125 text is drawn in multiple physical lines, it returns the width of
2126 the widest line. If an error occurs, it returns -1 and assigns an
2127 error code to the external variable #merror_code. */
2131 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2133 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2134 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2135 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2137 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2138 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2139 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2140 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2142 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2143 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2144 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2145 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2147 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2148 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2149 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2150 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2151 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2152 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2155 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2156 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2157 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2159 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2166 mdraw_text_extents (MFrame *frame,
2167 MText *mt, int from, int to, MDrawControl *control,
2168 MDrawMetric *overall_ink_return,
2169 MDrawMetric *overall_logical_return,
2170 MDrawMetric *overall_line_return)
2172 MGlyphString *gstring;
2174 int width, rbearing;
2176 ASSURE_CONTROL (control);
2177 M_CHECK_POS_X (mt, from, -1);
2178 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2179 to = mtext_nchars (mt) + (control->cursor_width != 0);
2183 gstring = get_gstring (frame, mt, from, to, control);
2185 MERROR (MERROR_DRAW, -1);
2186 width = gstring_width (gstring, from, to, &rbearing);
2187 if (overall_ink_return)
2189 overall_ink_return->y = - gstring->physical_ascent;
2190 overall_ink_return->x = gstring->lbearing;
2192 if (overall_logical_return)
2194 overall_logical_return->y = - gstring->ascent;
2195 overall_logical_return->x = 0;
2197 if (overall_line_return)
2199 overall_line_return->y = - gstring->line_ascent;
2200 overall_line_return->x = gstring->lbearing;
2203 for (from = gstring->to; from < to; from = gstring->to)
2205 int this_width, this_rbearing;
2207 y += gstring->line_descent;
2208 M17N_OBJECT_UNREF (gstring->top);
2209 gstring = get_gstring (frame, mt, from, to, control);
2210 this_width = gstring_width (gstring, from, to, &this_rbearing);
2211 y += gstring->line_ascent;
2212 if (width < this_width)
2214 if (rbearing < this_rbearing)
2215 rbearing = this_rbearing;
2217 if (overall_ink_return)
2219 overall_ink_return->width = rbearing;
2220 overall_ink_return->height
2221 = y + gstring->physical_descent - overall_ink_return->y;
2223 if (overall_logical_return)
2225 overall_logical_return->width = width;
2226 overall_logical_return->height
2227 = y + gstring->descent - overall_logical_return->y;
2229 if (overall_line_return)
2231 overall_line_return->width = MAX (width, rbearing);
2232 overall_line_return->height
2233 = y + gstring->line_descent - overall_line_return->y;
2236 M17N_OBJECT_UNREF (gstring->top);
2243 @brief Compute the text dimensions of each character of M-text.
2245 The mdraw_text_per_char_extents () function computes the drawn
2246 metric of each character between $FROM and $TO of M-text $MT
2247 assuming that they are drawn on a window of frame $FRAME using the
2248 mdraw_text_with_control () function with the drawing control
2251 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2252 $LOGICAL_ARRAY_RETURN. Each successive element of
2253 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2254 ink and logical metrics of successive characters respectively,
2255 relative to the drawing origin of the M-text. The number of
2256 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2257 been set is returned to $NUM_CHARS_RETURN.
2259 If $ARRAY_SIZE is too small to return all metrics, the function
2260 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2261 Otherwise, it returns zero.
2263 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2264 @c NULL, this function also computes the metrics of the overall
2265 text and stores the results in the members of the structure
2266 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2268 If $CONTROL->two_dimensional is nonzero, this function computes
2269 only the metrics of characters in the first line. */
2271 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2273 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2274 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2275 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2277 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2278 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2279 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2280 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2281 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2283 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2284 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2287 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2288 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2289 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2291 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2294 mdraw_text_per_char_extents (MFrame *frame,
2295 MText *mt, int from, int to,
2296 MDrawControl *control,
2297 MDrawMetric *ink_array_return,
2298 MDrawMetric *logical_array_return,
2300 int *num_chars_return,
2301 MDrawMetric *overall_ink_return,
2302 MDrawMetric *overall_logical_return)
2304 MGlyphString *gstring;
2308 ASSURE_CONTROL (control);
2309 *num_chars_return = to - from;
2310 if (array_size < *num_chars_return)
2311 MERROR (MERROR_DRAW, -1);
2312 if (overall_logical_return)
2313 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2314 if (overall_ink_return)
2315 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2317 M_CHECK_RANGE (mt, from, to, -1, 0);
2318 gstring = get_gstring (frame, mt, from, to, control);
2321 *num_chars_return = 0;
2325 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2326 if (g->pos >= from && g->pos < to)
2330 int width = g->width;
2331 int lbearing = g->lbearing;
2332 int rbearing = g->rbearing;
2333 int ascent = g->ascent;
2334 int descent = g->descent;
2336 int logical_descent;
2338 if (g->rface->rfont)
2340 logical_ascent = g->rface->rfont->ascent;
2341 logical_descent = g->rface->rfont->descent;
2345 logical_ascent = g->rface->ascent;
2346 logical_descent = g->rface->descent;
2348 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2350 if (lbearing < width + g->lbearing)
2351 lbearing = width + g->lbearing;
2352 if (rbearing < width + g->rbearing)
2353 rbearing = width + g->rbearing;
2355 if (ascent < g->ascent)
2357 if (descent < g->descent)
2358 descent = g->descent;
2365 if (ink_array_return)
2367 ink_array_return[start - from].x = x + lbearing;
2368 ink_array_return[start - from].y = - ascent;
2369 ink_array_return[start - from].width = rbearing - lbearing;
2370 ink_array_return[start - from].height = ascent + descent;
2372 if (logical_array_return)
2374 logical_array_return[start - from].x = x;
2375 logical_array_return[start - from].y = - logical_descent;
2376 logical_array_return[start - from].height
2377 = logical_ascent + logical_descent;
2378 logical_array_return[start - from].width = width;
2386 if (overall_ink_return)
2388 overall_ink_return->y = - gstring->line_ascent;
2389 overall_ink_return->x = gstring->lbearing;
2390 overall_ink_return->width = x - gstring->lbearing;
2391 overall_ink_return->height = gstring->height;
2393 if (overall_logical_return)
2395 overall_logical_return->y = - gstring->ascent;
2396 overall_logical_return->x = 0;
2397 overall_logical_return->width = x;
2398 overall_logical_return->height = gstring->ascent + gstring->descent;
2401 M17N_OBJECT_UNREF (gstring->top);
2408 @brief Return the character position nearest to the coordinates.
2410 The mdraw_coordinates_position () function checks which character
2411 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2412 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2413 mdraw_text_with_control () function with the drawing control
2414 object $CONTROL. Here, the character position means the number of
2415 characters that precede the character in question in $MT, that is,
2416 the character position of the first character is 0.
2418 $FRAME is used only to get the default face information.
2421 If the glyph image of a character covers coordinate ($X, $Y),
2422 mdraw_coordinates_position () returns the character position of
2424 If $Y is less than the minimum Y-coordinate of the drawn area, it
2426 If $Y is greater than the maximum Y-coordinate of the drawn area,
2428 If $Y fits in with the drawn area but $X is less than the minimum
2429 X-coordinate, it returns the character position of the first
2430 character drawn on the line $Y.\n\n
2431 If $Y fits in with the drawn area but $X is greater than the
2432 maximum X-coordinate, it returns the character position of the
2433 last character drawn on the line $Y. */
2436 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2438 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2439 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2440 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2441 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2442 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2443 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2445 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2448 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2449 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2450 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2451 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2452 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2453 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2454 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2455 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2458 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2459 int x_offset, int y_offset, MDrawControl *control)
2461 MGlyphString *gstring;
2466 M_CHECK_POS_X (mt, from, -1);
2467 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2468 to = mtext_nchars (mt) + (control->cursor_width != 0);
2474 ASSURE_CONTROL (control);
2475 gstring = get_gstring (frame, mt, from, to, control);
2476 while (y + gstring->line_descent <= y_offset
2477 && gstring->to < to)
2480 y += gstring->line_descent;
2481 M17N_OBJECT_UNREF (gstring->top);
2482 gstring = get_gstring (frame, mt, from, to, control);
2483 y += gstring->line_ascent;
2486 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2487 if (! control->orientation_reversed)
2489 width = gstring->indent;
2490 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2491 if (g->pos >= from && g->pos < to)
2494 if (width > x_offset)
2500 width = - gstring->indent;
2501 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2502 if (g->pos >= from && g->pos < to)
2505 if (width < x_offset)
2509 if (g->type == GLYPH_ANCHOR
2510 && control->two_dimensional
2514 M17N_OBJECT_UNREF (gstring->top);
2522 @brief Compute information about a glyph.
2524 The mdraw_glyph_info () function computes information about a
2525 glyph that covers a character at position $POS of the M-text $MT
2526 assuming that the text is drawn from the character at $FROM of $MT
2527 on a window of frame $FRAME using the mdraw_text_with_control ()
2528 function with the drawing control object $CONTROL.
2530 The information is stored in the members of $INFO. */
2532 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2534 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2535 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2536 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2537 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2539 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2547 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2548 MDrawControl *control, MDrawGlyphInfo *info)
2550 MGlyphString *gstring;
2554 M_CHECK_RANGE_X (mt, from, pos, -1);
2556 ASSURE_CONTROL (control);
2557 gstring = get_gstring (frame, mt, from, pos + 1, control);
2559 MERROR (MERROR_DRAW, -1);
2560 while (gstring->to <= pos)
2562 y += gstring->line_descent;
2563 M17N_OBJECT_UNREF (gstring->top);
2564 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2565 y += gstring->line_ascent;
2567 info->line_from = gstring->from;
2568 if (info->line_from < from)
2569 info->line_from = from;
2570 info->line_to = gstring->to;
2573 if (! control->orientation_reversed)
2575 info->x = gstring->indent;
2576 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2577 info->x += g->width;
2581 info->x = - gstring->indent;
2582 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2583 info->x -= g->width;
2584 while (g[-1].to == g->to)
2587 info->from = g->pos;
2589 info->metrics.x = g->lbearing;
2590 info->metrics.y = - gstring->line_ascent;
2591 info->metrics.height = gstring->height;
2592 info->metrics.width = - g->lbearing + g->width;
2593 if (g->rface->rfont)
2594 info->font = &g->rface->rfont->font;
2597 /* info->logical_width is calculated later. */
2599 if (info->from > info->line_from)
2601 /* The logically previous glyph is on this line. */
2602 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2604 info->prev_from = g_tmp->pos;
2606 else if (info->line_from > 0)
2608 /* The logically previous glyph is on the previous line. */
2609 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2610 gstring->from, control);
2611 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2613 info->prev_from = g_tmp->pos;
2614 M17N_OBJECT_UNREF (gst->top);
2617 info->prev_from = -1;
2619 if (GLYPH_INDEX (g) > 1)
2620 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2621 else if (! control->orientation_reversed)
2623 if (info->line_from > 0)
2627 int p = gstring->from - 1;
2629 gst = get_gstring (frame, mt, p, gstring->from, control);
2630 g_tmp = gst->glyphs + (gst->used - 2);
2631 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2632 M17N_OBJECT_UNREF (gst->top);
2635 info->left_from = info->left_to = -1;
2639 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2643 int p = gstring->to;
2645 gst = get_gstring (frame, mt, p, p + 1, control);
2646 g_tmp = gst->glyphs + (gst->used - 2);
2647 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2648 M17N_OBJECT_UNREF (gst->top);
2651 info->left_from = info->left_to = -1;
2654 if (info->to < gstring->to)
2656 /* The logically next glyph is on this line. */
2657 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2659 info->next_to = g_tmp->to;
2661 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2663 /* The logically next glyph is on the next line. */
2665 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2666 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2668 info->next_to = g_tmp->to;
2669 M17N_OBJECT_UNREF (gst->top);
2674 for (info->logical_width = (g++)->width;
2675 g->pos == pos && g->type != GLYPH_ANCHOR;
2676 info->metrics.width += g->width, info->logical_width += (g++)->width);
2677 info->metrics.width += g[-1].rbearing - g[-1].width;
2679 if (g->type != GLYPH_ANCHOR)
2680 info->right_from = g->pos, info->right_to = g->to;
2681 else if (! control->orientation_reversed)
2683 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2686 M17N_OBJECT_UNREF (gstring->top);
2687 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2689 info->right_from = g->pos, info->right_to = g->to;
2692 info->right_from = info->right_to = -1;
2696 if (info->line_from > 0)
2698 pos = gstring->from - 1;
2699 M17N_OBJECT_UNREF (gstring->top);
2700 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2702 info->right_from = g->pos, info->right_to = g->to;
2705 info->right_from = info->right_to = -1;
2708 M17N_OBJECT_UNREF (gstring->top);
2715 @brief Compute information about glyph sequence.
2717 The mdraw_glyph_list () function computes information about glyphs
2718 corresponding to the text between $FROM and $TO of M-text $MT when
2719 it is drawn on a window of frame $FRAME using the
2720 mdraw_text_with_control () function with the drawing control
2721 object $CONTROL. $GLYPHS is an array of objects to store the
2722 information, and $ARRAY_SIZE is the array size.
2724 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2725 number of actually filled elements in the place pointed by
2726 $NUM_GLYPHS_RETURN, and returns 0.
2728 Otherwise, it stores the required array size in the place pointed
2729 by $NUM_GLYPHS_RETURN, and returns -1. */
2732 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2734 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2735 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2736 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2737 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2739 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2740 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2743 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2753 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2754 MDrawControl *control, MDrawGlyph *glyphs,
2755 int array_size, int *num_glyphs_return)
2757 MGlyphString *gstring;
2762 ASSURE_CONTROL (control);
2763 *num_glyphs_return = 0;
2764 M_CHECK_RANGE (mt, from, to, -1, 0);
2765 gstring = get_gstring (frame, mt, from, to, control);
2768 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2770 if (g->type == GLYPH_BOX
2771 || g->pos < from || g->pos >= to)
2773 if (g->type == GLYPH_PAD)
2775 if (g->left_padding)
2776 pad_width = g->width;
2780 glyphs[-1].x_advance += g->width;
2786 glyphs->from = g->pos;
2788 glyphs->glyph_code = g->code;
2789 glyphs->x_off = g->xoff + pad_width;
2790 glyphs->y_off = g->yoff;
2791 glyphs->lbearing = g->lbearing;
2792 glyphs->rbearing = g->rbearing;
2793 glyphs->ascent = g->ascent;
2794 glyphs->descent = g->descent;
2795 glyphs->x_advance = g->width + pad_width;
2796 glyphs->y_advance = 0;
2797 if (g->rface->rfont)
2799 glyphs->font = &g->rface->rfont->font;
2800 glyphs->font_type = g->rface->rfont->type;
2801 glyphs->fontp = g->rface->rfont->fontp;
2805 glyphs->font = NULL;
2806 glyphs->font_type = Mnil;
2807 glyphs->fontp = NULL;
2814 M17N_OBJECT_UNREF (gstring->top);
2816 *num_glyphs_return = n;
2817 return (n <= array_size ? 0 : -1);
2823 @brief Draw one or more textitems.
2825 The mdraw_text_items () function draws one or more M-texts on
2826 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2827 of the textitems to be drawn and $NITEMS is the number of
2828 textitems in the array. */
2831 @brief textitem ¤òɽ¼¨¤¹¤ë.
2833 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2834 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2835 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2837 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2841 MTextItem, mdraw_text (). */
2844 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2845 MDrawTextItem *items, int nitems)
2847 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2849 while (nitems-- > 0)
2852 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2854 mdraw_text_with_control (frame, win, x, y,
2855 items->mt, 0, mtext_nchars (items->mt),
2857 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2858 items->control, NULL, NULL, NULL);
2861 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2867 @brief calculate a line breaking position.
2869 The function mdraw_default_line_break () calculates a line
2870 breaking position based on the line number $LINE and the
2871 coordinate $Y, when a line is too long to fit within the width
2872 limit. $POS is the position of the character next to the last
2873 one that fits within the limit. $FROM is the position of the
2874 first character of the line, and $TO is the position of the last
2875 character displayed on the line if there were not width limit.
2876 $LINE and $Y are reset to 0 when a line is broken by a newline
2877 character, and incremented each time when a long line is broken
2878 because of the width limit.
2881 This function returns a character position to break the
2886 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2888 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2889 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2890 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2891 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2892 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2893 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2894 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2897 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2901 mdraw_default_line_break (MText *mt, int pos,
2902 int from, int to, int line, int y)
2904 int c = mtext_ref_char (mt, pos);
2907 if (c == ' ' || c == '\t')
2911 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2918 if (c == ' ' || c == '\t')
2921 c = mtext_ref_char (mt, pos);
2934 @brief Obtain per character dimension information.
2936 The mdraw_per_char_extents () function computes the text dimension
2937 of each character in M-text $MT. The faces given as text
2938 properties in $MT and the default face of frame $FRAME determine
2939 the fonts to draw the text. Each successive element in
2940 $ARRAY_RETURN is set to the drawn metrics of successive
2941 characters, which is relative to the origin of the drawing, and a
2942 rectangle for each character in $MT. The number of elements of
2943 $ARRAY_RETURN must be equal to or greater than the number of
2946 If pointer $OVERALL_RETURN is not @c NULL, this function also
2947 computes the extents of the overall text and stores the results in
2948 the members of the structure pointed to by $OVERALL_RETURN. */
2951 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2953 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2954 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2955 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2956 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2957 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2958 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2959 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2961 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2962 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2963 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2965 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2968 mdraw_per_char_extents (MFrame *frame, MText *mt,
2969 MDrawMetric *array_return,
2970 MDrawMetric *overall_return)
2972 int n = mtext_nchars (mt);
2974 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2975 n, &n, overall_return, NULL);
2979 @brief clear cached information.
2981 The mdraw_clear_cache () function clear cached information
2982 on M-text $MT that was attached by any of the drawing functions.
2983 When the behavior of `format' or `line_break'
2984 member functions of MDrawControl is changed, the cache must be cleared.
2989 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2991 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2992 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2993 ¤¢¤ë¤¤¤Ï `line_break'
2994 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3000 mdraw_clear_cache (MText *mt)
3002 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);