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 pad.left_padding = 1;
783 INSERT_GLYPH (gstring, from, pad);
785 gstring->sub_lbearing = 0;
786 gstring->sub_width += extra_width;
787 gstring->sub_rbearing += extra_width;
789 g = MGLYPH (from - 1);
790 if (g->type == GLYPH_SPACE)
792 /* The pad just inserted is absorbed (maybe
793 partially) by the previous space while
794 keeping at least some space width. For the
795 moment, we use the arbitrary width 2-pixel.
796 Perhaps, it should be decided by the current
797 face, or a default value of the current
798 frame, which is, however, not yet
800 if (extra_width + 2 < g->width)
802 g->width -= extra_width;
806 extra_width -= g->width - 2;
809 gstring->width -= extra_width;
810 gstring->rbearing -= extra_width;
814 extra_width = gstring->sub_rbearing - gstring->sub_width;
818 if (g->type == GLYPH_SPACE && box == g->rface->box)
822 pad.type = GLYPH_PAD;
825 pad.width = pad.rbearing = extra_width;
827 INSERT_GLYPH (gstring, to, pad);
831 g[-1].width += extra_width;
832 gstring->sub_width += extra_width;
835 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
836 gstring->lbearing = gstring->width + gstring->sub_lbearing;
837 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
838 gstring->rbearing = gstring->width + gstring->sub_rbearing;
839 gstring->width += gstring->sub_width;
840 if (gstring->ascent < rface->ascent)
841 gstring->ascent = rface->ascent;
842 if (gstring->descent < rface->descent)
843 gstring->descent = rface->descent;
848 for (; fromg < g; fromg++)
850 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
851 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
852 fromg->width = fromg->rbearing = 1;
854 fromg->width = fromg->rbearing = rface->space_width;
855 fromg->xoff = fromg->lbearing = 0;
856 fromg->ascent = fromg->descent = 0;
857 gstring->width += fromg->width;
858 gstring->rbearing += fromg->width;
860 if (gstring->ascent < frame->rface->ascent)
861 gstring->ascent = frame->rface->ascent;
862 if (gstring->descent < frame->descent)
863 gstring->descent = frame->rface->descent;
866 else if (g->type == GLYPH_SPACE)
869 g->width = g->rface->space_width;
870 else if (g->c == '\n')
872 g->width = control->cursor_width;
875 if (control->cursor_bidi)
877 else if (g->width < 0)
878 g->width = g->rface->space_width;
881 else if (g->c == '\t')
883 g->width = tab_width - ((gstring->indent + gstring->width)
889 if (g[-1].type == GLYPH_PAD)
891 /* This space glyph absorbs (maybe partially) the
892 previous padding glyph. */
893 g->width -= g[-1].width;
895 /* But, keep at least some space width. For the
896 moment, we use the arbitrary width 2-pixel. */
899 g->rbearing = g->width;
900 gstring->width += g->width;
901 gstring->rbearing += g->width;
904 if (gstring->ascent < g->rface->ascent)
905 gstring->ascent = g->rface->ascent;
906 if (gstring->descent < g->rface->descent)
907 gstring->descent = g->rface->descent;
913 gstring->width += g->width;
914 gstring->rbearing += g->width;
921 /* Insert the right side of the box. */
922 int gidx = GLYPH_INDEX (g);
923 MGlyph box_glyph = g[-1];
925 box_glyph.type = GLYPH_BOX;
927 = (control->fixed_width
929 : box->inner_hmargin + box->width + box->outer_hmargin);
930 box_glyph.lbearing = 0;
931 box_glyph.rbearing = box_glyph.width;
933 box_glyph.right_padding = 1;
934 gstring->width += box_glyph.width;
935 gstring->rbearing += box_glyph.width;
936 INSERT_GLYPH (gstring, gidx, box_glyph);
939 gstring->text_ascent = gstring->ascent;
940 gstring->text_descent = gstring->descent;
941 if (gstring->text_ascent < gstring->physical_ascent)
942 gstring->text_ascent = gstring->physical_ascent;
943 if (gstring->text_descent < gstring->physical_descent)
944 gstring->text_descent = gstring->physical_descent;
945 gstring->line_ascent = gstring->text_ascent;
946 gstring->line_descent = gstring->text_descent;
947 if (box_line_height > 0)
949 gstring->line_ascent += box_line_height;
950 gstring->physical_ascent = gstring->line_ascent;
951 gstring->line_descent += box_line_height;
952 gstring->physical_descent = gstring->line_descent;
955 if (gstring->line_ascent < control->min_line_ascent)
956 gstring->line_ascent = control->min_line_ascent;
957 else if (control->max_line_ascent
958 && control->max_line_ascent > control->min_line_ascent
959 && gstring->line_ascent > control->max_line_ascent)
960 gstring->line_ascent = control->max_line_ascent;
962 if (gstring->line_descent < control->min_line_descent)
963 gstring->line_descent = control->min_line_descent;
964 else if (control->max_line_descent
965 && control->max_line_descent > control->min_line_descent
966 && gstring->line_descent > control->max_line_descent)
967 gstring->line_descent = control->max_line_descent;
968 gstring->height = gstring->line_ascent + gstring->line_descent;
970 if (control->orientation_reversed
973 /* We must adjust TAB width for RTL orientation. */
974 width = gstring->indent;
976 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
978 if (g->type == GLYPH_CHAR && g->c == '\t')
980 int this_width = tab_width - (width % tab_width);
982 if (g[1].type == GLYPH_PAD)
983 this_width -= g[1].width;
984 if (g[-1].type == GLYPH_PAD)
985 this_width -= g[-1].width;
988 gstring->width += this_width - g->width;
989 gstring->rbearing += this_width - g->width;
990 g->width = this_width;
1001 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
1002 MGlyphString *gstring, int from, int to,
1003 int *from_idx, int *to_idx, int *to_x)
1005 MGlyph *g = MGLYPH (1);
1006 MDrawRegion region = (MDrawRegion) NULL;
1007 MDrawControl *control = &gstring->control;
1008 int cursor_pos = -1;
1010 int cursor_bidi = control->cursor_bidi;
1012 if (control->with_cursor && control->cursor_width)
1014 if (gstring->from <= control->cursor_pos
1015 && gstring->to > control->cursor_pos)
1016 cursor_pos = control->cursor_pos;
1018 && gstring->from <= control->cursor_pos - 1
1019 && gstring->to > control->cursor_pos - 1)
1020 prev_pos = control->cursor_pos - 1;
1023 *from_idx = *to_idx = 0;
1024 while (g->type != GLYPH_ANCHOR)
1026 if (g->pos >= from && g->pos < to)
1028 MGlyph *fromg = g, *cursor = NULL;
1029 MRealizedFace *rface = g->rface;
1031 int cursor_width = 0;
1035 *from_idx = GLYPH_INDEX (g);
1036 while (g->pos >= from && g->pos < to
1037 && g->rface == rface)
1040 if (g->type != GLYPH_BOX
1041 && g->pos <= cursor_pos && g->to > cursor_pos)
1044 cursor = g, cursor_x = x + width;
1045 cursor_width += g->width;
1047 width += g++->width;
1050 && (control->as_image
1051 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1053 int this_x = x, this_width = width;
1055 if (fromg->type == GLYPH_BOX)
1056 this_x += fromg->width, this_width -= fromg->width;
1057 if (g[-1].type == GLYPH_BOX)
1058 this_width -= g[-1].width;
1059 (frame->driver->fill_space)
1060 (frame, win, rface, 0,
1061 this_x, y - gstring->text_ascent, this_width,
1062 gstring->text_ascent + gstring->text_descent,
1063 control->clip_region);
1070 rect.y = y - gstring->text_ascent;
1071 rect.height = gstring->text_ascent + gstring->text_descent;
1074 rect.width = ((control->cursor_width > 0
1075 && control->cursor_width < cursor_width)
1076 ? control->cursor_width : cursor_width);
1080 if (cursor->bidi_level % 2)
1081 rect.x += cursor_width - 1;
1084 (*frame->driver->fill_space)
1085 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1086 control->clip_region);
1088 region = (*frame->driver->region_from_rect) (&rect);
1090 (*frame->driver->region_add_rect) (region, &rect);
1093 if (cursor->bidi_level % 2)
1096 rect.width = cursor_width < 4 ? cursor_width : 4;
1097 (*frame->driver->fill_space)
1098 (frame, win, rface, 1,
1099 rect.x, rect.y, rect.width, rect.height,
1100 control->clip_region);
1101 (*frame->driver->region_add_rect) (region, &rect);
1113 if (fromg->type != GLYPH_BOX
1114 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1117 cursor = fromg, cursor_x = x + temp_width;
1118 cursor_width += fromg->width;
1120 temp_width += fromg++->width;
1127 if (! (cursor->bidi_level % 2))
1128 rect.x += cursor_width - 1;
1129 rect.y = y - gstring->text_ascent;
1130 rect.height = gstring->text_ascent + gstring->text_descent;
1132 (*frame->driver->fill_space)
1133 (frame, win, rface, 1,
1134 rect.x, rect.y, rect.width, rect.height,
1135 control->clip_region);
1137 region = (*frame->driver->region_from_rect) (&rect);
1139 (*frame->driver->region_add_rect) (region, &rect);
1140 rect.y += rect.height - 2;
1142 rect.width = cursor_width < 4 ? cursor_width : 4;
1143 if (! (cursor->bidi_level % 2))
1144 rect.x -= rect.width - 1;
1145 (*frame->driver->fill_space) (frame, win, rface, 1,
1146 rect.x, rect.y, rect.width, rect.height,
1147 control->clip_region);
1148 (*frame->driver->region_add_rect) (region, &rect);
1152 *to_idx = GLYPH_INDEX (g);
1162 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1163 MGlyphString *gstring, int from_idx, int to_idx,
1164 int reverse, MDrawRegion region)
1166 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1172 (*frame->driver->region_to_rect) (region, &rect);
1175 while (g != gend && x + g->rbearing <= rect.x)
1178 width -= g++->width;
1179 while (! g->enabled && g != gend)
1183 rect.x += rect.width;
1184 if (rect.x < x + width)
1187 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1189 width -= (--gend)->width;
1190 while (! gend->enabled && g != gend)
1194 while (gend[-1].to == gend->to) gend++;
1202 MRealizedFace *rface = g->rface;
1203 int width = g->width;
1204 MGlyph *from_g = g++;
1206 /* Handle the glyphs of the same type/face at once. */
1208 && g->type == from_g->type
1209 && g->rface == rface
1210 && (g->code < 0) == (from_g->code < 0)
1212 width += g++->width;
1214 if (from_g->type == GLYPH_CHAR)
1216 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1217 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1220 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1223 else if (from_g->type == GLYPH_BOX)
1225 /* Draw the left or right side of a box. If
1226 from_g->lbearing is nonzero, this is the left side,
1227 else this is the right side. */
1228 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1231 if (from_g->type != GLYPH_BOX)
1234 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1235 x, y, width, region);
1238 /* Draw the top and bottom side of a box. */
1239 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1240 x, y, width, region);
1251 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1252 int *from_x, int *to_x)
1255 int left_idx = *left, right_idx = *right;
1256 int left_x, right_x, x;
1258 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1261 if (x + g->rbearing > 0)
1263 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1265 left_idx = GLYPH_INDEX (g);
1270 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1273 if (x - g->width + g->lbearing < 0)
1275 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1277 right_idx = GLYPH_INDEX (g) + 1;
1282 if (*left == left_idx && *right == right_idx)
1285 if (*left != left_idx)
1287 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1292 if (*right != right_idx)
1294 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1304 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1309 if (from <= gstring->from && to >= gstring->to)
1312 *rbearing = gstring->rbearing;
1313 return gstring->width;
1318 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1319 if (g->pos >= from && g->pos < to)
1321 if (rbearing && width + g->rbearing > *rbearing)
1322 *rbearing = width + g->rbearing;
1330 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1331 MGlyphString *gstring, int from, int to)
1333 MDrawControl *control = &gstring->control;
1335 MDrawRegion clip_region, cursor_region;
1336 int from_idx, to_idx;
1339 if (control->orientation_reversed)
1340 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1342 x += gstring->indent;
1344 /* At first, draw all glyphs without cursor. */
1345 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1346 &from_idx, &to_idx, &to_x);
1348 if (control->partial_update)
1351 rect.width = to_x - x;
1352 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1354 rect.y = y - gstring->line_ascent;
1355 rect.height = gstring->height;
1356 clip_region = (*frame->driver->region_from_rect) (&rect);
1357 if (control->clip_region)
1358 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1361 clip_region = control->clip_region;
1364 clip_region = control->clip_region;
1366 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1371 (*frame->driver->intersect_region) (cursor_region, clip_region);
1372 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1375 if (clip_region != control->clip_region)
1376 (*frame->driver->free_region) (clip_region);
1378 (*frame->driver->free_region) (cursor_region);
1382 static int gstring_num;
1385 free_gstring (void *object)
1387 MGlyphString *gstring = (MGlyphString *) object;
1390 free_gstring (gstring->next);
1391 if (gstring->size > 0)
1392 free (gstring->glyphs);
1398 static MGlyphString scratch_gstring;
1400 static MGlyphString *
1401 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1404 MGlyphString *gstring;
1406 if (pos == mt->nchars)
1408 gstring = &scratch_gstring;
1412 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1413 MLIST_INIT1 (gstring, glyphs, 128);
1417 gstring->frame = frame;
1418 gstring->tick = frame->tick;
1419 gstring->top = gstring;
1421 gstring->control = *control;
1422 gstring->indent = gstring->width_limit = 0;
1423 if (control->format)
1424 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1426 gstring->width_limit = control->max_line_width;
1427 gstring->anti_alias = control->anti_alias;
1431 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1434 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1442 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1443 a width of glyphs for the character at I of GSTRING->mt. If I is
1444 not a beginning of a grapheme cluster, the corresponding element
1446 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1447 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1448 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1449 pos_width[g->pos - gstring->from] += g->width;
1450 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1452 if (pos_width[i] > 0)
1454 if (width + pos_width[i] > gstring->width_limit)
1457 width += pos_width[i];
1460 pos = gstring->from + i;
1461 if (gstring->control.line_break)
1463 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1464 gstring->from, gstring->to, 0, 0);
1465 if (pos <= gstring->from || pos >= gstring->to)
1468 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1469 layout_glyph_string (frame, gstring);
1473 /* Return a gstring that covers a character at POS. */
1475 static MGlyphString *
1476 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1478 MGlyphString *gstring = NULL;
1480 if (pos < mtext_nchars (mt))
1482 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1485 && ((prop->start != 0
1486 && mtext_ref_char (mt, prop->start - 1) != '\n')
1487 || (prop->end < mtext_nchars (mt)
1488 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1490 mtext_detach_property (prop);
1495 gstring = prop->val;
1496 if (gstring->frame != frame
1497 || gstring->tick != frame->tick
1498 || memcmp (control, &gstring->control,
1499 (char *) (&control->with_cursor)
1500 - (char *) (control)))
1502 mtext_detach_property (prop);
1507 else if (! control->cursor_width)
1515 offset = mtext_character (mt, pos, 0, '\n');
1520 offset -= gstring->from;
1522 for (gst = gstring; gst; gst = gst->next)
1526 gst->from += offset;
1528 for (i = 0; i < gst->used; i++)
1530 gst->glyphs[i].pos += offset;
1531 gst->glyphs[i].to += offset;
1534 M17N_OBJECT_REF (gstring);
1539 int line = 0, y = 0;
1541 if (control->two_dimensional)
1543 beg = mtext_character (mt, pos, 0, '\n');
1548 end = mtext_nchars (mt) + (control->cursor_width != 0);
1555 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1556 compose_glyph_string (frame, mt, beg, end, gstring);
1557 layout_glyph_string (frame, gstring);
1559 if (control->two_dimensional
1560 && gstring->width_limit
1561 && gstring->width > gstring->width_limit)
1563 MGlyphString *gst = gstring;
1565 truncate_gstring (frame, mt, gst);
1566 while (gst->to < end)
1568 line++, y += gst->height;
1569 gst->next = alloc_gstring (frame, mt, gst->from, control,
1571 gst->next->top = gstring;
1572 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1574 layout_glyph_string (frame, gst);
1575 if (gst->width <= gst->width_limit)
1577 truncate_gstring (frame, mt, gst);
1581 if (! control->disable_caching && pos < mtext_nchars (mt))
1583 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1584 MTEXTPROP_VOLATILE_STRONG);
1586 if (end > mtext_nchars (mt))
1587 end = mtext_nchars (mt);
1588 mtext_attach_property (mt, beg, end, prop);
1589 M17N_OBJECT_UNREF (prop);
1593 while (gstring->to <= pos)
1595 if (! gstring->next)
1597 gstring = gstring->next;
1599 gstring->control = *control;
1605 static MDrawControl control_noop;
1607 #define ASSURE_CONTROL(control) \
1609 control = &control_noop; \
1614 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1615 MText *mt, int from, int to,
1616 MDrawControl *control)
1618 MGlyphString *gstring;
1620 M_CHECK_POS_X (mt, from, -1);
1621 ASSURE_CONTROL (control);
1622 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1623 to = mtext_nchars (mt) + (control->cursor_width != 0);
1627 gstring = get_gstring (frame, mt, from, to, control);
1629 MERROR (MERROR_DRAW, -1);
1630 render_glyph_string (frame, win, x, y, gstring, from, to);
1634 y += gstring->line_descent;
1635 M17N_OBJECT_UNREF (gstring->top);
1636 gstring = get_gstring (frame, mt, from, to, control);
1637 y += gstring->line_ascent;
1638 render_glyph_string (frame, win, x, y, gstring, from, to);
1641 M17N_OBJECT_UNREF (gstring->top);
1648 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1654 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1655 if (g->pos <= pos && g->to > pos)
1660 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1661 if (g->pos <= pos && g->to > pos)
1668 /* for debugging... */
1672 dump_combining_code (int code)
1674 char *vallign = "tcbB";
1675 char *hallign = "lcr";
1681 if (COMBINING_BY_CLASS_P (code))
1682 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1683 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1684 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1685 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1686 off_x = COMBINING_CODE_OFF_X (code) - 128;
1688 sprintf (work + 2, "+%d", off_y);
1690 sprintf (work + 2, "%d", off_y);
1691 else if (off_x == 0)
1692 sprintf (work + 2, ".");
1693 p = work + strlen (work);
1695 sprintf (p, ">%d", off_x);
1697 sprintf (p, "<%d", -off_x);
1699 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1700 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1706 dump_gstring (MGlyphString *gstring, int indent)
1708 char *prefix = (char *) alloca (indent + 1);
1709 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1711 memset (prefix, 32, indent);
1714 fprintf (stderr, "(glyph-string");
1716 for (g = MGLYPH (0); g < last_g; g++)
1718 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1720 g - gstring->glyphs,
1721 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1722 : g->type == GLYPH_ANCHOR ? "ANC"
1723 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1724 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1725 dump_combining_code (g->combining_code),
1726 g->width, g->bidi_level);
1727 fprintf (stderr, ")");
1731 /* m17n-X internal APIs */
1736 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1738 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1739 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1741 Mlatin = msymbol ("latin");
1742 Minherited = msymbol ("inherited");
1744 McatCc = msymbol ("Cc");
1745 McatCf = msymbol ("Cf");
1747 MbidiR = msymbol ("R");
1748 MbidiAL = msymbol ("AL");
1749 MbidiRLE = msymbol ("RLE");
1750 MbidiRLO = msymbol ("RLO");
1751 MbidiBN = msymbol ("BN");
1752 MbidiS = msymbol ("S");
1754 fribidi_set_mirroring (TRUE);
1763 MLIST_FREE1 (&scratch_gstring, glyphs);
1767 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1771 /*** @addtogroup m17nDraw */
1776 @brief Draw an M-text on a window.
1778 The mdraw_text () function draws the text between $FROM and $TO of
1779 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1781 The appearance of the text (size, style, color, etc) is specified
1782 by the value of the text property whose key is @c Mface. If the
1783 M-text or a part of the M-text does not have such a text property,
1784 the default face of $FRAME is used.
1786 The font used to draw a character in the M-text is selected from
1787 the value of the fontset property of a face by the following
1792 <li> Search the text properties given to the character for the one
1793 whose key is @c Mcharset; its value should be either a symbol
1794 specifying a charset or #Mnil. If the value is #Mnil,
1795 proceed to the next step.
1797 Otherwise, search the mapping table of the fontset for the
1798 charset. If no entry is found proceed to the next step.
1800 If an entry is found, use one of the fonts in the entry that
1801 has a glyph for the character and that matches best with the
1802 face properties. If no such font exists, proceed to the next
1805 <li> Get the character property "script" of the character. If it is
1806 inherited, get the script property from the previous
1807 characters. If there is no previous character, or none of
1808 them has the script property other than inherited, proceed to
1811 Search the text properties given to the character for the one
1812 whose key is @c Mlanguage; its value should be either a
1813 symbol specifying a language or @c Mnil.
1815 Search the mapping table of the fontset for the combination
1816 of the script and language. If no entry is found, proceed to
1819 If an entry is found, use one of the fonts in the entry that
1820 has a glyph for the character and that matches best with the
1821 face properties. If no such font exists, proceed to the next
1824 <li> Search the fall-back table of the fontset for a font that has
1825 a glyph of the character. If such a font is found, use that
1830 If no font is found by the algorithm above, this function draws an
1831 empty box for the character.
1833 This function draws only the glyph foreground. To specify the
1834 background color, use mdraw_image_text () or
1835 mdraw_text_with_control ().
1837 This function is the counterpart of <tt>XDrawString ()</tt>,
1838 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1839 in the X Window System.
1842 If the operation was successful, mdraw_text () returns 0. If an
1843 error is detected, it returns -1 and assigns an error code to the
1844 external variable #merror_code. */
1846 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1848 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1849 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1852 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1853 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1854 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1855 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1857 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1858 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1862 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1863 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1864 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1865 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1866 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1869 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1870 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1871 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1874 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1875 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1876 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1877 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1879 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1880 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1883 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1884 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1887 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1888 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1889 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1892 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1893 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1897 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1898 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1900 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1901 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1904 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1905 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1908 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1909 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1911 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1918 mdraw_image_text () */
1921 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1922 MText *mt, int from, int to)
1924 MDrawControl control;
1926 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1927 memset (&control, 0, sizeof control);
1928 control.as_image = 0;
1929 return draw_text (frame, win, x, y, mt, from, to, &control);
1936 @brief Draw an M-text on a window as an image.
1938 The mdraw_image_text () function draws the text between $FROM and
1939 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1940 coordinate ($X, $Y).
1942 The way to draw a text is the same as in mdraw_text () except that
1943 this function also draws the background with the color specified
1946 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1947 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1948 functions in the X Window System.
1951 If the operation was successful, mdraw_image_text () returns 0.
1952 If an error is detected, it returns -1 and assigns an error code
1953 to the external variable #merror_code. */
1956 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1958 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1959 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1962 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1963 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1965 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1966 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1970 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1971 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1974 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1984 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1985 MText *mt, int from, int to)
1987 MDrawControl control;
1989 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1990 memset (&control, 0, sizeof control);
1991 control.as_image = 1;
1992 return draw_text (frame, win, x, y, mt, from, to, &control);
1998 @brief Draw an M-text on a window with fine control.
2000 The mdraw_text_with_control () function draws the text between
2001 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2002 coordinate ($X, $Y).
2004 The way to draw a text is the same as in mdraw_text () except that
2005 this function also follows what specified in the drawing control
2008 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2009 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2010 breaks lines and the following characters are drawn in the next
2011 line. See the documentation of the structure @ MDrawControl for
2015 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
2017 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2018 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2021 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2022 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2024 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2025 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2026 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2030 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2031 MText *mt, int from, int to, MDrawControl *control)
2033 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2034 return draw_text (frame, win, x, y, mt, from, to, control);
2040 @brief Compute text pixel width.
2042 The mdraw_text_extents () function computes the width of text
2043 between $FROM and $TO of M-text $MT when it is drawn on a window
2044 of frame $FRAME using the mdraw_text_with_control () function with
2045 the drawing control object $CONTROL.
2047 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2048 the bounding box of character ink of the M-text, and stores the
2049 results in the members of the structure pointed to by
2050 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2051 surrounding box, the box is included in the bounding box.
2053 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2054 computes the bounding box that provides mininum spacing to other
2055 graphical features (such as surrounding box) for the M-text, and
2056 stores the results in the members of the structure pointed to by
2057 $OVERALL_LOGICAL_RETURN.
2059 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2060 computes the bounding box that provides mininum spacing to the
2061 other M-text drawn, and stores the results in the members of the
2062 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2063 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2064 min_line_ascent, min_line_descent, max_line_ascent, and
2065 max_line_descent of $CONTROL are all zero.
2068 This function returns the width of the text to be drawn in the
2069 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2070 text is drawn in multiple physical lines, it returns the width of
2071 the widest line. If an error occurs, it returns -1 and assigns an
2072 error code to the external variable #merror_code. */
2076 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2078 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2079 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2080 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2082 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2083 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2084 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2085 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2087 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2088 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2089 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2090 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2092 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2093 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2094 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2095 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2096 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2097 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2099 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2100 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2101 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2102 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2104 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2111 mdraw_text_extents (MFrame *frame,
2112 MText *mt, int from, int to, MDrawControl *control,
2113 MDrawMetric *overall_ink_return,
2114 MDrawMetric *overall_logical_return,
2115 MDrawMetric *overall_line_return)
2117 MGlyphString *gstring;
2119 int width, rbearing;
2121 ASSURE_CONTROL (control);
2122 M_CHECK_POS_X (mt, from, -1);
2123 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2124 to = mtext_nchars (mt) + (control->cursor_width != 0);
2128 gstring = get_gstring (frame, mt, from, to, control);
2130 MERROR (MERROR_DRAW, -1);
2131 width = gstring_width (gstring, from, to, &rbearing);
2132 if (overall_ink_return)
2134 overall_ink_return->y = - gstring->physical_ascent;
2135 overall_ink_return->x = gstring->lbearing;
2137 if (overall_logical_return)
2139 overall_logical_return->y = - gstring->ascent;
2140 overall_logical_return->x = 0;
2142 if (overall_line_return)
2144 overall_line_return->y = - gstring->line_ascent;
2145 overall_line_return->x = gstring->lbearing;
2148 for (from = gstring->to; from < to; from = gstring->to)
2150 int this_width, this_rbearing;
2152 y += gstring->line_descent;
2153 M17N_OBJECT_UNREF (gstring->top);
2154 gstring = get_gstring (frame, mt, from, to, control);
2155 this_width = gstring_width (gstring, from, to, &this_rbearing);
2156 y += gstring->line_ascent;
2157 if (width < this_width)
2159 if (rbearing < this_rbearing)
2160 rbearing = this_rbearing;
2162 if (overall_ink_return)
2164 overall_ink_return->width = rbearing;
2165 overall_ink_return->height
2166 = y + gstring->physical_descent - overall_ink_return->y;
2168 if (overall_logical_return)
2170 overall_logical_return->width = width;
2171 overall_logical_return->height
2172 = y + gstring->descent - overall_logical_return->y;
2174 if (overall_line_return)
2176 overall_line_return->width = MAX (width, rbearing);
2177 overall_line_return->height
2178 = y + gstring->line_descent - overall_line_return->y;
2181 M17N_OBJECT_UNREF (gstring->top);
2188 @brief Compute the text dimensions of each character of M-text.
2190 The mdraw_text_per_char_extents () function computes the drawn
2191 metric of each character between $FROM and $TO of M-text $MT
2192 assuming that they are drawn on a window of frame $FRAME using the
2193 mdraw_text_with_control () function with the drawing control
2196 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2197 $LOGICAL_ARRAY_RETURN. Each successive element of
2198 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2199 ink and logical metrics of successive characters respectively,
2200 relative to the drawing origin of the M-text. The number of
2201 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2202 been set is returned to $NUM_CHARS_RETURN.
2204 If $ARRAY_SIZE is too small to return all metrics, the function
2205 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2206 Otherwise, it returns zero.
2208 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2209 @c NULL, this function also computes the metrics of the overall
2210 text and stores the results in the members of the structure
2211 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2213 If $CONTROL->two_dimensional is nonzero, this function computes
2214 only the metrics of characters in the first line. */
2216 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2218 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2219 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2220 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2221 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2223 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2224 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2225 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2226 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2227 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2229 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2230 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2233 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2234 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2235 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2238 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2239 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2242 mdraw_text_per_char_extents (MFrame *frame,
2243 MText *mt, int from, int to,
2244 MDrawControl *control,
2245 MDrawMetric *ink_array_return,
2246 MDrawMetric *logical_array_return,
2248 int *num_chars_return,
2249 MDrawMetric *overall_ink_return,
2250 MDrawMetric *overall_logical_return)
2252 MGlyphString *gstring;
2256 ASSURE_CONTROL (control);
2257 *num_chars_return = to - from;
2258 if (array_size < *num_chars_return)
2259 MERROR (MERROR_DRAW, -1);
2260 if (overall_logical_return)
2261 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2262 if (overall_ink_return)
2263 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2265 M_CHECK_RANGE (mt, from, to, -1, 0);
2266 gstring = get_gstring (frame, mt, from, to, control);
2269 *num_chars_return = 0;
2273 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2274 if (g->pos >= from && g->pos < to)
2278 int width = g->width;
2279 int lbearing = g->lbearing;
2280 int rbearing = g->rbearing;
2281 int ascent = g->ascent;
2282 int descent = g->descent;
2283 int logical_ascent = g->rface->rfont->ascent;
2284 int logical_descent = g->rface->rfont->descent;
2286 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2288 if (lbearing < width + g->lbearing)
2289 lbearing = width + g->lbearing;
2290 if (rbearing < width + g->rbearing)
2291 rbearing = width + g->rbearing;
2293 if (ascent < g->ascent)
2295 if (descent < g->descent)
2296 descent = g->descent;
2303 ink_array_return[start - from].x = x + lbearing;
2304 ink_array_return[start - from].y = - ascent;
2305 ink_array_return[start - from].width = rbearing - lbearing;
2306 ink_array_return[start - from].height = ascent + descent;
2307 logical_array_return[start - from].x = x;
2308 logical_array_return[start - from].y = - logical_descent;
2309 logical_array_return[start - from].height
2310 = logical_ascent + logical_descent;
2311 logical_array_return[start - from].width = width;
2317 if (overall_ink_return)
2319 overall_ink_return->y = - gstring->line_ascent;
2320 overall_ink_return->x = gstring->lbearing;
2321 overall_ink_return->width = x - gstring->lbearing;
2322 overall_ink_return->height = gstring->height;
2324 if (overall_logical_return)
2326 overall_logical_return->y = - gstring->ascent;
2327 overall_logical_return->x = 0;
2328 overall_logical_return->width = x;
2329 overall_logical_return->height = gstring->ascent + gstring->descent;
2332 M17N_OBJECT_UNREF (gstring->top);
2339 @brief Return the character position nearest to the coordinates.
2341 The mdraw_coordinates_position () function checks which character
2342 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2343 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2344 mdraw_text_with_control () function with the drawing control
2345 object $CONTROL. Here, the character position means the number of
2346 characters that precede the character in question in $MT, that is,
2347 the character position of the first character is 0.
2349 $FRAME is used only to get the default face information.
2352 If the glyph image of a character covers coordinate ($X, $Y),
2353 mdraw_coordinates_position () returns the character position of
2355 If $Y is less than the minimum Y-coordinate of the drawn area, it
2356 returns $FROM.\n\n\n
2357 If $Y is greater than the maximum Y-coordinate of the drawn area,
2358 it returns $TO.\n\n\n
2359 If $Y fits in with the drawn area but $X is less than the minimum
2360 X-coordinate, it returns the character position of the first
2361 character drawn on the line $Y.\n\n\n
2362 If $Y fits in with the drawn area but $X is greater than the
2363 maximum X-coordinate, it returns the character position of the
2364 last character drawn on the line $Y. */
2367 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2369 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2370 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2371 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2372 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2373 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2374 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2376 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2379 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2380 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2382 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2384 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2386 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2387 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2389 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2390 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2393 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2394 int x_offset, int y_offset, MDrawControl *control)
2396 MGlyphString *gstring;
2401 M_CHECK_POS_X (mt, from, -1);
2402 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2403 to = mtext_nchars (mt) + (control->cursor_width != 0);
2409 ASSURE_CONTROL (control);
2410 gstring = get_gstring (frame, mt, from, to, control);
2411 while (y + gstring->line_descent <= y_offset
2412 && gstring->to < to)
2415 y += gstring->line_descent;
2416 M17N_OBJECT_UNREF (gstring->top);
2417 gstring = get_gstring (frame, mt, from, to, control);
2418 y += gstring->line_ascent;
2421 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2422 if (! control->orientation_reversed)
2424 width = gstring->indent;
2425 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2426 if (g->pos >= from && g->pos < to)
2429 if (width > x_offset)
2435 width = - gstring->indent;
2436 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2437 if (g->pos >= from && g->pos < to)
2440 if (width < x_offset)
2445 M17N_OBJECT_UNREF (gstring->top);
2453 @brief Compute information about a glyph.
2455 The mdraw_glyph_info () function computes information about a
2456 glyph that covers a character at position $POS of the M-text $MT
2457 assuming that the text is drawn from the character at $FROM of $MT
2458 on a window of frame $FRAME using the mdraw_text_with_control ()
2459 function with the drawing control object $CONTROL.
2461 The information is stored in the members of $INFO. */
2463 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2465 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2466 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2467 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2468 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2470 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2478 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2479 MDrawControl *control, MDrawGlyphInfo *info)
2481 MGlyphString *gstring;
2485 M_CHECK_RANGE_X (mt, from, pos, -1);
2487 ASSURE_CONTROL (control);
2488 gstring = get_gstring (frame, mt, from, pos + 1, control);
2490 MERROR (MERROR_DRAW, -1);
2491 while (gstring->to <= pos)
2493 y += gstring->line_descent;
2494 M17N_OBJECT_UNREF (gstring->top);
2495 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2496 y += gstring->line_ascent;
2498 info->line_from = gstring->from;
2499 if (info->line_from < from)
2500 info->line_from = from;
2501 info->line_to = gstring->to;
2504 if (! control->orientation_reversed)
2506 info->x = gstring->indent;
2507 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2508 info->x += g->width;
2512 info->x = - gstring->indent;
2513 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2514 info->x -= g->width;
2515 while (g[-1].to == g->to)
2518 info->from = g->pos;
2520 info->glyph_code = g->code;
2521 info->this.x = g->lbearing;
2522 info->this.y = - gstring->line_ascent;
2523 info->this.height = gstring->height;
2524 info->this.width = - g->lbearing + g->width;
2525 if (g->rface->rfont)
2526 info->font = &g->rface->rfont->font;
2529 /* info->logical_width is calculated later. */
2531 if (info->from > info->line_from)
2533 /* The logically previous glyph is on this line. */
2534 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2536 info->prev_from = g_tmp->pos;
2538 else if (info->line_from > 0)
2540 /* The logically previous glyph is on the previous line. */
2541 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2542 gstring->from, control);
2543 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2545 info->prev_from = g_tmp->pos;
2546 M17N_OBJECT_UNREF (gst->top);
2549 info->prev_from = -1;
2551 if (GLYPH_INDEX (g) > 1)
2552 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2553 else if (! control->orientation_reversed)
2555 if (info->line_from > 0)
2559 int p = gstring->from - 1;
2561 gst = get_gstring (frame, mt, p, gstring->from, control);
2562 g_tmp = gst->glyphs + (gst->used - 2);
2563 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2564 M17N_OBJECT_UNREF (gst->top);
2567 info->left_from = info->left_to = -1;
2571 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2575 int p = gstring->to;
2577 gst = get_gstring (frame, mt, p, p + 1, control);
2578 g_tmp = gst->glyphs + (gst->used - 2);
2579 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2580 M17N_OBJECT_UNREF (gst->top);
2583 info->left_from = info->left_to = -1;
2586 if (info->to < gstring->to)
2588 /* The logically next glyph is on this line. */
2589 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2591 info->next_to = g_tmp->to;
2593 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2595 /* The logically next glyph is on the next line. */
2597 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2598 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2600 info->next_to = g_tmp->to;
2601 M17N_OBJECT_UNREF (gst->top);
2606 for (info->logical_width = (g++)->width;
2607 g->pos == pos && g->type != GLYPH_ANCHOR;
2608 info->this.width += g->width, info->logical_width += (g++)->width);
2609 info->this.width += g[-1].rbearing - g[-1].width;
2611 if (g->type != GLYPH_ANCHOR)
2612 info->right_from = g->pos, info->right_to = g->to;
2613 else if (! control->orientation_reversed)
2615 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2618 M17N_OBJECT_UNREF (gstring->top);
2619 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2621 info->right_from = g->pos, info->right_to = g->to;
2624 info->right_from = info->right_to = -1;
2628 if (info->line_from > 0)
2630 pos = gstring->from - 1;
2631 M17N_OBJECT_UNREF (gstring->top);
2632 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2634 info->right_from = g->pos, info->right_to = g->to;
2637 info->right_from = info->right_to = -1;
2640 M17N_OBJECT_UNREF (gstring->top);
2647 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2648 MDrawControl *control, MDrawGlyphInfo *info,
2649 int array_size, int *num_glyphs_return)
2651 MGlyphString *gstring;
2656 ASSURE_CONTROL (control);
2657 *num_glyphs_return = 0;
2658 M_CHECK_RANGE (mt, from, to, -1, 0);
2659 gstring = get_gstring (frame, mt, from, to, control);
2662 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2664 if (g->type == GLYPH_BOX
2665 || g->pos < from || g->pos >= to)
2667 if (g->type == GLYPH_PAD)
2669 if (g->left_padding)
2670 pad_width = g->width;
2674 info[-1]->x += g->width;
2675 info[-1]->this.x += g->width;
2676 info[-1]->this.width += g->width;
2677 info[-1]->logical_width += g->width;
2683 info->from = g->pos;
2685 info->glyph_code = g->code;
2686 info->x = g->xoff + pad_width;
2688 info->this.x = g->lbearing + pad_width;
2689 info->this.y = - g->ascent;
2690 info->this.height = g->ascent + g->descent;
2691 info->this.width = g->rbearing - g->lbearing + pad_width;
2692 info->logical_width = g->width;
2693 if (g->rface->rfont)
2694 info->font = &g->rface->rfont->font;
2702 M17N_OBJECT_UNREF (gstring->top);
2704 *num_glyphs_return = n;
2705 return (n <= array_size ? 0 : -1);
2711 @brief Draw one or more textitems.
2713 The mdraw_text_items () function draws one or more M-texts on
2714 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2715 of the textitems to be drawn and $NITEMS is the number of
2716 textimtems in the array. */
2719 @brief textitem ¤òɽ¼¨¤¹¤ë.
2721 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2722 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2723 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2726 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2730 MTextItem, mdraw_text (). */
2733 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2734 MDrawTextItem *items, int nitems)
2736 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2738 while (nitems-- > 0)
2741 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2743 mdraw_text_with_control (frame, win, x, y,
2744 items->mt, 0, mtext_nchars (items->mt),
2746 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2747 items->control, NULL, NULL, NULL);
2750 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2756 @brief calculate a line breaking position.
2758 The function mdraw_default_line_break () calculates a line
2759 breaking position based on the line number $LINE and the
2760 coordinate $Y, when a line is too long to fit within the width
2761 limit. $POS is the position of the character next to the last
2762 one that fits within the limit. $FROM is the position of the
2763 first character of the line, and TO is the position of the last
2764 character displayed on the line if there were not width limit.
2765 LINE and Y are reset to 0 when a line is broken by a newline
2766 character, and incremented each time when a long line is broken
2767 because of the width limit.
2770 This function returns a character position to break the
2775 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2777 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2778 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2779 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2780 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2781 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2782 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2783 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2786 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2790 mdraw_default_line_break (MText *mt, int pos,
2791 int from, int to, int line, int y)
2793 int c = mtext_ref_char (mt, pos);
2796 if (c == ' ' || c == '\t')
2800 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2807 if (c == ' ' || c == '\t')
2810 c = mtext_ref_char (mt, pos);
2823 @brief Obtain per character dimension information.
2825 The mdraw_per_char_extents () function computes the text dimension
2826 of each character in M-text $MT. The faces given as text
2827 properties in $MT and the default face of frame $FRAME determine
2828 the fonts to draw the text. Each successive element in
2829 $ARRAY_RETURN is set to the drawn metrics of successive
2830 characters, which is relative to the origin of the drawing, and a
2831 rectangle for each character in $MT. The number of elements of
2832 $ARRAY_RETURN must be equal to or greater than the number of
2835 If pointer $OVERALL_RETURN is not @c NULL, this function also
2836 computes the extents of the overall text and stores the results in
2837 the members of the structure pointed to by $OVERALL_RETURN. */
2840 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2842 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2843 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2844 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2845 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2846 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2847 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2850 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2851 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2854 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2857 mdraw_per_char_extents (MFrame *frame, MText *mt,
2858 MDrawMetric *array_return,
2859 MDrawMetric *overall_return)
2861 int n = mtext_nchars (mt);
2863 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2864 n, &n, overall_return, NULL);
2868 @brief clear cached information.
2870 The mdraw_clear_cache () function clear cached information
2871 on M-text $MT that was attached by any of the drawing functions.
2872 When the behaviour of `format' or `line_break'
2873 member functions of MDrawControl is changed, the cache must be cleared.
2878 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2880 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2881 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2882 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2883 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2888 mdraw_clear_cache (MText *mt)
2890 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);