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 if (face_change == mtext_nchars (mt))
275 rface = (num > 0 ? mface__realize (frame, faces, num, size)
279 if (stop > face_change)
283 if (pos < mtext_nchars (mt))
284 c = mtext_ref_char (mt, pos);
288 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
293 category = mchar_get_prop (c, Mcategory);
294 if (category == McatCf)
295 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
296 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
297 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
299 g_tmp.category = GLYPH_CATEGORY_NORMAL;
301 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
305 ctrl[0] = ctrl[1] = g_tmp;
307 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
308 APPEND_GLYPH (gstring, ctrl[0]);
309 APPEND_GLYPH (gstring, ctrl[1]);
312 APPEND_GLYPH (gstring, g_tmp);
313 if (c == '\n' && gstring->control.two_dimensional)
316 /* Append an anchor glyph. */
318 g_tmp.type = GLYPH_ANCHOR;
319 g_tmp.pos = g_tmp.to = pos;
320 APPEND_GLYPH (gstring, g_tmp);
323 /* The next loop is to change each <rface> member for non-ASCII
324 characters if necessary. */
325 stop = charset_change = language_change = from;
326 rfont = default_rface->rfont;
327 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
333 /* Short cut for the obvious case. */
334 this_script = Mlatin;
337 this_script = (MSymbol) mchar_get_prop (c, Mscript);
338 if (this_script == Minherited || this_script == Mnil)
339 this_script = script;
340 if (this_script == Mnil)
341 this_script = non_latin_script;
342 if (this_script == Mnil)
344 /* Search forward for a character that explicitly
345 specifies a non-latin script. */
349 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
351 && (sym = mchar_get_prop (g1->c, Mscript)) != Mnil
352 && sym != Minherited)
361 if (pos == stop || script != this_script || g->rface->rfont != rfont)
364 last_g = mface__for_chars (script, language, charset,
366 script = this_script;
367 if (script != Mnil && script != Mlatin)
368 non_latin_script = script;
369 rfont = g->rface->ascii_rface->rfont;
372 if (pos < mtext_nchars (mt) && pos == language_change)
374 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
375 mtext_prop_range (mt, Mlanguage, pos, NULL,
376 &language_change, 0);
378 if (pos < mtext_nchars (mt) && pos == charset_change)
380 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
381 mtext_prop_range (mt, Mcharset, pos, NULL,
385 if (stop > language_change)
386 stop = language_change;
387 if (stop > charset_change)
388 stop = charset_change;
393 last_g = mface__for_chars (script, language, charset, last_g, g, size);
395 /* The next loop is to run FLT or perform the default combining if
397 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
401 if (this->type == GLYPH_CHAR && this->rface->rfont)
405 if (this->rface->rfont->layouter != Mnil)
410 for (prev = MGLYPH (start - 1);
411 (prev->type == GLYPH_CHAR
412 && prev->category == GLYPH_CATEGORY_FORMATTER
413 && (code = mfont__encode_char (this->rface->rfont, prev->c)
414 != MCHAR_INVALID_CODE));
419 (g->type == GLYPH_CHAR
420 && (g->rface->rfont == this->rface->rfont
421 || (g->category == GLYPH_CATEGORY_FORMATTER
422 && ((code = mfont__encode_char (this->rface->rfont,
424 != MCHAR_INVALID_CODE))));
426 if (g->rface->rfont != this->rface->rfont)
428 g->rface->rfont = this->rface->rfont;
431 i = mfont__flt_run (gstring, start, i, this->rface);
435 while (this->type == GLYPH_CHAR
437 && this->category == GLYPH_CATEGORY_MODIFIER
438 && this->rface->rfont
439 && this->rface->rfont->layouter == Mnil)
441 int class = (int) mchar_get_prop (this->c,
444 = MAKE_COMBINING_CODE_BY_CLASS (class);
448 reorder_combining_chars (gstring, start, i);
449 if (this->type == GLYPH_ANCHOR)
458 /* At last, reorder glyphs visually if necessary. */
459 if (gstring->control.enable_bidi)
460 visual_order (gstring);
465 combining_code_from_class (int class)
470 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
471 else if (class == 200) /* below left attached */
472 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
473 else if (class == 202) /* below attached*/
474 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
475 else if (class == 204) /* below right attached */
476 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
477 else if (class == 208) /* left attached */
478 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
479 else if (class == 210) /* right attached */
480 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
481 else if (class == 212) /* above left attached */
482 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
483 else if (class == 214) /* above attached */
484 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
485 else if (class == 216) /* above right attached */
486 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
487 else if (class == 218) /* below left */
488 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
489 else if (class == 220) /* below */
490 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
491 else if (class == 222) /* below right */
492 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
493 else if (class == 224) /* left */
494 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
495 else if (class == 226) /* right */
496 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
497 else if (class == 228) /* above left */
498 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
499 else if (class == 230) /* above */
500 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
501 else if (class == 232) /* above right */
502 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
503 else if (class == 233) /* double below */
504 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
505 else if (class == 234) /* double above */
506 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
507 else if (class == 240) /* iota subscript */
508 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
510 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
516 int width, lbearing, rbearing;
520 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
521 MSubTextExtents *extents)
523 int g_physical_ascent, g_physical_descent;
524 MGlyph *g = MGLYPH (from);
525 MGlyph *last_g = MGLYPH (to);
528 g_physical_ascent = gstring->physical_ascent;
529 g_physical_descent = gstring->physical_descent;
530 extents->width = extents->lbearing = extents->rbearing = 0;
532 for (i = from; i < to;)
534 if ( MGLYPH (i)->otf_encoded)
540 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
541 mfont__get_metric (gstring, j, i);
549 MRealizedFont *rfont = base->rface->rfont;
550 int size = rfont->font.property[MFONT_SIZE];
551 int width, lbearing, rbearing;
553 if (g == last_g || ! g->combining_code)
556 if (base->width == 0 && ! base->left_padding && ! base->right_padding
557 && GLYPH_INDEX (base) > from)
559 MGlyph *prev = base - 1;
561 if (base->pos < prev->pos)
562 prev->pos = base->pos;
564 base->pos = prev->pos;
565 if (base->to > prev->to)
571 if (base->left_padding && base->lbearing < 0)
573 base->xoff = - base->lbearing;
574 base->width += base->xoff;
575 base->rbearing += base->xoff;
578 if (base->right_padding && base->rbearing > base->width)
580 base->width = base->rbearing;
582 lbearing = (base->xoff + base->lbearing < 0
583 ? base->xoff + base->lbearing : 0);
584 rbearing = base->xoff + base->rbearing;
588 /* With combining glyphs. */
589 int left = -base->width;
591 int top = - base->ascent;
592 int bottom = base->descent;
593 int height = bottom - top;
594 int begin = base->pos;
599 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
600 rbearing = base->rbearing;
602 while (g != last_g && g->combining_code)
604 int combining_code = g->combining_code;
608 else if (end < g->to)
611 if (! COMBINING_PRECOMPUTED_P (combining_code))
613 int base_x, base_y, add_x, add_y, off_x, off_y;
615 if (COMBINING_BY_CLASS_P (combining_code))
616 g->combining_code = combining_code
617 = combining_code_from_class (COMBINING_CODE_CLASS
620 rfont = g->rface->rfont;
621 size = rfont->font.property[MFONT_SIZE];
622 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
624 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
626 base_x = COMBINING_CODE_BASE_X (combining_code);
627 base_y = COMBINING_CODE_BASE_Y (combining_code);
628 add_x = COMBINING_CODE_ADD_X (combining_code);
629 add_y = COMBINING_CODE_ADD_Y (combining_code);
631 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
634 if (g->xoff + g->width > right)
635 right = g->xoff + g->width;
636 width = right - left;
639 g->yoff = top + height * base_y / 2;
643 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
647 if (g->xoff + g->lbearing < left + lbearing)
648 lbearing = g->xoff + g->lbearing - left;
649 if (g->xoff + g->rbearing > left + rbearing)
650 rbearing = g->xoff + g->rbearing - left;
651 if (g->yoff - g->ascent < top)
652 top = g->yoff - g->ascent;
653 if (g->yoff + g->descent > bottom)
654 bottom = g->yoff + g->descent;
655 height = bottom - top;
661 base->ascent = - top;
662 base->descent = bottom;
663 base->lbearing = lbearing;
664 base->rbearing = rbearing;
665 if (left < - base->width)
667 base->xoff = - base->width - left;
668 base->width += base->xoff;
669 base->rbearing += base->xoff;
670 base->lbearing += base->xoff;
674 base->width += right;
675 base->rbearing += right;
676 base->right_padding = 1;
677 for (i = 1; base + i != g; i++)
678 base[i].xoff -= right;
681 for (i = 0; base + i != g; i++)
688 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
689 g_physical_descent = MAX (g_physical_descent, base->descent);
690 extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
691 extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
692 extents->width += base->width;
695 gstring->physical_ascent = g_physical_ascent;
696 gstring->physical_descent = g_physical_descent;
700 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
701 by this function directly. Character glyphs are handled by
702 layouter functions registered in font drivers.
704 This function fill-in all the remaining members of glyphs. */
707 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
709 /* Default width of TAB. */
710 int tab_width = frame->space_width * (gstring->control.tab_width
711 ? gstring->control.tab_width : 8);
715 MDrawControl *control = &(gstring->control);
718 int box_line_height = 0;
719 int ignore_formatting_char = control->ignore_formatting_char;
721 gstring->ascent = gstring->descent = 0;
722 gstring->physical_ascent = gstring->physical_descent = 0;
723 gstring->width = gstring->lbearing = gstring->rbearing = 0;
727 while (g->type != GLYPH_ANCHOR)
729 if (box != g->rface->box)
731 int gidx = GLYPH_INDEX (g);
735 /* Insert the right side of the box. That glyph belongs
736 to the previous grapheme cluster. */
737 MGlyph box_glyph = g[-1];
739 box_glyph.type = GLYPH_BOX;
741 = (control->fixed_width
743 : box->inner_hmargin + box->width + box->outer_hmargin);
744 box_glyph.lbearing = 0;
745 box_glyph.rbearing = box_glyph.width;
747 box_glyph.right_padding = 1;
748 gstring->width += box_glyph.width;
749 gstring->rbearing += box_glyph.width;
750 INSERT_GLYPH (gstring, gidx, box_glyph);
757 /* Insert the left side of the box. That glyph belongs
758 to the following grapheme cluster. */
759 MGlyph box_glyph = *g;
760 int box_height = (box->width
761 + box->inner_vmargin + box->outer_vmargin);
763 if (box_line_height < box_height)
764 box_line_height = box_height;
765 box_glyph.type = GLYPH_BOX;
767 = (control->fixed_width
769 : box->inner_hmargin + box->width + box->outer_hmargin);
770 box_glyph.lbearing = 0;
771 box_glyph.rbearing = box_glyph.width;
773 box_glyph.left_padding = 1;
774 gstring->width += box_glyph.width;
775 gstring->rbearing += box_glyph.width;
776 INSERT_GLYPH (gstring, gidx, box_glyph);
782 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
783 g->type = GLYPH_SPACE;
785 if (g->type == GLYPH_CHAR)
787 MRealizedFace *rface = g->rface;
788 MRealizedFont *rfont = rface->rfont;
790 int from = GLYPH_INDEX (g);
792 for (g++; g->type == GLYPH_CHAR; g++)
793 if (! rfont != ! g->rface->rfont
794 || box != g->rface->box
795 || ((fromg->code == MCHAR_INVALID_CODE)
796 != (g->code == MCHAR_INVALID_CODE))
797 || (g->category == GLYPH_CATEGORY_FORMATTER
798 && ignore_formatting_char))
800 if (rfont && fromg->code != MCHAR_INVALID_CODE)
803 int to = GLYPH_INDEX (g);
804 MSubTextExtents extents;
806 layout_glyphs (frame, gstring, from, to, &extents);
807 extra_width = - extents.lbearing;
809 && ! control->disable_overlapping_adjustment
810 && (! control->orientation_reversed
811 ? ((to > 1 || control->align_head)
812 && g->type != GLYPH_ANCHOR)
813 : (((g->type && GLYPH_ANCHOR) || control->align_head)
818 pad.type = GLYPH_PAD;
821 pad.width = pad.rbearing = extra_width;
822 pad.left_padding = 1;
823 INSERT_GLYPH (gstring, from, pad);
825 extents.lbearing = 0;
826 extents.width += extra_width;
827 extents.rbearing += extra_width;
829 g = MGLYPH (from - 1);
830 if (g->type == GLYPH_SPACE)
832 /* The pad just inserted is absorbed (maybe
833 partially) by the previous space while
834 keeping at least some space width. For the
835 moment, we use the arbitrary width 2-pixel.
836 Perhaps, it should be decided by the current
837 face, or a default value of the current
838 frame, which is, however, not yet
840 if (extra_width + 2 < g->width)
842 g->width -= extra_width;
846 extra_width = g->width - 2;
849 gstring->width -= extra_width;
850 gstring->rbearing -= extra_width;
855 extra_width = extents.rbearing - extents.width;
857 && ! control->disable_overlapping_adjustment
858 && (GLYPH_INDEX (g) < gstring->used - 1
859 || (control->orientation_reversed && control->align_head)))
861 if (g->type == GLYPH_SPACE && box == g->rface->box)
864 pad.type = GLYPH_PAD;
867 pad.width = pad.rbearing = extra_width;
868 INSERT_GLYPH (gstring, to, pad);
873 g[-1].width += extra_width;
874 extents.width += extra_width;
877 if (gstring->lbearing > gstring->width + extents.lbearing)
878 gstring->lbearing = gstring->width + extents.lbearing;
879 if (gstring->rbearing < gstring->width + extents.rbearing)
880 gstring->rbearing = gstring->width + extents.rbearing;
881 gstring->width += extents.width;
882 if (gstring->ascent < rface->ascent)
883 gstring->ascent = rface->ascent;
884 if (gstring->descent < rface->descent)
885 gstring->descent = rface->descent;
889 for (; fromg < g; fromg++)
891 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
892 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
893 fromg->width = fromg->rbearing = 1;
895 fromg->width = fromg->rbearing = rface->space_width;
896 fromg->xoff = fromg->lbearing = 0;
897 fromg->ascent = fromg->descent = 0;
898 gstring->width += fromg->width;
899 gstring->rbearing += fromg->width;
901 if (gstring->ascent < frame->rface->ascent)
902 gstring->ascent = frame->rface->ascent;
903 if (gstring->descent < frame->descent)
904 gstring->descent = frame->rface->descent;
907 else if (g->type == GLYPH_SPACE)
910 g->width = g->rface->space_width;
911 else if (g->c == '\n')
913 g->width = control->cursor_width;
916 if (control->cursor_bidi)
918 else if (g->width < 0)
919 g->width = g->rface->space_width;
922 else if (g->c == '\t')
924 g->width = tab_width - ((gstring->indent + gstring->width)
930 if (g[-1].type == GLYPH_PAD)
932 /* This space glyph absorbs (maybe partially) the
933 previous padding glyph. */
934 g->width -= g[-1].width;
936 /* But, keep at least some space width. For the
937 moment, we use the arbitrary width 2-pixel. */
940 g->rbearing = g->width;
941 gstring->width += g->width;
942 gstring->rbearing += g->width;
945 if (gstring->ascent < g->rface->ascent)
946 gstring->ascent = g->rface->ascent;
947 if (gstring->descent < g->rface->descent)
948 gstring->descent = g->rface->descent;
954 gstring->width += g->width;
955 gstring->rbearing += g->width;
962 /* Insert the right side of the box. */
963 int gidx = GLYPH_INDEX (g);
964 MGlyph box_glyph = g[-1];
966 box_glyph.type = GLYPH_BOX;
968 = (control->fixed_width
970 : box->inner_hmargin + box->width + box->outer_hmargin);
971 box_glyph.lbearing = 0;
972 box_glyph.rbearing = box_glyph.width;
974 box_glyph.right_padding = 1;
975 gstring->width += box_glyph.width;
976 gstring->rbearing += box_glyph.width;
977 INSERT_GLYPH (gstring, gidx, box_glyph);
980 gstring->text_ascent = gstring->ascent;
981 gstring->text_descent = gstring->descent;
982 if (gstring->text_ascent < gstring->physical_ascent)
983 gstring->text_ascent = gstring->physical_ascent;
984 if (gstring->text_descent < gstring->physical_descent)
985 gstring->text_descent = gstring->physical_descent;
986 gstring->line_ascent = gstring->text_ascent;
987 gstring->line_descent = gstring->text_descent;
988 if (box_line_height > 0)
990 gstring->line_ascent += box_line_height;
991 gstring->physical_ascent = gstring->line_ascent;
992 gstring->line_descent += box_line_height;
993 gstring->physical_descent = gstring->line_descent;
996 if (gstring->line_ascent < control->min_line_ascent)
997 gstring->line_ascent = control->min_line_ascent;
998 else if (control->max_line_ascent
999 && control->max_line_ascent > control->min_line_ascent
1000 && gstring->line_ascent > control->max_line_ascent)
1001 gstring->line_ascent = control->max_line_ascent;
1003 if (gstring->line_descent < control->min_line_descent)
1004 gstring->line_descent = control->min_line_descent;
1005 else if (control->max_line_descent
1006 && control->max_line_descent > control->min_line_descent
1007 && gstring->line_descent > control->max_line_descent)
1008 gstring->line_descent = control->max_line_descent;
1009 gstring->height = gstring->line_ascent + gstring->line_descent;
1011 if (control->orientation_reversed
1014 /* We must adjust TAB width for RTL orientation. */
1015 width = gstring->indent;
1017 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1019 if (g->type == GLYPH_CHAR && g->c == '\t')
1021 int this_width = tab_width - (width % tab_width);
1023 if (g[1].type == GLYPH_PAD)
1024 this_width -= g[1].width;
1025 if (g[-1].type == GLYPH_PAD)
1026 this_width -= g[-1].width;
1029 gstring->width += this_width - g->width;
1030 gstring->rbearing += this_width - g->width;
1031 g->width = this_width;
1032 width += this_width;
1042 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1043 MGlyphString *gstring, int from, int to,
1044 int *from_idx, int *to_idx, int *to_x)
1046 MGlyph *g = MGLYPH (1);
1047 MDrawRegion region = (MDrawRegion) NULL;
1048 MDrawControl *control = &gstring->control;
1049 int cursor_pos = -1;
1051 int cursor_bidi = control->cursor_bidi;
1053 if (control->with_cursor && control->cursor_width)
1055 if (gstring->from <= control->cursor_pos
1056 && gstring->to > control->cursor_pos)
1057 cursor_pos = control->cursor_pos;
1060 && gstring->from <= control->cursor_pos - 1
1061 && gstring->to > control->cursor_pos - 1)
1062 prev_pos = control->cursor_pos - 1;
1065 *from_idx = *to_idx = 0;
1066 while (g->type != GLYPH_ANCHOR)
1068 if (g->pos >= from && g->pos < to)
1070 MGlyph *fromg = g, *cursor = NULL;
1071 MRealizedFace *rface = g->rface;
1073 int cursor_width = 0;
1077 *from_idx = GLYPH_INDEX (g);
1078 while (g->pos >= from && g->pos < to
1079 && g->rface == rface)
1082 if (g->type != GLYPH_BOX
1083 && g->pos <= cursor_pos && g->to > cursor_pos)
1086 cursor = g, cursor_x = x + width;
1087 cursor_width += g->width;
1089 width += g++->width;
1092 && (control->as_image
1093 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1095 int this_x = x, this_width = width;
1097 if (fromg->type == GLYPH_BOX)
1098 this_x += fromg->width, this_width -= fromg->width;
1099 if (g[-1].type == GLYPH_BOX)
1100 this_width -= g[-1].width;
1101 (frame->driver->fill_space)
1102 (frame, win, rface, 0,
1103 this_x, y - gstring->text_ascent, this_width,
1104 gstring->text_ascent + gstring->text_descent,
1105 control->clip_region);
1112 rect.y = y - gstring->text_ascent;
1113 rect.height = gstring->text_ascent + gstring->text_descent;
1116 rect.width = ((control->cursor_width > 0
1117 && control->cursor_width < cursor_width)
1118 ? control->cursor_width : cursor_width);
1122 if (cursor->bidi_level % 2)
1123 rect.x += cursor_width - rect.width;
1124 (*frame->driver->fill_space)
1125 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1126 control->clip_region);
1128 region = (*frame->driver->region_from_rect) (&rect);
1130 (*frame->driver->region_add_rect) (region, &rect);
1133 if (cursor->bidi_level % 2)
1136 rect.width = cursor_width < 4 ? cursor_width : 4;
1137 (*frame->driver->fill_space)
1138 (frame, win, rface, 1,
1139 rect.x, rect.y, rect.width, rect.height,
1140 control->clip_region);
1141 (*frame->driver->region_add_rect) (region, &rect);
1153 if (fromg->type != GLYPH_BOX
1154 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1157 cursor = fromg, cursor_x = x + temp_width;
1158 cursor_width += fromg->width;
1160 temp_width += fromg++->width;
1167 if (! (cursor->bidi_level % 2))
1168 rect.x += cursor_width - 1;
1169 rect.y = y - gstring->text_ascent;
1170 rect.height = gstring->text_ascent + gstring->text_descent;
1172 (*frame->driver->fill_space)
1173 (frame, win, rface, 1,
1174 rect.x, rect.y, rect.width, rect.height,
1175 control->clip_region);
1177 region = (*frame->driver->region_from_rect) (&rect);
1179 (*frame->driver->region_add_rect) (region, &rect);
1180 rect.y += rect.height - 2;
1182 rect.width = cursor_width < 4 ? cursor_width : 4;
1183 if (! (cursor->bidi_level % 2))
1184 rect.x -= rect.width - 1;
1185 (*frame->driver->fill_space) (frame, win, rface, 1,
1186 rect.x, rect.y, rect.width, rect.height,
1187 control->clip_region);
1188 (*frame->driver->region_add_rect) (region, &rect);
1192 *to_idx = GLYPH_INDEX (g);
1202 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1203 MGlyphString *gstring, int from_idx, int to_idx,
1204 int reverse, MDrawRegion region)
1206 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1212 (*frame->driver->region_to_rect) (region, &rect);
1215 while (g != gend && x + g->rbearing <= rect.x)
1218 width -= g++->width;
1219 while (! g->enabled && g != gend)
1223 rect.x += rect.width;
1224 if (rect.x < x + width)
1227 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1229 width -= (--gend)->width;
1230 while (! gend->enabled && g != gend)
1234 while (gend[-1].to == gend->to) gend++;
1242 MRealizedFace *rface = g->rface;
1243 int width = g->width;
1244 MGlyph *from_g = g++;
1246 /* Handle the glyphs of the same type/face at once. */
1248 && g->type == from_g->type
1249 && g->rface == rface
1250 && ((g->code == MCHAR_INVALID_CODE)
1251 == (from_g->code == MCHAR_INVALID_CODE))
1253 width += g++->width;
1255 if (from_g->type == GLYPH_CHAR)
1257 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1258 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1261 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1264 else if (from_g->type == GLYPH_BOX)
1266 /* Draw the left or right side of a box. If
1267 from_g->lbearing is nonzero, this is the left side,
1268 else this is the right side. */
1269 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1272 if (from_g->type != GLYPH_BOX)
1275 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1276 x, y, width, region);
1279 /* Draw the top and bottom side of a box. */
1280 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1281 x, y, width, region);
1292 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1293 int *from_x, int *to_x)
1296 int left_idx = *left, right_idx = *right;
1297 int left_x, right_x, x;
1299 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1302 if (x + g->rbearing > 0)
1304 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1306 left_idx = GLYPH_INDEX (g);
1311 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1314 if (x - g->width + g->lbearing < 0)
1316 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1318 right_idx = GLYPH_INDEX (g) + 1;
1323 if (*left == left_idx && *right == right_idx)
1326 if (*left != left_idx)
1328 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1333 if (*right != right_idx)
1335 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1345 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1350 if (from <= gstring->from && to >= gstring->to)
1353 *rbearing = gstring->rbearing;
1354 return gstring->width;
1359 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1360 if (g->pos >= from && g->pos < to)
1362 if (rbearing && width + g->rbearing > *rbearing)
1363 *rbearing = width + g->rbearing;
1371 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1372 MGlyphString *gstring, int from, int to)
1374 MDrawControl *control = &gstring->control;
1376 MDrawRegion clip_region, cursor_region;
1377 int from_idx, to_idx;
1380 if (control->orientation_reversed)
1381 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1383 x += gstring->indent;
1385 /* At first, draw all glyphs without cursor. */
1386 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1387 &from_idx, &to_idx, &to_x);
1389 if (control->partial_update)
1392 rect.width = to_x - x;
1393 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1395 rect.y = y - gstring->line_ascent;
1396 rect.height = gstring->height;
1397 clip_region = (*frame->driver->region_from_rect) (&rect);
1398 if (control->clip_region)
1399 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1402 clip_region = control->clip_region;
1405 clip_region = control->clip_region;
1407 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1412 (*frame->driver->intersect_region) (cursor_region, clip_region);
1413 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1416 if (clip_region != control->clip_region)
1417 (*frame->driver->free_region) (clip_region);
1419 (*frame->driver->free_region) (cursor_region);
1423 static int gstring_num;
1426 free_gstring (void *object)
1428 MGlyphString *gstring = (MGlyphString *) object;
1431 free_gstring (gstring->next);
1432 if (gstring->size > 0)
1433 free (gstring->glyphs);
1439 static MGlyphString scratch_gstring;
1441 static MGlyphString *
1442 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1445 MGlyphString *gstring;
1447 if (pos == mt->nchars)
1451 gstring = &scratch_gstring;
1452 if (gstring->size == 0)
1457 g_tmp.type = GLYPH_ANCHOR;
1458 APPEND_GLYPH (gstring, g_tmp);
1459 APPEND_GLYPH (gstring, g_tmp);
1460 APPEND_GLYPH (gstring, g_tmp);
1461 gstring->glyphs[1].type = GLYPH_SPACE;
1462 gstring->glyphs[1].c = '\n';
1463 gstring->glyphs[1].code = '\n';
1465 gstring->from = pos;
1467 g->rface = frame->rface;
1468 g->pos = g->to = pos;
1470 g->rface = frame->rface;
1471 g->pos = pos++, g->to = pos;
1473 g->rface = frame->rface;
1474 g->pos = g->to = pos;
1479 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1480 MLIST_INIT1 (gstring, glyphs, 128);
1484 gstring->frame = frame;
1485 gstring->tick = frame->tick;
1486 gstring->top = gstring;
1487 gstring->control = *control;
1488 gstring->indent = gstring->width_limit = 0;
1489 if (control->format)
1490 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1492 gstring->width_limit = control->max_line_width;
1493 gstring->anti_alias = control->anti_alias;
1497 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1500 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1508 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1509 a width of glyphs for the character at I of MT. If I is not a
1510 beginning of a grapheme cluster, the corresponding element is
1512 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1513 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1514 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1515 pos_width[g->pos - gstring->from] += g->width;
1516 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1518 if (pos_width[i] > 0)
1520 if (width + pos_width[i] > gstring->width_limit)
1523 width += pos_width[i];
1526 pos = gstring->from + i;
1527 if (gstring->control.line_break)
1529 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1530 gstring->from, gstring->to, 0, 0);
1531 if (pos <= gstring->from)
1532 pos = gstring->from + 1;
1533 else if (pos >= gstring->to)
1538 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1539 layout_glyph_string (frame, gstring);
1543 /* Return a gstring that covers a character at POS. */
1545 static MGlyphString *
1546 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1548 MGlyphString *gstring = NULL;
1550 if (pos < mtext_nchars (mt))
1552 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1555 && ((prop->start != 0
1556 && mtext_ref_char (mt, prop->start - 1) != '\n')
1557 || (prop->end < mtext_nchars (mt)
1558 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1560 mtext_detach_property (prop);
1565 gstring = prop->val;
1566 if (gstring->frame != frame
1567 || gstring->tick != frame->tick
1568 || memcmp (control, &gstring->control,
1569 (char *) (&control->with_cursor)
1570 - (char *) (control))
1571 || control->cursor_width != gstring->control.cursor_width
1572 || control->cursor_bidi != gstring->control.cursor_bidi)
1574 mtext_detach_property (prop);
1579 else if (! control->cursor_width)
1587 offset = mtext_character (mt, pos, 0, '\n');
1592 offset -= gstring->from;
1594 for (gst = gstring; gst; gst = gst->next)
1598 gst->from += offset;
1600 for (i = 0; i < gst->used; i++)
1602 gst->glyphs[i].pos += offset;
1603 gst->glyphs[i].to += offset;
1606 M17N_OBJECT_REF (gstring);
1611 int line = 0, y = 0;
1613 if (pos < mtext_nchars (mt))
1615 beg = mtext_character (mt, pos, 0, '\n');
1623 end = mtext_nchars (mt) + (control->cursor_width != 0);
1624 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1625 if (beg < mtext_nchars (mt))
1626 compose_glyph_string (frame, mt, beg, end, gstring);
1627 layout_glyph_string (frame, gstring);
1629 if (gstring->width_limit
1630 && gstring->width > gstring->width_limit)
1632 MGlyphString *gst = gstring;
1634 truncate_gstring (frame, mt, gst);
1635 while (gst->to < end)
1637 line++, y += gst->height;
1638 gst->next = alloc_gstring (frame, mt, gst->from, control,
1640 gst->next->top = gstring;
1641 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1643 layout_glyph_string (frame, gst);
1644 if (gst->width <= gst->width_limit)
1646 truncate_gstring (frame, mt, gst);
1650 if (! control->disable_caching && pos < mtext_nchars (mt))
1652 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1653 MTEXTPROP_VOLATILE_STRONG);
1655 if (end > mtext_nchars (mt))
1656 end = mtext_nchars (mt);
1657 mtext_attach_property (mt, beg, end, prop);
1658 M17N_OBJECT_UNREF (prop);
1662 while (gstring->to <= pos)
1664 if (! gstring->next)
1666 gstring = gstring->next;
1668 gstring->control = *control;
1674 static MDrawControl control_noop;
1676 #define ASSURE_CONTROL(control) \
1678 control = &control_noop; \
1683 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1684 MText *mt, int from, int to,
1685 MDrawControl *control)
1687 MGlyphString *gstring;
1689 M_CHECK_POS_X (mt, from, -1);
1690 ASSURE_CONTROL (control);
1691 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1692 to = mtext_nchars (mt) + (control->cursor_width != 0);
1696 gstring = get_gstring (frame, mt, from, to, control);
1698 MERROR (MERROR_DRAW, -1);
1699 render_glyph_string (frame, win, x, y, gstring, from, to);
1703 y += gstring->line_descent;
1704 M17N_OBJECT_UNREF (gstring->top);
1705 gstring = get_gstring (frame, mt, from, to, control);
1706 y += gstring->line_ascent;
1707 render_glyph_string (frame, win, x, y, gstring, from, to);
1710 M17N_OBJECT_UNREF (gstring->top);
1717 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1723 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1724 if (g->pos <= pos && g->to > pos)
1729 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1730 if (g->pos <= pos && g->to > pos)
1737 /* for debugging... */
1741 dump_combining_code (int code)
1743 char *vallign = "tcbB";
1744 char *hallign = "lcr";
1750 if (COMBINING_BY_CLASS_P (code))
1751 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1752 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1753 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1754 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1755 off_x = COMBINING_CODE_OFF_X (code) - 128;
1757 sprintf (work + 2, "+%d", off_y);
1759 sprintf (work + 2, "%d", off_y);
1760 else if (off_x == 0)
1761 sprintf (work + 2, ".");
1762 p = work + strlen (work);
1764 sprintf (p, ">%d", off_x);
1766 sprintf (p, "<%d", -off_x);
1768 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1769 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1775 dump_gstring (MGlyphString *gstring, int indent)
1777 char *prefix = (char *) alloca (indent + 1);
1778 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1780 memset (prefix, 32, indent);
1783 fprintf (stderr, "(glyph-string");
1785 for (g = MGLYPH (0); g < last_g; g++)
1787 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1789 g - gstring->glyphs,
1790 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1791 : g->type == GLYPH_ANCHOR ? "ANC"
1792 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1793 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1794 dump_combining_code (g->combining_code),
1795 g->width, g->bidi_level);
1796 fprintf (stderr, ")");
1800 /* m17n-X internal APIs */
1805 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1807 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1808 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1810 Minherited = msymbol ("inherited");
1812 McatCc = msymbol ("Cc");
1813 McatCf = msymbol ("Cf");
1815 MbidiR = msymbol ("R");
1816 MbidiAL = msymbol ("AL");
1817 MbidiRLE = msymbol ("RLE");
1818 MbidiRLO = msymbol ("RLO");
1819 MbidiBN = msymbol ("BN");
1820 MbidiS = msymbol ("S");
1822 fribidi_set_mirroring (TRUE);
1831 MLIST_FREE1 (&scratch_gstring, glyphs);
1835 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1839 /*** @addtogroup m17nDraw */
1844 @brief Draw an M-text on a window.
1846 The mdraw_text () function draws the text between $FROM and $TO of
1847 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1849 The appearance of the text (size, style, color, etc) is specified
1850 by the value of the text property whose key is @c Mface. If the
1851 M-text or a part of the M-text does not have such a text property,
1852 the default face of $FRAME is used.
1854 The font used to draw a character in the M-text is selected from
1855 the value of the fontset property of a face by the following
1860 <li> Search the text properties given to the character for the one
1861 whose key is @c Mcharset; its value should be either a symbol
1862 specifying a charset or #Mnil. If the value is #Mnil,
1863 proceed to the next step.
1865 Otherwise, search the mapping table of the fontset for the
1866 charset. If no entry is found proceed to the next step.
1868 If an entry is found, use one of the fonts in the entry that
1869 has a glyph for the character and that matches best with the
1870 face properties. If no such font exists, proceed to the next
1873 <li> Get the character property "script" of the character. If it is
1874 inherited, get the script property from the previous
1875 characters. If there is no previous character, or none of
1876 them has the script property other than inherited, proceed to
1879 Search the text properties given to the character for the one
1880 whose key is @c Mlanguage; its value should be either a
1881 symbol specifying a language or @c Mnil.
1883 Search the mapping table of the fontset for the combination
1884 of the script and language. If no entry is found, proceed to
1887 If an entry is found, use one of the fonts in the entry that
1888 has a glyph for the character and that matches best with the
1889 face properties. If no such font exists, proceed to the next
1892 <li> Search the fall-back table of the fontset for a font that has
1893 a glyph of the character. If such a font is found, use that
1898 If no font is found by the algorithm above, this function draws an
1899 empty box for the character.
1901 This function draws only the glyph foreground. To specify the
1902 background color, use mdraw_image_text () or
1903 mdraw_text_with_control ().
1905 This function is the counterpart of <tt>XDrawString ()</tt>,
1906 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1907 in the X Window System.
1910 If the operation was successful, mdraw_text () returns 0. If an
1911 error is detected, it returns -1 and assigns an error code to the
1912 external variable #merror_code. */
1914 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1916 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1917 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1920 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1921 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1922 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1923 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1925 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1926 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1930 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1931 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1932 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1933 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1934 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1937 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1938 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1939 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1942 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1943 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1944 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1945 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1947 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1948 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1951 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1952 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1955 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1956 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1957 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1960 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1961 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1965 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1966 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1968 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1969 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1972 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1973 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1976 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1977 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1979 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1986 mdraw_image_text () */
1989 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1990 MText *mt, int from, int to)
1992 MDrawControl control;
1994 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1995 memset (&control, 0, sizeof control);
1996 control.as_image = 0;
1997 return draw_text (frame, win, x, y, mt, from, to, &control);
2004 @brief Draw an M-text on a window as an image.
2006 The mdraw_image_text () function draws the text between $FROM and
2007 $TO of M-text $MT as image on window $WIN of frame $FRAME at
2008 coordinate ($X, $Y).
2010 The way to draw a text is the same as in mdraw_text () except that
2011 this function also draws the background with the color specified
2014 This function is the counterpart of <tt>XDrawImageString ()</tt>,
2015 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
2016 functions in the X Window System.
2019 If the operation was successful, mdraw_image_text () returns 0.
2020 If an error is detected, it returns -1 and assigns an error code
2021 to the external variable #merror_code. */
2024 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
2026 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
2027 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
2030 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
2031 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2033 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
2034 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
2038 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2039 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
2042 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
2052 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2053 MText *mt, int from, int to)
2055 MDrawControl control;
2057 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2058 memset (&control, 0, sizeof control);
2059 control.as_image = 1;
2060 return draw_text (frame, win, x, y, mt, from, to, &control);
2066 @brief Draw an M-text on a window with fine control.
2068 The mdraw_text_with_control () function draws the text between
2069 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2070 coordinate ($X, $Y).
2072 The way to draw a text is the same as in mdraw_text () except that
2073 this function also follows what specified in the drawing control
2076 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2077 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2078 breaks lines and the following characters are drawn in the next
2079 line. See the documentation of the structure @ MDrawControl for
2083 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2085 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2086 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2089 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2090 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2092 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2093 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2094 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2098 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2099 MText *mt, int from, int to, MDrawControl *control)
2101 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2102 return draw_text (frame, win, x, y, mt, from, to, control);
2108 @brief Compute text pixel width.
2110 The mdraw_text_extents () function computes the width of text
2111 between $FROM and $TO of M-text $MT when it is drawn on a window
2112 of frame $FRAME using the mdraw_text_with_control () function with
2113 the drawing control object $CONTROL.
2115 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2116 the bounding box of character ink of the M-text, and stores the
2117 results in the members of the structure pointed to by
2118 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2119 surrounding box, the box is included in the bounding box.
2121 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2122 computes the bounding box that provides mininum spacing to other
2123 graphical features (such as surrounding box) for the M-text, and
2124 stores the results in the members of the structure pointed to by
2125 $OVERALL_LOGICAL_RETURN.
2127 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2128 computes the bounding box that provides mininum spacing to the
2129 other M-text drawn, and stores the results in the members of the
2130 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2131 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2132 min_line_ascent, min_line_descent, max_line_ascent, and
2133 max_line_descent of $CONTROL are all zero.
2136 This function returns the width of the text to be drawn in the
2137 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2138 text is drawn in multiple physical lines, it returns the width of
2139 the widest line. If an error occurs, it returns -1 and assigns an
2140 error code to the external variable #merror_code. */
2144 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2146 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2147 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2148 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2150 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2151 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2152 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2153 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2155 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2156 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2157 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2158 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2160 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2161 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2162 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2163 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2164 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2165 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2167 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2168 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2169 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2170 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2172 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2179 mdraw_text_extents (MFrame *frame,
2180 MText *mt, int from, int to, MDrawControl *control,
2181 MDrawMetric *overall_ink_return,
2182 MDrawMetric *overall_logical_return,
2183 MDrawMetric *overall_line_return)
2185 MGlyphString *gstring;
2187 int width, rbearing;
2189 ASSURE_CONTROL (control);
2190 M_CHECK_POS_X (mt, from, -1);
2191 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2192 to = mtext_nchars (mt) + (control->cursor_width != 0);
2196 gstring = get_gstring (frame, mt, from, to, control);
2198 MERROR (MERROR_DRAW, -1);
2199 width = gstring_width (gstring, from, to, &rbearing);
2200 if (overall_ink_return)
2202 overall_ink_return->y = - gstring->physical_ascent;
2203 overall_ink_return->x = gstring->lbearing;
2205 if (overall_logical_return)
2207 overall_logical_return->y = - gstring->ascent;
2208 overall_logical_return->x = 0;
2210 if (overall_line_return)
2212 overall_line_return->y = - gstring->line_ascent;
2213 overall_line_return->x = gstring->lbearing;
2216 for (from = gstring->to; from < to; from = gstring->to)
2218 int this_width, this_rbearing;
2220 y += gstring->line_descent;
2221 M17N_OBJECT_UNREF (gstring->top);
2222 gstring = get_gstring (frame, mt, from, to, control);
2223 this_width = gstring_width (gstring, from, to, &this_rbearing);
2224 y += gstring->line_ascent;
2225 if (width < this_width)
2227 if (rbearing < this_rbearing)
2228 rbearing = this_rbearing;
2230 if (overall_ink_return)
2232 overall_ink_return->width = rbearing;
2233 overall_ink_return->height
2234 = y + gstring->physical_descent - overall_ink_return->y;
2236 if (overall_logical_return)
2238 overall_logical_return->width = width;
2239 overall_logical_return->height
2240 = y + gstring->descent - overall_logical_return->y;
2242 if (overall_line_return)
2244 overall_line_return->width = MAX (width, rbearing);
2245 overall_line_return->height
2246 = y + gstring->line_descent - overall_line_return->y;
2249 M17N_OBJECT_UNREF (gstring->top);
2256 @brief Compute the text dimensions of each character of M-text.
2258 The mdraw_text_per_char_extents () function computes the drawn
2259 metric of each character between $FROM and $TO of M-text $MT
2260 assuming that they are drawn on a window of frame $FRAME using the
2261 mdraw_text_with_control () function with the drawing control
2264 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2265 $LOGICAL_ARRAY_RETURN. Each successive element of
2266 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2267 ink and logical metrics of successive characters respectively,
2268 relative to the drawing origin of the M-text. The number of
2269 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2270 been set is returned to $NUM_CHARS_RETURN.
2272 If $ARRAY_SIZE is too small to return all metrics, the function
2273 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2274 Otherwise, it returns zero.
2276 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2277 @c NULL, this function also computes the metrics of the overall
2278 text and stores the results in the members of the structure
2279 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2281 If $CONTROL->two_dimensional is nonzero, this function computes
2282 only the metrics of characters in the first line. */
2284 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2286 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2287 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2288 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2289 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2291 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2292 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2293 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2294 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2295 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2297 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2298 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2301 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2302 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2303 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2306 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2307 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2310 mdraw_text_per_char_extents (MFrame *frame,
2311 MText *mt, int from, int to,
2312 MDrawControl *control,
2313 MDrawMetric *ink_array_return,
2314 MDrawMetric *logical_array_return,
2316 int *num_chars_return,
2317 MDrawMetric *overall_ink_return,
2318 MDrawMetric *overall_logical_return)
2320 MGlyphString *gstring;
2324 ASSURE_CONTROL (control);
2325 *num_chars_return = to - from;
2326 if (array_size < *num_chars_return)
2327 MERROR (MERROR_DRAW, -1);
2328 if (overall_logical_return)
2329 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2330 if (overall_ink_return)
2331 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2333 M_CHECK_RANGE (mt, from, to, -1, 0);
2334 gstring = get_gstring (frame, mt, from, to, control);
2337 *num_chars_return = 0;
2341 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2342 if (g->pos >= from && g->pos < to)
2346 int width = g->width;
2347 int lbearing = g->lbearing;
2348 int rbearing = g->rbearing;
2349 int ascent = g->ascent;
2350 int descent = g->descent;
2352 int logical_descent;
2354 if (g->rface->rfont)
2356 logical_ascent = g->rface->rfont->ascent;
2357 logical_descent = g->rface->rfont->descent;
2361 logical_ascent = g->rface->ascent;
2362 logical_descent = g->rface->descent;
2364 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2366 if (lbearing < width + g->lbearing)
2367 lbearing = width + g->lbearing;
2368 if (rbearing < width + g->rbearing)
2369 rbearing = width + g->rbearing;
2371 if (ascent < g->ascent)
2373 if (descent < g->descent)
2374 descent = g->descent;
2381 if (ink_array_return)
2383 ink_array_return[start - from].x = x + lbearing;
2384 ink_array_return[start - from].y = - ascent;
2385 ink_array_return[start - from].width = rbearing - lbearing;
2386 ink_array_return[start - from].height = ascent + descent;
2388 if (logical_array_return)
2390 logical_array_return[start - from].x = x;
2391 logical_array_return[start - from].y = - logical_descent;
2392 logical_array_return[start - from].height
2393 = logical_ascent + logical_descent;
2394 logical_array_return[start - from].width = width;
2402 if (overall_ink_return)
2404 overall_ink_return->y = - gstring->line_ascent;
2405 overall_ink_return->x = gstring->lbearing;
2406 overall_ink_return->width = x - gstring->lbearing;
2407 overall_ink_return->height = gstring->height;
2409 if (overall_logical_return)
2411 overall_logical_return->y = - gstring->ascent;
2412 overall_logical_return->x = 0;
2413 overall_logical_return->width = x;
2414 overall_logical_return->height = gstring->ascent + gstring->descent;
2417 M17N_OBJECT_UNREF (gstring->top);
2424 @brief Return the character position nearest to the coordinates.
2426 The mdraw_coordinates_position () function checks which character
2427 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2428 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2429 mdraw_text_with_control () function with the drawing control
2430 object $CONTROL. Here, the character position means the number of
2431 characters that precede the character in question in $MT, that is,
2432 the character position of the first character is 0.
2434 $FRAME is used only to get the default face information.
2437 If the glyph image of a character covers coordinate ($X, $Y),
2438 mdraw_coordinates_position () returns the character position of
2440 If $Y is less than the minimum Y-coordinate of the drawn area, it
2441 returns $FROM.\n\n\n
2442 If $Y is greater than the maximum Y-coordinate of the drawn area,
2443 it returns $TO.\n\n\n
2444 If $Y fits in with the drawn area but $X is less than the minimum
2445 X-coordinate, it returns the character position of the first
2446 character drawn on the line $Y.\n\n\n
2447 If $Y fits in with the drawn area but $X is greater than the
2448 maximum X-coordinate, it returns the character position of the
2449 last character drawn on the line $Y. */
2452 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2454 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2455 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2456 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2457 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2458 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2459 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2461 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2464 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2465 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2467 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2469 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2471 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2472 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2474 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2475 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2478 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2479 int x_offset, int y_offset, MDrawControl *control)
2481 MGlyphString *gstring;
2486 M_CHECK_POS_X (mt, from, -1);
2487 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2488 to = mtext_nchars (mt) + (control->cursor_width != 0);
2494 ASSURE_CONTROL (control);
2495 gstring = get_gstring (frame, mt, from, to, control);
2496 while (y + gstring->line_descent <= y_offset
2497 && gstring->to < to)
2500 y += gstring->line_descent;
2501 M17N_OBJECT_UNREF (gstring->top);
2502 gstring = get_gstring (frame, mt, from, to, control);
2503 y += gstring->line_ascent;
2506 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2507 if (! control->orientation_reversed)
2509 width = gstring->indent;
2510 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2511 if (g->pos >= from && g->pos < to)
2514 if (width > x_offset)
2520 width = - gstring->indent;
2521 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2522 if (g->pos >= from && g->pos < to)
2525 if (width < x_offset)
2529 if (g->type == GLYPH_ANCHOR
2530 && control->two_dimensional
2534 M17N_OBJECT_UNREF (gstring->top);
2542 @brief Compute information about a glyph.
2544 The mdraw_glyph_info () function computes information about a
2545 glyph that covers a character at position $POS of the M-text $MT
2546 assuming that the text is drawn from the character at $FROM of $MT
2547 on a window of frame $FRAME using the mdraw_text_with_control ()
2548 function with the drawing control object $CONTROL.
2550 The information is stored in the members of $INFO. */
2552 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2554 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2555 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2556 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2557 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2559 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2567 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2568 MDrawControl *control, MDrawGlyphInfo *info)
2570 MGlyphString *gstring;
2574 M_CHECK_RANGE_X (mt, from, pos, -1);
2576 ASSURE_CONTROL (control);
2577 gstring = get_gstring (frame, mt, from, pos + 1, control);
2579 MERROR (MERROR_DRAW, -1);
2580 while (gstring->to <= pos)
2582 y += gstring->line_descent;
2583 M17N_OBJECT_UNREF (gstring->top);
2584 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2585 y += gstring->line_ascent;
2587 info->line_from = gstring->from;
2588 if (info->line_from < from)
2589 info->line_from = from;
2590 info->line_to = gstring->to;
2593 if (! control->orientation_reversed)
2595 info->x = gstring->indent;
2596 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2597 info->x += g->width;
2601 info->x = - gstring->indent;
2602 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2603 info->x -= g->width;
2604 while (g[-1].to == g->to)
2607 info->from = g->pos;
2609 info->metrics.x = g->lbearing;
2610 info->metrics.y = - gstring->line_ascent;
2611 info->metrics.height = gstring->height;
2612 info->metrics.width = - g->lbearing + g->width;
2613 if (g->rface->rfont)
2614 info->font = &g->rface->rfont->font;
2617 /* info->logical_width is calculated later. */
2619 if (info->from > info->line_from)
2621 /* The logically previous glyph is on this line. */
2622 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2624 info->prev_from = g_tmp->pos;
2626 else if (info->line_from > 0)
2628 /* The logically previous glyph is on the previous line. */
2629 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2630 gstring->from, control);
2631 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2633 info->prev_from = g_tmp->pos;
2634 M17N_OBJECT_UNREF (gst->top);
2637 info->prev_from = -1;
2639 if (GLYPH_INDEX (g) > 1)
2640 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2641 else if (! control->orientation_reversed)
2643 if (info->line_from > 0)
2647 int p = gstring->from - 1;
2649 gst = get_gstring (frame, mt, p, gstring->from, control);
2650 g_tmp = gst->glyphs + (gst->used - 2);
2651 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2652 M17N_OBJECT_UNREF (gst->top);
2655 info->left_from = info->left_to = -1;
2659 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2663 int p = gstring->to;
2665 gst = get_gstring (frame, mt, p, p + 1, control);
2666 g_tmp = gst->glyphs + (gst->used - 2);
2667 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2668 M17N_OBJECT_UNREF (gst->top);
2671 info->left_from = info->left_to = -1;
2674 if (info->to < gstring->to)
2676 /* The logically next glyph is on this line. */
2677 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2679 info->next_to = g_tmp->to;
2681 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2683 /* The logically next glyph is on the next line. */
2685 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2686 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2688 info->next_to = g_tmp->to;
2689 M17N_OBJECT_UNREF (gst->top);
2694 for (info->logical_width = (g++)->width;
2695 g->pos == pos && g->type != GLYPH_ANCHOR;
2696 info->metrics.width += g->width, info->logical_width += (g++)->width);
2697 info->metrics.width += g[-1].rbearing - g[-1].width;
2699 if (g->type != GLYPH_ANCHOR)
2700 info->right_from = g->pos, info->right_to = g->to;
2701 else if (! control->orientation_reversed)
2703 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2706 M17N_OBJECT_UNREF (gstring->top);
2707 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2709 info->right_from = g->pos, info->right_to = g->to;
2712 info->right_from = info->right_to = -1;
2716 if (info->line_from > 0)
2718 pos = gstring->from - 1;
2719 M17N_OBJECT_UNREF (gstring->top);
2720 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2722 info->right_from = g->pos, info->right_to = g->to;
2725 info->right_from = info->right_to = -1;
2728 M17N_OBJECT_UNREF (gstring->top);
2735 @brief Compute information about glyph sequence.
2737 The mdraw_glyph_list () function computes information about glyphs
2738 corresponding to the text between $FROM and $TO of M-text $MT when
2739 it is drawn on a window of frame $FRAME using the
2740 mdraw_text_with_control () function with the drawing control
2741 object $CONTROL. $GLYPHS is an array of objects to store the
2742 information, and $ARRAY_SIZE is the array size.
2744 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2745 number of actually filled elements in the place pointed by
2746 $NUM_GLYPHS_RETURN, and returns 0.
2748 Otherwise, it stores the required array size in the place pointed
2749 by $NUM_GLYPHS_RETURN, and returns -1. */
2752 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2754 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
2755 À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
2756 ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
2757 ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2759 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
2760 ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
2769 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2770 MDrawControl *control, MDrawGlyph *glyphs,
2771 int array_size, int *num_glyphs_return)
2773 MGlyphString *gstring;
2778 ASSURE_CONTROL (control);
2779 *num_glyphs_return = 0;
2780 M_CHECK_RANGE (mt, from, to, -1, 0);
2781 gstring = get_gstring (frame, mt, from, to, control);
2784 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2786 if (g->type == GLYPH_BOX
2787 || g->pos < from || g->pos >= to)
2789 if (g->type == GLYPH_PAD)
2791 if (g->left_padding)
2792 pad_width = g->width;
2796 glyphs[-1].x_advance += g->width;
2802 glyphs->from = g->pos;
2804 glyphs->glyph_code = g->code;
2805 glyphs->x_off = g->xoff + pad_width;
2806 glyphs->y_off = g->yoff;
2807 glyphs->lbearing = g->lbearing;
2808 glyphs->rbearing = g->rbearing;
2809 glyphs->ascent = g->ascent;
2810 glyphs->descent = g->descent;
2811 glyphs->x_advance = g->width + pad_width;
2812 glyphs->y_advance = 0;
2813 if (g->rface->rfont)
2815 glyphs->font = &g->rface->rfont->font;
2816 glyphs->font_type = g->rface->rfont->type;
2817 glyphs->fontp = g->rface->rfont->fontp;
2821 glyphs->font = NULL;
2822 glyphs->font_type = Mnil;
2823 glyphs->fontp = NULL;
2830 M17N_OBJECT_UNREF (gstring->top);
2832 *num_glyphs_return = n;
2833 return (n <= array_size ? 0 : -1);
2839 @brief Draw one or more textitems.
2841 The mdraw_text_items () function draws one or more M-texts on
2842 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2843 of the textitems to be drawn and $NITEMS is the number of
2844 textimtems in the array. */
2847 @brief textitem ¤òɽ¼¨¤¹¤ë.
2849 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2850 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2851 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2854 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2858 MTextItem, mdraw_text (). */
2861 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2862 MDrawTextItem *items, int nitems)
2864 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2866 while (nitems-- > 0)
2869 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2871 mdraw_text_with_control (frame, win, x, y,
2872 items->mt, 0, mtext_nchars (items->mt),
2874 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2875 items->control, NULL, NULL, NULL);
2878 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2884 @brief calculate a line breaking position.
2886 The function mdraw_default_line_break () calculates a line
2887 breaking position based on the line number $LINE and the
2888 coordinate $Y, when a line is too long to fit within the width
2889 limit. $POS is the position of the character next to the last
2890 one that fits within the limit. $FROM is the position of the
2891 first character of the line, and TO is the position of the last
2892 character displayed on the line if there were not width limit.
2893 LINE and Y are reset to 0 when a line is broken by a newline
2894 character, and incremented each time when a long line is broken
2895 because of the width limit.
2898 This function returns a character position to break the
2903 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2905 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2906 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2907 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2908 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2909 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2910 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2911 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2914 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2918 mdraw_default_line_break (MText *mt, int pos,
2919 int from, int to, int line, int y)
2921 int c = mtext_ref_char (mt, pos);
2924 if (c == ' ' || c == '\t')
2928 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2935 if (c == ' ' || c == '\t')
2938 c = mtext_ref_char (mt, pos);
2951 @brief Obtain per character dimension information.
2953 The mdraw_per_char_extents () function computes the text dimension
2954 of each character in M-text $MT. The faces given as text
2955 properties in $MT and the default face of frame $FRAME determine
2956 the fonts to draw the text. Each successive element in
2957 $ARRAY_RETURN is set to the drawn metrics of successive
2958 characters, which is relative to the origin of the drawing, and a
2959 rectangle for each character in $MT. The number of elements of
2960 $ARRAY_RETURN must be equal to or greater than the number of
2963 If pointer $OVERALL_RETURN is not @c NULL, this function also
2964 computes the extents of the overall text and stores the results in
2965 the members of the structure pointed to by $OVERALL_RETURN. */
2968 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2970 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2971 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2972 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2973 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2974 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2975 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2978 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2979 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2982 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2985 mdraw_per_char_extents (MFrame *frame, MText *mt,
2986 MDrawMetric *array_return,
2987 MDrawMetric *overall_return)
2989 int n = mtext_nchars (mt);
2991 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2992 n, &n, overall_return, NULL);
2996 @brief clear cached information.
2998 The mdraw_clear_cache () function clear cached information
2999 on M-text $MT that was attached by any of the drawing functions.
3000 When the behaviour of `format' or `line_break'
3001 member functions of MDrawControl is changed, the cache must be cleared.
3006 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
3008 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
3009 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
3010 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
3011 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3016 mdraw_clear_cache (MText *mt)
3018 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);