1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-texts on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layouting
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face ¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å
44 ¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É
45 ¤¨¤â face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆó¼¡
48 ¸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
53 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
54 /*** @addtogroup m17nInternal
61 #include <sys/types.h>
65 #include "m17n-misc.h"
69 #include "internal-gui.h"
74 #include <fribidi/fribidi.h>
75 #endif /* HAVE_FRIBIDI */
77 #define MAX(x, y) ((x) > (y) ? (x) : (y))
78 #define MIN(x, y) ((x) < (y) ? (x) : (y))
80 static MSymbol M_glyph_string;
83 static MSymbol Mlatin, Minherited;
84 /* Special categories */
85 static MSymbol McatCc, McatCf;
88 /* Glyph-string composer. */
90 static MSymbol MbidiR;
91 static MSymbol MbidiAL;
92 static MSymbol MbidiRLE;
93 static MSymbol MbidiRLO;
94 static MSymbol MbidiBN;
95 static MSymbol MbidiS;
98 visual_order (MGlyphString *gstring)
100 int len = gstring->used - 2;
102 int *idx = alloca (sizeof (int) * len);
104 int bidi_sensitive = gstring->control.orientation_reversed;
106 MGlyph *g = MGLYPH (1);
109 FriBidiCharType base = (gstring->control.orientation_reversed
110 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
111 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
113 FriBidiStrIndex *indices;
114 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
115 #else /* not HAVE_FRIBIDI */
116 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
119 #endif /* not HAVE_FRIBIDI */
121 while (g->type != GLYPH_ANCHOR)
123 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
125 if (bidi == MbidiR || bidi == MbidiAL
126 || bidi == MbidiRLE || bidi == MbidiRLO)
133 idx[size] = GLYPH_INDEX (g);
134 logical[size++] = g++->c;
135 while (g->type != GLYPH_ANCHOR && g->combining_code)
139 if (! bidi_sensitive)
142 glyphs = alloca (sizeof (MGlyph) * gstring->used);
143 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
145 visual = alloca (sizeof (FriBidiChar) * size);
146 indices = alloca (sizeof (FriBidiStrIndex) * size);
148 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
149 #else /* not HAVE_FRIBIDI */
150 indices = alloca (sizeof (int) * size);
151 for (i = 0; i < size; i++)
157 for (j = i + 1; j < size && levels[j]; j++);
158 for (k = j--; i < k; i++, j--)
165 #endif /* not HAVE_FRIBIDI */
167 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
168 starts from gstring->glyphs[IDX[N]].
170 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
171 originally at LOGICAL[INDICES[N]]. */
173 for (i = 0, gidx = 1; i < size; i++)
178 glyphs[k].bidi_level = levels[j];
180 if (visual[i] != logical[j])
183 glyphs[k].c = visual[i];
184 if (glyphs[k].rface->rfont)
185 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
188 #endif /* not HAVE_FRIBIDI */
189 *(MGLYPH (gidx)) = glyphs[k];
191 k < gstring->used - 1 && glyphs[k].combining_code;
194 glyphs[k].bidi_level = levels[j];
195 *(MGLYPH (gidx)) = glyphs[k];
201 reorder_combining_chars (MGlyphString *gstring, int from, int to)
203 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
209 for (g = gbeg; g != gend; g++)
210 if (COMBINING_CODE_CLASS (g->combining_code) > 0
211 && (COMBINING_CODE_CLASS (g[-1].combining_code)
212 > COMBINING_CODE_CLASS (g->combining_code)))
223 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
224 displaying them on FRAME.
226 This function fills members <type>, <rface>, <c>, <pos>, <to>,
227 <code> of glyphs. The other members are filled by
228 layout_glyph_string. */
231 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
232 MGlyphString *gstring)
234 MRealizedFace *default_rface = frame->rface;
235 int stop, face_change, language_change, charset_change;
238 MSymbol language = Mnil, script = Mnil, charset = Mnil;
239 MRealizedFace *rface = default_rface;
240 int size = gstring->control.fixed_width;
244 MLIST_RESET (gstring);
245 gstring->from = from;
247 /* At first generate glyphs while using the member <enabled> as a
248 flag for rface re-checking. */
251 /** Put anchor glyphs at the head and tail. */
252 g_tmp.type = GLYPH_ANCHOR;
253 g_tmp.pos = g_tmp.to = from;
255 APPEND_GLYPH (gstring, g_tmp);
257 stop = face_change = charset_change = language_change = pos = from;
264 if (pos < mtext_nchars (mt))
265 c = mtext_ref_char (mt, pos);
270 /* Short cut for the obvious case. */
271 g_tmp.category = Mnil;
272 if (c == ' ' || c == '\n' || c == '\t')
273 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
275 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
279 g_tmp.category = mchar_get_prop (c, Mcategory);
280 g_tmp.type = GLYPH_CHAR;
281 this_script = (MSymbol) mchar_get_prop (c, Mscript);
282 if (this_script == Minherited || this_script == Mnil)
283 this_script = script;
284 if (this_script == Mnil)
285 /* Search forward for a character that explicitly
286 specifies a script. */
287 for (i = pos + 1; i < to; i++)
289 int c1 = mtext_ref_char (mt, i);
290 MSymbol sym = ((c1 > 0x20 && c1 < 0x100) ? Mlatin
291 : mchar_get_prop (c1, Mscript));
293 if (sym != Minherited && sym != Mnil)
301 if (pos == stop || script != this_script
302 || MGLYPH (last)->type != g_tmp.type)
305 if (g->type == GLYPH_CHAR)
306 while (g < gstring->glyphs + gstring->used)
307 g = mface__for_chars (script, language, charset,
308 g, gstring->glyphs + gstring->used, size);
311 last = gstring->used;
312 script = this_script;
315 if (pos < mtext_nchars (mt) && pos == language_change)
317 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
318 mtext_prop_range (mt, Mlanguage, pos, NULL,
319 &language_change, 0);
321 if (pos < mtext_nchars (mt) && pos == charset_change)
323 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
324 mtext_prop_range (mt, Mcharset, pos, NULL,
327 if (pos < mtext_nchars (mt) && pos == face_change)
330 int num = mtext_get_prop_values (mt, pos, Mface,
331 (void **) faces, 64);
333 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
335 ? mface__realize (frame, faces, num,
336 language, charset, size)
340 if (stop > language_change)
341 stop = language_change;
342 if (stop > charset_change)
343 stop = charset_change;
344 if (face_change < stop)
354 if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
357 APPEND_GLYPH (gstring, g_tmp);
363 APPEND_GLYPH (gstring, g_tmp);
365 && gstring->control.two_dimensional)
369 /* Append an anchor glyph. */
370 g_tmp.type = GLYPH_ANCHOR;
372 g_tmp.code = MCHAR_INVALID_CODE;
373 g_tmp.pos = g_tmp.to = pos;
375 APPEND_GLYPH (gstring, g_tmp);
379 /* Next, run FLT if necessary. */
380 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
384 if (this->type == GLYPH_CHAR && this->rface->rfont)
388 if (this->rface->rfont->layouter != Mnil)
393 for (prev = MGLYPH (start - 1);
394 (prev->type == GLYPH_CHAR
395 && prev->category == McatCf
396 && (code = mfont__encode_char (this->rface->rfont, prev->c)
397 != MCHAR_INVALID_CODE));
402 (g->type == GLYPH_CHAR
403 && (g->rface->rfont == this->rface->rfont
404 || (g->category == McatCf
405 && ((code = mfont__encode_char (this->rface->rfont,
407 != MCHAR_INVALID_CODE))));
409 if (g->rface->rfont != this->rface->rfont)
411 g->rface->rfont = this->rface->rfont;
414 i = mfont__flt_run (gstring, start, i, this->rface);
418 while (this->type == GLYPH_CHAR
421 && MSYMBOL_NAME (this->category)[0] == 'M'
422 && this->rface->rfont
423 && this->rface->rfont->layouter == Mnil)
425 int class = (int) mchar_get_prop (this->c,
428 = MAKE_COMBINING_CODE_BY_CLASS (class);
432 reorder_combining_chars (gstring, start, i);
440 /* At last, reorder glyphs visually if necessary. */
441 if (gstring->control.enable_bidi)
442 visual_order (gstring);
447 combining_code_from_class (int class)
452 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
453 else if (class == 200) /* below left attached */
454 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
455 else if (class == 202) /* below attached*/
456 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
457 else if (class == 204) /* below right attached */
458 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
459 else if (class == 208) /* left attached */
460 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
461 else if (class == 210) /* right attached */
462 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
463 else if (class == 212) /* above left attached */
464 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
465 else if (class == 214) /* above attached */
466 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
467 else if (class == 216) /* above right attached */
468 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
469 else if (class == 218) /* below left */
470 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
471 else if (class == 220) /* below */
472 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
473 else if (class == 222) /* below right */
474 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
475 else if (class == 224) /* left */
476 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
477 else if (class == 226) /* right */
478 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
479 else if (class == 228) /* above left */
480 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
481 else if (class == 230) /* above */
482 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
483 else if (class == 232) /* above right */
484 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
485 else if (class == 233) /* double below */
486 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
487 else if (class == 234) /* double above */
488 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
489 else if (class == 240) /* iota subscript */
490 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
492 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
498 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
500 int g_physical_ascent, g_physical_descent;
501 int g_width, g_lbearing, g_rbearing;
502 MGlyph *g = MGLYPH (from);
503 MGlyph *last_g = MGLYPH (to);
505 g_physical_ascent = gstring->physical_ascent;
506 g_physical_descent = gstring->physical_descent;
507 g_width = g_lbearing = g_rbearing = 0;
509 mfont__get_metric (gstring, from, to);
514 MRealizedFont *rfont = base->rface->rfont;
515 int size = rfont->font.property[MFONT_SIZE];
516 int width, lbearing, rbearing;
518 if (g == last_g || ! g->combining_code)
521 if (base->left_padding && base->lbearing < 0)
523 base->xoff = - base->lbearing;
524 base->width += base->xoff;
525 base->rbearing += base->xoff;
528 if (base->right_padding && base->rbearing > base->width)
530 base->width = base->rbearing;
532 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
533 rbearing = base->rbearing;
537 /* With combining glyphs. */
538 int left = -base->width;
540 int top = - base->ascent;
541 int bottom = base->descent;
542 int height = bottom - top;
543 int begin = base->pos;
548 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
549 rbearing = base->rbearing;
551 while (g != last_g && g->combining_code)
553 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
555 combining_code = g->combining_code;
556 if (COMBINING_BY_CLASS_P (combining_code))
557 g->combining_code = combining_code
558 = combining_code_from_class (COMBINING_CODE_CLASS
561 rfont = g->rface->rfont;
562 size = rfont->font.property[MFONT_SIZE];
563 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
565 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
567 base_x = COMBINING_CODE_BASE_X (combining_code);
568 base_y = COMBINING_CODE_BASE_Y (combining_code);
569 add_x = COMBINING_CODE_ADD_X (combining_code);
570 add_y = COMBINING_CODE_ADD_Y (combining_code);
574 else if (end < g->to)
577 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
580 if (g->xoff + g->width > right)
581 right = g->xoff + g->width;
582 width = right - left;
583 if (g->xoff + g->lbearing < left + lbearing)
584 lbearing = g->xoff + g->lbearing - left;
585 if (g->xoff + g->rbearing > left + rbearing)
586 rbearing = g->xoff + g->rbearing - left;
589 g->yoff = top + height * base_y / 2;
593 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
595 if (g->yoff - g->ascent < top)
596 top = g->yoff - g->ascent;
597 if (g->yoff + g->descent > bottom)
598 bottom = g->yoff + g->descent;
599 height = bottom - top;
605 base->ascent = - top;
606 base->descent = bottom;
607 base->lbearing = lbearing;
608 base->rbearing = rbearing;
609 if (left < - base->width)
611 base->xoff = - base->width - left;
612 base->width += base->xoff;
613 base->rbearing += base->xoff;
614 base->lbearing += base->xoff;
618 base->width += right;
619 base->rbearing += right;
620 base->right_padding = 1;
621 for (i = 1; base + i != g; i++)
622 base[i].xoff -= right;
625 for (i = 0; base + i != g; i++)
632 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
633 g_physical_descent = MAX (g_physical_descent, base->descent);
634 g_lbearing = MIN (g_lbearing, g_width + lbearing);
635 g_rbearing = MAX (g_rbearing, g_width + rbearing);
636 g_width += base->width;
639 gstring->physical_ascent = g_physical_ascent;
640 gstring->physical_descent = g_physical_descent;
641 gstring->sub_width = g_width;
642 gstring->sub_lbearing = g_lbearing;
643 gstring->sub_rbearing = g_rbearing;
647 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
648 by this function directly. Character glyphs are handled by
649 layouter functions registered in font drivers.
651 This function fill-in all the remaining members of glyphs. */
654 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
656 /* Default width of TAB. */
657 int tab_width = frame->space_width * (gstring->control.tab_width
658 ? gstring->control.tab_width : 8);
662 MDrawControl *control = &(gstring->control);
665 int box_line_height = 0;
666 int ignore_formatting_char = control->ignore_formatting_char;
668 gstring->ascent = gstring->descent = 0;
669 gstring->physical_ascent = gstring->physical_descent = 0;
670 gstring->width = gstring->lbearing = gstring->rbearing = 0;
674 while (g->type != GLYPH_ANCHOR)
676 if (box != g->rface->box)
678 int gidx = GLYPH_INDEX (g);
682 /* Insert the right side of the box. That glyph belongs
683 to the previous grapheme cluster. */
684 MGlyph box_glyph = g[-1];
686 box_glyph.type = GLYPH_BOX;
688 = (control->fixed_width
690 : box->inner_hmargin + box->width + box->outer_hmargin);
691 box_glyph.lbearing = 0;
692 box_glyph.rbearing = box_glyph.width;
694 box_glyph.right_padding = 1;
695 gstring->width += box_glyph.width;
696 gstring->rbearing += box_glyph.width;
697 INSERT_GLYPH (gstring, gidx, box_glyph);
704 /* Insert the left side of the box. That glyph belongs
705 to the following grapheme cluster. */
706 MGlyph box_glyph = *g;
707 int box_height = (box->width
708 + box->inner_vmargin + box->outer_vmargin);
710 if (box_line_height < box_height)
711 box_line_height = box_height;
712 box_glyph.type = GLYPH_BOX;
714 = (control->fixed_width
716 : box->inner_hmargin + box->width + box->outer_hmargin);
717 box_glyph.lbearing = 0;
718 box_glyph.rbearing = box_glyph.width;
720 box_glyph.left_padding = 1;
721 gstring->width += box_glyph.width;
722 gstring->rbearing += box_glyph.width;
723 INSERT_GLYPH (gstring, gidx, box_glyph);
729 if (g->category == McatCf && ignore_formatting_char)
730 g->type = GLYPH_SPACE;
732 if (g->type == GLYPH_CHAR)
734 MRealizedFace *rface = g->rface;
735 MRealizedFont *rfont = rface->rfont;
737 int from = GLYPH_INDEX (g);
739 for (g++; g->type == GLYPH_CHAR; g++)
740 if (! rfont != ! g->rface->rfont
741 || box != g->rface->box
742 || ((fromg->code == MCHAR_INVALID_CODE)
743 != (g->code == MCHAR_INVALID_CODE))
744 || (g->category == McatCf && ignore_formatting_char))
746 if (rfont && fromg->code != MCHAR_INVALID_CODE)
749 int to = GLYPH_INDEX (g);
751 layout_glyphs (frame, gstring, from, to);
752 extra_width = - gstring->sub_lbearing;
754 && (GLYPH_INDEX (g) > 1
755 || control->align_head))
759 pad.type = GLYPH_PAD;
762 pad.width = pad.rbearing = extra_width;
763 INSERT_GLYPH (gstring, from, pad);
765 gstring->sub_lbearing = 0;
766 gstring->sub_width += extra_width;
767 gstring->sub_rbearing += extra_width;
769 g = MGLYPH (from - 1);
770 if (g->type == GLYPH_SPACE)
772 /* The pad just inserted is absorbed (maybe
773 partially) by the previous space while
774 keeping at least some space width. For the
775 moment, we use the arbitrary width 2-pixel.
776 Perhaps, it should be decided by the current
777 face, or a default value of the current
778 frame, which is, however, not yet
780 if (extra_width + 2 < g->width)
782 g->width -= extra_width;
786 extra_width -= g->width - 2;
789 gstring->width -= extra_width;
790 gstring->rbearing -= extra_width;
794 extra_width = gstring->sub_rbearing - gstring->sub_width;
798 if (g->type == GLYPH_SPACE && box == g->rface->box)
802 pad.type = GLYPH_PAD;
805 pad.width = pad.rbearing = extra_width;
806 INSERT_GLYPH (gstring, to, pad);
810 g[-1].width += extra_width;
811 gstring->sub_width += extra_width;
814 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
815 gstring->lbearing = gstring->width + gstring->sub_lbearing;
816 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
817 gstring->rbearing = gstring->width + gstring->sub_rbearing;
818 gstring->width += gstring->sub_width;
819 if (gstring->ascent < rface->ascent)
820 gstring->ascent = rface->ascent;
821 if (gstring->descent < rface->descent)
822 gstring->descent = rface->descent;
827 for (; fromg < g; fromg++)
829 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
830 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
831 fromg->width = fromg->rbearing = 1;
833 fromg->width = fromg->rbearing = rface->space_width;
834 fromg->xoff = fromg->lbearing = 0;
835 fromg->ascent = fromg->descent = 0;
836 gstring->width += fromg->width;
837 gstring->rbearing += fromg->width;
839 if (gstring->ascent < frame->rface->ascent)
840 gstring->ascent = frame->rface->ascent;
841 if (gstring->descent < frame->descent)
842 gstring->descent = frame->rface->descent;
845 else if (g->type == GLYPH_SPACE)
848 g->width = g->rface->space_width;
849 else if (g->c == '\n')
851 g->width = control->cursor_width;
854 if (control->cursor_bidi)
856 else if (g->width < 0)
857 g->width = g->rface->space_width;
860 else if (g->c == '\t')
862 g->width = tab_width - ((gstring->indent + gstring->width)
868 if (g[-1].type == GLYPH_PAD)
870 /* This space glyph absorbs (maybe partially) the
871 previous padding glyph. */
872 g->width -= g[-1].width;
874 /* But, keep at least some space width. For the
875 moment, we use the arbitrary width 2-pixel. */
878 g->rbearing = g->width;
879 gstring->width += g->width;
880 gstring->rbearing += g->width;
883 if (gstring->ascent < g->rface->ascent)
884 gstring->ascent = g->rface->ascent;
885 if (gstring->descent < g->rface->descent)
886 gstring->descent = g->rface->descent;
892 gstring->width += g->width;
893 gstring->rbearing += g->width;
900 /* Insert the right side of the box. */
901 int gidx = GLYPH_INDEX (g);
902 MGlyph box_glyph = g[-1];
904 box_glyph.type = GLYPH_BOX;
906 = (control->fixed_width
908 : box->inner_hmargin + box->width + box->outer_hmargin);
909 box_glyph.lbearing = 0;
910 box_glyph.rbearing = box_glyph.width;
912 box_glyph.right_padding = 1;
913 gstring->width += box_glyph.width;
914 gstring->rbearing += box_glyph.width;
915 INSERT_GLYPH (gstring, gidx, box_glyph);
918 gstring->text_ascent = gstring->ascent;
919 gstring->text_descent = gstring->descent;
920 if (gstring->text_ascent < gstring->physical_ascent)
921 gstring->text_ascent = gstring->physical_ascent;
922 if (gstring->text_descent < gstring->physical_descent)
923 gstring->text_descent = gstring->physical_descent;
924 gstring->line_ascent = gstring->text_ascent;
925 gstring->line_descent = gstring->text_descent;
926 if (box_line_height > 0)
928 gstring->line_ascent += box_line_height;
929 gstring->physical_ascent = gstring->line_ascent;
930 gstring->line_descent += box_line_height;
931 gstring->physical_descent = gstring->line_descent;
934 if (gstring->line_ascent < control->min_line_ascent)
935 gstring->line_ascent = control->min_line_ascent;
936 else if (control->max_line_ascent
937 && control->max_line_ascent > control->min_line_ascent
938 && gstring->line_ascent > control->max_line_ascent)
939 gstring->line_ascent = control->max_line_ascent;
941 if (gstring->line_descent < control->min_line_descent)
942 gstring->line_descent = control->min_line_descent;
943 else if (control->max_line_descent
944 && control->max_line_descent > control->min_line_descent
945 && gstring->line_descent > control->max_line_descent)
946 gstring->line_descent = control->max_line_descent;
947 gstring->height = gstring->line_ascent + gstring->line_descent;
949 if (control->orientation_reversed
952 /* We must adjust TAB width for RTL orientation. */
953 width = gstring->indent;
955 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
957 if (g->type == GLYPH_CHAR && g->c == '\t')
959 int this_width = tab_width - (width % tab_width);
961 if (g[1].type == GLYPH_PAD)
962 this_width -= g[1].width;
963 if (g[-1].type == GLYPH_PAD)
964 this_width -= g[-1].width;
967 gstring->width += this_width - g->width;
968 gstring->rbearing += this_width - g->width;
969 g->width = this_width;
980 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
981 MGlyphString *gstring, int from, int to,
982 int *from_idx, int *to_idx, int *to_x)
984 MGlyph *g = MGLYPH (1);
985 MDrawRegion region = (MDrawRegion) NULL;
986 MDrawControl *control = &gstring->control;
989 int cursor_bidi = control->cursor_bidi;
991 if (control->with_cursor && control->cursor_width)
993 if (gstring->from <= control->cursor_pos
994 && gstring->to > control->cursor_pos)
995 cursor_pos = control->cursor_pos;
997 && gstring->from <= control->cursor_pos - 1
998 && gstring->to > control->cursor_pos - 1)
999 prev_pos = control->cursor_pos - 1;
1002 *from_idx = *to_idx = 0;
1003 while (g->type != GLYPH_ANCHOR)
1005 if (g->pos >= from && g->pos < to)
1007 MGlyph *fromg = g, *cursor = NULL;
1008 MRealizedFace *rface = g->rface;
1010 int cursor_width = 0;
1014 *from_idx = GLYPH_INDEX (g);
1015 while (g->pos >= from && g->pos < to
1016 && g->rface == rface)
1019 if (g->type != GLYPH_BOX
1020 && g->pos <= cursor_pos && g->to > cursor_pos)
1023 cursor = g, cursor_x = x + width;
1024 cursor_width += g->width;
1026 width += g++->width;
1029 && (control->as_image
1030 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1032 int this_x = x, this_width = width;
1034 if (fromg->type == GLYPH_BOX)
1035 this_x += fromg->width, this_width -= fromg->width;
1036 if (g[-1].type == GLYPH_BOX)
1037 this_width -= g[-1].width;
1038 (frame->driver->fill_space)
1039 (frame, win, rface, 0,
1040 this_x, y - gstring->text_ascent, this_width,
1041 gstring->text_ascent + gstring->text_descent,
1042 control->clip_region);
1049 rect.y = y - gstring->text_ascent;
1050 rect.height = gstring->text_ascent + gstring->text_descent;
1053 rect.width = ((control->cursor_width > 0
1054 && control->cursor_width < cursor_width)
1055 ? control->cursor_width : cursor_width);
1059 if (cursor->bidi_level % 2)
1060 rect.x += cursor_width - 1;
1063 (*frame->driver->fill_space)
1064 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1065 control->clip_region);
1067 region = (*frame->driver->region_from_rect) (&rect);
1069 (*frame->driver->region_add_rect) (region, &rect);
1072 if (cursor->bidi_level % 2)
1075 rect.width = cursor_width < 4 ? cursor_width : 4;
1076 (*frame->driver->fill_space)
1077 (frame, win, rface, 1,
1078 rect.x, rect.y, rect.width, rect.height,
1079 control->clip_region);
1080 (*frame->driver->region_add_rect) (region, &rect);
1092 if (fromg->type != GLYPH_BOX
1093 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1096 cursor = fromg, cursor_x = x + temp_width;
1097 cursor_width += fromg->width;
1099 temp_width += fromg++->width;
1106 if (! (cursor->bidi_level % 2))
1107 rect.x += cursor_width - 1;
1108 rect.y = y - gstring->text_ascent;
1109 rect.height = gstring->text_ascent + gstring->text_descent;
1111 (*frame->driver->fill_space)
1112 (frame, win, rface, 1,
1113 rect.x, rect.y, rect.width, rect.height,
1114 control->clip_region);
1116 region = (*frame->driver->region_from_rect) (&rect);
1118 (*frame->driver->region_add_rect) (region, &rect);
1119 rect.y += rect.height - 2;
1121 rect.width = cursor_width < 4 ? cursor_width : 4;
1122 if (! (cursor->bidi_level % 2))
1123 rect.x -= rect.width - 1;
1124 (*frame->driver->fill_space) (frame, win, rface, 1,
1125 rect.x, rect.y, rect.width, rect.height,
1126 control->clip_region);
1127 (*frame->driver->region_add_rect) (region, &rect);
1131 *to_idx = GLYPH_INDEX (g);
1141 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1142 MGlyphString *gstring, int from_idx, int to_idx,
1143 int reverse, MDrawRegion region)
1145 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1151 (*frame->driver->region_to_rect) (region, &rect);
1154 while (g != gend && x + g->rbearing <= rect.x)
1157 width -= g++->width;
1158 while (! g->enabled && g != gend)
1162 rect.x += rect.width;
1163 if (rect.x < x + width)
1166 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1168 width -= (--gend)->width;
1169 while (! gend->enabled && g != gend)
1173 while (gend[-1].to == gend->to) gend++;
1181 MRealizedFace *rface = g->rface;
1182 int width = g->width;
1183 MGlyph *from_g = g++;
1185 /* Handle the glyphs of the same type/face at once. */
1187 && g->type == from_g->type
1188 && g->rface == rface
1189 && (g->code < 0) == (from_g->code < 0)
1191 width += g++->width;
1193 if (from_g->type == GLYPH_CHAR)
1195 if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
1196 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1199 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1202 else if (from_g->type == GLYPH_BOX)
1204 /* Draw the left or right side of a box. If
1205 from_g->lbearing is nonzero, this is the left side,
1206 else this is the right side. */
1207 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1210 if (from_g->type != GLYPH_BOX)
1213 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1214 x, y, width, region);
1217 /* Draw the top and bottom side of a box. */
1218 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1219 x, y, width, region);
1230 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1231 int *from_x, int *to_x)
1234 int left_idx = *left, right_idx = *right;
1235 int left_x, right_x, x;
1237 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1240 if (x + g->rbearing > 0)
1242 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1244 left_idx = GLYPH_INDEX (g);
1249 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1252 if (x - g->width + g->lbearing < 0)
1254 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1256 right_idx = GLYPH_INDEX (g) + 1;
1261 if (*left == left_idx && *right == right_idx)
1264 if (*left != left_idx)
1266 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1271 if (*right != right_idx)
1273 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1283 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1288 if (from <= gstring->from && to >= gstring->to)
1291 *rbearing = gstring->rbearing;
1292 return gstring->width;
1297 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1298 if (g->pos >= from && g->pos < to)
1300 if (rbearing && width + g->rbearing > *rbearing)
1301 *rbearing = width + g->rbearing;
1309 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1310 MGlyphString *gstring, int from, int to)
1312 MDrawControl *control = &gstring->control;
1314 MDrawRegion clip_region, cursor_region;
1315 int from_idx, to_idx;
1318 if (control->orientation_reversed)
1319 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1321 x += gstring->indent;
1323 /* At first, draw all glyphs without cursor. */
1324 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1325 &from_idx, &to_idx, &to_x);
1327 if (control->partial_update)
1330 rect.width = to_x - x;
1331 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1333 rect.y = y - gstring->line_ascent;
1334 rect.height = gstring->height;
1335 clip_region = (*frame->driver->region_from_rect) (&rect);
1336 if (control->clip_region)
1337 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1340 clip_region = control->clip_region;
1343 clip_region = control->clip_region;
1345 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1350 (*frame->driver->intersect_region) (cursor_region, clip_region);
1351 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1354 if (clip_region != control->clip_region)
1355 (*frame->driver->free_region) (clip_region);
1357 (*frame->driver->free_region) (cursor_region);
1361 static int gstring_num;
1364 free_gstring (void *object)
1366 MGlyphString *gstring = (MGlyphString *) object;
1369 free_gstring (gstring->next);
1370 if (gstring->size > 0)
1371 free (gstring->glyphs);
1377 static MGlyphString scratch_gstring;
1379 static MGlyphString *
1380 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1383 MGlyphString *gstring;
1385 if (pos == mt->nchars)
1387 gstring = &scratch_gstring;
1391 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1392 MLIST_INIT1 (gstring, glyphs, 128);
1396 gstring->frame = frame;
1397 gstring->tick = frame->tick;
1398 gstring->top = gstring;
1400 gstring->control = *control;
1401 gstring->indent = gstring->width_limit = 0;
1402 if (control->format)
1403 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1405 gstring->width_limit = control->max_line_width;
1406 gstring->anti_alias = control->anti_alias;
1410 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1413 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1421 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1422 a width of glyphs for the character at I of GSTRING->mt. If I is
1423 not a beginning of a grapheme cluster, the corresponding element
1425 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1426 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1427 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1428 pos_width[g->pos - gstring->from] += g->width;
1429 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1431 if (pos_width[i] > 0)
1433 if (width + pos_width[i] > gstring->width_limit)
1436 width += pos_width[i];
1439 pos = gstring->from + i;
1440 if (gstring->control.line_break)
1442 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1443 gstring->from, gstring->to, 0, 0);
1444 if (pos <= gstring->from || pos >= gstring->to)
1447 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1448 layout_glyph_string (frame, gstring);
1452 /* Return a gstring that covers a character at POS. */
1454 static MGlyphString *
1455 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1457 MGlyphString *gstring = NULL;
1459 if (pos < mtext_nchars (mt))
1461 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1464 && ((prop->start != 0
1465 && mtext_ref_char (mt, prop->start - 1) != '\n')
1466 || (prop->end < mtext_nchars (mt)
1467 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1469 mtext_detach_property (prop);
1474 gstring = prop->val;
1475 if (gstring->frame != frame
1476 || gstring->tick != frame->tick
1477 || memcmp (control, &gstring->control,
1478 (char *) (&control->with_cursor)
1479 - (char *) (control)))
1481 mtext_detach_property (prop);
1486 else if (! control->cursor_width)
1494 offset = mtext_character (mt, pos, 0, '\n');
1499 offset -= gstring->from;
1501 for (gst = gstring; gst; gst = gst->next)
1505 gst->from += offset;
1507 for (i = 0; i < gst->used; i++)
1509 gst->glyphs[i].pos += offset;
1510 gst->glyphs[i].to += offset;
1513 M17N_OBJECT_REF (gstring);
1518 int line = 0, y = 0;
1520 if (control->two_dimensional)
1522 beg = mtext_character (mt, pos, 0, '\n');
1527 end = mtext_nchars (mt) + (control->cursor_width != 0);
1534 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1535 compose_glyph_string (frame, mt, beg, end, gstring);
1536 layout_glyph_string (frame, gstring);
1538 if (control->two_dimensional
1539 && gstring->width_limit
1540 && gstring->width > gstring->width_limit)
1542 MGlyphString *gst = gstring;
1544 truncate_gstring (frame, mt, gst);
1545 while (gst->to < end)
1547 line++, y += gst->height;
1548 gst->next = alloc_gstring (frame, mt, gst->from, control,
1550 gst->next->top = gstring;
1551 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1553 layout_glyph_string (frame, gst);
1554 if (gst->width <= gst->width_limit)
1556 truncate_gstring (frame, mt, gst);
1560 if (! control->disable_caching && pos < mtext_nchars (mt))
1562 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1563 MTEXTPROP_VOLATILE_STRONG);
1565 if (end > mtext_nchars (mt))
1566 end = mtext_nchars (mt);
1567 mtext_attach_property (mt, beg, end, prop);
1568 M17N_OBJECT_UNREF (prop);
1572 while (gstring->to <= pos)
1574 if (! gstring->next)
1576 gstring = gstring->next;
1578 gstring->control = *control;
1584 static MDrawControl control_noop;
1586 #define ASSURE_CONTROL(control) \
1588 control = &control_noop; \
1593 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1594 MText *mt, int from, int to,
1595 MDrawControl *control)
1597 MGlyphString *gstring;
1599 M_CHECK_POS_X (mt, from, -1);
1600 ASSURE_CONTROL (control);
1601 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1602 to = mtext_nchars (mt) + (control->cursor_width != 0);
1606 gstring = get_gstring (frame, mt, from, to, control);
1608 MERROR (MERROR_DRAW, -1);
1609 render_glyph_string (frame, win, x, y, gstring, from, to);
1613 y += gstring->line_descent;
1614 M17N_OBJECT_UNREF (gstring->top);
1615 gstring = get_gstring (frame, mt, from, to, control);
1616 y += gstring->line_ascent;
1617 render_glyph_string (frame, win, x, y, gstring, from, to);
1620 M17N_OBJECT_UNREF (gstring->top);
1627 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1633 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1634 if (g->pos <= pos && g->to > pos)
1639 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1640 if (g->pos <= pos && g->to > pos)
1647 /* for debugging... */
1651 dump_combining_code (int code)
1653 char *vallign = "tcbB";
1654 char *hallign = "lcr";
1660 if (COMBINING_BY_CLASS_P (code))
1661 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1662 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1663 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1664 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1665 off_x = COMBINING_CODE_OFF_X (code) - 128;
1667 sprintf (work + 2, "+%d", off_y);
1669 sprintf (work + 2, "%d", off_y);
1670 else if (off_x == 0)
1671 sprintf (work + 2, ".");
1672 p = work + strlen (work);
1674 sprintf (p, ">%d", off_x);
1676 sprintf (p, "<%d", -off_x);
1678 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1679 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1685 dump_gstring (MGlyphString *gstring, int indent)
1687 char *prefix = (char *) alloca (indent + 1);
1688 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1690 memset (prefix, 32, indent);
1693 fprintf (stderr, "(glyph-string");
1695 for (g = MGLYPH (0); g < last_g; g++)
1697 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1699 g - gstring->glyphs,
1700 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1701 : g->type == GLYPH_ANCHOR ? "ANC"
1702 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1703 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1704 dump_combining_code (g->combining_code),
1705 g->width, g->bidi_level);
1706 fprintf (stderr, ")");
1710 /* m17n-X internal APIs */
1715 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1717 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1718 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1720 Mlatin = msymbol ("latin");
1721 Minherited = msymbol ("inherited");
1723 McatCc = msymbol ("Cc");
1724 McatCf = msymbol ("Cf");
1726 MbidiR = msymbol ("R");
1727 MbidiAL = msymbol ("AL");
1728 MbidiRLE = msymbol ("RLE");
1729 MbidiRLO = msymbol ("RLO");
1730 MbidiBN = msymbol ("BN");
1731 MbidiS = msymbol ("S");
1733 fribidi_set_mirroring (TRUE);
1742 MLIST_FREE1 (&scratch_gstring, glyphs);
1746 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1750 /*** @addtogroup m17nDraw */
1755 @brief Draw an M-text on a window.
1757 The mdraw_text () function draws the text between $FROM and $TO of
1758 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1760 The appearance of the text (size, style, color, etc) is specified
1761 by the value of the text property whose key is @c Mface. If the
1762 M-text or a part of the M-text does not have such a text property,
1763 the default face of $FRAME is used.
1765 The font used to draw a character in the M-text is selected from
1766 the value of the fontset property of a face by the following
1771 <li> Search the text properties given to the character for the one
1772 whose key is @c Mcharset; its value should be either a symbol
1773 specifying a charset or #Mnil. If the value is #Mnil,
1774 proceed to the next step.
1776 Otherwise, search the mapping table of the fontset for the
1777 charset. If no entry is found proceed to the next step.
1779 If an entry is found, use one of the fonts in the entry that
1780 has a glyph for the character and that matches best with the
1781 face properties. If no such font exists, proceed to the next
1784 <li> Get the character property "script" of the character. If it is
1785 inherited, get the script property from the previous
1786 characters. If there is no previous character, or none of
1787 them has the script property other than inherited, proceed to
1790 Search the text properties given to the character for the one
1791 whose key is @c Mlanguage; its value should be either a
1792 symbol specifying a language or @c Mnil.
1794 Search the mapping table of the fontset for the combination
1795 of the script and language. If no entry is found, proceed to
1798 If an entry is found, use one of the fonts in the entry that
1799 has a glyph for the character and that matches best with the
1800 face properties. If no such font exists, proceed to the next
1803 <li> Search the fall-back table of the fontset for a font that has
1804 a glyph of the character. If such a font is found, use that
1809 If no font is found by the algorithm above, this function draws an
1810 empty box for the character.
1812 This function draws only the glyph foreground. To specify the
1813 background color, use mdraw_image_text () or
1814 mdraw_text_with_control ().
1816 This function is the counterpart of <tt>XDrawString ()</tt>,
1817 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1818 in the X Window System.
1821 If the operation was successful, mdraw_text () returns 0. If an
1822 error is detected, it returns -1 and assigns an error code to the
1823 external variable #merror_code. */
1825 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1827 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1828 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1831 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1832 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1833 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1834 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1836 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£
1837 ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1841 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1842 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1843 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê
1844 ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã
1845 ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë
1848 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ
1849 »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ
1850 ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê
1853 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ
1854 ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò
1855 Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê
1856 ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1858 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1859 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î
1862 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È
1863 ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1866 ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½
1867 ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç
1868 Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã
1871 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼
1872 ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1876 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1877 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1879 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢
1880 ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦
1883 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1884 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1887 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1888 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1890 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1897 mdraw_image_text () */
1900 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1901 MText *mt, int from, int to)
1903 MDrawControl control;
1905 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1906 memset (&control, 0, sizeof control);
1907 control.as_image = 0;
1908 return draw_text (frame, win, x, y, mt, from, to, &control);
1915 @brief Draw an M-text on a window as an image.
1917 The mdraw_image_text () function draws the text between $FROM and
1918 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1919 coordinate ($X, $Y).
1921 The way to draw a text is the same as in mdraw_text () except that
1922 this function also draws the background with the color specified
1925 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1926 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1927 functions in the X Window System.
1930 If the operation was successful, mdraw_image_text () returns 0.
1931 If an error is detected, it returns -1 and assigns an error code
1932 to the external variable #merror_code. */
1935 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1937 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1938 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1941 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1942 ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1944 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1945 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1949 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1950 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1953 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1963 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1964 MText *mt, int from, int to)
1966 MDrawControl control;
1968 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1969 memset (&control, 0, sizeof control);
1970 control.as_image = 1;
1971 return draw_text (frame, win, x, y, mt, from, to, &control);
1977 @brief Draw an M-text on a window with fine control.
1979 The mdraw_text_with_control () function draws the text between
1980 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1981 coordinate ($X, $Y).
1983 The way to draw a text is the same as in mdraw_text () except that
1984 this function also follows what specified in the drawing control
1987 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1988 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1989 breaks lines and the following characters are drawn in the next
1990 line. See the documentation of the structure @ MDrawControl for
1994 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¡Ë.
1996 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
1997 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2000 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï
2001 ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2003 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô
2004 ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯
2005 ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³
2009 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2010 MText *mt, int from, int to, MDrawControl *control)
2012 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2013 return draw_text (frame, win, x, y, mt, from, to, control);
2019 @brief Compute text pixel width.
2021 The mdraw_text_extents () function computes the width of text
2022 between $FROM and $TO of M-text $MT when it is drawn on a window
2023 of frame $FRAME using the mdraw_text_with_control () function with
2024 the drawing control object $CONTROL.
2026 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2027 the bounding box of character ink of the M-text, and stores the
2028 results in the members of the structure pointed to by
2029 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2030 surrounding box, the box is included in the bounding box.
2032 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2033 computes the bounding box that provides mininum spacing to other
2034 graphical features (such as surrounding box) for the M-text, and
2035 stores the results in the members of the structure pointed to by
2036 $OVERALL_LOGICAL_RETURN.
2038 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2039 computes the bounding box that provides mininum spacing to the
2040 other M-text drawn, and stores the results in the members of the
2041 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2042 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2043 min_line_ascent, min_line_descent, max_line_ascent, and
2044 max_line_descent of $CONTROL are all zero.
2047 This function returns the width of the text to be drawn in the
2048 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2049 text is drawn in multiple physical lines, it returns the width of
2050 the widest line. If an error occurs, it returns -1 and assigns an
2051 error code to the external variable #merror_code. */
2055 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2057 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬
2058 ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2059 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2061 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ
2062 »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬
2063 »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box)
2064 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2066 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2067 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨
2068 ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½
2069 ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2071 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2072 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2073 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª
2074 ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2075 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2076 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2078 @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£
2079 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ
2080 ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°
2081 ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2083 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2090 mdraw_text_extents (MFrame *frame,
2091 MText *mt, int from, int to, MDrawControl *control,
2092 MDrawMetric *overall_ink_return,
2093 MDrawMetric *overall_logical_return,
2094 MDrawMetric *overall_line_return)
2096 MGlyphString *gstring;
2098 int width, rbearing;
2100 ASSURE_CONTROL (control);
2101 M_CHECK_POS_X (mt, from, -1);
2102 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2103 to = mtext_nchars (mt) + (control->cursor_width != 0);
2107 gstring = get_gstring (frame, mt, from, to, control);
2109 MERROR (MERROR_DRAW, -1);
2110 width = gstring_width (gstring, from, to, &rbearing);
2111 if (overall_ink_return)
2113 overall_ink_return->y = - gstring->physical_ascent;
2114 overall_ink_return->x = gstring->lbearing;
2116 if (overall_logical_return)
2118 overall_logical_return->y = - gstring->ascent;
2119 overall_logical_return->x = 0;
2121 if (overall_line_return)
2123 overall_line_return->y = - gstring->line_ascent;
2124 overall_line_return->x = gstring->lbearing;
2127 for (from = gstring->to; from < to; from = gstring->to)
2129 int this_width, this_rbearing;
2131 y += gstring->line_descent;
2132 M17N_OBJECT_UNREF (gstring->top);
2133 gstring = get_gstring (frame, mt, from, to, control);
2134 this_width = gstring_width (gstring, from, to, &this_rbearing);
2135 y += gstring->line_ascent;
2136 if (width < this_width)
2138 if (rbearing < this_rbearing)
2139 rbearing = this_rbearing;
2141 if (overall_ink_return)
2143 overall_ink_return->width = rbearing;
2144 overall_ink_return->height
2145 = y + gstring->physical_descent - overall_ink_return->y;
2147 if (overall_logical_return)
2149 overall_logical_return->width = width;
2150 overall_logical_return->height
2151 = y + gstring->descent - overall_logical_return->y;
2153 if (overall_line_return)
2155 overall_line_return->width = MAX (width, rbearing);
2156 overall_line_return->height
2157 = y + gstring->line_descent - overall_line_return->y;
2160 M17N_OBJECT_UNREF (gstring->top);
2167 @brief Compute the text dimensions of each character of M-text.
2169 The mdraw_text_per_char_extents () function computes the drawn
2170 metric of each character between $FROM and $TO of M-text $MT
2171 assuming that they are drawn on a window of frame $FRAME using the
2172 mdraw_text_with_control () function with the drawing control
2175 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2176 $LOGICAL_ARRAY_RETURN. Each successive element of
2177 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2178 ink and logical metrics of successive characters respectively,
2179 relative to the drawing origin of the M-text. The number of
2180 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2181 been set is returned to $NUM_CHARS_RETURN.
2183 If $ARRAY_SIZE is too small to return all metrics, the function
2184 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2185 Otherwise, it returns zero.
2187 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2188 @c NULL, this function also computes the metrics of the overall
2189 text and stores the results in the members of the structure
2190 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2192 If $CONTROL->two_dimensional is nonzero, this function computes
2193 only the metrics of characters in the first line. */
2195 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2197 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô
2198 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2199 ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ
2200 ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2202 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î
2203 ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ×
2204 ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î
2205 ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2206 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2208 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2209 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2212 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2213 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2214 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á
2217 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú
2218 ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2221 mdraw_text_per_char_extents (MFrame *frame,
2222 MText *mt, int from, int to,
2223 MDrawControl *control,
2224 MDrawMetric *ink_array_return,
2225 MDrawMetric *logical_array_return,
2227 int *num_chars_return,
2228 MDrawMetric *overall_ink_return,
2229 MDrawMetric *overall_logical_return)
2231 MGlyphString *gstring;
2235 ASSURE_CONTROL (control);
2236 *num_chars_return = to - from;
2237 if (array_size < *num_chars_return)
2238 MERROR (MERROR_DRAW, -1);
2239 if (overall_logical_return)
2240 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2241 if (overall_ink_return)
2242 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2244 M_CHECK_RANGE (mt, from, to, -1, 0);
2245 gstring = get_gstring (frame, mt, from, to, control);
2248 *num_chars_return = 0;
2252 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2253 if (g->pos >= from && g->pos < to)
2257 int width = g->width;
2258 int lbearing = g->lbearing;
2259 int rbearing = g->rbearing;
2260 int ascent = g->ascent;
2261 int descent = g->descent;
2262 int logical_ascent = g->rface->rfont->ascent;
2263 int logical_descent = g->rface->rfont->descent;
2265 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2267 if (lbearing < width + g->lbearing)
2268 lbearing = width + g->lbearing;
2269 if (rbearing < width + g->rbearing)
2270 rbearing = width + g->rbearing;
2272 if (ascent < g->ascent)
2274 if (descent < g->descent)
2275 descent = g->descent;
2282 ink_array_return[start - from].x = x + lbearing;
2283 ink_array_return[start - from].y = - ascent;
2284 ink_array_return[start - from].width = rbearing - lbearing;
2285 ink_array_return[start - from].height = ascent + descent;
2286 logical_array_return[start - from].x = x;
2287 logical_array_return[start - from].y = - logical_descent;
2288 logical_array_return[start - from].height
2289 = logical_ascent + logical_descent;
2290 logical_array_return[start - from].width = width;
2296 if (overall_ink_return)
2298 overall_ink_return->y = - gstring->line_ascent;
2299 overall_ink_return->x = gstring->lbearing;
2300 overall_ink_return->width = x - gstring->lbearing;
2301 overall_ink_return->height = gstring->height;
2303 if (overall_logical_return)
2305 overall_logical_return->y = - gstring->ascent;
2306 overall_logical_return->x = 0;
2307 overall_logical_return->width = x;
2308 overall_logical_return->height = gstring->ascent + gstring->descent;
2311 M17N_OBJECT_UNREF (gstring->top);
2318 @brief Return the character position nearest to the coordinates.
2320 The mdraw_coordinates_position () function checks which character
2321 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2322 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2323 mdraw_text_with_control () function with the drawing control
2324 object $CONTROL. Here, the character position means the number of
2325 characters that precede the character in question in $MT, that is,
2326 the character position of the first character is 0.
2328 $FRAME is used only to get the default face information.
2331 If the glyph image of a character covers coordinate ($X, $Y),
2332 mdraw_coordinates_position () returns the character position of
2334 If $Y is less than the minimum Y-coordinate of the drawn area, it
2335 returns $FROM.\n\n\n
2336 If $Y is greater than the maximum Y-coordinate of the drawn area,
2337 it returns $TO.\n\n\n
2338 If $Y fits in with the drawn area but $X is less than the minimum
2339 X-coordinate, it returns the character position of the first
2340 character drawn on the line $Y.\n\n\n
2341 If $Y fits in with the drawn area but $X is greater than the
2342 maximum X-coordinate, it returns the character position of the
2343 last character drawn on the line $Y. */
2346 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2348 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2349 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤
2350 ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è
2351 ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç
2352 ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨
2353 ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2355 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2358 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2359 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2361 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2363 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2365 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2366 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2368 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2369 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2372 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2373 int x_offset, int y_offset, MDrawControl *control)
2375 MGlyphString *gstring;
2380 M_CHECK_POS_X (mt, from, -1);
2381 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2382 to = mtext_nchars (mt) + (control->cursor_width != 0);
2388 ASSURE_CONTROL (control);
2389 gstring = get_gstring (frame, mt, from, to, control);
2390 while (y + gstring->line_descent <= y_offset
2391 && gstring->to < to)
2394 y += gstring->line_descent;
2395 M17N_OBJECT_UNREF (gstring->top);
2396 gstring = get_gstring (frame, mt, from, to, control);
2397 y += gstring->line_ascent;
2400 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2401 if (! control->orientation_reversed)
2403 width = gstring->indent;
2404 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2405 if (g->pos >= from && g->pos < to)
2408 if (width > x_offset)
2414 width = - gstring->indent;
2415 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2416 if (g->pos >= from && g->pos < to)
2419 if (width < x_offset)
2424 M17N_OBJECT_UNREF (gstring->top);
2432 @brief Compute information about a glyph.
2434 The mdraw_glyph_info () function computes information about a
2435 glyph that covers a character at position $POS of the M-text $MT
2436 assuming that the text is drawn from the character at $FROM of $MT
2437 on a window of frame $FRAME using the mdraw_text_with_control ()
2438 function with the drawing control object $CONTROL.
2440 The information is stored in the members of $INFO. */
2442 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2444 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ
2445 ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2446 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ
2447 »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2449 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2457 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2458 MDrawControl *control, MDrawGlyphInfo *info)
2460 MGlyphString *gstring;
2464 M_CHECK_RANGE_X (mt, from, pos, -1);
2466 ASSURE_CONTROL (control);
2467 gstring = get_gstring (frame, mt, from, pos + 1, control);
2469 MERROR (MERROR_DRAW, -1);
2470 while (gstring->to <= pos)
2472 y += gstring->line_descent;
2473 M17N_OBJECT_UNREF (gstring->top);
2474 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2475 y += gstring->line_ascent;
2477 info->line_from = gstring->from;
2478 if (info->line_from < from)
2479 info->line_from = from;
2480 info->line_to = gstring->to;
2483 if (! control->orientation_reversed)
2485 info->x = gstring->indent;
2486 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2487 info->x += g->width;
2491 info->x = - gstring->indent;
2492 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2493 info->x -= g->width;
2494 while (g[-1].to == g->to)
2497 info->from = g->pos;
2499 info->glyph_code = g->code;
2500 info->this.x = g->lbearing;
2501 info->this.y = - gstring->line_ascent;
2502 info->this.height = gstring->height;
2503 info->this.width = - g->lbearing + g->width;
2504 if (g->rface->rfont)
2505 info->font = &g->rface->rfont->font;
2508 /* info->logical_width is calculated later. */
2510 if (info->from > info->line_from)
2512 /* The logically previous glyph is on this line. */
2513 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2515 info->prev_from = g_tmp->pos;
2517 else if (info->line_from > 0)
2519 /* The logically previous glyph is on the previous line. */
2520 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2521 gstring->from, control);
2522 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2524 info->prev_from = g_tmp->pos;
2525 M17N_OBJECT_UNREF (gst->top);
2528 info->prev_from = -1;
2530 if (GLYPH_INDEX (g) > 1)
2531 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2532 else if (! control->orientation_reversed)
2534 if (info->line_from > 0)
2538 int p = gstring->from - 1;
2540 gst = get_gstring (frame, mt, p, gstring->from, control);
2541 g_tmp = gst->glyphs + (gst->used - 2);
2542 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2543 M17N_OBJECT_UNREF (gst->top);
2546 info->left_from = info->left_to = -1;
2550 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2554 int p = gstring->to;
2556 gst = get_gstring (frame, mt, p, p + 1, control);
2557 g_tmp = gst->glyphs + (gst->used - 2);
2558 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2559 M17N_OBJECT_UNREF (gst->top);
2562 info->left_from = info->left_to = -1;
2565 if (info->to < gstring->to)
2567 /* The logically next glyph is on this line. */
2568 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2570 info->next_to = g_tmp->to;
2572 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2574 /* The logically next glyph is on the next line. */
2576 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2577 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2579 info->next_to = g_tmp->to;
2580 M17N_OBJECT_UNREF (gst->top);
2585 for (info->logical_width = (g++)->width;
2586 g->pos == pos && g->type != GLYPH_ANCHOR;
2587 info->this.width += g->width, info->logical_width += (g++)->width);
2588 info->this.width += g[-1].rbearing - g[-1].width;
2590 if (g->type != GLYPH_ANCHOR)
2591 info->right_from = g->pos, info->right_to = g->to;
2592 else if (! control->orientation_reversed)
2594 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
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;
2607 if (info->line_from > 0)
2609 pos = gstring->from - 1;
2610 M17N_OBJECT_UNREF (gstring->top);
2611 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2613 info->right_from = g->pos, info->right_to = g->to;
2616 info->right_from = info->right_to = -1;
2619 M17N_OBJECT_UNREF (gstring->top);
2626 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2627 MDrawControl *control, MDrawGlyphInfo *info,
2628 int array_size, int *num_glyphs_return)
2630 MGlyphString *gstring;
2634 ASSURE_CONTROL (control);
2635 *num_glyphs_return = 0;
2636 M_CHECK_RANGE (mt, from, to, -1, 0);
2637 gstring = get_gstring (frame, mt, from, to, control);
2640 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2642 if (g->type == GLYPH_BOX
2643 || g->pos < from || g->pos >= to)
2647 info->from = g->pos;
2649 info->glyph_code = (g->type == GLYPH_CHAR ? g->code : 0);
2652 info->this.x = g->lbearing;
2653 info->this.y = - g->ascent;
2654 info->this.height = g->ascent + g->descent;
2655 info->this.width = g->rbearing - g->lbearing;
2656 info->logical_width = g->width;
2657 if (g->rface->rfont)
2658 info->font = &g->rface->rfont->font;
2665 M17N_OBJECT_UNREF (gstring->top);
2667 *num_glyphs_return = n;
2668 return (n <= array_size ? 0 : -1);
2674 @brief Draw one or more textitems.
2676 The mdraw_text_items () function draws one or more M-texts on
2677 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2678 of the textitems to be drawn and $NITEMS is the number of
2679 textimtems in the array. */
2682 @brief textitem ¤òɽ¼¨¤¹¤ë.
2684 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2685 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2686 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2689 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2693 MTextItem, mdraw_text (). */
2696 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2697 MDrawTextItem *items, int nitems)
2699 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2701 while (nitems-- > 0)
2704 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2706 mdraw_text_with_control (frame, win, x, y,
2707 items->mt, 0, mtext_nchars (items->mt),
2709 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2710 items->control, NULL, NULL, NULL);
2713 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2719 @brief calculate a line breaking position.
2721 The function mdraw_default_line_break () calculates a line
2722 breaking position based on the line number $LINE and the
2723 coordinate $Y, when a line is too long to fit within the width
2724 limit. $POS is the position of the character next to the last
2725 one that fits within the limit. $FROM is the position of the
2726 first character of the line, and TO is the position of the last
2727 character displayed on the line if there were not width limit.
2728 LINE and Y are reset to 0 when a line is broken by a newline
2729 character, and incremented each time when a long line is broken
2730 because of the width limit.
2733 This function returns a character position to break the
2738 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2740 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì
2741 ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2742 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï
2743 ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë
2744 ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ
2745 ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿
2746 ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2749 ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2753 mdraw_default_line_break (MText *mt, int pos,
2754 int from, int to, int line, int y)
2756 int c = mtext_ref_char (mt, pos);
2759 if (c == ' ' || c == '\t')
2763 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2770 if (c == ' ' || c == '\t')
2773 c = mtext_ref_char (mt, pos);
2786 @brief Obtain per character dimension information.
2788 The mdraw_per_char_extents () function computes the text dimension
2789 of each character in M-text $MT. The faces given as text
2790 properties in $MT and the default face of frame $FRAME determine
2791 the fonts to draw the text. Each successive element in
2792 $ARRAY_RETURN is set to the drawn metrics of successive
2793 characters, which is relative to the origin of the drawing, and a
2794 rectangle for each character in $MT. The number of elements of
2795 $ARRAY_RETURN must be equal to or greater than the number of
2798 If pointer $OVERALL_RETURN is not @c NULL, this function also
2799 computes the extents of the overall text and stores the results in
2800 the members of the structure pointed to by $OVERALL_RETURN. */
2803 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2805 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2806 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2807 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
2808 ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2809 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
2810 ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
2813 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
2814 ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
2817 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2820 mdraw_per_char_extents (MFrame *frame, MText *mt,
2821 MDrawMetric *array_return,
2822 MDrawMetric *overall_return)
2824 int n = mtext_nchars (mt);
2826 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2827 n, &n, overall_return, NULL);
2831 @brief clear cached information.
2833 The mdraw_clear_cache () function clear cached information
2834 on M-text $MT that was attached by any of the drawing functions.
2835 When the behaviour of `format' or `line_break'
2836 member functions of MDrawControl is changed, the cache must be cleared.
2841 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2843 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉÕ²Ã
2844 ¤µ¤ì¤¿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢
2845 ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å
2846 ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2851 mdraw_clear_cache (MText *mt)
2853 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);