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 forward for a character that explicitly
286 specifies a script. */
287 for (i = pos + 1; i < to; 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)
301 if (pos == stop || script != this_script
302 || MGLYPH (last)->type != g_tmp.type)
305 if (g->type != GLYPH_ANCHOR)
306 while (g < gstring->glyphs + gstring->used)
307 g = mface__for_chars (script, language, charset,
308 g, gstring->glyphs + gstring->used, size);
311 last = gstring->used;
312 script = this_script;
315 if (pos < mtext_nchars (mt) && pos == language_change)
317 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
318 mtext_prop_range (mt, Mlanguage, pos, NULL,
319 &language_change, 0);
321 if (pos < mtext_nchars (mt) && pos == charset_change)
323 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
324 mtext_prop_range (mt, Mcharset, pos, NULL,
327 if (pos < mtext_nchars (mt) && pos == face_change)
330 int num = mtext_get_prop_values (mt, pos, Mface,
331 (void **) faces, 64);
333 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
335 ? mface__realize (frame, faces, num,
336 language, charset, size)
340 if (stop > language_change)
341 stop = language_change;
342 if (stop > charset_change)
343 stop = charset_change;
344 if (face_change < stop)
354 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
358 ctrl[0] = ctrl[1] = g_tmp;
360 ctrl[1].c = c < ' ' ? c + 0x40 : '?';
361 mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
362 APPEND_GLYPH (gstring, ctrl[0]);
363 APPEND_GLYPH (gstring, ctrl[1]);
366 APPEND_GLYPH (gstring, g_tmp);
368 && gstring->control.two_dimensional)
372 /* Append an anchor glyph. */
373 g_tmp.type = GLYPH_ANCHOR;
375 g_tmp.code = MCHAR_INVALID_CODE;
376 g_tmp.pos = g_tmp.to = pos;
378 APPEND_GLYPH (gstring, g_tmp);
382 /* Next, run FLT if necessary. */
383 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
387 if (this->type == GLYPH_CHAR && this->rface->rfont)
391 if (this->rface->rfont->layouter != Mnil)
396 for (prev = MGLYPH (start - 1);
397 (prev->type == GLYPH_CHAR
398 && prev->category == McatCf
399 && (code = mfont__encode_char (this->rface->rfont, prev->c)
400 != MCHAR_INVALID_CODE));
405 (g->type == GLYPH_CHAR
406 && (g->rface->rfont == this->rface->rfont
407 || (g->category == McatCf
408 && ((code = mfont__encode_char (this->rface->rfont,
410 != MCHAR_INVALID_CODE))));
412 if (g->rface->rfont != this->rface->rfont)
414 g->rface->rfont = this->rface->rfont;
417 i = mfont__flt_run (gstring, start, i, this->rface);
421 while (this->type == GLYPH_CHAR
424 && MSYMBOL_NAME (this->category)[0] == 'M'
425 && this->rface->rfont
426 && this->rface->rfont->layouter == Mnil)
428 int class = (int) mchar_get_prop (this->c,
431 = MAKE_COMBINING_CODE_BY_CLASS (class);
435 reorder_combining_chars (gstring, start, i);
436 if (this->type == GLYPH_ANCHOR)
445 /* At last, reorder glyphs visually if necessary. */
446 if (gstring->control.enable_bidi)
447 visual_order (gstring);
452 combining_code_from_class (int class)
457 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
458 else if (class == 200) /* below left attached */
459 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
460 else if (class == 202) /* below attached*/
461 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
462 else if (class == 204) /* below right attached */
463 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
464 else if (class == 208) /* left attached */
465 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
466 else if (class == 210) /* right attached */
467 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
468 else if (class == 212) /* above left attached */
469 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
470 else if (class == 214) /* above attached */
471 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
472 else if (class == 216) /* above right attached */
473 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
474 else if (class == 218) /* below left */
475 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
476 else if (class == 220) /* below */
477 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
478 else if (class == 222) /* below right */
479 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
480 else if (class == 224) /* left */
481 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
482 else if (class == 226) /* right */
483 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
484 else if (class == 228) /* above left */
485 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
486 else if (class == 230) /* above */
487 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
488 else if (class == 232) /* above right */
489 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
490 else if (class == 233) /* double below */
491 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
492 else if (class == 234) /* double above */
493 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
494 else if (class == 240) /* iota subscript */
495 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
497 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
503 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
505 int g_physical_ascent, g_physical_descent;
506 int g_width, g_lbearing, g_rbearing;
507 MGlyph *g = MGLYPH (from);
508 MGlyph *last_g = MGLYPH (to);
510 g_physical_ascent = gstring->physical_ascent;
511 g_physical_descent = gstring->physical_descent;
512 g_width = g_lbearing = g_rbearing = 0;
514 mfont__get_metric (gstring, from, to);
523 while (g < last_g && base->otf_cmd == g->otf_cmd) g++;
524 mfont__ft_drive_gpos (gstring, GLYPH_INDEX (base), GLYPH_INDEX (g));
533 MRealizedFont *rfont = base->rface->rfont;
534 int size = rfont->font.property[MFONT_SIZE];
535 int width, lbearing, rbearing;
537 if (g == last_g || ! g->combining_code)
540 if (base->left_padding && base->lbearing < 0)
542 base->xoff = - base->lbearing;
543 base->width += base->xoff;
544 base->rbearing += base->xoff;
547 if (base->right_padding && base->rbearing > base->width)
549 base->width = base->rbearing;
551 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
552 rbearing = base->rbearing;
556 /* With combining glyphs. */
557 int left = -base->width;
559 int top = - base->ascent;
560 int bottom = base->descent;
561 int height = bottom - top;
562 int begin = base->pos;
567 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
568 rbearing = base->rbearing;
570 while (g != last_g && g->combining_code)
572 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
574 combining_code = g->combining_code;
575 if (COMBINING_BY_CLASS_P (combining_code))
576 g->combining_code = combining_code
577 = combining_code_from_class (COMBINING_CODE_CLASS
580 rfont = g->rface->rfont;
581 size = rfont->font.property[MFONT_SIZE];
582 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
584 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
586 base_x = COMBINING_CODE_BASE_X (combining_code);
587 base_y = COMBINING_CODE_BASE_Y (combining_code);
588 add_x = COMBINING_CODE_ADD_X (combining_code);
589 add_y = COMBINING_CODE_ADD_Y (combining_code);
593 else if (end < g->to)
596 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
599 if (g->xoff + g->width > right)
600 right = g->xoff + g->width;
601 width = right - left;
602 if (g->xoff + g->lbearing < left + lbearing)
603 lbearing = g->xoff + g->lbearing - left;
604 if (g->xoff + g->rbearing > left + rbearing)
605 rbearing = g->xoff + g->rbearing - left;
608 g->yoff = top + height * base_y / 2;
612 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
614 if (g->yoff - g->ascent < top)
615 top = g->yoff - g->ascent;
616 if (g->yoff + g->descent > bottom)
617 bottom = g->yoff + g->descent;
618 height = bottom - top;
624 base->ascent = - top;
625 base->descent = bottom;
626 base->lbearing = lbearing;
627 base->rbearing = rbearing;
628 if (left < - base->width)
630 base->xoff = - base->width - left;
631 base->width += base->xoff;
632 base->rbearing += base->xoff;
633 base->lbearing += base->xoff;
637 base->width += right;
638 base->rbearing += right;
639 base->right_padding = 1;
640 for (i = 1; base + i != g; i++)
641 base[i].xoff -= right;
644 for (i = 0; base + i != g; i++)
651 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
652 g_physical_descent = MAX (g_physical_descent, base->descent);
653 g_lbearing = MIN (g_lbearing, g_width + lbearing);
654 g_rbearing = MAX (g_rbearing, g_width + rbearing);
655 g_width += base->width;
658 gstring->physical_ascent = g_physical_ascent;
659 gstring->physical_descent = g_physical_descent;
660 gstring->sub_width = g_width;
661 gstring->sub_lbearing = g_lbearing;
662 gstring->sub_rbearing = g_rbearing;
666 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
667 by this function directly. Character glyphs are handled by
668 layouter functions registered in font drivers.
670 This function fill-in all the remaining members of glyphs. */
673 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
675 /* Default width of TAB. */
676 int tab_width = frame->space_width * (gstring->control.tab_width
677 ? gstring->control.tab_width : 8);
681 MDrawControl *control = &(gstring->control);
684 int box_line_height = 0;
685 int ignore_formatting_char = control->ignore_formatting_char;
687 gstring->ascent = gstring->descent = 0;
688 gstring->physical_ascent = gstring->physical_descent = 0;
689 gstring->width = gstring->lbearing = gstring->rbearing = 0;
693 while (g->type != GLYPH_ANCHOR)
695 if (box != g->rface->box)
697 int gidx = GLYPH_INDEX (g);
701 /* Insert the right side of the box. That glyph belongs
702 to the previous grapheme cluster. */
703 MGlyph box_glyph = g[-1];
705 box_glyph.type = GLYPH_BOX;
707 = (control->fixed_width
709 : box->inner_hmargin + box->width + box->outer_hmargin);
710 box_glyph.lbearing = 0;
711 box_glyph.rbearing = box_glyph.width;
713 box_glyph.right_padding = 1;
714 gstring->width += box_glyph.width;
715 gstring->rbearing += box_glyph.width;
716 INSERT_GLYPH (gstring, gidx, box_glyph);
723 /* Insert the left side of the box. That glyph belongs
724 to the following grapheme cluster. */
725 MGlyph box_glyph = *g;
726 int box_height = (box->width
727 + box->inner_vmargin + box->outer_vmargin);
729 if (box_line_height < box_height)
730 box_line_height = box_height;
731 box_glyph.type = GLYPH_BOX;
733 = (control->fixed_width
735 : box->inner_hmargin + box->width + box->outer_hmargin);
736 box_glyph.lbearing = 0;
737 box_glyph.rbearing = box_glyph.width;
739 box_glyph.left_padding = 1;
740 gstring->width += box_glyph.width;
741 gstring->rbearing += box_glyph.width;
742 INSERT_GLYPH (gstring, gidx, box_glyph);
748 if (g->category == McatCf && ignore_formatting_char)
749 g->type = GLYPH_SPACE;
751 if (g->type == GLYPH_CHAR)
753 MRealizedFace *rface = g->rface;
754 MRealizedFont *rfont = rface->rfont;
756 int from = GLYPH_INDEX (g);
758 for (g++; g->type == GLYPH_CHAR; g++)
759 if (! rfont != ! g->rface->rfont
760 || box != g->rface->box
761 || ((fromg->code == MCHAR_INVALID_CODE)
762 != (g->code == MCHAR_INVALID_CODE))
763 || (g->category == McatCf && ignore_formatting_char))
765 if (rfont && fromg->code != MCHAR_INVALID_CODE)
768 int to = GLYPH_INDEX (g);
770 layout_glyphs (frame, gstring, from, to);
771 extra_width = - gstring->sub_lbearing;
773 && (GLYPH_INDEX (g) > 1
774 || control->align_head))
778 pad.type = GLYPH_PAD;
781 pad.width = pad.rbearing = extra_width;
782 INSERT_GLYPH (gstring, from, pad);
784 gstring->sub_lbearing = 0;
785 gstring->sub_width += extra_width;
786 gstring->sub_rbearing += extra_width;
788 g = MGLYPH (from - 1);
789 if (g->type == GLYPH_SPACE)
791 /* The pad just inserted is absorbed (maybe
792 partially) by the previous space while
793 keeping at least some space width. For the
794 moment, we use the arbitrary width 2-pixel.
795 Perhaps, it should be decided by the current
796 face, or a default value of the current
797 frame, which is, however, not yet
799 if (extra_width + 2 < g->width)
801 g->width -= extra_width;
805 extra_width -= g->width - 2;
808 gstring->width -= extra_width;
809 gstring->rbearing -= extra_width;
813 extra_width = gstring->sub_rbearing - gstring->sub_width;
817 if (g->type == GLYPH_SPACE && box == g->rface->box)
821 pad.type = GLYPH_PAD;
824 pad.width = pad.rbearing = extra_width;
825 INSERT_GLYPH (gstring, to, pad);
829 g[-1].width += extra_width;
830 gstring->sub_width += extra_width;
833 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
834 gstring->lbearing = gstring->width + gstring->sub_lbearing;
835 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
836 gstring->rbearing = gstring->width + gstring->sub_rbearing;
837 gstring->width += gstring->sub_width;
838 if (gstring->ascent < rface->ascent)
839 gstring->ascent = rface->ascent;
840 if (gstring->descent < rface->descent)
841 gstring->descent = rface->descent;
846 for (; fromg < g; fromg++)
848 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
849 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
850 fromg->width = fromg->rbearing = 1;
852 fromg->width = fromg->rbearing = rface->space_width;
853 fromg->xoff = fromg->lbearing = 0;
854 fromg->ascent = fromg->descent = 0;
855 gstring->width += fromg->width;
856 gstring->rbearing += fromg->width;
858 if (gstring->ascent < frame->rface->ascent)
859 gstring->ascent = frame->rface->ascent;
860 if (gstring->descent < frame->descent)
861 gstring->descent = frame->rface->descent;
864 else if (g->type == GLYPH_SPACE)
867 g->width = g->rface->space_width;
868 else if (g->c == '\n')
870 g->width = control->cursor_width;
873 if (control->cursor_bidi)
875 else if (g->width < 0)
876 g->width = g->rface->space_width;
879 else if (g->c == '\t')
881 g->width = tab_width - ((gstring->indent + gstring->width)
887 if (g[-1].type == GLYPH_PAD)
889 /* This space glyph absorbs (maybe partially) the
890 previous padding glyph. */
891 g->width -= g[-1].width;
893 /* But, keep at least some space width. For the
894 moment, we use the arbitrary width 2-pixel. */
897 g->rbearing = g->width;
898 gstring->width += g->width;
899 gstring->rbearing += g->width;
902 if (gstring->ascent < g->rface->ascent)
903 gstring->ascent = g->rface->ascent;
904 if (gstring->descent < g->rface->descent)
905 gstring->descent = g->rface->descent;
911 gstring->width += g->width;
912 gstring->rbearing += g->width;
919 /* Insert the right side of the box. */
920 int gidx = GLYPH_INDEX (g);
921 MGlyph box_glyph = g[-1];
923 box_glyph.type = GLYPH_BOX;
925 = (control->fixed_width
927 : box->inner_hmargin + box->width + box->outer_hmargin);
928 box_glyph.lbearing = 0;
929 box_glyph.rbearing = box_glyph.width;
931 box_glyph.right_padding = 1;
932 gstring->width += box_glyph.width;
933 gstring->rbearing += box_glyph.width;
934 INSERT_GLYPH (gstring, gidx, box_glyph);
937 gstring->text_ascent = gstring->ascent;
938 gstring->text_descent = gstring->descent;
939 if (gstring->text_ascent < gstring->physical_ascent)
940 gstring->text_ascent = gstring->physical_ascent;
941 if (gstring->text_descent < gstring->physical_descent)
942 gstring->text_descent = gstring->physical_descent;
943 gstring->line_ascent = gstring->text_ascent;
944 gstring->line_descent = gstring->text_descent;
945 if (box_line_height > 0)
947 gstring->line_ascent += box_line_height;
948 gstring->physical_ascent = gstring->line_ascent;
949 gstring->line_descent += box_line_height;
950 gstring->physical_descent = gstring->line_descent;
953 if (gstring->line_ascent < control->min_line_ascent)
954 gstring->line_ascent = control->min_line_ascent;
955 else if (control->max_line_ascent
956 && control->max_line_ascent > control->min_line_ascent
957 && gstring->line_ascent > control->max_line_ascent)
958 gstring->line_ascent = control->max_line_ascent;
960 if (gstring->line_descent < control->min_line_descent)
961 gstring->line_descent = control->min_line_descent;
962 else if (control->max_line_descent
963 && control->max_line_descent > control->min_line_descent
964 && gstring->line_descent > control->max_line_descent)
965 gstring->line_descent = control->max_line_descent;
966 gstring->height = gstring->line_ascent + gstring->line_descent;
968 if (control->orientation_reversed
971 /* We must adjust TAB width for RTL orientation. */
972 width = gstring->indent;
974 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
976 if (g->type == GLYPH_CHAR && g->c == '\t')
978 int this_width = tab_width - (width % tab_width);
980 if (g[1].type == GLYPH_PAD)
981 this_width -= g[1].width;
982 if (g[-1].type == GLYPH_PAD)
983 this_width -= g[-1].width;
986 gstring->width += this_width - g->width;
987 gstring->rbearing += this_width - g->width;
988 g->width = this_width;
999 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1000 MGlyphString *gstring, int from, int to,
1001 int *from_idx, int *to_idx, int *to_x)
1003 MGlyph *g = MGLYPH (1);
1004 MDrawRegion region = (MDrawRegion) NULL;
1005 MDrawControl *control = &gstring->control;
1006 int cursor_pos = -1;
1008 int cursor_bidi = control->cursor_bidi;
1010 if (control->with_cursor && control->cursor_width)
1012 if (gstring->from <= control->cursor_pos
1013 && gstring->to > control->cursor_pos)
1014 cursor_pos = control->cursor_pos;
1016 && gstring->from <= control->cursor_pos - 1
1017 && gstring->to > control->cursor_pos - 1)
1018 prev_pos = control->cursor_pos - 1;
1021 *from_idx = *to_idx = 0;
1022 while (g->type != GLYPH_ANCHOR)
1024 if (g->pos >= from && g->pos < to)
1026 MGlyph *fromg = g, *cursor = NULL;
1027 MRealizedFace *rface = g->rface;
1029 int cursor_width = 0;
1033 *from_idx = GLYPH_INDEX (g);
1034 while (g->pos >= from && g->pos < to
1035 && g->rface == rface)
1038 if (g->type != GLYPH_BOX
1039 && g->pos <= cursor_pos && g->to > cursor_pos)
1042 cursor = g, cursor_x = x + width;
1043 cursor_width += g->width;
1045 width += g++->width;
1048 && (control->as_image
1049 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1051 int this_x = x, this_width = width;
1053 if (fromg->type == GLYPH_BOX)
1054 this_x += fromg->width, this_width -= fromg->width;
1055 if (g[-1].type == GLYPH_BOX)
1056 this_width -= g[-1].width;
1057 (frame->driver->fill_space)
1058 (frame, win, rface, 0,
1059 this_x, y - gstring->text_ascent, this_width,
1060 gstring->text_ascent + gstring->text_descent,
1061 control->clip_region);
1068 rect.y = y - gstring->text_ascent;
1069 rect.height = gstring->text_ascent + gstring->text_descent;
1072 rect.width = ((control->cursor_width > 0
1073 && control->cursor_width < cursor_width)
1074 ? control->cursor_width : cursor_width);
1078 if (cursor->bidi_level % 2)
1079 rect.x += cursor_width - 1;
1082 (*frame->driver->fill_space)
1083 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1084 control->clip_region);
1086 region = (*frame->driver->region_from_rect) (&rect);
1088 (*frame->driver->region_add_rect) (region, &rect);
1091 if (cursor->bidi_level % 2)
1094 rect.width = cursor_width < 4 ? cursor_width : 4;
1095 (*frame->driver->fill_space)
1096 (frame, win, rface, 1,
1097 rect.x, rect.y, rect.width, rect.height,
1098 control->clip_region);
1099 (*frame->driver->region_add_rect) (region, &rect);
1111 if (fromg->type != GLYPH_BOX
1112 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1115 cursor = fromg, cursor_x = x + temp_width;
1116 cursor_width += fromg->width;
1118 temp_width += fromg++->width;
1125 if (! (cursor->bidi_level % 2))
1126 rect.x += cursor_width - 1;
1127 rect.y = y - gstring->text_ascent;
1128 rect.height = gstring->text_ascent + gstring->text_descent;
1130 (*frame->driver->fill_space)
1131 (frame, win, rface, 1,
1132 rect.x, rect.y, rect.width, rect.height,
1133 control->clip_region);
1135 region = (*frame->driver->region_from_rect) (&rect);
1137 (*frame->driver->region_add_rect) (region, &rect);
1138 rect.y += rect.height - 2;
1140 rect.width = cursor_width < 4 ? cursor_width : 4;
1141 if (! (cursor->bidi_level % 2))
1142 rect.x -= rect.width - 1;
1143 (*frame->driver->fill_space) (frame, win, rface, 1,
1144 rect.x, rect.y, rect.width, rect.height,
1145 control->clip_region);
1146 (*frame->driver->region_add_rect) (region, &rect);
1150 *to_idx = GLYPH_INDEX (g);
1160 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1161 MGlyphString *gstring, int from_idx, int to_idx,
1162 int reverse, MDrawRegion region)
1164 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1170 (*frame->driver->region_to_rect) (region, &rect);
1173 while (g != gend && x + g->rbearing <= rect.x)
1176 width -= g++->width;
1177 while (! g->enabled && g != gend)
1181 rect.x += rect.width;
1182 if (rect.x < x + width)
1185 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1187 width -= (--gend)->width;
1188 while (! gend->enabled && g != gend)
1192 while (gend[-1].to == gend->to) gend++;
1200 MRealizedFace *rface = g->rface;
1201 int width = g->width;
1202 MGlyph *from_g = g++;
1204 /* Handle the glyphs of the same type/face at once. */
1206 && g->type == from_g->type
1207 && g->rface == rface
1208 && (g->code < 0) == (from_g->code < 0)
1210 width += g++->width;
1212 if (from_g->type == GLYPH_CHAR)
1214 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1215 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1218 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1221 else if (from_g->type == GLYPH_BOX)
1223 /* Draw the left or right side of a box. If
1224 from_g->lbearing is nonzero, this is the left side,
1225 else this is the right side. */
1226 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1229 if (from_g->type != GLYPH_BOX)
1232 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1233 x, y, width, region);
1236 /* Draw the top and bottom side of a box. */
1237 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1238 x, y, width, region);
1249 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1250 int *from_x, int *to_x)
1253 int left_idx = *left, right_idx = *right;
1254 int left_x, right_x, x;
1256 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1259 if (x + g->rbearing > 0)
1261 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1263 left_idx = GLYPH_INDEX (g);
1268 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1271 if (x - g->width + g->lbearing < 0)
1273 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1275 right_idx = GLYPH_INDEX (g) + 1;
1280 if (*left == left_idx && *right == right_idx)
1283 if (*left != left_idx)
1285 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1290 if (*right != right_idx)
1292 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1302 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1307 if (from <= gstring->from && to >= gstring->to)
1310 *rbearing = gstring->rbearing;
1311 return gstring->width;
1316 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1317 if (g->pos >= from && g->pos < to)
1319 if (rbearing && width + g->rbearing > *rbearing)
1320 *rbearing = width + g->rbearing;
1328 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1329 MGlyphString *gstring, int from, int to)
1331 MDrawControl *control = &gstring->control;
1333 MDrawRegion clip_region, cursor_region;
1334 int from_idx, to_idx;
1337 if (control->orientation_reversed)
1338 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1340 x += gstring->indent;
1342 /* At first, draw all glyphs without cursor. */
1343 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1344 &from_idx, &to_idx, &to_x);
1346 if (control->partial_update)
1349 rect.width = to_x - x;
1350 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1352 rect.y = y - gstring->line_ascent;
1353 rect.height = gstring->height;
1354 clip_region = (*frame->driver->region_from_rect) (&rect);
1355 if (control->clip_region)
1356 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1359 clip_region = control->clip_region;
1362 clip_region = control->clip_region;
1364 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1369 (*frame->driver->intersect_region) (cursor_region, clip_region);
1370 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1373 if (clip_region != control->clip_region)
1374 (*frame->driver->free_region) (clip_region);
1376 (*frame->driver->free_region) (cursor_region);
1380 static int gstring_num;
1383 free_gstring (void *object)
1385 MGlyphString *gstring = (MGlyphString *) object;
1388 free_gstring (gstring->next);
1389 if (gstring->size > 0)
1390 free (gstring->glyphs);
1396 static MGlyphString scratch_gstring;
1398 static MGlyphString *
1399 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1402 MGlyphString *gstring;
1404 if (pos == mt->nchars)
1406 gstring = &scratch_gstring;
1410 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1411 MLIST_INIT1 (gstring, glyphs, 128);
1415 gstring->frame = frame;
1416 gstring->tick = frame->tick;
1417 gstring->top = gstring;
1419 gstring->control = *control;
1420 gstring->indent = gstring->width_limit = 0;
1421 if (control->format)
1422 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1424 gstring->width_limit = control->max_line_width;
1425 gstring->anti_alias = control->anti_alias;
1429 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1432 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1440 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1441 a width of glyphs for the character at I of GSTRING->mt. If I is
1442 not a beginning of a grapheme cluster, the corresponding element
1444 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1445 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1446 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1447 pos_width[g->pos - gstring->from] += g->width;
1448 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1450 if (pos_width[i] > 0)
1452 if (width + pos_width[i] > gstring->width_limit)
1455 width += pos_width[i];
1458 pos = gstring->from + i;
1459 if (gstring->control.line_break)
1461 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1462 gstring->from, gstring->to, 0, 0);
1463 if (pos <= gstring->from || pos >= gstring->to)
1466 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1467 layout_glyph_string (frame, gstring);
1471 /* Return a gstring that covers a character at POS. */
1473 static MGlyphString *
1474 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1476 MGlyphString *gstring = NULL;
1478 if (pos < mtext_nchars (mt))
1480 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1483 && ((prop->start != 0
1484 && mtext_ref_char (mt, prop->start - 1) != '\n')
1485 || (prop->end < mtext_nchars (mt)
1486 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1488 mtext_detach_property (prop);
1493 gstring = prop->val;
1494 if (gstring->frame != frame
1495 || gstring->tick != frame->tick
1496 || memcmp (control, &gstring->control,
1497 (char *) (&control->with_cursor)
1498 - (char *) (control)))
1500 mtext_detach_property (prop);
1505 else if (! control->cursor_width)
1513 offset = mtext_character (mt, pos, 0, '\n');
1518 offset -= gstring->from;
1520 for (gst = gstring; gst; gst = gst->next)
1524 gst->from += offset;
1526 for (i = 0; i < gst->used; i++)
1528 gst->glyphs[i].pos += offset;
1529 gst->glyphs[i].to += offset;
1532 M17N_OBJECT_REF (gstring);
1537 int line = 0, y = 0;
1539 if (control->two_dimensional)
1541 beg = mtext_character (mt, pos, 0, '\n');
1546 end = mtext_nchars (mt) + (control->cursor_width != 0);
1553 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1554 compose_glyph_string (frame, mt, beg, end, gstring);
1555 layout_glyph_string (frame, gstring);
1557 if (control->two_dimensional
1558 && gstring->width_limit
1559 && gstring->width > gstring->width_limit)
1561 MGlyphString *gst = gstring;
1563 truncate_gstring (frame, mt, gst);
1564 while (gst->to < end)
1566 line++, y += gst->height;
1567 gst->next = alloc_gstring (frame, mt, gst->from, control,
1569 gst->next->top = gstring;
1570 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1572 layout_glyph_string (frame, gst);
1573 if (gst->width <= gst->width_limit)
1575 truncate_gstring (frame, mt, gst);
1579 if (! control->disable_caching && pos < mtext_nchars (mt))
1581 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1582 MTEXTPROP_VOLATILE_STRONG);
1584 if (end > mtext_nchars (mt))
1585 end = mtext_nchars (mt);
1586 mtext_attach_property (mt, beg, end, prop);
1587 M17N_OBJECT_UNREF (prop);
1591 while (gstring->to <= pos)
1593 if (! gstring->next)
1595 gstring = gstring->next;
1597 gstring->control = *control;
1603 static MDrawControl control_noop;
1605 #define ASSURE_CONTROL(control) \
1607 control = &control_noop; \
1612 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1613 MText *mt, int from, int to,
1614 MDrawControl *control)
1616 MGlyphString *gstring;
1618 M_CHECK_POS_X (mt, from, -1);
1619 ASSURE_CONTROL (control);
1620 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1621 to = mtext_nchars (mt) + (control->cursor_width != 0);
1625 gstring = get_gstring (frame, mt, from, to, control);
1627 MERROR (MERROR_DRAW, -1);
1628 render_glyph_string (frame, win, x, y, gstring, from, to);
1632 y += gstring->line_descent;
1633 M17N_OBJECT_UNREF (gstring->top);
1634 gstring = get_gstring (frame, mt, from, to, control);
1635 y += gstring->line_ascent;
1636 render_glyph_string (frame, win, x, y, gstring, from, to);
1639 M17N_OBJECT_UNREF (gstring->top);
1646 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1652 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1653 if (g->pos <= pos && g->to > pos)
1658 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1659 if (g->pos <= pos && g->to > pos)
1666 /* for debugging... */
1670 dump_combining_code (int code)
1672 char *vallign = "tcbB";
1673 char *hallign = "lcr";
1679 if (COMBINING_BY_CLASS_P (code))
1680 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1681 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1682 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1683 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1684 off_x = COMBINING_CODE_OFF_X (code) - 128;
1686 sprintf (work + 2, "+%d", off_y);
1688 sprintf (work + 2, "%d", off_y);
1689 else if (off_x == 0)
1690 sprintf (work + 2, ".");
1691 p = work + strlen (work);
1693 sprintf (p, ">%d", off_x);
1695 sprintf (p, "<%d", -off_x);
1697 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1698 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1704 dump_gstring (MGlyphString *gstring, int indent)
1706 char *prefix = (char *) alloca (indent + 1);
1707 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1709 memset (prefix, 32, indent);
1712 fprintf (stderr, "(glyph-string");
1714 for (g = MGLYPH (0); g < last_g; g++)
1716 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1718 g - gstring->glyphs,
1719 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1720 : g->type == GLYPH_ANCHOR ? "ANC"
1721 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1722 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1723 dump_combining_code (g->combining_code),
1724 g->width, g->bidi_level);
1725 fprintf (stderr, ")");
1729 /* m17n-X internal APIs */
1734 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1736 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1737 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1739 Mlatin = msymbol ("latin");
1740 Minherited = msymbol ("inherited");
1742 McatCc = msymbol ("Cc");
1743 McatCf = msymbol ("Cf");
1745 MbidiR = msymbol ("R");
1746 MbidiAL = msymbol ("AL");
1747 MbidiRLE = msymbol ("RLE");
1748 MbidiRLO = msymbol ("RLO");
1749 MbidiBN = msymbol ("BN");
1750 MbidiS = msymbol ("S");
1752 fribidi_set_mirroring (TRUE);
1761 MLIST_FREE1 (&scratch_gstring, glyphs);
1765 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1769 /*** @addtogroup m17nDraw */
1774 @brief Draw an M-text on a window.
1776 The mdraw_text () function draws the text between $FROM and $TO of
1777 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1779 The appearance of the text (size, style, color, etc) is specified
1780 by the value of the text property whose key is @c Mface. If the
1781 M-text or a part of the M-text does not have such a text property,
1782 the default face of $FRAME is used.
1784 The font used to draw a character in the M-text is selected from
1785 the value of the fontset property of a face by the following
1790 <li> Search the text properties given to the character for the one
1791 whose key is @c Mcharset; its value should be either a symbol
1792 specifying a charset or #Mnil. If the value is #Mnil,
1793 proceed to the next step.
1795 Otherwise, search the mapping table of the fontset for the
1796 charset. If no entry is found proceed to the next step.
1798 If an entry is found, use one of the fonts in the entry that
1799 has a glyph for the character and that matches best with the
1800 face properties. If no such font exists, proceed to the next
1803 <li> Get the character property "script" of the character. If it is
1804 inherited, get the script property from the previous
1805 characters. If there is no previous character, or none of
1806 them has the script property other than inherited, proceed to
1809 Search the text properties given to the character for the one
1810 whose key is @c Mlanguage; its value should be either a
1811 symbol specifying a language or @c Mnil.
1813 Search the mapping table of the fontset for the combination
1814 of the script and language. If no entry is found, proceed to
1817 If an entry is found, use one of the fonts in the entry that
1818 has a glyph for the character and that matches best with the
1819 face properties. If no such font exists, proceed to the next
1822 <li> Search the fall-back table of the fontset for a font that has
1823 a glyph of the character. If such a font is found, use that
1828 If no font is found by the algorithm above, this function draws an
1829 empty box for the character.
1831 This function draws only the glyph foreground. To specify the
1832 background color, use mdraw_image_text () or
1833 mdraw_text_with_control ().
1835 This function is the counterpart of <tt>XDrawString ()</tt>,
1836 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1837 in the X Window System.
1840 If the operation was successful, mdraw_text () returns 0. If an
1841 error is detected, it returns -1 and assigns an error code to the
1842 external variable #merror_code. */
1844 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1846 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1847 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1850 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1851 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1852 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1853 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1855 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1856 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1860 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1861 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1862 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1863 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1864 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1867 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1868 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1869 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1872 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1873 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1874 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1875 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1877 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1878 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1881 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1882 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1885 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1886 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1887 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1890 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1891 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1895 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1896 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1898 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1899 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1902 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1903 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1906 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1907 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1909 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1916 mdraw_image_text () */
1919 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1920 MText *mt, int from, int to)
1922 MDrawControl control;
1924 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1925 memset (&control, 0, sizeof control);
1926 control.as_image = 0;
1927 return draw_text (frame, win, x, y, mt, from, to, &control);
1934 @brief Draw an M-text on a window as an image.
1936 The mdraw_image_text () function draws the text between $FROM and
1937 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1938 coordinate ($X, $Y).
1940 The way to draw a text is the same as in mdraw_text () except that
1941 this function also draws the background with the color specified
1944 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1945 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1946 functions in the X Window System.
1949 If the operation was successful, mdraw_image_text () returns 0.
1950 If an error is detected, it returns -1 and assigns an error code
1951 to the external variable #merror_code. */
1954 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1956 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1957 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1960 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1961 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1963 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1964 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1968 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1969 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1972 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1982 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1983 MText *mt, int from, int to)
1985 MDrawControl control;
1987 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1988 memset (&control, 0, sizeof control);
1989 control.as_image = 1;
1990 return draw_text (frame, win, x, y, mt, from, to, &control);
1996 @brief Draw an M-text on a window with fine control.
1998 The mdraw_text_with_control () function draws the text between
1999 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2000 coordinate ($X, $Y).
2002 The way to draw a text is the same as in mdraw_text () except that
2003 this function also follows what specified in the drawing control
2006 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2007 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2008 breaks lines and the following characters are drawn in the next
2009 line. See the documentation of the structure @ MDrawControl for
2013 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2015 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2016 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2019 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2020 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2022 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2023 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2024 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2028 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2029 MText *mt, int from, int to, MDrawControl *control)
2031 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2032 return draw_text (frame, win, x, y, mt, from, to, control);
2038 @brief Compute text pixel width.
2040 The mdraw_text_extents () function computes the width of text
2041 between $FROM and $TO of M-text $MT when it is drawn on a window
2042 of frame $FRAME using the mdraw_text_with_control () function with
2043 the drawing control object $CONTROL.
2045 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2046 the bounding box of character ink of the M-text, and stores the
2047 results in the members of the structure pointed to by
2048 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2049 surrounding box, the box is included in the bounding box.
2051 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2052 computes the bounding box that provides mininum spacing to other
2053 graphical features (such as surrounding box) for the M-text, and
2054 stores the results in the members of the structure pointed to by
2055 $OVERALL_LOGICAL_RETURN.
2057 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2058 computes the bounding box that provides mininum spacing to the
2059 other M-text drawn, and stores the results in the members of the
2060 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2061 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2062 min_line_ascent, min_line_descent, max_line_ascent, and
2063 max_line_descent of $CONTROL are all zero.
2066 This function returns the width of the text to be drawn in the
2067 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2068 text is drawn in multiple physical lines, it returns the width of
2069 the widest line. If an error occurs, it returns -1 and assigns an
2070 error code to the external variable #merror_code. */
2074 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2076 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2077 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2078 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2080 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2081 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2082 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2083 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2085 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2086 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2087 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2088 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2090 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2091 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2092 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2093 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2094 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2095 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2097 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2098 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2099 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2100 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2102 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2109 mdraw_text_extents (MFrame *frame,
2110 MText *mt, int from, int to, MDrawControl *control,
2111 MDrawMetric *overall_ink_return,
2112 MDrawMetric *overall_logical_return,
2113 MDrawMetric *overall_line_return)
2115 MGlyphString *gstring;
2117 int width, rbearing;
2119 ASSURE_CONTROL (control);
2120 M_CHECK_POS_X (mt, from, -1);
2121 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2122 to = mtext_nchars (mt) + (control->cursor_width != 0);
2126 gstring = get_gstring (frame, mt, from, to, control);
2128 MERROR (MERROR_DRAW, -1);
2129 width = gstring_width (gstring, from, to, &rbearing);
2130 if (overall_ink_return)
2132 overall_ink_return->y = - gstring->physical_ascent;
2133 overall_ink_return->x = gstring->lbearing;
2135 if (overall_logical_return)
2137 overall_logical_return->y = - gstring->ascent;
2138 overall_logical_return->x = 0;
2140 if (overall_line_return)
2142 overall_line_return->y = - gstring->line_ascent;
2143 overall_line_return->x = gstring->lbearing;
2146 for (from = gstring->to; from < to; from = gstring->to)
2148 int this_width, this_rbearing;
2150 y += gstring->line_descent;
2151 M17N_OBJECT_UNREF (gstring->top);
2152 gstring = get_gstring (frame, mt, from, to, control);
2153 this_width = gstring_width (gstring, from, to, &this_rbearing);
2154 y += gstring->line_ascent;
2155 if (width < this_width)
2157 if (rbearing < this_rbearing)
2158 rbearing = this_rbearing;
2160 if (overall_ink_return)
2162 overall_ink_return->width = rbearing;
2163 overall_ink_return->height
2164 = y + gstring->physical_descent - overall_ink_return->y;
2166 if (overall_logical_return)
2168 overall_logical_return->width = width;
2169 overall_logical_return->height
2170 = y + gstring->descent - overall_logical_return->y;
2172 if (overall_line_return)
2174 overall_line_return->width = MAX (width, rbearing);
2175 overall_line_return->height
2176 = y + gstring->line_descent - overall_line_return->y;
2179 M17N_OBJECT_UNREF (gstring->top);
2186 @brief Compute the text dimensions of each character of M-text.
2188 The mdraw_text_per_char_extents () function computes the drawn
2189 metric of each character between $FROM and $TO of M-text $MT
2190 assuming that they are drawn on a window of frame $FRAME using the
2191 mdraw_text_with_control () function with the drawing control
2194 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2195 $LOGICAL_ARRAY_RETURN. Each successive element of
2196 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2197 ink and logical metrics of successive characters respectively,
2198 relative to the drawing origin of the M-text. The number of
2199 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2200 been set is returned to $NUM_CHARS_RETURN.
2202 If $ARRAY_SIZE is too small to return all metrics, the function
2203 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2204 Otherwise, it returns zero.
2206 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2207 @c NULL, this function also computes the metrics of the overall
2208 text and stores the results in the members of the structure
2209 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2211 If $CONTROL->two_dimensional is nonzero, this function computes
2212 only the metrics of characters in the first line. */
2214 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2216 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2217 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2218 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2219 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2221 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2222 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2223 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2224 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2225 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2227 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2228 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2231 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2232 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2233 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2236 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2237 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2240 mdraw_text_per_char_extents (MFrame *frame,
2241 MText *mt, int from, int to,
2242 MDrawControl *control,
2243 MDrawMetric *ink_array_return,
2244 MDrawMetric *logical_array_return,
2246 int *num_chars_return,
2247 MDrawMetric *overall_ink_return,
2248 MDrawMetric *overall_logical_return)
2250 MGlyphString *gstring;
2254 ASSURE_CONTROL (control);
2255 *num_chars_return = to - from;
2256 if (array_size < *num_chars_return)
2257 MERROR (MERROR_DRAW, -1);
2258 if (overall_logical_return)
2259 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2260 if (overall_ink_return)
2261 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2263 M_CHECK_RANGE (mt, from, to, -1, 0);
2264 gstring = get_gstring (frame, mt, from, to, control);
2267 *num_chars_return = 0;
2271 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2272 if (g->pos >= from && g->pos < to)
2276 int width = g->width;
2277 int lbearing = g->lbearing;
2278 int rbearing = g->rbearing;
2279 int ascent = g->ascent;
2280 int descent = g->descent;
2281 int logical_ascent = g->rface->rfont->ascent;
2282 int logical_descent = g->rface->rfont->descent;
2284 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2286 if (lbearing < width + g->lbearing)
2287 lbearing = width + g->lbearing;
2288 if (rbearing < width + g->rbearing)
2289 rbearing = width + g->rbearing;
2291 if (ascent < g->ascent)
2293 if (descent < g->descent)
2294 descent = g->descent;
2301 ink_array_return[start - from].x = x + lbearing;
2302 ink_array_return[start - from].y = - ascent;
2303 ink_array_return[start - from].width = rbearing - lbearing;
2304 ink_array_return[start - from].height = ascent + descent;
2305 logical_array_return[start - from].x = x;
2306 logical_array_return[start - from].y = - logical_descent;
2307 logical_array_return[start - from].height
2308 = logical_ascent + logical_descent;
2309 logical_array_return[start - from].width = width;
2315 if (overall_ink_return)
2317 overall_ink_return->y = - gstring->line_ascent;
2318 overall_ink_return->x = gstring->lbearing;
2319 overall_ink_return->width = x - gstring->lbearing;
2320 overall_ink_return->height = gstring->height;
2322 if (overall_logical_return)
2324 overall_logical_return->y = - gstring->ascent;
2325 overall_logical_return->x = 0;
2326 overall_logical_return->width = x;
2327 overall_logical_return->height = gstring->ascent + gstring->descent;
2330 M17N_OBJECT_UNREF (gstring->top);
2337 @brief Return the character position nearest to the coordinates.
2339 The mdraw_coordinates_position () function checks which character
2340 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2341 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2342 mdraw_text_with_control () function with the drawing control
2343 object $CONTROL. Here, the character position means the number of
2344 characters that precede the character in question in $MT, that is,
2345 the character position of the first character is 0.
2347 $FRAME is used only to get the default face information.
2350 If the glyph image of a character covers coordinate ($X, $Y),
2351 mdraw_coordinates_position () returns the character position of
2353 If $Y is less than the minimum Y-coordinate of the drawn area, it
2354 returns $FROM.\n\n\n
2355 If $Y is greater than the maximum Y-coordinate of the drawn area,
2356 it returns $TO.\n\n\n
2357 If $Y fits in with the drawn area but $X is less than the minimum
2358 X-coordinate, it returns the character position of the first
2359 character drawn on the line $Y.\n\n\n
2360 If $Y fits in with the drawn area but $X is greater than the
2361 maximum X-coordinate, it returns the character position of the
2362 last character drawn on the line $Y. */
2365 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2367 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2368 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2369 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2370 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2371 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2372 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2374 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2377 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2378 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2380 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2382 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2384 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2385 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2387 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2388 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2391 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2392 int x_offset, int y_offset, MDrawControl *control)
2394 MGlyphString *gstring;
2399 M_CHECK_POS_X (mt, from, -1);
2400 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2401 to = mtext_nchars (mt) + (control->cursor_width != 0);
2407 ASSURE_CONTROL (control);
2408 gstring = get_gstring (frame, mt, from, to, control);
2409 while (y + gstring->line_descent <= y_offset
2410 && gstring->to < to)
2413 y += gstring->line_descent;
2414 M17N_OBJECT_UNREF (gstring->top);
2415 gstring = get_gstring (frame, mt, from, to, control);
2416 y += gstring->line_ascent;
2419 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2420 if (! control->orientation_reversed)
2422 width = gstring->indent;
2423 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2424 if (g->pos >= from && g->pos < to)
2427 if (width > x_offset)
2433 width = - gstring->indent;
2434 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2435 if (g->pos >= from && g->pos < to)
2438 if (width < x_offset)
2443 M17N_OBJECT_UNREF (gstring->top);
2451 @brief Compute information about a glyph.
2453 The mdraw_glyph_info () function computes information about a
2454 glyph that covers a character at position $POS of the M-text $MT
2455 assuming that the text is drawn from the character at $FROM of $MT
2456 on a window of frame $FRAME using the mdraw_text_with_control ()
2457 function with the drawing control object $CONTROL.
2459 The information is stored in the members of $INFO. */
2461 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2463 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2464 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2465 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2466 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2468 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2476 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2477 MDrawControl *control, MDrawGlyphInfo *info)
2479 MGlyphString *gstring;
2483 M_CHECK_RANGE_X (mt, from, pos, -1);
2485 ASSURE_CONTROL (control);
2486 gstring = get_gstring (frame, mt, from, pos + 1, control);
2488 MERROR (MERROR_DRAW, -1);
2489 while (gstring->to <= pos)
2491 y += gstring->line_descent;
2492 M17N_OBJECT_UNREF (gstring->top);
2493 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2494 y += gstring->line_ascent;
2496 info->line_from = gstring->from;
2497 if (info->line_from < from)
2498 info->line_from = from;
2499 info->line_to = gstring->to;
2502 if (! control->orientation_reversed)
2504 info->x = gstring->indent;
2505 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2506 info->x += g->width;
2510 info->x = - gstring->indent;
2511 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2512 info->x -= g->width;
2513 while (g[-1].to == g->to)
2516 info->from = g->pos;
2518 info->glyph_code = g->code;
2519 info->this.x = g->lbearing;
2520 info->this.y = - gstring->line_ascent;
2521 info->this.height = gstring->height;
2522 info->this.width = - g->lbearing + g->width;
2523 if (g->rface->rfont)
2524 info->font = &g->rface->rfont->font;
2527 /* info->logical_width is calculated later. */
2529 if (info->from > info->line_from)
2531 /* The logically previous glyph is on this line. */
2532 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2534 info->prev_from = g_tmp->pos;
2536 else if (info->line_from > 0)
2538 /* The logically previous glyph is on the previous line. */
2539 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2540 gstring->from, control);
2541 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2543 info->prev_from = g_tmp->pos;
2544 M17N_OBJECT_UNREF (gst->top);
2547 info->prev_from = -1;
2549 if (GLYPH_INDEX (g) > 1)
2550 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2551 else if (! control->orientation_reversed)
2553 if (info->line_from > 0)
2557 int p = gstring->from - 1;
2559 gst = get_gstring (frame, mt, p, gstring->from, control);
2560 g_tmp = gst->glyphs + (gst->used - 2);
2561 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2562 M17N_OBJECT_UNREF (gst->top);
2565 info->left_from = info->left_to = -1;
2569 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2573 int p = gstring->to;
2575 gst = get_gstring (frame, mt, p, p + 1, control);
2576 g_tmp = gst->glyphs + (gst->used - 2);
2577 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2578 M17N_OBJECT_UNREF (gst->top);
2581 info->left_from = info->left_to = -1;
2584 if (info->to < gstring->to)
2586 /* The logically next glyph is on this line. */
2587 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2589 info->next_to = g_tmp->to;
2591 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2593 /* The logically next glyph is on the next line. */
2595 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2596 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2598 info->next_to = g_tmp->to;
2599 M17N_OBJECT_UNREF (gst->top);
2604 for (info->logical_width = (g++)->width;
2605 g->pos == pos && g->type != GLYPH_ANCHOR;
2606 info->this.width += g->width, info->logical_width += (g++)->width);
2607 info->this.width += g[-1].rbearing - g[-1].width;
2609 if (g->type != GLYPH_ANCHOR)
2610 info->right_from = g->pos, info->right_to = g->to;
2611 else if (! control->orientation_reversed)
2613 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2616 M17N_OBJECT_UNREF (gstring->top);
2617 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2619 info->right_from = g->pos, info->right_to = g->to;
2622 info->right_from = info->right_to = -1;
2626 if (info->line_from > 0)
2628 pos = gstring->from - 1;
2629 M17N_OBJECT_UNREF (gstring->top);
2630 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2632 info->right_from = g->pos, info->right_to = g->to;
2635 info->right_from = info->right_to = -1;
2638 M17N_OBJECT_UNREF (gstring->top);
2645 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2646 MDrawControl *control, MDrawGlyphInfo *info,
2647 int array_size, int *num_glyphs_return)
2649 MGlyphString *gstring;
2653 ASSURE_CONTROL (control);
2654 *num_glyphs_return = 0;
2655 M_CHECK_RANGE (mt, from, to, -1, 0);
2656 gstring = get_gstring (frame, mt, from, to, control);
2659 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2661 if (g->type == GLYPH_BOX
2662 || g->pos < from || g->pos >= to)
2666 info->from = g->pos;
2668 if (g->type == GLYPH_CHAR)
2669 info->glyph_code = g->code;
2671 info->glyph_code = mfont__encode_char (g->rface->rfont, ' ');
2674 info->this.x = g->lbearing;
2675 info->this.y = - g->ascent;
2676 info->this.height = g->ascent + g->descent;
2677 info->this.width = g->rbearing - g->lbearing;
2678 info->logical_width = g->width;
2679 if (g->rface->rfont)
2680 info->font = &g->rface->rfont->font;
2687 M17N_OBJECT_UNREF (gstring->top);
2689 *num_glyphs_return = n;
2690 return (n <= array_size ? 0 : -1);
2696 @brief Draw one or more textitems.
2698 The mdraw_text_items () function draws one or more M-texts on
2699 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2700 of the textitems to be drawn and $NITEMS is the number of
2701 textimtems in the array. */
2704 @brief textitem ¤òɽ¼¨¤¹¤ë.
2706 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2707 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2708 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2711 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2715 MTextItem, mdraw_text (). */
2718 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2719 MDrawTextItem *items, int nitems)
2721 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2723 while (nitems-- > 0)
2726 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2728 mdraw_text_with_control (frame, win, x, y,
2729 items->mt, 0, mtext_nchars (items->mt),
2731 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2732 items->control, NULL, NULL, NULL);
2735 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2741 @brief calculate a line breaking position.
2743 The function mdraw_default_line_break () calculates a line
2744 breaking position based on the line number $LINE and the
2745 coordinate $Y, when a line is too long to fit within the width
2746 limit. $POS is the position of the character next to the last
2747 one that fits within the limit. $FROM is the position of the
2748 first character of the line, and TO is the position of the last
2749 character displayed on the line if there were not width limit.
2750 LINE and Y are reset to 0 when a line is broken by a newline
2751 character, and incremented each time when a long line is broken
2752 because of the width limit.
2755 This function returns a character position to break the
2760 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2762 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2763 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2764 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2765 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2766 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2767 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2768 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2771 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2775 mdraw_default_line_break (MText *mt, int pos,
2776 int from, int to, int line, int y)
2778 int c = mtext_ref_char (mt, pos);
2781 if (c == ' ' || c == '\t')
2785 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2792 if (c == ' ' || c == '\t')
2795 c = mtext_ref_char (mt, pos);
2808 @brief Obtain per character dimension information.
2810 The mdraw_per_char_extents () function computes the text dimension
2811 of each character in M-text $MT. The faces given as text
2812 properties in $MT and the default face of frame $FRAME determine
2813 the fonts to draw the text. Each successive element in
2814 $ARRAY_RETURN is set to the drawn metrics of successive
2815 characters, which is relative to the origin of the drawing, and a
2816 rectangle for each character in $MT. The number of elements of
2817 $ARRAY_RETURN must be equal to or greater than the number of
2820 If pointer $OVERALL_RETURN is not @c NULL, this function also
2821 computes the extents of the overall text and stores the results in
2822 the members of the structure pointed to by $OVERALL_RETURN. */
2825 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2827 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2828 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2829 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2830 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2831 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2832 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2835 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2836 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2839 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2842 mdraw_per_char_extents (MFrame *frame, MText *mt,
2843 MDrawMetric *array_return,
2844 MDrawMetric *overall_return)
2846 int n = mtext_nchars (mt);
2848 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2849 n, &n, overall_return, NULL);
2853 @brief clear cached information.
2855 The mdraw_clear_cache () function clear cached information
2856 on M-text $MT that was attached by any of the drawing functions.
2857 When the behaviour of `format' or `line_break'
2858 member functions of MDrawControl is changed, the cache must be cleared.
2863 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2865 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2866 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2867 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2868 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2873 mdraw_clear_cache (MText *mt)
2875 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);