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_VIDEOMODE] == Mreverse))
1020 int this_x = x, this_width = width;
1022 if (fromg->type == GLYPH_BOX)
1023 this_x += fromg->width, this_width -= fromg->width;
1024 if (g[-1].type == GLYPH_BOX)
1025 this_width -= g[-1].width;
1026 mwin__fill_space (frame, win, rface, 0,
1027 this_x, y - gstring->text_ascent, this_width,
1028 gstring->text_ascent + gstring->text_descent,
1029 control->clip_region);
1036 rect.y = y - gstring->text_ascent;
1037 rect.height = gstring->text_ascent + gstring->text_descent;
1040 rect.width = ((control->cursor_width > 0
1041 && control->cursor_width < cursor_width)
1042 ? control->cursor_width : cursor_width);
1046 if (cursor->bidi_level % 2)
1047 rect.x += cursor_width - 1;
1050 mwin__fill_space (frame, win, rface, 1,
1051 rect.x, rect.y, rect.width, rect.height,
1052 control->clip_region);
1054 region = mwin__region_from_rect (&rect);
1056 mwin__region_add_rect (region, &rect);
1057 mwin__verify_region (frame, region);
1060 if (cursor->bidi_level % 2)
1063 rect.width = cursor_width < 4 ? cursor_width : 4;
1064 mwin__fill_space (frame, win, rface, 1,
1065 rect.x, rect.y, rect.width, rect.height,
1066 control->clip_region);
1067 mwin__region_add_rect (region, &rect);
1068 mwin__verify_region (frame, region);
1080 if (fromg->type != GLYPH_BOX
1081 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1084 cursor = fromg, cursor_x = x + temp_width;
1085 cursor_width += fromg->width;
1087 temp_width += fromg++->width;
1094 if (! (cursor->bidi_level % 2))
1095 rect.x += cursor_width - 1;
1096 rect.y = y - gstring->text_ascent;
1097 rect.height = gstring->text_ascent + gstring->text_descent;
1099 mwin__fill_space (frame, win, rface, 1,
1100 rect.x, rect.y, rect.width, rect.height,
1101 control->clip_region);
1103 region = mwin__region_from_rect (&rect);
1105 mwin__region_add_rect (region, &rect);
1106 mwin__verify_region (frame, region);
1107 rect.y += rect.height - 2;
1109 rect.width = cursor_width < 4 ? cursor_width : 4;
1110 if (! (cursor->bidi_level % 2))
1111 rect.x -= rect.width - 1;
1112 mwin__fill_space (frame, win, rface, 1,
1113 rect.x, rect.y, rect.width, rect.height,
1114 control->clip_region);
1115 mwin__region_add_rect (region, &rect);
1116 mwin__verify_region (frame, region);
1120 *to_idx = GLYPH_INDEX (g);
1130 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1131 MGlyphString *gstring, int from_idx, int to_idx,
1132 int reverse, MDrawRegion region)
1134 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1140 mwin__region_to_rect (region, &rect);
1143 while (g != gend && x + g->rbearing <= rect.x)
1146 width -= g++->width;
1147 while (! g->enabled && g != gend)
1151 rect.x += rect.width;
1152 if (rect.x < x + width)
1155 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1157 width -= (--gend)->width;
1158 while (! gend->enabled && g != gend)
1162 while (gend[-1].to == gend->to) gend++;
1170 MRealizedFace *rface = g->rface;
1171 int width = g->width;
1172 MGlyph *from_g = g++;
1174 /* Handle the glyphs of the same type/face at once. */
1176 && g->type == from_g->type
1177 && g->rface == rface
1178 && (g->code < 0) == (from_g->code < 0)
1180 width += g++->width;
1182 if (from_g->type == GLYPH_CHAR)
1184 if (rface->rfont && from_g->code >= 0)
1185 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1188 mwin__draw_empty_boxes (win, x, y, gstring, from_g, g,
1191 else if (from_g->type == GLYPH_BOX)
1193 /* Draw the left or right side of a box. If
1194 from_g->lbearing is nonzero, this is the left side,
1195 else this is the right side. */
1196 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1199 if (from_g->type != GLYPH_BOX)
1202 mwin__draw_hline (frame, win, gstring, rface, reverse,
1203 x, y, width, region);
1206 /* Draw the top and bottom side of a box. */
1207 mwin__draw_box (frame, win, gstring, from_g,
1208 x, y, width, region);
1219 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1220 int *from_x, int *to_x)
1223 int left_idx = *left, right_idx = *right;
1224 int left_x, right_x, x;
1226 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1229 if (x + g->rbearing > 0)
1231 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1233 left_idx = GLYPH_INDEX (g);
1238 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1241 if (x - g->width + g->lbearing < 0)
1243 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1245 right_idx = GLYPH_INDEX (g) + 1;
1250 if (*left == left_idx && *right == right_idx)
1253 if (*left != left_idx)
1255 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1260 if (*right != right_idx)
1262 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1272 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1277 if (from <= gstring->from && to >= gstring->to)
1280 *rbearing = gstring->rbearing;
1281 return gstring->width;
1286 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1287 if (g->pos >= from && g->pos < to)
1289 if (rbearing && width + g->rbearing > *rbearing)
1290 *rbearing = width + g->rbearing;
1298 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1299 MGlyphString *gstring, int from, int to)
1301 MDrawControl *control = &gstring->control;
1303 MDrawRegion clip_region, cursor_region;
1304 int from_idx, to_idx;
1307 if (control->orientation_reversed)
1308 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1310 x += gstring->indent;
1312 /* At first, draw all glyphs without cursor. */
1313 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1314 &from_idx, &to_idx, &to_x);
1316 if (control->partial_update)
1319 rect.width = to_x - x;
1320 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1322 rect.y = y - gstring->line_ascent;
1323 rect.height = gstring->height;
1324 clip_region = mwin__region_from_rect (&rect);
1325 if (control->clip_region)
1326 mwin__intersect_region (clip_region, control->clip_region);
1329 clip_region = control->clip_region;
1332 clip_region = control->clip_region;
1334 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1339 mwin__intersect_region (cursor_region, clip_region);
1340 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1343 if (clip_region != control->clip_region)
1344 mwin__free_region (clip_region);
1346 mwin__free_region (cursor_region);
1350 static int gstring_num;
1353 free_gstring (void *object)
1355 MGlyphString *gstring = (MGlyphString *) object;
1358 free_gstring (gstring->next);
1359 if (gstring->size > 0)
1360 free (gstring->glyphs);
1366 static MGlyphString scratch_gstring;
1368 static MGlyphString *
1369 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1372 MGlyphString *gstring;
1374 if (pos == mt->nchars)
1376 gstring = &scratch_gstring;
1380 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1381 MLIST_INIT1 (gstring, glyphs, 128);
1385 gstring->frame = frame;
1386 gstring->tick = frame->tick;
1387 gstring->top = gstring;
1389 gstring->control = *control;
1390 gstring->indent = gstring->width_limit = 0;
1391 if (control->format)
1392 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1394 gstring->width_limit = control->max_line_width;
1395 gstring->anti_alias = control->anti_alias;
1396 if (gstring->anti_alias
1397 && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
1398 gstring->anti_alias = 0;
1402 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1405 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1413 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1414 a width of glyphs for the character at I of GSTRING->mt. If I is
1415 not a beginning of a grapheme cluster, the corresponding element
1417 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1418 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1419 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1420 pos_width[g->pos - gstring->from] += g->width;
1421 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1423 if (pos_width[i] > 0)
1425 if (width + pos_width[i] > gstring->width_limit)
1428 width += pos_width[i];
1431 pos = gstring->from + i;
1432 if (gstring->control.line_break)
1434 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1435 gstring->from, gstring->to, 0, 0);
1436 if (pos <= gstring->from || pos >= gstring->to)
1439 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1440 layout_glyph_string (frame, gstring);
1444 /* Return a gstring that covers a character at POS. */
1446 static MGlyphString *
1447 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1449 MGlyphString *gstring = NULL;
1451 if (pos < mtext_nchars (mt))
1453 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1456 && ((prop->start != 0
1457 && mtext_ref_char (mt, prop->start - 1) != '\n')
1458 || (prop->end < mtext_nchars (mt)
1459 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1461 mtext_detach_property (prop);
1466 gstring = prop->val;
1467 if (gstring->frame != frame
1468 || gstring->tick != frame->tick
1469 || memcmp (control, &gstring->control,
1470 (char *) (&control->with_cursor)
1471 - (char *) (control)))
1473 mtext_detach_property (prop);
1478 else if (! control->cursor_width)
1486 offset = mtext_character (mt, pos, 0, '\n');
1491 offset -= gstring->from;
1493 for (gst = gstring; gst; gst = gst->next)
1497 gst->from += offset;
1499 for (i = 0; i < gst->used; i++)
1501 gst->glyphs[i].pos += offset;
1502 gst->glyphs[i].to += offset;
1505 M17N_OBJECT_REF (gstring);
1510 int line = 0, y = 0;
1512 if (control->two_dimensional)
1514 beg = mtext_character (mt, pos, 0, '\n');
1519 end = mtext_nchars (mt) + (control->cursor_width != 0);
1526 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1527 compose_glyph_string (frame, mt, beg, end, gstring);
1528 layout_glyph_string (frame, gstring);
1530 if (control->two_dimensional
1531 && gstring->width_limit
1532 && gstring->width > gstring->width_limit)
1534 MGlyphString *gst = gstring;
1536 truncate_gstring (frame, mt, gst);
1537 while (gst->to < end)
1539 line++, y += gst->height;
1540 gst->next = alloc_gstring (frame, mt, gst->from, control,
1542 gst->next->top = gstring;
1543 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1545 layout_glyph_string (frame, gst);
1546 if (gst->width <= gst->width_limit)
1548 truncate_gstring (frame, mt, gst);
1552 if (! control->disable_caching && pos < mtext_nchars (mt))
1554 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1555 MTEXTPROP_VOLATILE_STRONG);
1557 if (end > mtext_nchars (mt))
1558 end = mtext_nchars (mt);
1559 mtext_attach_property (mt, beg, end, prop);
1560 M17N_OBJECT_UNREF (prop);
1564 while (gstring->to <= pos)
1566 if (! gstring->next)
1568 gstring = gstring->next;
1570 gstring->control = *control;
1576 static MDrawControl control_noop;
1578 #define ASSURE_CONTROL(control) \
1580 control = &control_noop; \
1585 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1586 MText *mt, int from, int to,
1587 MDrawControl *control)
1589 MGlyphString *gstring;
1591 M_CHECK_POS_X (mt, from, -1);
1592 ASSURE_CONTROL (control);
1593 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1594 to = mtext_nchars (mt) + (control->cursor_width != 0);
1598 gstring = get_gstring (frame, mt, from, to, control);
1600 MERROR (MERROR_DRAW, -1);
1601 render_glyph_string (frame, win, x, y, gstring, from, to);
1605 y += gstring->line_descent;
1606 M17N_OBJECT_UNREF (gstring->top);
1607 gstring = get_gstring (frame, mt, from, to, control);
1608 y += gstring->line_ascent;
1609 render_glyph_string (frame, win, x, y, gstring, from, to);
1612 M17N_OBJECT_UNREF (gstring->top);
1619 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1625 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1626 if (g->pos <= pos && g->to > pos)
1631 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1632 if (g->pos <= pos && g->to > pos)
1639 /* for debugging... */
1643 dump_combining_code (int code)
1645 char *vallign = "tcbB";
1646 char *hallign = "lcr";
1652 if (COMBINING_BY_CLASS_P (code))
1653 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1654 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1655 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1656 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1657 off_x = COMBINING_CODE_OFF_X (code) - 128;
1659 sprintf (work + 2, "+%d", off_y);
1661 sprintf (work + 2, "%d", off_y);
1662 else if (off_x == 0)
1663 sprintf (work + 2, ".");
1664 p = work + strlen (work);
1666 sprintf (p, ">%d", off_x);
1668 sprintf (p, "<%d", -off_x);
1670 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1671 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1677 dump_gstring (MGlyphString *gstring, int indent)
1679 char *prefix = (char *) alloca (indent + 1);
1680 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1682 memset (prefix, 32, indent);
1685 fprintf (stderr, "(glyph-string");
1687 for (g = MGLYPH (0); g < last_g; g++)
1689 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1691 g - gstring->glyphs,
1692 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1693 : g->type == GLYPH_ANCHOR ? "ANC"
1694 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1695 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1696 dump_combining_code (g->combining_code),
1697 g->width, g->bidi_level);
1698 fprintf (stderr, ")");
1702 /* m17n-X internal APIs */
1707 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1709 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1710 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1712 Mlatin = msymbol ("latin");
1713 Minherited = msymbol ("inherited");
1715 McatCc = msymbol ("Cc");
1716 McatCf = msymbol ("Cf");
1717 Mdepth = msymbol ("depth");
1719 MbidiR = msymbol ("R");
1720 MbidiAL = msymbol ("AL");
1721 MbidiRLE = msymbol ("RLE");
1722 MbidiRLO = msymbol ("RLO");
1723 MbidiBN = msymbol ("BN");
1724 MbidiS = msymbol ("S");
1726 fribidi_set_mirroring (TRUE);
1735 MLIST_FREE1 (&scratch_gstring, glyphs);
1739 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1743 /*** @addtogroup m17nDraw */
1748 @brief Draw an M-text on a window.
1750 The mdraw_text () function draws the text between $FROM and $TO of
1751 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1753 The appearance of the text (size, style, color, etc) is specified
1754 by the value of the text property whose key is @c Mface. If the
1755 M-text or a part of the M-text does not have such a text property,
1756 the default face of $FRAME is used.
1758 The font used to draw a character in the M-text is selected from
1759 the value of the fontset property of a face by the following
1764 <li> Search the text properties given to the character for the one
1765 whose key is @c Mcharset; its value should be either a symbol
1766 specifying a charset or #Mnil. If the value is #Mnil,
1767 proceed to the next step.
1769 Otherwise, search the mapping table of the fontset for the
1770 charset. If no entry is found proceed to the next step.
1772 If an entry is found, use one of the fonts in the entry that
1773 has a glyph for the character and that matches best with the
1774 face properties. If no such font exists, proceed to the next
1777 <li> Get the character property "script" of the character. If it is
1778 inherited, get the script property from the previous
1779 characters. If there is no previous character, or none of
1780 them has the script property other than inherited, proceed to
1783 Search the text properties given to the character for the one
1784 whose key is @c Mlanguage; its value should be either a
1785 symbol specifying a language or @c Mnil.
1787 Search the mapping table of the fontset for the combination
1788 of the script and language. If no entry is found, proceed to
1791 If an entry is found, use one of the fonts in the entry that
1792 has a glyph for the character and that matches best with the
1793 face properties. If no such font exists, proceed to the next
1796 <li> Search the fall-back table of the fontset for a font that has
1797 a glyph of the character. If such a font is found, use that
1802 If no font is found by the algorithm above, this function draws an
1803 empty box for the character.
1805 This function draws only the glyph foreground. To specify the
1806 background color, use mdraw_image_text () or
1807 mdraw_text_with_control ().
1809 This function is the counterpart of <tt>XDrawString ()</tt>,
1810 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1811 in the X Window System.
1814 If the operation was successful, mdraw_text () returns 0. If an
1815 error is detected, it returns -1 and assigns an error code to the
1816 external variable #merror_code. */
1818 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1820 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1821 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1824 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1825 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1826 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1827 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1829 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1830 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1834 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1835 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1836 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1837 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1838 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1841 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1842 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1843 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1846 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1847 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1848 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1849 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1851 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1852 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1855 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1856 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1859 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1860 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1861 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1864 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1865 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1869 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1870 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1872 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1873 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1876 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1877 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1880 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1881 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1883 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1890 mdraw_image_text () */
1893 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1894 MText *mt, int from, int to)
1896 MDrawControl control;
1898 memset (&control, 0, sizeof control);
1899 control.as_image = 0;
1900 return draw_text (frame, win, x, y, mt, from, to, &control);
1907 @brief Draw an M-text on a window as an image.
1909 The mdraw_image_text () function draws the text between $FROM and
1910 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1911 coordinate ($X, $Y).
1913 The way to draw a text is the same as in mdraw_text () except that
1914 this function also draws the background with the color specified
1917 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1918 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1919 functions in the X Window System.
1922 If the operation was successful, mdraw_image_text () returns 0.
1923 If an error is detected, it returns -1 and assigns an error code
1924 to the external variable #merror_code. */
1927 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1929 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1930 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1933 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1934 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1936 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1937 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1941 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1942 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1945 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1955 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1956 MText *mt, int from, int to)
1958 MDrawControl control;
1960 memset (&control, 0, sizeof control);
1961 control.as_image = 1;
1962 return draw_text (frame, win, x, y, mt, from, to, &control);
1968 @brief Draw an M-text on a window with fine control.
1970 The mdraw_text_with_control () function draws the text between
1971 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1972 coordinate ($X, $Y).
1974 The way to draw a text is the same as in mdraw_text () except that
1975 this function also follows what specified in the drawing control
1978 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1979 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1980 breaks lines and the following characters are drawn in the next
1981 line. See the documentation of the structure @ MDrawControl for
1985 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
1987 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1988 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
1991 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
1992 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1994 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
1995 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
1996 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2000 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2001 MText *mt, int from, int to, MDrawControl *control)
2003 return draw_text (frame, win, x, y, mt, from, to, control);
2009 @brief Compute text pixel width.
2011 The mdraw_text_extents () function computes the width of text
2012 between $FROM and $TO of M-text $MT when it is drawn on a window
2013 of frame $FRAME using the mdraw_text_with_control () function with
2014 the drawing control object $CONTROL.
2016 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2017 the bounding box of character ink of the M-text, and stores the
2018 results in the members of the structure pointed to by
2019 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2020 surrounding box, the box is included in the bounding box.
2022 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2023 computes the bounding box that provides mininum spacing to other
2024 graphical features (such as surrounding box) for the M-text, and
2025 stores the results in the members of the structure pointed to by
2026 $OVERALL_LOGICAL_RETURN.
2028 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2029 computes the bounding box that provides mininum spacing to the
2030 other M-text drawn, and stores the results in the members of the
2031 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2032 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2033 min_line_ascent, min_line_descent, max_line_ascent, and
2034 max_line_descent of $CONTROL are all zero.
2037 This function returns the width of the text to be drawn in the
2038 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2039 text is drawn in multiple physical lines, it returns the width of
2040 the widest line. If an error occurs, it returns -1 and assigns an
2041 error code to the external variable #merror_code. */
2045 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2047 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2048 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2049 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2051 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2052 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2053 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2054 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2056 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2057 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2058 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2059 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2061 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2062 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2063 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2064 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2065 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2066 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2068 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2069 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2070 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2071 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2073 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2080 mdraw_text_extents (MFrame *frame,
2081 MText *mt, int from, int to, MDrawControl *control,
2082 MDrawMetric *overall_ink_return,
2083 MDrawMetric *overall_logical_return,
2084 MDrawMetric *overall_line_return)
2086 MGlyphString *gstring;
2088 int width, rbearing;
2090 ASSURE_CONTROL (control);
2091 M_CHECK_POS_X (mt, from, -1);
2092 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2093 to = mtext_nchars (mt) + (control->cursor_width != 0);
2097 gstring = get_gstring (frame, mt, from, to, control);
2099 MERROR (MERROR_DRAW, -1);
2100 width = gstring_width (gstring, from, to, &rbearing);
2101 if (overall_ink_return)
2103 overall_ink_return->y = - gstring->physical_ascent;
2104 overall_ink_return->x = gstring->lbearing;
2106 if (overall_logical_return)
2108 overall_logical_return->y = - gstring->ascent;
2109 overall_logical_return->x = 0;
2111 if (overall_line_return)
2113 overall_line_return->y = - gstring->line_ascent;
2114 overall_line_return->x = gstring->lbearing;
2117 for (from = gstring->to; from < to; from = gstring->to)
2119 int this_width, this_rbearing;
2121 y += gstring->line_descent;
2122 M17N_OBJECT_UNREF (gstring->top);
2123 gstring = get_gstring (frame, mt, from, to, control);
2124 this_width = gstring_width (gstring, from, to, &this_rbearing);
2125 y += gstring->line_ascent;
2126 if (width < this_width)
2128 if (rbearing < this_rbearing)
2129 rbearing = this_rbearing;
2131 if (overall_ink_return)
2133 overall_ink_return->width = rbearing;
2134 overall_ink_return->height
2135 = y + gstring->physical_descent - overall_ink_return->y;
2137 if (overall_logical_return)
2139 overall_logical_return->width = width;
2140 overall_logical_return->height
2141 = y + gstring->descent - overall_logical_return->y;
2143 if (overall_line_return)
2145 overall_line_return->width = MAX (width, rbearing);
2146 overall_line_return->height
2147 = y + gstring->line_descent - overall_line_return->y;
2150 M17N_OBJECT_UNREF (gstring->top);
2157 @brief Compute the text dimensions of each character of M-text.
2159 The mdraw_text_per_char_extents () function computes the drawn
2160 metric of each character between $FROM and $TO of M-text $MT
2161 assuming that they are drawn on a window of frame $FRAME using the
2162 mdraw_text_with_control () function with the drawing control
2165 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2166 $LOGICAL_ARRAY_RETURN. Each successive element of
2167 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2168 ink and logical metrics of successive characters respectively,
2169 relative to the drawing origin of the M-text. The number of
2170 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2171 been set is returned to $NUM_CHARS_RETURN.
2173 If $ARRAY_SIZE is too small to return all metrics, the function
2174 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2175 Otherwise, it returns zero.
2177 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2178 @c NULL, this function also computes the metrics of the overall
2179 text and stores the results in the members of the structure
2180 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2182 If $CONTROL->two_dimensional is nonzero, this function computes
2183 only the metrics of characters in the first line. */
2185 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2187 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2188 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2189 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2190 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2192 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2193 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2194 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2195 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2196 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2198 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2199 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2202 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2203 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2204 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2207 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2208 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2211 mdraw_text_per_char_extents (MFrame *frame,
2212 MText *mt, int from, int to,
2213 MDrawControl *control,
2214 MDrawMetric *ink_array_return,
2215 MDrawMetric *logical_array_return,
2217 int *num_chars_return,
2218 MDrawMetric *overall_ink_return,
2219 MDrawMetric *overall_logical_return)
2221 MGlyphString *gstring;
2225 ASSURE_CONTROL (control);
2226 *num_chars_return = to - from;
2227 if (array_size < *num_chars_return)
2229 if (overall_logical_return)
2230 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2231 if (overall_ink_return)
2232 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2234 M_CHECK_RANGE (mt, from, to, -1, 0);
2235 gstring = get_gstring (frame, mt, from, to, control);
2238 *num_chars_return = 0;
2242 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2243 if (g->pos >= from && g->pos < to)
2247 int width = g->width;
2248 int lbearing = g->lbearing;
2249 int rbearing = g->rbearing;
2250 int ascent = g->ascent;
2251 int descent = g->descent;
2252 int logical_ascent = g->rface->rfont->ascent;
2253 int logical_descent = g->rface->rfont->descent;
2255 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2257 if (lbearing < width + g->lbearing)
2258 lbearing = width + g->lbearing;
2259 if (rbearing < width + g->rbearing)
2260 rbearing = width + g->rbearing;
2262 if (ascent < g->ascent)
2264 if (descent < g->descent)
2265 descent = g->descent;
2272 ink_array_return[start - from].x = x + lbearing;
2273 ink_array_return[start - from].y = - ascent;
2274 ink_array_return[start - from].width = rbearing - lbearing;
2275 ink_array_return[start - from].height = ascent + descent;
2276 logical_array_return[start - from].x = x;
2277 logical_array_return[start - from].y = - logical_descent;
2278 logical_array_return[start - from].height
2279 = logical_ascent + logical_descent;
2280 logical_array_return[start - from].width = width;
2286 if (overall_ink_return)
2288 overall_ink_return->y = - gstring->line_ascent;
2289 overall_ink_return->x = gstring->lbearing;
2290 overall_ink_return->width = x - gstring->lbearing;
2291 overall_ink_return->height = gstring->height;
2293 if (overall_logical_return)
2295 overall_logical_return->y = - gstring->ascent;
2296 overall_logical_return->x = 0;
2297 overall_logical_return->width = x;
2298 overall_logical_return->height = gstring->ascent + gstring->descent;
2301 M17N_OBJECT_UNREF (gstring->top);
2308 @brief Return the character position nearest to the coordinates.
2310 The mdraw_coordinates_position () function checks which character
2311 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2312 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2313 mdraw_text_with_control () function with the drawing control
2314 object $CONTROL. Here, the character position means the number of
2315 characters that precede the character in question in $MT, that is,
2316 the character position of the first character is 0.
2318 $FRAME is used only to get the default face information.
2321 If the glyph image of a character covers coordinate ($X, $Y),
2322 mdraw_coordinates_position () returns the character position of
2324 If $Y is less than the minimum Y-coordinate of the drawn area, it
2325 returns $FROM.\n\n\n
2326 If $Y is greater than the maximum Y-coordinate of the drawn area,
2327 it returns $TO.\n\n\n
2328 If $Y fits in with the drawn area but $X is less than the minimum
2329 X-coordinate, it returns the character position of the first
2330 character drawn on the line $Y.\n\n\n
2331 If $Y fits in with the drawn area but $X is greater than the
2332 maximum X-coordinate, it returns the character position of the
2333 last character drawn on the line $Y. */
2336 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2338 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2339 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2340 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2341 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2342 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2343 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2345 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2348 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2349 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2351 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2353 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2355 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2356 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2358 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2359 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2362 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2363 int x_offset, int y_offset, MDrawControl *control)
2365 MGlyphString *gstring;
2370 M_CHECK_POS_X (mt, from, -1);
2371 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2372 to = mtext_nchars (mt) + (control->cursor_width != 0);
2378 ASSURE_CONTROL (control);
2379 gstring = get_gstring (frame, mt, from, to, control);
2380 while (y + gstring->line_descent <= y_offset
2381 && gstring->to < to)
2384 y += gstring->line_descent;
2385 M17N_OBJECT_UNREF (gstring->top);
2386 gstring = get_gstring (frame, mt, from, to, control);
2387 y += gstring->line_ascent;
2390 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2391 if (! control->orientation_reversed)
2393 width = gstring->indent;
2394 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2395 if (g->pos >= from && g->pos < to)
2398 if (width > x_offset)
2404 width = - gstring->indent;
2405 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2406 if (g->pos >= from && g->pos < to)
2409 if (width < x_offset)
2414 M17N_OBJECT_UNREF (gstring->top);
2422 @brief Compute information about a glyph.
2424 The mdraw_glyph_info () function computes information about a
2425 glyph that covers a character at position $POS of the M-text $MT
2426 assuming that the text is drawn from the character at $FROM of $MT
2427 on a window of frame $FRAME using the mdraw_text_with_control ()
2428 function with the drawing control object $CONTROL.
2430 The information is stored in the members of $INFO. */
2432 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2434 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2435 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2436 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2437 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2439 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2447 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2448 MDrawControl *control, MDrawGlyphInfo *info)
2450 MGlyphString *gstring;
2454 M_CHECK_RANGE_X (mt, from, pos, -1);
2456 ASSURE_CONTROL (control);
2457 gstring = get_gstring (frame, mt, from, pos + 1, control);
2459 MERROR (MERROR_DRAW, -1);
2460 while (gstring->to <= pos)
2462 y += gstring->line_descent;
2463 M17N_OBJECT_UNREF (gstring->top);
2464 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2465 y += gstring->line_ascent;
2467 info->line_from = gstring->from;
2468 if (info->line_from < from)
2469 info->line_from = from;
2470 info->line_to = gstring->to;
2473 if (! control->orientation_reversed)
2475 info->x = gstring->indent;
2476 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2477 info->x += g->width;
2481 info->x = - gstring->indent;
2482 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2483 info->x -= g->width;
2484 while (g[-1].to == g->to)
2487 info->from = g->pos;
2489 info->this.x = g->lbearing;
2490 info->this.y = - gstring->line_ascent;
2491 info->this.height = gstring->height;
2492 if (g->rface->rfont)
2493 info->font = &g->rface->rfont->font;
2496 /* info->this.width is calculated later. */
2498 if (info->from > info->line_from)
2500 /* The logically previous glyph is on this line. */
2501 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2503 info->prev_from = g_tmp->pos;
2505 else if (info->line_from > 0)
2507 /* The logically previous glyph is on the previous line. */
2508 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2509 gstring->from, control);
2510 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2512 info->prev_from = g_tmp->pos;
2513 M17N_OBJECT_UNREF (gst->top);
2516 info->prev_from = -1;
2518 if (GLYPH_INDEX (g) > 1)
2519 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2520 else if (! control->orientation_reversed)
2522 if (info->line_from > 0)
2526 int p = gstring->from - 1;
2528 gst = get_gstring (frame, mt, p, gstring->from, control);
2529 g_tmp = gst->glyphs + (gst->used - 2);
2530 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2531 M17N_OBJECT_UNREF (gst->top);
2534 info->left_from = info->left_to = -1;
2538 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2542 int p = gstring->to;
2544 gst = get_gstring (frame, mt, p, p + 1, control);
2545 g_tmp = gst->glyphs + (gst->used - 2);
2546 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2547 M17N_OBJECT_UNREF (gst->top);
2550 info->left_from = info->left_to = -1;
2553 if (info->to < gstring->to)
2555 /* The logically next glyph is on this line. */
2556 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2558 info->next_to = g_tmp->to;
2560 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2562 /* The logically next glyph is on the next line. */
2564 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2565 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2567 info->next_to = g_tmp->to;
2568 M17N_OBJECT_UNREF (gst->top);
2573 for (info->this.width = (g++)->width;
2574 g->pos == pos && g->type != GLYPH_ANCHOR;
2575 info->this.width += (g++)->width);
2577 if (g->type != GLYPH_ANCHOR)
2578 info->right_from = g->pos, info->right_to = g->to;
2579 else if (! control->orientation_reversed)
2581 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2584 M17N_OBJECT_UNREF (gstring->top);
2585 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2587 info->right_from = g->pos, info->right_to = g->to;
2590 info->right_from = info->right_to = -1;
2594 if (info->line_from > 0)
2596 pos = gstring->from - 1;
2597 M17N_OBJECT_UNREF (gstring->top);
2598 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2600 info->right_from = g->pos, info->right_to = g->to;
2603 info->right_from = info->right_to = -1;
2606 M17N_OBJECT_UNREF (gstring->top);
2613 @brief Draw one or more textitems.
2615 The mdraw_text_items () function draws one or more M-texts on
2616 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2617 of the textitems to be drawn and $NITEMS is the number of
2618 textimtems in the array. */
2621 @brief textitem ¤òɽ¼¨¤¹¤ë.
2623 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2624 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2625 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2628 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2632 MTextItem, mdraw_text (). */
2635 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2636 MDrawTextItem *items, int nitems)
2638 while (nitems-- > 0)
2641 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2643 mdraw_text_with_control (frame, win, x, y,
2644 items->mt, 0, mtext_nchars (items->mt),
2646 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2647 items->control, NULL, NULL, NULL);
2650 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2656 @brief calculate a line breaking position.
2658 The function mdraw_default_line_break () calculates a line
2659 breaking position based on the line number $LINE and the
2660 coordinate $Y, when a line is too long to fit within the width
2661 limit. $POS is the position of the character next to the last
2662 one that fits within the limit. $FROM is the position of the
2663 first character of the line, and TO is the position of the last
2664 character displayed on the line if there were not width limit.
2665 LINE and Y are reset to 0 when a line is broken by a newline
2666 character, and incremented each time when a long line is broken
2667 because of the width limit.
2670 This function returns a character position to break the
2675 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2677 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2678 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2679 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2680 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2681 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2682 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2683 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2686 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2690 mdraw_default_line_break (MText *mt, int pos,
2691 int from, int to, int line, int y)
2693 int c = mtext_ref_char (mt, pos);
2696 if (c == ' ' || c == '\t')
2700 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2707 if (c == ' ' || c == '\t')
2710 c = mtext_ref_char (mt, pos);
2723 @brief Obtain per character dimension information.
2725 The mdraw_per_char_extents () function computes the text dimension
2726 of each character in M-text $MT. The faces given as text
2727 properties in $MT and the default face of frame $FRAME determine
2728 the fonts to draw the text. Each successive element in
2729 $ARRAY_RETURN is set to the drawn metrics of successive
2730 characters, which is relative to the origin of the drawing, and a
2731 rectangle for each character in $MT. The number of elements of
2732 $ARRAY_RETURN must be equal to or greater than the number of
2735 If pointer $OVERALL_RETURN is not @c NULL, this function also
2736 computes the extents of the overall text and stores the results in
2737 the members of the structure pointed to by $OVERALL_RETURN */
2740 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2742 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2743 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2744 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è
2745 ¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2746 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2747 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2748 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2750 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2751 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2754 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2757 mdraw_per_char_extents (MFrame *frame, MText *mt,
2758 MDrawMetric *array_return,
2759 MDrawMetric *overall_return)
2764 @brief clear cached information.
2766 The mdraw_clear_cache () function clear cached information
2767 on M-text $MT that was attached by any of the drawing functions.
2768 When the behaviour of `format' or `line_break'
2769 member functions of MDrawControl is changed, the cache must be cleared.
2774 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2776 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2777 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2778 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2779 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2784 mdraw_clear_cache (MText *mt)
2786 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);