1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-texts on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layouting
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face ¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å
44 ¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É
45 ¤¨¤â face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆó¼¡
48 ¸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
53 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
54 /*** @addtogroup m17nInternal
61 #include <sys/types.h>
65 #include "m17n-misc.h"
69 #include "internal-gui.h"
74 #include <fribidi/fribidi.h>
75 #endif /* HAVE_FRIBIDI */
77 #define MAX(x, y) ((x) > (y) ? (x) : (y))
78 #define MIN(x, y) ((x) < (y) ? (x) : (y))
80 static MSymbol M_glyph_string;
83 static MSymbol Mlatin, Minherited;
84 /* Special categories */
85 static MSymbol McatCc, McatCf;
88 /* Glyph-string composer. */
90 static MSymbol MbidiR;
91 static MSymbol MbidiAL;
92 static MSymbol MbidiRLE;
93 static MSymbol MbidiRLO;
94 static MSymbol MbidiBN;
95 static MSymbol MbidiS;
98 visual_order (MGlyphString *gstring)
100 int len = gstring->used - 2;
102 int *idx = alloca (sizeof (int) * len);
104 int bidi_sensitive = gstring->control.orientation_reversed;
106 MGlyph *g = MGLYPH (1);
109 FriBidiCharType base = (gstring->control.orientation_reversed
110 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
111 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
113 FriBidiStrIndex *indices;
114 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
115 #else /* not HAVE_FRIBIDI */
116 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
119 #endif /* not HAVE_FRIBIDI */
121 while (g->type != GLYPH_ANCHOR)
123 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
125 if (bidi == MbidiR || bidi == MbidiAL
126 || bidi == MbidiRLE || bidi == MbidiRLO)
133 idx[size] = GLYPH_INDEX (g);
134 logical[size++] = g++->c;
135 while (g->type != GLYPH_ANCHOR && g->combining_code)
139 if (! bidi_sensitive)
142 glyphs = alloca (sizeof (MGlyph) * gstring->used);
143 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
145 visual = alloca (sizeof (FriBidiChar) * size);
146 indices = alloca (sizeof (FriBidiStrIndex) * size);
148 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
149 #else /* not HAVE_FRIBIDI */
150 indices = alloca (sizeof (int) * size);
151 for (i = 0; i < size; i++)
157 for (j = i + 1; j < size && levels[j]; j++);
158 for (k = j--; i < k; i++, j--)
165 #endif /* not HAVE_FRIBIDI */
167 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
168 starts from gstring->glyphs[IDX[N]].
170 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
171 originally at LOGICAL[INDICES[N]]. */
173 for (i = 0, gidx = 1; i < size; i++)
178 glyphs[k].bidi_level = levels[j];
180 if (visual[i] != logical[j])
183 glyphs[k].c = visual[i];
184 if (glyphs[k].rface->rfont)
185 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
188 #endif /* not HAVE_FRIBIDI */
189 *(MGLYPH (gidx)) = glyphs[k];
191 k < gstring->used - 1 && glyphs[k].combining_code;
194 glyphs[k].bidi_level = levels[j];
195 *(MGLYPH (gidx)) = glyphs[k];
201 reorder_combining_chars (MGlyphString *gstring, int from, int to)
203 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
209 for (g = gbeg; g != gend; g++)
210 if (COMBINING_CODE_CLASS (g->combining_code) > 0
211 && (COMBINING_CODE_CLASS (g[-1].combining_code)
212 > COMBINING_CODE_CLASS (g->combining_code)))
223 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
224 displaying them on FRAME.
226 This function fills members <type>, <rface>, <c>, <pos>, <to>,
227 <code> of glyphs. The other members are filled by
228 layout_glyph_string. */
231 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
232 MGlyphString *gstring)
234 MRealizedFace *default_rface = frame->rface;
235 int stop, face_change, language_change, charset_change;
238 MSymbol language = Mnil, script = Mnil, charset = Mnil;
239 MRealizedFace *rface = default_rface;
241 int size = gstring->control.fixed_width;
245 MLIST_RESET (gstring);
246 gstring->from = from;
248 /* At first generate glyphs while using the member <enabled> as a
249 flag for rface re-checking. */
252 /** Put anchor glyphs at the head and tail. */
253 g_tmp.type = GLYPH_ANCHOR;
254 g_tmp.pos = g_tmp.to = from;
256 APPEND_GLYPH (gstring, g_tmp);
258 stop = face_change = charset_change = language_change = pos = from;
266 if (pos < mtext_nchars (mt))
267 c = mtext_ref_char (mt, pos);
270 g_tmp.category = Mnil;
273 if (c == ' ' || c == '\n' || c == '\t')
274 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
276 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
280 g_tmp.category = mchar_get_prop (c, Mcategory);
281 g_tmp.type = GLYPH_CHAR;
282 this_script = (MSymbol) mchar_get_prop (c, Mscript);
283 if (this_script == Minherited)
284 this_script = script;
287 if (pos == stop || script != this_script
288 || MGLYPH (last)->type != g_tmp.type)
291 if ((non_ascii_found || language != Mnil)
292 && g->type == GLYPH_CHAR)
293 while (g < gstring->glyphs + gstring->used)
294 g = mface__for_chars (script, language, charset,
295 g, gstring->glyphs + gstring->used, size);
296 last = gstring->used;
298 script = this_script;
301 if (pos < mtext_nchars (mt) && pos == language_change)
303 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
304 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
306 if (pos < mtext_nchars (mt) && pos == charset_change)
308 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
309 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
311 if (pos < mtext_nchars (mt) && pos == face_change)
314 int num = mtext_get_prop_values (mt, pos, Mface,
315 (void **) faces, 64);
317 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
319 ? mface__realize (frame, faces, num,
320 language, charset, size)
324 if (stop > language_change)
325 stop = language_change;
326 if (stop > charset_change)
327 stop = charset_change;
328 if (face_change < stop)
332 g_tmp.c = g_tmp.code = c;
339 else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
342 APPEND_GLYPH (gstring, g_tmp);
344 g_tmp.code = g_tmp.c + 0x40;
348 APPEND_GLYPH (gstring, g_tmp);
350 && gstring->control.two_dimensional)
356 /* Append an anchor glyph. */
357 g_tmp.type = GLYPH_ANCHOR;
359 g_tmp.code = MCHAR_INVALID_CODE;
360 g_tmp.pos = g_tmp.to = pos;
362 APPEND_GLYPH (gstring, g_tmp);
366 /* Next, run FLT if necessary. */
367 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
371 if (this->type == GLYPH_CHAR && this->rface->rfont)
375 if (this->rface->rfont->layouter != Mnil)
380 for (prev = MGLYPH (start - 1);
381 (prev->type == GLYPH_CHAR
382 && prev->category == McatCf
383 && (code = mfont__encode_char (this->rface->rfont, prev->c)
384 != MCHAR_INVALID_CODE));
389 (g->type == GLYPH_CHAR
390 && (g->rface->rfont == this->rface->rfont
391 || (g->category == McatCf
392 && ((code = mfont__encode_char (this->rface->rfont,
394 != MCHAR_INVALID_CODE))));
396 if (g->rface->rfont != this->rface->rfont)
398 g->rface->rfont = this->rface->rfont;
401 i = mfont__flt_run (gstring, start, i, this->rface);
405 while (this->type == GLYPH_CHAR
408 && MSYMBOL_NAME (this->category)[0] == 'M'
409 && this->rface->rfont
410 && this->rface->rfont->layouter == Mnil)
412 int class = (int) mchar_get_prop (this->c,
415 = MAKE_COMBINING_CODE_BY_CLASS (class);
419 reorder_combining_chars (gstring, start, i);
427 /* At last, reorder glyphs visually if necessary. */
428 if (gstring->control.enable_bidi)
429 visual_order (gstring);
434 combining_code_from_class (int class)
439 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
440 else if (class == 200) /* below left attached */
441 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
442 else if (class == 202) /* below attached*/
443 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
444 else if (class == 204) /* below right attached */
445 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
446 else if (class == 208) /* left attached */
447 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
448 else if (class == 210) /* right attached */
449 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
450 else if (class == 212) /* above left attached */
451 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
452 else if (class == 214) /* above attached */
453 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
454 else if (class == 216) /* above right attached */
455 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
456 else if (class == 218) /* below left */
457 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
458 else if (class == 220) /* below */
459 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
460 else if (class == 222) /* below right */
461 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
462 else if (class == 224) /* left */
463 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
464 else if (class == 226) /* right */
465 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
466 else if (class == 228) /* above left */
467 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
468 else if (class == 230) /* above */
469 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
470 else if (class == 232) /* above right */
471 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
472 else if (class == 233) /* double below */
473 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
474 else if (class == 234) /* double above */
475 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
476 else if (class == 240) /* iota subscript */
477 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
479 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
485 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
487 int g_physical_ascent, g_physical_descent;
488 int g_width, g_lbearing, g_rbearing;
489 MGlyph *g = MGLYPH (from);
490 MGlyph *last_g = MGLYPH (to);
492 g_physical_ascent = gstring->physical_ascent;
493 g_physical_descent = gstring->physical_descent;
494 g_width = g_lbearing = g_rbearing = 0;
496 mfont__get_metric (gstring, from, to);
501 MRealizedFont *rfont = base->rface->rfont;
502 int size = rfont->font.property[MFONT_SIZE];
503 int width, lbearing, rbearing;
505 if (g == last_g || ! g->combining_code)
508 if (base->left_padding && base->lbearing < 0)
510 base->xoff = - base->lbearing;
511 base->width += base->xoff;
512 base->rbearing += base->xoff;
515 if (base->right_padding && base->rbearing > base->width)
517 base->width = base->rbearing;
519 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
520 rbearing = base->rbearing;
524 /* With combining glyphs. */
525 int left = -base->width;
527 int top = - base->ascent;
528 int bottom = base->descent;
529 int height = bottom - top;
530 int begin = base->pos;
535 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
536 rbearing = base->rbearing;
538 while (g != last_g && g->combining_code)
540 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
542 combining_code = g->combining_code;
543 if (COMBINING_BY_CLASS_P (combining_code))
544 g->combining_code = combining_code
545 = combining_code_from_class (COMBINING_CODE_CLASS
548 rfont = g->rface->rfont;
549 size = rfont->font.property[MFONT_SIZE];
550 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
552 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
554 base_x = COMBINING_CODE_BASE_X (combining_code);
555 base_y = COMBINING_CODE_BASE_Y (combining_code);
556 add_x = COMBINING_CODE_ADD_X (combining_code);
557 add_y = COMBINING_CODE_ADD_Y (combining_code);
561 else if (end < g->to)
564 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
567 if (g->xoff + g->width > right)
568 right = g->xoff + g->width;
569 width = right - left;
570 if (g->xoff + g->lbearing < left + lbearing)
571 lbearing = g->xoff + g->lbearing - left;
572 if (g->xoff + g->rbearing > left + rbearing)
573 rbearing = g->xoff + g->rbearing - left;
576 g->yoff = top + height * base_y / 2;
580 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
582 if (g->yoff - g->ascent < top)
583 top = g->yoff - g->ascent;
584 if (g->yoff + g->descent > bottom)
585 bottom = g->yoff + g->descent;
586 height = bottom - top;
592 base->ascent = - top;
593 base->descent = bottom;
594 base->lbearing = lbearing;
595 base->rbearing = rbearing;
596 if (left < - base->width)
598 base->xoff = - base->width - left;
599 base->width += base->xoff;
600 base->rbearing += base->xoff;
601 base->lbearing += base->xoff;
605 base->width += right;
606 base->rbearing += right;
607 base->right_padding = 1;
608 for (i = 1; base + i != g; i++)
609 base[i].xoff -= right;
612 for (i = 0; base + i != g; i++)
619 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
620 g_physical_descent = MAX (g_physical_descent, base->descent);
621 g_lbearing = MIN (g_lbearing, g_width + lbearing);
622 g_rbearing = MAX (g_rbearing, g_width + rbearing);
623 g_width += base->width;
626 gstring->physical_ascent = g_physical_ascent;
627 gstring->physical_descent = g_physical_descent;
628 gstring->sub_width = g_width;
629 gstring->sub_lbearing = g_lbearing;
630 gstring->sub_rbearing = g_rbearing;
634 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
635 by this function directly. Character glyphs are handled by
636 layouter functions registered in font drivers.
638 This function fill-in all the remaining members of glyphs. */
641 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
643 /* Default width of TAB. */
644 int tab_width = frame->space_width * (gstring->control.tab_width
645 ? gstring->control.tab_width : 8);
649 MDrawControl *control = &(gstring->control);
652 int box_line_height = 0;
653 int ignore_formatting_char = control->ignore_formatting_char;
655 gstring->ascent = gstring->descent = 0;
656 gstring->physical_ascent = gstring->physical_descent = 0;
657 gstring->width = gstring->lbearing = gstring->rbearing = 0;
661 while (g->type != GLYPH_ANCHOR)
663 if (box != g->rface->box)
665 int gidx = GLYPH_INDEX (g);
669 /* Insert the right side of the box. That glyph belongs
670 to the previous grapheme cluster. */
671 MGlyph box_glyph = g[-1];
673 box_glyph.type = GLYPH_BOX;
675 = (control->fixed_width
677 : box->inner_hmargin + box->width + box->outer_hmargin);
678 box_glyph.lbearing = 0;
679 box_glyph.rbearing = box_glyph.width;
681 box_glyph.right_padding = 1;
682 gstring->width += box_glyph.width;
683 gstring->rbearing += box_glyph.width;
684 INSERT_GLYPH (gstring, gidx, box_glyph);
691 /* Insert the left side of the box. That glyph belongs
692 to the following grapheme cluster. */
693 MGlyph box_glyph = *g;
694 int box_height = (box->width
695 + box->inner_vmargin + box->outer_vmargin);
697 if (box_line_height < box_height)
698 box_line_height = box_height;
699 box_glyph.type = GLYPH_BOX;
701 = (control->fixed_width
703 : box->inner_hmargin + box->width + box->outer_hmargin);
704 box_glyph.lbearing = 0;
705 box_glyph.rbearing = box_glyph.width;
707 box_glyph.left_padding = 1;
708 gstring->width += box_glyph.width;
709 gstring->rbearing += box_glyph.width;
710 INSERT_GLYPH (gstring, gidx, box_glyph);
716 if (g->category == McatCf && ignore_formatting_char)
717 g->type = GLYPH_SPACE;
719 if (g->type == GLYPH_CHAR)
721 MRealizedFace *rface = g->rface;
722 MRealizedFont *rfont = rface->rfont;
724 int from = GLYPH_INDEX (g);
726 for (g++; g->type == GLYPH_CHAR; g++)
727 if (! rfont != ! g->rface->rfont
728 || box != g->rface->box
729 || ((fromg->code == MCHAR_INVALID_CODE)
730 != (g->code == MCHAR_INVALID_CODE))
731 || (g->category == McatCf && ignore_formatting_char))
733 if (rfont && fromg->code != MCHAR_INVALID_CODE)
736 int to = GLYPH_INDEX (g);
738 layout_glyphs (frame, gstring, from, to);
739 extra_width = - gstring->sub_lbearing;
741 && (GLYPH_INDEX (g) > 1
742 || control->align_head))
746 pad.type = GLYPH_PAD;
749 pad.width = pad.rbearing = extra_width;
750 INSERT_GLYPH (gstring, from, pad);
752 gstring->sub_lbearing = 0;
753 gstring->sub_width += extra_width;
754 gstring->sub_rbearing += extra_width;
756 g = MGLYPH (from - 1);
757 if (g->type == GLYPH_SPACE)
759 /* The pad just inserted is absorbed (maybe
760 partially) by the previous space while
761 keeping at least some space width. For the
762 moment, we use the arbitrary width 2-pixel.
763 Perhaps, it should be decided by the current
764 face, or a default value of the current
765 frame, which is, however, not yet
767 if (extra_width + 2 < g->width)
769 g->width -= extra_width;
773 extra_width -= g->width - 2;
776 gstring->width -= extra_width;
777 gstring->rbearing -= extra_width;
781 extra_width = gstring->sub_rbearing - gstring->sub_width;
785 if (g->type == GLYPH_SPACE && box == g->rface->box)
789 pad.type = GLYPH_PAD;
792 pad.width = pad.rbearing = extra_width;
793 INSERT_GLYPH (gstring, to, pad);
797 g[-1].width += extra_width;
798 gstring->sub_width += extra_width;
801 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
802 gstring->lbearing = gstring->width + gstring->sub_lbearing;
803 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
804 gstring->rbearing = gstring->width + gstring->sub_rbearing;
805 gstring->width += gstring->sub_width;
806 if (gstring->ascent < rface->ascent)
807 gstring->ascent = rface->ascent;
808 if (gstring->descent < rface->descent)
809 gstring->descent = rface->descent;
814 for (; fromg < g; fromg++)
816 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
817 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
818 fromg->width = fromg->rbearing = 1;
820 fromg->width = fromg->rbearing = rface->space_width;
821 fromg->xoff = fromg->lbearing = 0;
822 fromg->ascent = fromg->descent = 0;
823 gstring->width += fromg->width;
824 gstring->rbearing += fromg->width;
826 if (gstring->ascent < frame->rface->ascent)
827 gstring->ascent = frame->rface->ascent;
828 if (gstring->descent < frame->descent)
829 gstring->descent = frame->rface->descent;
832 else if (g->type == GLYPH_SPACE)
835 g->width = g->rface->space_width;
836 else if (g->c == '\n')
838 g->width = control->cursor_width;
841 if (control->cursor_bidi)
843 else if (g->width < 0)
844 g->width = g->rface->space_width;
847 else if (g->c == '\t')
849 g->width = tab_width - ((gstring->indent + gstring->width)
855 if (g[-1].type == GLYPH_PAD)
857 /* This space glyph absorbs (maybe partially) the
858 previous padding glyph. */
859 g->width -= g[-1].width;
861 /* But, keep at least some space width. For the
862 moment, we use the arbitrary width 2-pixel. */
865 g->rbearing = g->width;
866 gstring->width += g->width;
867 gstring->rbearing += g->width;
870 if (gstring->ascent < g->rface->ascent)
871 gstring->ascent = g->rface->ascent;
872 if (gstring->descent < g->rface->descent)
873 gstring->descent = g->rface->descent;
879 gstring->width += g->width;
880 gstring->rbearing += g->width;
887 /* Insert the right side of the box. */
888 int gidx = GLYPH_INDEX (g);
889 MGlyph box_glyph = g[-1];
891 box_glyph.type = GLYPH_BOX;
893 = (control->fixed_width
895 : box->inner_hmargin + box->width + box->outer_hmargin);
896 box_glyph.lbearing = 0;
897 box_glyph.rbearing = box_glyph.width;
899 box_glyph.right_padding = 1;
900 gstring->width += box_glyph.width;
901 gstring->rbearing += box_glyph.width;
902 INSERT_GLYPH (gstring, gidx, box_glyph);
905 gstring->text_ascent = gstring->ascent;
906 gstring->text_descent = gstring->descent;
907 if (gstring->text_ascent < gstring->physical_ascent)
908 gstring->text_ascent = gstring->physical_ascent;
909 if (gstring->text_descent < gstring->physical_descent)
910 gstring->text_descent = gstring->physical_descent;
911 gstring->line_ascent = gstring->text_ascent;
912 gstring->line_descent = gstring->text_descent;
913 if (box_line_height > 0)
915 gstring->line_ascent += box_line_height;
916 gstring->physical_ascent = gstring->line_ascent;
917 gstring->line_descent += box_line_height;
918 gstring->physical_descent = gstring->line_descent;
921 if (gstring->line_ascent < control->min_line_ascent)
922 gstring->line_ascent = control->min_line_ascent;
923 else if (control->max_line_ascent
924 && control->max_line_ascent > control->min_line_ascent
925 && gstring->line_ascent > control->max_line_ascent)
926 gstring->line_ascent = control->max_line_ascent;
928 if (gstring->line_descent < control->min_line_descent)
929 gstring->line_descent = control->min_line_descent;
930 else if (control->max_line_descent
931 && control->max_line_descent > control->min_line_descent
932 && gstring->line_descent > control->max_line_descent)
933 gstring->line_descent = control->max_line_descent;
934 gstring->height = gstring->line_ascent + gstring->line_descent;
936 if (control->orientation_reversed
939 /* We must adjust TAB width for RTL orientation. */
940 width = gstring->indent;
942 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
944 if (g->type == GLYPH_CHAR && g->c == '\t')
946 int this_width = tab_width - (width % tab_width);
948 if (g[1].type == GLYPH_PAD)
949 this_width -= g[1].width;
950 if (g[-1].type == GLYPH_PAD)
951 this_width -= g[-1].width;
954 gstring->width += this_width - g->width;
955 gstring->rbearing += this_width - g->width;
956 g->width = this_width;
967 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
968 MGlyphString *gstring, int from, int to,
969 int *from_idx, int *to_idx, int *to_x)
971 MGlyph *g = MGLYPH (1);
972 MDrawRegion region = (MDrawRegion) NULL;
973 MDrawControl *control = &gstring->control;
976 int cursor_bidi = control->cursor_bidi;
978 if (control->with_cursor && control->cursor_width)
980 if (gstring->from <= control->cursor_pos
981 && gstring->to > control->cursor_pos)
982 cursor_pos = control->cursor_pos;
984 && gstring->from <= control->cursor_pos - 1
985 && gstring->to > control->cursor_pos - 1)
986 prev_pos = control->cursor_pos - 1;
989 *from_idx = *to_idx = 0;
990 while (g->type != GLYPH_ANCHOR)
992 if (g->pos >= from && g->pos < to)
994 MGlyph *fromg = g, *cursor = NULL;
995 MRealizedFace *rface = g->rface;
997 int cursor_width = 0;
1001 *from_idx = GLYPH_INDEX (g);
1002 while (g->pos >= from && g->pos < to
1003 && g->rface == rface)
1006 if (g->type != GLYPH_BOX
1007 && g->pos <= cursor_pos && g->to > cursor_pos)
1010 cursor = g, cursor_x = x + width;
1011 cursor_width += g->width;
1013 width += g++->width;
1016 && (control->as_image
1017 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1019 int this_x = x, this_width = width;
1021 if (fromg->type == GLYPH_BOX)
1022 this_x += fromg->width, this_width -= fromg->width;
1023 if (g[-1].type == GLYPH_BOX)
1024 this_width -= g[-1].width;
1025 (frame->driver->fill_space)
1026 (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 (*frame->driver->fill_space)
1051 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1052 control->clip_region);
1054 region = (*frame->driver->region_from_rect) (&rect);
1056 (*frame->driver->region_add_rect) (region, &rect);
1059 if (cursor->bidi_level % 2)
1062 rect.width = cursor_width < 4 ? cursor_width : 4;
1063 (*frame->driver->fill_space)
1064 (frame, win, rface, 1,
1065 rect.x, rect.y, rect.width, rect.height,
1066 control->clip_region);
1067 (*frame->driver->region_add_rect) (region, &rect);
1079 if (fromg->type != GLYPH_BOX
1080 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1083 cursor = fromg, cursor_x = x + temp_width;
1084 cursor_width += fromg->width;
1086 temp_width += fromg++->width;
1093 if (! (cursor->bidi_level % 2))
1094 rect.x += cursor_width - 1;
1095 rect.y = y - gstring->text_ascent;
1096 rect.height = gstring->text_ascent + gstring->text_descent;
1098 (*frame->driver->fill_space)
1099 (frame, win, rface, 1,
1100 rect.x, rect.y, rect.width, rect.height,
1101 control->clip_region);
1103 region = (*frame->driver->region_from_rect) (&rect);
1105 (*frame->driver->region_add_rect) (region, &rect);
1106 rect.y += rect.height - 2;
1108 rect.width = cursor_width < 4 ? cursor_width : 4;
1109 if (! (cursor->bidi_level % 2))
1110 rect.x -= rect.width - 1;
1111 (*frame->driver->fill_space) (frame, win, rface, 1,
1112 rect.x, rect.y, rect.width, rect.height,
1113 control->clip_region);
1114 (*frame->driver->region_add_rect) (region, &rect);
1118 *to_idx = GLYPH_INDEX (g);
1128 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1129 MGlyphString *gstring, int from_idx, int to_idx,
1130 int reverse, MDrawRegion region)
1132 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1138 (*frame->driver->region_to_rect) (region, &rect);
1141 while (g != gend && x + g->rbearing <= rect.x)
1144 width -= g++->width;
1145 while (! g->enabled && g != gend)
1149 rect.x += rect.width;
1150 if (rect.x < x + width)
1153 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1155 width -= (--gend)->width;
1156 while (! gend->enabled && g != gend)
1160 while (gend[-1].to == gend->to) gend++;
1168 MRealizedFace *rface = g->rface;
1169 int width = g->width;
1170 MGlyph *from_g = g++;
1172 /* Handle the glyphs of the same type/face at once. */
1174 && g->type == from_g->type
1175 && g->rface == rface
1176 && (g->code < 0) == (from_g->code < 0)
1178 width += g++->width;
1180 if (from_g->type == GLYPH_CHAR)
1182 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1183 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1186 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1189 else if (from_g->type == GLYPH_BOX)
1191 /* Draw the left or right side of a box. If
1192 from_g->lbearing is nonzero, this is the left side,
1193 else this is the right side. */
1194 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1197 if (from_g->type != GLYPH_BOX)
1200 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1201 x, y, width, region);
1204 /* Draw the top and bottom side of a box. */
1205 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1206 x, y, width, region);
1217 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1218 int *from_x, int *to_x)
1221 int left_idx = *left, right_idx = *right;
1222 int left_x, right_x, x;
1224 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1227 if (x + g->rbearing > 0)
1229 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1231 left_idx = GLYPH_INDEX (g);
1236 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1239 if (x - g->width + g->lbearing < 0)
1241 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1243 right_idx = GLYPH_INDEX (g) + 1;
1248 if (*left == left_idx && *right == right_idx)
1251 if (*left != left_idx)
1253 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1258 if (*right != right_idx)
1260 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1270 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1275 if (from <= gstring->from && to >= gstring->to)
1278 *rbearing = gstring->rbearing;
1279 return gstring->width;
1284 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1285 if (g->pos >= from && g->pos < to)
1287 if (rbearing && width + g->rbearing > *rbearing)
1288 *rbearing = width + g->rbearing;
1296 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1297 MGlyphString *gstring, int from, int to)
1299 MDrawControl *control = &gstring->control;
1301 MDrawRegion clip_region, cursor_region;
1302 int from_idx, to_idx;
1305 if (control->orientation_reversed)
1306 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1308 x += gstring->indent;
1310 /* At first, draw all glyphs without cursor. */
1311 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1312 &from_idx, &to_idx, &to_x);
1314 if (control->partial_update)
1317 rect.width = to_x - x;
1318 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1320 rect.y = y - gstring->line_ascent;
1321 rect.height = gstring->height;
1322 clip_region = (*frame->driver->region_from_rect) (&rect);
1323 if (control->clip_region)
1324 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1327 clip_region = control->clip_region;
1330 clip_region = control->clip_region;
1332 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1337 (*frame->driver->intersect_region) (cursor_region, clip_region);
1338 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1341 if (clip_region != control->clip_region)
1342 (*frame->driver->free_region) (clip_region);
1344 (*frame->driver->free_region) (cursor_region);
1348 static int gstring_num;
1351 free_gstring (void *object)
1353 MGlyphString *gstring = (MGlyphString *) object;
1356 free_gstring (gstring->next);
1357 if (gstring->size > 0)
1358 free (gstring->glyphs);
1364 static MGlyphString scratch_gstring;
1366 static MGlyphString *
1367 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1370 MGlyphString *gstring;
1372 if (pos == mt->nchars)
1374 gstring = &scratch_gstring;
1378 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1379 MLIST_INIT1 (gstring, glyphs, 128);
1383 gstring->frame = frame;
1384 gstring->tick = frame->tick;
1385 gstring->top = gstring;
1387 gstring->control = *control;
1388 gstring->indent = gstring->width_limit = 0;
1389 if (control->format)
1390 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1392 gstring->width_limit = control->max_line_width;
1393 gstring->anti_alias = control->anti_alias;
1397 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1400 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1408 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1409 a width of glyphs for the character at I of GSTRING->mt. If I is
1410 not a beginning of a grapheme cluster, the corresponding element
1412 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1413 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1414 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1415 pos_width[g->pos - gstring->from] += g->width;
1416 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1418 if (pos_width[i] > 0)
1420 if (width + pos_width[i] > gstring->width_limit)
1423 width += pos_width[i];
1426 pos = gstring->from + i;
1427 if (gstring->control.line_break)
1429 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1430 gstring->from, gstring->to, 0, 0);
1431 if (pos <= gstring->from || pos >= gstring->to)
1434 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1435 layout_glyph_string (frame, gstring);
1439 /* Return a gstring that covers a character at POS. */
1441 static MGlyphString *
1442 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1444 MGlyphString *gstring = NULL;
1446 if (pos < mtext_nchars (mt))
1448 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1451 && ((prop->start != 0
1452 && mtext_ref_char (mt, prop->start - 1) != '\n')
1453 || (prop->end < mtext_nchars (mt)
1454 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1456 mtext_detach_property (prop);
1461 gstring = prop->val;
1462 if (gstring->frame != frame
1463 || gstring->tick != frame->tick
1464 || memcmp (control, &gstring->control,
1465 (char *) (&control->with_cursor)
1466 - (char *) (control)))
1468 mtext_detach_property (prop);
1473 else if (! control->cursor_width)
1481 offset = mtext_character (mt, pos, 0, '\n');
1486 offset -= gstring->from;
1488 for (gst = gstring; gst; gst = gst->next)
1492 gst->from += offset;
1494 for (i = 0; i < gst->used; i++)
1496 gst->glyphs[i].pos += offset;
1497 gst->glyphs[i].to += offset;
1500 M17N_OBJECT_REF (gstring);
1505 int line = 0, y = 0;
1507 if (control->two_dimensional)
1509 beg = mtext_character (mt, pos, 0, '\n');
1514 end = mtext_nchars (mt) + (control->cursor_width != 0);
1521 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1522 compose_glyph_string (frame, mt, beg, end, gstring);
1523 layout_glyph_string (frame, gstring);
1525 if (control->two_dimensional
1526 && gstring->width_limit
1527 && gstring->width > gstring->width_limit)
1529 MGlyphString *gst = gstring;
1531 truncate_gstring (frame, mt, gst);
1532 while (gst->to < end)
1534 line++, y += gst->height;
1535 gst->next = alloc_gstring (frame, mt, gst->from, control,
1537 gst->next->top = gstring;
1538 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1540 layout_glyph_string (frame, gst);
1541 if (gst->width <= gst->width_limit)
1543 truncate_gstring (frame, mt, gst);
1547 if (! control->disable_caching && pos < mtext_nchars (mt))
1549 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1550 MTEXTPROP_VOLATILE_STRONG);
1552 if (end > mtext_nchars (mt))
1553 end = mtext_nchars (mt);
1554 mtext_attach_property (mt, beg, end, prop);
1555 M17N_OBJECT_UNREF (prop);
1559 while (gstring->to <= pos)
1561 if (! gstring->next)
1563 gstring = gstring->next;
1565 gstring->control = *control;
1571 static MDrawControl control_noop;
1573 #define ASSURE_CONTROL(control) \
1575 control = &control_noop; \
1580 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1581 MText *mt, int from, int to,
1582 MDrawControl *control)
1584 MGlyphString *gstring;
1586 M_CHECK_POS_X (mt, from, -1);
1587 ASSURE_CONTROL (control);
1588 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1589 to = mtext_nchars (mt) + (control->cursor_width != 0);
1593 gstring = get_gstring (frame, mt, from, to, control);
1595 MERROR (MERROR_DRAW, -1);
1596 render_glyph_string (frame, win, x, y, gstring, from, to);
1600 y += gstring->line_descent;
1601 M17N_OBJECT_UNREF (gstring->top);
1602 gstring = get_gstring (frame, mt, from, to, control);
1603 y += gstring->line_ascent;
1604 render_glyph_string (frame, win, x, y, gstring, from, to);
1607 M17N_OBJECT_UNREF (gstring->top);
1614 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1620 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1621 if (g->pos <= pos && g->to > pos)
1626 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1627 if (g->pos <= pos && g->to > pos)
1634 /* for debugging... */
1638 dump_combining_code (int code)
1640 char *vallign = "tcbB";
1641 char *hallign = "lcr";
1647 if (COMBINING_BY_CLASS_P (code))
1648 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1649 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1650 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1651 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1652 off_x = COMBINING_CODE_OFF_X (code) - 128;
1654 sprintf (work + 2, "+%d", off_y);
1656 sprintf (work + 2, "%d", off_y);
1657 else if (off_x == 0)
1658 sprintf (work + 2, ".");
1659 p = work + strlen (work);
1661 sprintf (p, ">%d", off_x);
1663 sprintf (p, "<%d", -off_x);
1665 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1666 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1672 dump_gstring (MGlyphString *gstring, int indent)
1674 char *prefix = (char *) alloca (indent + 1);
1675 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1677 memset (prefix, 32, indent);
1680 fprintf (stderr, "(glyph-string");
1682 for (g = MGLYPH (0); g < last_g; g++)
1684 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1686 g - gstring->glyphs,
1687 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1688 : g->type == GLYPH_ANCHOR ? "ANC"
1689 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1690 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1691 dump_combining_code (g->combining_code),
1692 g->width, g->bidi_level);
1693 fprintf (stderr, ")");
1697 /* m17n-X internal APIs */
1702 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1704 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1705 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1707 Mlatin = msymbol ("latin");
1708 Minherited = msymbol ("inherited");
1710 McatCc = msymbol ("Cc");
1711 McatCf = msymbol ("Cf");
1713 MbidiR = msymbol ("R");
1714 MbidiAL = msymbol ("AL");
1715 MbidiRLE = msymbol ("RLE");
1716 MbidiRLO = msymbol ("RLO");
1717 MbidiBN = msymbol ("BN");
1718 MbidiS = msymbol ("S");
1720 fribidi_set_mirroring (TRUE);
1729 MLIST_FREE1 (&scratch_gstring, glyphs);
1733 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1737 /*** @addtogroup m17nDraw */
1742 @brief Draw an M-text on a window.
1744 The mdraw_text () function draws the text between $FROM and $TO of
1745 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1747 The appearance of the text (size, style, color, etc) is specified
1748 by the value of the text property whose key is @c Mface. If the
1749 M-text or a part of the M-text does not have such a text property,
1750 the default face of $FRAME is used.
1752 The font used to draw a character in the M-text is selected from
1753 the value of the fontset property of a face by the following
1758 <li> Search the text properties given to the character for the one
1759 whose key is @c Mcharset; its value should be either a symbol
1760 specifying a charset or #Mnil. If the value is #Mnil,
1761 proceed to the next step.
1763 Otherwise, search the mapping table of the fontset for the
1764 charset. If no entry is found proceed to the next step.
1766 If an entry is found, use one of the fonts in the entry that
1767 has a glyph for the character and that matches best with the
1768 face properties. If no such font exists, proceed to the next
1771 <li> Get the character property "script" of the character. If it is
1772 inherited, get the script property from the previous
1773 characters. If there is no previous character, or none of
1774 them has the script property other than inherited, proceed to
1777 Search the text properties given to the character for the one
1778 whose key is @c Mlanguage; its value should be either a
1779 symbol specifying a language or @c Mnil.
1781 Search the mapping table of the fontset for the combination
1782 of the script and language. If no entry is found, proceed to
1785 If an entry is found, use one of the fonts in the entry that
1786 has a glyph for the character and that matches best with the
1787 face properties. If no such font exists, proceed to the next
1790 <li> Search the fall-back table of the fontset for a font that has
1791 a glyph of the character. If such a font is found, use that
1796 If no font is found by the algorithm above, this function draws an
1797 empty box for the character.
1799 This function draws only the glyph foreground. To specify the
1800 background color, use mdraw_image_text () or
1801 mdraw_text_with_control ().
1803 This function is the counterpart of <tt>XDrawString ()</tt>,
1804 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1805 in the X Window System.
1808 If the operation was successful, mdraw_text () returns 0. If an
1809 error is detected, it returns -1 and assigns an error code to the
1810 external variable #merror_code. */
1812 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1814 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1815 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1818 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1819 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1820 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1821 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1823 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1824 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1828 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1829 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1830 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1831 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1832 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1835 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1836 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1837 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1840 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1841 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1842 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1843 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1845 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1846 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1849 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1850 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1853 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1854 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1855 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1858 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1859 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1863 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1864 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1866 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1867 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1870 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1871 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1874 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1875 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1877 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1884 mdraw_image_text () */
1887 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1888 MText *mt, int from, int to)
1890 MDrawControl control;
1892 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1893 memset (&control, 0, sizeof control);
1894 control.as_image = 0;
1895 return draw_text (frame, win, x, y, mt, from, to, &control);
1902 @brief Draw an M-text on a window as an image.
1904 The mdraw_image_text () function draws the text between $FROM and
1905 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1906 coordinate ($X, $Y).
1908 The way to draw a text is the same as in mdraw_text () except that
1909 this function also draws the background with the color specified
1912 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1913 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1914 functions in the X Window System.
1917 If the operation was successful, mdraw_image_text () returns 0.
1918 If an error is detected, it returns -1 and assigns an error code
1919 to the external variable #merror_code. */
1922 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1924 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1925 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1928 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1929 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1931 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1932 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1936 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1937 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1940 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1950 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1951 MText *mt, int from, int to)
1953 MDrawControl control;
1955 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1956 memset (&control, 0, sizeof control);
1957 control.as_image = 1;
1958 return draw_text (frame, win, x, y, mt, from, to, &control);
1964 @brief Draw an M-text on a window with fine control.
1966 The mdraw_text_with_control () function draws the text between
1967 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1968 coordinate ($X, $Y).
1970 The way to draw a text is the same as in mdraw_text () except that
1971 this function also follows what specified in the drawing control
1974 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1975 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1976 breaks lines and the following characters are drawn in the next
1977 line. See the documentation of the structure @ MDrawControl for
1981 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
1983 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1984 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
1987 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
1988 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1990 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
1991 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
1992 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
1996 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
1997 MText *mt, int from, int to, MDrawControl *control)
1999 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2000 return draw_text (frame, win, x, y, mt, from, to, control);
2006 @brief Compute text pixel width.
2008 The mdraw_text_extents () function computes the width of text
2009 between $FROM and $TO of M-text $MT when it is drawn on a window
2010 of frame $FRAME using the mdraw_text_with_control () function with
2011 the drawing control object $CONTROL.
2013 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2014 the bounding box of character ink of the M-text, and stores the
2015 results in the members of the structure pointed to by
2016 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2017 surrounding box, the box is included in the bounding box.
2019 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2020 computes the bounding box that provides mininum spacing to other
2021 graphical features (such as surrounding box) for the M-text, and
2022 stores the results in the members of the structure pointed to by
2023 $OVERALL_LOGICAL_RETURN.
2025 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2026 computes the bounding box that provides mininum spacing to the
2027 other M-text drawn, and stores the results in the members of the
2028 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2029 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2030 min_line_ascent, min_line_descent, max_line_ascent, and
2031 max_line_descent of $CONTROL are all zero.
2034 This function returns the width of the text to be drawn in the
2035 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2036 text is drawn in multiple physical lines, it returns the width of
2037 the widest line. If an error occurs, it returns -1 and assigns an
2038 error code to the external variable #merror_code. */
2042 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2044 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2045 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2046 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2048 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2049 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2050 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2051 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2053 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2054 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2055 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2056 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2058 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2059 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2060 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2061 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2062 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2063 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2065 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2066 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2067 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2068 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2070 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2077 mdraw_text_extents (MFrame *frame,
2078 MText *mt, int from, int to, MDrawControl *control,
2079 MDrawMetric *overall_ink_return,
2080 MDrawMetric *overall_logical_return,
2081 MDrawMetric *overall_line_return)
2083 MGlyphString *gstring;
2085 int width, rbearing;
2087 ASSURE_CONTROL (control);
2088 M_CHECK_POS_X (mt, from, -1);
2089 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2090 to = mtext_nchars (mt) + (control->cursor_width != 0);
2094 gstring = get_gstring (frame, mt, from, to, control);
2096 MERROR (MERROR_DRAW, -1);
2097 width = gstring_width (gstring, from, to, &rbearing);
2098 if (overall_ink_return)
2100 overall_ink_return->y = - gstring->physical_ascent;
2101 overall_ink_return->x = gstring->lbearing;
2103 if (overall_logical_return)
2105 overall_logical_return->y = - gstring->ascent;
2106 overall_logical_return->x = 0;
2108 if (overall_line_return)
2110 overall_line_return->y = - gstring->line_ascent;
2111 overall_line_return->x = gstring->lbearing;
2114 for (from = gstring->to; from < to; from = gstring->to)
2116 int this_width, this_rbearing;
2118 y += gstring->line_descent;
2119 M17N_OBJECT_UNREF (gstring->top);
2120 gstring = get_gstring (frame, mt, from, to, control);
2121 this_width = gstring_width (gstring, from, to, &this_rbearing);
2122 y += gstring->line_ascent;
2123 if (width < this_width)
2125 if (rbearing < this_rbearing)
2126 rbearing = this_rbearing;
2128 if (overall_ink_return)
2130 overall_ink_return->width = rbearing;
2131 overall_ink_return->height
2132 = y + gstring->physical_descent - overall_ink_return->y;
2134 if (overall_logical_return)
2136 overall_logical_return->width = width;
2137 overall_logical_return->height
2138 = y + gstring->descent - overall_logical_return->y;
2140 if (overall_line_return)
2142 overall_line_return->width = MAX (width, rbearing);
2143 overall_line_return->height
2144 = y + gstring->line_descent - overall_line_return->y;
2147 M17N_OBJECT_UNREF (gstring->top);
2154 @brief Compute the text dimensions of each character of M-text.
2156 The mdraw_text_per_char_extents () function computes the drawn
2157 metric of each character between $FROM and $TO of M-text $MT
2158 assuming that they are drawn on a window of frame $FRAME using the
2159 mdraw_text_with_control () function with the drawing control
2162 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2163 $LOGICAL_ARRAY_RETURN. Each successive element of
2164 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2165 ink and logical metrics of successive characters respectively,
2166 relative to the drawing origin of the M-text. The number of
2167 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2168 been set is returned to $NUM_CHARS_RETURN.
2170 If $ARRAY_SIZE is too small to return all metrics, the function
2171 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2172 Otherwise, it returns zero.
2174 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2175 @c NULL, this function also computes the metrics of the overall
2176 text and stores the results in the members of the structure
2177 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2179 If $CONTROL->two_dimensional is nonzero, this function computes
2180 only the metrics of characters in the first line. */
2182 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2184 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2185 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2186 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2187 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2189 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2190 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2191 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2192 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2193 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2195 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2196 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2199 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2200 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2201 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2204 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2205 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2208 mdraw_text_per_char_extents (MFrame *frame,
2209 MText *mt, int from, int to,
2210 MDrawControl *control,
2211 MDrawMetric *ink_array_return,
2212 MDrawMetric *logical_array_return,
2214 int *num_chars_return,
2215 MDrawMetric *overall_ink_return,
2216 MDrawMetric *overall_logical_return)
2218 MGlyphString *gstring;
2222 ASSURE_CONTROL (control);
2223 *num_chars_return = to - from;
2224 if (array_size < *num_chars_return)
2225 MERROR (MERROR_DRAW, -1);
2226 if (overall_logical_return)
2227 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2228 if (overall_ink_return)
2229 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2231 M_CHECK_RANGE (mt, from, to, -1, 0);
2232 gstring = get_gstring (frame, mt, from, to, control);
2235 *num_chars_return = 0;
2239 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2240 if (g->pos >= from && g->pos < to)
2244 int width = g->width;
2245 int lbearing = g->lbearing;
2246 int rbearing = g->rbearing;
2247 int ascent = g->ascent;
2248 int descent = g->descent;
2249 int logical_ascent = g->rface->rfont->ascent;
2250 int logical_descent = g->rface->rfont->descent;
2252 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2254 if (lbearing < width + g->lbearing)
2255 lbearing = width + g->lbearing;
2256 if (rbearing < width + g->rbearing)
2257 rbearing = width + g->rbearing;
2259 if (ascent < g->ascent)
2261 if (descent < g->descent)
2262 descent = g->descent;
2269 ink_array_return[start - from].x = x + lbearing;
2270 ink_array_return[start - from].y = - ascent;
2271 ink_array_return[start - from].width = rbearing - lbearing;
2272 ink_array_return[start - from].height = ascent + descent;
2273 logical_array_return[start - from].x = x;
2274 logical_array_return[start - from].y = - logical_descent;
2275 logical_array_return[start - from].height
2276 = logical_ascent + logical_descent;
2277 logical_array_return[start - from].width = width;
2283 if (overall_ink_return)
2285 overall_ink_return->y = - gstring->line_ascent;
2286 overall_ink_return->x = gstring->lbearing;
2287 overall_ink_return->width = x - gstring->lbearing;
2288 overall_ink_return->height = gstring->height;
2290 if (overall_logical_return)
2292 overall_logical_return->y = - gstring->ascent;
2293 overall_logical_return->x = 0;
2294 overall_logical_return->width = x;
2295 overall_logical_return->height = gstring->ascent + gstring->descent;
2298 M17N_OBJECT_UNREF (gstring->top);
2305 @brief Return the character position nearest to the coordinates.
2307 The mdraw_coordinates_position () function checks which character
2308 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2309 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2310 mdraw_text_with_control () function with the drawing control
2311 object $CONTROL. Here, the character position means the number of
2312 characters that precede the character in question in $MT, that is,
2313 the character position of the first character is 0.
2315 $FRAME is used only to get the default face information.
2318 If the glyph image of a character covers coordinate ($X, $Y),
2319 mdraw_coordinates_position () returns the character position of
2321 If $Y is less than the minimum Y-coordinate of the drawn area, it
2322 returns $FROM.\n\n\n
2323 If $Y is greater than the maximum Y-coordinate of the drawn area,
2324 it returns $TO.\n\n\n
2325 If $Y fits in with the drawn area but $X is less than the minimum
2326 X-coordinate, it returns the character position of the first
2327 character drawn on the line $Y.\n\n\n
2328 If $Y fits in with the drawn area but $X is greater than the
2329 maximum X-coordinate, it returns the character position of the
2330 last character drawn on the line $Y. */
2333 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2335 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2336 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2337 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2338 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2339 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2340 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2342 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2345 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2346 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2348 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2350 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2352 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2353 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2355 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2356 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2359 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2360 int x_offset, int y_offset, MDrawControl *control)
2362 MGlyphString *gstring;
2367 M_CHECK_POS_X (mt, from, -1);
2368 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2369 to = mtext_nchars (mt) + (control->cursor_width != 0);
2375 ASSURE_CONTROL (control);
2376 gstring = get_gstring (frame, mt, from, to, control);
2377 while (y + gstring->line_descent <= y_offset
2378 && gstring->to < to)
2381 y += gstring->line_descent;
2382 M17N_OBJECT_UNREF (gstring->top);
2383 gstring = get_gstring (frame, mt, from, to, control);
2384 y += gstring->line_ascent;
2387 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2388 if (! control->orientation_reversed)
2390 width = gstring->indent;
2391 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2392 if (g->pos >= from && g->pos < to)
2395 if (width > x_offset)
2401 width = - gstring->indent;
2402 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2403 if (g->pos >= from && g->pos < to)
2406 if (width < x_offset)
2411 M17N_OBJECT_UNREF (gstring->top);
2419 @brief Compute information about a glyph.
2421 The mdraw_glyph_info () function computes information about a
2422 glyph that covers a character at position $POS of the M-text $MT
2423 assuming that the text is drawn from the character at $FROM of $MT
2424 on a window of frame $FRAME using the mdraw_text_with_control ()
2425 function with the drawing control object $CONTROL.
2427 The information is stored in the members of $INFO. */
2429 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2431 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2432 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2433 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2434 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2436 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2444 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2445 MDrawControl *control, MDrawGlyphInfo *info)
2447 MGlyphString *gstring;
2451 M_CHECK_RANGE_X (mt, from, pos, -1);
2453 ASSURE_CONTROL (control);
2454 gstring = get_gstring (frame, mt, from, pos + 1, control);
2456 MERROR (MERROR_DRAW, -1);
2457 while (gstring->to <= pos)
2459 y += gstring->line_descent;
2460 M17N_OBJECT_UNREF (gstring->top);
2461 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2462 y += gstring->line_ascent;
2464 info->line_from = gstring->from;
2465 if (info->line_from < from)
2466 info->line_from = from;
2467 info->line_to = gstring->to;
2470 if (! control->orientation_reversed)
2472 info->x = gstring->indent;
2473 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2474 info->x += g->width;
2478 info->x = - gstring->indent;
2479 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2480 info->x -= g->width;
2481 while (g[-1].to == g->to)
2484 info->from = g->pos;
2486 info->this.x = g->lbearing;
2487 info->this.y = - gstring->line_ascent;
2488 info->this.height = gstring->height;
2489 if (g->rface->rfont)
2490 info->font = &g->rface->rfont->font;
2493 /* info->this.width is calculated later. */
2495 if (info->from > info->line_from)
2497 /* The logically previous glyph is on this line. */
2498 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2500 info->prev_from = g_tmp->pos;
2502 else if (info->line_from > 0)
2504 /* The logically previous glyph is on the previous line. */
2505 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2506 gstring->from, control);
2507 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2509 info->prev_from = g_tmp->pos;
2510 M17N_OBJECT_UNREF (gst->top);
2513 info->prev_from = -1;
2515 if (GLYPH_INDEX (g) > 1)
2516 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2517 else if (! control->orientation_reversed)
2519 if (info->line_from > 0)
2523 int p = gstring->from - 1;
2525 gst = get_gstring (frame, mt, p, gstring->from, control);
2526 g_tmp = gst->glyphs + (gst->used - 2);
2527 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2528 M17N_OBJECT_UNREF (gst->top);
2531 info->left_from = info->left_to = -1;
2535 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2539 int p = gstring->to;
2541 gst = get_gstring (frame, mt, p, p + 1, control);
2542 g_tmp = gst->glyphs + (gst->used - 2);
2543 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2544 M17N_OBJECT_UNREF (gst->top);
2547 info->left_from = info->left_to = -1;
2550 if (info->to < gstring->to)
2552 /* The logically next glyph is on this line. */
2553 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2555 info->next_to = g_tmp->to;
2557 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2559 /* The logically next glyph is on the next line. */
2561 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2562 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2564 info->next_to = g_tmp->to;
2565 M17N_OBJECT_UNREF (gst->top);
2570 for (info->this.width = (g++)->width;
2571 g->pos == pos && g->type != GLYPH_ANCHOR;
2572 info->this.width += (g++)->width);
2574 if (g->type != GLYPH_ANCHOR)
2575 info->right_from = g->pos, info->right_to = g->to;
2576 else if (! control->orientation_reversed)
2578 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2581 M17N_OBJECT_UNREF (gstring->top);
2582 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2584 info->right_from = g->pos, info->right_to = g->to;
2587 info->right_from = info->right_to = -1;
2591 if (info->line_from > 0)
2593 pos = gstring->from - 1;
2594 M17N_OBJECT_UNREF (gstring->top);
2595 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2597 info->right_from = g->pos, info->right_to = g->to;
2600 info->right_from = info->right_to = -1;
2603 M17N_OBJECT_UNREF (gstring->top);
2610 @brief Draw one or more textitems.
2612 The mdraw_text_items () function draws one or more M-texts on
2613 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2614 of the textitems to be drawn and $NITEMS is the number of
2615 textimtems in the array. */
2618 @brief textitem ¤òɽ¼¨¤¹¤ë.
2620 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2621 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2622 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2625 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2629 MTextItem, mdraw_text (). */
2632 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2633 MDrawTextItem *items, int nitems)
2635 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2637 while (nitems-- > 0)
2640 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2642 mdraw_text_with_control (frame, win, x, y,
2643 items->mt, 0, mtext_nchars (items->mt),
2645 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2646 items->control, NULL, NULL, NULL);
2649 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2655 @brief calculate a line breaking position.
2657 The function mdraw_default_line_break () calculates a line
2658 breaking position based on the line number $LINE and the
2659 coordinate $Y, when a line is too long to fit within the width
2660 limit. $POS is the position of the character next to the last
2661 one that fits within the limit. $FROM is the position of the
2662 first character of the line, and TO is the position of the last
2663 character displayed on the line if there were not width limit.
2664 LINE and Y are reset to 0 when a line is broken by a newline
2665 character, and incremented each time when a long line is broken
2666 because of the width limit.
2669 This function returns a character position to break the
2674 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2676 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2677 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2678 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2679 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2680 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2681 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2682 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2685 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2689 mdraw_default_line_break (MText *mt, int pos,
2690 int from, int to, int line, int y)
2692 int c = mtext_ref_char (mt, pos);
2695 if (c == ' ' || c == '\t')
2699 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2706 if (c == ' ' || c == '\t')
2709 c = mtext_ref_char (mt, pos);
2722 @brief Obtain per character dimension information.
2724 The mdraw_per_char_extents () function computes the text dimension
2725 of each character in M-text $MT. The faces given as text
2726 properties in $MT and the default face of frame $FRAME determine
2727 the fonts to draw the text. Each successive element in
2728 $ARRAY_RETURN is set to the drawn metrics of successive
2729 characters, which is relative to the origin of the drawing, and a
2730 rectangle for each character in $MT. The number of elements of
2731 $ARRAY_RETURN must be equal to or greater than the number of
2734 If pointer $OVERALL_RETURN is not @c NULL, this function also
2735 computes the extents of the overall text and stores the results in
2736 the members of the structure pointed to by $OVERALL_RETURN. */
2739 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2741 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2742 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2743 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2744 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2745 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2746 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2749 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2750 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2753 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2756 mdraw_per_char_extents (MFrame *frame, MText *mt,
2757 MDrawMetric *array_return,
2758 MDrawMetric *overall_return)
2760 int n = mtext_nchars (mt);
2762 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2763 n, &n, overall_return, NULL);
2767 @brief clear cached information.
2769 The mdraw_clear_cache () function clear cached information
2770 on M-text $MT that was attached by any of the drawing functions.
2771 When the behaviour of `format' or `line_break'
2772 member functions of MDrawControl is changed, the cache must be cleared.
2777 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2779 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2780 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2781 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2782 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2787 mdraw_clear_cache (MText *mt)
2789 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);