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
530 && base->bidi_level == g->bidi_level)
532 mfont__ft_drive_gpos (gstring, GLYPH_INDEX (base), GLYPH_INDEX (g));
541 MRealizedFont *rfont = base->rface->rfont;
542 int size = rfont->font.property[MFONT_SIZE];
543 int width, lbearing, rbearing;
545 if (g == last_g || ! g->combining_code)
548 if (base->left_padding && base->lbearing < 0)
550 base->xoff = - base->lbearing;
551 base->width += base->xoff;
552 base->rbearing += base->xoff;
555 if (base->right_padding && base->rbearing > base->width)
557 base->width = base->rbearing;
559 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
560 rbearing = base->rbearing;
564 /* With combining glyphs. */
565 int left = -base->width;
567 int top = - base->ascent;
568 int bottom = base->descent;
569 int height = bottom - top;
570 int begin = base->pos;
575 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
576 rbearing = base->rbearing;
578 while (g != last_g && g->combining_code)
580 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
582 combining_code = g->combining_code;
583 if (COMBINING_BY_CLASS_P (combining_code))
584 g->combining_code = combining_code
585 = combining_code_from_class (COMBINING_CODE_CLASS
588 rfont = g->rface->rfont;
589 size = rfont->font.property[MFONT_SIZE];
590 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
592 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
594 base_x = COMBINING_CODE_BASE_X (combining_code);
595 base_y = COMBINING_CODE_BASE_Y (combining_code);
596 add_x = COMBINING_CODE_ADD_X (combining_code);
597 add_y = COMBINING_CODE_ADD_Y (combining_code);
601 else if (end < g->to)
604 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
607 if (g->xoff + g->width > right)
608 right = g->xoff + g->width;
609 width = right - left;
610 if (g->xoff + g->lbearing < left + lbearing)
611 lbearing = g->xoff + g->lbearing - left;
612 if (g->xoff + g->rbearing > left + rbearing)
613 rbearing = g->xoff + g->rbearing - left;
616 g->yoff = top + height * base_y / 2;
620 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
622 if (g->yoff - g->ascent < top)
623 top = g->yoff - g->ascent;
624 if (g->yoff + g->descent > bottom)
625 bottom = g->yoff + g->descent;
626 height = bottom - top;
632 base->ascent = - top;
633 base->descent = bottom;
634 base->lbearing = lbearing;
635 base->rbearing = rbearing;
636 if (left < - base->width)
638 base->xoff = - base->width - left;
639 base->width += base->xoff;
640 base->rbearing += base->xoff;
641 base->lbearing += base->xoff;
645 base->width += right;
646 base->rbearing += right;
647 base->right_padding = 1;
648 for (i = 1; base + i != g; i++)
649 base[i].xoff -= right;
652 for (i = 0; base + i != g; i++)
659 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
660 g_physical_descent = MAX (g_physical_descent, base->descent);
661 g_lbearing = MIN (g_lbearing, g_width + lbearing);
662 g_rbearing = MAX (g_rbearing, g_width + rbearing);
663 g_width += base->width;
666 gstring->physical_ascent = g_physical_ascent;
667 gstring->physical_descent = g_physical_descent;
668 gstring->sub_width = g_width;
669 gstring->sub_lbearing = g_lbearing;
670 gstring->sub_rbearing = g_rbearing;
674 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
675 by this function directly. Character glyphs are handled by
676 layouter functions registered in font drivers.
678 This function fill-in all the remaining members of glyphs. */
681 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
683 /* Default width of TAB. */
684 int tab_width = frame->space_width * (gstring->control.tab_width
685 ? gstring->control.tab_width : 8);
689 MDrawControl *control = &(gstring->control);
692 int box_line_height = 0;
693 int ignore_formatting_char = control->ignore_formatting_char;
695 gstring->ascent = gstring->descent = 0;
696 gstring->physical_ascent = gstring->physical_descent = 0;
697 gstring->width = gstring->lbearing = gstring->rbearing = 0;
701 while (g->type != GLYPH_ANCHOR)
703 if (box != g->rface->box)
705 int gidx = GLYPH_INDEX (g);
709 /* Insert the right side of the box. That glyph belongs
710 to the previous grapheme cluster. */
711 MGlyph box_glyph = g[-1];
713 box_glyph.type = GLYPH_BOX;
715 = (control->fixed_width
717 : box->inner_hmargin + box->width + box->outer_hmargin);
718 box_glyph.lbearing = 0;
719 box_glyph.rbearing = box_glyph.width;
721 box_glyph.right_padding = 1;
722 gstring->width += box_glyph.width;
723 gstring->rbearing += box_glyph.width;
724 INSERT_GLYPH (gstring, gidx, box_glyph);
731 /* Insert the left side of the box. That glyph belongs
732 to the following grapheme cluster. */
733 MGlyph box_glyph = *g;
734 int box_height = (box->width
735 + box->inner_vmargin + box->outer_vmargin);
737 if (box_line_height < box_height)
738 box_line_height = box_height;
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.left_padding = 1;
748 gstring->width += box_glyph.width;
749 gstring->rbearing += box_glyph.width;
750 INSERT_GLYPH (gstring, gidx, box_glyph);
756 if (g->category == McatCf && ignore_formatting_char)
757 g->type = GLYPH_SPACE;
759 if (g->type == GLYPH_CHAR)
761 MRealizedFace *rface = g->rface;
762 MRealizedFont *rfont = rface->rfont;
764 int from = GLYPH_INDEX (g);
766 for (g++; g->type == GLYPH_CHAR; g++)
767 if (! rfont != ! g->rface->rfont
768 || box != g->rface->box
769 || ((fromg->code == MCHAR_INVALID_CODE)
770 != (g->code == MCHAR_INVALID_CODE))
771 || (g->category == McatCf && ignore_formatting_char))
773 if (rfont && fromg->code != MCHAR_INVALID_CODE)
776 int to = GLYPH_INDEX (g);
778 layout_glyphs (frame, gstring, from, to);
779 extra_width = - gstring->sub_lbearing;
781 && (GLYPH_INDEX (g) > 1
782 || control->align_head))
786 pad.type = GLYPH_PAD;
789 pad.width = pad.rbearing = extra_width;
790 pad.left_padding = 1;
791 INSERT_GLYPH (gstring, from, pad);
793 gstring->sub_lbearing = 0;
794 gstring->sub_width += extra_width;
795 gstring->sub_rbearing += extra_width;
797 g = MGLYPH (from - 1);
798 if (g->type == GLYPH_SPACE)
800 /* The pad just inserted is absorbed (maybe
801 partially) by the previous space while
802 keeping at least some space width. For the
803 moment, we use the arbitrary width 2-pixel.
804 Perhaps, it should be decided by the current
805 face, or a default value of the current
806 frame, which is, however, not yet
808 if (extra_width + 2 < g->width)
810 g->width -= extra_width;
814 extra_width -= g->width - 2;
817 gstring->width -= extra_width;
818 gstring->rbearing -= extra_width;
822 extra_width = gstring->sub_rbearing - gstring->sub_width;
826 if (g->type == GLYPH_SPACE && box == g->rface->box)
830 pad.type = GLYPH_PAD;
833 pad.width = pad.rbearing = extra_width;
835 INSERT_GLYPH (gstring, to, pad);
839 g[-1].width += extra_width;
840 gstring->sub_width += extra_width;
843 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
844 gstring->lbearing = gstring->width + gstring->sub_lbearing;
845 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
846 gstring->rbearing = gstring->width + gstring->sub_rbearing;
847 gstring->width += gstring->sub_width;
848 if (gstring->ascent < rface->ascent)
849 gstring->ascent = rface->ascent;
850 if (gstring->descent < rface->descent)
851 gstring->descent = rface->descent;
856 for (; fromg < g; fromg++)
858 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
859 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
860 fromg->width = fromg->rbearing = 1;
862 fromg->width = fromg->rbearing = rface->space_width;
863 fromg->xoff = fromg->lbearing = 0;
864 fromg->ascent = fromg->descent = 0;
865 gstring->width += fromg->width;
866 gstring->rbearing += fromg->width;
868 if (gstring->ascent < frame->rface->ascent)
869 gstring->ascent = frame->rface->ascent;
870 if (gstring->descent < frame->descent)
871 gstring->descent = frame->rface->descent;
874 else if (g->type == GLYPH_SPACE)
877 g->width = g->rface->space_width;
878 else if (g->c == '\n')
880 g->width = control->cursor_width;
883 if (control->cursor_bidi)
885 else if (g->width < 0)
886 g->width = g->rface->space_width;
889 else if (g->c == '\t')
891 g->width = tab_width - ((gstring->indent + gstring->width)
897 if (g[-1].type == GLYPH_PAD)
899 /* This space glyph absorbs (maybe partially) the
900 previous padding glyph. */
901 g->width -= g[-1].width;
903 /* But, keep at least some space width. For the
904 moment, we use the arbitrary width 2-pixel. */
907 g->rbearing = g->width;
908 gstring->width += g->width;
909 gstring->rbearing += g->width;
912 if (gstring->ascent < g->rface->ascent)
913 gstring->ascent = g->rface->ascent;
914 if (gstring->descent < g->rface->descent)
915 gstring->descent = g->rface->descent;
921 gstring->width += g->width;
922 gstring->rbearing += g->width;
929 /* Insert the right side of the box. */
930 int gidx = GLYPH_INDEX (g);
931 MGlyph box_glyph = g[-1];
933 box_glyph.type = GLYPH_BOX;
935 = (control->fixed_width
937 : box->inner_hmargin + box->width + box->outer_hmargin);
938 box_glyph.lbearing = 0;
939 box_glyph.rbearing = box_glyph.width;
941 box_glyph.right_padding = 1;
942 gstring->width += box_glyph.width;
943 gstring->rbearing += box_glyph.width;
944 INSERT_GLYPH (gstring, gidx, box_glyph);
947 gstring->text_ascent = gstring->ascent;
948 gstring->text_descent = gstring->descent;
949 if (gstring->text_ascent < gstring->physical_ascent)
950 gstring->text_ascent = gstring->physical_ascent;
951 if (gstring->text_descent < gstring->physical_descent)
952 gstring->text_descent = gstring->physical_descent;
953 gstring->line_ascent = gstring->text_ascent;
954 gstring->line_descent = gstring->text_descent;
955 if (box_line_height > 0)
957 gstring->line_ascent += box_line_height;
958 gstring->physical_ascent = gstring->line_ascent;
959 gstring->line_descent += box_line_height;
960 gstring->physical_descent = gstring->line_descent;
963 if (gstring->line_ascent < control->min_line_ascent)
964 gstring->line_ascent = control->min_line_ascent;
965 else if (control->max_line_ascent
966 && control->max_line_ascent > control->min_line_ascent
967 && gstring->line_ascent > control->max_line_ascent)
968 gstring->line_ascent = control->max_line_ascent;
970 if (gstring->line_descent < control->min_line_descent)
971 gstring->line_descent = control->min_line_descent;
972 else if (control->max_line_descent
973 && control->max_line_descent > control->min_line_descent
974 && gstring->line_descent > control->max_line_descent)
975 gstring->line_descent = control->max_line_descent;
976 gstring->height = gstring->line_ascent + gstring->line_descent;
978 if (control->orientation_reversed
981 /* We must adjust TAB width for RTL orientation. */
982 width = gstring->indent;
984 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
986 if (g->type == GLYPH_CHAR && g->c == '\t')
988 int this_width = tab_width - (width % tab_width);
990 if (g[1].type == GLYPH_PAD)
991 this_width -= g[1].width;
992 if (g[-1].type == GLYPH_PAD)
993 this_width -= g[-1].width;
996 gstring->width += this_width - g->width;
997 gstring->rbearing += this_width - g->width;
998 g->width = this_width;
1009 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1010 MGlyphString *gstring, int from, int to,
1011 int *from_idx, int *to_idx, int *to_x)
1013 MGlyph *g = MGLYPH (1);
1014 MDrawRegion region = (MDrawRegion) NULL;
1015 MDrawControl *control = &gstring->control;
1016 int cursor_pos = -1;
1018 int cursor_bidi = control->cursor_bidi;
1020 if (control->with_cursor && control->cursor_width)
1022 if (gstring->from <= control->cursor_pos
1023 && gstring->to > control->cursor_pos)
1024 cursor_pos = control->cursor_pos;
1026 && gstring->from <= control->cursor_pos - 1
1027 && gstring->to > control->cursor_pos - 1)
1028 prev_pos = control->cursor_pos - 1;
1031 *from_idx = *to_idx = 0;
1032 while (g->type != GLYPH_ANCHOR)
1034 if (g->pos >= from && g->pos < to)
1036 MGlyph *fromg = g, *cursor = NULL;
1037 MRealizedFace *rface = g->rface;
1039 int cursor_width = 0;
1043 *from_idx = GLYPH_INDEX (g);
1044 while (g->pos >= from && g->pos < to
1045 && g->rface == rface)
1048 if (g->type != GLYPH_BOX
1049 && g->pos <= cursor_pos && g->to > cursor_pos)
1052 cursor = g, cursor_x = x + width;
1053 cursor_width += g->width;
1055 width += g++->width;
1058 && (control->as_image
1059 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1061 int this_x = x, this_width = width;
1063 if (fromg->type == GLYPH_BOX)
1064 this_x += fromg->width, this_width -= fromg->width;
1065 if (g[-1].type == GLYPH_BOX)
1066 this_width -= g[-1].width;
1067 (frame->driver->fill_space)
1068 (frame, win, rface, 0,
1069 this_x, y - gstring->text_ascent, this_width,
1070 gstring->text_ascent + gstring->text_descent,
1071 control->clip_region);
1078 rect.y = y - gstring->text_ascent;
1079 rect.height = gstring->text_ascent + gstring->text_descent;
1082 rect.width = ((control->cursor_width > 0
1083 && control->cursor_width < cursor_width)
1084 ? control->cursor_width : cursor_width);
1088 if (cursor->bidi_level % 2)
1089 rect.x += cursor_width - 1;
1092 (*frame->driver->fill_space)
1093 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1094 control->clip_region);
1096 region = (*frame->driver->region_from_rect) (&rect);
1098 (*frame->driver->region_add_rect) (region, &rect);
1101 if (cursor->bidi_level % 2)
1104 rect.width = cursor_width < 4 ? cursor_width : 4;
1105 (*frame->driver->fill_space)
1106 (frame, win, rface, 1,
1107 rect.x, rect.y, rect.width, rect.height,
1108 control->clip_region);
1109 (*frame->driver->region_add_rect) (region, &rect);
1121 if (fromg->type != GLYPH_BOX
1122 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1125 cursor = fromg, cursor_x = x + temp_width;
1126 cursor_width += fromg->width;
1128 temp_width += fromg++->width;
1135 if (! (cursor->bidi_level % 2))
1136 rect.x += cursor_width - 1;
1137 rect.y = y - gstring->text_ascent;
1138 rect.height = gstring->text_ascent + gstring->text_descent;
1140 (*frame->driver->fill_space)
1141 (frame, win, rface, 1,
1142 rect.x, rect.y, rect.width, rect.height,
1143 control->clip_region);
1145 region = (*frame->driver->region_from_rect) (&rect);
1147 (*frame->driver->region_add_rect) (region, &rect);
1148 rect.y += rect.height - 2;
1150 rect.width = cursor_width < 4 ? cursor_width : 4;
1151 if (! (cursor->bidi_level % 2))
1152 rect.x -= rect.width - 1;
1153 (*frame->driver->fill_space) (frame, win, rface, 1,
1154 rect.x, rect.y, rect.width, rect.height,
1155 control->clip_region);
1156 (*frame->driver->region_add_rect) (region, &rect);
1160 *to_idx = GLYPH_INDEX (g);
1170 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1171 MGlyphString *gstring, int from_idx, int to_idx,
1172 int reverse, MDrawRegion region)
1174 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1180 (*frame->driver->region_to_rect) (region, &rect);
1183 while (g != gend && x + g->rbearing <= rect.x)
1186 width -= g++->width;
1187 while (! g->enabled && g != gend)
1191 rect.x += rect.width;
1192 if (rect.x < x + width)
1195 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1197 width -= (--gend)->width;
1198 while (! gend->enabled && g != gend)
1202 while (gend[-1].to == gend->to) gend++;
1210 MRealizedFace *rface = g->rface;
1211 int width = g->width;
1212 MGlyph *from_g = g++;
1214 /* Handle the glyphs of the same type/face at once. */
1216 && g->type == from_g->type
1217 && g->rface == rface
1218 && ((g->code == MCHAR_INVALID_CODE)
1219 == (from_g->code == MCHAR_INVALID_CODE))
1221 width += g++->width;
1223 if (from_g->type == GLYPH_CHAR)
1225 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1226 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1229 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1232 else if (from_g->type == GLYPH_BOX)
1234 /* Draw the left or right side of a box. If
1235 from_g->lbearing is nonzero, this is the left side,
1236 else this is the right side. */
1237 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1240 if (from_g->type != GLYPH_BOX)
1243 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1244 x, y, width, region);
1247 /* Draw the top and bottom side of a box. */
1248 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1249 x, y, width, region);
1260 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1261 int *from_x, int *to_x)
1264 int left_idx = *left, right_idx = *right;
1265 int left_x, right_x, x;
1267 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1270 if (x + g->rbearing > 0)
1272 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1274 left_idx = GLYPH_INDEX (g);
1279 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1282 if (x - g->width + g->lbearing < 0)
1284 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1286 right_idx = GLYPH_INDEX (g) + 1;
1291 if (*left == left_idx && *right == right_idx)
1294 if (*left != left_idx)
1296 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1301 if (*right != right_idx)
1303 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1313 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1318 if (from <= gstring->from && to >= gstring->to)
1321 *rbearing = gstring->rbearing;
1322 return gstring->width;
1327 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1328 if (g->pos >= from && g->pos < to)
1330 if (rbearing && width + g->rbearing > *rbearing)
1331 *rbearing = width + g->rbearing;
1339 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1340 MGlyphString *gstring, int from, int to)
1342 MDrawControl *control = &gstring->control;
1344 MDrawRegion clip_region, cursor_region;
1345 int from_idx, to_idx;
1348 if (control->orientation_reversed)
1349 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1351 x += gstring->indent;
1353 /* At first, draw all glyphs without cursor. */
1354 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1355 &from_idx, &to_idx, &to_x);
1357 if (control->partial_update)
1360 rect.width = to_x - x;
1361 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1363 rect.y = y - gstring->line_ascent;
1364 rect.height = gstring->height;
1365 clip_region = (*frame->driver->region_from_rect) (&rect);
1366 if (control->clip_region)
1367 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1370 clip_region = control->clip_region;
1373 clip_region = control->clip_region;
1375 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1380 (*frame->driver->intersect_region) (cursor_region, clip_region);
1381 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1384 if (clip_region != control->clip_region)
1385 (*frame->driver->free_region) (clip_region);
1387 (*frame->driver->free_region) (cursor_region);
1391 static int gstring_num;
1394 free_gstring (void *object)
1396 MGlyphString *gstring = (MGlyphString *) object;
1399 free_gstring (gstring->next);
1400 if (gstring->size > 0)
1401 free (gstring->glyphs);
1407 static MGlyphString scratch_gstring;
1409 static MGlyphString *
1410 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1413 MGlyphString *gstring;
1415 if (pos == mt->nchars)
1417 gstring = &scratch_gstring;
1421 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1422 MLIST_INIT1 (gstring, glyphs, 128);
1426 gstring->frame = frame;
1427 gstring->tick = frame->tick;
1428 gstring->top = gstring;
1430 gstring->control = *control;
1431 gstring->indent = gstring->width_limit = 0;
1432 if (control->format)
1433 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1435 gstring->width_limit = control->max_line_width;
1436 gstring->anti_alias = control->anti_alias;
1440 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1443 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1451 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1452 a width of glyphs for the character at I of GSTRING->mt. If I is
1453 not a beginning of a grapheme cluster, the corresponding element
1455 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1456 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1457 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1458 pos_width[g->pos - gstring->from] += g->width;
1459 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1461 if (pos_width[i] > 0)
1463 if (width + pos_width[i] > gstring->width_limit)
1466 width += pos_width[i];
1469 pos = gstring->from + i;
1470 if (gstring->control.line_break)
1472 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1473 gstring->from, gstring->to, 0, 0);
1474 if (pos <= gstring->from || pos >= gstring->to)
1477 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1478 layout_glyph_string (frame, gstring);
1482 /* Return a gstring that covers a character at POS. */
1484 static MGlyphString *
1485 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1487 MGlyphString *gstring = NULL;
1489 if (pos < mtext_nchars (mt))
1491 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1494 && ((prop->start != 0
1495 && mtext_ref_char (mt, prop->start - 1) != '\n')
1496 || (prop->end < mtext_nchars (mt)
1497 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1499 mtext_detach_property (prop);
1504 gstring = prop->val;
1505 if (gstring->frame != frame
1506 || gstring->tick != frame->tick
1507 || memcmp (control, &gstring->control,
1508 (char *) (&control->with_cursor)
1509 - (char *) (control)))
1511 mtext_detach_property (prop);
1516 else if (! control->cursor_width)
1524 offset = mtext_character (mt, pos, 0, '\n');
1529 offset -= gstring->from;
1531 for (gst = gstring; gst; gst = gst->next)
1535 gst->from += offset;
1537 for (i = 0; i < gst->used; i++)
1539 gst->glyphs[i].pos += offset;
1540 gst->glyphs[i].to += offset;
1543 M17N_OBJECT_REF (gstring);
1548 int line = 0, y = 0;
1550 if (control->two_dimensional)
1552 beg = mtext_character (mt, pos, 0, '\n');
1557 end = mtext_nchars (mt) + (control->cursor_width != 0);
1564 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1565 compose_glyph_string (frame, mt, beg, end, gstring);
1566 layout_glyph_string (frame, gstring);
1568 if (control->two_dimensional
1569 && gstring->width_limit
1570 && gstring->width > gstring->width_limit)
1572 MGlyphString *gst = gstring;
1574 truncate_gstring (frame, mt, gst);
1575 while (gst->to < end)
1577 line++, y += gst->height;
1578 gst->next = alloc_gstring (frame, mt, gst->from, control,
1580 gst->next->top = gstring;
1581 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1583 layout_glyph_string (frame, gst);
1584 if (gst->width <= gst->width_limit)
1586 truncate_gstring (frame, mt, gst);
1590 if (! control->disable_caching && pos < mtext_nchars (mt))
1592 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1593 MTEXTPROP_VOLATILE_STRONG);
1595 if (end > mtext_nchars (mt))
1596 end = mtext_nchars (mt);
1597 mtext_attach_property (mt, beg, end, prop);
1598 M17N_OBJECT_UNREF (prop);
1602 while (gstring->to <= pos)
1604 if (! gstring->next)
1606 gstring = gstring->next;
1608 gstring->control = *control;
1614 static MDrawControl control_noop;
1616 #define ASSURE_CONTROL(control) \
1618 control = &control_noop; \
1623 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1624 MText *mt, int from, int to,
1625 MDrawControl *control)
1627 MGlyphString *gstring;
1629 M_CHECK_POS_X (mt, from, -1);
1630 ASSURE_CONTROL (control);
1631 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1632 to = mtext_nchars (mt) + (control->cursor_width != 0);
1636 gstring = get_gstring (frame, mt, from, to, control);
1638 MERROR (MERROR_DRAW, -1);
1639 render_glyph_string (frame, win, x, y, gstring, from, to);
1643 y += gstring->line_descent;
1644 M17N_OBJECT_UNREF (gstring->top);
1645 gstring = get_gstring (frame, mt, from, to, control);
1646 y += gstring->line_ascent;
1647 render_glyph_string (frame, win, x, y, gstring, from, to);
1650 M17N_OBJECT_UNREF (gstring->top);
1657 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1663 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1664 if (g->pos <= pos && g->to > pos)
1669 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1670 if (g->pos <= pos && g->to > pos)
1677 /* for debugging... */
1681 dump_combining_code (int code)
1683 char *vallign = "tcbB";
1684 char *hallign = "lcr";
1690 if (COMBINING_BY_CLASS_P (code))
1691 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1692 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1693 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1694 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1695 off_x = COMBINING_CODE_OFF_X (code) - 128;
1697 sprintf (work + 2, "+%d", off_y);
1699 sprintf (work + 2, "%d", off_y);
1700 else if (off_x == 0)
1701 sprintf (work + 2, ".");
1702 p = work + strlen (work);
1704 sprintf (p, ">%d", off_x);
1706 sprintf (p, "<%d", -off_x);
1708 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1709 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1715 dump_gstring (MGlyphString *gstring, int indent)
1717 char *prefix = (char *) alloca (indent + 1);
1718 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1720 memset (prefix, 32, indent);
1723 fprintf (stderr, "(glyph-string");
1725 for (g = MGLYPH (0); g < last_g; g++)
1727 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1729 g - gstring->glyphs,
1730 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1731 : g->type == GLYPH_ANCHOR ? "ANC"
1732 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1733 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1734 dump_combining_code (g->combining_code),
1735 g->width, g->bidi_level);
1736 fprintf (stderr, ")");
1740 /* m17n-X internal APIs */
1745 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1747 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1748 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1750 Mlatin = msymbol ("latin");
1751 Minherited = msymbol ("inherited");
1753 McatCc = msymbol ("Cc");
1754 McatCf = msymbol ("Cf");
1756 MbidiR = msymbol ("R");
1757 MbidiAL = msymbol ("AL");
1758 MbidiRLE = msymbol ("RLE");
1759 MbidiRLO = msymbol ("RLO");
1760 MbidiBN = msymbol ("BN");
1761 MbidiS = msymbol ("S");
1763 fribidi_set_mirroring (TRUE);
1772 MLIST_FREE1 (&scratch_gstring, glyphs);
1776 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1780 /*** @addtogroup m17nDraw */
1785 @brief Draw an M-text on a window.
1787 The mdraw_text () function draws the text between $FROM and $TO of
1788 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1790 The appearance of the text (size, style, color, etc) is specified
1791 by the value of the text property whose key is @c Mface. If the
1792 M-text or a part of the M-text does not have such a text property,
1793 the default face of $FRAME is used.
1795 The font used to draw a character in the M-text is selected from
1796 the value of the fontset property of a face by the following
1801 <li> Search the text properties given to the character for the one
1802 whose key is @c Mcharset; its value should be either a symbol
1803 specifying a charset or #Mnil. If the value is #Mnil,
1804 proceed to the next step.
1806 Otherwise, search the mapping table of the fontset for the
1807 charset. If no entry is found proceed to the next step.
1809 If an entry is found, use one of the fonts in the entry that
1810 has a glyph for the character and that matches best with the
1811 face properties. If no such font exists, proceed to the next
1814 <li> Get the character property "script" of the character. If it is
1815 inherited, get the script property from the previous
1816 characters. If there is no previous character, or none of
1817 them has the script property other than inherited, proceed to
1820 Search the text properties given to the character for the one
1821 whose key is @c Mlanguage; its value should be either a
1822 symbol specifying a language or @c Mnil.
1824 Search the mapping table of the fontset for the combination
1825 of the script and language. If no entry is found, proceed to
1828 If an entry is found, use one of the fonts in the entry that
1829 has a glyph for the character and that matches best with the
1830 face properties. If no such font exists, proceed to the next
1833 <li> Search the fall-back table of the fontset for a font that has
1834 a glyph of the character. If such a font is found, use that
1839 If no font is found by the algorithm above, this function draws an
1840 empty box for the character.
1842 This function draws only the glyph foreground. To specify the
1843 background color, use mdraw_image_text () or
1844 mdraw_text_with_control ().
1846 This function is the counterpart of <tt>XDrawString ()</tt>,
1847 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1848 in the X Window System.
1851 If the operation was successful, mdraw_text () returns 0. If an
1852 error is detected, it returns -1 and assigns an error code to the
1853 external variable #merror_code. */
1855 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1857 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1858 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1861 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1862 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1863 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1864 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1866 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1867 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1871 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1872 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1873 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1874 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1875 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1878 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1879 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1880 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1883 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1884 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1885 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1886 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1888 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1889 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1892 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1893 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1896 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1897 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1898 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1901 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1902 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1906 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1907 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1909 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1910 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1913 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1914 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1917 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1918 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1920 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1927 mdraw_image_text () */
1930 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1931 MText *mt, int from, int to)
1933 MDrawControl control;
1935 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1936 memset (&control, 0, sizeof control);
1937 control.as_image = 0;
1938 return draw_text (frame, win, x, y, mt, from, to, &control);
1945 @brief Draw an M-text on a window as an image.
1947 The mdraw_image_text () function draws the text between $FROM and
1948 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1949 coordinate ($X, $Y).
1951 The way to draw a text is the same as in mdraw_text () except that
1952 this function also draws the background with the color specified
1955 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1956 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1957 functions in the X Window System.
1960 If the operation was successful, mdraw_image_text () returns 0.
1961 If an error is detected, it returns -1 and assigns an error code
1962 to the external variable #merror_code. */
1965 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1967 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1968 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1971 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1972 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1974 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1975 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1979 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1980 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1983 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1993 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1994 MText *mt, int from, int to)
1996 MDrawControl control;
1998 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1999 memset (&control, 0, sizeof control);
2000 control.as_image = 1;
2001 return draw_text (frame, win, x, y, mt, from, to, &control);
2007 @brief Draw an M-text on a window with fine control.
2009 The mdraw_text_with_control () function draws the text between
2010 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2011 coordinate ($X, $Y).
2013 The way to draw a text is the same as in mdraw_text () except that
2014 this function also follows what specified in the drawing control
2017 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2018 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2019 breaks lines and the following characters are drawn in the next
2020 line. See the documentation of the structure @ MDrawControl for
2024 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2026 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2027 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2030 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2031 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2033 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2034 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2035 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2039 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2040 MText *mt, int from, int to, MDrawControl *control)
2042 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2043 return draw_text (frame, win, x, y, mt, from, to, control);
2049 @brief Compute text pixel width.
2051 The mdraw_text_extents () function computes the width of text
2052 between $FROM and $TO of M-text $MT when it is drawn on a window
2053 of frame $FRAME using the mdraw_text_with_control () function with
2054 the drawing control object $CONTROL.
2056 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2057 the bounding box of character ink of the M-text, and stores the
2058 results in the members of the structure pointed to by
2059 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2060 surrounding box, the box is included in the bounding box.
2062 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2063 computes the bounding box that provides mininum spacing to other
2064 graphical features (such as surrounding box) for the M-text, and
2065 stores the results in the members of the structure pointed to by
2066 $OVERALL_LOGICAL_RETURN.
2068 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2069 computes the bounding box that provides mininum spacing to the
2070 other M-text drawn, and stores the results in the members of the
2071 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2072 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2073 min_line_ascent, min_line_descent, max_line_ascent, and
2074 max_line_descent of $CONTROL are all zero.
2077 This function returns the width of the text to be drawn in the
2078 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2079 text is drawn in multiple physical lines, it returns the width of
2080 the widest line. If an error occurs, it returns -1 and assigns an
2081 error code to the external variable #merror_code. */
2085 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2087 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2088 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2089 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2091 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2092 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2093 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2094 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2096 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2097 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2098 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2099 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2101 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2102 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2103 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2104 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2105 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2106 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2108 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2109 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2110 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2111 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2113 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2120 mdraw_text_extents (MFrame *frame,
2121 MText *mt, int from, int to, MDrawControl *control,
2122 MDrawMetric *overall_ink_return,
2123 MDrawMetric *overall_logical_return,
2124 MDrawMetric *overall_line_return)
2126 MGlyphString *gstring;
2128 int width, rbearing;
2130 ASSURE_CONTROL (control);
2131 M_CHECK_POS_X (mt, from, -1);
2132 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2133 to = mtext_nchars (mt) + (control->cursor_width != 0);
2137 gstring = get_gstring (frame, mt, from, to, control);
2139 MERROR (MERROR_DRAW, -1);
2140 width = gstring_width (gstring, from, to, &rbearing);
2141 if (overall_ink_return)
2143 overall_ink_return->y = - gstring->physical_ascent;
2144 overall_ink_return->x = gstring->lbearing;
2146 if (overall_logical_return)
2148 overall_logical_return->y = - gstring->ascent;
2149 overall_logical_return->x = 0;
2151 if (overall_line_return)
2153 overall_line_return->y = - gstring->line_ascent;
2154 overall_line_return->x = gstring->lbearing;
2157 for (from = gstring->to; from < to; from = gstring->to)
2159 int this_width, this_rbearing;
2161 y += gstring->line_descent;
2162 M17N_OBJECT_UNREF (gstring->top);
2163 gstring = get_gstring (frame, mt, from, to, control);
2164 this_width = gstring_width (gstring, from, to, &this_rbearing);
2165 y += gstring->line_ascent;
2166 if (width < this_width)
2168 if (rbearing < this_rbearing)
2169 rbearing = this_rbearing;
2171 if (overall_ink_return)
2173 overall_ink_return->width = rbearing;
2174 overall_ink_return->height
2175 = y + gstring->physical_descent - overall_ink_return->y;
2177 if (overall_logical_return)
2179 overall_logical_return->width = width;
2180 overall_logical_return->height
2181 = y + gstring->descent - overall_logical_return->y;
2183 if (overall_line_return)
2185 overall_line_return->width = MAX (width, rbearing);
2186 overall_line_return->height
2187 = y + gstring->line_descent - overall_line_return->y;
2190 M17N_OBJECT_UNREF (gstring->top);
2197 @brief Compute the text dimensions of each character of M-text.
2199 The mdraw_text_per_char_extents () function computes the drawn
2200 metric of each character between $FROM and $TO of M-text $MT
2201 assuming that they are drawn on a window of frame $FRAME using the
2202 mdraw_text_with_control () function with the drawing control
2205 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2206 $LOGICAL_ARRAY_RETURN. Each successive element of
2207 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2208 ink and logical metrics of successive characters respectively,
2209 relative to the drawing origin of the M-text. The number of
2210 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2211 been set is returned to $NUM_CHARS_RETURN.
2213 If $ARRAY_SIZE is too small to return all metrics, the function
2214 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2215 Otherwise, it returns zero.
2217 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2218 @c NULL, this function also computes the metrics of the overall
2219 text and stores the results in the members of the structure
2220 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2222 If $CONTROL->two_dimensional is nonzero, this function computes
2223 only the metrics of characters in the first line. */
2225 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2227 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2228 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2229 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2230 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2232 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2233 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2234 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2235 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2236 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2238 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2239 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2242 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2243 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2244 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2247 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2248 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2251 mdraw_text_per_char_extents (MFrame *frame,
2252 MText *mt, int from, int to,
2253 MDrawControl *control,
2254 MDrawMetric *ink_array_return,
2255 MDrawMetric *logical_array_return,
2257 int *num_chars_return,
2258 MDrawMetric *overall_ink_return,
2259 MDrawMetric *overall_logical_return)
2261 MGlyphString *gstring;
2265 ASSURE_CONTROL (control);
2266 *num_chars_return = to - from;
2267 if (array_size < *num_chars_return)
2268 MERROR (MERROR_DRAW, -1);
2269 if (overall_logical_return)
2270 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2271 if (overall_ink_return)
2272 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2274 M_CHECK_RANGE (mt, from, to, -1, 0);
2275 gstring = get_gstring (frame, mt, from, to, control);
2278 *num_chars_return = 0;
2282 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2283 if (g->pos >= from && g->pos < to)
2287 int width = g->width;
2288 int lbearing = g->lbearing;
2289 int rbearing = g->rbearing;
2290 int ascent = g->ascent;
2291 int descent = g->descent;
2292 int logical_ascent = g->rface->rfont->ascent;
2293 int logical_descent = g->rface->rfont->descent;
2295 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2297 if (lbearing < width + g->lbearing)
2298 lbearing = width + g->lbearing;
2299 if (rbearing < width + g->rbearing)
2300 rbearing = width + g->rbearing;
2302 if (ascent < g->ascent)
2304 if (descent < g->descent)
2305 descent = g->descent;
2312 ink_array_return[start - from].x = x + lbearing;
2313 ink_array_return[start - from].y = - ascent;
2314 ink_array_return[start - from].width = rbearing - lbearing;
2315 ink_array_return[start - from].height = ascent + descent;
2316 logical_array_return[start - from].x = x;
2317 logical_array_return[start - from].y = - logical_descent;
2318 logical_array_return[start - from].height
2319 = logical_ascent + logical_descent;
2320 logical_array_return[start - from].width = width;
2326 if (overall_ink_return)
2328 overall_ink_return->y = - gstring->line_ascent;
2329 overall_ink_return->x = gstring->lbearing;
2330 overall_ink_return->width = x - gstring->lbearing;
2331 overall_ink_return->height = gstring->height;
2333 if (overall_logical_return)
2335 overall_logical_return->y = - gstring->ascent;
2336 overall_logical_return->x = 0;
2337 overall_logical_return->width = x;
2338 overall_logical_return->height = gstring->ascent + gstring->descent;
2341 M17N_OBJECT_UNREF (gstring->top);
2348 @brief Return the character position nearest to the coordinates.
2350 The mdraw_coordinates_position () function checks which character
2351 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2352 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2353 mdraw_text_with_control () function with the drawing control
2354 object $CONTROL. Here, the character position means the number of
2355 characters that precede the character in question in $MT, that is,
2356 the character position of the first character is 0.
2358 $FRAME is used only to get the default face information.
2361 If the glyph image of a character covers coordinate ($X, $Y),
2362 mdraw_coordinates_position () returns the character position of
2364 If $Y is less than the minimum Y-coordinate of the drawn area, it
2365 returns $FROM.\n\n\n
2366 If $Y is greater than the maximum Y-coordinate of the drawn area,
2367 it returns $TO.\n\n\n
2368 If $Y fits in with the drawn area but $X is less than the minimum
2369 X-coordinate, it returns the character position of the first
2370 character drawn on the line $Y.\n\n\n
2371 If $Y fits in with the drawn area but $X is greater than the
2372 maximum X-coordinate, it returns the character position of the
2373 last character drawn on the line $Y. */
2376 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2378 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2379 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2380 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2381 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2382 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2383 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2385 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2388 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2389 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2393 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2395 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2396 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2398 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2399 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2402 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2403 int x_offset, int y_offset, MDrawControl *control)
2405 MGlyphString *gstring;
2410 M_CHECK_POS_X (mt, from, -1);
2411 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2412 to = mtext_nchars (mt) + (control->cursor_width != 0);
2418 ASSURE_CONTROL (control);
2419 gstring = get_gstring (frame, mt, from, to, control);
2420 while (y + gstring->line_descent <= y_offset
2421 && gstring->to < to)
2424 y += gstring->line_descent;
2425 M17N_OBJECT_UNREF (gstring->top);
2426 gstring = get_gstring (frame, mt, from, to, control);
2427 y += gstring->line_ascent;
2430 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2431 if (! control->orientation_reversed)
2433 width = gstring->indent;
2434 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2435 if (g->pos >= from && g->pos < to)
2438 if (width > x_offset)
2444 width = - gstring->indent;
2445 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2446 if (g->pos >= from && g->pos < to)
2449 if (width < x_offset)
2454 M17N_OBJECT_UNREF (gstring->top);
2462 @brief Compute information about a glyph.
2464 The mdraw_glyph_info () function computes information about a
2465 glyph that covers a character at position $POS of the M-text $MT
2466 assuming that the text is drawn from the character at $FROM of $MT
2467 on a window of frame $FRAME using the mdraw_text_with_control ()
2468 function with the drawing control object $CONTROL.
2470 The information is stored in the members of $INFO. */
2472 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2474 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2475 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2476 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2477 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2479 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2487 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2488 MDrawControl *control, MDrawGlyphInfo *info)
2490 MGlyphString *gstring;
2494 M_CHECK_RANGE_X (mt, from, pos, -1);
2496 ASSURE_CONTROL (control);
2497 gstring = get_gstring (frame, mt, from, pos + 1, control);
2499 MERROR (MERROR_DRAW, -1);
2500 while (gstring->to <= pos)
2502 y += gstring->line_descent;
2503 M17N_OBJECT_UNREF (gstring->top);
2504 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2505 y += gstring->line_ascent;
2507 info->line_from = gstring->from;
2508 if (info->line_from < from)
2509 info->line_from = from;
2510 info->line_to = gstring->to;
2513 if (! control->orientation_reversed)
2515 info->x = gstring->indent;
2516 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2517 info->x += g->width;
2521 info->x = - gstring->indent;
2522 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2523 info->x -= g->width;
2524 while (g[-1].to == g->to)
2527 info->from = g->pos;
2529 info->glyph_code = g->code;
2530 info->this.x = g->lbearing;
2531 info->this.y = - gstring->line_ascent;
2532 info->this.height = gstring->height;
2533 info->this.width = - g->lbearing + g->width;
2534 if (g->rface->rfont)
2535 info->font = &g->rface->rfont->font;
2538 /* info->logical_width is calculated later. */
2540 if (info->from > info->line_from)
2542 /* The logically previous glyph is on this line. */
2543 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2545 info->prev_from = g_tmp->pos;
2547 else if (info->line_from > 0)
2549 /* The logically previous glyph is on the previous line. */
2550 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2551 gstring->from, control);
2552 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2554 info->prev_from = g_tmp->pos;
2555 M17N_OBJECT_UNREF (gst->top);
2558 info->prev_from = -1;
2560 if (GLYPH_INDEX (g) > 1)
2561 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2562 else if (! control->orientation_reversed)
2564 if (info->line_from > 0)
2568 int p = gstring->from - 1;
2570 gst = get_gstring (frame, mt, p, gstring->from, control);
2571 g_tmp = gst->glyphs + (gst->used - 2);
2572 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2573 M17N_OBJECT_UNREF (gst->top);
2576 info->left_from = info->left_to = -1;
2580 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2584 int p = gstring->to;
2586 gst = get_gstring (frame, mt, p, p + 1, control);
2587 g_tmp = gst->glyphs + (gst->used - 2);
2588 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2589 M17N_OBJECT_UNREF (gst->top);
2592 info->left_from = info->left_to = -1;
2595 if (info->to < gstring->to)
2597 /* The logically next glyph is on this line. */
2598 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2600 info->next_to = g_tmp->to;
2602 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2604 /* The logically next glyph is on the next line. */
2606 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2607 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2609 info->next_to = g_tmp->to;
2610 M17N_OBJECT_UNREF (gst->top);
2615 for (info->logical_width = (g++)->width;
2616 g->pos == pos && g->type != GLYPH_ANCHOR;
2617 info->this.width += g->width, info->logical_width += (g++)->width);
2618 info->this.width += g[-1].rbearing - g[-1].width;
2620 if (g->type != GLYPH_ANCHOR)
2621 info->right_from = g->pos, info->right_to = g->to;
2622 else if (! control->orientation_reversed)
2624 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2627 M17N_OBJECT_UNREF (gstring->top);
2628 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2630 info->right_from = g->pos, info->right_to = g->to;
2633 info->right_from = info->right_to = -1;
2637 if (info->line_from > 0)
2639 pos = gstring->from - 1;
2640 M17N_OBJECT_UNREF (gstring->top);
2641 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2643 info->right_from = g->pos, info->right_to = g->to;
2646 info->right_from = info->right_to = -1;
2649 M17N_OBJECT_UNREF (gstring->top);
2656 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2657 MDrawControl *control, MDrawGlyphInfo *info,
2658 int array_size, int *num_glyphs_return)
2660 MGlyphString *gstring;
2665 ASSURE_CONTROL (control);
2666 *num_glyphs_return = 0;
2667 M_CHECK_RANGE (mt, from, to, -1, 0);
2668 gstring = get_gstring (frame, mt, from, to, control);
2671 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2673 if (g->type == GLYPH_BOX
2674 || g->pos < from || g->pos >= to)
2676 if (g->type == GLYPH_PAD)
2678 if (g->left_padding)
2679 pad_width = g->width;
2683 info[-1].x += g->width;
2684 info[-1].logical_width += g->width;
2690 info->from = g->pos;
2692 info->glyph_code = g->code;
2693 info->x = g->xoff + pad_width;
2695 info->this.x = g->lbearing;
2696 info->this.y = - g->ascent;
2697 info->this.height = g->ascent + g->descent;
2698 info->this.width = g->rbearing - g->lbearing;
2699 info->logical_width = g->width + pad_width;
2700 if (g->rface->rfont)
2701 info->font = &g->rface->rfont->font;
2709 M17N_OBJECT_UNREF (gstring->top);
2711 *num_glyphs_return = n;
2712 return (n <= array_size ? 0 : -1);
2718 @brief Draw one or more textitems.
2720 The mdraw_text_items () function draws one or more M-texts on
2721 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2722 of the textitems to be drawn and $NITEMS is the number of
2723 textimtems in the array. */
2726 @brief textitem ¤òɽ¼¨¤¹¤ë.
2728 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2729 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2730 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2733 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2737 MTextItem, mdraw_text (). */
2740 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2741 MDrawTextItem *items, int nitems)
2743 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2745 while (nitems-- > 0)
2748 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2750 mdraw_text_with_control (frame, win, x, y,
2751 items->mt, 0, mtext_nchars (items->mt),
2753 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2754 items->control, NULL, NULL, NULL);
2757 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2763 @brief calculate a line breaking position.
2765 The function mdraw_default_line_break () calculates a line
2766 breaking position based on the line number $LINE and the
2767 coordinate $Y, when a line is too long to fit within the width
2768 limit. $POS is the position of the character next to the last
2769 one that fits within the limit. $FROM is the position of the
2770 first character of the line, and TO is the position of the last
2771 character displayed on the line if there were not width limit.
2772 LINE and Y are reset to 0 when a line is broken by a newline
2773 character, and incremented each time when a long line is broken
2774 because of the width limit.
2777 This function returns a character position to break the
2782 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2784 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2785 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2786 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2787 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2788 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2789 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2790 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2793 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2797 mdraw_default_line_break (MText *mt, int pos,
2798 int from, int to, int line, int y)
2800 int c = mtext_ref_char (mt, pos);
2803 if (c == ' ' || c == '\t')
2807 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2814 if (c == ' ' || c == '\t')
2817 c = mtext_ref_char (mt, pos);
2830 @brief Obtain per character dimension information.
2832 The mdraw_per_char_extents () function computes the text dimension
2833 of each character in M-text $MT. The faces given as text
2834 properties in $MT and the default face of frame $FRAME determine
2835 the fonts to draw the text. Each successive element in
2836 $ARRAY_RETURN is set to the drawn metrics of successive
2837 characters, which is relative to the origin of the drawing, and a
2838 rectangle for each character in $MT. The number of elements of
2839 $ARRAY_RETURN must be equal to or greater than the number of
2842 If pointer $OVERALL_RETURN is not @c NULL, this function also
2843 computes the extents of the overall text and stores the results in
2844 the members of the structure pointed to by $OVERALL_RETURN. */
2847 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2849 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2850 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2851 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2852 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2853 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2854 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2857 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2858 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2861 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2864 mdraw_per_char_extents (MFrame *frame, MText *mt,
2865 MDrawMetric *array_return,
2866 MDrawMetric *overall_return)
2868 int n = mtext_nchars (mt);
2870 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2871 n, &n, overall_return, NULL);
2875 @brief clear cached information.
2877 The mdraw_clear_cache () function clear cached information
2878 on M-text $MT that was attached by any of the drawing functions.
2879 When the behaviour of `format' or `line_break'
2880 member functions of MDrawControl is changed, the cache must be cleared.
2885 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2887 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2888 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2889 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2890 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2895 mdraw_clear_cache (MText *mt)
2897 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);