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_CHAR)
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)
357 APPEND_GLYPH (gstring, g_tmp);
363 APPEND_GLYPH (gstring, g_tmp);
365 && gstring->control.two_dimensional)
369 /* Append an anchor glyph. */
370 g_tmp.type = GLYPH_ANCHOR;
372 g_tmp.code = MCHAR_INVALID_CODE;
373 g_tmp.pos = g_tmp.to = pos;
375 APPEND_GLYPH (gstring, g_tmp);
379 /* Next, run FLT if necessary. */
380 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
384 if (this->type == GLYPH_CHAR && this->rface->rfont)
388 if (this->rface->rfont->layouter != Mnil)
393 for (prev = MGLYPH (start - 1);
394 (prev->type == GLYPH_CHAR
395 && prev->category == McatCf
396 && (code = mfont__encode_char (this->rface->rfont, prev->c)
397 != MCHAR_INVALID_CODE));
402 (g->type == GLYPH_CHAR
403 && (g->rface->rfont == this->rface->rfont
404 || (g->category == McatCf
405 && ((code = mfont__encode_char (this->rface->rfont,
407 != MCHAR_INVALID_CODE))));
409 if (g->rface->rfont != this->rface->rfont)
411 g->rface->rfont = this->rface->rfont;
414 i = mfont__flt_run (gstring, start, i, this->rface);
418 while (this->type == GLYPH_CHAR
421 && MSYMBOL_NAME (this->category)[0] == 'M'
422 && this->rface->rfont
423 && this->rface->rfont->layouter == Mnil)
425 int class = (int) mchar_get_prop (this->c,
428 = MAKE_COMBINING_CODE_BY_CLASS (class);
432 reorder_combining_chars (gstring, start, i);
433 if (this->type == GLYPH_ANCHOR)
442 /* At last, reorder glyphs visually if necessary. */
443 if (gstring->control.enable_bidi)
444 visual_order (gstring);
449 combining_code_from_class (int class)
454 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
455 else if (class == 200) /* below left attached */
456 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
457 else if (class == 202) /* below attached*/
458 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
459 else if (class == 204) /* below right attached */
460 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
461 else if (class == 208) /* left attached */
462 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
463 else if (class == 210) /* right attached */
464 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
465 else if (class == 212) /* above left attached */
466 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
467 else if (class == 214) /* above attached */
468 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
469 else if (class == 216) /* above right attached */
470 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
471 else if (class == 218) /* below left */
472 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
473 else if (class == 220) /* below */
474 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
475 else if (class == 222) /* below right */
476 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
477 else if (class == 224) /* left */
478 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
479 else if (class == 226) /* right */
480 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
481 else if (class == 228) /* above left */
482 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
483 else if (class == 230) /* above */
484 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
485 else if (class == 232) /* above right */
486 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
487 else if (class == 233) /* double below */
488 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
489 else if (class == 234) /* double above */
490 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
491 else if (class == 240) /* iota subscript */
492 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
494 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
500 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
502 int g_physical_ascent, g_physical_descent;
503 int g_width, g_lbearing, g_rbearing;
504 MGlyph *g = MGLYPH (from);
505 MGlyph *last_g = MGLYPH (to);
507 g_physical_ascent = gstring->physical_ascent;
508 g_physical_descent = gstring->physical_descent;
509 g_width = g_lbearing = g_rbearing = 0;
511 mfont__get_metric (gstring, from, to);
516 MRealizedFont *rfont = base->rface->rfont;
517 int size = rfont->font.property[MFONT_SIZE];
518 int width, lbearing, rbearing;
520 if (g == last_g || ! g->combining_code)
523 if (base->left_padding && base->lbearing < 0)
525 base->xoff = - base->lbearing;
526 base->width += base->xoff;
527 base->rbearing += base->xoff;
530 if (base->right_padding && base->rbearing > base->width)
532 base->width = base->rbearing;
534 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
535 rbearing = base->rbearing;
539 /* With combining glyphs. */
540 int left = -base->width;
542 int top = - base->ascent;
543 int bottom = base->descent;
544 int height = bottom - top;
545 int begin = base->pos;
550 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
551 rbearing = base->rbearing;
553 while (g != last_g && g->combining_code)
555 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
557 combining_code = g->combining_code;
558 if (COMBINING_BY_CLASS_P (combining_code))
559 g->combining_code = combining_code
560 = combining_code_from_class (COMBINING_CODE_CLASS
563 rfont = g->rface->rfont;
564 size = rfont->font.property[MFONT_SIZE];
565 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
567 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
569 base_x = COMBINING_CODE_BASE_X (combining_code);
570 base_y = COMBINING_CODE_BASE_Y (combining_code);
571 add_x = COMBINING_CODE_ADD_X (combining_code);
572 add_y = COMBINING_CODE_ADD_Y (combining_code);
576 else if (end < g->to)
579 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
582 if (g->xoff + g->width > right)
583 right = g->xoff + g->width;
584 width = right - left;
585 if (g->xoff + g->lbearing < left + lbearing)
586 lbearing = g->xoff + g->lbearing - left;
587 if (g->xoff + g->rbearing > left + rbearing)
588 rbearing = g->xoff + g->rbearing - left;
591 g->yoff = top + height * base_y / 2;
595 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
597 if (g->yoff - g->ascent < top)
598 top = g->yoff - g->ascent;
599 if (g->yoff + g->descent > bottom)
600 bottom = g->yoff + g->descent;
601 height = bottom - top;
607 base->ascent = - top;
608 base->descent = bottom;
609 base->lbearing = lbearing;
610 base->rbearing = rbearing;
611 if (left < - base->width)
613 base->xoff = - base->width - left;
614 base->width += base->xoff;
615 base->rbearing += base->xoff;
616 base->lbearing += base->xoff;
620 base->width += right;
621 base->rbearing += right;
622 base->right_padding = 1;
623 for (i = 1; base + i != g; i++)
624 base[i].xoff -= right;
627 for (i = 0; base + i != g; i++)
634 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
635 g_physical_descent = MAX (g_physical_descent, base->descent);
636 g_lbearing = MIN (g_lbearing, g_width + lbearing);
637 g_rbearing = MAX (g_rbearing, g_width + rbearing);
638 g_width += base->width;
641 gstring->physical_ascent = g_physical_ascent;
642 gstring->physical_descent = g_physical_descent;
643 gstring->sub_width = g_width;
644 gstring->sub_lbearing = g_lbearing;
645 gstring->sub_rbearing = g_rbearing;
649 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
650 by this function directly. Character glyphs are handled by
651 layouter functions registered in font drivers.
653 This function fill-in all the remaining members of glyphs. */
656 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
658 /* Default width of TAB. */
659 int tab_width = frame->space_width * (gstring->control.tab_width
660 ? gstring->control.tab_width : 8);
664 MDrawControl *control = &(gstring->control);
667 int box_line_height = 0;
668 int ignore_formatting_char = control->ignore_formatting_char;
670 gstring->ascent = gstring->descent = 0;
671 gstring->physical_ascent = gstring->physical_descent = 0;
672 gstring->width = gstring->lbearing = gstring->rbearing = 0;
676 while (g->type != GLYPH_ANCHOR)
678 if (box != g->rface->box)
680 int gidx = GLYPH_INDEX (g);
684 /* Insert the right side of the box. That glyph belongs
685 to the previous grapheme cluster. */
686 MGlyph box_glyph = g[-1];
688 box_glyph.type = GLYPH_BOX;
690 = (control->fixed_width
692 : box->inner_hmargin + box->width + box->outer_hmargin);
693 box_glyph.lbearing = 0;
694 box_glyph.rbearing = box_glyph.width;
696 box_glyph.right_padding = 1;
697 gstring->width += box_glyph.width;
698 gstring->rbearing += box_glyph.width;
699 INSERT_GLYPH (gstring, gidx, box_glyph);
706 /* Insert the left side of the box. That glyph belongs
707 to the following grapheme cluster. */
708 MGlyph box_glyph = *g;
709 int box_height = (box->width
710 + box->inner_vmargin + box->outer_vmargin);
712 if (box_line_height < box_height)
713 box_line_height = box_height;
714 box_glyph.type = GLYPH_BOX;
716 = (control->fixed_width
718 : box->inner_hmargin + box->width + box->outer_hmargin);
719 box_glyph.lbearing = 0;
720 box_glyph.rbearing = box_glyph.width;
722 box_glyph.left_padding = 1;
723 gstring->width += box_glyph.width;
724 gstring->rbearing += box_glyph.width;
725 INSERT_GLYPH (gstring, gidx, box_glyph);
731 if (g->category == McatCf && ignore_formatting_char)
732 g->type = GLYPH_SPACE;
734 if (g->type == GLYPH_CHAR)
736 MRealizedFace *rface = g->rface;
737 MRealizedFont *rfont = rface->rfont;
739 int from = GLYPH_INDEX (g);
741 for (g++; g->type == GLYPH_CHAR; g++)
742 if (! rfont != ! g->rface->rfont
743 || box != g->rface->box
744 || ((fromg->code == MCHAR_INVALID_CODE)
745 != (g->code == MCHAR_INVALID_CODE))
746 || (g->category == McatCf && ignore_formatting_char))
748 if (rfont && fromg->code != MCHAR_INVALID_CODE)
751 int to = GLYPH_INDEX (g);
753 layout_glyphs (frame, gstring, from, to);
754 extra_width = - gstring->sub_lbearing;
756 && (GLYPH_INDEX (g) > 1
757 || control->align_head))
761 pad.type = GLYPH_PAD;
764 pad.width = pad.rbearing = extra_width;
765 INSERT_GLYPH (gstring, from, pad);
767 gstring->sub_lbearing = 0;
768 gstring->sub_width += extra_width;
769 gstring->sub_rbearing += extra_width;
771 g = MGLYPH (from - 1);
772 if (g->type == GLYPH_SPACE)
774 /* The pad just inserted is absorbed (maybe
775 partially) by the previous space while
776 keeping at least some space width. For the
777 moment, we use the arbitrary width 2-pixel.
778 Perhaps, it should be decided by the current
779 face, or a default value of the current
780 frame, which is, however, not yet
782 if (extra_width + 2 < g->width)
784 g->width -= extra_width;
788 extra_width -= g->width - 2;
791 gstring->width -= extra_width;
792 gstring->rbearing -= extra_width;
796 extra_width = gstring->sub_rbearing - gstring->sub_width;
800 if (g->type == GLYPH_SPACE && box == g->rface->box)
804 pad.type = GLYPH_PAD;
807 pad.width = pad.rbearing = extra_width;
808 INSERT_GLYPH (gstring, to, pad);
812 g[-1].width += extra_width;
813 gstring->sub_width += extra_width;
816 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
817 gstring->lbearing = gstring->width + gstring->sub_lbearing;
818 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
819 gstring->rbearing = gstring->width + gstring->sub_rbearing;
820 gstring->width += gstring->sub_width;
821 if (gstring->ascent < rface->ascent)
822 gstring->ascent = rface->ascent;
823 if (gstring->descent < rface->descent)
824 gstring->descent = rface->descent;
829 for (; fromg < g; fromg++)
831 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
832 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
833 fromg->width = fromg->rbearing = 1;
835 fromg->width = fromg->rbearing = rface->space_width;
836 fromg->xoff = fromg->lbearing = 0;
837 fromg->ascent = fromg->descent = 0;
838 gstring->width += fromg->width;
839 gstring->rbearing += fromg->width;
841 if (gstring->ascent < frame->rface->ascent)
842 gstring->ascent = frame->rface->ascent;
843 if (gstring->descent < frame->descent)
844 gstring->descent = frame->rface->descent;
847 else if (g->type == GLYPH_SPACE)
850 g->width = g->rface->space_width;
851 else if (g->c == '\n')
853 g->width = control->cursor_width;
856 if (control->cursor_bidi)
858 else if (g->width < 0)
859 g->width = g->rface->space_width;
862 else if (g->c == '\t')
864 g->width = tab_width - ((gstring->indent + gstring->width)
870 if (g[-1].type == GLYPH_PAD)
872 /* This space glyph absorbs (maybe partially) the
873 previous padding glyph. */
874 g->width -= g[-1].width;
876 /* But, keep at least some space width. For the
877 moment, we use the arbitrary width 2-pixel. */
880 g->rbearing = g->width;
881 gstring->width += g->width;
882 gstring->rbearing += g->width;
885 if (gstring->ascent < g->rface->ascent)
886 gstring->ascent = g->rface->ascent;
887 if (gstring->descent < g->rface->descent)
888 gstring->descent = g->rface->descent;
894 gstring->width += g->width;
895 gstring->rbearing += g->width;
902 /* Insert the right side of the box. */
903 int gidx = GLYPH_INDEX (g);
904 MGlyph box_glyph = g[-1];
906 box_glyph.type = GLYPH_BOX;
908 = (control->fixed_width
910 : box->inner_hmargin + box->width + box->outer_hmargin);
911 box_glyph.lbearing = 0;
912 box_glyph.rbearing = box_glyph.width;
914 box_glyph.right_padding = 1;
915 gstring->width += box_glyph.width;
916 gstring->rbearing += box_glyph.width;
917 INSERT_GLYPH (gstring, gidx, box_glyph);
920 gstring->text_ascent = gstring->ascent;
921 gstring->text_descent = gstring->descent;
922 if (gstring->text_ascent < gstring->physical_ascent)
923 gstring->text_ascent = gstring->physical_ascent;
924 if (gstring->text_descent < gstring->physical_descent)
925 gstring->text_descent = gstring->physical_descent;
926 gstring->line_ascent = gstring->text_ascent;
927 gstring->line_descent = gstring->text_descent;
928 if (box_line_height > 0)
930 gstring->line_ascent += box_line_height;
931 gstring->physical_ascent = gstring->line_ascent;
932 gstring->line_descent += box_line_height;
933 gstring->physical_descent = gstring->line_descent;
936 if (gstring->line_ascent < control->min_line_ascent)
937 gstring->line_ascent = control->min_line_ascent;
938 else if (control->max_line_ascent
939 && control->max_line_ascent > control->min_line_ascent
940 && gstring->line_ascent > control->max_line_ascent)
941 gstring->line_ascent = control->max_line_ascent;
943 if (gstring->line_descent < control->min_line_descent)
944 gstring->line_descent = control->min_line_descent;
945 else if (control->max_line_descent
946 && control->max_line_descent > control->min_line_descent
947 && gstring->line_descent > control->max_line_descent)
948 gstring->line_descent = control->max_line_descent;
949 gstring->height = gstring->line_ascent + gstring->line_descent;
951 if (control->orientation_reversed
954 /* We must adjust TAB width for RTL orientation. */
955 width = gstring->indent;
957 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
959 if (g->type == GLYPH_CHAR && g->c == '\t')
961 int this_width = tab_width - (width % tab_width);
963 if (g[1].type == GLYPH_PAD)
964 this_width -= g[1].width;
965 if (g[-1].type == GLYPH_PAD)
966 this_width -= g[-1].width;
969 gstring->width += this_width - g->width;
970 gstring->rbearing += this_width - g->width;
971 g->width = this_width;
982 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
983 MGlyphString *gstring, int from, int to,
984 int *from_idx, int *to_idx, int *to_x)
986 MGlyph *g = MGLYPH (1);
987 MDrawRegion region = (MDrawRegion) NULL;
988 MDrawControl *control = &gstring->control;
991 int cursor_bidi = control->cursor_bidi;
993 if (control->with_cursor && control->cursor_width)
995 if (gstring->from <= control->cursor_pos
996 && gstring->to > control->cursor_pos)
997 cursor_pos = control->cursor_pos;
999 && gstring->from <= control->cursor_pos - 1
1000 && gstring->to > control->cursor_pos - 1)
1001 prev_pos = control->cursor_pos - 1;
1004 *from_idx = *to_idx = 0;
1005 while (g->type != GLYPH_ANCHOR)
1007 if (g->pos >= from && g->pos < to)
1009 MGlyph *fromg = g, *cursor = NULL;
1010 MRealizedFace *rface = g->rface;
1012 int cursor_width = 0;
1016 *from_idx = GLYPH_INDEX (g);
1017 while (g->pos >= from && g->pos < to
1018 && g->rface == rface)
1021 if (g->type != GLYPH_BOX
1022 && g->pos <= cursor_pos && g->to > cursor_pos)
1025 cursor = g, cursor_x = x + width;
1026 cursor_width += g->width;
1028 width += g++->width;
1031 && (control->as_image
1032 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1034 int this_x = x, this_width = width;
1036 if (fromg->type == GLYPH_BOX)
1037 this_x += fromg->width, this_width -= fromg->width;
1038 if (g[-1].type == GLYPH_BOX)
1039 this_width -= g[-1].width;
1040 (frame->driver->fill_space)
1041 (frame, win, rface, 0,
1042 this_x, y - gstring->text_ascent, this_width,
1043 gstring->text_ascent + gstring->text_descent,
1044 control->clip_region);
1051 rect.y = y - gstring->text_ascent;
1052 rect.height = gstring->text_ascent + gstring->text_descent;
1055 rect.width = ((control->cursor_width > 0
1056 && control->cursor_width < cursor_width)
1057 ? control->cursor_width : cursor_width);
1061 if (cursor->bidi_level % 2)
1062 rect.x += cursor_width - 1;
1065 (*frame->driver->fill_space)
1066 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1067 control->clip_region);
1069 region = (*frame->driver->region_from_rect) (&rect);
1071 (*frame->driver->region_add_rect) (region, &rect);
1074 if (cursor->bidi_level % 2)
1077 rect.width = cursor_width < 4 ? cursor_width : 4;
1078 (*frame->driver->fill_space)
1079 (frame, win, rface, 1,
1080 rect.x, rect.y, rect.width, rect.height,
1081 control->clip_region);
1082 (*frame->driver->region_add_rect) (region, &rect);
1094 if (fromg->type != GLYPH_BOX
1095 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1098 cursor = fromg, cursor_x = x + temp_width;
1099 cursor_width += fromg->width;
1101 temp_width += fromg++->width;
1108 if (! (cursor->bidi_level % 2))
1109 rect.x += cursor_width - 1;
1110 rect.y = y - gstring->text_ascent;
1111 rect.height = gstring->text_ascent + gstring->text_descent;
1113 (*frame->driver->fill_space)
1114 (frame, win, rface, 1,
1115 rect.x, rect.y, rect.width, rect.height,
1116 control->clip_region);
1118 region = (*frame->driver->region_from_rect) (&rect);
1120 (*frame->driver->region_add_rect) (region, &rect);
1121 rect.y += rect.height - 2;
1123 rect.width = cursor_width < 4 ? cursor_width : 4;
1124 if (! (cursor->bidi_level % 2))
1125 rect.x -= rect.width - 1;
1126 (*frame->driver->fill_space) (frame, win, rface, 1,
1127 rect.x, rect.y, rect.width, rect.height,
1128 control->clip_region);
1129 (*frame->driver->region_add_rect) (region, &rect);
1133 *to_idx = GLYPH_INDEX (g);
1143 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1144 MGlyphString *gstring, int from_idx, int to_idx,
1145 int reverse, MDrawRegion region)
1147 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1153 (*frame->driver->region_to_rect) (region, &rect);
1156 while (g != gend && x + g->rbearing <= rect.x)
1159 width -= g++->width;
1160 while (! g->enabled && g != gend)
1164 rect.x += rect.width;
1165 if (rect.x < x + width)
1168 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1170 width -= (--gend)->width;
1171 while (! gend->enabled && g != gend)
1175 while (gend[-1].to == gend->to) gend++;
1183 MRealizedFace *rface = g->rface;
1184 int width = g->width;
1185 MGlyph *from_g = g++;
1187 /* Handle the glyphs of the same type/face at once. */
1189 && g->type == from_g->type
1190 && g->rface == rface
1191 && (g->code < 0) == (from_g->code < 0)
1193 width += g++->width;
1195 if (from_g->type == GLYPH_CHAR)
1197 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1198 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1201 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1204 else if (from_g->type == GLYPH_BOX)
1206 /* Draw the left or right side of a box. If
1207 from_g->lbearing is nonzero, this is the left side,
1208 else this is the right side. */
1209 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1212 if (from_g->type != GLYPH_BOX)
1215 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1216 x, y, width, region);
1219 /* Draw the top and bottom side of a box. */
1220 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1221 x, y, width, region);
1232 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1233 int *from_x, int *to_x)
1236 int left_idx = *left, right_idx = *right;
1237 int left_x, right_x, x;
1239 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1242 if (x + g->rbearing > 0)
1244 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1246 left_idx = GLYPH_INDEX (g);
1251 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1254 if (x - g->width + g->lbearing < 0)
1256 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1258 right_idx = GLYPH_INDEX (g) + 1;
1263 if (*left == left_idx && *right == right_idx)
1266 if (*left != left_idx)
1268 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1273 if (*right != right_idx)
1275 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1285 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1290 if (from <= gstring->from && to >= gstring->to)
1293 *rbearing = gstring->rbearing;
1294 return gstring->width;
1299 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1300 if (g->pos >= from && g->pos < to)
1302 if (rbearing && width + g->rbearing > *rbearing)
1303 *rbearing = width + g->rbearing;
1311 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1312 MGlyphString *gstring, int from, int to)
1314 MDrawControl *control = &gstring->control;
1316 MDrawRegion clip_region, cursor_region;
1317 int from_idx, to_idx;
1320 if (control->orientation_reversed)
1321 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1323 x += gstring->indent;
1325 /* At first, draw all glyphs without cursor. */
1326 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1327 &from_idx, &to_idx, &to_x);
1329 if (control->partial_update)
1332 rect.width = to_x - x;
1333 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1335 rect.y = y - gstring->line_ascent;
1336 rect.height = gstring->height;
1337 clip_region = (*frame->driver->region_from_rect) (&rect);
1338 if (control->clip_region)
1339 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1342 clip_region = control->clip_region;
1345 clip_region = control->clip_region;
1347 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1352 (*frame->driver->intersect_region) (cursor_region, clip_region);
1353 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1356 if (clip_region != control->clip_region)
1357 (*frame->driver->free_region) (clip_region);
1359 (*frame->driver->free_region) (cursor_region);
1363 static int gstring_num;
1366 free_gstring (void *object)
1368 MGlyphString *gstring = (MGlyphString *) object;
1371 free_gstring (gstring->next);
1372 if (gstring->size > 0)
1373 free (gstring->glyphs);
1379 static MGlyphString scratch_gstring;
1381 static MGlyphString *
1382 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1385 MGlyphString *gstring;
1387 if (pos == mt->nchars)
1389 gstring = &scratch_gstring;
1393 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1394 MLIST_INIT1 (gstring, glyphs, 128);
1398 gstring->frame = frame;
1399 gstring->tick = frame->tick;
1400 gstring->top = gstring;
1402 gstring->control = *control;
1403 gstring->indent = gstring->width_limit = 0;
1404 if (control->format)
1405 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1407 gstring->width_limit = control->max_line_width;
1408 gstring->anti_alias = control->anti_alias;
1412 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1415 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1423 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1424 a width of glyphs for the character at I of GSTRING->mt. If I is
1425 not a beginning of a grapheme cluster, the corresponding element
1427 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1428 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1429 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1430 pos_width[g->pos - gstring->from] += g->width;
1431 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1433 if (pos_width[i] > 0)
1435 if (width + pos_width[i] > gstring->width_limit)
1438 width += pos_width[i];
1441 pos = gstring->from + i;
1442 if (gstring->control.line_break)
1444 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1445 gstring->from, gstring->to, 0, 0);
1446 if (pos <= gstring->from || pos >= gstring->to)
1449 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1450 layout_glyph_string (frame, gstring);
1454 /* Return a gstring that covers a character at POS. */
1456 static MGlyphString *
1457 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1459 MGlyphString *gstring = NULL;
1461 if (pos < mtext_nchars (mt))
1463 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1466 && ((prop->start != 0
1467 && mtext_ref_char (mt, prop->start - 1) != '\n')
1468 || (prop->end < mtext_nchars (mt)
1469 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1471 mtext_detach_property (prop);
1476 gstring = prop->val;
1477 if (gstring->frame != frame
1478 || gstring->tick != frame->tick
1479 || memcmp (control, &gstring->control,
1480 (char *) (&control->with_cursor)
1481 - (char *) (control)))
1483 mtext_detach_property (prop);
1488 else if (! control->cursor_width)
1496 offset = mtext_character (mt, pos, 0, '\n');
1501 offset -= gstring->from;
1503 for (gst = gstring; gst; gst = gst->next)
1507 gst->from += offset;
1509 for (i = 0; i < gst->used; i++)
1511 gst->glyphs[i].pos += offset;
1512 gst->glyphs[i].to += offset;
1515 M17N_OBJECT_REF (gstring);
1520 int line = 0, y = 0;
1522 if (control->two_dimensional)
1524 beg = mtext_character (mt, pos, 0, '\n');
1529 end = mtext_nchars (mt) + (control->cursor_width != 0);
1536 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1537 compose_glyph_string (frame, mt, beg, end, gstring);
1538 layout_glyph_string (frame, gstring);
1540 if (control->two_dimensional
1541 && gstring->width_limit
1542 && gstring->width > gstring->width_limit)
1544 MGlyphString *gst = gstring;
1546 truncate_gstring (frame, mt, gst);
1547 while (gst->to < end)
1549 line++, y += gst->height;
1550 gst->next = alloc_gstring (frame, mt, gst->from, control,
1552 gst->next->top = gstring;
1553 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1555 layout_glyph_string (frame, gst);
1556 if (gst->width <= gst->width_limit)
1558 truncate_gstring (frame, mt, gst);
1562 if (! control->disable_caching && pos < mtext_nchars (mt))
1564 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1565 MTEXTPROP_VOLATILE_STRONG);
1567 if (end > mtext_nchars (mt))
1568 end = mtext_nchars (mt);
1569 mtext_attach_property (mt, beg, end, prop);
1570 M17N_OBJECT_UNREF (prop);
1574 while (gstring->to <= pos)
1576 if (! gstring->next)
1578 gstring = gstring->next;
1580 gstring->control = *control;
1586 static MDrawControl control_noop;
1588 #define ASSURE_CONTROL(control) \
1590 control = &control_noop; \
1595 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1596 MText *mt, int from, int to,
1597 MDrawControl *control)
1599 MGlyphString *gstring;
1601 M_CHECK_POS_X (mt, from, -1);
1602 ASSURE_CONTROL (control);
1603 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1604 to = mtext_nchars (mt) + (control->cursor_width != 0);
1608 gstring = get_gstring (frame, mt, from, to, control);
1610 MERROR (MERROR_DRAW, -1);
1611 render_glyph_string (frame, win, x, y, gstring, from, to);
1615 y += gstring->line_descent;
1616 M17N_OBJECT_UNREF (gstring->top);
1617 gstring = get_gstring (frame, mt, from, to, control);
1618 y += gstring->line_ascent;
1619 render_glyph_string (frame, win, x, y, gstring, from, to);
1622 M17N_OBJECT_UNREF (gstring->top);
1629 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1635 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1636 if (g->pos <= pos && g->to > pos)
1641 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1642 if (g->pos <= pos && g->to > pos)
1649 /* for debugging... */
1653 dump_combining_code (int code)
1655 char *vallign = "tcbB";
1656 char *hallign = "lcr";
1662 if (COMBINING_BY_CLASS_P (code))
1663 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1664 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1665 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1666 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1667 off_x = COMBINING_CODE_OFF_X (code) - 128;
1669 sprintf (work + 2, "+%d", off_y);
1671 sprintf (work + 2, "%d", off_y);
1672 else if (off_x == 0)
1673 sprintf (work + 2, ".");
1674 p = work + strlen (work);
1676 sprintf (p, ">%d", off_x);
1678 sprintf (p, "<%d", -off_x);
1680 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1681 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1687 dump_gstring (MGlyphString *gstring, int indent)
1689 char *prefix = (char *) alloca (indent + 1);
1690 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1692 memset (prefix, 32, indent);
1695 fprintf (stderr, "(glyph-string");
1697 for (g = MGLYPH (0); g < last_g; g++)
1699 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1701 g - gstring->glyphs,
1702 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1703 : g->type == GLYPH_ANCHOR ? "ANC"
1704 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1705 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1706 dump_combining_code (g->combining_code),
1707 g->width, g->bidi_level);
1708 fprintf (stderr, ")");
1712 /* m17n-X internal APIs */
1717 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1719 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1720 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1722 Mlatin = msymbol ("latin");
1723 Minherited = msymbol ("inherited");
1725 McatCc = msymbol ("Cc");
1726 McatCf = msymbol ("Cf");
1728 MbidiR = msymbol ("R");
1729 MbidiAL = msymbol ("AL");
1730 MbidiRLE = msymbol ("RLE");
1731 MbidiRLO = msymbol ("RLO");
1732 MbidiBN = msymbol ("BN");
1733 MbidiS = msymbol ("S");
1735 fribidi_set_mirroring (TRUE);
1744 MLIST_FREE1 (&scratch_gstring, glyphs);
1748 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1752 /*** @addtogroup m17nDraw */
1757 @brief Draw an M-text on a window.
1759 The mdraw_text () function draws the text between $FROM and $TO of
1760 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1762 The appearance of the text (size, style, color, etc) is specified
1763 by the value of the text property whose key is @c Mface. If the
1764 M-text or a part of the M-text does not have such a text property,
1765 the default face of $FRAME is used.
1767 The font used to draw a character in the M-text is selected from
1768 the value of the fontset property of a face by the following
1773 <li> Search the text properties given to the character for the one
1774 whose key is @c Mcharset; its value should be either a symbol
1775 specifying a charset or #Mnil. If the value is #Mnil,
1776 proceed to the next step.
1778 Otherwise, search the mapping table of the fontset for the
1779 charset. If no entry is found proceed to the next step.
1781 If an entry is found, use one of the fonts in the entry that
1782 has a glyph for the character and that matches best with the
1783 face properties. If no such font exists, proceed to the next
1786 <li> Get the character property "script" of the character. If it is
1787 inherited, get the script property from the previous
1788 characters. If there is no previous character, or none of
1789 them has the script property other than inherited, proceed to
1792 Search the text properties given to the character for the one
1793 whose key is @c Mlanguage; its value should be either a
1794 symbol specifying a language or @c Mnil.
1796 Search the mapping table of the fontset for the combination
1797 of the script and language. If no entry is found, proceed to
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> Search the fall-back table of the fontset for a font that has
1806 a glyph of the character. If such a font is found, use that
1811 If no font is found by the algorithm above, this function draws an
1812 empty box for the character.
1814 This function draws only the glyph foreground. To specify the
1815 background color, use mdraw_image_text () or
1816 mdraw_text_with_control ().
1818 This function is the counterpart of <tt>XDrawString ()</tt>,
1819 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1820 in the X Window System.
1823 If the operation was successful, mdraw_text () returns 0. If an
1824 error is detected, it returns -1 and assigns an error code to the
1825 external variable #merror_code. */
1827 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1829 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1830 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1833 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1834 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1835 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1836 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1838 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1839 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1843 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1844 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1845 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1846 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1847 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1850 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1851 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1852 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1855 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1856 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1857 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1858 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1860 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1861 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1864 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1865 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1868 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1869 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1870 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1873 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1874 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1878 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1879 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1881 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1882 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1885 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1886 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1889 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1890 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1892 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1899 mdraw_image_text () */
1902 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1903 MText *mt, int from, int to)
1905 MDrawControl control;
1907 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1908 memset (&control, 0, sizeof control);
1909 control.as_image = 0;
1910 return draw_text (frame, win, x, y, mt, from, to, &control);
1917 @brief Draw an M-text on a window as an image.
1919 The mdraw_image_text () function draws the text between $FROM and
1920 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1921 coordinate ($X, $Y).
1923 The way to draw a text is the same as in mdraw_text () except that
1924 this function also draws the background with the color specified
1927 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1928 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1929 functions in the X Window System.
1932 If the operation was successful, mdraw_image_text () returns 0.
1933 If an error is detected, it returns -1 and assigns an error code
1934 to the external variable #merror_code. */
1937 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1939 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1940 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1943 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1944 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1946 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1947 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1951 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1952 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1955 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1965 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1966 MText *mt, int from, int to)
1968 MDrawControl control;
1970 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1971 memset (&control, 0, sizeof control);
1972 control.as_image = 1;
1973 return draw_text (frame, win, x, y, mt, from, to, &control);
1979 @brief Draw an M-text on a window with fine control.
1981 The mdraw_text_with_control () function draws the text between
1982 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1983 coordinate ($X, $Y).
1985 The way to draw a text is the same as in mdraw_text () except that
1986 this function also follows what specified in the drawing control
1989 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1990 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1991 breaks lines and the following characters are drawn in the next
1992 line. See the documentation of the structure @ MDrawControl for
1996 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
1998 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1999 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2002 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2003 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2005 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2006 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2007 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2011 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2012 MText *mt, int from, int to, MDrawControl *control)
2014 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2015 return draw_text (frame, win, x, y, mt, from, to, control);
2021 @brief Compute text pixel width.
2023 The mdraw_text_extents () function computes the width of text
2024 between $FROM and $TO of M-text $MT when it is drawn on a window
2025 of frame $FRAME using the mdraw_text_with_control () function with
2026 the drawing control object $CONTROL.
2028 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2029 the bounding box of character ink of the M-text, and stores the
2030 results in the members of the structure pointed to by
2031 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2032 surrounding box, the box is included in the bounding box.
2034 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2035 computes the bounding box that provides mininum spacing to other
2036 graphical features (such as surrounding box) for the M-text, and
2037 stores the results in the members of the structure pointed to by
2038 $OVERALL_LOGICAL_RETURN.
2040 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2041 computes the bounding box that provides mininum spacing to the
2042 other M-text drawn, and stores the results in the members of the
2043 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2044 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2045 min_line_ascent, min_line_descent, max_line_ascent, and
2046 max_line_descent of $CONTROL are all zero.
2049 This function returns the width of the text to be drawn in the
2050 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2051 text is drawn in multiple physical lines, it returns the width of
2052 the widest line. If an error occurs, it returns -1 and assigns an
2053 error code to the external variable #merror_code. */
2057 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2059 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2060 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2061 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2063 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2064 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2065 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2066 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2068 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2069 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2070 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2071 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2073 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2074 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2075 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2076 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2077 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2078 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2080 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2081 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2082 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2083 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2085 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2092 mdraw_text_extents (MFrame *frame,
2093 MText *mt, int from, int to, MDrawControl *control,
2094 MDrawMetric *overall_ink_return,
2095 MDrawMetric *overall_logical_return,
2096 MDrawMetric *overall_line_return)
2098 MGlyphString *gstring;
2100 int width, rbearing;
2102 ASSURE_CONTROL (control);
2103 M_CHECK_POS_X (mt, from, -1);
2104 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2105 to = mtext_nchars (mt) + (control->cursor_width != 0);
2109 gstring = get_gstring (frame, mt, from, to, control);
2111 MERROR (MERROR_DRAW, -1);
2112 width = gstring_width (gstring, from, to, &rbearing);
2113 if (overall_ink_return)
2115 overall_ink_return->y = - gstring->physical_ascent;
2116 overall_ink_return->x = gstring->lbearing;
2118 if (overall_logical_return)
2120 overall_logical_return->y = - gstring->ascent;
2121 overall_logical_return->x = 0;
2123 if (overall_line_return)
2125 overall_line_return->y = - gstring->line_ascent;
2126 overall_line_return->x = gstring->lbearing;
2129 for (from = gstring->to; from < to; from = gstring->to)
2131 int this_width, this_rbearing;
2133 y += gstring->line_descent;
2134 M17N_OBJECT_UNREF (gstring->top);
2135 gstring = get_gstring (frame, mt, from, to, control);
2136 this_width = gstring_width (gstring, from, to, &this_rbearing);
2137 y += gstring->line_ascent;
2138 if (width < this_width)
2140 if (rbearing < this_rbearing)
2141 rbearing = this_rbearing;
2143 if (overall_ink_return)
2145 overall_ink_return->width = rbearing;
2146 overall_ink_return->height
2147 = y + gstring->physical_descent - overall_ink_return->y;
2149 if (overall_logical_return)
2151 overall_logical_return->width = width;
2152 overall_logical_return->height
2153 = y + gstring->descent - overall_logical_return->y;
2155 if (overall_line_return)
2157 overall_line_return->width = MAX (width, rbearing);
2158 overall_line_return->height
2159 = y + gstring->line_descent - overall_line_return->y;
2162 M17N_OBJECT_UNREF (gstring->top);
2169 @brief Compute the text dimensions of each character of M-text.
2171 The mdraw_text_per_char_extents () function computes the drawn
2172 metric of each character between $FROM and $TO of M-text $MT
2173 assuming that they are drawn on a window of frame $FRAME using the
2174 mdraw_text_with_control () function with the drawing control
2177 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2178 $LOGICAL_ARRAY_RETURN. Each successive element of
2179 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2180 ink and logical metrics of successive characters respectively,
2181 relative to the drawing origin of the M-text. The number of
2182 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2183 been set is returned to $NUM_CHARS_RETURN.
2185 If $ARRAY_SIZE is too small to return all metrics, the function
2186 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2187 Otherwise, it returns zero.
2189 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2190 @c NULL, this function also computes the metrics of the overall
2191 text and stores the results in the members of the structure
2192 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2194 If $CONTROL->two_dimensional is nonzero, this function computes
2195 only the metrics of characters in the first line. */
2197 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2199 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2200 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2201 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2202 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2204 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2205 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2206 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2207 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2208 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2210 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2211 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2214 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2215 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2216 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2219 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2220 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2223 mdraw_text_per_char_extents (MFrame *frame,
2224 MText *mt, int from, int to,
2225 MDrawControl *control,
2226 MDrawMetric *ink_array_return,
2227 MDrawMetric *logical_array_return,
2229 int *num_chars_return,
2230 MDrawMetric *overall_ink_return,
2231 MDrawMetric *overall_logical_return)
2233 MGlyphString *gstring;
2237 ASSURE_CONTROL (control);
2238 *num_chars_return = to - from;
2239 if (array_size < *num_chars_return)
2240 MERROR (MERROR_DRAW, -1);
2241 if (overall_logical_return)
2242 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2243 if (overall_ink_return)
2244 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2246 M_CHECK_RANGE (mt, from, to, -1, 0);
2247 gstring = get_gstring (frame, mt, from, to, control);
2250 *num_chars_return = 0;
2254 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2255 if (g->pos >= from && g->pos < to)
2259 int width = g->width;
2260 int lbearing = g->lbearing;
2261 int rbearing = g->rbearing;
2262 int ascent = g->ascent;
2263 int descent = g->descent;
2264 int logical_ascent = g->rface->rfont->ascent;
2265 int logical_descent = g->rface->rfont->descent;
2267 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2269 if (lbearing < width + g->lbearing)
2270 lbearing = width + g->lbearing;
2271 if (rbearing < width + g->rbearing)
2272 rbearing = width + g->rbearing;
2274 if (ascent < g->ascent)
2276 if (descent < g->descent)
2277 descent = g->descent;
2284 ink_array_return[start - from].x = x + lbearing;
2285 ink_array_return[start - from].y = - ascent;
2286 ink_array_return[start - from].width = rbearing - lbearing;
2287 ink_array_return[start - from].height = ascent + descent;
2288 logical_array_return[start - from].x = x;
2289 logical_array_return[start - from].y = - logical_descent;
2290 logical_array_return[start - from].height
2291 = logical_ascent + logical_descent;
2292 logical_array_return[start - from].width = width;
2298 if (overall_ink_return)
2300 overall_ink_return->y = - gstring->line_ascent;
2301 overall_ink_return->x = gstring->lbearing;
2302 overall_ink_return->width = x - gstring->lbearing;
2303 overall_ink_return->height = gstring->height;
2305 if (overall_logical_return)
2307 overall_logical_return->y = - gstring->ascent;
2308 overall_logical_return->x = 0;
2309 overall_logical_return->width = x;
2310 overall_logical_return->height = gstring->ascent + gstring->descent;
2313 M17N_OBJECT_UNREF (gstring->top);
2320 @brief Return the character position nearest to the coordinates.
2322 The mdraw_coordinates_position () function checks which character
2323 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2324 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2325 mdraw_text_with_control () function with the drawing control
2326 object $CONTROL. Here, the character position means the number of
2327 characters that precede the character in question in $MT, that is,
2328 the character position of the first character is 0.
2330 $FRAME is used only to get the default face information.
2333 If the glyph image of a character covers coordinate ($X, $Y),
2334 mdraw_coordinates_position () returns the character position of
2336 If $Y is less than the minimum Y-coordinate of the drawn area, it
2337 returns $FROM.\n\n\n
2338 If $Y is greater than the maximum Y-coordinate of the drawn area,
2339 it returns $TO.\n\n\n
2340 If $Y fits in with the drawn area but $X is less than the minimum
2341 X-coordinate, it returns the character position of the first
2342 character drawn on the line $Y.\n\n\n
2343 If $Y fits in with the drawn area but $X is greater than the
2344 maximum X-coordinate, it returns the character position of the
2345 last character drawn on the line $Y. */
2348 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2350 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2351 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2352 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2353 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2354 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2355 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2357 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2360 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2361 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2363 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2365 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2367 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2368 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2370 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2371 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2374 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2375 int x_offset, int y_offset, MDrawControl *control)
2377 MGlyphString *gstring;
2382 M_CHECK_POS_X (mt, from, -1);
2383 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2384 to = mtext_nchars (mt) + (control->cursor_width != 0);
2390 ASSURE_CONTROL (control);
2391 gstring = get_gstring (frame, mt, from, to, control);
2392 while (y + gstring->line_descent <= y_offset
2393 && gstring->to < to)
2396 y += gstring->line_descent;
2397 M17N_OBJECT_UNREF (gstring->top);
2398 gstring = get_gstring (frame, mt, from, to, control);
2399 y += gstring->line_ascent;
2402 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2403 if (! control->orientation_reversed)
2405 width = gstring->indent;
2406 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2407 if (g->pos >= from && g->pos < to)
2410 if (width > x_offset)
2416 width = - gstring->indent;
2417 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2418 if (g->pos >= from && g->pos < to)
2421 if (width < x_offset)
2426 M17N_OBJECT_UNREF (gstring->top);
2434 @brief Compute information about a glyph.
2436 The mdraw_glyph_info () function computes information about a
2437 glyph that covers a character at position $POS of the M-text $MT
2438 assuming that the text is drawn from the character at $FROM of $MT
2439 on a window of frame $FRAME using the mdraw_text_with_control ()
2440 function with the drawing control object $CONTROL.
2442 The information is stored in the members of $INFO. */
2444 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2446 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2447 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2448 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2449 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2451 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2459 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2460 MDrawControl *control, MDrawGlyphInfo *info)
2462 MGlyphString *gstring;
2466 M_CHECK_RANGE_X (mt, from, pos, -1);
2468 ASSURE_CONTROL (control);
2469 gstring = get_gstring (frame, mt, from, pos + 1, control);
2471 MERROR (MERROR_DRAW, -1);
2472 while (gstring->to <= pos)
2474 y += gstring->line_descent;
2475 M17N_OBJECT_UNREF (gstring->top);
2476 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2477 y += gstring->line_ascent;
2479 info->line_from = gstring->from;
2480 if (info->line_from < from)
2481 info->line_from = from;
2482 info->line_to = gstring->to;
2485 if (! control->orientation_reversed)
2487 info->x = gstring->indent;
2488 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2489 info->x += g->width;
2493 info->x = - gstring->indent;
2494 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2495 info->x -= g->width;
2496 while (g[-1].to == g->to)
2499 info->from = g->pos;
2501 info->glyph_code = g->code;
2502 info->this.x = g->lbearing;
2503 info->this.y = - gstring->line_ascent;
2504 info->this.height = gstring->height;
2505 info->this.width = - g->lbearing + g->width;
2506 if (g->rface->rfont)
2507 info->font = &g->rface->rfont->font;
2510 /* info->logical_width is calculated later. */
2512 if (info->from > info->line_from)
2514 /* The logically previous glyph is on this line. */
2515 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2517 info->prev_from = g_tmp->pos;
2519 else if (info->line_from > 0)
2521 /* The logically previous glyph is on the previous line. */
2522 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2523 gstring->from, control);
2524 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2526 info->prev_from = g_tmp->pos;
2527 M17N_OBJECT_UNREF (gst->top);
2530 info->prev_from = -1;
2532 if (GLYPH_INDEX (g) > 1)
2533 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2534 else if (! control->orientation_reversed)
2536 if (info->line_from > 0)
2540 int p = gstring->from - 1;
2542 gst = get_gstring (frame, mt, p, gstring->from, control);
2543 g_tmp = gst->glyphs + (gst->used - 2);
2544 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2545 M17N_OBJECT_UNREF (gst->top);
2548 info->left_from = info->left_to = -1;
2552 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2556 int p = gstring->to;
2558 gst = get_gstring (frame, mt, p, p + 1, control);
2559 g_tmp = gst->glyphs + (gst->used - 2);
2560 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2561 M17N_OBJECT_UNREF (gst->top);
2564 info->left_from = info->left_to = -1;
2567 if (info->to < gstring->to)
2569 /* The logically next glyph is on this line. */
2570 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2572 info->next_to = g_tmp->to;
2574 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2576 /* The logically next glyph is on the next line. */
2578 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2579 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2581 info->next_to = g_tmp->to;
2582 M17N_OBJECT_UNREF (gst->top);
2587 for (info->logical_width = (g++)->width;
2588 g->pos == pos && g->type != GLYPH_ANCHOR;
2589 info->this.width += g->width, info->logical_width += (g++)->width);
2590 info->this.width += g[-1].rbearing - g[-1].width;
2592 if (g->type != GLYPH_ANCHOR)
2593 info->right_from = g->pos, info->right_to = g->to;
2594 else if (! control->orientation_reversed)
2596 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2599 M17N_OBJECT_UNREF (gstring->top);
2600 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2602 info->right_from = g->pos, info->right_to = g->to;
2605 info->right_from = info->right_to = -1;
2609 if (info->line_from > 0)
2611 pos = gstring->from - 1;
2612 M17N_OBJECT_UNREF (gstring->top);
2613 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2615 info->right_from = g->pos, info->right_to = g->to;
2618 info->right_from = info->right_to = -1;
2621 M17N_OBJECT_UNREF (gstring->top);
2628 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2629 MDrawControl *control, MDrawGlyphInfo *info,
2630 int array_size, int *num_glyphs_return)
2632 MGlyphString *gstring;
2636 ASSURE_CONTROL (control);
2637 *num_glyphs_return = 0;
2638 M_CHECK_RANGE (mt, from, to, -1, 0);
2639 gstring = get_gstring (frame, mt, from, to, control);
2642 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2644 if (g->type == GLYPH_BOX
2645 || g->pos < from || g->pos >= to)
2649 info->from = g->pos;
2651 info->glyph_code = (g->type == GLYPH_CHAR ? g->code : 0);
2654 info->this.x = g->lbearing;
2655 info->this.y = - g->ascent;
2656 info->this.height = g->ascent + g->descent;
2657 info->this.width = g->rbearing - g->lbearing;
2658 info->logical_width = g->width;
2659 if (g->rface->rfont)
2660 info->font = &g->rface->rfont->font;
2667 M17N_OBJECT_UNREF (gstring->top);
2669 *num_glyphs_return = n;
2670 return (n <= array_size ? 0 : -1);
2676 @brief Draw one or more textitems.
2678 The mdraw_text_items () function draws one or more M-texts on
2679 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2680 of the textitems to be drawn and $NITEMS is the number of
2681 textimtems in the array. */
2684 @brief textitem ¤òɽ¼¨¤¹¤ë.
2686 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2687 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2688 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2691 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2695 MTextItem, mdraw_text (). */
2698 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2699 MDrawTextItem *items, int nitems)
2701 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2703 while (nitems-- > 0)
2706 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2708 mdraw_text_with_control (frame, win, x, y,
2709 items->mt, 0, mtext_nchars (items->mt),
2711 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2712 items->control, NULL, NULL, NULL);
2715 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2721 @brief calculate a line breaking position.
2723 The function mdraw_default_line_break () calculates a line
2724 breaking position based on the line number $LINE and the
2725 coordinate $Y, when a line is too long to fit within the width
2726 limit. $POS is the position of the character next to the last
2727 one that fits within the limit. $FROM is the position of the
2728 first character of the line, and TO is the position of the last
2729 character displayed on the line if there were not width limit.
2730 LINE and Y are reset to 0 when a line is broken by a newline
2731 character, and incremented each time when a long line is broken
2732 because of the width limit.
2735 This function returns a character position to break the
2740 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2742 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2743 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2744 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2745 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2746 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2747 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2748 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2751 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2755 mdraw_default_line_break (MText *mt, int pos,
2756 int from, int to, int line, int y)
2758 int c = mtext_ref_char (mt, pos);
2761 if (c == ' ' || c == '\t')
2765 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2772 if (c == ' ' || c == '\t')
2775 c = mtext_ref_char (mt, pos);
2788 @brief Obtain per character dimension information.
2790 The mdraw_per_char_extents () function computes the text dimension
2791 of each character in M-text $MT. The faces given as text
2792 properties in $MT and the default face of frame $FRAME determine
2793 the fonts to draw the text. Each successive element in
2794 $ARRAY_RETURN is set to the drawn metrics of successive
2795 characters, which is relative to the origin of the drawing, and a
2796 rectangle for each character in $MT. The number of elements of
2797 $ARRAY_RETURN must be equal to or greater than the number of
2800 If pointer $OVERALL_RETURN is not @c NULL, this function also
2801 computes the extents of the overall text and stores the results in
2802 the members of the structure pointed to by $OVERALL_RETURN. */
2805 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2807 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2808 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2809 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2810 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2811 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2812 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2815 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2816 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2819 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2822 mdraw_per_char_extents (MFrame *frame, MText *mt,
2823 MDrawMetric *array_return,
2824 MDrawMetric *overall_return)
2826 int n = mtext_nchars (mt);
2828 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2829 n, &n, overall_return, NULL);
2833 @brief clear cached information.
2835 The mdraw_clear_cache () function clear cached information
2836 on M-text $MT that was attached by any of the drawing functions.
2837 When the behaviour of `format' or `line_break'
2838 member functions of MDrawControl is changed, the cache must be cleared.
2843 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2845 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2846 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2847 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2848 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2853 mdraw_clear_cache (MText *mt)
2855 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);