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 Mlatin, 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 *idx = alloca (sizeof (int) * len);
104 int bidi_sensitive = gstring->control.orientation_reversed;
106 MGlyph *g = MGLYPH (1);
109 FriBidiCharType base = (gstring->control.orientation_reversed
110 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
111 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
113 FriBidiStrIndex *indices;
114 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
115 #else /* not HAVE_FRIBIDI */
116 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
119 #endif /* not HAVE_FRIBIDI */
121 while (g->type != GLYPH_ANCHOR)
123 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
125 if (bidi == MbidiR || bidi == MbidiAL
126 || bidi == MbidiRLE || bidi == MbidiRLO)
133 idx[size] = GLYPH_INDEX (g);
134 logical[size++] = g++->c;
135 while (g->type != GLYPH_ANCHOR && g->combining_code)
139 if (! bidi_sensitive)
142 glyphs = alloca (sizeof (MGlyph) * gstring->used);
143 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
145 visual = alloca (sizeof (FriBidiChar) * size);
146 indices = alloca (sizeof (FriBidiStrIndex) * size);
148 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
149 #else /* not HAVE_FRIBIDI */
150 indices = alloca (sizeof (int) * size);
151 for (i = 0; i < size; i++)
157 for (j = i + 1; j < size && levels[j]; j++);
158 for (k = j--; i < k; i++, j--)
165 #endif /* not HAVE_FRIBIDI */
167 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
168 starts from gstring->glyphs[IDX[N]].
170 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
171 originally at LOGICAL[INDICES[N]]. */
173 for (i = 0, gidx = 1; i < size; i++)
178 glyphs[k].bidi_level = levels[j];
180 if (visual[i] != logical[j])
183 glyphs[k].c = visual[i];
184 if (glyphs[k].rface->rfont)
185 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
188 #endif /* not HAVE_FRIBIDI */
189 *(MGLYPH (gidx)) = glyphs[k];
191 k < gstring->used - 1 && glyphs[k].combining_code;
194 glyphs[k].bidi_level = levels[j];
195 *(MGLYPH (gidx)) = glyphs[k];
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 members <type>, <rface>, <c>, <pos>, <to>,
227 <code> of glyphs. The other members are filled by
228 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;
238 MSymbol language = Mnil, script = Mnil, charset = Mnil;
239 MSymbol non_latin_script = Mnil;
240 MRealizedFace *rface = default_rface;
241 int size = gstring->control.fixed_width;
245 MLIST_RESET (gstring);
246 gstring->from = from;
248 /* At first generate glyphs while using the member <enabled> as a
249 flag for rface re-checking. */
252 /** Put anchor glyphs at the head and tail. */
253 g_tmp.type = GLYPH_ANCHOR;
254 g_tmp.pos = g_tmp.to = from;
256 APPEND_GLYPH (gstring, g_tmp);
258 stop = face_change = charset_change = language_change = pos = from;
265 if (pos < mtext_nchars (mt))
266 c = mtext_ref_char (mt, pos);
269 g_tmp.category = mchar_get_prop (c, Mcategory);
272 /* Short cut for the obvious case. */
273 g_tmp.type = (c == ' ' || c == '\n' || c == '\t'
274 ? GLYPH_SPACE : GLYPH_CHAR);
275 this_script = (MSYMBOL_NAME (g_tmp.category)[0] == 'L'
280 g_tmp.type = GLYPH_CHAR;
281 this_script = (MSymbol) mchar_get_prop (c, Mscript);
282 if (this_script == Minherited || this_script == Mnil)
283 this_script = script;
284 if (this_script == Mnil)
285 this_script = non_latin_script;
286 if (this_script == Mnil)
288 /* Search forward for a character that explicitly
289 specifies a non-latin script. */
293 for (i = pos + 1; i < to; i++)
294 if ((c1 = mtext_ref_char (mt, i)) >= 0x100
295 && (sym = mchar_get_prop (c1, Mscript)) != Mnil
296 && sym != Minherited)
304 if (pos == stop || script != this_script
305 || MGLYPH (last)->type != g_tmp.type)
308 if (g->type != GLYPH_ANCHOR)
309 while (g < gstring->glyphs + gstring->used)
310 g = mface__for_chars (script == Mnil ? Mlatin : script,
312 g, gstring->glyphs + gstring->used, size);
315 last = gstring->used;
316 script = this_script;
317 if (script != Mnil && script != Mlatin)
318 non_latin_script = script;
321 if (pos < mtext_nchars (mt) && pos == language_change)
323 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
324 mtext_prop_range (mt, Mlanguage, pos, NULL,
325 &language_change, 0);
327 if (pos < mtext_nchars (mt) && pos == charset_change)
329 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
330 mtext_prop_range (mt, Mcharset, pos, NULL,
333 if (pos < mtext_nchars (mt) && pos == face_change)
336 int num = mtext_get_prop_values (mt, pos, Mface,
337 (void **) faces, 64);
339 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
341 ? mface__realize (frame, faces, num,
342 language, charset, size)
346 if (stop > language_change)
347 stop = language_change;
348 if (stop > charset_change)
349 stop = charset_change;
350 if (face_change < stop)
360 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
364 ctrl[0] = ctrl[1] = g_tmp;
366 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
367 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
368 APPEND_GLYPH (gstring, ctrl[0]);
369 APPEND_GLYPH (gstring, ctrl[1]);
372 APPEND_GLYPH (gstring, g_tmp);
374 && gstring->control.two_dimensional)
378 /* Append an anchor glyph. */
379 g_tmp.type = GLYPH_ANCHOR;
381 g_tmp.code = MCHAR_INVALID_CODE;
382 g_tmp.pos = g_tmp.to = pos;
384 APPEND_GLYPH (gstring, g_tmp);
388 /* Next, run FLT if necessary. */
389 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
393 if (this->type == GLYPH_CHAR && this->rface->rfont)
397 if (this->rface->rfont->layouter != Mnil)
402 for (prev = MGLYPH (start - 1);
403 (prev->type == GLYPH_CHAR
404 && prev->category == McatCf
405 && (code = mfont__encode_char (this->rface->rfont, prev->c)
406 != MCHAR_INVALID_CODE));
411 (g->type == GLYPH_CHAR
412 && (g->rface->rfont == this->rface->rfont
413 || (g->category == McatCf
414 && ((code = mfont__encode_char (this->rface->rfont,
416 != MCHAR_INVALID_CODE))));
418 if (g->rface->rfont != this->rface->rfont)
420 g->rface->rfont = this->rface->rfont;
423 i = mfont__flt_run (gstring, start, i, this->rface);
427 while (this->type == GLYPH_CHAR
430 && MSYMBOL_NAME (this->category)[0] == 'M'
431 && this->rface->rfont
432 && this->rface->rfont->layouter == Mnil)
434 int class = (int) mchar_get_prop (this->c,
437 = MAKE_COMBINING_CODE_BY_CLASS (class);
441 reorder_combining_chars (gstring, start, i);
442 if (this->type == GLYPH_ANCHOR)
451 /* At last, reorder glyphs visually if necessary. */
452 if (gstring->control.enable_bidi)
453 visual_order (gstring);
458 combining_code_from_class (int class)
463 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
464 else if (class == 200) /* below left attached */
465 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
466 else if (class == 202) /* below attached*/
467 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
468 else if (class == 204) /* below right attached */
469 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
470 else if (class == 208) /* left attached */
471 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
472 else if (class == 210) /* right attached */
473 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
474 else if (class == 212) /* above left attached */
475 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
476 else if (class == 214) /* above attached */
477 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
478 else if (class == 216) /* above right attached */
479 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
480 else if (class == 218) /* below left */
481 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
482 else if (class == 220) /* below */
483 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
484 else if (class == 222) /* below right */
485 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
486 else if (class == 224) /* left */
487 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
488 else if (class == 226) /* right */
489 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
490 else if (class == 228) /* above left */
491 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
492 else if (class == 230) /* above */
493 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
494 else if (class == 232) /* above right */
495 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
496 else if (class == 233) /* double below */
497 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
498 else if (class == 234) /* double above */
499 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
500 else if (class == 240) /* iota subscript */
501 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
503 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
509 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
511 int g_physical_ascent, g_physical_descent;
512 int g_width, g_lbearing, g_rbearing;
513 MGlyph *g = MGLYPH (from);
514 MGlyph *last_g = MGLYPH (to);
516 g_physical_ascent = gstring->physical_ascent;
517 g_physical_descent = gstring->physical_descent;
518 g_width = g_lbearing = g_rbearing = 0;
520 mfont__get_metric (gstring, from, to);
529 while (g < last_g && base->otf_cmd == g->otf_cmd) g++;
530 mfont__ft_drive_gpos (gstring, GLYPH_INDEX (base), GLYPH_INDEX (g));
539 MRealizedFont *rfont = base->rface->rfont;
540 int size = rfont->font.property[MFONT_SIZE];
541 int width, lbearing, rbearing;
543 if (g == last_g || ! g->combining_code)
546 if (base->left_padding && base->lbearing < 0)
548 base->xoff = - base->lbearing;
549 base->width += base->xoff;
550 base->rbearing += base->xoff;
553 if (base->right_padding && base->rbearing > base->width)
555 base->width = base->rbearing;
557 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
558 rbearing = base->rbearing;
562 /* With combining glyphs. */
563 int left = -base->width;
565 int top = - base->ascent;
566 int bottom = base->descent;
567 int height = bottom - top;
568 int begin = base->pos;
573 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
574 rbearing = base->rbearing;
576 while (g != last_g && g->combining_code)
578 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
580 combining_code = g->combining_code;
581 if (COMBINING_BY_CLASS_P (combining_code))
582 g->combining_code = combining_code
583 = combining_code_from_class (COMBINING_CODE_CLASS
586 rfont = g->rface->rfont;
587 size = rfont->font.property[MFONT_SIZE];
588 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
590 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
592 base_x = COMBINING_CODE_BASE_X (combining_code);
593 base_y = COMBINING_CODE_BASE_Y (combining_code);
594 add_x = COMBINING_CODE_ADD_X (combining_code);
595 add_y = COMBINING_CODE_ADD_Y (combining_code);
599 else if (end < g->to)
602 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
605 if (g->xoff + g->width > right)
606 right = g->xoff + g->width;
607 width = right - left;
608 if (g->xoff + g->lbearing < left + lbearing)
609 lbearing = g->xoff + g->lbearing - left;
610 if (g->xoff + g->rbearing > left + rbearing)
611 rbearing = g->xoff + g->rbearing - left;
614 g->yoff = top + height * base_y / 2;
618 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
620 if (g->yoff - g->ascent < top)
621 top = g->yoff - g->ascent;
622 if (g->yoff + g->descent > bottom)
623 bottom = g->yoff + g->descent;
624 height = bottom - top;
630 base->ascent = - top;
631 base->descent = bottom;
632 base->lbearing = lbearing;
633 base->rbearing = rbearing;
634 if (left < - base->width)
636 base->xoff = - base->width - left;
637 base->width += base->xoff;
638 base->rbearing += base->xoff;
639 base->lbearing += base->xoff;
643 base->width += right;
644 base->rbearing += right;
645 base->right_padding = 1;
646 for (i = 1; base + i != g; i++)
647 base[i].xoff -= right;
650 for (i = 0; base + i != g; i++)
657 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
658 g_physical_descent = MAX (g_physical_descent, base->descent);
659 g_lbearing = MIN (g_lbearing, g_width + lbearing);
660 g_rbearing = MAX (g_rbearing, g_width + rbearing);
661 g_width += base->width;
664 gstring->physical_ascent = g_physical_ascent;
665 gstring->physical_descent = g_physical_descent;
666 gstring->sub_width = g_width;
667 gstring->sub_lbearing = g_lbearing;
668 gstring->sub_rbearing = g_rbearing;
672 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
673 by this function directly. Character glyphs are handled by
674 layouter functions registered in font drivers.
676 This function fill-in all the remaining members of glyphs. */
679 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
681 /* Default width of TAB. */
682 int tab_width = frame->space_width * (gstring->control.tab_width
683 ? gstring->control.tab_width : 8);
687 MDrawControl *control = &(gstring->control);
690 int box_line_height = 0;
691 int ignore_formatting_char = control->ignore_formatting_char;
693 gstring->ascent = gstring->descent = 0;
694 gstring->physical_ascent = gstring->physical_descent = 0;
695 gstring->width = gstring->lbearing = gstring->rbearing = 0;
699 while (g->type != GLYPH_ANCHOR)
701 if (box != g->rface->box)
703 int gidx = GLYPH_INDEX (g);
707 /* Insert the right side of the box. That glyph belongs
708 to the previous grapheme cluster. */
709 MGlyph box_glyph = g[-1];
711 box_glyph.type = GLYPH_BOX;
713 = (control->fixed_width
715 : box->inner_hmargin + box->width + box->outer_hmargin);
716 box_glyph.lbearing = 0;
717 box_glyph.rbearing = box_glyph.width;
719 box_glyph.right_padding = 1;
720 gstring->width += box_glyph.width;
721 gstring->rbearing += box_glyph.width;
722 INSERT_GLYPH (gstring, gidx, box_glyph);
729 /* Insert the left side of the box. That glyph belongs
730 to the following grapheme cluster. */
731 MGlyph box_glyph = *g;
732 int box_height = (box->width
733 + box->inner_vmargin + box->outer_vmargin);
735 if (box_line_height < box_height)
736 box_line_height = box_height;
737 box_glyph.type = GLYPH_BOX;
739 = (control->fixed_width
741 : box->inner_hmargin + box->width + box->outer_hmargin);
742 box_glyph.lbearing = 0;
743 box_glyph.rbearing = box_glyph.width;
745 box_glyph.left_padding = 1;
746 gstring->width += box_glyph.width;
747 gstring->rbearing += box_glyph.width;
748 INSERT_GLYPH (gstring, gidx, box_glyph);
754 if (g->category == McatCf && ignore_formatting_char)
755 g->type = GLYPH_SPACE;
757 if (g->type == GLYPH_CHAR)
759 MRealizedFace *rface = g->rface;
760 MRealizedFont *rfont = rface->rfont;
762 int from = GLYPH_INDEX (g);
764 for (g++; g->type == GLYPH_CHAR; g++)
765 if (! rfont != ! g->rface->rfont
766 || box != g->rface->box
767 || ((fromg->code == MCHAR_INVALID_CODE)
768 != (g->code == MCHAR_INVALID_CODE))
769 || (g->category == McatCf && ignore_formatting_char))
771 if (rfont && fromg->code != MCHAR_INVALID_CODE)
774 int to = GLYPH_INDEX (g);
776 layout_glyphs (frame, gstring, from, to);
777 extra_width = - gstring->sub_lbearing;
779 && (GLYPH_INDEX (g) > 1
780 || control->align_head))
784 pad.type = GLYPH_PAD;
787 pad.width = pad.rbearing = extra_width;
788 pad.left_padding = 1;
789 INSERT_GLYPH (gstring, from, pad);
791 gstring->sub_lbearing = 0;
792 gstring->sub_width += extra_width;
793 gstring->sub_rbearing += extra_width;
795 g = MGLYPH (from - 1);
796 if (g->type == GLYPH_SPACE)
798 /* The pad just inserted is absorbed (maybe
799 partially) by the previous space while
800 keeping at least some space width. For the
801 moment, we use the arbitrary width 2-pixel.
802 Perhaps, it should be decided by the current
803 face, or a default value of the current
804 frame, which is, however, not yet
806 if (extra_width + 2 < g->width)
808 g->width -= extra_width;
812 extra_width -= g->width - 2;
815 gstring->width -= extra_width;
816 gstring->rbearing -= extra_width;
820 extra_width = gstring->sub_rbearing - gstring->sub_width;
824 if (g->type == GLYPH_SPACE && box == g->rface->box)
828 pad.type = GLYPH_PAD;
831 pad.width = pad.rbearing = extra_width;
833 INSERT_GLYPH (gstring, to, pad);
837 g[-1].width += extra_width;
838 gstring->sub_width += extra_width;
841 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
842 gstring->lbearing = gstring->width + gstring->sub_lbearing;
843 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
844 gstring->rbearing = gstring->width + gstring->sub_rbearing;
845 gstring->width += gstring->sub_width;
846 if (gstring->ascent < rface->ascent)
847 gstring->ascent = rface->ascent;
848 if (gstring->descent < rface->descent)
849 gstring->descent = rface->descent;
854 for (; fromg < g; fromg++)
856 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
857 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
858 fromg->width = fromg->rbearing = 1;
860 fromg->width = fromg->rbearing = rface->space_width;
861 fromg->xoff = fromg->lbearing = 0;
862 fromg->ascent = fromg->descent = 0;
863 gstring->width += fromg->width;
864 gstring->rbearing += fromg->width;
866 if (gstring->ascent < frame->rface->ascent)
867 gstring->ascent = frame->rface->ascent;
868 if (gstring->descent < frame->descent)
869 gstring->descent = frame->rface->descent;
872 else if (g->type == GLYPH_SPACE)
875 g->width = g->rface->space_width;
876 else if (g->c == '\n')
878 g->width = control->cursor_width;
881 if (control->cursor_bidi)
883 else if (g->width < 0)
884 g->width = g->rface->space_width;
887 else if (g->c == '\t')
889 g->width = tab_width - ((gstring->indent + gstring->width)
895 if (g[-1].type == GLYPH_PAD)
897 /* This space glyph absorbs (maybe partially) the
898 previous padding glyph. */
899 g->width -= g[-1].width;
901 /* But, keep at least some space width. For the
902 moment, we use the arbitrary width 2-pixel. */
905 g->rbearing = g->width;
906 gstring->width += g->width;
907 gstring->rbearing += g->width;
910 if (gstring->ascent < g->rface->ascent)
911 gstring->ascent = g->rface->ascent;
912 if (gstring->descent < g->rface->descent)
913 gstring->descent = g->rface->descent;
919 gstring->width += g->width;
920 gstring->rbearing += g->width;
927 /* Insert the right side of the box. */
928 int gidx = GLYPH_INDEX (g);
929 MGlyph box_glyph = g[-1];
931 box_glyph.type = GLYPH_BOX;
933 = (control->fixed_width
935 : box->inner_hmargin + box->width + box->outer_hmargin);
936 box_glyph.lbearing = 0;
937 box_glyph.rbearing = box_glyph.width;
939 box_glyph.right_padding = 1;
940 gstring->width += box_glyph.width;
941 gstring->rbearing += box_glyph.width;
942 INSERT_GLYPH (gstring, gidx, box_glyph);
945 gstring->text_ascent = gstring->ascent;
946 gstring->text_descent = gstring->descent;
947 if (gstring->text_ascent < gstring->physical_ascent)
948 gstring->text_ascent = gstring->physical_ascent;
949 if (gstring->text_descent < gstring->physical_descent)
950 gstring->text_descent = gstring->physical_descent;
951 gstring->line_ascent = gstring->text_ascent;
952 gstring->line_descent = gstring->text_descent;
953 if (box_line_height > 0)
955 gstring->line_ascent += box_line_height;
956 gstring->physical_ascent = gstring->line_ascent;
957 gstring->line_descent += box_line_height;
958 gstring->physical_descent = gstring->line_descent;
961 if (gstring->line_ascent < control->min_line_ascent)
962 gstring->line_ascent = control->min_line_ascent;
963 else if (control->max_line_ascent
964 && control->max_line_ascent > control->min_line_ascent
965 && gstring->line_ascent > control->max_line_ascent)
966 gstring->line_ascent = control->max_line_ascent;
968 if (gstring->line_descent < control->min_line_descent)
969 gstring->line_descent = control->min_line_descent;
970 else if (control->max_line_descent
971 && control->max_line_descent > control->min_line_descent
972 && gstring->line_descent > control->max_line_descent)
973 gstring->line_descent = control->max_line_descent;
974 gstring->height = gstring->line_ascent + gstring->line_descent;
976 if (control->orientation_reversed
979 /* We must adjust TAB width for RTL orientation. */
980 width = gstring->indent;
982 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
984 if (g->type == GLYPH_CHAR && g->c == '\t')
986 int this_width = tab_width - (width % tab_width);
988 if (g[1].type == GLYPH_PAD)
989 this_width -= g[1].width;
990 if (g[-1].type == GLYPH_PAD)
991 this_width -= g[-1].width;
994 gstring->width += this_width - g->width;
995 gstring->rbearing += this_width - g->width;
996 g->width = this_width;
1007 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1008 MGlyphString *gstring, int from, int to,
1009 int *from_idx, int *to_idx, int *to_x)
1011 MGlyph *g = MGLYPH (1);
1012 MDrawRegion region = (MDrawRegion) NULL;
1013 MDrawControl *control = &gstring->control;
1014 int cursor_pos = -1;
1016 int cursor_bidi = control->cursor_bidi;
1018 if (control->with_cursor && control->cursor_width)
1020 if (gstring->from <= control->cursor_pos
1021 && gstring->to > control->cursor_pos)
1022 cursor_pos = control->cursor_pos;
1024 && gstring->from <= control->cursor_pos - 1
1025 && gstring->to > control->cursor_pos - 1)
1026 prev_pos = control->cursor_pos - 1;
1029 *from_idx = *to_idx = 0;
1030 while (g->type != GLYPH_ANCHOR)
1032 if (g->pos >= from && g->pos < to)
1034 MGlyph *fromg = g, *cursor = NULL;
1035 MRealizedFace *rface = g->rface;
1037 int cursor_width = 0;
1041 *from_idx = GLYPH_INDEX (g);
1042 while (g->pos >= from && g->pos < to
1043 && g->rface == rface)
1046 if (g->type != GLYPH_BOX
1047 && g->pos <= cursor_pos && g->to > cursor_pos)
1050 cursor = g, cursor_x = x + width;
1051 cursor_width += g->width;
1053 width += g++->width;
1056 && (control->as_image
1057 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1059 int this_x = x, this_width = width;
1061 if (fromg->type == GLYPH_BOX)
1062 this_x += fromg->width, this_width -= fromg->width;
1063 if (g[-1].type == GLYPH_BOX)
1064 this_width -= g[-1].width;
1065 (frame->driver->fill_space)
1066 (frame, win, rface, 0,
1067 this_x, y - gstring->text_ascent, this_width,
1068 gstring->text_ascent + gstring->text_descent,
1069 control->clip_region);
1076 rect.y = y - gstring->text_ascent;
1077 rect.height = gstring->text_ascent + gstring->text_descent;
1080 rect.width = ((control->cursor_width > 0
1081 && control->cursor_width < cursor_width)
1082 ? control->cursor_width : cursor_width);
1086 if (cursor->bidi_level % 2)
1087 rect.x += cursor_width - 1;
1090 (*frame->driver->fill_space)
1091 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1092 control->clip_region);
1094 region = (*frame->driver->region_from_rect) (&rect);
1096 (*frame->driver->region_add_rect) (region, &rect);
1099 if (cursor->bidi_level % 2)
1102 rect.width = cursor_width < 4 ? cursor_width : 4;
1103 (*frame->driver->fill_space)
1104 (frame, win, rface, 1,
1105 rect.x, rect.y, rect.width, rect.height,
1106 control->clip_region);
1107 (*frame->driver->region_add_rect) (region, &rect);
1119 if (fromg->type != GLYPH_BOX
1120 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1123 cursor = fromg, cursor_x = x + temp_width;
1124 cursor_width += fromg->width;
1126 temp_width += fromg++->width;
1133 if (! (cursor->bidi_level % 2))
1134 rect.x += cursor_width - 1;
1135 rect.y = y - gstring->text_ascent;
1136 rect.height = gstring->text_ascent + gstring->text_descent;
1138 (*frame->driver->fill_space)
1139 (frame, win, rface, 1,
1140 rect.x, rect.y, rect.width, rect.height,
1141 control->clip_region);
1143 region = (*frame->driver->region_from_rect) (&rect);
1145 (*frame->driver->region_add_rect) (region, &rect);
1146 rect.y += rect.height - 2;
1148 rect.width = cursor_width < 4 ? cursor_width : 4;
1149 if (! (cursor->bidi_level % 2))
1150 rect.x -= rect.width - 1;
1151 (*frame->driver->fill_space) (frame, win, rface, 1,
1152 rect.x, rect.y, rect.width, rect.height,
1153 control->clip_region);
1154 (*frame->driver->region_add_rect) (region, &rect);
1158 *to_idx = GLYPH_INDEX (g);
1168 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1169 MGlyphString *gstring, int from_idx, int to_idx,
1170 int reverse, MDrawRegion region)
1172 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1178 (*frame->driver->region_to_rect) (region, &rect);
1181 while (g != gend && x + g->rbearing <= rect.x)
1184 width -= g++->width;
1185 while (! g->enabled && g != gend)
1189 rect.x += rect.width;
1190 if (rect.x < x + width)
1193 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1195 width -= (--gend)->width;
1196 while (! gend->enabled && g != gend)
1200 while (gend[-1].to == gend->to) gend++;
1208 MRealizedFace *rface = g->rface;
1209 int width = g->width;
1210 MGlyph *from_g = g++;
1212 /* Handle the glyphs of the same type/face at once. */
1214 && g->type == from_g->type
1215 && g->rface == rface
1216 && ((g->code == MCHAR_INVALID_CODE)
1217 == (from_g->code == MCHAR_INVALID_CODE))
1219 width += g++->width;
1221 if (from_g->type == GLYPH_CHAR)
1223 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1224 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1227 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1230 else if (from_g->type == GLYPH_BOX)
1232 /* Draw the left or right side of a box. If
1233 from_g->lbearing is nonzero, this is the left side,
1234 else this is the right side. */
1235 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1238 if (from_g->type != GLYPH_BOX)
1241 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1242 x, y, width, region);
1245 /* Draw the top and bottom side of a box. */
1246 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1247 x, y, width, region);
1258 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1259 int *from_x, int *to_x)
1262 int left_idx = *left, right_idx = *right;
1263 int left_x, right_x, x;
1265 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1268 if (x + g->rbearing > 0)
1270 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1272 left_idx = GLYPH_INDEX (g);
1277 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1280 if (x - g->width + g->lbearing < 0)
1282 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1284 right_idx = GLYPH_INDEX (g) + 1;
1289 if (*left == left_idx && *right == right_idx)
1292 if (*left != left_idx)
1294 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1299 if (*right != right_idx)
1301 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1311 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1316 if (from <= gstring->from && to >= gstring->to)
1319 *rbearing = gstring->rbearing;
1320 return gstring->width;
1325 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1326 if (g->pos >= from && g->pos < to)
1328 if (rbearing && width + g->rbearing > *rbearing)
1329 *rbearing = width + g->rbearing;
1337 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1338 MGlyphString *gstring, int from, int to)
1340 MDrawControl *control = &gstring->control;
1342 MDrawRegion clip_region, cursor_region;
1343 int from_idx, to_idx;
1346 if (control->orientation_reversed)
1347 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1349 x += gstring->indent;
1351 /* At first, draw all glyphs without cursor. */
1352 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1353 &from_idx, &to_idx, &to_x);
1355 if (control->partial_update)
1358 rect.width = to_x - x;
1359 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1361 rect.y = y - gstring->line_ascent;
1362 rect.height = gstring->height;
1363 clip_region = (*frame->driver->region_from_rect) (&rect);
1364 if (control->clip_region)
1365 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1368 clip_region = control->clip_region;
1371 clip_region = control->clip_region;
1373 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1378 (*frame->driver->intersect_region) (cursor_region, clip_region);
1379 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1382 if (clip_region != control->clip_region)
1383 (*frame->driver->free_region) (clip_region);
1385 (*frame->driver->free_region) (cursor_region);
1389 static int gstring_num;
1392 free_gstring (void *object)
1394 MGlyphString *gstring = (MGlyphString *) object;
1397 free_gstring (gstring->next);
1398 if (gstring->size > 0)
1399 free (gstring->glyphs);
1405 static MGlyphString scratch_gstring;
1407 static MGlyphString *
1408 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1411 MGlyphString *gstring;
1413 if (pos == mt->nchars)
1415 gstring = &scratch_gstring;
1419 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1420 MLIST_INIT1 (gstring, glyphs, 128);
1424 gstring->frame = frame;
1425 gstring->tick = frame->tick;
1426 gstring->top = gstring;
1428 gstring->control = *control;
1429 gstring->indent = gstring->width_limit = 0;
1430 if (control->format)
1431 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1433 gstring->width_limit = control->max_line_width;
1434 gstring->anti_alias = control->anti_alias;
1438 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1441 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1449 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1450 a width of glyphs for the character at I of GSTRING->mt. If I is
1451 not a beginning of a grapheme cluster, the corresponding element
1453 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1454 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1455 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1456 pos_width[g->pos - gstring->from] += g->width;
1457 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1459 if (pos_width[i] > 0)
1461 if (width + pos_width[i] > gstring->width_limit)
1464 width += pos_width[i];
1467 pos = gstring->from + i;
1468 if (gstring->control.line_break)
1470 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1471 gstring->from, gstring->to, 0, 0);
1472 if (pos <= gstring->from || pos >= gstring->to)
1475 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1476 layout_glyph_string (frame, gstring);
1480 /* Return a gstring that covers a character at POS. */
1482 static MGlyphString *
1483 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1485 MGlyphString *gstring = NULL;
1487 if (pos < mtext_nchars (mt))
1489 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1492 && ((prop->start != 0
1493 && mtext_ref_char (mt, prop->start - 1) != '\n')
1494 || (prop->end < mtext_nchars (mt)
1495 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1497 mtext_detach_property (prop);
1502 gstring = prop->val;
1503 if (gstring->frame != frame
1504 || gstring->tick != frame->tick
1505 || memcmp (control, &gstring->control,
1506 (char *) (&control->with_cursor)
1507 - (char *) (control)))
1509 mtext_detach_property (prop);
1514 else if (! control->cursor_width)
1522 offset = mtext_character (mt, pos, 0, '\n');
1527 offset -= gstring->from;
1529 for (gst = gstring; gst; gst = gst->next)
1533 gst->from += offset;
1535 for (i = 0; i < gst->used; i++)
1537 gst->glyphs[i].pos += offset;
1538 gst->glyphs[i].to += offset;
1541 M17N_OBJECT_REF (gstring);
1546 int line = 0, y = 0;
1548 if (control->two_dimensional)
1550 beg = mtext_character (mt, pos, 0, '\n');
1555 end = mtext_nchars (mt) + (control->cursor_width != 0);
1562 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1563 compose_glyph_string (frame, mt, beg, end, gstring);
1564 layout_glyph_string (frame, gstring);
1566 if (control->two_dimensional
1567 && gstring->width_limit
1568 && gstring->width > gstring->width_limit)
1570 MGlyphString *gst = gstring;
1572 truncate_gstring (frame, mt, gst);
1573 while (gst->to < end)
1575 line++, y += gst->height;
1576 gst->next = alloc_gstring (frame, mt, gst->from, control,
1578 gst->next->top = gstring;
1579 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1581 layout_glyph_string (frame, gst);
1582 if (gst->width <= gst->width_limit)
1584 truncate_gstring (frame, mt, gst);
1588 if (! control->disable_caching && pos < mtext_nchars (mt))
1590 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1591 MTEXTPROP_VOLATILE_STRONG);
1593 if (end > mtext_nchars (mt))
1594 end = mtext_nchars (mt);
1595 mtext_attach_property (mt, beg, end, prop);
1596 M17N_OBJECT_UNREF (prop);
1600 while (gstring->to <= pos)
1602 if (! gstring->next)
1604 gstring = gstring->next;
1606 gstring->control = *control;
1612 static MDrawControl control_noop;
1614 #define ASSURE_CONTROL(control) \
1616 control = &control_noop; \
1621 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1622 MText *mt, int from, int to,
1623 MDrawControl *control)
1625 MGlyphString *gstring;
1627 M_CHECK_POS_X (mt, from, -1);
1628 ASSURE_CONTROL (control);
1629 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1630 to = mtext_nchars (mt) + (control->cursor_width != 0);
1634 gstring = get_gstring (frame, mt, from, to, control);
1636 MERROR (MERROR_DRAW, -1);
1637 render_glyph_string (frame, win, x, y, gstring, from, to);
1641 y += gstring->line_descent;
1642 M17N_OBJECT_UNREF (gstring->top);
1643 gstring = get_gstring (frame, mt, from, to, control);
1644 y += gstring->line_ascent;
1645 render_glyph_string (frame, win, x, y, gstring, from, to);
1648 M17N_OBJECT_UNREF (gstring->top);
1655 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1661 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1662 if (g->pos <= pos && g->to > pos)
1667 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1668 if (g->pos <= pos && g->to > pos)
1675 /* for debugging... */
1679 dump_combining_code (int code)
1681 char *vallign = "tcbB";
1682 char *hallign = "lcr";
1688 if (COMBINING_BY_CLASS_P (code))
1689 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1690 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1691 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1692 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1693 off_x = COMBINING_CODE_OFF_X (code) - 128;
1695 sprintf (work + 2, "+%d", off_y);
1697 sprintf (work + 2, "%d", off_y);
1698 else if (off_x == 0)
1699 sprintf (work + 2, ".");
1700 p = work + strlen (work);
1702 sprintf (p, ">%d", off_x);
1704 sprintf (p, "<%d", -off_x);
1706 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1707 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1713 dump_gstring (MGlyphString *gstring, int indent)
1715 char *prefix = (char *) alloca (indent + 1);
1716 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1718 memset (prefix, 32, indent);
1721 fprintf (stderr, "(glyph-string");
1723 for (g = MGLYPH (0); g < last_g; g++)
1725 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1727 g - gstring->glyphs,
1728 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1729 : g->type == GLYPH_ANCHOR ? "ANC"
1730 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1731 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1732 dump_combining_code (g->combining_code),
1733 g->width, g->bidi_level);
1734 fprintf (stderr, ")");
1738 /* m17n-X internal APIs */
1743 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1745 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1746 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1748 Mlatin = msymbol ("latin");
1749 Minherited = msymbol ("inherited");
1751 McatCc = msymbol ("Cc");
1752 McatCf = msymbol ("Cf");
1754 MbidiR = msymbol ("R");
1755 MbidiAL = msymbol ("AL");
1756 MbidiRLE = msymbol ("RLE");
1757 MbidiRLO = msymbol ("RLO");
1758 MbidiBN = msymbol ("BN");
1759 MbidiS = msymbol ("S");
1761 fribidi_set_mirroring (TRUE);
1770 MLIST_FREE1 (&scratch_gstring, glyphs);
1774 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1778 /*** @addtogroup m17nDraw */
1783 @brief Draw an M-text on a window.
1785 The mdraw_text () function draws the text between $FROM and $TO of
1786 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1788 The appearance of the text (size, style, color, etc) is specified
1789 by the value of the text property whose key is @c Mface. If the
1790 M-text or a part of the M-text does not have such a text property,
1791 the default face of $FRAME is used.
1793 The font used to draw a character in the M-text is selected from
1794 the value of the fontset property of a face by the following
1799 <li> Search the text properties given to the character for the one
1800 whose key is @c Mcharset; its value should be either a symbol
1801 specifying a charset or #Mnil. If the value is #Mnil,
1802 proceed to the next step.
1804 Otherwise, search the mapping table of the fontset for the
1805 charset. If no entry is found proceed to the next step.
1807 If an entry is found, use one of the fonts in the entry that
1808 has a glyph for the character and that matches best with the
1809 face properties. If no such font exists, proceed to the next
1812 <li> Get the character property "script" of the character. If it is
1813 inherited, get the script property from the previous
1814 characters. If there is no previous character, or none of
1815 them has the script property other than inherited, proceed to
1818 Search the text properties given to the character for the one
1819 whose key is @c Mlanguage; its value should be either a
1820 symbol specifying a language or @c Mnil.
1822 Search the mapping table of the fontset for the combination
1823 of the script and language. If no entry is found, proceed to
1826 If an entry is found, use one of the fonts in the entry that
1827 has a glyph for the character and that matches best with the
1828 face properties. If no such font exists, proceed to the next
1831 <li> Search the fall-back table of the fontset for a font that has
1832 a glyph of the character. If such a font is found, use that
1837 If no font is found by the algorithm above, this function draws an
1838 empty box for the character.
1840 This function draws only the glyph foreground. To specify the
1841 background color, use mdraw_image_text () or
1842 mdraw_text_with_control ().
1844 This function is the counterpart of <tt>XDrawString ()</tt>,
1845 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1846 in the X Window System.
1849 If the operation was successful, mdraw_text () returns 0. If an
1850 error is detected, it returns -1 and assigns an error code to the
1851 external variable #merror_code. */
1853 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1855 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1856 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1859 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1860 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1861 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1862 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1864 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1865 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1869 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1870 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1871 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1872 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1873 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1876 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1877 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1878 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1881 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1882 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1883 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1884 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1886 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1887 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1890 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1891 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1894 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1895 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1896 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1899 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1900 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1904 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1905 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1907 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1908 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1911 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1912 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1915 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1916 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1918 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1925 mdraw_image_text () */
1928 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1929 MText *mt, int from, int to)
1931 MDrawControl control;
1933 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1934 memset (&control, 0, sizeof control);
1935 control.as_image = 0;
1936 return draw_text (frame, win, x, y, mt, from, to, &control);
1943 @brief Draw an M-text on a window as an image.
1945 The mdraw_image_text () function draws the text between $FROM and
1946 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1947 coordinate ($X, $Y).
1949 The way to draw a text is the same as in mdraw_text () except that
1950 this function also draws the background with the color specified
1953 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1954 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1955 functions in the X Window System.
1958 If the operation was successful, mdraw_image_text () returns 0.
1959 If an error is detected, it returns -1 and assigns an error code
1960 to the external variable #merror_code. */
1963 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1965 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1966 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1969 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1970 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1972 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1973 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1977 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1978 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1981 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1991 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1992 MText *mt, int from, int to)
1994 MDrawControl control;
1996 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1997 memset (&control, 0, sizeof control);
1998 control.as_image = 1;
1999 return draw_text (frame, win, x, y, mt, from, to, &control);
2005 @brief Draw an M-text on a window with fine control.
2007 The mdraw_text_with_control () function draws the text between
2008 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2009 coordinate ($X, $Y).
2011 The way to draw a text is the same as in mdraw_text () except that
2012 this function also follows what specified in the drawing control
2015 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2016 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2017 breaks lines and the following characters are drawn in the next
2018 line. See the documentation of the structure @ MDrawControl for
2022 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2024 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2025 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2028 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2029 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2031 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2032 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2033 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2037 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2038 MText *mt, int from, int to, MDrawControl *control)
2040 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2041 return draw_text (frame, win, x, y, mt, from, to, control);
2047 @brief Compute text pixel width.
2049 The mdraw_text_extents () function computes the width of text
2050 between $FROM and $TO of M-text $MT when it is drawn on a window
2051 of frame $FRAME using the mdraw_text_with_control () function with
2052 the drawing control object $CONTROL.
2054 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2055 the bounding box of character ink of the M-text, and stores the
2056 results in the members of the structure pointed to by
2057 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2058 surrounding box, the box is included in the bounding box.
2060 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2061 computes the bounding box that provides mininum spacing to other
2062 graphical features (such as surrounding box) for the M-text, and
2063 stores the results in the members of the structure pointed to by
2064 $OVERALL_LOGICAL_RETURN.
2066 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2067 computes the bounding box that provides mininum spacing to the
2068 other M-text drawn, and stores the results in the members of the
2069 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2070 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2071 min_line_ascent, min_line_descent, max_line_ascent, and
2072 max_line_descent of $CONTROL are all zero.
2075 This function returns the width of the text to be drawn in the
2076 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2077 text is drawn in multiple physical lines, it returns the width of
2078 the widest line. If an error occurs, it returns -1 and assigns an
2079 error code to the external variable #merror_code. */
2083 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2085 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2086 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2087 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2089 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2090 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2091 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2092 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2094 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2095 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2096 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2097 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2099 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2100 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2101 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2102 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2103 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2104 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2106 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2107 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2108 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2109 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2111 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2118 mdraw_text_extents (MFrame *frame,
2119 MText *mt, int from, int to, MDrawControl *control,
2120 MDrawMetric *overall_ink_return,
2121 MDrawMetric *overall_logical_return,
2122 MDrawMetric *overall_line_return)
2124 MGlyphString *gstring;
2126 int width, rbearing;
2128 ASSURE_CONTROL (control);
2129 M_CHECK_POS_X (mt, from, -1);
2130 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2131 to = mtext_nchars (mt) + (control->cursor_width != 0);
2135 gstring = get_gstring (frame, mt, from, to, control);
2137 MERROR (MERROR_DRAW, -1);
2138 width = gstring_width (gstring, from, to, &rbearing);
2139 if (overall_ink_return)
2141 overall_ink_return->y = - gstring->physical_ascent;
2142 overall_ink_return->x = gstring->lbearing;
2144 if (overall_logical_return)
2146 overall_logical_return->y = - gstring->ascent;
2147 overall_logical_return->x = 0;
2149 if (overall_line_return)
2151 overall_line_return->y = - gstring->line_ascent;
2152 overall_line_return->x = gstring->lbearing;
2155 for (from = gstring->to; from < to; from = gstring->to)
2157 int this_width, this_rbearing;
2159 y += gstring->line_descent;
2160 M17N_OBJECT_UNREF (gstring->top);
2161 gstring = get_gstring (frame, mt, from, to, control);
2162 this_width = gstring_width (gstring, from, to, &this_rbearing);
2163 y += gstring->line_ascent;
2164 if (width < this_width)
2166 if (rbearing < this_rbearing)
2167 rbearing = this_rbearing;
2169 if (overall_ink_return)
2171 overall_ink_return->width = rbearing;
2172 overall_ink_return->height
2173 = y + gstring->physical_descent - overall_ink_return->y;
2175 if (overall_logical_return)
2177 overall_logical_return->width = width;
2178 overall_logical_return->height
2179 = y + gstring->descent - overall_logical_return->y;
2181 if (overall_line_return)
2183 overall_line_return->width = MAX (width, rbearing);
2184 overall_line_return->height
2185 = y + gstring->line_descent - overall_line_return->y;
2188 M17N_OBJECT_UNREF (gstring->top);
2195 @brief Compute the text dimensions of each character of M-text.
2197 The mdraw_text_per_char_extents () function computes the drawn
2198 metric of each character between $FROM and $TO of M-text $MT
2199 assuming that they are drawn on a window of frame $FRAME using the
2200 mdraw_text_with_control () function with the drawing control
2203 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2204 $LOGICAL_ARRAY_RETURN. Each successive element of
2205 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2206 ink and logical metrics of successive characters respectively,
2207 relative to the drawing origin of the M-text. The number of
2208 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2209 been set is returned to $NUM_CHARS_RETURN.
2211 If $ARRAY_SIZE is too small to return all metrics, the function
2212 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2213 Otherwise, it returns zero.
2215 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2216 @c NULL, this function also computes the metrics of the overall
2217 text and stores the results in the members of the structure
2218 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2220 If $CONTROL->two_dimensional is nonzero, this function computes
2221 only the metrics of characters in the first line. */
2223 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2225 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2226 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2227 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2228 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2230 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2231 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2232 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2233 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2234 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2236 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2237 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2240 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2241 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2242 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2245 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2246 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2249 mdraw_text_per_char_extents (MFrame *frame,
2250 MText *mt, int from, int to,
2251 MDrawControl *control,
2252 MDrawMetric *ink_array_return,
2253 MDrawMetric *logical_array_return,
2255 int *num_chars_return,
2256 MDrawMetric *overall_ink_return,
2257 MDrawMetric *overall_logical_return)
2259 MGlyphString *gstring;
2263 ASSURE_CONTROL (control);
2264 *num_chars_return = to - from;
2265 if (array_size < *num_chars_return)
2266 MERROR (MERROR_DRAW, -1);
2267 if (overall_logical_return)
2268 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2269 if (overall_ink_return)
2270 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2272 M_CHECK_RANGE (mt, from, to, -1, 0);
2273 gstring = get_gstring (frame, mt, from, to, control);
2276 *num_chars_return = 0;
2280 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2281 if (g->pos >= from && g->pos < to)
2285 int width = g->width;
2286 int lbearing = g->lbearing;
2287 int rbearing = g->rbearing;
2288 int ascent = g->ascent;
2289 int descent = g->descent;
2290 int logical_ascent = g->rface->rfont->ascent;
2291 int logical_descent = g->rface->rfont->descent;
2293 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2295 if (lbearing < width + g->lbearing)
2296 lbearing = width + g->lbearing;
2297 if (rbearing < width + g->rbearing)
2298 rbearing = width + g->rbearing;
2300 if (ascent < g->ascent)
2302 if (descent < g->descent)
2303 descent = g->descent;
2310 ink_array_return[start - from].x = x + lbearing;
2311 ink_array_return[start - from].y = - ascent;
2312 ink_array_return[start - from].width = rbearing - lbearing;
2313 ink_array_return[start - from].height = ascent + descent;
2314 logical_array_return[start - from].x = x;
2315 logical_array_return[start - from].y = - logical_descent;
2316 logical_array_return[start - from].height
2317 = logical_ascent + logical_descent;
2318 logical_array_return[start - from].width = width;
2324 if (overall_ink_return)
2326 overall_ink_return->y = - gstring->line_ascent;
2327 overall_ink_return->x = gstring->lbearing;
2328 overall_ink_return->width = x - gstring->lbearing;
2329 overall_ink_return->height = gstring->height;
2331 if (overall_logical_return)
2333 overall_logical_return->y = - gstring->ascent;
2334 overall_logical_return->x = 0;
2335 overall_logical_return->width = x;
2336 overall_logical_return->height = gstring->ascent + gstring->descent;
2339 M17N_OBJECT_UNREF (gstring->top);
2346 @brief Return the character position nearest to the coordinates.
2348 The mdraw_coordinates_position () function checks which character
2349 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2350 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2351 mdraw_text_with_control () function with the drawing control
2352 object $CONTROL. Here, the character position means the number of
2353 characters that precede the character in question in $MT, that is,
2354 the character position of the first character is 0.
2356 $FRAME is used only to get the default face information.
2359 If the glyph image of a character covers coordinate ($X, $Y),
2360 mdraw_coordinates_position () returns the character position of
2362 If $Y is less than the minimum Y-coordinate of the drawn area, it
2363 returns $FROM.\n\n\n
2364 If $Y is greater than the maximum Y-coordinate of the drawn area,
2365 it returns $TO.\n\n\n
2366 If $Y fits in with the drawn area but $X is less than the minimum
2367 X-coordinate, it returns the character position of the first
2368 character drawn on the line $Y.\n\n\n
2369 If $Y fits in with the drawn area but $X is greater than the
2370 maximum X-coordinate, it returns the character position of the
2371 last character drawn on the line $Y. */
2374 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2376 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2377 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2378 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2379 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2380 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2381 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2383 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2386 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2387 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2389 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2393 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2394 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2396 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2397 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2400 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2401 int x_offset, int y_offset, MDrawControl *control)
2403 MGlyphString *gstring;
2408 M_CHECK_POS_X (mt, from, -1);
2409 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2410 to = mtext_nchars (mt) + (control->cursor_width != 0);
2416 ASSURE_CONTROL (control);
2417 gstring = get_gstring (frame, mt, from, to, control);
2418 while (y + gstring->line_descent <= y_offset
2419 && gstring->to < to)
2422 y += gstring->line_descent;
2423 M17N_OBJECT_UNREF (gstring->top);
2424 gstring = get_gstring (frame, mt, from, to, control);
2425 y += gstring->line_ascent;
2428 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2429 if (! control->orientation_reversed)
2431 width = gstring->indent;
2432 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2433 if (g->pos >= from && g->pos < to)
2436 if (width > x_offset)
2442 width = - gstring->indent;
2443 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2444 if (g->pos >= from && g->pos < to)
2447 if (width < x_offset)
2452 M17N_OBJECT_UNREF (gstring->top);
2460 @brief Compute information about a glyph.
2462 The mdraw_glyph_info () function computes information about a
2463 glyph that covers a character at position $POS of the M-text $MT
2464 assuming that the text is drawn from the character at $FROM of $MT
2465 on a window of frame $FRAME using the mdraw_text_with_control ()
2466 function with the drawing control object $CONTROL.
2468 The information is stored in the members of $INFO. */
2470 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2472 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2473 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2474 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2475 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2477 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2485 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2486 MDrawControl *control, MDrawGlyphInfo *info)
2488 MGlyphString *gstring;
2492 M_CHECK_RANGE_X (mt, from, pos, -1);
2494 ASSURE_CONTROL (control);
2495 gstring = get_gstring (frame, mt, from, pos + 1, control);
2497 MERROR (MERROR_DRAW, -1);
2498 while (gstring->to <= pos)
2500 y += gstring->line_descent;
2501 M17N_OBJECT_UNREF (gstring->top);
2502 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2503 y += gstring->line_ascent;
2505 info->line_from = gstring->from;
2506 if (info->line_from < from)
2507 info->line_from = from;
2508 info->line_to = gstring->to;
2511 if (! control->orientation_reversed)
2513 info->x = gstring->indent;
2514 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2515 info->x += g->width;
2519 info->x = - gstring->indent;
2520 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2521 info->x -= g->width;
2522 while (g[-1].to == g->to)
2525 info->from = g->pos;
2527 info->glyph_code = g->code;
2528 info->this.x = g->lbearing;
2529 info->this.y = - gstring->line_ascent;
2530 info->this.height = gstring->height;
2531 info->this.width = - g->lbearing + g->width;
2532 if (g->rface->rfont)
2533 info->font = &g->rface->rfont->font;
2536 /* info->logical_width is calculated later. */
2538 if (info->from > info->line_from)
2540 /* The logically previous glyph is on this line. */
2541 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2543 info->prev_from = g_tmp->pos;
2545 else if (info->line_from > 0)
2547 /* The logically previous glyph is on the previous line. */
2548 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2549 gstring->from, control);
2550 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2552 info->prev_from = g_tmp->pos;
2553 M17N_OBJECT_UNREF (gst->top);
2556 info->prev_from = -1;
2558 if (GLYPH_INDEX (g) > 1)
2559 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2560 else if (! control->orientation_reversed)
2562 if (info->line_from > 0)
2566 int p = gstring->from - 1;
2568 gst = get_gstring (frame, mt, p, gstring->from, control);
2569 g_tmp = gst->glyphs + (gst->used - 2);
2570 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2571 M17N_OBJECT_UNREF (gst->top);
2574 info->left_from = info->left_to = -1;
2578 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2582 int p = gstring->to;
2584 gst = get_gstring (frame, mt, p, p + 1, control);
2585 g_tmp = gst->glyphs + (gst->used - 2);
2586 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2587 M17N_OBJECT_UNREF (gst->top);
2590 info->left_from = info->left_to = -1;
2593 if (info->to < gstring->to)
2595 /* The logically next glyph is on this line. */
2596 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2598 info->next_to = g_tmp->to;
2600 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2602 /* The logically next glyph is on the next line. */
2604 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2605 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2607 info->next_to = g_tmp->to;
2608 M17N_OBJECT_UNREF (gst->top);
2613 for (info->logical_width = (g++)->width;
2614 g->pos == pos && g->type != GLYPH_ANCHOR;
2615 info->this.width += g->width, info->logical_width += (g++)->width);
2616 info->this.width += g[-1].rbearing - g[-1].width;
2618 if (g->type != GLYPH_ANCHOR)
2619 info->right_from = g->pos, info->right_to = g->to;
2620 else if (! control->orientation_reversed)
2622 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2625 M17N_OBJECT_UNREF (gstring->top);
2626 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2628 info->right_from = g->pos, info->right_to = g->to;
2631 info->right_from = info->right_to = -1;
2635 if (info->line_from > 0)
2637 pos = gstring->from - 1;
2638 M17N_OBJECT_UNREF (gstring->top);
2639 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2641 info->right_from = g->pos, info->right_to = g->to;
2644 info->right_from = info->right_to = -1;
2647 M17N_OBJECT_UNREF (gstring->top);
2654 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2655 MDrawControl *control, MDrawGlyphInfo *info,
2656 int array_size, int *num_glyphs_return)
2658 MGlyphString *gstring;
2663 ASSURE_CONTROL (control);
2664 *num_glyphs_return = 0;
2665 M_CHECK_RANGE (mt, from, to, -1, 0);
2666 gstring = get_gstring (frame, mt, from, to, control);
2669 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2671 if (g->type == GLYPH_BOX
2672 || g->pos < from || g->pos >= to)
2674 if (g->type == GLYPH_PAD)
2676 if (g->left_padding)
2677 pad_width = g->width;
2681 info[-1].x += g->width;
2682 info[-1].logical_width += g->width;
2688 info->from = g->pos;
2690 info->glyph_code = g->code;
2691 info->x = g->xoff + pad_width;
2693 info->this.x = g->lbearing;
2694 info->this.y = - g->ascent;
2695 info->this.height = g->ascent + g->descent;
2696 info->this.width = g->rbearing - g->lbearing;
2697 info->logical_width = g->width + pad_width;
2698 if (g->rface->rfont)
2699 info->font = &g->rface->rfont->font;
2707 M17N_OBJECT_UNREF (gstring->top);
2709 *num_glyphs_return = n;
2710 return (n <= array_size ? 0 : -1);
2716 @brief Draw one or more textitems.
2718 The mdraw_text_items () function draws one or more M-texts on
2719 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2720 of the textitems to be drawn and $NITEMS is the number of
2721 textimtems in the array. */
2724 @brief textitem ¤òɽ¼¨¤¹¤ë.
2726 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2727 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2728 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2731 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2735 MTextItem, mdraw_text (). */
2738 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2739 MDrawTextItem *items, int nitems)
2741 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2743 while (nitems-- > 0)
2746 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2748 mdraw_text_with_control (frame, win, x, y,
2749 items->mt, 0, mtext_nchars (items->mt),
2751 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2752 items->control, NULL, NULL, NULL);
2755 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2761 @brief calculate a line breaking position.
2763 The function mdraw_default_line_break () calculates a line
2764 breaking position based on the line number $LINE and the
2765 coordinate $Y, when a line is too long to fit within the width
2766 limit. $POS is the position of the character next to the last
2767 one that fits within the limit. $FROM is the position of the
2768 first character of the line, and TO is the position of the last
2769 character displayed on the line if there were not width limit.
2770 LINE and Y are reset to 0 when a line is broken by a newline
2771 character, and incremented each time when a long line is broken
2772 because of the width limit.
2775 This function returns a character position to break the
2780 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2782 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2783 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2784 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2785 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2786 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2787 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2788 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2791 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2795 mdraw_default_line_break (MText *mt, int pos,
2796 int from, int to, int line, int y)
2798 int c = mtext_ref_char (mt, pos);
2801 if (c == ' ' || c == '\t')
2805 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2812 if (c == ' ' || c == '\t')
2815 c = mtext_ref_char (mt, pos);
2828 @brief Obtain per character dimension information.
2830 The mdraw_per_char_extents () function computes the text dimension
2831 of each character in M-text $MT. The faces given as text
2832 properties in $MT and the default face of frame $FRAME determine
2833 the fonts to draw the text. Each successive element in
2834 $ARRAY_RETURN is set to the drawn metrics of successive
2835 characters, which is relative to the origin of the drawing, and a
2836 rectangle for each character in $MT. The number of elements of
2837 $ARRAY_RETURN must be equal to or greater than the number of
2840 If pointer $OVERALL_RETURN is not @c NULL, this function also
2841 computes the extents of the overall text and stores the results in
2842 the members of the structure pointed to by $OVERALL_RETURN. */
2845 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2847 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2848 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2849 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2850 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2851 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2852 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2855 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2856 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2859 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2862 mdraw_per_char_extents (MFrame *frame, MText *mt,
2863 MDrawMetric *array_return,
2864 MDrawMetric *overall_return)
2866 int n = mtext_nchars (mt);
2868 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2869 n, &n, overall_return, NULL);
2873 @brief clear cached information.
2875 The mdraw_clear_cache () function clear cached information
2876 on M-text $MT that was attached by any of the drawing functions.
2877 When the behaviour of `format' or `line_break'
2878 member functions of MDrawControl is changed, the cache must be cleared.
2883 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2885 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2886 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2887 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2888 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2893 mdraw_clear_cache (MText *mt)
2895 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);