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 bidi_sensitive = gstring->control.orientation_reversed;
106 FriBidiCharType base = (gstring->control.orientation_reversed
107 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
108 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
110 FriBidiStrIndex *indices;
111 FriBidiLevel *levels;
112 #else /* not HAVE_FRIBIDI */
113 int *logical = alloca (sizeof (int) * len);
115 char *levels = alloca (len);
116 #endif /* not HAVE_FRIBIDI */
118 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
120 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
122 if (bidi == MbidiR || bidi == MbidiAL
123 || bidi == MbidiRLE || bidi == MbidiRLO)
128 #endif /* not HAVE_FRIBIDI */
133 if (! bidi_sensitive)
136 glyphs = alloca (sizeof (MGlyph) * len);
137 memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
139 visual = alloca (sizeof (FriBidiChar) * (len + 1));
140 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
141 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
143 fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
144 #else /* not HAVE_FRIBIDI */
145 indices = alloca (sizeof (int) * len);
146 for (i = 0; i < len; i++)
152 for (j = i + 1; j < len && levels[j]; j++);
153 for (k = j--; i < k; i++, j--)
160 #endif /* not HAVE_FRIBIDI */
162 for (i = 0; i < len; i++)
169 g->bidi_level = levels[i];
171 if (visual[j] != logical[i])
176 g->code = mfont__encode_char (g->rface->rfont, g->c);
178 #endif /* HAVE_FRIBIDI */
183 reorder_combining_chars (MGlyphString *gstring, int from, int to)
185 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
191 for (g = gbeg; g != gend; g++)
192 if (COMBINING_CODE_CLASS (g->combining_code) > 0
193 && (COMBINING_CODE_CLASS (g[-1].combining_code)
194 > COMBINING_CODE_CLASS (g->combining_code)))
205 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
206 displaying them on FRAME.
208 This function fills members <type>, <rface>, <c>, <pos>, <to>,
209 <code> of glyphs. The other members are filled by
210 layout_glyph_string. */
213 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
214 MGlyphString *gstring)
216 MRealizedFace *default_rface = frame->rface;
217 int stop, face_change, language_change, charset_change;
220 MSymbol language = Mnil, script = Mnil, charset = Mnil;
221 MSymbol non_latin_script = Mnil;
222 MRealizedFace *rface = default_rface;
223 int size = gstring->control.fixed_width;
227 MLIST_RESET (gstring);
228 gstring->from = from;
230 /* At first generate glyphs while using the member <enabled> as a
231 flag for rface re-checking. */
234 /** Put anchor glyphs at the head and tail. */
235 g_tmp.type = GLYPH_ANCHOR;
236 g_tmp.pos = g_tmp.to = from;
238 APPEND_GLYPH (gstring, g_tmp);
240 stop = face_change = charset_change = language_change = pos = from;
247 if (pos < mtext_nchars (mt))
248 c = mtext_ref_char (mt, pos);
251 g_tmp.category = mchar_get_prop (c, Mcategory);
254 /* Short cut for the obvious case. */
255 g_tmp.type = (c == ' ' || c == '\n' || c == '\t'
256 ? GLYPH_SPACE : GLYPH_CHAR);
257 this_script = (MSYMBOL_NAME (g_tmp.category)[0] == 'L'
262 g_tmp.type = GLYPH_CHAR;
263 this_script = (MSymbol) mchar_get_prop (c, Mscript);
264 if (this_script == Minherited || this_script == Mnil)
265 this_script = script;
266 if (this_script == Mnil)
267 this_script = non_latin_script;
268 if (this_script == Mnil)
270 /* Search forward for a character that explicitly
271 specifies a non-latin script. */
275 for (i = pos + 1; i < to; i++)
276 if ((c1 = mtext_ref_char (mt, i)) >= 0x100
277 && (sym = mchar_get_prop (c1, Mscript)) != Mnil
278 && sym != Minherited)
286 if (pos == stop || script != this_script
287 || MGLYPH (last)->type != g_tmp.type)
290 if (g->type != GLYPH_ANCHOR)
291 while (g < gstring->glyphs + gstring->used)
292 g = mface__for_chars (script == Mnil ? Mlatin : script,
294 g, gstring->glyphs + gstring->used, size);
297 last = gstring->used;
298 script = this_script;
299 if (script != Mnil && script != Mlatin)
300 non_latin_script = script;
303 if (pos < mtext_nchars (mt) && pos == language_change)
305 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
306 mtext_prop_range (mt, Mlanguage, pos, NULL,
307 &language_change, 0);
309 if (pos < mtext_nchars (mt) && pos == charset_change)
311 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
312 mtext_prop_range (mt, Mcharset, pos, NULL,
315 if (pos < mtext_nchars (mt) && pos == face_change)
318 int num = mtext_get_prop_values (mt, pos, Mface,
319 (void **) faces, 64);
321 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
323 ? mface__realize (frame, faces, num,
324 language, charset, size)
328 if (stop > language_change)
329 stop = language_change;
330 if (stop > charset_change)
331 stop = charset_change;
332 if (face_change < stop)
342 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
346 ctrl[0] = ctrl[1] = g_tmp;
348 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
349 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
350 APPEND_GLYPH (gstring, ctrl[0]);
351 APPEND_GLYPH (gstring, ctrl[1]);
354 APPEND_GLYPH (gstring, g_tmp);
356 && gstring->control.two_dimensional)
360 /* Append an anchor glyph. */
361 g_tmp.type = GLYPH_ANCHOR;
363 g_tmp.code = MCHAR_INVALID_CODE;
364 g_tmp.pos = g_tmp.to = pos;
366 APPEND_GLYPH (gstring, g_tmp);
370 /* Next, run FLT if necessary. */
371 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
375 if (this->type == GLYPH_CHAR && this->rface->rfont)
379 if (this->rface->rfont->layouter != Mnil)
384 for (prev = MGLYPH (start - 1);
385 (prev->type == GLYPH_CHAR
386 && prev->category == McatCf
387 && (code = mfont__encode_char (this->rface->rfont, prev->c)
388 != MCHAR_INVALID_CODE));
393 (g->type == GLYPH_CHAR
394 && (g->rface->rfont == this->rface->rfont
395 || (g->category == McatCf
396 && ((code = mfont__encode_char (this->rface->rfont,
398 != MCHAR_INVALID_CODE))));
400 if (g->rface->rfont != this->rface->rfont)
402 g->rface->rfont = this->rface->rfont;
405 i = mfont__flt_run (gstring, start, i, this->rface);
409 while (this->type == GLYPH_CHAR
412 && MSYMBOL_NAME (this->category)[0] == 'M'
413 && this->rface->rfont
414 && this->rface->rfont->layouter == Mnil)
416 int class = (int) mchar_get_prop (this->c,
419 = MAKE_COMBINING_CODE_BY_CLASS (class);
423 reorder_combining_chars (gstring, start, i);
424 if (this->type == GLYPH_ANCHOR)
433 /* At last, reorder glyphs visually if necessary. */
434 if (gstring->control.enable_bidi)
435 visual_order (gstring);
440 combining_code_from_class (int class)
445 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
446 else if (class == 200) /* below left attached */
447 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
448 else if (class == 202) /* below attached*/
449 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
450 else if (class == 204) /* below right attached */
451 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
452 else if (class == 208) /* left attached */
453 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
454 else if (class == 210) /* right attached */
455 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
456 else if (class == 212) /* above left attached */
457 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
458 else if (class == 214) /* above attached */
459 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
460 else if (class == 216) /* above right attached */
461 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
462 else if (class == 218) /* below left */
463 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
464 else if (class == 220) /* below */
465 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
466 else if (class == 222) /* below right */
467 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
468 else if (class == 224) /* left */
469 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
470 else if (class == 226) /* right */
471 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
472 else if (class == 228) /* above left */
473 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
474 else if (class == 230) /* above */
475 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
476 else if (class == 232) /* above right */
477 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
478 else if (class == 233) /* double below */
479 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
480 else if (class == 234) /* double above */
481 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
482 else if (class == 240) /* iota subscript */
483 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
485 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
491 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
493 int g_physical_ascent, g_physical_descent;
494 int g_width, g_lbearing, g_rbearing;
495 MGlyph *g = MGLYPH (from);
496 MGlyph *last_g = MGLYPH (to);
499 g_physical_ascent = gstring->physical_ascent;
500 g_physical_descent = gstring->physical_descent;
501 g_width = g_lbearing = g_rbearing = 0;
503 for (i = from; i < to;)
505 if ( MGLYPH (i)->otf_encoded)
511 while (i < to && ! MGLYPH (i)->otf_encoded) i++;
512 mfont__get_metric (gstring, j, i);
520 if (base->combining_code && (base->bidi_level % 2))
522 MGlyph *g1 = base, *g2, temp;
524 while (g->combining_code)
526 for (g2 = g; g1 < g2; g1++, g2--)
527 temp = *g1, *g1 = *g2, *g2 = temp;
535 MRealizedFont *rfont = base->rface->rfont;
536 int size = rfont->font.property[MFONT_SIZE];
537 int width, lbearing, rbearing;
539 if (g == last_g || ! g->combining_code || g->otf_encoded)
542 if (base->width == 0 && GLYPH_INDEX (base) > from)
544 MGlyph *prev = base - 1;
546 if (base->pos < prev->pos)
547 prev->pos = base->pos;
549 base->pos = prev->pos;
550 if (base->to > prev->to)
556 if (base->left_padding && base->lbearing < 0)
558 base->xoff = - base->lbearing;
559 base->width += base->xoff;
560 base->rbearing += base->xoff;
563 if (base->right_padding && base->rbearing > base->width)
565 base->width = base->rbearing;
567 lbearing = (base->xoff + base->lbearing < 0
568 ? base->xoff + base->lbearing : 0);
569 rbearing = base->xoff + base->rbearing;
573 /* With combining glyphs. */
574 int left = -base->width;
576 int top = - base->ascent;
577 int bottom = base->descent;
578 int height = bottom - top;
579 int begin = base->pos;
584 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
585 rbearing = base->rbearing;
587 while (g != last_g && g->combining_code)
589 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
591 combining_code = g->combining_code;
592 if (COMBINING_BY_CLASS_P (combining_code))
593 g->combining_code = combining_code
594 = combining_code_from_class (COMBINING_CODE_CLASS
597 rfont = g->rface->rfont;
598 size = rfont->font.property[MFONT_SIZE];
599 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
601 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
603 base_x = COMBINING_CODE_BASE_X (combining_code);
604 base_y = COMBINING_CODE_BASE_Y (combining_code);
605 add_x = COMBINING_CODE_ADD_X (combining_code);
606 add_y = COMBINING_CODE_ADD_Y (combining_code);
610 else if (end < g->to)
613 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
616 if (g->xoff + g->width > right)
617 right = g->xoff + g->width;
618 width = right - left;
619 if (g->xoff + g->lbearing < left + lbearing)
620 lbearing = g->xoff + g->lbearing - left;
621 if (g->xoff + g->rbearing > left + rbearing)
622 rbearing = g->xoff + g->rbearing - left;
625 g->yoff = top + height * base_y / 2;
629 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
631 if (g->yoff - g->ascent < top)
632 top = g->yoff - g->ascent;
633 if (g->yoff + g->descent > bottom)
634 bottom = g->yoff + g->descent;
635 height = bottom - top;
641 base->ascent = - top;
642 base->descent = bottom;
643 base->lbearing = lbearing;
644 base->rbearing = rbearing;
645 if (left < - base->width)
647 base->xoff = - base->width - left;
648 base->width += base->xoff;
649 base->rbearing += base->xoff;
650 base->lbearing += base->xoff;
654 base->width += right;
655 base->rbearing += right;
656 base->right_padding = 1;
657 for (i = 1; base + i != g; i++)
658 base[i].xoff -= right;
661 for (i = 0; base + i != g; i++)
668 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
669 g_physical_descent = MAX (g_physical_descent, base->descent);
670 g_lbearing = MIN (g_lbearing, g_width + lbearing);
671 g_rbearing = MAX (g_rbearing, g_width + rbearing);
672 g_width += base->width;
675 gstring->physical_ascent = g_physical_ascent;
676 gstring->physical_descent = g_physical_descent;
677 gstring->sub_width = g_width;
678 gstring->sub_lbearing = g_lbearing;
679 gstring->sub_rbearing = g_rbearing;
683 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
684 by this function directly. Character glyphs are handled by
685 layouter functions registered in font drivers.
687 This function fill-in all the remaining members of glyphs. */
690 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
692 /* Default width of TAB. */
693 int tab_width = frame->space_width * (gstring->control.tab_width
694 ? gstring->control.tab_width : 8);
698 MDrawControl *control = &(gstring->control);
701 int box_line_height = 0;
702 int ignore_formatting_char = control->ignore_formatting_char;
704 gstring->ascent = gstring->descent = 0;
705 gstring->physical_ascent = gstring->physical_descent = 0;
706 gstring->width = gstring->lbearing = gstring->rbearing = 0;
710 while (g->type != GLYPH_ANCHOR)
712 if (box != g->rface->box)
714 int gidx = GLYPH_INDEX (g);
718 /* Insert the right side of the box. That glyph belongs
719 to the previous grapheme cluster. */
720 MGlyph box_glyph = g[-1];
722 box_glyph.type = GLYPH_BOX;
724 = (control->fixed_width
726 : box->inner_hmargin + box->width + box->outer_hmargin);
727 box_glyph.lbearing = 0;
728 box_glyph.rbearing = box_glyph.width;
730 box_glyph.right_padding = 1;
731 gstring->width += box_glyph.width;
732 gstring->rbearing += box_glyph.width;
733 INSERT_GLYPH (gstring, gidx, box_glyph);
740 /* Insert the left side of the box. That glyph belongs
741 to the following grapheme cluster. */
742 MGlyph box_glyph = *g;
743 int box_height = (box->width
744 + box->inner_vmargin + box->outer_vmargin);
746 if (box_line_height < box_height)
747 box_line_height = box_height;
748 box_glyph.type = GLYPH_BOX;
750 = (control->fixed_width
752 : box->inner_hmargin + box->width + box->outer_hmargin);
753 box_glyph.lbearing = 0;
754 box_glyph.rbearing = box_glyph.width;
756 box_glyph.left_padding = 1;
757 gstring->width += box_glyph.width;
758 gstring->rbearing += box_glyph.width;
759 INSERT_GLYPH (gstring, gidx, box_glyph);
765 if (g->category == McatCf && ignore_formatting_char)
766 g->type = GLYPH_SPACE;
768 if (g->type == GLYPH_CHAR)
770 MRealizedFace *rface = g->rface;
771 MRealizedFont *rfont = rface->rfont;
773 int from = GLYPH_INDEX (g);
775 for (g++; g->type == GLYPH_CHAR; g++)
776 if (! rfont != ! g->rface->rfont
777 || box != g->rface->box
778 || ((fromg->code == MCHAR_INVALID_CODE)
779 != (g->code == MCHAR_INVALID_CODE))
780 || (g->category == McatCf && ignore_formatting_char))
782 if (rfont && fromg->code != MCHAR_INVALID_CODE)
785 int to = GLYPH_INDEX (g);
787 layout_glyphs (frame, gstring, from, to);
788 extra_width = - gstring->sub_lbearing;
790 && (GLYPH_INDEX (g) > 1
791 || (! control->orientation_reversed && control->align_head)))
795 pad.type = GLYPH_PAD;
798 pad.width = pad.rbearing = extra_width;
799 pad.left_padding = 1;
800 INSERT_GLYPH (gstring, from, pad);
802 gstring->sub_lbearing = 0;
803 gstring->sub_width += extra_width;
804 gstring->sub_rbearing += extra_width;
806 g = MGLYPH (from - 1);
807 if (g->type == GLYPH_SPACE)
809 /* The pad just inserted is absorbed (maybe
810 partially) by the previous space while
811 keeping at least some space width. For the
812 moment, we use the arbitrary width 2-pixel.
813 Perhaps, it should be decided by the current
814 face, or a default value of the current
815 frame, which is, however, not yet
817 if (extra_width + 2 < g->width)
819 g->width -= extra_width;
823 extra_width = g->width - 2;
826 gstring->width -= extra_width;
827 gstring->rbearing -= extra_width;
832 extra_width = gstring->sub_rbearing - gstring->sub_width;
834 && (GLYPH_INDEX (g) < gstring->used - 1
835 || (control->orientation_reversed && control->align_head)))
837 if (g->type == GLYPH_SPACE && box == g->rface->box)
840 pad.type = GLYPH_PAD;
843 pad.width = pad.rbearing = extra_width;
844 INSERT_GLYPH (gstring, to, pad);
847 g[-1].width += extra_width;
848 gstring->sub_width += extra_width;
851 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
852 gstring->lbearing = gstring->width + gstring->sub_lbearing;
853 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
854 gstring->rbearing = gstring->width + gstring->sub_rbearing;
855 gstring->width += gstring->sub_width;
856 if (gstring->ascent < rface->ascent)
857 gstring->ascent = rface->ascent;
858 if (gstring->descent < rface->descent)
859 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;
1034 && gstring->from <= control->cursor_pos - 1
1035 && gstring->to > control->cursor_pos - 1)
1036 prev_pos = control->cursor_pos - 1;
1039 *from_idx = *to_idx = 0;
1040 while (g->type != GLYPH_ANCHOR)
1042 if (g->pos >= from && g->pos < to)
1044 MGlyph *fromg = g, *cursor = NULL;
1045 MRealizedFace *rface = g->rface;
1047 int cursor_width = 0;
1051 *from_idx = GLYPH_INDEX (g);
1052 while (g->pos >= from && g->pos < to
1053 && g->rface == rface)
1056 if (g->type != GLYPH_BOX
1057 && g->pos <= cursor_pos && g->to > cursor_pos)
1060 cursor = g, cursor_x = x + width;
1061 cursor_width += g->width;
1063 width += g++->width;
1066 && (control->as_image
1067 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1069 int this_x = x, this_width = width;
1071 if (fromg->type == GLYPH_BOX)
1072 this_x += fromg->width, this_width -= fromg->width;
1073 if (g[-1].type == GLYPH_BOX)
1074 this_width -= g[-1].width;
1075 (frame->driver->fill_space)
1076 (frame, win, rface, 0,
1077 this_x, y - gstring->text_ascent, this_width,
1078 gstring->text_ascent + gstring->text_descent,
1079 control->clip_region);
1086 rect.y = y - gstring->text_ascent;
1087 rect.height = gstring->text_ascent + gstring->text_descent;
1090 rect.width = ((control->cursor_width > 0
1091 && control->cursor_width < cursor_width)
1092 ? control->cursor_width : cursor_width);
1096 if (cursor->bidi_level % 2)
1097 rect.x += cursor_width - rect.width;
1098 (*frame->driver->fill_space)
1099 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1100 control->clip_region);
1102 region = (*frame->driver->region_from_rect) (&rect);
1104 (*frame->driver->region_add_rect) (region, &rect);
1107 if (cursor->bidi_level % 2)
1110 rect.width = cursor_width < 4 ? cursor_width : 4;
1111 (*frame->driver->fill_space)
1112 (frame, win, rface, 1,
1113 rect.x, rect.y, rect.width, rect.height,
1114 control->clip_region);
1115 (*frame->driver->region_add_rect) (region, &rect);
1127 if (fromg->type != GLYPH_BOX
1128 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1131 cursor = fromg, cursor_x = x + temp_width;
1132 cursor_width += fromg->width;
1134 temp_width += fromg++->width;
1141 if (! (cursor->bidi_level % 2))
1142 rect.x += cursor_width - 1;
1143 rect.y = y - gstring->text_ascent;
1144 rect.height = gstring->text_ascent + gstring->text_descent;
1146 (*frame->driver->fill_space)
1147 (frame, win, rface, 1,
1148 rect.x, rect.y, rect.width, rect.height,
1149 control->clip_region);
1151 region = (*frame->driver->region_from_rect) (&rect);
1153 (*frame->driver->region_add_rect) (region, &rect);
1154 rect.y += rect.height - 2;
1156 rect.width = cursor_width < 4 ? cursor_width : 4;
1157 if (! (cursor->bidi_level % 2))
1158 rect.x -= rect.width - 1;
1159 (*frame->driver->fill_space) (frame, win, rface, 1,
1160 rect.x, rect.y, rect.width, rect.height,
1161 control->clip_region);
1162 (*frame->driver->region_add_rect) (region, &rect);
1166 *to_idx = GLYPH_INDEX (g);
1176 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1177 MGlyphString *gstring, int from_idx, int to_idx,
1178 int reverse, MDrawRegion region)
1180 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1186 (*frame->driver->region_to_rect) (region, &rect);
1189 while (g != gend && x + g->rbearing <= rect.x)
1192 width -= g++->width;
1193 while (! g->enabled && g != gend)
1197 rect.x += rect.width;
1198 if (rect.x < x + width)
1201 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1203 width -= (--gend)->width;
1204 while (! gend->enabled && g != gend)
1208 while (gend[-1].to == gend->to) gend++;
1216 MRealizedFace *rface = g->rface;
1217 int width = g->width;
1218 MGlyph *from_g = g++;
1220 /* Handle the glyphs of the same type/face at once. */
1222 && g->type == from_g->type
1223 && g->rface == rface
1224 && ((g->code == MCHAR_INVALID_CODE)
1225 == (from_g->code == MCHAR_INVALID_CODE))
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);