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;
87 static MSymbol Mdepth;
90 /* Glyph-string composer. */
92 static MSymbol MbidiR;
93 static MSymbol MbidiAL;
94 static MSymbol MbidiRLE;
95 static MSymbol MbidiRLO;
96 static MSymbol MbidiBN;
97 static MSymbol MbidiS;
100 visual_order (MGlyphString *gstring)
102 int len = gstring->used - 2;
104 int *idx = alloca (sizeof (int) * len);
106 int bidi_sensitive = gstring->control.orientation_reversed;
108 MGlyph *g = MGLYPH (1);
111 FriBidiCharType base = (gstring->control.orientation_reversed
112 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
113 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
115 FriBidiStrIndex *indices;
116 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
117 #else /* not HAVE_FRIBIDI */
118 int *logical = alloca (sizeof (int) * len);
120 char *levels = alloca (len);
121 #endif /* not HAVE_FRIBIDI */
123 while (g->type != GLYPH_ANCHOR)
125 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
127 if (bidi == MbidiR || bidi == MbidiAL
128 || bidi == MbidiRLE || bidi == MbidiRLO)
135 idx[size] = GLYPH_INDEX (g);
136 logical[size++] = g++->c;
137 while (g->type != GLYPH_ANCHOR && g->combining_code)
141 if (! bidi_sensitive)
144 glyphs = alloca (sizeof (MGlyph) * gstring->used);
145 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
147 visual = alloca (sizeof (FriBidiChar) * size);
148 indices = alloca (sizeof (FriBidiStrIndex) * size);
150 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
151 #else /* not HAVE_FRIBIDI */
152 indices = alloca (sizeof (int) * size);
153 for (i = 0; i < size; i++)
159 for (j = i + 1; j < size && levels[j]; j++);
160 for (k = j--; i < k; i++, j--)
167 #endif /* not HAVE_FRIBIDI */
169 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
170 starts from gstring->glyphs[IDX[N]].
172 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
173 originally at LOGICAL[INDICES[N]]. */
175 for (i = 0, gidx = 1; i < size; i++)
180 glyphs[k].bidi_level = levels[j];
182 if (visual[i] != logical[j])
185 glyphs[k].c = visual[i];
186 if (glyphs[k].rface->rfont)
187 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
190 #endif /* not HAVE_FRIBIDI */
191 *(MGLYPH (gidx)) = glyphs[k];
193 k < gstring->used - 1 && glyphs[k].combining_code;
196 glyphs[k].bidi_level = levels[j];
197 *(MGLYPH (gidx)) = glyphs[k];
203 reorder_combining_chars (MGlyphString *gstring, int from, int to)
205 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
211 for (g = gbeg; g != gend; g++)
212 if (COMBINING_CODE_CLASS (g->combining_code) > 0
213 && (COMBINING_CODE_CLASS (g[-1].combining_code)
214 > COMBINING_CODE_CLASS (g->combining_code)))
225 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
226 displaying them on FRAME.
228 This function fills members <type>, <rface>, <c>, <pos>, <to>,
229 <code> of glyphs. The other members are filled by
230 layout_glyph_string. */
233 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
234 MGlyphString *gstring)
236 MRealizedFace *default_rface = frame->rface;
237 int stop, face_change, language_change, charset_change;
240 MSymbol language = Mnil, script = Mnil, charset = Mnil;
241 MRealizedFace *rface = default_rface;
243 int size = gstring->control.fixed_width;
247 MLIST_RESET (gstring);
248 gstring->from = from;
250 /* At first generate glyphs while using the member <enabled> as a
251 flag for rface re-checking. */
254 /** Put anchor glyphs at the head and tail. */
255 g_tmp.type = GLYPH_ANCHOR;
256 g_tmp.pos = g_tmp.to = from;
258 APPEND_GLYPH (gstring, g_tmp);
260 stop = face_change = charset_change = language_change = pos = from;
268 if (pos < mtext_nchars (mt))
269 c = mtext_ref_char (mt, pos);
272 g_tmp.category = Mnil;
275 if (c == ' ' || c == '\n' || c == '\t')
276 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
278 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
282 g_tmp.category = mchar_get_prop (c, Mcategory);
283 g_tmp.type = GLYPH_CHAR;
284 this_script = (MSymbol) mchar_get_prop (c, Mscript);
285 if (this_script == Minherited)
286 this_script = script;
289 if (pos == stop || script != this_script
290 || MGLYPH (last)->type != g_tmp.type)
293 if (non_ascii_found && g->type == GLYPH_CHAR)
294 while (g < gstring->glyphs + gstring->used)
295 g = mface__for_chars (script, language, charset,
296 g, gstring->glyphs + gstring->used, size);
297 last = gstring->used;
299 script = this_script;
302 if (pos < mtext_nchars (mt) && pos == language_change)
304 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
305 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
307 if (pos < mtext_nchars (mt) && pos == charset_change)
309 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
310 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
312 if (pos < mtext_nchars (mt) && pos == face_change)
315 int num = mtext_get_prop_values (mt, pos, Mface,
316 (void **) faces, 64);
318 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
320 ? mface__realize (frame, faces, num,
321 language, charset, size)
325 if (stop > language_change)
326 stop = language_change;
327 if (stop > charset_change)
328 stop = charset_change;
329 if (face_change < stop)
333 g_tmp.c = g_tmp.code = c;
340 else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
343 APPEND_GLYPH (gstring, g_tmp);
345 g_tmp.code = g_tmp.c + 0x40;
349 APPEND_GLYPH (gstring, g_tmp);
351 && gstring->control.two_dimensional)
357 /* Append an anchor glyph. */
358 g_tmp.type = GLYPH_ANCHOR;
360 g_tmp.code = MCHAR_INVALID_CODE;
361 g_tmp.pos = g_tmp.to = pos;
363 APPEND_GLYPH (gstring, g_tmp);
367 /* Next, run FLT if necessary. */
368 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
372 if (this->type == GLYPH_CHAR && this->rface->rfont)
376 if (this->rface->rfont->layouter != Mnil)
381 for (prev = MGLYPH (start - 1);
382 (prev->type == GLYPH_CHAR
383 && prev->category == McatCf
384 && (code = mfont__encode_char (this->rface->rfont, prev->c)
385 != MCHAR_INVALID_CODE));
390 (g->type == GLYPH_CHAR
391 && (g->rface->rfont == this->rface->rfont
392 || (g->category == McatCf
393 && ((code = mfont__encode_char (this->rface->rfont,
395 != MCHAR_INVALID_CODE))));
397 if (g->rface->rfont != this->rface->rfont)
399 g->rface->rfont = this->rface->rfont;
402 i = mfont__flt_run (gstring, start, i, this->rface);
406 while (this->type == GLYPH_CHAR
409 && MSYMBOL_NAME (this->category)[0] == 'M'
410 && this->rface->rfont
411 && this->rface->rfont->layouter == Mnil)
413 int class = (int) mchar_get_prop (this->c,
416 = MAKE_COMBINING_CODE_BY_CLASS (class);
420 reorder_combining_chars (gstring, start, i);
428 /* At last, reorder glyphs visually if necessary. */
429 if (gstring->control.enable_bidi)
430 visual_order (gstring);
435 combining_code_from_class (int class)
440 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
441 else if (class == 200) /* below left attached */
442 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
443 else if (class == 202) /* below attached*/
444 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
445 else if (class == 204) /* below right attached */
446 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
447 else if (class == 208) /* left attached */
448 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
449 else if (class == 210) /* right attached */
450 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
451 else if (class == 212) /* above left attached */
452 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
453 else if (class == 214) /* above attached */
454 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
455 else if (class == 216) /* above right attached */
456 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
457 else if (class == 218) /* below left */
458 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
459 else if (class == 220) /* below */
460 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
461 else if (class == 222) /* below right */
462 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
463 else if (class == 224) /* left */
464 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
465 else if (class == 226) /* right */
466 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
467 else if (class == 228) /* above left */
468 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
469 else if (class == 230) /* above */
470 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
471 else if (class == 232) /* above right */
472 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
473 else if (class == 233) /* double below */
474 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
475 else if (class == 234) /* double above */
476 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
477 else if (class == 240) /* iota subscript */
478 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
480 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
486 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
488 int g_physical_ascent, g_physical_descent;
489 int g_width, g_lbearing, g_rbearing;
490 MGlyph *g = MGLYPH (from);
491 MGlyph *last_g = MGLYPH (to);
493 g_physical_ascent = gstring->physical_ascent;
494 g_physical_descent = gstring->physical_descent;
495 g_width = g_lbearing = g_rbearing = 0;
497 mfont__get_metric (gstring, from, to);
502 MRealizedFont *rfont = base->rface->rfont;
503 int size = rfont->font.property[MFONT_SIZE];
504 int width, lbearing, rbearing;
506 if (g == last_g || ! g->combining_code)
509 if (base->left_padding && base->lbearing < 0)
511 base->xoff = - base->lbearing;
512 base->width += base->xoff;
513 base->rbearing += base->xoff;
516 if (base->right_padding && base->rbearing > base->width)
518 base->width = base->rbearing;
520 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
521 rbearing = base->rbearing;
525 /* With combining glyphs. */
526 int left = -base->width;
528 int top = - base->ascent;
529 int bottom = base->descent;
530 int height = bottom - top;
531 int begin = base->pos;
536 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
537 rbearing = base->rbearing;
539 while (g != last_g && g->combining_code)
541 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
543 combining_code = g->combining_code;
544 if (COMBINING_BY_CLASS_P (combining_code))
545 g->combining_code = combining_code
546 = combining_code_from_class (COMBINING_CODE_CLASS
549 rfont = g->rface->rfont;
550 size = rfont->font.property[MFONT_SIZE];
551 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
553 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
555 base_x = COMBINING_CODE_BASE_X (combining_code);
556 base_y = COMBINING_CODE_BASE_Y (combining_code);
557 add_x = COMBINING_CODE_ADD_X (combining_code);
558 add_y = COMBINING_CODE_ADD_Y (combining_code);
562 else if (end < g->to)
565 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
568 if (g->xoff + g->width > right)
569 right = g->xoff + g->width;
570 width = right - left;
571 if (g->xoff + g->lbearing < left + lbearing)
572 lbearing = g->xoff + g->lbearing - left;
573 if (g->xoff + g->rbearing > left + rbearing)
574 rbearing = g->xoff + g->rbearing - left;
577 g->yoff = top + height * base_y / 2;
581 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
583 if (g->yoff - g->ascent < top)
584 top = g->yoff - g->ascent;
585 if (g->yoff + g->descent > bottom)
586 bottom = g->yoff + g->descent;
587 height = bottom - top;
593 base->ascent = - top;
594 base->descent = bottom;
595 base->lbearing = lbearing;
596 base->rbearing = rbearing;
597 if (left < - base->width)
599 base->xoff = - base->width - left;
600 base->width += base->xoff;
601 base->rbearing += base->xoff;
602 base->lbearing += base->xoff;
606 base->width += right;
607 base->rbearing += right;
608 base->right_padding = 1;
609 for (i = 1; base + i != g; i++)
610 base[i].xoff -= right;
613 for (i = 0; base + i != g; i++)
620 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
621 g_physical_descent = MAX (g_physical_descent, base->descent);
622 g_lbearing = MIN (g_lbearing, g_width + lbearing);
623 g_rbearing = MAX (g_rbearing, g_width + rbearing);
624 g_width += base->width;
627 gstring->physical_ascent = g_physical_ascent;
628 gstring->physical_descent = g_physical_descent;
629 gstring->sub_width = g_width;
630 gstring->sub_lbearing = g_lbearing;
631 gstring->sub_rbearing = g_rbearing;
635 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
636 by this function directly. Character glyphs are handled by
637 layouter functions registered in font drivers.
639 This function fill-in all the remaining members of glyphs. */
642 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
644 /* Default width of TAB. */
645 int tab_width = frame->space_width * (gstring->control.tab_width
646 ? gstring->control.tab_width : 8);
650 MDrawControl *control = &(gstring->control);
653 int box_line_height = 0;
654 int ignore_formatting_char = control->ignore_formatting_char;
656 gstring->ascent = gstring->descent = 0;
657 gstring->physical_ascent = gstring->physical_descent = 0;
658 gstring->width = gstring->lbearing = gstring->rbearing = 0;
662 while (g->type != GLYPH_ANCHOR)
664 if (box != g->rface->box)
666 int gidx = GLYPH_INDEX (g);
670 /* Insert the right side of the box. That glyph belongs
671 to the previous grapheme cluster. */
672 MGlyph box_glyph = g[-1];
674 box_glyph.type = GLYPH_BOX;
676 = (control->fixed_width
678 : box->inner_hmargin + box->width + box->outer_hmargin);
679 box_glyph.lbearing = 0;
680 box_glyph.rbearing = box_glyph.width;
682 box_glyph.right_padding = 1;
683 gstring->width += box_glyph.width;
684 gstring->rbearing += box_glyph.width;
685 INSERT_GLYPH (gstring, gidx, box_glyph);
692 /* Insert the left side of the box. That glyph belongs
693 to the following grapheme cluster. */
694 MGlyph box_glyph = *g;
695 int box_height = (box->width
696 + box->inner_vmargin + box->outer_vmargin);
698 if (box_line_height < box_height)
699 box_line_height = box_height;
700 box_glyph.type = GLYPH_BOX;
702 = (control->fixed_width
704 : box->inner_hmargin + box->width + box->outer_hmargin);
705 box_glyph.lbearing = 0;
706 box_glyph.rbearing = box_glyph.width;
708 box_glyph.left_padding = 1;
709 gstring->width += box_glyph.width;
710 gstring->rbearing += box_glyph.width;
711 INSERT_GLYPH (gstring, gidx, box_glyph);
717 if (g->category == McatCf && ignore_formatting_char)
718 g->type = GLYPH_SPACE;
720 if (g->type == GLYPH_CHAR)
722 MRealizedFace *rface = g->rface;
723 MRealizedFont *rfont = rface->rfont;
725 int from = GLYPH_INDEX (g);
727 for (g++; g->type == GLYPH_CHAR; g++)
728 if (! rfont != ! g->rface->rfont
729 || box != g->rface->box
730 || ((fromg->code == MCHAR_INVALID_CODE)
731 != (g->code == MCHAR_INVALID_CODE))
732 || (g->category == McatCf && ignore_formatting_char))
734 if (rfont && fromg->code != MCHAR_INVALID_CODE)
737 int to = GLYPH_INDEX (g);
739 layout_glyphs (frame, gstring, from, to);
740 extra_width = - gstring->sub_lbearing;
742 && (GLYPH_INDEX (g) > 1
743 || control->align_head))
747 pad.type = GLYPH_PAD;
750 pad.width = pad.rbearing = extra_width;
751 INSERT_GLYPH (gstring, from, pad);
753 gstring->sub_lbearing = 0;
754 gstring->sub_width += extra_width;
755 gstring->sub_rbearing += extra_width;
757 g = MGLYPH (from - 1);
758 if (g->type == GLYPH_SPACE)
760 /* The pad just inserted is absorbed (maybe
761 partially) by the previous space while
762 keeping at least some space width. For the
763 moment, we use the arbitrary width 2-pixel.
764 Perhaps, it should be decided by the current
765 face, or a default value of the current
766 frame, which is, however, not yet
768 if (extra_width + 2 < g->width)
770 g->width -= extra_width;
774 extra_width -= g->width - 2;
777 gstring->width -= extra_width;
778 gstring->rbearing -= extra_width;
782 extra_width = gstring->sub_rbearing - gstring->sub_width;
786 if (g->type == GLYPH_SPACE && box == g->rface->box)
790 pad.type = GLYPH_PAD;
793 pad.width = pad.rbearing = extra_width;
794 INSERT_GLYPH (gstring, to, pad);
798 g[-1].width += extra_width;
799 gstring->sub_width += extra_width;
802 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
803 gstring->lbearing = gstring->width + gstring->sub_lbearing;
804 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
805 gstring->rbearing = gstring->width + gstring->sub_rbearing;
806 gstring->width += gstring->sub_width;
807 if (gstring->ascent < rface->ascent)
808 gstring->ascent = rface->ascent;
809 if (gstring->descent < rface->descent)
810 gstring->descent = rface->descent;
815 for (; fromg < g; fromg++)
817 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
818 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
819 fromg->width = fromg->rbearing = 1;
821 fromg->width = fromg->rbearing = rface->space_width;
822 fromg->xoff = fromg->lbearing = 0;
823 fromg->ascent = fromg->descent = 0;
824 gstring->width += fromg->width;
825 gstring->rbearing += fromg->width;
827 if (gstring->ascent < frame->rface->ascent)
828 gstring->ascent = frame->rface->ascent;
829 if (gstring->descent < frame->descent)
830 gstring->descent = frame->rface->descent;
833 else if (g->type == GLYPH_SPACE)
836 g->width = g->rface->space_width;
837 else if (g->c == '\n')
839 g->width = control->cursor_width;
842 if (control->cursor_bidi)
844 else if (g->width < 0)
845 g->width = g->rface->space_width;
848 else if (g->c == '\t')
850 g->width = tab_width - ((gstring->indent + gstring->width)
856 if (g[-1].type == GLYPH_PAD)
858 /* This space glyph absorbs (maybe partially) the
859 previous padding glyph. */
860 g->width -= g[-1].width;
862 /* But, keep at least some space width. For the
863 moment, we use the arbitrary width 2-pixel. */
866 g->rbearing = g->width;
867 gstring->width += g->width;
868 gstring->rbearing += g->width;
871 if (gstring->ascent < g->rface->ascent)
872 gstring->ascent = g->rface->ascent;
873 if (gstring->descent < g->rface->descent)
874 gstring->descent = g->rface->descent;
880 gstring->width += g->width;
881 gstring->rbearing += g->width;
888 /* Insert the right side of the box. */
889 int gidx = GLYPH_INDEX (g);
890 MGlyph box_glyph = g[-1];
892 box_glyph.type = GLYPH_BOX;
894 = (control->fixed_width
896 : box->inner_hmargin + box->width + box->outer_hmargin);
897 box_glyph.lbearing = 0;
898 box_glyph.rbearing = box_glyph.width;
900 box_glyph.right_padding = 1;
901 gstring->width += box_glyph.width;
902 gstring->rbearing += box_glyph.width;
903 INSERT_GLYPH (gstring, gidx, box_glyph);
906 gstring->text_ascent = gstring->ascent;
907 gstring->text_descent = gstring->descent;
908 if (gstring->text_ascent < gstring->physical_ascent)
909 gstring->text_ascent = gstring->physical_ascent;
910 if (gstring->text_descent < gstring->physical_descent)
911 gstring->text_descent = gstring->physical_descent;
912 gstring->line_ascent = gstring->text_ascent;
913 gstring->line_descent = gstring->text_descent;
914 if (box_line_height > 0)
916 gstring->line_ascent += box_line_height;
917 gstring->physical_ascent = gstring->line_ascent;
918 gstring->line_descent += box_line_height;
919 gstring->physical_descent = gstring->line_descent;
922 if (gstring->line_ascent < control->min_line_ascent)
923 gstring->line_ascent = control->min_line_ascent;
924 else if (control->max_line_ascent
925 && control->max_line_ascent > control->min_line_ascent
926 && gstring->line_ascent > control->max_line_ascent)
927 gstring->line_ascent = control->max_line_ascent;
929 if (gstring->line_descent < control->min_line_descent)
930 gstring->line_descent = control->min_line_descent;
931 else if (control->max_line_descent
932 && control->max_line_descent > control->min_line_descent
933 && gstring->line_descent > control->max_line_descent)
934 gstring->line_descent = control->max_line_descent;
935 gstring->height = gstring->line_ascent + gstring->line_descent;
937 if (control->orientation_reversed
940 /* We must adjust TAB width for RTL orientation. */
941 width = gstring->indent;
943 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
945 if (g->type == GLYPH_CHAR && g->c == '\t')
947 int this_width = tab_width - (width % tab_width);
949 if (g[1].type == GLYPH_PAD)
950 this_width -= g[1].width;
951 if (g[-1].type == GLYPH_PAD)
952 this_width -= g[-1].width;
955 gstring->width += this_width - g->width;
956 gstring->rbearing += this_width - g->width;
957 g->width = this_width;
968 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
969 MGlyphString *gstring, int from, int to,
970 int *from_idx, int *to_idx, int *to_x)
972 MGlyph *g = MGLYPH (1);
973 MDrawRegion region = (MDrawRegion) NULL;
974 MDrawControl *control = &gstring->control;
977 int cursor_bidi = control->cursor_bidi;
979 if (control->with_cursor && control->cursor_width)
981 if (gstring->from <= control->cursor_pos
982 && gstring->to > control->cursor_pos)
983 cursor_pos = control->cursor_pos;
985 && gstring->from <= control->cursor_pos - 1
986 && gstring->to > control->cursor_pos - 1)
987 prev_pos = control->cursor_pos - 1;
990 *from_idx = *to_idx = 0;
991 while (g->type != GLYPH_ANCHOR)
993 if (g->pos >= from && g->pos < to)
995 MGlyph *fromg = g, *cursor = NULL;
996 MRealizedFace *rface = g->rface;
998 int cursor_width = 0;
1002 *from_idx = GLYPH_INDEX (g);
1003 while (g->pos >= from && g->pos < to
1004 && g->rface == rface)
1007 if (g->type != GLYPH_BOX
1008 && g->pos <= cursor_pos && g->to > cursor_pos)
1011 cursor = g, cursor_x = x + width;
1012 cursor_width += g->width;
1014 width += g++->width;
1017 && (control->as_image
1018 || rface->face.property[MFACE_BACKGROUND] != Mnil
1019 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1021 int this_x = x, this_width = width;
1023 if (fromg->type == GLYPH_BOX)
1024 this_x += fromg->width, this_width -= fromg->width;
1025 if (g[-1].type == GLYPH_BOX)
1026 this_width -= g[-1].width;
1027 mwin__fill_space (frame, win, rface, 0,
1028 this_x, y - gstring->text_ascent, this_width,
1029 gstring->text_ascent + gstring->text_descent,
1030 control->clip_region);
1037 rect.y = y - gstring->text_ascent;
1038 rect.height = gstring->text_ascent + gstring->text_descent;
1041 rect.width = ((control->cursor_width > 0
1042 && control->cursor_width < cursor_width)
1043 ? control->cursor_width : cursor_width);
1047 if (cursor->bidi_level % 2)
1048 rect.x += cursor_width - 1;
1051 mwin__fill_space (frame, win, rface, 1,
1052 rect.x, rect.y, rect.width, rect.height,
1053 control->clip_region);
1055 region = mwin__region_from_rect (&rect);
1057 mwin__region_add_rect (region, &rect);
1058 mwin__verify_region (frame, region);
1061 if (cursor->bidi_level % 2)
1064 rect.width = cursor_width < 4 ? cursor_width : 4;
1065 mwin__fill_space (frame, win, rface, 1,
1066 rect.x, rect.y, rect.width, rect.height,
1067 control->clip_region);
1068 mwin__region_add_rect (region, &rect);
1069 mwin__verify_region (frame, region);
1081 if (fromg->type != GLYPH_BOX
1082 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1085 cursor = fromg, cursor_x = x + temp_width;
1086 cursor_width += fromg->width;
1088 temp_width += fromg++->width;
1095 if (! (cursor->bidi_level % 2))
1096 rect.x += cursor_width - 1;
1097 rect.y = y - gstring->text_ascent;
1098 rect.height = gstring->text_ascent + gstring->text_descent;
1100 mwin__fill_space (frame, win, rface, 1,
1101 rect.x, rect.y, rect.width, rect.height,
1102 control->clip_region);
1104 region = mwin__region_from_rect (&rect);
1106 mwin__region_add_rect (region, &rect);
1107 mwin__verify_region (frame, region);
1108 rect.y += rect.height - 2;
1110 rect.width = cursor_width < 4 ? cursor_width : 4;
1111 if (! (cursor->bidi_level % 2))
1112 rect.x -= rect.width - 1;
1113 mwin__fill_space (frame, win, rface, 1,
1114 rect.x, rect.y, rect.width, rect.height,
1115 control->clip_region);
1116 mwin__region_add_rect (region, &rect);
1117 mwin__verify_region (frame, region);
1121 *to_idx = GLYPH_INDEX (g);
1131 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1132 MGlyphString *gstring, int from_idx, int to_idx,
1133 int reverse, MDrawRegion region)
1135 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1141 mwin__region_to_rect (region, &rect);
1144 while (g != gend && x + g->rbearing <= rect.x)
1147 width -= g++->width;
1148 while (! g->enabled && g != gend)
1152 rect.x += rect.width;
1153 if (rect.x < x + width)
1156 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1158 width -= (--gend)->width;
1159 while (! gend->enabled && g != gend)
1163 while (gend[-1].to == gend->to) gend++;
1171 MRealizedFace *rface = g->rface;
1172 int width = g->width;
1173 MGlyph *from_g = g++;
1175 /* Handle the glyphs of the same type/face at once. */
1177 && g->type == from_g->type
1178 && g->rface == rface
1179 && (g->code < 0) == (from_g->code < 0)
1181 width += g++->width;
1183 if (from_g->type == GLYPH_CHAR)
1185 if (rface->rfont && from_g->code >= 0)
1186 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1189 mwin__draw_empty_boxes (win, x, y, gstring, from_g, g,
1192 else if (from_g->type == GLYPH_BOX)
1194 /* Draw the left or right side of a box. If
1195 from_g->lbearing is nonzero, this is the left side,
1196 else this is the right side. */
1197 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1200 if (from_g->type != GLYPH_BOX)
1203 mwin__draw_hline (frame, win, gstring, rface, reverse,
1204 x, y, width, region);
1207 /* Draw the top and bottom side of a box. */
1208 mwin__draw_box (frame, win, gstring, from_g,
1209 x, y, width, region);
1220 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1221 int *from_x, int *to_x)
1224 int left_idx = *left, right_idx = *right;
1225 int left_x, right_x, x;
1227 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1230 if (x + g->rbearing > 0)
1232 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1234 left_idx = GLYPH_INDEX (g);
1239 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1242 if (x - g->width + g->lbearing < 0)
1244 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1246 right_idx = GLYPH_INDEX (g) + 1;
1251 if (*left == left_idx && *right == right_idx)
1254 if (*left != left_idx)
1256 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1261 if (*right != right_idx)
1263 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1273 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1278 if (from <= gstring->from && to >= gstring->to)
1281 *rbearing = gstring->rbearing;
1282 return gstring->width;
1287 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1288 if (g->pos >= from && g->pos < to)
1290 if (rbearing && width + g->rbearing > *rbearing)
1291 *rbearing = width + g->rbearing;
1299 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1300 MGlyphString *gstring, int from, int to)
1302 MDrawControl *control = &gstring->control;
1304 MDrawRegion clip_region, cursor_region;
1305 int from_idx, to_idx;
1308 if (control->orientation_reversed)
1309 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1311 x += gstring->indent;
1313 /* At first, draw all glyphs without cursor. */
1314 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1315 &from_idx, &to_idx, &to_x);
1317 if (control->partial_update)
1320 rect.width = to_x - x;
1321 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1323 rect.y = y - gstring->line_ascent;
1324 rect.height = gstring->height;
1325 clip_region = mwin__region_from_rect (&rect);
1326 if (control->clip_region)
1327 mwin__intersect_region (clip_region, control->clip_region);
1330 clip_region = control->clip_region;
1333 clip_region = control->clip_region;
1335 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1340 mwin__intersect_region (cursor_region, clip_region);
1341 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1344 if (clip_region != control->clip_region)
1345 mwin__free_region (clip_region);
1347 mwin__free_region (cursor_region);
1351 static int gstring_num;
1354 free_gstring (void *object)
1356 MGlyphString *gstring = (MGlyphString *) object;
1359 free_gstring (gstring->next);
1360 if (gstring->size > 0)
1361 free (gstring->glyphs);
1367 static MGlyphString scratch_gstring;
1369 static MGlyphString *
1370 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1373 MGlyphString *gstring;
1375 if (pos == mt->nchars)
1377 gstring = &scratch_gstring;
1381 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1382 MLIST_INIT1 (gstring, glyphs, 128);
1386 gstring->frame = frame;
1387 gstring->tick = frame->tick;
1388 gstring->top = gstring;
1390 gstring->control = *control;
1391 gstring->indent = gstring->width_limit = 0;
1392 if (control->format)
1393 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1395 gstring->width_limit = control->max_line_width;
1396 gstring->anti_alias = control->anti_alias;
1397 if (gstring->anti_alias
1398 && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
1399 gstring->anti_alias = 0;
1403 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1406 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1414 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1415 a width of glyphs for the character at I of GSTRING->mt. If I is
1416 not a beginning of a grapheme cluster, the corresponding element
1418 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1419 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1420 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1421 pos_width[g->pos - gstring->from] += g->width;
1422 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1424 if (pos_width[i] > 0)
1426 if (width + pos_width[i] > gstring->width_limit)
1429 width += pos_width[i];
1432 pos = gstring->from + i;
1433 if (gstring->control.line_break)
1435 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1436 gstring->from, gstring->to, 0, 0);
1437 if (pos <= gstring->from || pos >= gstring->to)
1440 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1441 layout_glyph_string (frame, gstring);
1445 /* Return a gstring that covers a character at POS. */
1447 static MGlyphString *
1448 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1450 MGlyphString *gstring = NULL;
1452 if (pos < mtext_nchars (mt))
1454 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1457 && ((prop->start != 0
1458 && mtext_ref_char (mt, prop->start - 1) != '\n')
1459 || (prop->end < mtext_nchars (mt)
1460 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1462 mtext_detach_property (prop);
1467 gstring = prop->val;
1468 if (gstring->frame != frame
1469 || gstring->tick != frame->tick
1470 || memcmp (control, &gstring->control,
1471 (char *) (&control->with_cursor)
1472 - (char *) (control)))
1474 mtext_detach_property (prop);
1479 else if (! control->cursor_width)
1487 offset = mtext_character (mt, pos, 0, '\n');
1492 offset -= gstring->from;
1494 for (gst = gstring; gst; gst = gst->next)
1498 gst->from += offset;
1500 for (i = 0; i < gst->used; i++)
1502 gst->glyphs[i].pos += offset;
1503 gst->glyphs[i].to += offset;
1506 M17N_OBJECT_REF (gstring);
1511 int line = 0, y = 0;
1513 if (control->two_dimensional)
1515 beg = mtext_character (mt, pos, 0, '\n');
1520 end = mtext_nchars (mt) + (control->cursor_width != 0);
1527 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1528 compose_glyph_string (frame, mt, beg, end, gstring);
1529 layout_glyph_string (frame, gstring);
1531 if (control->two_dimensional
1532 && gstring->width_limit
1533 && gstring->width > gstring->width_limit)
1535 MGlyphString *gst = gstring;
1537 truncate_gstring (frame, mt, gst);
1538 while (gst->to < end)
1540 line++, y += gst->height;
1541 gst->next = alloc_gstring (frame, mt, gst->from, control,
1543 gst->next->top = gstring;
1544 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1546 layout_glyph_string (frame, gst);
1547 if (gst->width <= gst->width_limit)
1549 truncate_gstring (frame, mt, gst);
1553 if (! control->disable_caching && pos < mtext_nchars (mt))
1555 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1556 MTEXTPROP_VOLATILE_STRONG);
1558 if (end > mtext_nchars (mt))
1559 end = mtext_nchars (mt);
1560 mtext_attach_property (mt, beg, end, prop);
1561 M17N_OBJECT_UNREF (prop);
1565 while (gstring->to <= pos)
1567 if (! gstring->next)
1569 gstring = gstring->next;
1571 gstring->control = *control;
1577 static MDrawControl control_noop;
1579 #define ASSURE_CONTROL(control) \
1581 control = &control_noop; \
1586 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1587 MText *mt, int from, int to,
1588 MDrawControl *control)
1590 MGlyphString *gstring;
1592 M_CHECK_POS_X (mt, from, -1);
1593 ASSURE_CONTROL (control);
1594 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1595 to = mtext_nchars (mt) + (control->cursor_width != 0);
1599 gstring = get_gstring (frame, mt, from, to, control);
1601 MERROR (MERROR_DRAW, -1);
1602 render_glyph_string (frame, win, x, y, gstring, from, to);
1606 y += gstring->line_descent;
1607 M17N_OBJECT_UNREF (gstring->top);
1608 gstring = get_gstring (frame, mt, from, to, control);
1609 y += gstring->line_ascent;
1610 render_glyph_string (frame, win, x, y, gstring, from, to);
1613 M17N_OBJECT_UNREF (gstring->top);
1620 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1626 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1627 if (g->pos <= pos && g->to > pos)
1632 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1633 if (g->pos <= pos && g->to > pos)
1640 /* for debugging... */
1644 dump_combining_code (int code)
1646 char *vallign = "tcbB";
1647 char *hallign = "lcr";
1653 if (COMBINING_BY_CLASS_P (code))
1654 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1655 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1656 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1657 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1658 off_x = COMBINING_CODE_OFF_X (code) - 128;
1660 sprintf (work + 2, "+%d", off_y);
1662 sprintf (work + 2, "%d", off_y);
1663 else if (off_x == 0)
1664 sprintf (work + 2, ".");
1665 p = work + strlen (work);
1667 sprintf (p, ">%d", off_x);
1669 sprintf (p, "<%d", -off_x);
1671 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1672 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1678 dump_gstring (MGlyphString *gstring, int indent)
1680 char *prefix = (char *) alloca (indent + 1);
1681 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1683 memset (prefix, 32, indent);
1686 fprintf (stderr, "(glyph-string");
1688 for (g = MGLYPH (0); g < last_g; g++)
1690 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1692 g - gstring->glyphs,
1693 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1694 : g->type == GLYPH_ANCHOR ? "ANC"
1695 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1696 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1697 dump_combining_code (g->combining_code),
1698 g->width, g->bidi_level);
1699 fprintf (stderr, ")");
1703 /* m17n-X internal APIs */
1708 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1710 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1711 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1713 Mlatin = msymbol ("latin");
1714 Minherited = msymbol ("inherited");
1716 McatCc = msymbol ("Cc");
1717 McatCf = msymbol ("Cf");
1718 Mdepth = msymbol ("depth");
1720 MbidiR = msymbol ("R");
1721 MbidiAL = msymbol ("AL");
1722 MbidiRLE = msymbol ("RLE");
1723 MbidiRLO = msymbol ("RLO");
1724 MbidiBN = msymbol ("BN");
1725 MbidiS = msymbol ("S");
1727 fribidi_set_mirroring (TRUE);
1736 MLIST_FREE1 (&scratch_gstring, glyphs);
1740 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1744 /*** @addtogroup m17nDraw */
1749 @brief Draw an M-text on a window.
1751 The mdraw_text () function draws the text between $FROM and $TO of
1752 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1754 The appearance of the text (size, style, color, etc) is specified
1755 by the value of the text property whose key is @c Mface. If the
1756 M-text or a part of the M-text does not have such a text property,
1757 the default face of $FRAME is used.
1759 The font used to draw a character in the M-text is selected from
1760 the value of the fontset property of a face by the following
1765 <li> Search the text properties given to the character for the one
1766 whose key is @c Mcharset; its value should be either a symbol
1767 specifying a charset or #Mnil. If the value is #Mnil,
1768 proceed to the next step.
1770 Otherwise, search the mapping table of the fontset for the
1771 charset. If no entry is found proceed to the next step.
1773 If an entry is found, use one of the fonts in the entry that
1774 has a glyph for the character and that matches best with the
1775 face properties. If no such font exists, proceed to the next
1778 <li> Get the character property "script" of the character. If it is
1779 inherited, get the script property from the previous
1780 characters. If there is no previous character, or none of
1781 them has the script property other than inherited, proceed to
1784 Search the text properties given to the character for the one
1785 whose key is @c Mlanguage; its value should be either a
1786 symbol specifying a language or @c Mnil.
1788 Search the mapping table of the fontset for the combination
1789 of the script and language. If no entry is found, proceed to
1792 If an entry is found, use one of the fonts in the entry that
1793 has a glyph for the character and that matches best with the
1794 face properties. If no such font exists, proceed to the next
1797 <li> Search the fall-back table of the fontset for a font that has
1798 a glyph of the character. If such a font is found, use that
1803 If no font is found by the algorithm above, this function draws an
1804 empty box for the character.
1806 This function draws only the glyph foreground. To specify the
1807 background color, use mdraw_image_text () or
1808 mdraw_text_with_control ().
1810 This function is the counterpart of <tt>XDrawString ()</tt>,
1811 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1812 in the X Window System.
1815 If the operation was successful, mdraw_text () returns 0. If an
1816 error is detected, it returns -1 and assigns an error code to the
1817 external variable #merror_code. */
1819 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1821 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1822 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1825 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1826 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1827 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1828 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1830 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1831 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1835 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1836 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1837 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1838 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1839 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1842 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1843 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1844 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1847 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1848 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1849 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1850 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1852 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1853 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1856 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1857 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1860 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1861 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1862 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1865 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1866 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1870 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1871 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1873 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1874 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1877 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1878 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1881 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1882 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1884 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1891 mdraw_image_text () */
1894 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1895 MText *mt, int from, int to)
1897 MDrawControl control;
1899 memset (&control, 0, sizeof control);
1900 control.as_image = 0;
1901 return draw_text (frame, win, x, y, mt, from, to, &control);
1908 @brief Draw an M-text on a window as an image.
1910 The mdraw_image_text () function draws the text between $FROM and
1911 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1912 coordinate ($X, $Y).
1914 The way to draw a text is the same as in mdraw_text () except that
1915 this function also draws the background with the color specified
1918 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1919 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1920 functions in the X Window System.
1923 If the operation was successful, mdraw_image_text () returns 0.
1924 If an error is detected, it returns -1 and assigns an error code
1925 to the external variable #merror_code. */
1928 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1930 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1931 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1934 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1935 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1937 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1938 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1942 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1943 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1946 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1956 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1957 MText *mt, int from, int to)
1959 MDrawControl control;
1961 memset (&control, 0, sizeof control);
1962 control.as_image = 1;
1963 return draw_text (frame, win, x, y, mt, from, to, &control);
1969 @brief Draw an M-text on a window with fine control.
1971 The mdraw_text_with_control () function draws the text between
1972 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1973 coordinate ($X, $Y).
1975 The way to draw a text is the same as in mdraw_text () except that
1976 this function also follows what specified in the drawing control
1979 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1980 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1981 breaks lines and the following characters are drawn in the next
1982 line. See the documentation of the structure @ MDrawControl for
1986 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
1988 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1989 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
1992 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
1993 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1995 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
1996 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
1997 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2001 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2002 MText *mt, int from, int to, MDrawControl *control)
2004 return draw_text (frame, win, x, y, mt, from, to, control);
2010 @brief Compute text pixel width.
2012 The mdraw_text_extents () function computes the width of text
2013 between $FROM and $TO of M-text $MT when it is drawn on a window
2014 of frame $FRAME using the mdraw_text_with_control () function with
2015 the drawing control object $CONTROL.
2017 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2018 the bounding box of character ink of the M-text, and stores the
2019 results in the members of the structure pointed to by
2020 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2021 surrounding box, the box is included in the bounding box.
2023 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2024 computes the bounding box that provides mininum spacing to other
2025 graphical features (such as surrounding box) for the M-text, and
2026 stores the results in the members of the structure pointed to by
2027 $OVERALL_LOGICAL_RETURN.
2029 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2030 computes the bounding box that provides mininum spacing to the
2031 other M-text drawn, and stores the results in the members of the
2032 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2033 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2034 min_line_ascent, min_line_descent, max_line_ascent, and
2035 max_line_descent of $CONTROL are all zero.
2038 This function returns the width of the text to be drawn in the
2039 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2040 text is drawn in multiple physical lines, it returns the width of
2041 the widest line. If an error occurs, it returns -1 and assigns an
2042 error code to the external variable #merror_code. */
2046 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2048 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2049 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2050 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2052 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2053 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2054 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2055 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2057 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2058 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2059 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2060 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2062 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2063 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2064 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2065 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2066 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2067 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2069 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2070 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2071 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2072 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2074 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2081 mdraw_text_extents (MFrame *frame,
2082 MText *mt, int from, int to, MDrawControl *control,
2083 MDrawMetric *overall_ink_return,
2084 MDrawMetric *overall_logical_return,
2085 MDrawMetric *overall_line_return)
2087 MGlyphString *gstring;
2089 int width, rbearing;
2091 ASSURE_CONTROL (control);
2092 M_CHECK_POS_X (mt, from, -1);
2093 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2094 to = mtext_nchars (mt) + (control->cursor_width != 0);
2098 gstring = get_gstring (frame, mt, from, to, control);
2100 MERROR (MERROR_DRAW, -1);
2101 width = gstring_width (gstring, from, to, &rbearing);
2102 if (overall_ink_return)
2104 overall_ink_return->y = - gstring->physical_ascent;
2105 overall_ink_return->x = gstring->lbearing;
2107 if (overall_logical_return)
2109 overall_logical_return->y = - gstring->ascent;
2110 overall_logical_return->x = 0;
2112 if (overall_line_return)
2114 overall_line_return->y = - gstring->line_ascent;
2115 overall_line_return->x = gstring->lbearing;
2118 for (from = gstring->to; from < to; from = gstring->to)
2120 int this_width, this_rbearing;
2122 y += gstring->line_descent;
2123 M17N_OBJECT_UNREF (gstring->top);
2124 gstring = get_gstring (frame, mt, from, to, control);
2125 this_width = gstring_width (gstring, from, to, &this_rbearing);
2126 y += gstring->line_ascent;
2127 if (width < this_width)
2129 if (rbearing < this_rbearing)
2130 rbearing = this_rbearing;
2132 if (overall_ink_return)
2134 overall_ink_return->width = rbearing;
2135 overall_ink_return->height
2136 = y + gstring->physical_descent - overall_ink_return->y;
2138 if (overall_logical_return)
2140 overall_logical_return->width = width;
2141 overall_logical_return->height
2142 = y + gstring->descent - overall_logical_return->y;
2144 if (overall_line_return)
2146 overall_line_return->width = MAX (width, rbearing);
2147 overall_line_return->height
2148 = y + gstring->line_descent - overall_line_return->y;
2151 M17N_OBJECT_UNREF (gstring->top);
2158 @brief Compute the text dimensions of each character of M-text.
2160 The mdraw_text_per_char_extents () function computes the drawn
2161 metric of each character between $FROM and $TO of M-text $MT
2162 assuming that they are drawn on a window of frame $FRAME using the
2163 mdraw_text_with_control () function with the drawing control
2166 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2167 $LOGICAL_ARRAY_RETURN. Each successive element of
2168 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2169 ink and logical metrics of successive characters respectively,
2170 relative to the drawing origin of the M-text. The number of
2171 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2172 been set is returned to $NUM_CHARS_RETURN.
2174 If $ARRAY_SIZE is too small to return all metrics, the function
2175 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2176 Otherwise, it returns zero.
2178 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2179 @c NULL, this function also computes the metrics of the overall
2180 text and stores the results in the members of the structure
2181 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2183 If $CONTROL->two_dimensional is nonzero, this function computes
2184 only the metrics of characters in the first line. */
2186 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2188 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2189 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2190 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2191 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2193 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2194 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2195 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2196 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2197 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2199 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2200 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2203 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2204 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2205 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2208 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2209 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2212 mdraw_text_per_char_extents (MFrame *frame,
2213 MText *mt, int from, int to,
2214 MDrawControl *control,
2215 MDrawMetric *ink_array_return,
2216 MDrawMetric *logical_array_return,
2218 int *num_chars_return,
2219 MDrawMetric *overall_ink_return,
2220 MDrawMetric *overall_logical_return)
2222 MGlyphString *gstring;
2226 ASSURE_CONTROL (control);
2227 *num_chars_return = to - from;
2228 if (array_size < *num_chars_return)
2230 if (overall_logical_return)
2231 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2232 if (overall_ink_return)
2233 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2235 M_CHECK_RANGE (mt, from, to, -1, 0);
2236 gstring = get_gstring (frame, mt, from, to, control);
2239 *num_chars_return = 0;
2243 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2244 if (g->pos >= from && g->pos < to)
2248 int width = g->width;
2249 int lbearing = g->lbearing;
2250 int rbearing = g->rbearing;
2251 int ascent = g->ascent;
2252 int descent = g->descent;
2253 int logical_ascent = g->rface->rfont->ascent;
2254 int logical_descent = g->rface->rfont->descent;
2256 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2258 if (lbearing < width + g->lbearing)
2259 lbearing = width + g->lbearing;
2260 if (rbearing < width + g->rbearing)
2261 rbearing = width + g->rbearing;
2263 if (ascent < g->ascent)
2265 if (descent < g->descent)
2266 descent = g->descent;
2273 ink_array_return[start - from].x = x + lbearing;
2274 ink_array_return[start - from].y = - ascent;
2275 ink_array_return[start - from].width = rbearing - lbearing;
2276 ink_array_return[start - from].height = ascent + descent;
2277 logical_array_return[start - from].x = x;
2278 logical_array_return[start - from].y = - logical_descent;
2279 logical_array_return[start - from].height
2280 = logical_ascent + logical_descent;
2281 logical_array_return[start - from].width = width;
2287 if (overall_ink_return)
2289 overall_ink_return->y = - gstring->line_ascent;
2290 overall_ink_return->x = gstring->lbearing;
2291 overall_ink_return->width = x - gstring->lbearing;
2292 overall_ink_return->height = gstring->height;
2294 if (overall_logical_return)
2296 overall_logical_return->y = - gstring->ascent;
2297 overall_logical_return->x = 0;
2298 overall_logical_return->width = x;
2299 overall_logical_return->height = gstring->ascent + gstring->descent;
2302 M17N_OBJECT_UNREF (gstring->top);
2309 @brief Return the character position nearest to the coordinates.
2311 The mdraw_coordinates_position () function checks which character
2312 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2313 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2314 mdraw_text_with_control () function with the drawing control
2315 object $CONTROL. Here, the character position means the number of
2316 characters that precede the character in question in $MT, that is,
2317 the character position of the first character is 0.
2319 $FRAME is used only to get the default face information.
2322 If the glyph image of a character covers coordinate ($X, $Y),
2323 mdraw_coordinates_position () returns the character position of
2325 If $Y is less than the minimum Y-coordinate of the drawn area, it
2326 returns $FROM.\n\n\n
2327 If $Y is greater than the maximum Y-coordinate of the drawn area,
2328 it returns $TO.\n\n\n
2329 If $Y fits in with the drawn area but $X is less than the minimum
2330 X-coordinate, it returns the character position of the first
2331 character drawn on the line $Y.\n\n\n
2332 If $Y fits in with the drawn area but $X is greater than the
2333 maximum X-coordinate, it returns the character position of the
2334 last character drawn on the line $Y. */
2337 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2339 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2340 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2341 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2342 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2343 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2344 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2346 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2349 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2350 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2352 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2354 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2356 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2357 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2359 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2360 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2363 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2364 int x_offset, int y_offset, MDrawControl *control)
2366 MGlyphString *gstring;
2371 M_CHECK_POS_X (mt, from, -1);
2372 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2373 to = mtext_nchars (mt) + (control->cursor_width != 0);
2379 ASSURE_CONTROL (control);
2380 gstring = get_gstring (frame, mt, from, to, control);
2381 while (y + gstring->line_descent <= y_offset
2382 && gstring->to < to)
2385 y += gstring->line_descent;
2386 M17N_OBJECT_UNREF (gstring->top);
2387 gstring = get_gstring (frame, mt, from, to, control);
2388 y += gstring->line_ascent;
2391 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2392 if (! control->orientation_reversed)
2394 width = gstring->indent;
2395 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2396 if (g->pos >= from && g->pos < to)
2399 if (width > x_offset)
2405 width = - gstring->indent;
2406 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2407 if (g->pos >= from && g->pos < to)
2410 if (width < x_offset)
2415 M17N_OBJECT_UNREF (gstring->top);
2423 @brief Compute information about a glyph.
2425 The mdraw_glyph_info () function computes information about a
2426 glyph that covers a character at position $POS of the M-text $MT
2427 assuming that the text is drawn from the character at $FROM of $MT
2428 on a window of frame $FRAME using the mdraw_text_with_control ()
2429 function with the drawing control object $CONTROL.
2431 The information is stored in the members of $INFO. */
2433 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2435 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2436 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2437 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2438 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2440 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2448 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2449 MDrawControl *control, MDrawGlyphInfo *info)
2451 MGlyphString *gstring;
2455 M_CHECK_RANGE_X (mt, from, pos, -1);
2457 ASSURE_CONTROL (control);
2458 gstring = get_gstring (frame, mt, from, pos + 1, control);
2460 MERROR (MERROR_DRAW, -1);
2461 while (gstring->to <= pos)
2463 y += gstring->line_descent;
2464 M17N_OBJECT_UNREF (gstring->top);
2465 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2466 y += gstring->line_ascent;
2468 info->line_from = gstring->from;
2469 if (info->line_from < from)
2470 info->line_from = from;
2471 info->line_to = gstring->to;
2474 if (! control->orientation_reversed)
2476 info->x = gstring->indent;
2477 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2478 info->x += g->width;
2482 info->x = - gstring->indent;
2483 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2484 info->x -= g->width;
2485 while (g[-1].to == g->to)
2488 info->from = g->pos;
2490 info->this.x = g->lbearing;
2491 info->this.y = - gstring->line_ascent;
2492 info->this.height = gstring->height;
2493 if (g->rface->rfont)
2494 info->font = &g->rface->rfont->font;
2497 /* info->this.width is calculated later. */
2499 if (info->from > info->line_from)
2501 /* The logically previous glyph is on this line. */
2502 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2504 info->prev_from = g_tmp->pos;
2506 else if (info->line_from > 0)
2508 /* The logically previous glyph is on the previous line. */
2509 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2510 gstring->from, control);
2511 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2513 info->prev_from = g_tmp->pos;
2514 M17N_OBJECT_UNREF (gst->top);
2517 info->prev_from = -1;
2519 if (GLYPH_INDEX (g) > 1)
2520 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2521 else if (! control->orientation_reversed)
2523 if (info->line_from > 0)
2527 int p = gstring->from - 1;
2529 gst = get_gstring (frame, mt, p, gstring->from, control);
2530 g_tmp = gst->glyphs + (gst->used - 2);
2531 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2532 M17N_OBJECT_UNREF (gst->top);
2535 info->left_from = info->left_to = -1;
2539 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2543 int p = gstring->to;
2545 gst = get_gstring (frame, mt, p, p + 1, control);
2546 g_tmp = gst->glyphs + (gst->used - 2);
2547 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2548 M17N_OBJECT_UNREF (gst->top);
2551 info->left_from = info->left_to = -1;
2554 if (info->to < gstring->to)
2556 /* The logically next glyph is on this line. */
2557 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2559 info->next_to = g_tmp->to;
2561 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2563 /* The logically next glyph is on the next line. */
2565 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2566 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2568 info->next_to = g_tmp->to;
2569 M17N_OBJECT_UNREF (gst->top);
2574 for (info->this.width = (g++)->width;
2575 g->pos == pos && g->type != GLYPH_ANCHOR;
2576 info->this.width += (g++)->width);
2578 if (g->type != GLYPH_ANCHOR)
2579 info->right_from = g->pos, info->right_to = g->to;
2580 else if (! control->orientation_reversed)
2582 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2585 M17N_OBJECT_UNREF (gstring->top);
2586 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2588 info->right_from = g->pos, info->right_to = g->to;
2591 info->right_from = info->right_to = -1;
2595 if (info->line_from > 0)
2597 pos = gstring->from - 1;
2598 M17N_OBJECT_UNREF (gstring->top);
2599 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2601 info->right_from = g->pos, info->right_to = g->to;
2604 info->right_from = info->right_to = -1;
2607 M17N_OBJECT_UNREF (gstring->top);
2614 @brief Draw one or more textitems.
2616 The mdraw_text_items () function draws one or more M-texts on
2617 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2618 of the textitems to be drawn and $NITEMS is the number of
2619 textimtems in the array. */
2622 @brief textitem ¤òɽ¼¨¤¹¤ë.
2624 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2625 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2626 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2629 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2633 MTextItem, mdraw_text (). */
2636 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2637 MDrawTextItem *items, int nitems)
2639 while (nitems-- > 0)
2642 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2644 mdraw_text_with_control (frame, win, x, y,
2645 items->mt, 0, mtext_nchars (items->mt),
2647 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2648 items->control, NULL, NULL, NULL);
2651 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2657 @brief calculate a line breaking position.
2659 The function mdraw_default_line_break () calculates a line
2660 breaking position based on the line number $LINE and the
2661 coordinate $Y, when a line is too long to fit within the width
2662 limit. $POS is the position of the character next to the last
2663 one that fits within the limit. $FROM is the position of the
2664 first character of the line, and TO is the position of the last
2665 character displayed on the line if there were not width limit.
2666 LINE and Y are reset to 0 when a line is broken by a newline
2667 character, and incremented each time when a long line is broken
2668 because of the width limit.
2671 This function returns a character position to break the
2676 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2678 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2679 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2680 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2681 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2682 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2683 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2684 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2687 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2691 mdraw_default_line_break (MText *mt, int pos,
2692 int from, int to, int line, int y)
2694 int c = mtext_ref_char (mt, pos);
2697 if (c == ' ' || c == '\t')
2701 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2708 if (c == ' ' || c == '\t')
2711 c = mtext_ref_char (mt, pos);
2724 @brief Obtain per character dimension information.
2726 The mdraw_per_char_extents () function computes the text dimension
2727 of each character in M-text $MT. The faces given as text
2728 properties in $MT and the default face of frame $FRAME determine
2729 the fonts to draw the text. Each successive element in
2730 $ARRAY_RETURN is set to the drawn metrics of successive
2731 characters, which is relative to the origin of the drawing, and a
2732 rectangle for each character in $MT. The number of elements of
2733 $ARRAY_RETURN must be equal to or greater than the number of
2736 If pointer $OVERALL_RETURN is not @c NULL, this function also
2737 computes the extents of the overall text and stores the results in
2738 the members of the structure pointed to by $OVERALL_RETURN */
2741 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2743 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2744 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2745 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è
2746 ¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2747 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2748 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2749 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2751 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2752 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2755 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2758 mdraw_per_char_extents (MFrame *frame, MText *mt,
2759 MDrawMetric *array_return,
2760 MDrawMetric *overall_return)
2765 @brief clear cached information.
2767 The mdraw_clear_cache () function clear cached information
2768 on M-text $MT that was attached by any of the drawing functions.
2769 When the behaviour of `format' or `line_break'
2770 member functions of MDrawControl is changed, the cache must be cleared.
2775 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2777 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2778 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2779 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2780 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2785 mdraw_clear_cache (MText *mt)
2787 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);