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 MRealizedFace *rface = default_rface;
240 int size = gstring->control.fixed_width;
244 MLIST_RESET (gstring);
245 gstring->from = from;
247 /* At first generate glyphs while using the member <enabled> as a
248 flag for rface re-checking. */
251 /** Put anchor glyphs at the head and tail. */
252 g_tmp.type = GLYPH_ANCHOR;
253 g_tmp.pos = g_tmp.to = from;
255 APPEND_GLYPH (gstring, g_tmp);
257 stop = face_change = charset_change = language_change = pos = from;
264 if (pos < mtext_nchars (mt))
265 c = mtext_ref_char (mt, pos);
270 /* Short cut for the obvious case. */
271 g_tmp.category = Mnil;
272 if (c == ' ' || c == '\n' || c == '\t')
273 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
275 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
279 g_tmp.category = mchar_get_prop (c, Mcategory);
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 /* Search backward for a character that explicitly
286 specifies a script. */
287 for (i = pos - 1; i >= from; i--)
289 int c1 = mtext_ref_char (mt, i);
290 MSymbol sym = ((c1 > 0x20 && c1 < 0x100) ? Mlatin
291 : mchar_get_prop (c1, Mscript));
293 if (sym != Minherited && sym != Mnil)
299 if (this_script == Mnil)
300 /* Search forward for a character that explicitly
301 specifies a script. */
302 for (i = pos + 1; i < to; i++)
304 int c1 = mtext_ref_char (mt, i);
305 MSymbol sym = ((c1 > 0x20 && c1 < 0x100) ? Mlatin
306 : mchar_get_prop (c1, Mscript));
308 if (sym != Minherited && sym != Mnil)
316 if (pos == stop || script != this_script
317 || MGLYPH (last)->type != g_tmp.type)
320 if (g->type != GLYPH_ANCHOR)
321 while (g < gstring->glyphs + gstring->used)
322 g = mface__for_chars (script, language, charset,
323 g, gstring->glyphs + gstring->used, size);
326 last = gstring->used;
327 script = this_script;
330 if (pos < mtext_nchars (mt) && pos == language_change)
332 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
333 mtext_prop_range (mt, Mlanguage, pos, NULL,
334 &language_change, 0);
336 if (pos < mtext_nchars (mt) && pos == charset_change)
338 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
339 mtext_prop_range (mt, Mcharset, pos, NULL,
342 if (pos < mtext_nchars (mt) && pos == face_change)
345 int num = mtext_get_prop_values (mt, pos, Mface,
346 (void **) faces, 64);
348 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
350 ? mface__realize (frame, faces, num,
351 language, charset, size)
355 if (stop > language_change)
356 stop = language_change;
357 if (stop > charset_change)
358 stop = charset_change;
359 if (face_change < stop)
369 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
373 ctrl[0] = ctrl[1] = g_tmp;
375 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
376 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
377 APPEND_GLYPH (gstring, ctrl[0]);
378 APPEND_GLYPH (gstring, ctrl[1]);
381 APPEND_GLYPH (gstring, g_tmp);
383 && gstring->control.two_dimensional)
387 /* Append an anchor glyph. */
388 g_tmp.type = GLYPH_ANCHOR;
390 g_tmp.code = MCHAR_INVALID_CODE;
391 g_tmp.pos = g_tmp.to = pos;
393 APPEND_GLYPH (gstring, g_tmp);
397 /* Next, run FLT if necessary. */
398 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
402 if (this->type == GLYPH_CHAR && this->rface->rfont)
406 if (this->rface->rfont->layouter != Mnil)
411 for (prev = MGLYPH (start - 1);
412 (prev->type == GLYPH_CHAR
413 && prev->category == McatCf
414 && (code = mfont__encode_char (this->rface->rfont, prev->c)
415 != MCHAR_INVALID_CODE));
420 (g->type == GLYPH_CHAR
421 && (g->rface->rfont == this->rface->rfont
422 || (g->category == McatCf
423 && ((code = mfont__encode_char (this->rface->rfont,
425 != MCHAR_INVALID_CODE))));
427 if (g->rface->rfont != this->rface->rfont)
429 g->rface->rfont = this->rface->rfont;
432 i = mfont__flt_run (gstring, start, i, this->rface);
436 while (this->type == GLYPH_CHAR
439 && MSYMBOL_NAME (this->category)[0] == 'M'
440 && this->rface->rfont
441 && this->rface->rfont->layouter == Mnil)
443 int class = (int) mchar_get_prop (this->c,
446 = MAKE_COMBINING_CODE_BY_CLASS (class);
450 reorder_combining_chars (gstring, start, i);
451 if (this->type == GLYPH_ANCHOR)
460 /* At last, reorder glyphs visually if necessary. */
461 if (gstring->control.enable_bidi)
462 visual_order (gstring);
467 combining_code_from_class (int class)
472 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
473 else if (class == 200) /* below left attached */
474 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
475 else if (class == 202) /* below attached*/
476 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
477 else if (class == 204) /* below right attached */
478 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
479 else if (class == 208) /* left attached */
480 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
481 else if (class == 210) /* right attached */
482 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
483 else if (class == 212) /* above left attached */
484 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
485 else if (class == 214) /* above attached */
486 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
487 else if (class == 216) /* above right attached */
488 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
489 else if (class == 218) /* below left */
490 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
491 else if (class == 220) /* below */
492 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
493 else if (class == 222) /* below right */
494 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
495 else if (class == 224) /* left */
496 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
497 else if (class == 226) /* right */
498 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
499 else if (class == 228) /* above left */
500 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
501 else if (class == 230) /* above */
502 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
503 else if (class == 232) /* above right */
504 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
505 else if (class == 233) /* double below */
506 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
507 else if (class == 234) /* double above */
508 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
509 else if (class == 240) /* iota subscript */
510 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
512 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
518 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
520 int g_physical_ascent, g_physical_descent;
521 int g_width, g_lbearing, g_rbearing;
522 MGlyph *g = MGLYPH (from);
523 MGlyph *last_g = MGLYPH (to);
525 g_physical_ascent = gstring->physical_ascent;
526 g_physical_descent = gstring->physical_descent;
527 g_width = g_lbearing = g_rbearing = 0;
529 mfont__get_metric (gstring, from, to);
538 while (g < last_g && base->otf_cmd == g->otf_cmd) g++;
539 mfont__ft_drive_gpos (gstring, GLYPH_INDEX (base), GLYPH_INDEX (g));
548 MRealizedFont *rfont = base->rface->rfont;
549 int size = rfont->font.property[MFONT_SIZE];
550 int width, lbearing, rbearing;
552 if (g == last_g || ! g->combining_code)
555 if (base->left_padding && base->lbearing < 0)
557 base->xoff = - base->lbearing;
558 base->width += base->xoff;
559 base->rbearing += base->xoff;
562 if (base->right_padding && base->rbearing > base->width)
564 base->width = base->rbearing;
566 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
567 rbearing = base->rbearing;
571 /* With combining glyphs. */
572 int left = -base->width;
574 int top = - base->ascent;
575 int bottom = base->descent;
576 int height = bottom - top;
577 int begin = base->pos;
582 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
583 rbearing = base->rbearing;
585 while (g != last_g && g->combining_code)
587 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
589 combining_code = g->combining_code;
590 if (COMBINING_BY_CLASS_P (combining_code))
591 g->combining_code = combining_code
592 = combining_code_from_class (COMBINING_CODE_CLASS
595 rfont = g->rface->rfont;
596 size = rfont->font.property[MFONT_SIZE];
597 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
599 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
601 base_x = COMBINING_CODE_BASE_X (combining_code);
602 base_y = COMBINING_CODE_BASE_Y (combining_code);
603 add_x = COMBINING_CODE_ADD_X (combining_code);
604 add_y = COMBINING_CODE_ADD_Y (combining_code);
608 else if (end < g->to)
611 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
614 if (g->xoff + g->width > right)
615 right = g->xoff + g->width;
616 width = right - left;
617 if (g->xoff + g->lbearing < left + lbearing)
618 lbearing = g->xoff + g->lbearing - left;
619 if (g->xoff + g->rbearing > left + rbearing)
620 rbearing = g->xoff + g->rbearing - left;
623 g->yoff = top + height * base_y / 2;
627 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
629 if (g->yoff - g->ascent < top)
630 top = g->yoff - g->ascent;
631 if (g->yoff + g->descent > bottom)
632 bottom = g->yoff + g->descent;
633 height = bottom - top;
639 base->ascent = - top;
640 base->descent = bottom;
641 base->lbearing = lbearing;
642 base->rbearing = rbearing;
643 if (left < - base->width)
645 base->xoff = - base->width - left;
646 base->width += base->xoff;
647 base->rbearing += base->xoff;
648 base->lbearing += base->xoff;
652 base->width += right;
653 base->rbearing += right;
654 base->right_padding = 1;
655 for (i = 1; base + i != g; i++)
656 base[i].xoff -= right;
659 for (i = 0; base + i != g; i++)
666 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
667 g_physical_descent = MAX (g_physical_descent, base->descent);
668 g_lbearing = MIN (g_lbearing, g_width + lbearing);
669 g_rbearing = MAX (g_rbearing, g_width + rbearing);
670 g_width += base->width;
673 gstring->physical_ascent = g_physical_ascent;
674 gstring->physical_descent = g_physical_descent;
675 gstring->sub_width = g_width;
676 gstring->sub_lbearing = g_lbearing;
677 gstring->sub_rbearing = g_rbearing;
681 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
682 by this function directly. Character glyphs are handled by
683 layouter functions registered in font drivers.
685 This function fill-in all the remaining members of glyphs. */
688 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
690 /* Default width of TAB. */
691 int tab_width = frame->space_width * (gstring->control.tab_width
692 ? gstring->control.tab_width : 8);
696 MDrawControl *control = &(gstring->control);
699 int box_line_height = 0;
700 int ignore_formatting_char = control->ignore_formatting_char;
702 gstring->ascent = gstring->descent = 0;
703 gstring->physical_ascent = gstring->physical_descent = 0;
704 gstring->width = gstring->lbearing = gstring->rbearing = 0;
708 while (g->type != GLYPH_ANCHOR)
710 if (box != g->rface->box)
712 int gidx = GLYPH_INDEX (g);
716 /* Insert the right side of the box. That glyph belongs
717 to the previous grapheme cluster. */
718 MGlyph box_glyph = g[-1];
720 box_glyph.type = GLYPH_BOX;
722 = (control->fixed_width
724 : box->inner_hmargin + box->width + box->outer_hmargin);
725 box_glyph.lbearing = 0;
726 box_glyph.rbearing = box_glyph.width;
728 box_glyph.right_padding = 1;
729 gstring->width += box_glyph.width;
730 gstring->rbearing += box_glyph.width;
731 INSERT_GLYPH (gstring, gidx, box_glyph);
738 /* Insert the left side of the box. That glyph belongs
739 to the following grapheme cluster. */
740 MGlyph box_glyph = *g;
741 int box_height = (box->width
742 + box->inner_vmargin + box->outer_vmargin);
744 if (box_line_height < box_height)
745 box_line_height = box_height;
746 box_glyph.type = GLYPH_BOX;
748 = (control->fixed_width
750 : box->inner_hmargin + box->width + box->outer_hmargin);
751 box_glyph.lbearing = 0;
752 box_glyph.rbearing = box_glyph.width;
754 box_glyph.left_padding = 1;
755 gstring->width += box_glyph.width;
756 gstring->rbearing += box_glyph.width;
757 INSERT_GLYPH (gstring, gidx, box_glyph);
763 if (g->category == McatCf && ignore_formatting_char)
764 g->type = GLYPH_SPACE;
766 if (g->type == GLYPH_CHAR)
768 MRealizedFace *rface = g->rface;
769 MRealizedFont *rfont = rface->rfont;
771 int from = GLYPH_INDEX (g);
773 for (g++; g->type == GLYPH_CHAR; g++)
774 if (! rfont != ! g->rface->rfont
775 || box != g->rface->box
776 || ((fromg->code == MCHAR_INVALID_CODE)
777 != (g->code == MCHAR_INVALID_CODE))
778 || (g->category == McatCf && ignore_formatting_char))
780 if (rfont && fromg->code != MCHAR_INVALID_CODE)
783 int to = GLYPH_INDEX (g);
785 layout_glyphs (frame, gstring, from, to);
786 extra_width = - gstring->sub_lbearing;
788 && (GLYPH_INDEX (g) > 1
789 || control->align_head))
793 pad.type = GLYPH_PAD;
796 pad.width = pad.rbearing = extra_width;
797 pad.left_padding = 1;
798 INSERT_GLYPH (gstring, from, pad);
800 gstring->sub_lbearing = 0;
801 gstring->sub_width += extra_width;
802 gstring->sub_rbearing += extra_width;
804 g = MGLYPH (from - 1);
805 if (g->type == GLYPH_SPACE)
807 /* The pad just inserted is absorbed (maybe
808 partially) by the previous space while
809 keeping at least some space width. For the
810 moment, we use the arbitrary width 2-pixel.
811 Perhaps, it should be decided by the current
812 face, or a default value of the current
813 frame, which is, however, not yet
815 if (extra_width + 2 < g->width)
817 g->width -= extra_width;
821 extra_width -= g->width - 2;
824 gstring->width -= extra_width;
825 gstring->rbearing -= extra_width;
829 extra_width = gstring->sub_rbearing - gstring->sub_width;
833 if (g->type == GLYPH_SPACE && box == g->rface->box)
837 pad.type = GLYPH_PAD;
840 pad.width = pad.rbearing = extra_width;
842 INSERT_GLYPH (gstring, to, pad);
846 g[-1].width += extra_width;
847 gstring->sub_width += extra_width;
850 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
851 gstring->lbearing = gstring->width + gstring->sub_lbearing;
852 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
853 gstring->rbearing = gstring->width + gstring->sub_rbearing;
854 gstring->width += gstring->sub_width;
855 if (gstring->ascent < rface->ascent)
856 gstring->ascent = rface->ascent;
857 if (gstring->descent < rface->descent)
858 gstring->descent = rface->descent;
863 for (; fromg < g; fromg++)
865 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
866 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
867 fromg->width = fromg->rbearing = 1;
869 fromg->width = fromg->rbearing = rface->space_width;
870 fromg->xoff = fromg->lbearing = 0;
871 fromg->ascent = fromg->descent = 0;
872 gstring->width += fromg->width;
873 gstring->rbearing += fromg->width;
875 if (gstring->ascent < frame->rface->ascent)
876 gstring->ascent = frame->rface->ascent;
877 if (gstring->descent < frame->descent)
878 gstring->descent = frame->rface->descent;
881 else if (g->type == GLYPH_SPACE)
884 g->width = g->rface->space_width;
885 else if (g->c == '\n')
887 g->width = control->cursor_width;
890 if (control->cursor_bidi)
892 else if (g->width < 0)
893 g->width = g->rface->space_width;
896 else if (g->c == '\t')
898 g->width = tab_width - ((gstring->indent + gstring->width)
904 if (g[-1].type == GLYPH_PAD)
906 /* This space glyph absorbs (maybe partially) the
907 previous padding glyph. */
908 g->width -= g[-1].width;
910 /* But, keep at least some space width. For the
911 moment, we use the arbitrary width 2-pixel. */
914 g->rbearing = g->width;
915 gstring->width += g->width;
916 gstring->rbearing += g->width;
919 if (gstring->ascent < g->rface->ascent)
920 gstring->ascent = g->rface->ascent;
921 if (gstring->descent < g->rface->descent)
922 gstring->descent = g->rface->descent;
928 gstring->width += g->width;
929 gstring->rbearing += g->width;
936 /* Insert the right side of the box. */
937 int gidx = GLYPH_INDEX (g);
938 MGlyph box_glyph = g[-1];
940 box_glyph.type = GLYPH_BOX;
942 = (control->fixed_width
944 : box->inner_hmargin + box->width + box->outer_hmargin);
945 box_glyph.lbearing = 0;
946 box_glyph.rbearing = box_glyph.width;
948 box_glyph.right_padding = 1;
949 gstring->width += box_glyph.width;
950 gstring->rbearing += box_glyph.width;
951 INSERT_GLYPH (gstring, gidx, box_glyph);
954 gstring->text_ascent = gstring->ascent;
955 gstring->text_descent = gstring->descent;
956 if (gstring->text_ascent < gstring->physical_ascent)
957 gstring->text_ascent = gstring->physical_ascent;
958 if (gstring->text_descent < gstring->physical_descent)
959 gstring->text_descent = gstring->physical_descent;
960 gstring->line_ascent = gstring->text_ascent;
961 gstring->line_descent = gstring->text_descent;
962 if (box_line_height > 0)
964 gstring->line_ascent += box_line_height;
965 gstring->physical_ascent = gstring->line_ascent;
966 gstring->line_descent += box_line_height;
967 gstring->physical_descent = gstring->line_descent;
970 if (gstring->line_ascent < control->min_line_ascent)
971 gstring->line_ascent = control->min_line_ascent;
972 else if (control->max_line_ascent
973 && control->max_line_ascent > control->min_line_ascent
974 && gstring->line_ascent > control->max_line_ascent)
975 gstring->line_ascent = control->max_line_ascent;
977 if (gstring->line_descent < control->min_line_descent)
978 gstring->line_descent = control->min_line_descent;
979 else if (control->max_line_descent
980 && control->max_line_descent > control->min_line_descent
981 && gstring->line_descent > control->max_line_descent)
982 gstring->line_descent = control->max_line_descent;
983 gstring->height = gstring->line_ascent + gstring->line_descent;
985 if (control->orientation_reversed
988 /* We must adjust TAB width for RTL orientation. */
989 width = gstring->indent;
991 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
993 if (g->type == GLYPH_CHAR && g->c == '\t')
995 int this_width = tab_width - (width % tab_width);
997 if (g[1].type == GLYPH_PAD)
998 this_width -= g[1].width;
999 if (g[-1].type == GLYPH_PAD)
1000 this_width -= g[-1].width;
1003 gstring->width += this_width - g->width;
1004 gstring->rbearing += this_width - g->width;
1005 g->width = this_width;
1006 width += this_width;
1016 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1017 MGlyphString *gstring, int from, int to,
1018 int *from_idx, int *to_idx, int *to_x)
1020 MGlyph *g = MGLYPH (1);
1021 MDrawRegion region = (MDrawRegion) NULL;
1022 MDrawControl *control = &gstring->control;
1023 int cursor_pos = -1;
1025 int cursor_bidi = control->cursor_bidi;
1027 if (control->with_cursor && control->cursor_width)
1029 if (gstring->from <= control->cursor_pos
1030 && gstring->to > control->cursor_pos)
1031 cursor_pos = control->cursor_pos;
1033 && gstring->from <= control->cursor_pos - 1
1034 && gstring->to > control->cursor_pos - 1)
1035 prev_pos = control->cursor_pos - 1;
1038 *from_idx = *to_idx = 0;
1039 while (g->type != GLYPH_ANCHOR)
1041 if (g->pos >= from && g->pos < to)
1043 MGlyph *fromg = g, *cursor = NULL;
1044 MRealizedFace *rface = g->rface;
1046 int cursor_width = 0;
1050 *from_idx = GLYPH_INDEX (g);
1051 while (g->pos >= from && g->pos < to
1052 && g->rface == rface)
1055 if (g->type != GLYPH_BOX
1056 && g->pos <= cursor_pos && g->to > cursor_pos)
1059 cursor = g, cursor_x = x + width;
1060 cursor_width += g->width;
1062 width += g++->width;
1065 && (control->as_image
1066 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1068 int this_x = x, this_width = width;
1070 if (fromg->type == GLYPH_BOX)
1071 this_x += fromg->width, this_width -= fromg->width;
1072 if (g[-1].type == GLYPH_BOX)
1073 this_width -= g[-1].width;
1074 (frame->driver->fill_space)
1075 (frame, win, rface, 0,
1076 this_x, y - gstring->text_ascent, this_width,
1077 gstring->text_ascent + gstring->text_descent,
1078 control->clip_region);
1085 rect.y = y - gstring->text_ascent;
1086 rect.height = gstring->text_ascent + gstring->text_descent;
1089 rect.width = ((control->cursor_width > 0
1090 && control->cursor_width < cursor_width)
1091 ? control->cursor_width : cursor_width);
1095 if (cursor->bidi_level % 2)
1096 rect.x += cursor_width - 1;
1099 (*frame->driver->fill_space)
1100 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1101 control->clip_region);
1103 region = (*frame->driver->region_from_rect) (&rect);
1105 (*frame->driver->region_add_rect) (region, &rect);
1108 if (cursor->bidi_level % 2)
1111 rect.width = cursor_width < 4 ? cursor_width : 4;
1112 (*frame->driver->fill_space)
1113 (frame, win, rface, 1,
1114 rect.x, rect.y, rect.width, rect.height,
1115 control->clip_region);
1116 (*frame->driver->region_add_rect) (region, &rect);
1128 if (fromg->type != GLYPH_BOX
1129 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1132 cursor = fromg, cursor_x = x + temp_width;
1133 cursor_width += fromg->width;
1135 temp_width += fromg++->width;
1142 if (! (cursor->bidi_level % 2))
1143 rect.x += cursor_width - 1;
1144 rect.y = y - gstring->text_ascent;
1145 rect.height = gstring->text_ascent + gstring->text_descent;
1147 (*frame->driver->fill_space)
1148 (frame, win, rface, 1,
1149 rect.x, rect.y, rect.width, rect.height,
1150 control->clip_region);
1152 region = (*frame->driver->region_from_rect) (&rect);
1154 (*frame->driver->region_add_rect) (region, &rect);
1155 rect.y += rect.height - 2;
1157 rect.width = cursor_width < 4 ? cursor_width : 4;
1158 if (! (cursor->bidi_level % 2))
1159 rect.x -= rect.width - 1;
1160 (*frame->driver->fill_space) (frame, win, rface, 1,
1161 rect.x, rect.y, rect.width, rect.height,
1162 control->clip_region);
1163 (*frame->driver->region_add_rect) (region, &rect);
1167 *to_idx = GLYPH_INDEX (g);
1177 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1178 MGlyphString *gstring, int from_idx, int to_idx,
1179 int reverse, MDrawRegion region)
1181 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1187 (*frame->driver->region_to_rect) (region, &rect);
1190 while (g != gend && x + g->rbearing <= rect.x)
1193 width -= g++->width;
1194 while (! g->enabled && g != gend)
1198 rect.x += rect.width;
1199 if (rect.x < x + width)
1202 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1204 width -= (--gend)->width;
1205 while (! gend->enabled && g != gend)
1209 while (gend[-1].to == gend->to) gend++;
1217 MRealizedFace *rface = g->rface;
1218 int width = g->width;
1219 MGlyph *from_g = g++;
1221 /* Handle the glyphs of the same type/face at once. */
1223 && g->type == from_g->type
1224 && g->rface == rface
1225 && (g->code < 0) == (from_g->code < 0)
1227 width += g++->width;
1229 if (from_g->type == GLYPH_CHAR)
1231 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1232 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1235 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1238 else if (from_g->type == GLYPH_BOX)
1240 /* Draw the left or right side of a box. If
1241 from_g->lbearing is nonzero, this is the left side,
1242 else this is the right side. */
1243 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1246 if (from_g->type != GLYPH_BOX)
1249 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1250 x, y, width, region);
1253 /* Draw the top and bottom side of a box. */
1254 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1255 x, y, width, region);
1266 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1267 int *from_x, int *to_x)
1270 int left_idx = *left, right_idx = *right;
1271 int left_x, right_x, x;
1273 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1276 if (x + g->rbearing > 0)
1278 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1280 left_idx = GLYPH_INDEX (g);
1285 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1288 if (x - g->width + g->lbearing < 0)
1290 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1292 right_idx = GLYPH_INDEX (g) + 1;
1297 if (*left == left_idx && *right == right_idx)
1300 if (*left != left_idx)
1302 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1307 if (*right != right_idx)
1309 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1319 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1324 if (from <= gstring->from && to >= gstring->to)
1327 *rbearing = gstring->rbearing;
1328 return gstring->width;
1333 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1334 if (g->pos >= from && g->pos < to)
1336 if (rbearing && width + g->rbearing > *rbearing)
1337 *rbearing = width + g->rbearing;
1345 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1346 MGlyphString *gstring, int from, int to)
1348 MDrawControl *control = &gstring->control;
1350 MDrawRegion clip_region, cursor_region;
1351 int from_idx, to_idx;
1354 if (control->orientation_reversed)
1355 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1357 x += gstring->indent;
1359 /* At first, draw all glyphs without cursor. */
1360 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1361 &from_idx, &to_idx, &to_x);
1363 if (control->partial_update)
1366 rect.width = to_x - x;
1367 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1369 rect.y = y - gstring->line_ascent;
1370 rect.height = gstring->height;
1371 clip_region = (*frame->driver->region_from_rect) (&rect);
1372 if (control->clip_region)
1373 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1376 clip_region = control->clip_region;
1379 clip_region = control->clip_region;
1381 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1386 (*frame->driver->intersect_region) (cursor_region, clip_region);
1387 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1390 if (clip_region != control->clip_region)
1391 (*frame->driver->free_region) (clip_region);
1393 (*frame->driver->free_region) (cursor_region);
1397 static int gstring_num;
1400 free_gstring (void *object)
1402 MGlyphString *gstring = (MGlyphString *) object;
1405 free_gstring (gstring->next);
1406 if (gstring->size > 0)
1407 free (gstring->glyphs);
1413 static MGlyphString scratch_gstring;
1415 static MGlyphString *
1416 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1419 MGlyphString *gstring;
1421 if (pos == mt->nchars)
1423 gstring = &scratch_gstring;
1427 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1428 MLIST_INIT1 (gstring, glyphs, 128);
1432 gstring->frame = frame;
1433 gstring->tick = frame->tick;
1434 gstring->top = gstring;
1436 gstring->control = *control;
1437 gstring->indent = gstring->width_limit = 0;
1438 if (control->format)
1439 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1441 gstring->width_limit = control->max_line_width;
1442 gstring->anti_alias = control->anti_alias;
1446 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1449 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1457 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1458 a width of glyphs for the character at I of GSTRING->mt. If I is
1459 not a beginning of a grapheme cluster, the corresponding element
1461 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1462 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1463 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1464 pos_width[g->pos - gstring->from] += g->width;
1465 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1467 if (pos_width[i] > 0)
1469 if (width + pos_width[i] > gstring->width_limit)
1472 width += pos_width[i];
1475 pos = gstring->from + i;
1476 if (gstring->control.line_break)
1478 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1479 gstring->from, gstring->to, 0, 0);
1480 if (pos <= gstring->from || pos >= gstring->to)
1483 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1484 layout_glyph_string (frame, gstring);
1488 /* Return a gstring that covers a character at POS. */
1490 static MGlyphString *
1491 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1493 MGlyphString *gstring = NULL;
1495 if (pos < mtext_nchars (mt))
1497 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1500 && ((prop->start != 0
1501 && mtext_ref_char (mt, prop->start - 1) != '\n')
1502 || (prop->end < mtext_nchars (mt)
1503 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1505 mtext_detach_property (prop);
1510 gstring = prop->val;
1511 if (gstring->frame != frame
1512 || gstring->tick != frame->tick
1513 || memcmp (control, &gstring->control,
1514 (char *) (&control->with_cursor)
1515 - (char *) (control)))
1517 mtext_detach_property (prop);
1522 else if (! control->cursor_width)
1530 offset = mtext_character (mt, pos, 0, '\n');
1535 offset -= gstring->from;
1537 for (gst = gstring; gst; gst = gst->next)
1541 gst->from += offset;
1543 for (i = 0; i < gst->used; i++)
1545 gst->glyphs[i].pos += offset;
1546 gst->glyphs[i].to += offset;
1549 M17N_OBJECT_REF (gstring);
1554 int line = 0, y = 0;
1556 if (control->two_dimensional)
1558 beg = mtext_character (mt, pos, 0, '\n');
1563 end = mtext_nchars (mt) + (control->cursor_width != 0);
1570 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1571 compose_glyph_string (frame, mt, beg, end, gstring);
1572 layout_glyph_string (frame, gstring);
1574 if (control->two_dimensional
1575 && gstring->width_limit
1576 && gstring->width > gstring->width_limit)
1578 MGlyphString *gst = gstring;
1580 truncate_gstring (frame, mt, gst);
1581 while (gst->to < end)
1583 line++, y += gst->height;
1584 gst->next = alloc_gstring (frame, mt, gst->from, control,
1586 gst->next->top = gstring;
1587 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1589 layout_glyph_string (frame, gst);
1590 if (gst->width <= gst->width_limit)
1592 truncate_gstring (frame, mt, gst);
1596 if (! control->disable_caching && pos < mtext_nchars (mt))
1598 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1599 MTEXTPROP_VOLATILE_STRONG);
1601 if (end > mtext_nchars (mt))
1602 end = mtext_nchars (mt);
1603 mtext_attach_property (mt, beg, end, prop);
1604 M17N_OBJECT_UNREF (prop);
1608 while (gstring->to <= pos)
1610 if (! gstring->next)
1612 gstring = gstring->next;
1614 gstring->control = *control;
1620 static MDrawControl control_noop;
1622 #define ASSURE_CONTROL(control) \
1624 control = &control_noop; \
1629 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1630 MText *mt, int from, int to,
1631 MDrawControl *control)
1633 MGlyphString *gstring;
1635 M_CHECK_POS_X (mt, from, -1);
1636 ASSURE_CONTROL (control);
1637 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1638 to = mtext_nchars (mt) + (control->cursor_width != 0);
1642 gstring = get_gstring (frame, mt, from, to, control);
1644 MERROR (MERROR_DRAW, -1);
1645 render_glyph_string (frame, win, x, y, gstring, from, to);
1649 y += gstring->line_descent;
1650 M17N_OBJECT_UNREF (gstring->top);
1651 gstring = get_gstring (frame, mt, from, to, control);
1652 y += gstring->line_ascent;
1653 render_glyph_string (frame, win, x, y, gstring, from, to);
1656 M17N_OBJECT_UNREF (gstring->top);
1663 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1669 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1670 if (g->pos <= pos && g->to > pos)
1675 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1676 if (g->pos <= pos && g->to > pos)
1683 /* for debugging... */
1687 dump_combining_code (int code)
1689 char *vallign = "tcbB";
1690 char *hallign = "lcr";
1696 if (COMBINING_BY_CLASS_P (code))
1697 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1698 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1699 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1700 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1701 off_x = COMBINING_CODE_OFF_X (code) - 128;
1703 sprintf (work + 2, "+%d", off_y);
1705 sprintf (work + 2, "%d", off_y);
1706 else if (off_x == 0)
1707 sprintf (work + 2, ".");
1708 p = work + strlen (work);
1710 sprintf (p, ">%d", off_x);
1712 sprintf (p, "<%d", -off_x);
1714 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1715 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1721 dump_gstring (MGlyphString *gstring, int indent)
1723 char *prefix = (char *) alloca (indent + 1);
1724 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1726 memset (prefix, 32, indent);
1729 fprintf (stderr, "(glyph-string");
1731 for (g = MGLYPH (0); g < last_g; g++)
1733 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1735 g - gstring->glyphs,
1736 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1737 : g->type == GLYPH_ANCHOR ? "ANC"
1738 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1739 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1740 dump_combining_code (g->combining_code),
1741 g->width, g->bidi_level);
1742 fprintf (stderr, ")");
1746 /* m17n-X internal APIs */
1751 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1753 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1754 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1756 Mlatin = msymbol ("latin");
1757 Minherited = msymbol ("inherited");
1759 McatCc = msymbol ("Cc");
1760 McatCf = msymbol ("Cf");
1762 MbidiR = msymbol ("R");
1763 MbidiAL = msymbol ("AL");
1764 MbidiRLE = msymbol ("RLE");
1765 MbidiRLO = msymbol ("RLO");
1766 MbidiBN = msymbol ("BN");
1767 MbidiS = msymbol ("S");
1769 fribidi_set_mirroring (TRUE);
1778 MLIST_FREE1 (&scratch_gstring, glyphs);
1782 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1786 /*** @addtogroup m17nDraw */
1791 @brief Draw an M-text on a window.
1793 The mdraw_text () function draws the text between $FROM and $TO of
1794 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1796 The appearance of the text (size, style, color, etc) is specified
1797 by the value of the text property whose key is @c Mface. If the
1798 M-text or a part of the M-text does not have such a text property,
1799 the default face of $FRAME is used.
1801 The font used to draw a character in the M-text is selected from
1802 the value of the fontset property of a face by the following
1807 <li> Search the text properties given to the character for the one
1808 whose key is @c Mcharset; its value should be either a symbol
1809 specifying a charset or #Mnil. If the value is #Mnil,
1810 proceed to the next step.
1812 Otherwise, search the mapping table of the fontset for the
1813 charset. If no entry is found proceed to the next step.
1815 If an entry is found, use one of the fonts in the entry that
1816 has a glyph for the character and that matches best with the
1817 face properties. If no such font exists, proceed to the next
1820 <li> Get the character property "script" of the character. If it is
1821 inherited, get the script property from the previous
1822 characters. If there is no previous character, or none of
1823 them has the script property other than inherited, proceed to
1826 Search the text properties given to the character for the one
1827 whose key is @c Mlanguage; its value should be either a
1828 symbol specifying a language or @c Mnil.
1830 Search the mapping table of the fontset for the combination
1831 of the script and language. If no entry is found, proceed to
1834 If an entry is found, use one of the fonts in the entry that
1835 has a glyph for the character and that matches best with the
1836 face properties. If no such font exists, proceed to the next
1839 <li> Search the fall-back table of the fontset for a font that has
1840 a glyph of the character. If such a font is found, use that
1845 If no font is found by the algorithm above, this function draws an
1846 empty box for the character.
1848 This function draws only the glyph foreground. To specify the
1849 background color, use mdraw_image_text () or
1850 mdraw_text_with_control ().
1852 This function is the counterpart of <tt>XDrawString ()</tt>,
1853 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1854 in the X Window System.
1857 If the operation was successful, mdraw_text () returns 0. If an
1858 error is detected, it returns -1 and assigns an error code to the
1859 external variable #merror_code. */
1861 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1863 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1864 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1867 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1868 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1869 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1870 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1872 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1873 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1877 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1878 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1879 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1880 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1881 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1884 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1885 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1886 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1889 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1890 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1891 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1892 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1894 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1895 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1898 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1899 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1902 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1903 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1904 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1907 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1908 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1912 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1913 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1915 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1916 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1919 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1920 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1923 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1924 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1926 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1933 mdraw_image_text () */
1936 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1937 MText *mt, int from, int to)
1939 MDrawControl control;
1941 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1942 memset (&control, 0, sizeof control);
1943 control.as_image = 0;
1944 return draw_text (frame, win, x, y, mt, from, to, &control);
1951 @brief Draw an M-text on a window as an image.
1953 The mdraw_image_text () function draws the text between $FROM and
1954 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1955 coordinate ($X, $Y).
1957 The way to draw a text is the same as in mdraw_text () except that
1958 this function also draws the background with the color specified
1961 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1962 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1963 functions in the X Window System.
1966 If the operation was successful, mdraw_image_text () returns 0.
1967 If an error is detected, it returns -1 and assigns an error code
1968 to the external variable #merror_code. */
1971 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1973 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1974 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1977 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1978 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1980 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1981 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1985 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1986 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1989 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1999 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
2000 MText *mt, int from, int to)
2002 MDrawControl control;
2004 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2005 memset (&control, 0, sizeof control);
2006 control.as_image = 1;
2007 return draw_text (frame, win, x, y, mt, from, to, &control);
2013 @brief Draw an M-text on a window with fine control.
2015 The mdraw_text_with_control () function draws the text between
2016 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2017 coordinate ($X, $Y).
2019 The way to draw a text is the same as in mdraw_text () except that
2020 this function also follows what specified in the drawing control
2023 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2024 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2025 breaks lines and the following characters are drawn in the next
2026 line. See the documentation of the structure @ MDrawControl for
2030 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2032 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2033 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2036 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2037 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2039 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2040 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2041 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2045 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2046 MText *mt, int from, int to, MDrawControl *control)
2048 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2049 return draw_text (frame, win, x, y, mt, from, to, control);
2055 @brief Compute text pixel width.
2057 The mdraw_text_extents () function computes the width of text
2058 between $FROM and $TO of M-text $MT when it is drawn on a window
2059 of frame $FRAME using the mdraw_text_with_control () function with
2060 the drawing control object $CONTROL.
2062 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2063 the bounding box of character ink of the M-text, and stores the
2064 results in the members of the structure pointed to by
2065 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2066 surrounding box, the box is included in the bounding box.
2068 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2069 computes the bounding box that provides mininum spacing to other
2070 graphical features (such as surrounding box) for the M-text, and
2071 stores the results in the members of the structure pointed to by
2072 $OVERALL_LOGICAL_RETURN.
2074 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2075 computes the bounding box that provides mininum spacing to the
2076 other M-text drawn, and stores the results in the members of the
2077 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2078 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2079 min_line_ascent, min_line_descent, max_line_ascent, and
2080 max_line_descent of $CONTROL are all zero.
2083 This function returns the width of the text to be drawn in the
2084 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2085 text is drawn in multiple physical lines, it returns the width of
2086 the widest line. If an error occurs, it returns -1 and assigns an
2087 error code to the external variable #merror_code. */
2091 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2093 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2094 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2095 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2097 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2098 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2099 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2100 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2102 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2103 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2104 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2105 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2107 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2108 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2109 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2110 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2111 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2112 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2114 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2115 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2116 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2117 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2119 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2126 mdraw_text_extents (MFrame *frame,
2127 MText *mt, int from, int to, MDrawControl *control,
2128 MDrawMetric *overall_ink_return,
2129 MDrawMetric *overall_logical_return,
2130 MDrawMetric *overall_line_return)
2132 MGlyphString *gstring;
2134 int width, rbearing;
2136 ASSURE_CONTROL (control);
2137 M_CHECK_POS_X (mt, from, -1);
2138 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2139 to = mtext_nchars (mt) + (control->cursor_width != 0);
2143 gstring = get_gstring (frame, mt, from, to, control);
2145 MERROR (MERROR_DRAW, -1);
2146 width = gstring_width (gstring, from, to, &rbearing);
2147 if (overall_ink_return)
2149 overall_ink_return->y = - gstring->physical_ascent;
2150 overall_ink_return->x = gstring->lbearing;
2152 if (overall_logical_return)
2154 overall_logical_return->y = - gstring->ascent;
2155 overall_logical_return->x = 0;
2157 if (overall_line_return)
2159 overall_line_return->y = - gstring->line_ascent;
2160 overall_line_return->x = gstring->lbearing;
2163 for (from = gstring->to; from < to; from = gstring->to)
2165 int this_width, this_rbearing;
2167 y += gstring->line_descent;
2168 M17N_OBJECT_UNREF (gstring->top);
2169 gstring = get_gstring (frame, mt, from, to, control);
2170 this_width = gstring_width (gstring, from, to, &this_rbearing);
2171 y += gstring->line_ascent;
2172 if (width < this_width)
2174 if (rbearing < this_rbearing)
2175 rbearing = this_rbearing;
2177 if (overall_ink_return)
2179 overall_ink_return->width = rbearing;
2180 overall_ink_return->height
2181 = y + gstring->physical_descent - overall_ink_return->y;
2183 if (overall_logical_return)
2185 overall_logical_return->width = width;
2186 overall_logical_return->height
2187 = y + gstring->descent - overall_logical_return->y;
2189 if (overall_line_return)
2191 overall_line_return->width = MAX (width, rbearing);
2192 overall_line_return->height
2193 = y + gstring->line_descent - overall_line_return->y;
2196 M17N_OBJECT_UNREF (gstring->top);
2203 @brief Compute the text dimensions of each character of M-text.
2205 The mdraw_text_per_char_extents () function computes the drawn
2206 metric of each character between $FROM and $TO of M-text $MT
2207 assuming that they are drawn on a window of frame $FRAME using the
2208 mdraw_text_with_control () function with the drawing control
2211 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2212 $LOGICAL_ARRAY_RETURN. Each successive element of
2213 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2214 ink and logical metrics of successive characters respectively,
2215 relative to the drawing origin of the M-text. The number of
2216 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2217 been set is returned to $NUM_CHARS_RETURN.
2219 If $ARRAY_SIZE is too small to return all metrics, the function
2220 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2221 Otherwise, it returns zero.
2223 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2224 @c NULL, this function also computes the metrics of the overall
2225 text and stores the results in the members of the structure
2226 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2228 If $CONTROL->two_dimensional is nonzero, this function computes
2229 only the metrics of characters in the first line. */
2231 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2233 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2234 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2235 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2236 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2238 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2239 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2240 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2241 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2242 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2244 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2245 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2248 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2249 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2250 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2253 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2254 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2257 mdraw_text_per_char_extents (MFrame *frame,
2258 MText *mt, int from, int to,
2259 MDrawControl *control,
2260 MDrawMetric *ink_array_return,
2261 MDrawMetric *logical_array_return,
2263 int *num_chars_return,
2264 MDrawMetric *overall_ink_return,
2265 MDrawMetric *overall_logical_return)
2267 MGlyphString *gstring;
2271 ASSURE_CONTROL (control);
2272 *num_chars_return = to - from;
2273 if (array_size < *num_chars_return)
2274 MERROR (MERROR_DRAW, -1);
2275 if (overall_logical_return)
2276 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2277 if (overall_ink_return)
2278 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2280 M_CHECK_RANGE (mt, from, to, -1, 0);
2281 gstring = get_gstring (frame, mt, from, to, control);
2284 *num_chars_return = 0;
2288 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2289 if (g->pos >= from && g->pos < to)
2293 int width = g->width;
2294 int lbearing = g->lbearing;
2295 int rbearing = g->rbearing;
2296 int ascent = g->ascent;
2297 int descent = g->descent;
2298 int logical_ascent = g->rface->rfont->ascent;
2299 int logical_descent = g->rface->rfont->descent;
2301 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2303 if (lbearing < width + g->lbearing)
2304 lbearing = width + g->lbearing;
2305 if (rbearing < width + g->rbearing)
2306 rbearing = width + g->rbearing;
2308 if (ascent < g->ascent)
2310 if (descent < g->descent)
2311 descent = g->descent;
2318 ink_array_return[start - from].x = x + lbearing;
2319 ink_array_return[start - from].y = - ascent;
2320 ink_array_return[start - from].width = rbearing - lbearing;
2321 ink_array_return[start - from].height = ascent + descent;
2322 logical_array_return[start - from].x = x;
2323 logical_array_return[start - from].y = - logical_descent;
2324 logical_array_return[start - from].height
2325 = logical_ascent + logical_descent;
2326 logical_array_return[start - from].width = width;
2332 if (overall_ink_return)
2334 overall_ink_return->y = - gstring->line_ascent;
2335 overall_ink_return->x = gstring->lbearing;
2336 overall_ink_return->width = x - gstring->lbearing;
2337 overall_ink_return->height = gstring->height;
2339 if (overall_logical_return)
2341 overall_logical_return->y = - gstring->ascent;
2342 overall_logical_return->x = 0;
2343 overall_logical_return->width = x;
2344 overall_logical_return->height = gstring->ascent + gstring->descent;
2347 M17N_OBJECT_UNREF (gstring->top);
2354 @brief Return the character position nearest to the coordinates.
2356 The mdraw_coordinates_position () function checks which character
2357 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2358 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2359 mdraw_text_with_control () function with the drawing control
2360 object $CONTROL. Here, the character position means the number of
2361 characters that precede the character in question in $MT, that is,
2362 the character position of the first character is 0.
2364 $FRAME is used only to get the default face information.
2367 If the glyph image of a character covers coordinate ($X, $Y),
2368 mdraw_coordinates_position () returns the character position of
2370 If $Y is less than the minimum Y-coordinate of the drawn area, it
2371 returns $FROM.\n\n\n
2372 If $Y is greater than the maximum Y-coordinate of the drawn area,
2373 it returns $TO.\n\n\n
2374 If $Y fits in with the drawn area but $X is less than the minimum
2375 X-coordinate, it returns the character position of the first
2376 character drawn on the line $Y.\n\n\n
2377 If $Y fits in with the drawn area but $X is greater than the
2378 maximum X-coordinate, it returns the character position of the
2379 last character drawn on the line $Y. */
2382 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2384 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2385 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2386 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2387 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2388 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2389 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2391 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2394 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2395 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2397 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2399 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2401 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2402 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2404 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2405 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2408 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2409 int x_offset, int y_offset, MDrawControl *control)
2411 MGlyphString *gstring;
2416 M_CHECK_POS_X (mt, from, -1);
2417 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2418 to = mtext_nchars (mt) + (control->cursor_width != 0);
2424 ASSURE_CONTROL (control);
2425 gstring = get_gstring (frame, mt, from, to, control);
2426 while (y + gstring->line_descent <= y_offset
2427 && gstring->to < to)
2430 y += gstring->line_descent;
2431 M17N_OBJECT_UNREF (gstring->top);
2432 gstring = get_gstring (frame, mt, from, to, control);
2433 y += gstring->line_ascent;
2436 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2437 if (! control->orientation_reversed)
2439 width = gstring->indent;
2440 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2441 if (g->pos >= from && g->pos < to)
2444 if (width > x_offset)
2450 width = - gstring->indent;
2451 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2452 if (g->pos >= from && g->pos < to)
2455 if (width < x_offset)
2460 M17N_OBJECT_UNREF (gstring->top);
2468 @brief Compute information about a glyph.
2470 The mdraw_glyph_info () function computes information about a
2471 glyph that covers a character at position $POS of the M-text $MT
2472 assuming that the text is drawn from the character at $FROM of $MT
2473 on a window of frame $FRAME using the mdraw_text_with_control ()
2474 function with the drawing control object $CONTROL.
2476 The information is stored in the members of $INFO. */
2478 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2480 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2481 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2482 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2483 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2485 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2493 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2494 MDrawControl *control, MDrawGlyphInfo *info)
2496 MGlyphString *gstring;
2500 M_CHECK_RANGE_X (mt, from, pos, -1);
2502 ASSURE_CONTROL (control);
2503 gstring = get_gstring (frame, mt, from, pos + 1, control);
2505 MERROR (MERROR_DRAW, -1);
2506 while (gstring->to <= pos)
2508 y += gstring->line_descent;
2509 M17N_OBJECT_UNREF (gstring->top);
2510 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2511 y += gstring->line_ascent;
2513 info->line_from = gstring->from;
2514 if (info->line_from < from)
2515 info->line_from = from;
2516 info->line_to = gstring->to;
2519 if (! control->orientation_reversed)
2521 info->x = gstring->indent;
2522 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2523 info->x += g->width;
2527 info->x = - gstring->indent;
2528 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2529 info->x -= g->width;
2530 while (g[-1].to == g->to)
2533 info->from = g->pos;
2535 info->glyph_code = g->code;
2536 info->this.x = g->lbearing;
2537 info->this.y = - gstring->line_ascent;
2538 info->this.height = gstring->height;
2539 info->this.width = - g->lbearing + g->width;
2540 if (g->rface->rfont)
2541 info->font = &g->rface->rfont->font;
2544 /* info->logical_width is calculated later. */
2546 if (info->from > info->line_from)
2548 /* The logically previous glyph is on this line. */
2549 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2551 info->prev_from = g_tmp->pos;
2553 else if (info->line_from > 0)
2555 /* The logically previous glyph is on the previous line. */
2556 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2557 gstring->from, control);
2558 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2560 info->prev_from = g_tmp->pos;
2561 M17N_OBJECT_UNREF (gst->top);
2564 info->prev_from = -1;
2566 if (GLYPH_INDEX (g) > 1)
2567 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2568 else if (! control->orientation_reversed)
2570 if (info->line_from > 0)
2574 int p = gstring->from - 1;
2576 gst = get_gstring (frame, mt, p, gstring->from, control);
2577 g_tmp = gst->glyphs + (gst->used - 2);
2578 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2579 M17N_OBJECT_UNREF (gst->top);
2582 info->left_from = info->left_to = -1;
2586 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2590 int p = gstring->to;
2592 gst = get_gstring (frame, mt, p, p + 1, control);
2593 g_tmp = gst->glyphs + (gst->used - 2);
2594 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2595 M17N_OBJECT_UNREF (gst->top);
2598 info->left_from = info->left_to = -1;
2601 if (info->to < gstring->to)
2603 /* The logically next glyph is on this line. */
2604 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2606 info->next_to = g_tmp->to;
2608 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2610 /* The logically next glyph is on the next line. */
2612 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2613 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2615 info->next_to = g_tmp->to;
2616 M17N_OBJECT_UNREF (gst->top);
2621 for (info->logical_width = (g++)->width;
2622 g->pos == pos && g->type != GLYPH_ANCHOR;
2623 info->this.width += g->width, info->logical_width += (g++)->width);
2624 info->this.width += g[-1].rbearing - g[-1].width;
2626 if (g->type != GLYPH_ANCHOR)
2627 info->right_from = g->pos, info->right_to = g->to;
2628 else if (! control->orientation_reversed)
2630 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2633 M17N_OBJECT_UNREF (gstring->top);
2634 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2636 info->right_from = g->pos, info->right_to = g->to;
2639 info->right_from = info->right_to = -1;
2643 if (info->line_from > 0)
2645 pos = gstring->from - 1;
2646 M17N_OBJECT_UNREF (gstring->top);
2647 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2649 info->right_from = g->pos, info->right_to = g->to;
2652 info->right_from = info->right_to = -1;
2655 M17N_OBJECT_UNREF (gstring->top);
2662 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2663 MDrawControl *control, MDrawGlyphInfo *info,
2664 int array_size, int *num_glyphs_return)
2666 MGlyphString *gstring;
2671 ASSURE_CONTROL (control);
2672 *num_glyphs_return = 0;
2673 M_CHECK_RANGE (mt, from, to, -1, 0);
2674 gstring = get_gstring (frame, mt, from, to, control);
2677 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2679 if (g->type == GLYPH_BOX
2680 || g->pos < from || g->pos >= to)
2682 if (g->type == GLYPH_PAD)
2684 if (g->left_padding)
2685 pad_width = g->width;
2689 info[-1].x += g->width;
2690 info[-1].logical_width += g->width;
2696 info->from = g->pos;
2698 info->glyph_code = g->code;
2699 info->x = g->xoff + pad_width;
2701 info->this.x = g->lbearing;
2702 info->this.y = - g->ascent;
2703 info->this.height = g->ascent + g->descent;
2704 info->this.width = g->rbearing - g->lbearing;
2705 info->logical_width = g->width + pad_width;
2706 if (g->rface->rfont)
2707 info->font = &g->rface->rfont->font;
2715 M17N_OBJECT_UNREF (gstring->top);
2717 *num_glyphs_return = n;
2718 return (n <= array_size ? 0 : -1);
2724 @brief Draw one or more textitems.
2726 The mdraw_text_items () function draws one or more M-texts on
2727 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2728 of the textitems to be drawn and $NITEMS is the number of
2729 textimtems in the array. */
2732 @brief textitem ¤òɽ¼¨¤¹¤ë.
2734 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2735 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2736 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2739 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2743 MTextItem, mdraw_text (). */
2746 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2747 MDrawTextItem *items, int nitems)
2749 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2751 while (nitems-- > 0)
2754 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2756 mdraw_text_with_control (frame, win, x, y,
2757 items->mt, 0, mtext_nchars (items->mt),
2759 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2760 items->control, NULL, NULL, NULL);
2763 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2769 @brief calculate a line breaking position.
2771 The function mdraw_default_line_break () calculates a line
2772 breaking position based on the line number $LINE and the
2773 coordinate $Y, when a line is too long to fit within the width
2774 limit. $POS is the position of the character next to the last
2775 one that fits within the limit. $FROM is the position of the
2776 first character of the line, and TO is the position of the last
2777 character displayed on the line if there were not width limit.
2778 LINE and Y are reset to 0 when a line is broken by a newline
2779 character, and incremented each time when a long line is broken
2780 because of the width limit.
2783 This function returns a character position to break the
2788 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2790 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2791 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2792 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2793 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2794 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2795 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2796 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2799 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2803 mdraw_default_line_break (MText *mt, int pos,
2804 int from, int to, int line, int y)
2806 int c = mtext_ref_char (mt, pos);
2809 if (c == ' ' || c == '\t')
2813 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2820 if (c == ' ' || c == '\t')
2823 c = mtext_ref_char (mt, pos);
2836 @brief Obtain per character dimension information.
2838 The mdraw_per_char_extents () function computes the text dimension
2839 of each character in M-text $MT. The faces given as text
2840 properties in $MT and the default face of frame $FRAME determine
2841 the fonts to draw the text. Each successive element in
2842 $ARRAY_RETURN is set to the drawn metrics of successive
2843 characters, which is relative to the origin of the drawing, and a
2844 rectangle for each character in $MT. The number of elements of
2845 $ARRAY_RETURN must be equal to or greater than the number of
2848 If pointer $OVERALL_RETURN is not @c NULL, this function also
2849 computes the extents of the overall text and stores the results in
2850 the members of the structure pointed to by $OVERALL_RETURN. */
2853 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2855 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2856 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2857 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2858 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2859 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2860 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2863 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2864 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2867 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2870 mdraw_per_char_extents (MFrame *frame, MText *mt,
2871 MDrawMetric *array_return,
2872 MDrawMetric *overall_return)
2874 int n = mtext_nchars (mt);
2876 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2877 n, &n, overall_return, NULL);
2881 @brief clear cached information.
2883 The mdraw_clear_cache () function clear cached information
2884 on M-text $MT that was attached by any of the drawing functions.
2885 When the behaviour of `format' or `line_break'
2886 member functions of MDrawControl is changed, the cache must be cleared.
2891 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2893 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2894 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2895 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2896 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2901 mdraw_clear_cache (MText *mt)
2903 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);