1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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., 51 Franklin Street, Fifth Floor,
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 layout
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face
44 ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include <sys/types.h>
64 #include "m17n-misc.h"
69 #include "internal-gui.h"
70 #include "internal-flt.h"
75 #include <fribidi/fribidi.h>
76 #endif /* HAVE_FRIBIDI */
78 #define MAX(x, y) ((x) > (y) ? (x) : (y))
79 #define MIN(x, y) ((x) < (y) ? (x) : (y))
81 static MSymbol M_glyph_string;
84 static MSymbol Mcommon;
85 /* Special categories */
86 static MSymbol McatCc, McatCf;
88 static MCharTable *linebreak_table;
89 static MSymbol M_break_at_space, M_break_at_word, M_break_at_any;
90 static MSymbol M_kinsoku_bol, M_kinsoku_eol;
93 /* Glyph-string composer. */
95 static MSymbol MbidiR;
96 static MSymbol MbidiAL;
97 static MSymbol MbidiRLE;
98 static MSymbol MbidiRLO;
99 static MSymbol MbidiBN;
100 static MSymbol MbidiS;
101 static MSymbol MbidiNSM;
104 analyse_bidi_level (MGlyphString *gstring)
106 int len = gstring->used - 2;
107 int bidi_sensitive = gstring->control.orientation_reversed;
112 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
113 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
114 FriBidiLevel *levels;
115 FriBidiStrIndex *indices;
116 #else /* not HAVE_FRIBIDI */
117 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
120 memset (levels, 0, sizeof (int) * len);
121 #endif /* not HAVE_FRIBIDI */
123 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
128 #endif /* not HAVE_FRIBIDI */
131 MSymbol bidi = (MSymbol) mchar_get_prop (g->g.c, Mbidi_category);
133 if (bidi == MbidiR || bidi == MbidiAL
134 || bidi == MbidiRLE || bidi == MbidiRLO)
139 #endif /* not HAVE_FRIBIDI */
142 else if (bidi == MbidiNSM && i > 0 && levels[i - 1])
144 #endif /* not HAVE_FRIBIDI */
149 if (! bidi_sensitive)
153 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
154 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
156 fribidi_log2vis (logical, len, &base, NULL, NULL, indices, levels);
157 #endif /* not HAVE_FRIBIDI */
159 MGLYPH (0)->bidi_level = 0;
161 for (g = MGLYPH (1), i = 0; i < len; g++, i++)
163 g->bidi_level = levels[i];
164 if (max_level < g->bidi_level)
165 max_level = g->bidi_level;
167 MGLYPH (i)->bidi_level = 0;
172 visual_order (MGlyphString *gstring)
174 MGlyph *glyphs = alloca (sizeof (MGlyph) * gstring->used);
177 memcpy (glyphs, gstring->glyphs, sizeof (MGlyph) * gstring->used);
179 for (i = gidx = 0; i < gstring->used - 1; gidx++)
181 int level = glyphs[i].bidi_level;
183 gstring->glyphs[gidx] = glyphs[i];
184 glyphs[i].rface = NULL;
188 int prev_level = glyphs[i - 1].bidi_level;
190 if (prev_level == level)
192 else if (prev_level > level)
194 for (; glyphs[i - 1].bidi_level > level; i--);
195 if (glyphs[i].bidi_level % 2)
196 for (level = glyphs[i].bidi_level;
197 glyphs[i + 1].bidi_level == level; i++);
200 for (i++; ! glyphs[i].rface; i++);
204 int next_level = glyphs[i + 1].bidi_level;
206 if (next_level == level)
208 else if (next_level > level)
210 for (; glyphs[i + 1].bidi_level > level; i++);
211 if ((glyphs[i].bidi_level % 2) == 0)
212 for (level = glyphs[i].bidi_level;
213 glyphs[i - 1].bidi_level == level; i--);
219 for (i--; glyphs[i].bidi_level >= level; i--);
220 if (! glyphs[i].rface)
221 for (i = save; ! glyphs[i].rface; i++);
225 for (i = 1; i < gstring->used - 1; i++)
227 MGlyph *g = gstring->glyphs + i;
229 for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++);
232 memcpy (glyphs + i, gstring->glyphs + i,
233 sizeof (MGlyph) * (j - i + 1));
235 g[j - i] = glyphs[i];
242 font_id (MFLTFont *font)
244 return ((MFLTFontForRealized *) font)->rfont->id;
248 run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
250 MRealizedFont *rfont = rface->rfont;
251 MSymbol layouter = rface->layouter;
252 MFLTGlyphString flt_gstr;
253 MFLTFontForRealized font;
255 int from_pos = MGLYPH (from)->g.from;
260 flt = mflt_get (layouter);
261 flt_gstr.glyph_size = sizeof (MGlyph);
262 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
263 flt_gstr.used = gstring->used;
264 flt_gstr.allocated = gstring->size;
266 font.font.family = mfont_get_prop (rfont->font, Mfamily);
267 font.font.x_ppem = rfont->x_ppem;
268 font.font.y_ppem = rfont->y_ppem;
269 font.font.get_glyph_id = mfont__get_glyph_id;
270 font.font.get_metrics = mfont__get_metrics;
271 font.font.check_otf = rfont->driver->check_otf;
272 font.font.drive_otf = rfont->driver->drive_otf;
273 font.font.internal = NULL;
275 mflt_font_id = font_id;
276 mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature;
277 mflt_try_otf = rfont->driver->try_otf;
278 for (i = 0; i < 3; i++)
280 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
283 APPEND_GLYPH (gstring, *MGLYPH (0));
284 APPEND_GLYPH (gstring, *MGLYPH (0));
287 if (from + len != to)
288 gstring->used += to - (from + len);
289 for (i = from, catcode = -1; i < to; i++)
291 MGlyph *g = MGLYPH (i);
293 g->g.from += from_pos - from;
294 g->g.to += from_pos - from + 1;
304 if (catcode < 0 || g->g.from != g[-1].g.from)
306 MSymbol category = mchar_get_prop (g->g.c, Mcategory);
308 catcode = (category == McatCf
309 ? GLYPH_CATEGORY_FORMATTER
310 : category != Mnil && MSYMBOL_NAME (category)[0] == 'M'
311 ? GLYPH_CATEGORY_MODIFIER
312 : GLYPH_CATEGORY_NORMAL);
314 g->category = catcode;
319 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
320 displaying them on FRAME.
322 This function fills these members:
323 pos, to, c, code, rface, bidi_level, categories, type, combining_code
324 The other members are filled by layout_glyph_string. */
327 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
328 MGlyphString *gstring)
330 MRealizedFace *default_rface = frame->rface;
331 int stop, face_change, language_change, charset_change, font_change;
332 MGlyph g_tmp, *g, *last_g;
334 MSymbol language = Mnil, script = Mnil, charset = Mnil;
335 MSymbol non_latin_script = Mnil;
336 MRealizedFace *rface = default_rface;
337 MRealizedFont *rfont;
338 int size = gstring->control.fixed_width;
339 int max_bidi_level = 0;
342 MLIST_RESET (gstring);
343 gstring->from = from;
345 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
346 <category> and <rface> members.*/
349 /** Put anchor glyphs at the head and tail. */
350 g_tmp.type = GLYPH_ANCHOR;
351 g_tmp.g.from = g_tmp.g.to = from;
352 APPEND_GLYPH (gstring, g_tmp);
353 stop = face_change = font_change = pos = from;
363 if (pos < mtext_nchars (mt))
365 MFont *font = rface->font;
369 if (pos == font_change)
371 font = mtext_get_prop (mt, pos, Mfont);
372 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
373 if (font_change == mtext_nchars (mt))
376 if (pos == face_change)
378 num = mtext_get_prop_values (mt, pos, Mface,
379 (void **) faces, 64);
380 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
381 if (face_change == mtext_nchars (mt))
386 faces[0] = &rface->face;
389 rface = mface__realize (frame, faces, num, size, font);
392 rface = default_rface;
394 if (stop > font_change)
396 if (stop > face_change)
400 if (pos < mtext_nchars (mt))
401 c = mtext_ref_char (mt, pos);
405 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
407 g_tmp.g.from = pos++;
410 category = mchar_get_prop (c, Mcategory);
411 if (category == McatCf)
412 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
413 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
414 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
416 g_tmp.category = GLYPH_CATEGORY_NORMAL;
418 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
422 ctrl[0] = ctrl[1] = g_tmp;
424 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
425 APPEND_GLYPH (gstring, ctrl[0]);
426 APPEND_GLYPH (gstring, ctrl[1]);
429 APPEND_GLYPH (gstring, g_tmp);
430 if (c == '\n' && gstring->control.two_dimensional)
433 /* Append an anchor glyph. */
435 g_tmp.type = GLYPH_ANCHOR;
436 g_tmp.g.from = g_tmp.g.to = pos;
437 APPEND_GLYPH (gstring, g_tmp);
440 if (gstring->control.enable_bidi)
441 max_bidi_level = analyse_bidi_level (gstring);
443 /* The next loop is to change each <rface> member for non-ASCII
444 characters if necessary. */
445 stop = charset_change = language_change = from;
446 rfont = default_rface->rfont;
447 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
453 /* Short cut for the obvious case. */
454 this_script = Mlatin;
457 this_script = (MSymbol) mchar_get_prop (c, Mscript);
458 if (this_script == Minherited || this_script == Mcommon)
462 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
464 if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z')
465 this_script = script;
468 if (this_script == Mcommon && non_latin_script)
469 this_script = non_latin_script;
470 if (this_script == Mcommon)
472 /* Search forward for a character that explicitly
473 specifies a non-latin script. */
477 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
479 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
480 && sym != Minherited)
486 if (this_script == Minherited || this_script == Mcommon)
487 this_script = (MSymbol) mchar_get_prop (c, Mblock);
491 if (pos == stop || script != this_script || g->rface->rfont != rfont)
494 last_g = mface__for_chars (script, language, charset,
496 script = this_script;
497 if (script != Mnil && script != Mlatin)
498 non_latin_script = script;
499 rfont = g->rface->ascii_rface->rfont;
502 if (pos < mtext_nchars (mt) && pos == language_change)
504 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
505 mtext_prop_range (mt, Mlanguage, pos, NULL,
506 &language_change, 0);
508 if (pos < mtext_nchars (mt) && pos == charset_change)
510 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
511 mtext_prop_range (mt, Mcharset, pos, NULL,
515 if (stop > language_change)
516 stop = language_change;
517 if (stop > charset_change)
518 stop = charset_change;
523 last_g = mface__for_chars (script, language, charset, last_g, g, size);
525 /* The next loop is to run FLT or perform the default combining if
527 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
531 if (this->type == GLYPH_CHAR && this->rface->rfont)
535 if (this->rface->layouter != Mnil)
537 MGlyph *prev = MGLYPH (start - 1);
539 while (prev->type == GLYPH_CHAR
540 && prev->category == GLYPH_CATEGORY_FORMATTER
541 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
543 != MCHAR_INVALID_CODE))
545 prev->rface->rfont = this->rface->rfont;
550 (g->type == GLYPH_CHAR
551 && g->rface->layouter == this->rface->layouter
552 && (g->rface->rfont == this->rface->rfont
553 || (g->category == GLYPH_CATEGORY_FORMATTER
554 && (mfont__encode_char (NULL,
555 (MFont *) this->rface->rfont,
557 != MCHAR_INVALID_CODE))));
559 g->rface->rfont = this->rface->rfont;
560 i = run_flt (gstring, start, i, this->rface);
565 while (g->type == GLYPH_CHAR
567 && g->category == GLYPH_CATEGORY_MODIFIER
569 && g->rface->layouter == Mnil)
573 this->rface->layouter = Mcombining;
574 run_flt (gstring, start, i, this->rface);
577 mfont__get_metric (gstring, start, i);
585 /* At last, reorder glyphs visually if necessary. */
586 if (max_bidi_level > 0)
587 visual_order (gstring);
591 int width, lbearing, rbearing;
595 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
596 MSubTextExtents *extents)
598 int g_physical_ascent, g_physical_descent;
599 MGlyph *g = MGLYPH (from);
600 MGlyph *last_g = MGLYPH (to);
602 g_physical_ascent = gstring->physical_ascent;
603 g_physical_descent = gstring->physical_descent;
604 extents->width = extents->lbearing = extents->rbearing = 0;
606 for (g = MGLYPH (from); g < last_g; g++)
608 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
609 g_physical_descent = MAX (g_physical_descent, g->g.descent);
610 extents->lbearing = MIN (extents->lbearing,
611 extents->width + g->g.lbearing);
612 extents->rbearing = MAX (extents->rbearing,
613 extents->width + g->g.rbearing);
614 extents->width += g->g.xadv;
617 gstring->physical_ascent = g_physical_ascent;
618 gstring->physical_descent = g_physical_descent;
622 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
623 by this function directly. Character glyphs are handled by
624 layouter functions registered in font drivers.
626 This function fill-in all the remaining members of glyphs. */
629 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
631 /* Default width of TAB. */
632 int tab_width = frame->space_width * (gstring->control.tab_width
633 ? gstring->control.tab_width : 8);
637 MDrawControl *control = &(gstring->control);
640 int box_line_height = 0;
641 int ignore_formatting_char = control->ignore_formatting_char;
643 gstring->ascent = gstring->descent = 0;
644 gstring->physical_ascent = gstring->physical_descent = 0;
645 gstring->width = gstring->lbearing = gstring->rbearing = 0;
649 while (g->type != GLYPH_ANCHOR)
651 if (box != g->rface->box)
653 int gidx = GLYPH_INDEX (g);
657 /* Insert the right side of the box. That glyph belongs
658 to the previous grapheme cluster. */
659 MGlyph box_glyph = g[-1];
661 box_glyph.type = GLYPH_BOX;
663 = (control->fixed_width
665 : box->inner_hmargin + box->width + box->outer_hmargin);
666 box_glyph.g.lbearing = 0;
667 box_glyph.g.rbearing = box_glyph.g.xadv;
668 box_glyph.g.xoff = 0;
669 box_glyph.right_padding = 1;
670 gstring->width += box_glyph.g.xadv;
671 gstring->rbearing += box_glyph.g.xadv;
672 INSERT_GLYPH (gstring, gidx, box_glyph);
679 /* Insert the left side of the box. That glyph belongs
680 to the following grapheme cluster. */
681 MGlyph box_glyph = *g;
682 int box_height = (box->width
683 + box->inner_vmargin + box->outer_vmargin);
685 if (box_line_height < box_height)
686 box_line_height = box_height;
687 box_glyph.type = GLYPH_BOX;
689 = (control->fixed_width
691 : box->inner_hmargin + box->width + box->outer_hmargin);
692 box_glyph.g.lbearing = 0;
693 box_glyph.g.rbearing = box_glyph.g.xadv;
694 box_glyph.g.xoff = 0;
695 box_glyph.left_padding = 1;
696 gstring->width += box_glyph.g.xadv;
697 gstring->rbearing += box_glyph.g.xadv;
698 INSERT_GLYPH (gstring, gidx, box_glyph);
704 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
705 g->type = GLYPH_SPACE;
707 if (g->type == GLYPH_CHAR)
709 MRealizedFace *rface = g->rface;
710 MRealizedFont *rfont = rface->rfont;
712 int from = GLYPH_INDEX (g);
714 for (g++; g->type == GLYPH_CHAR; g++)
715 if (! rfont != ! g->rface->rfont
716 || box != g->rface->box
717 || ((fromg->g.code == MCHAR_INVALID_CODE)
718 != (g->g.code == MCHAR_INVALID_CODE))
719 || (g->category == GLYPH_CATEGORY_FORMATTER
720 && ignore_formatting_char))
722 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
725 int to = GLYPH_INDEX (g);
726 MSubTextExtents extents;
728 layout_glyphs (frame, gstring, from, to, &extents);
729 extra_width = - extents.lbearing;
731 && ! control->disable_overlapping_adjustment
732 && (! control->orientation_reversed
733 ? ((to > 1 || control->align_head)
734 && g->type != GLYPH_ANCHOR)
735 : (((g->type && GLYPH_ANCHOR) || control->align_head)
740 pad.type = GLYPH_PAD;
743 pad.g.xadv = pad.g.rbearing = extra_width;
744 pad.left_padding = 1;
745 INSERT_GLYPH (gstring, from, pad);
747 extents.lbearing = 0;
748 extents.width += extra_width;
749 extents.rbearing += extra_width;
751 g = MGLYPH (from - 1);
752 if (g->type == GLYPH_SPACE)
754 /* The pad just inserted is absorbed (maybe
755 partially) by the previous space while
756 keeping at least some space width. For the
757 moment, we use the arbitrary width 2-pixel.
758 Perhaps, it should be decided by the current
759 face, or a default value of the current
760 frame, which is, however, not yet
762 if (extra_width + 2 < g->g.xadv)
764 g->g.xadv -= extra_width;
768 extra_width = g->g.xadv - 2;
771 gstring->width -= extra_width;
772 gstring->rbearing -= extra_width;
777 extra_width = extents.rbearing - extents.width;
779 && ! control->disable_overlapping_adjustment
780 && (GLYPH_INDEX (g) < gstring->used - 1
781 || (control->orientation_reversed && control->align_head)))
783 if (g->type == GLYPH_SPACE && box == g->rface->box)
786 pad.type = GLYPH_PAD;
789 pad.g.xadv = pad.g.rbearing = extra_width;
790 INSERT_GLYPH (gstring, to, pad);
795 g[-1].g.xadv += extra_width;
796 extents.width += extra_width;
799 if (gstring->lbearing > gstring->width + extents.lbearing)
800 gstring->lbearing = gstring->width + extents.lbearing;
801 if (gstring->rbearing < gstring->width + extents.rbearing)
802 gstring->rbearing = gstring->width + extents.rbearing;
803 gstring->width += extents.width;
804 if (gstring->ascent < rface->ascent)
805 gstring->ascent = rface->ascent;
806 if (gstring->descent < rface->descent)
807 gstring->descent = rface->descent;
811 for (; fromg < g; fromg++)
813 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
814 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
815 fromg->g.xadv = fromg->g.rbearing = 1;
817 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
818 fromg->g.xoff = fromg->g.lbearing = 0;
819 fromg->g.ascent = fromg->g.descent = 0;
820 gstring->width += fromg->g.xadv;
821 gstring->rbearing += fromg->g.xadv;
823 if (gstring->ascent < frame->rface->ascent)
824 gstring->ascent = frame->rface->ascent;
825 if (gstring->descent < frame->descent)
826 gstring->descent = frame->rface->descent;
829 else if (g->type == GLYPH_SPACE)
832 g->g.xadv = g->rface->space_width;
833 else if (g->g.c == '\n')
835 g->g.xadv = control->cursor_width;
838 if (control->cursor_bidi)
840 else if (g->g.xadv < 0)
841 g->g.xadv = g->rface->space_width;
844 else if (g->g.c == '\t')
846 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
852 if (g[-1].type == GLYPH_PAD)
854 /* This space glyph absorbs (maybe partially) the
855 previous padding glyph. */
856 g->g.xadv -= g[-1].g.xadv;
858 /* But, keep at least some space width. For the
859 moment, we use the arbitrary width 2-pixel. */
862 g->g.rbearing = g->g.xadv;
863 gstring->width += g->g.xadv;
864 gstring->rbearing += g->g.xadv;
867 if (gstring->ascent < g->rface->ascent)
868 gstring->ascent = g->rface->ascent;
869 if (gstring->descent < g->rface->descent)
870 gstring->descent = g->rface->descent;
876 gstring->width += g->g.xadv;
877 gstring->rbearing += g->g.xadv;
884 /* Insert the right side of the box. */
885 int gidx = GLYPH_INDEX (g);
886 MGlyph box_glyph = g[-1];
888 box_glyph.type = GLYPH_BOX;
890 = (control->fixed_width
892 : box->inner_hmargin + box->width + box->outer_hmargin);
893 box_glyph.g.lbearing = 0;
894 box_glyph.g.rbearing = box_glyph.g.xadv;
895 box_glyph.g.xoff = 0;
896 box_glyph.right_padding = 1;
897 gstring->width += box_glyph.g.xadv;
898 gstring->rbearing += box_glyph.g.xadv;
899 INSERT_GLYPH (gstring, gidx, box_glyph);
902 gstring->text_ascent = gstring->ascent;
903 gstring->text_descent = gstring->descent;
904 if (gstring->text_ascent < gstring->physical_ascent)
905 gstring->text_ascent = gstring->physical_ascent;
906 if (gstring->text_descent < gstring->physical_descent)
907 gstring->text_descent = gstring->physical_descent;
908 gstring->line_ascent = gstring->text_ascent;
909 gstring->line_descent = gstring->text_descent;
910 if (box_line_height > 0)
912 gstring->line_ascent += box_line_height;
913 gstring->physical_ascent = gstring->line_ascent;
914 gstring->line_descent += box_line_height;
915 gstring->physical_descent = gstring->line_descent;
918 if (gstring->line_ascent < control->min_line_ascent)
919 gstring->line_ascent = control->min_line_ascent;
920 else if (control->max_line_ascent
921 && control->max_line_ascent > control->min_line_ascent
922 && gstring->line_ascent > control->max_line_ascent)
923 gstring->line_ascent = control->max_line_ascent;
925 if (gstring->line_descent < control->min_line_descent)
926 gstring->line_descent = control->min_line_descent;
927 else if (control->max_line_descent
928 && control->max_line_descent > control->min_line_descent
929 && gstring->line_descent > control->max_line_descent)
930 gstring->line_descent = control->max_line_descent;
931 gstring->height = gstring->line_ascent + gstring->line_descent;
933 if (control->orientation_reversed
936 /* We must adjust TAB width for RTL orientation. */
937 width = gstring->indent;
939 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
941 if (g->type == GLYPH_CHAR && g->g.c == '\t')
943 int this_width = tab_width - (width % tab_width);
945 if (g[1].type == GLYPH_PAD)
946 this_width -= g[1].g.xadv;
947 if (g[-1].type == GLYPH_PAD)
948 this_width -= g[-1].g.xadv;
951 gstring->width += this_width - g->g.xadv;
952 gstring->rbearing += this_width - g->g.xadv;
953 g->g.xadv = this_width;
964 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
965 MGlyphString *gstring, int from, int to,
966 int *from_idx, int *to_idx, int *to_x)
968 MGlyph *g = MGLYPH (1);
969 MDrawRegion region = (MDrawRegion) NULL;
970 MDrawControl *control = &gstring->control;
973 int cursor_bidi = control->cursor_bidi;
975 if (control->with_cursor && control->cursor_width)
977 if (gstring->from <= control->cursor_pos
978 && gstring->to > control->cursor_pos)
979 cursor_pos = control->cursor_pos;
982 && gstring->from <= control->cursor_pos - 1
983 && gstring->to > control->cursor_pos - 1)
984 prev_pos = control->cursor_pos - 1;
987 *from_idx = *to_idx = 0;
989 while (g->type != GLYPH_ANCHOR)
991 if (g->g.from >= from && g->g.from < to)
993 MGlyph *fromg = g, *cursor = NULL;
994 MRealizedFace *rface = g->rface;
996 int cursor_width = 0;
1000 *from_idx = GLYPH_INDEX (g);
1001 while (g->g.from >= from && g->g.from < to
1002 && g->rface == rface)
1005 if (g->type != GLYPH_BOX
1006 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1009 cursor = g, cursor_x = x + width;
1010 cursor_width += g->g.xadv;
1012 width += g++->g.xadv;
1015 && (control->as_image
1016 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1018 int this_x = x, this_width = width;
1020 if (fromg->type == GLYPH_BOX)
1021 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1022 if (g[-1].type == GLYPH_BOX)
1023 this_width -= g[-1].g.xadv;
1024 (frame->driver->fill_space)
1025 (frame, win, rface, 0,
1026 this_x, y - gstring->text_ascent, this_width,
1027 gstring->text_ascent + gstring->text_descent,
1028 control->clip_region);
1035 rect.y = y - gstring->text_ascent;
1036 rect.height = gstring->text_ascent + gstring->text_descent;
1039 rect.width = ((control->cursor_width > 0
1040 && control->cursor_width < cursor_width)
1041 ? control->cursor_width : cursor_width);
1045 if (cursor->bidi_level % 2)
1046 rect.x += cursor_width - rect.width;
1047 (*frame->driver->fill_space)
1048 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1049 control->clip_region);
1051 region = (*frame->driver->region_from_rect) (&rect);
1053 (*frame->driver->region_add_rect) (region, &rect);
1056 if (cursor->bidi_level % 2)
1059 rect.width = cursor_width < 4 ? cursor_width : 4;
1060 (*frame->driver->fill_space)
1061 (frame, win, rface, 1,
1062 rect.x, rect.y, rect.width, rect.height,
1063 control->clip_region);
1064 (*frame->driver->region_add_rect) (region, &rect);
1076 if (fromg->type != GLYPH_BOX
1077 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1080 cursor = fromg, cursor_x = x + temp_width;
1081 cursor_width += fromg->g.xadv;
1083 temp_width += fromg++->g.xadv;
1090 if (! (cursor->bidi_level % 2))
1091 rect.x += cursor_width - 1;
1092 rect.y = y - gstring->text_ascent;
1093 rect.height = gstring->text_ascent + gstring->text_descent;
1095 (*frame->driver->fill_space)
1096 (frame, win, rface, 1,
1097 rect.x, rect.y, rect.width, rect.height,
1098 control->clip_region);
1100 region = (*frame->driver->region_from_rect) (&rect);
1102 (*frame->driver->region_add_rect) (region, &rect);
1103 rect.y += rect.height - 2;
1105 rect.width = cursor_width < 4 ? cursor_width : 4;
1106 if (! (cursor->bidi_level % 2))
1107 rect.x -= rect.width - 1;
1108 (*frame->driver->fill_space) (frame, win, rface, 1,
1109 rect.x, rect.y, rect.width, rect.height,
1110 control->clip_region);
1111 (*frame->driver->region_add_rect) (region, &rect);
1115 *to_idx = GLYPH_INDEX (g);
1125 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1126 MGlyphString *gstring, int from_idx, int to_idx,
1127 int reverse, MDrawRegion region)
1129 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1135 (*frame->driver->region_to_rect) (region, &rect);
1138 while (g != gend && x + g->g.rbearing <= rect.x)
1141 width -= g++->g.xadv;
1142 while (! g->enabled && g != gend)
1146 rect.x += rect.width;
1147 if (rect.x < x + width)
1150 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1152 width -= (--gend)->g.xadv;
1153 while (! gend->enabled && g != gend)
1157 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1166 MRealizedFace *rface = g->rface;
1167 int width = g->g.xadv;
1168 MGlyph *from_g = g++;
1170 /* Handle the glyphs of the same type/face at once. */
1172 && g->type == from_g->type
1173 && g->rface == rface
1174 && ((g->g.code == MCHAR_INVALID_CODE)
1175 == (from_g->g.code == MCHAR_INVALID_CODE))
1177 width += g++->g.xadv;
1179 if (from_g->type == GLYPH_CHAR)
1181 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1182 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1185 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1188 else if (from_g->type == GLYPH_BOX)
1190 /* Draw the left or right side of a box. If
1191 from_g->lbearing is nonzero, this is the left side,
1192 else this is the right side. */
1193 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1196 if (from_g->type != GLYPH_BOX)
1199 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1200 x, y, width, region);
1203 /* Draw the top and bottom side of a box. */
1204 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1205 x, y, width, region);
1216 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1217 int *from_x, int *to_x)
1220 int left_idx = *left, right_idx = *right;
1221 int left_x, right_x, x;
1223 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1226 if (x + g->g.rbearing > 0)
1228 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1230 left_idx = GLYPH_INDEX (g);
1235 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1238 if (x - g->g.xadv + g->g.lbearing < 0)
1240 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1242 right_idx = GLYPH_INDEX (g) + 1;
1247 if (*left == left_idx && *right == right_idx)
1250 if (*left != left_idx)
1252 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1257 if (*right != right_idx)
1259 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1269 gstring_width (MGlyphString *gstring, int from, int to,
1270 int *lbearing, int *rbearing)
1275 if (from <= gstring->from && to >= gstring->to)
1278 *lbearing = gstring->lbearing;
1280 *rbearing = gstring->rbearing;
1281 return gstring->width;
1288 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1289 if (g->g.from >= from && g->g.from < to)
1291 if (lbearing && width + g->g.lbearing < *lbearing)
1292 *lbearing = width + g->g.lbearing;
1293 if (rbearing && width + g->g.rbearing > *rbearing)
1294 *rbearing = width + g->g.rbearing;
1302 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1303 MGlyphString *gstring, int from, int to)
1305 MDrawControl *control = &gstring->control;
1307 MDrawRegion clip_region, cursor_region;
1308 int from_idx, to_idx;
1313 if (control->orientation_reversed)
1314 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1316 x += gstring->indent;
1318 /* At first, draw all glyphs without cursor. */
1319 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1320 &from_idx, &to_idx, &to_x);
1322 if (control->partial_update)
1325 rect.width = to_x - x;
1326 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1328 rect.y = y - gstring->line_ascent;
1329 rect.height = gstring->height;
1330 clip_region = (*frame->driver->region_from_rect) (&rect);
1331 if (control->clip_region)
1332 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1335 clip_region = control->clip_region;
1338 clip_region = control->clip_region;
1340 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1345 (*frame->driver->intersect_region) (cursor_region, clip_region);
1346 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1349 if (clip_region != control->clip_region)
1350 (*frame->driver->free_region) (clip_region);
1352 (*frame->driver->free_region) (cursor_region);
1356 static int gstring_num;
1359 free_gstring (void *object)
1361 MGlyphString *gstring = (MGlyphString *) object;
1364 free_gstring (gstring->next);
1365 if (gstring->size > 0)
1366 free (gstring->glyphs);
1372 static MGlyphString scratch_gstring;
1374 static MGlyphString *
1375 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1378 MGlyphString *gstring;
1380 if (pos == mt->nchars)
1384 gstring = &scratch_gstring;
1385 if (gstring->size == 0)
1390 g_tmp.type = GLYPH_ANCHOR;
1391 APPEND_GLYPH (gstring, g_tmp);
1392 APPEND_GLYPH (gstring, g_tmp);
1393 APPEND_GLYPH (gstring, g_tmp);
1394 gstring->glyphs[1].type = GLYPH_SPACE;
1395 gstring->glyphs[1].g.c = '\n';
1396 gstring->glyphs[1].g.code = '\n';
1398 gstring->from = pos;
1400 g->rface = frame->rface;
1401 g->g.from = g->g.to = pos;
1403 g->rface = frame->rface;
1404 g->g.from = pos++, g->g.to = pos;
1406 g->rface = frame->rface;
1407 g->g.from = g->g.to = pos;
1412 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1413 MLIST_INIT1 (gstring, glyphs, 128);
1417 gstring->frame = frame;
1418 gstring->tick = frame->tick;
1419 gstring->top = gstring;
1420 gstring->control = *control;
1421 gstring->indent = gstring->width_limit = 0;
1422 if (control->format)
1423 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1425 gstring->width_limit = control->max_line_width;
1426 gstring->anti_alias = control->anti_alias;
1430 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1433 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1436 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1444 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1445 a width of glyphs for the character at I of MT. If I is not a
1446 beginning of a grapheme cluster, the corresponding element is
1448 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1449 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1450 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1451 pos_width[g->g.from - gstring->from] += g->g.xadv;
1452 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1454 if (pos_width[i] > 0)
1456 if (width + pos_width[i] > gstring->width_limit)
1459 width += pos_width[i];
1462 pos = gstring->from + i;
1463 if (gstring->control.line_break)
1465 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1466 gstring->from, gstring->from + i,
1468 if (pos <= gstring->from)
1470 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1473 else if (pos >= gstring->to)
1478 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1481 if (pos < gstring->to)
1483 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1484 layout_glyph_string (frame, gstring);
1489 /* Return a gstring that covers a character at POS. */
1491 static MGlyphString *
1492 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1494 MGlyphString *gstring = NULL;
1496 if (pos < mtext_nchars (mt))
1498 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1501 && ((prop->start != 0
1502 && mtext_ref_char (mt, prop->start - 1) != '\n')
1503 || (prop->end < mtext_nchars (mt)
1504 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1506 mtext_detach_property (prop);
1511 gstring = prop->val;
1512 if (gstring->frame != frame
1513 || gstring->tick != frame->tick
1514 || memcmp (control, &gstring->control,
1515 (char *) (&control->with_cursor)
1516 - (char *) (control))
1517 || control->cursor_pos != gstring->control.cursor_pos
1518 || control->cursor_width != gstring->control.cursor_width
1519 || control->cursor_bidi != gstring->control.cursor_bidi)
1521 mtext_detach_property (prop);
1526 else if (! control->cursor_width)
1534 offset = mtext_character (mt, pos, 0, '\n');
1539 offset -= gstring->from;
1541 for (gst = gstring; gst; gst = gst->next)
1545 gst->from += offset;
1547 for (i = 0; i < gst->used; i++)
1549 gst->glyphs[i].g.from += offset;
1550 gst->glyphs[i].g.to += offset;
1553 M17N_OBJECT_REF (gstring);
1558 int line = 0, y = 0;
1560 if (pos < mtext_nchars (mt))
1562 beg = mtext_character (mt, pos, 0, '\n');
1570 end = mtext_nchars (mt) + (control->cursor_width != 0);
1571 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1572 if (beg < mtext_nchars (mt))
1573 compose_glyph_string (frame, mt, beg, end, gstring);
1574 layout_glyph_string (frame, gstring);
1576 if (gstring->width_limit
1577 && gstring->width > gstring->width_limit)
1579 MGlyphString *gst = gstring;
1581 truncate_gstring (frame, mt, gst);
1582 while (gst->to < end)
1584 line++, y += gst->height;
1585 gst->next = alloc_gstring (frame, mt, gst->from, control,
1587 gst->next->top = gstring;
1588 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1590 layout_glyph_string (frame, gst);
1591 if (gst->width <= gst->width_limit)
1593 truncate_gstring (frame, mt, gst);
1597 if (! control->disable_caching && pos < mtext_nchars (mt))
1599 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1600 MTEXTPROP_VOLATILE_STRONG);
1602 if (end > mtext_nchars (mt))
1603 end = mtext_nchars (mt);
1604 mtext_attach_property (mt, beg, end, prop);
1605 M17N_OBJECT_UNREF (prop);
1609 while (gstring->to <= pos)
1611 if (! gstring->next)
1613 gstring = gstring->next;
1615 gstring->control = *control;
1621 static MDrawControl control_noop;
1623 #define ASSURE_CONTROL(control) \
1625 control = &control_noop; \
1630 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1631 MText *mt, int from, int to,
1632 MDrawControl *control)
1634 MGlyphString *gstring;
1636 M_CHECK_POS_X (mt, from, -1);
1637 ASSURE_CONTROL (control);
1638 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1639 to = mtext_nchars (mt) + (control->cursor_width != 0);
1643 gstring = get_gstring (frame, mt, from, to, control);
1645 MERROR (MERROR_DRAW, -1);
1646 render_glyph_string (frame, win, x, y, gstring, from, to);
1650 y += gstring->line_descent;
1651 M17N_OBJECT_UNREF (gstring->top);
1652 gstring = get_gstring (frame, mt, from, to, control);
1653 y += gstring->line_ascent;
1654 render_glyph_string (frame, win, x, y, gstring, from, to);
1657 M17N_OBJECT_UNREF (gstring->top);
1664 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1670 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1671 if (g->g.from <= pos && g->g.to > pos)
1676 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1677 if (g->g.from <= pos && g->g.to > pos)
1684 /* for debugging... */
1688 dump_gstring (MGlyphString *gstring, int indent, int type)
1690 char *prefix = (char *) alloca (indent + 1);
1691 MGlyph *g, *first_g, *last_g;
1693 memset (prefix, 32, indent);
1696 fprintf (stderr, "(glyph-string");
1700 first_g = MGLYPH (0);
1701 last_g = first_g + gstring->used;
1705 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1706 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1709 for (g = first_g; g < last_g; g++)
1712 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1715 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1716 : g->type == GLYPH_ANCHOR ? "ANC"
1717 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1718 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1719 g->g.xadv, g->bidi_level);
1720 if (g->g.xoff || g->g.yoff)
1721 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1722 fprintf (stderr, ")");
1724 fprintf (stderr, ")");
1728 /* m17n-X internal APIs */
1733 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1735 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1736 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1738 Mcommon = msymbol ("common");
1740 McatCc = msymbol ("Cc");
1741 McatCf = msymbol ("Cf");
1743 MbidiR = msymbol ("R");
1744 MbidiAL = msymbol ("AL");
1745 MbidiRLE = msymbol ("RLE");
1746 MbidiRLO = msymbol ("RLO");
1747 MbidiBN = msymbol ("BN");
1748 MbidiS = msymbol ("S");
1749 MbidiNSM = msymbol ("NSM");
1751 #if FRIBIDI_INTERFACE_VERSION < 3
1752 fribidi_set_mirroring (TRUE);
1754 fribidi_set_mirroring (1);
1758 M_break_at_space = msymbol ("bs");
1759 M_break_at_word = msymbol ("bw");
1760 M_break_at_any = msymbol ("ba");
1761 M_kinsoku_bol = msymbol ("kb");
1762 M_kinsoku_eol = msymbol ("ke");
1764 mflt_enable_new_feature = 1;
1772 MLIST_FREE1 (&scratch_gstring, glyphs);
1773 M17N_OBJECT_UNREF (linebreak_table);
1774 linebreak_table = NULL;
1778 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1782 /*** @addtogroup m17nDraw */
1787 @brief Draw an M-text on a window.
1789 The mdraw_text () function draws the text between $FROM and $TO of
1790 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1792 The appearance of the text (size, style, color, etc) is specified
1793 by the value of the text property whose key is @c Mface. If the
1794 M-text or a part of the M-text does not have such a text property,
1795 the default face of $FRAME is used.
1797 The font used to draw a character in the M-text is selected from
1798 the value of the fontset property of a face by the following
1803 <li> Search the text properties given to the character for the one
1804 whose key is @c Mcharset; its value should be either a symbol
1805 specifying a charset or #Mnil. If the value is #Mnil,
1806 proceed to the next step.
1808 Otherwise, search the mapping table of the fontset for the
1809 charset. If no entry is found proceed to the next step.
1811 If an entry is found, use one of the fonts in the entry that
1812 has a glyph for the character and that matches best with the
1813 face properties. If no such font exists, proceed to the next
1816 <li> Get the character property "script" of the character. If it is
1817 inherited, get the script property from the previous
1818 characters. If there is no previous character, or none of
1819 them has the script property other than inherited, proceed to
1822 Search the text properties given to the character for the one
1823 whose key is @c Mlanguage; its value should be either a
1824 symbol specifying a language or @c Mnil.
1826 Search the mapping table of the fontset for the combination
1827 of the script and language. If no entry is found, proceed to
1830 If an entry is found, use one of the fonts in the entry that
1831 has a glyph for the character and that matches best with the
1832 face properties. If no such font exists, proceed to the next
1835 <li> Search the fall-back table of the fontset for a font that has
1836 a glyph of the character. If such a font is found, use that
1841 If no font is found by the algorithm above, this function draws an
1842 empty box for the character.
1844 This function draws only the glyph foreground. To specify the
1845 background color, use mdraw_image_text () or
1846 mdraw_text_with_control ().
1848 This function is the counterpart of <tt>XDrawString ()</tt>,
1849 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1850 in the X Window System.
1853 If the operation was successful, mdraw_text () returns 0. If an
1854 error is detected, it returns -1 and assigns an error code to the
1855 external variable #merror_code. */
1857 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1859 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1860 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1862 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1863 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1864 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1865 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1867 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1868 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1872 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1873 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1874 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1875 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1876 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1877 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1879 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1880 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1882 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1883 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1884 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1886 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1887 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1889 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1890 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1892 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1893 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1895 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1896 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1900 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1902 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1903 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1905 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1906 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1909 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1910 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1912 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1919 mdraw_image_text () */
1922 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1923 MText *mt, int from, int to)
1925 MDrawControl control;
1927 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1928 memset (&control, 0, sizeof control);
1929 control.as_image = 0;
1930 return draw_text (frame, win, x, y, mt, from, to, &control);
1937 @brief Draw an M-text on a window as an image.
1939 The mdraw_image_text () function draws the text between $FROM and
1940 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1941 coordinate ($X, $Y).
1943 The way to draw a text is the same as in mdraw_text () except that
1944 this function also draws the background with the color specified
1947 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1948 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1949 functions in the X Window System.
1952 If the operation was successful, mdraw_image_text () returns 0.
1953 If an error is detected, it returns -1 and assigns an error code
1954 to the external variable #merror_code. */
1957 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1959 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1960 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1961 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1963 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1964 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1966 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1967 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1971 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1972 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1974 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1984 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1985 MText *mt, int from, int to)
1987 MDrawControl control;
1989 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1990 memset (&control, 0, sizeof control);
1991 control.as_image = 1;
1992 return draw_text (frame, win, x, y, mt, from, to, &control);
1998 @brief Draw an M-text on a window with fine control.
2000 The mdraw_text_with_control () function draws the text between
2001 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2002 coordinate ($X, $Y).
2004 The way to draw a text is the same as in mdraw_text () except that
2005 this function also follows what specified in the drawing control
2008 For instance, if \<two_dimensional\> of $CONTROL is nonzero, this
2009 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2010 breaks lines and the following characters are drawn in the next
2011 line. See the documentation of the structure @ MDrawControl for
2015 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2017 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2018 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2021 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2022 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2024 ¤¿¤È¤¨¤Ð $CONTROL ¤Î \<two_dimensional\> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2025 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2026 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2029 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2030 MText *mt, int from, int to, MDrawControl *control)
2032 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2033 return draw_text (frame, win, x, y, mt, from, to, control);
2039 @brief Compute text pixel width.
2041 The mdraw_text_extents () function computes the width of text
2042 between $FROM and $TO of M-text $MT when it is drawn on a window
2043 of frame $FRAME using the mdraw_text_with_control () function with
2044 the drawing control object $CONTROL.
2046 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2047 the bounding box of character ink of the M-text, and stores the
2048 results in the members of the structure pointed to by
2049 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2050 surrounding box, the box is included in the bounding box.
2052 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2053 computes the bounding box that provides minimum spacing to other
2054 graphical features (such as surrounding box) for the M-text, and
2055 stores the results in the members of the structure pointed to by
2056 $OVERALL_LOGICAL_RETURN.
2058 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2059 computes the bounding box that provides minimum spacing to the
2060 other M-text drawn, and stores the results in the members of the
2061 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2062 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2063 min_line_ascent, min_line_descent, max_line_ascent, and
2064 max_line_descent of $CONTROL are all zero.
2067 This function returns the width of the text to be drawn in the
2068 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2069 text is drawn in multiple physical lines, it returns the width of
2070 the widest line. If an error occurs, it returns -1 and assigns an
2071 error code to the external variable #merror_code. */
2075 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2077 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2078 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2079 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2081 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2082 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2083 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2084 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2086 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2087 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2088 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2089 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2091 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2092 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2093 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2094 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2095 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2096 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2099 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2100 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2101 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2103 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2110 mdraw_text_extents (MFrame *frame,
2111 MText *mt, int from, int to, MDrawControl *control,
2112 MDrawMetric *overall_ink_return,
2113 MDrawMetric *overall_logical_return,
2114 MDrawMetric *overall_line_return)
2116 MGlyphString *gstring;
2118 int width, lbearing, rbearing;
2120 ASSURE_CONTROL (control);
2121 M_CHECK_POS_X (mt, from, -1);
2122 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2123 to = mtext_nchars (mt) + (control->cursor_width != 0);
2127 gstring = get_gstring (frame, mt, from, to, control);
2129 MERROR (MERROR_DRAW, -1);
2130 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2131 if (overall_ink_return)
2132 overall_ink_return->y = - gstring->physical_ascent;
2133 if (overall_logical_return)
2134 overall_logical_return->y = - gstring->ascent;
2135 if (overall_line_return)
2136 overall_line_return->y = - gstring->line_ascent;
2138 for (from = gstring->to; from < to; from = gstring->to)
2140 int this_width, this_lbearing, this_rbearing;
2142 y += gstring->line_descent;
2143 M17N_OBJECT_UNREF (gstring->top);
2144 gstring = get_gstring (frame, mt, from, to, control);
2145 this_width = gstring_width (gstring, from, to,
2146 &this_lbearing, &this_rbearing);
2147 y += gstring->line_ascent;
2148 if (width < this_width)
2150 if (rbearing < this_rbearing)
2151 rbearing = this_rbearing;
2152 if (lbearing > this_lbearing)
2153 lbearing = this_lbearing;
2155 if (overall_ink_return)
2157 overall_ink_return->x = lbearing;
2158 overall_ink_return->width = rbearing - lbearing;
2159 overall_ink_return->height
2160 = y + gstring->physical_descent - overall_ink_return->y;
2162 if (overall_logical_return)
2164 overall_logical_return->x = 0;
2165 overall_logical_return->width = width;
2166 overall_logical_return->height
2167 = y + gstring->descent - overall_logical_return->y;
2169 if (overall_line_return)
2171 overall_line_return->x = lbearing;
2172 overall_line_return->width = MAX (width, rbearing - lbearing);
2173 overall_line_return->height
2174 = y + gstring->line_descent - overall_line_return->y;
2177 M17N_OBJECT_UNREF (gstring->top);
2184 @brief Compute the text dimensions of each character of M-text.
2186 The mdraw_text_per_char_extents () function computes the drawn
2187 metric of each character between $FROM and $TO of M-text $MT
2188 assuming that they are drawn on a window of frame $FRAME using the
2189 mdraw_text_with_control () function with the drawing control
2192 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2193 $LOGICAL_ARRAY_RETURN. Each successive element of
2194 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2195 ink and logical metrics of successive characters respectively,
2196 relative to the drawing origin of the M-text. The number of
2197 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2198 been set is returned to $NUM_CHARS_RETURN.
2200 If $ARRAY_SIZE is too small to return all metrics, the function
2201 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2202 Otherwise, it returns zero.
2204 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2205 @c NULL, this function also computes the metrics of the overall
2206 text and stores the results in the members of the structure
2207 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2209 If $CONTROL->two_dimensional is nonzero, this function computes
2210 only the metrics of characters in the first line. */
2212 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2214 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2215 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2216 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2218 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2219 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2220 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2221 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2222 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2224 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2225 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2228 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2229 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2230 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2232 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2235 mdraw_text_per_char_extents (MFrame *frame,
2236 MText *mt, int from, int to,
2237 MDrawControl *control,
2238 MDrawMetric *ink_array_return,
2239 MDrawMetric *logical_array_return,
2241 int *num_chars_return,
2242 MDrawMetric *overall_ink_return,
2243 MDrawMetric *overall_logical_return)
2245 MGlyphString *gstring;
2249 ASSURE_CONTROL (control);
2250 *num_chars_return = to - from;
2251 if (array_size < *num_chars_return)
2252 MERROR (MERROR_DRAW, -1);
2253 if (overall_logical_return)
2254 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2255 if (overall_ink_return)
2256 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2258 M_CHECK_RANGE (mt, from, to, -1, 0);
2259 gstring = get_gstring (frame, mt, from, to, control);
2262 *num_chars_return = 0;
2266 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2267 if (g->g.from >= from && g->g.from < to)
2269 int start = g->g.from;
2271 int width = g->g.xadv;
2272 int lbearing = g->g.lbearing;
2273 int rbearing = g->g.rbearing;
2274 int ascent = g->g.ascent;
2275 int descent = g->g.descent;
2277 int logical_descent;
2279 if (g->rface->rfont)
2281 logical_ascent = g->rface->rfont->ascent;
2282 logical_descent = g->rface->rfont->descent;
2286 logical_ascent = g->rface->ascent;
2287 logical_descent = g->rface->descent;
2289 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2291 if (lbearing < width + g->g.lbearing)
2292 lbearing = width + g->g.lbearing;
2293 if (rbearing < width + g->g.rbearing)
2294 rbearing = width + g->g.rbearing;
2296 if (ascent < g->g.ascent)
2297 ascent = g->g.ascent;
2298 if (descent < g->g.descent)
2299 descent = g->g.descent;
2306 if (ink_array_return)
2308 ink_array_return[start - from].x = x + lbearing;
2309 ink_array_return[start - from].y = - ascent;
2310 ink_array_return[start - from].width = rbearing - lbearing;
2311 ink_array_return[start - from].height = ascent + descent;
2313 if (logical_array_return)
2315 logical_array_return[start - from].x = x;
2316 logical_array_return[start - from].y = - logical_descent;
2317 logical_array_return[start - from].height
2318 = logical_ascent + logical_descent;
2319 logical_array_return[start - from].width = width;
2327 if (overall_ink_return)
2329 overall_ink_return->y = - gstring->line_ascent;
2330 overall_ink_return->x = gstring->lbearing;
2331 overall_ink_return->width = x - gstring->lbearing;
2332 overall_ink_return->height = gstring->height;
2334 if (overall_logical_return)
2336 overall_logical_return->y = - gstring->ascent;
2337 overall_logical_return->x = 0;
2338 overall_logical_return->width = x;
2339 overall_logical_return->height = gstring->ascent + gstring->descent;
2342 M17N_OBJECT_UNREF (gstring->top);
2349 @brief Return the character position nearest to the coordinates.
2351 The mdraw_coordinates_position () function checks which character
2352 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2353 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2354 mdraw_text_with_control () function with the drawing control
2355 object $CONTROL. Here, the character position means the number of
2356 characters that precede the character in question in $MT, that is,
2357 the character position of the first character is 0.
2359 $FRAME is used only to get the default face information.
2362 If the glyph image of a character covers coordinate ($X, $Y),
2363 mdraw_coordinates_position () returns the character position of
2365 If $Y is less than the minimum Y-coordinate of the drawn area, it
2367 If $Y is greater than the maximum Y-coordinate of the drawn area,
2369 If $Y fits in with the drawn area but $X is less than the minimum
2370 X-coordinate, it returns the character position of the first
2371 character drawn on the line $Y.\n\n
2372 If $Y fits in with the drawn area but $X is greater than the
2373 maximum X-coordinate, it returns the character position of the
2374 last character drawn on the line $Y. */
2377 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2379 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2380 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2381 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2382 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2383 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2384 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2386 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2389 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2390 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2392 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2393 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2394 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2395 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2396 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2399 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2400 int x_offset, int y_offset, MDrawControl *control)
2402 MGlyphString *gstring;
2407 M_CHECK_POS_X (mt, from, -1);
2408 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2409 to = mtext_nchars (mt) + (control->cursor_width != 0);
2415 ASSURE_CONTROL (control);
2416 gstring = get_gstring (frame, mt, from, to, control);
2417 while (y + gstring->line_descent <= y_offset
2418 && gstring->to < to)
2421 y += gstring->line_descent;
2422 M17N_OBJECT_UNREF (gstring->top);
2423 gstring = get_gstring (frame, mt, from, to, control);
2424 y += gstring->line_ascent;
2427 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2428 if (! control->orientation_reversed)
2430 width = gstring->indent;
2431 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2432 if (g->g.from >= from && g->g.from < to)
2435 if (width > x_offset)
2441 width = - gstring->indent;
2442 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2443 if (g->g.from >= from && g->g.from < to)
2446 if (width < x_offset)
2450 if (g->type == GLYPH_ANCHOR
2451 && control->two_dimensional
2452 && g[-1].g.c == '\n')
2455 M17N_OBJECT_UNREF (gstring->top);
2463 @brief Compute information about a glyph.
2465 The mdraw_glyph_info () function computes information about a
2466 glyph that covers a character at position $POS of the M-text $MT
2467 assuming that the text is drawn from the character at $FROM of $MT
2468 on a window of frame $FRAME using the mdraw_text_with_control ()
2469 function with the drawing control object $CONTROL.
2471 The information is stored in the members of $INFO. */
2473 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2475 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2476 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2477 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2478 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2480 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2488 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2489 MDrawControl *control, MDrawGlyphInfo *info)
2491 MGlyphString *gstring;
2495 M_CHECK_RANGE_X (mt, from, pos, -1);
2497 ASSURE_CONTROL (control);
2498 gstring = get_gstring (frame, mt, from, pos + 1, control);
2500 MERROR (MERROR_DRAW, -1);
2501 while (gstring->to <= pos)
2503 y += gstring->line_descent;
2504 M17N_OBJECT_UNREF (gstring->top);
2505 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2506 y += gstring->line_ascent;
2508 info->line_from = gstring->from;
2509 if (info->line_from < from)
2510 info->line_from = from;
2511 info->line_to = gstring->to;
2514 if (! control->orientation_reversed)
2516 info->x = gstring->indent;
2517 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2518 info->x += g->g.xadv;
2522 info->x = - gstring->indent;
2523 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2524 info->x -= g->g.xadv;
2525 while (g[-1].g.to == g->g.to)
2528 info->from = g->g.from;
2530 info->metrics.x = g->g.lbearing;
2531 info->metrics.y = - gstring->line_ascent;
2532 info->metrics.height = gstring->height;
2533 info->metrics.width = - g->g.lbearing + g->g.xadv;
2534 if (g->rface->rfont)
2535 info->font = (MFont *) g->rface->rfont;
2538 /* info->logical_width is calculated later. */
2540 if (info->from > info->line_from)
2542 /* The logically previous glyph is on this line. */
2543 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2545 info->prev_from = g_tmp->g.from;
2547 else if (info->line_from > 0
2548 && gstring->from > 0)
2550 /* The logically previous glyph is on the previous line. */
2551 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2552 gstring->from, control);
2553 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2555 info->prev_from = g_tmp->g.from;
2556 M17N_OBJECT_UNREF (gst->top);
2559 info->prev_from = -1;
2561 if (GLYPH_INDEX (g) > 1)
2562 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2563 else if (! control->orientation_reversed)
2565 if (info->line_from > 0)
2569 int p = gstring->from - 1;
2571 gst = get_gstring (frame, mt, p, gstring->from, control);
2572 g_tmp = gst->glyphs + (gst->used - 2);
2573 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2574 M17N_OBJECT_UNREF (gst->top);
2577 info->left_from = info->left_to = -1;
2581 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2585 int p = gstring->to;
2587 gst = get_gstring (frame, mt, p, p + 1, control);
2588 g_tmp = gst->glyphs + (gst->used - 2);
2589 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2590 M17N_OBJECT_UNREF (gst->top);
2593 info->left_from = info->left_to = -1;
2596 if (info->to < gstring->to)
2598 /* The logically next glyph is on this line. */
2599 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2601 info->next_to = g_tmp->g.to;
2603 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2605 /* The logically next glyph is on the next line. */
2607 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2608 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2610 info->next_to = g_tmp->g.to;
2611 M17N_OBJECT_UNREF (gst->top);
2616 for (info->logical_width = (g++)->g.xadv;
2617 g->g.from == pos && g->type != GLYPH_ANCHOR;
2618 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2619 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2621 if (g->type != GLYPH_ANCHOR)
2622 info->right_from = g->g.from, info->right_to = g->g.to;
2623 else if (! control->orientation_reversed)
2625 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2628 M17N_OBJECT_UNREF (gstring->top);
2629 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2631 info->right_from = g->g.from, info->right_to = g->g.to;
2634 info->right_from = info->right_to = -1;
2638 if (info->line_from > 0)
2640 pos = gstring->from - 1;
2641 M17N_OBJECT_UNREF (gstring->top);
2642 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2644 info->right_from = g->g.from, info->right_to = g->g.to;
2647 info->right_from = info->right_to = -1;
2650 M17N_OBJECT_UNREF (gstring->top);
2657 @brief Compute information about glyph sequence.
2659 The mdraw_glyph_list () function computes information about glyphs
2660 corresponding to the text between $FROM and $TO of M-text $MT when
2661 it is drawn on a window of frame $FRAME using the
2662 mdraw_text_with_control () function with the drawing control
2663 object $CONTROL. $GLYPHS is an array of objects to store the
2664 information, and $ARRAY_SIZE is the array size.
2666 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2667 number of actually filled elements in the place pointed by
2668 $NUM_GLYPHS_RETURN, and returns 0.
2670 Otherwise, it stores the required array size in the place pointed
2671 by $NUM_GLYPHS_RETURN, and returns -1. */
2674 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2676 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2677 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2678 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2679 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2681 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2682 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2685 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2695 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2696 MDrawControl *control, MDrawGlyph *glyphs,
2697 int array_size, int *num_glyphs_return)
2699 MGlyphString *gstring;
2704 ASSURE_CONTROL (control);
2705 *num_glyphs_return = 0;
2706 M_CHECK_RANGE (mt, from, to, -1, 0);
2707 gstring = get_gstring (frame, mt, from, to, control);
2710 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2712 if (g->type == GLYPH_BOX
2713 || g->g.from < from || g->g.from >= to)
2715 if (g->type == GLYPH_PAD)
2717 if (g->left_padding)
2718 pad_width = g->g.xadv;
2722 glyphs[-1].x_advance += g->g.xadv;
2728 glyphs->from = g->g.from;
2729 glyphs->to = g->g.to;
2730 glyphs->glyph_code = g->g.code;
2731 glyphs->x_off = g->g.xoff + pad_width;
2732 glyphs->y_off = g->g.yoff;
2733 glyphs->lbearing = g->g.lbearing;
2734 glyphs->rbearing = g->g.rbearing;
2735 glyphs->ascent = g->g.ascent;
2736 glyphs->descent = g->g.descent;
2737 glyphs->x_advance = g->g.xadv + pad_width;
2738 glyphs->y_advance = 0;
2739 if (g->rface->rfont)
2741 glyphs->font = (MFont *) g->rface->rfont;
2742 #ifdef HAVE_FREETYPE
2744 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2745 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2747 #else /* not HAVE_FREETYPE */
2748 glyphs->font_type = Mx;
2749 #endif /* not HAVE_FREETYPE */
2750 glyphs->fontp = g->rface->rfont->fontp;
2754 glyphs->font = NULL;
2755 glyphs->font_type = Mnil;
2756 glyphs->fontp = NULL;
2763 M17N_OBJECT_UNREF (gstring->top);
2765 *num_glyphs_return = n;
2766 return (n <= array_size ? 0 : -1);
2772 @brief Draw one or more textitems.
2774 The mdraw_text_items () function draws one or more M-texts on
2775 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2776 of the textitems to be drawn and $NITEMS is the number of
2777 textitems in the array. */
2780 @brief textitem ¤òɽ¼¨¤¹¤ë.
2782 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2783 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2784 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2786 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2790 MTextItem, mdraw_text (). */
2793 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2794 MDrawTextItem *items, int nitems)
2796 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2798 while (nitems-- > 0)
2801 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2803 mdraw_text_with_control (frame, win, x, y,
2804 items->mt, 0, mtext_nchars (items->mt),
2806 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2807 items->control, NULL, NULL, NULL);
2810 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2816 @brief Option of line breaking for drawing text.
2818 The variable #mdraw_line_break_option specifies line breaking
2819 options by logical-or of the members of #MTextLineBreakOption. It
2820 controls the line breaking algorithm of the function
2821 mdraw_default_line_break (). */
2823 int mdraw_line_break_option;
2827 @brief Calculate a line breaking position.
2829 The function mdraw_default_line_break () calculates a line
2830 breaking position based on the line number $LINE and the
2831 coordinate $Y, when a line is too long to fit within the width
2832 limit. $POS is the position of the character next to the last one
2833 that fits within the limit. $FROM is the position of the first
2834 character of the line, and $TO is the position of the last
2835 character displayed on the line if there were not width limit.
2836 $LINE and $Y are reset to 0 when a line is broken by a newline
2837 character, and incremented each time when a long line is broken
2838 because of the width limit.
2841 This function returns a character position to break the
2846 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2848 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2849 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2850 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2851 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2852 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2853 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2854 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2857 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2861 mdraw_default_line_break (MText *mt, int pos,
2862 int from, int to, int line, int y)
2866 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2877 @brief Obtain per character dimension information.
2879 The mdraw_per_char_extents () function computes the text dimension
2880 of each character in M-text $MT. The faces given as text
2881 properties in $MT and the default face of frame $FRAME determine
2882 the fonts to draw the text. Each successive element in
2883 $ARRAY_RETURN is set to the drawn metrics of successive
2884 characters, which is relative to the origin of the drawing, and a
2885 rectangle for each character in $MT. The number of elements of
2886 $ARRAY_RETURN must be equal to or greater than the number of
2889 If pointer $OVERALL_RETURN is not @c NULL, this function also
2890 computes the extents of the overall text and stores the results in
2891 the members of the structure pointed to by $OVERALL_RETURN. */
2894 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2896 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2897 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2898 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2899 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2900 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2901 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2902 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2904 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2905 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2906 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2908 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2911 mdraw_per_char_extents (MFrame *frame, MText *mt,
2912 MDrawMetric *array_return,
2913 MDrawMetric *overall_return)
2915 int n = mtext_nchars (mt);
2917 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2918 n, &n, overall_return, NULL);
2922 @brief clear cached information.
2924 The mdraw_clear_cache () function clear cached information
2925 on M-text $MT that was attached by any of the drawing functions.
2926 When the behavior of `format' or `line_break'
2927 member functions of MDrawControl is changed, the cache must be cleared.
2932 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2934 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2935 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2936 ¤¢¤ë¤¤¤Ï `line_break'
2937 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2943 mdraw_clear_cache (MText *mt)
2945 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);