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)
489 if (pos == stop || script != this_script || g->rface->rfont != rfont)
492 last_g = mface__for_chars (script, language, charset,
494 script = this_script;
495 if (script != Mnil && script != Mlatin)
496 non_latin_script = script;
497 rfont = g->rface->ascii_rface->rfont;
500 if (pos < mtext_nchars (mt) && pos == language_change)
502 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
503 mtext_prop_range (mt, Mlanguage, pos, NULL,
504 &language_change, 0);
506 if (pos < mtext_nchars (mt) && pos == charset_change)
508 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
509 mtext_prop_range (mt, Mcharset, pos, NULL,
513 if (stop > language_change)
514 stop = language_change;
515 if (stop > charset_change)
516 stop = charset_change;
521 last_g = mface__for_chars (script, language, charset, last_g, g, size);
523 /* The next loop is to run FLT or perform the default combining if
525 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
529 if (this->type == GLYPH_CHAR && this->rface->rfont)
533 if (this->rface->layouter != Mnil)
535 MGlyph *prev = MGLYPH (start - 1);
537 while (prev->type == GLYPH_CHAR
538 && prev->category == GLYPH_CATEGORY_FORMATTER
539 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
541 != MCHAR_INVALID_CODE))
543 prev->rface->rfont = this->rface->rfont;
548 (g->type == GLYPH_CHAR
549 && g->g.from != gstring->control.cursor_pos
550 && g->rface->layouter == this->rface->layouter
551 && (g->rface->rfont == this->rface->rfont
552 || (g->category == GLYPH_CATEGORY_FORMATTER
553 && (mfont__encode_char (NULL,
554 (MFont *) this->rface->rfont,
556 != MCHAR_INVALID_CODE))));
558 g->rface->rfont = this->rface->rfont;
559 i = run_flt (gstring, start, i, this->rface);
564 while (g->type == GLYPH_CHAR
566 && g->category == GLYPH_CATEGORY_MODIFIER
568 && g->rface->layouter == Mnil)
572 this->rface->layouter = Mcombining;
573 run_flt (gstring, start, i, this->rface);
576 mfont__get_metric (gstring, start, i);
584 /* At last, reorder glyphs visually if necessary. */
585 if (max_bidi_level > 0)
586 visual_order (gstring);
590 int width, lbearing, rbearing;
594 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
595 MSubTextExtents *extents)
597 int g_physical_ascent, g_physical_descent;
598 MGlyph *g = MGLYPH (from);
599 MGlyph *last_g = MGLYPH (to);
601 g_physical_ascent = gstring->physical_ascent;
602 g_physical_descent = gstring->physical_descent;
603 extents->width = extents->lbearing = extents->rbearing = 0;
605 for (g = MGLYPH (from); g < last_g; g++)
607 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
608 g_physical_descent = MAX (g_physical_descent, g->g.descent);
609 extents->lbearing = MIN (extents->lbearing,
610 extents->width + g->g.lbearing);
611 extents->rbearing = MAX (extents->rbearing,
612 extents->width + g->g.rbearing);
613 extents->width += g->g.xadv;
616 gstring->physical_ascent = g_physical_ascent;
617 gstring->physical_descent = g_physical_descent;
621 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
622 by this function directly. Character glyphs are handled by
623 layouter functions registered in font drivers.
625 This function fill-in all the remaining members of glyphs. */
628 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
630 /* Default width of TAB. */
631 int tab_width = frame->space_width * (gstring->control.tab_width
632 ? gstring->control.tab_width : 8);
636 MDrawControl *control = &(gstring->control);
639 int box_line_height = 0;
640 int ignore_formatting_char = control->ignore_formatting_char;
642 gstring->ascent = gstring->descent = 0;
643 gstring->physical_ascent = gstring->physical_descent = 0;
644 gstring->width = gstring->lbearing = gstring->rbearing = 0;
648 while (g->type != GLYPH_ANCHOR)
650 if (box != g->rface->box)
652 int gidx = GLYPH_INDEX (g);
656 /* Insert the right side of the box. That glyph belongs
657 to the previous grapheme cluster. */
658 MGlyph box_glyph = g[-1];
660 box_glyph.type = GLYPH_BOX;
662 = (control->fixed_width
664 : box->inner_hmargin + box->width + box->outer_hmargin);
665 box_glyph.g.lbearing = 0;
666 box_glyph.g.rbearing = box_glyph.g.xadv;
667 box_glyph.g.xoff = 0;
668 box_glyph.right_padding = 1;
669 gstring->width += box_glyph.g.xadv;
670 gstring->rbearing += box_glyph.g.xadv;
671 INSERT_GLYPH (gstring, gidx, box_glyph);
678 /* Insert the left side of the box. That glyph belongs
679 to the following grapheme cluster. */
680 MGlyph box_glyph = *g;
681 int box_height = (box->width
682 + box->inner_vmargin + box->outer_vmargin);
684 if (box_line_height < box_height)
685 box_line_height = box_height;
686 box_glyph.type = GLYPH_BOX;
688 = (control->fixed_width
690 : box->inner_hmargin + box->width + box->outer_hmargin);
691 box_glyph.g.lbearing = 0;
692 box_glyph.g.rbearing = box_glyph.g.xadv;
693 box_glyph.g.xoff = 0;
694 box_glyph.left_padding = 1;
695 gstring->width += box_glyph.g.xadv;
696 gstring->rbearing += box_glyph.g.xadv;
697 INSERT_GLYPH (gstring, gidx, box_glyph);
703 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
704 g->type = GLYPH_SPACE;
706 if (g->type == GLYPH_CHAR)
708 MRealizedFace *rface = g->rface;
709 MRealizedFont *rfont = rface->rfont;
711 int from = GLYPH_INDEX (g);
713 for (g++; g->type == GLYPH_CHAR; g++)
714 if (! rfont != ! g->rface->rfont
715 || box != g->rface->box
716 || ((fromg->g.code == MCHAR_INVALID_CODE)
717 != (g->g.code == MCHAR_INVALID_CODE))
718 || (g->category == GLYPH_CATEGORY_FORMATTER
719 && ignore_formatting_char))
721 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
724 int to = GLYPH_INDEX (g);
725 MSubTextExtents extents;
727 layout_glyphs (frame, gstring, from, to, &extents);
728 extra_width = - extents.lbearing;
730 && ! control->disable_overlapping_adjustment
731 && (! control->orientation_reversed
732 ? ((to > 1 || control->align_head)
733 && g->type != GLYPH_ANCHOR)
734 : (((g->type && GLYPH_ANCHOR) || control->align_head)
739 pad.type = GLYPH_PAD;
742 pad.g.xadv = pad.g.rbearing = extra_width;
743 pad.left_padding = 1;
744 INSERT_GLYPH (gstring, from, pad);
746 extents.lbearing = 0;
747 extents.width += extra_width;
748 extents.rbearing += extra_width;
750 g = MGLYPH (from - 1);
751 if (g->type == GLYPH_SPACE)
753 /* The pad just inserted is absorbed (maybe
754 partially) by the previous space while
755 keeping at least some space width. For the
756 moment, we use the arbitrary width 2-pixel.
757 Perhaps, it should be decided by the current
758 face, or a default value of the current
759 frame, which is, however, not yet
761 if (extra_width + 2 < g->g.xadv)
763 g->g.xadv -= extra_width;
767 extra_width = g->g.xadv - 2;
770 gstring->width -= extra_width;
771 gstring->rbearing -= extra_width;
776 extra_width = extents.rbearing - extents.width;
778 && ! control->disable_overlapping_adjustment
779 && (GLYPH_INDEX (g) < gstring->used - 1
780 || (control->orientation_reversed && control->align_head)))
782 if (g->type == GLYPH_SPACE && box == g->rface->box)
785 pad.type = GLYPH_PAD;
788 pad.g.xadv = pad.g.rbearing = extra_width;
789 INSERT_GLYPH (gstring, to, pad);
794 g[-1].g.xadv += extra_width;
795 extents.width += extra_width;
798 if (gstring->lbearing > gstring->width + extents.lbearing)
799 gstring->lbearing = gstring->width + extents.lbearing;
800 if (gstring->rbearing < gstring->width + extents.rbearing)
801 gstring->rbearing = gstring->width + extents.rbearing;
802 gstring->width += extents.width;
803 if (gstring->ascent < rface->ascent)
804 gstring->ascent = rface->ascent;
805 if (gstring->descent < rface->descent)
806 gstring->descent = rface->descent;
810 for (; fromg < g; fromg++)
812 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
813 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
814 fromg->g.xadv = fromg->g.rbearing = 1;
816 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
817 fromg->g.xoff = fromg->g.lbearing = 0;
818 fromg->g.ascent = fromg->g.descent = 0;
819 gstring->width += fromg->g.xadv;
820 gstring->rbearing += fromg->g.xadv;
822 if (gstring->ascent < frame->rface->ascent)
823 gstring->ascent = frame->rface->ascent;
824 if (gstring->descent < frame->descent)
825 gstring->descent = frame->rface->descent;
828 else if (g->type == GLYPH_SPACE)
831 g->g.xadv = g->rface->space_width;
832 else if (g->g.c == '\n')
834 g->g.xadv = control->cursor_width;
837 if (control->cursor_bidi)
839 else if (g->g.xadv < 0)
840 g->g.xadv = g->rface->space_width;
843 else if (g->g.c == '\t')
845 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
851 if (g[-1].type == GLYPH_PAD)
853 /* This space glyph absorbs (maybe partially) the
854 previous padding glyph. */
855 g->g.xadv -= g[-1].g.xadv;
857 /* But, keep at least some space width. For the
858 moment, we use the arbitrary width 2-pixel. */
861 g->g.rbearing = g->g.xadv;
862 gstring->width += g->g.xadv;
863 gstring->rbearing += g->g.xadv;
866 if (gstring->ascent < g->rface->ascent)
867 gstring->ascent = g->rface->ascent;
868 if (gstring->descent < g->rface->descent)
869 gstring->descent = g->rface->descent;
875 gstring->width += g->g.xadv;
876 gstring->rbearing += g->g.xadv;
883 /* Insert the right side of the box. */
884 int gidx = GLYPH_INDEX (g);
885 MGlyph box_glyph = g[-1];
887 box_glyph.type = GLYPH_BOX;
889 = (control->fixed_width
891 : box->inner_hmargin + box->width + box->outer_hmargin);
892 box_glyph.g.lbearing = 0;
893 box_glyph.g.rbearing = box_glyph.g.xadv;
894 box_glyph.g.xoff = 0;
895 box_glyph.right_padding = 1;
896 gstring->width += box_glyph.g.xadv;
897 gstring->rbearing += box_glyph.g.xadv;
898 INSERT_GLYPH (gstring, gidx, box_glyph);
901 gstring->text_ascent = gstring->ascent;
902 gstring->text_descent = gstring->descent;
903 if (gstring->text_ascent < gstring->physical_ascent)
904 gstring->text_ascent = gstring->physical_ascent;
905 if (gstring->text_descent < gstring->physical_descent)
906 gstring->text_descent = gstring->physical_descent;
907 gstring->line_ascent = gstring->text_ascent;
908 gstring->line_descent = gstring->text_descent;
909 if (box_line_height > 0)
911 gstring->line_ascent += box_line_height;
912 gstring->physical_ascent = gstring->line_ascent;
913 gstring->line_descent += box_line_height;
914 gstring->physical_descent = gstring->line_descent;
917 if (gstring->line_ascent < control->min_line_ascent)
918 gstring->line_ascent = control->min_line_ascent;
919 else if (control->max_line_ascent
920 && control->max_line_ascent > control->min_line_ascent
921 && gstring->line_ascent > control->max_line_ascent)
922 gstring->line_ascent = control->max_line_ascent;
924 if (gstring->line_descent < control->min_line_descent)
925 gstring->line_descent = control->min_line_descent;
926 else if (control->max_line_descent
927 && control->max_line_descent > control->min_line_descent
928 && gstring->line_descent > control->max_line_descent)
929 gstring->line_descent = control->max_line_descent;
930 gstring->height = gstring->line_ascent + gstring->line_descent;
932 if (control->orientation_reversed
935 /* We must adjust TAB width for RTL orientation. */
936 width = gstring->indent;
938 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
940 if (g->type == GLYPH_CHAR && g->g.c == '\t')
942 int this_width = tab_width - (width % tab_width);
944 if (g[1].type == GLYPH_PAD)
945 this_width -= g[1].g.xadv;
946 if (g[-1].type == GLYPH_PAD)
947 this_width -= g[-1].g.xadv;
950 gstring->width += this_width - g->g.xadv;
951 gstring->rbearing += this_width - g->g.xadv;
952 g->g.xadv = this_width;
963 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
964 MGlyphString *gstring, int from, int to,
965 int *from_idx, int *to_idx, int *to_x)
967 MGlyph *g = MGLYPH (1);
968 MDrawRegion region = (MDrawRegion) NULL;
969 MDrawControl *control = &gstring->control;
972 int cursor_bidi = control->cursor_bidi;
974 if (control->with_cursor && control->cursor_width)
976 if (gstring->from <= control->cursor_pos
977 && gstring->to > control->cursor_pos)
978 cursor_pos = control->cursor_pos;
981 && gstring->from <= control->cursor_pos - 1
982 && gstring->to > control->cursor_pos - 1)
983 prev_pos = control->cursor_pos - 1;
986 *from_idx = *to_idx = 0;
988 while (g->type != GLYPH_ANCHOR)
990 if (g->g.from >= from && g->g.from < to)
992 MGlyph *fromg = g, *cursor = NULL;
993 MRealizedFace *rface = g->rface;
995 int cursor_width = 0;
999 *from_idx = GLYPH_INDEX (g);
1000 while (g->g.from >= from && g->g.from < to
1001 && g->rface == rface)
1004 if (g->type != GLYPH_BOX
1005 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1008 cursor = g, cursor_x = x + width;
1009 cursor_width += g->g.xadv;
1011 width += g++->g.xadv;
1014 && (control->as_image
1015 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1017 int this_x = x, this_width = width;
1019 if (fromg->type == GLYPH_BOX)
1020 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1021 if (g[-1].type == GLYPH_BOX)
1022 this_width -= g[-1].g.xadv;
1023 (frame->driver->fill_space)
1024 (frame, win, rface, 0,
1025 this_x, y - gstring->text_ascent, this_width,
1026 gstring->text_ascent + gstring->text_descent,
1027 control->clip_region);
1034 rect.y = y - gstring->text_ascent;
1035 rect.height = gstring->text_ascent + gstring->text_descent;
1038 rect.width = ((control->cursor_width > 0
1039 && control->cursor_width < cursor_width)
1040 ? control->cursor_width : cursor_width);
1044 if (cursor->bidi_level % 2)
1045 rect.x += cursor_width - rect.width;
1046 (*frame->driver->fill_space)
1047 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1048 control->clip_region);
1050 region = (*frame->driver->region_from_rect) (&rect);
1052 (*frame->driver->region_add_rect) (region, &rect);
1055 if (cursor->bidi_level % 2)
1058 rect.width = cursor_width < 4 ? cursor_width : 4;
1059 (*frame->driver->fill_space)
1060 (frame, win, rface, 1,
1061 rect.x, rect.y, rect.width, rect.height,
1062 control->clip_region);
1063 (*frame->driver->region_add_rect) (region, &rect);
1075 if (fromg->type != GLYPH_BOX
1076 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1079 cursor = fromg, cursor_x = x + temp_width;
1080 cursor_width += fromg->g.xadv;
1082 temp_width += fromg++->g.xadv;
1089 if (! (cursor->bidi_level % 2))
1090 rect.x += cursor_width - 1;
1091 rect.y = y - gstring->text_ascent;
1092 rect.height = gstring->text_ascent + gstring->text_descent;
1094 (*frame->driver->fill_space)
1095 (frame, win, rface, 1,
1096 rect.x, rect.y, rect.width, rect.height,
1097 control->clip_region);
1099 region = (*frame->driver->region_from_rect) (&rect);
1101 (*frame->driver->region_add_rect) (region, &rect);
1102 rect.y += rect.height - 2;
1104 rect.width = cursor_width < 4 ? cursor_width : 4;
1105 if (! (cursor->bidi_level % 2))
1106 rect.x -= rect.width - 1;
1107 (*frame->driver->fill_space) (frame, win, rface, 1,
1108 rect.x, rect.y, rect.width, rect.height,
1109 control->clip_region);
1110 (*frame->driver->region_add_rect) (region, &rect);
1114 *to_idx = GLYPH_INDEX (g);
1124 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1125 MGlyphString *gstring, int from_idx, int to_idx,
1126 int reverse, MDrawRegion region)
1128 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1134 (*frame->driver->region_to_rect) (region, &rect);
1137 while (g != gend && x + g->g.rbearing <= rect.x)
1140 width -= g++->g.xadv;
1141 while (! g->enabled && g != gend)
1145 rect.x += rect.width;
1146 if (rect.x < x + width)
1149 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1151 width -= (--gend)->g.xadv;
1152 while (! gend->enabled && g != gend)
1156 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1165 MRealizedFace *rface = g->rface;
1166 int width = g->g.xadv;
1167 MGlyph *from_g = g++;
1169 /* Handle the glyphs of the same type/face at once. */
1171 && g->type == from_g->type
1172 && g->rface == rface
1173 && ((g->g.code == MCHAR_INVALID_CODE)
1174 == (from_g->g.code == MCHAR_INVALID_CODE))
1176 width += g++->g.xadv;
1178 if (from_g->type == GLYPH_CHAR)
1180 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1181 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1184 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1187 else if (from_g->type == GLYPH_BOX)
1189 /* Draw the left or right side of a box. If
1190 from_g->lbearing is nonzero, this is the left side,
1191 else this is the right side. */
1192 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1195 if (from_g->type != GLYPH_BOX)
1198 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1199 x, y, width, region);
1202 /* Draw the top and bottom side of a box. */
1203 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1204 x, y, width, region);
1215 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1216 int *from_x, int *to_x)
1219 int left_idx = *left, right_idx = *right;
1220 int left_x, right_x, x;
1222 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1225 if (x + g->g.rbearing > 0)
1227 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1229 left_idx = GLYPH_INDEX (g);
1234 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1237 if (x - g->g.xadv + g->g.lbearing < 0)
1239 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1241 right_idx = GLYPH_INDEX (g) + 1;
1246 if (*left == left_idx && *right == right_idx)
1249 if (*left != left_idx)
1251 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1256 if (*right != right_idx)
1258 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1268 gstring_width (MGlyphString *gstring, int from, int to,
1269 int *lbearing, int *rbearing)
1274 if (from <= gstring->from && to >= gstring->to)
1277 *lbearing = gstring->lbearing;
1279 *rbearing = gstring->rbearing;
1280 return gstring->width;
1287 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1288 if (g->g.from >= from && g->g.from < to)
1290 if (lbearing && width + g->g.lbearing < *lbearing)
1291 *lbearing = width + g->g.lbearing;
1292 if (rbearing && width + g->g.rbearing > *rbearing)
1293 *rbearing = width + g->g.rbearing;
1301 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1302 MGlyphString *gstring, int from, int to)
1304 MDrawControl *control = &gstring->control;
1306 MDrawRegion clip_region, cursor_region;
1307 int from_idx, to_idx;
1312 if (control->orientation_reversed)
1313 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1315 x += gstring->indent;
1317 /* At first, draw all glyphs without cursor. */
1318 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1319 &from_idx, &to_idx, &to_x);
1321 if (control->partial_update)
1324 rect.width = to_x - x;
1325 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1327 rect.y = y - gstring->line_ascent;
1328 rect.height = gstring->height;
1329 clip_region = (*frame->driver->region_from_rect) (&rect);
1330 if (control->clip_region)
1331 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1334 clip_region = control->clip_region;
1337 clip_region = control->clip_region;
1339 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1344 (*frame->driver->intersect_region) (cursor_region, clip_region);
1345 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1348 if (clip_region != control->clip_region)
1349 (*frame->driver->free_region) (clip_region);
1351 (*frame->driver->free_region) (cursor_region);
1355 static int gstring_num;
1358 free_gstring (void *object)
1360 MGlyphString *gstring = (MGlyphString *) object;
1363 free_gstring (gstring->next);
1364 if (gstring->size > 0)
1365 free (gstring->glyphs);
1371 static MGlyphString scratch_gstring;
1373 static MGlyphString *
1374 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1377 MGlyphString *gstring;
1379 if (pos == mt->nchars)
1383 gstring = &scratch_gstring;
1384 if (gstring->size == 0)
1389 g_tmp.type = GLYPH_ANCHOR;
1390 APPEND_GLYPH (gstring, g_tmp);
1391 APPEND_GLYPH (gstring, g_tmp);
1392 APPEND_GLYPH (gstring, g_tmp);
1393 gstring->glyphs[1].type = GLYPH_SPACE;
1394 gstring->glyphs[1].g.c = '\n';
1395 gstring->glyphs[1].g.code = '\n';
1397 gstring->from = pos;
1399 g->rface = frame->rface;
1400 g->g.from = g->g.to = pos;
1402 g->rface = frame->rface;
1403 g->g.from = pos++, g->g.to = pos;
1405 g->rface = frame->rface;
1406 g->g.from = g->g.to = pos;
1411 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1412 MLIST_INIT1 (gstring, glyphs, 128);
1416 gstring->frame = frame;
1417 gstring->tick = frame->tick;
1418 gstring->top = gstring;
1419 gstring->control = *control;
1420 gstring->indent = gstring->width_limit = 0;
1421 if (control->format)
1422 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1424 gstring->width_limit = control->max_line_width;
1425 gstring->anti_alias = control->anti_alias;
1429 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1432 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1435 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1443 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1444 a width of glyphs for the character at I of MT. If I is not a
1445 beginning of a grapheme cluster, the corresponding element is
1447 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1448 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1449 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1450 pos_width[g->g.from - gstring->from] += g->g.xadv;
1451 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1453 if (pos_width[i] > 0)
1455 if (width + pos_width[i] > gstring->width_limit)
1458 width += pos_width[i];
1461 pos = gstring->from + i;
1462 if (gstring->control.line_break)
1464 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1465 gstring->from, gstring->from + i,
1467 if (pos <= gstring->from)
1469 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1472 else if (pos >= gstring->to)
1477 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1480 if (pos < gstring->to)
1482 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1483 layout_glyph_string (frame, gstring);
1488 /* Return a gstring that covers a character at POS. */
1490 static MGlyphString *
1491 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1493 MGlyphString *gstring = NULL;
1495 if (pos < mtext_nchars (mt))
1497 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1500 && ((prop->start != 0
1501 && mtext_ref_char (mt, prop->start - 1) != '\n')
1502 || (prop->end < mtext_nchars (mt)
1503 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1505 mtext_detach_property (prop);
1510 gstring = prop->val;
1511 if (gstring->frame != frame
1512 || gstring->tick != frame->tick
1513 || memcmp (control, &gstring->control,
1514 (char *) (&control->with_cursor)
1515 - (char *) (control))
1516 || control->cursor_pos != gstring->control.cursor_pos
1517 || control->cursor_width != gstring->control.cursor_width
1518 || control->cursor_bidi != gstring->control.cursor_bidi)
1520 mtext_detach_property (prop);
1525 else if (! control->cursor_width)
1533 offset = mtext_character (mt, pos, 0, '\n');
1538 offset -= gstring->from;
1540 for (gst = gstring; gst; gst = gst->next)
1544 gst->from += offset;
1546 for (i = 0; i < gst->used; i++)
1548 gst->glyphs[i].g.from += offset;
1549 gst->glyphs[i].g.to += offset;
1552 M17N_OBJECT_REF (gstring);
1557 int line = 0, y = 0;
1559 if (pos < mtext_nchars (mt))
1561 beg = mtext_character (mt, pos, 0, '\n');
1569 end = mtext_nchars (mt) + (control->cursor_width != 0);
1570 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1571 if (beg < mtext_nchars (mt))
1572 compose_glyph_string (frame, mt, beg, end, gstring);
1573 layout_glyph_string (frame, gstring);
1575 if (gstring->width_limit
1576 && gstring->width > gstring->width_limit)
1578 MGlyphString *gst = gstring;
1580 truncate_gstring (frame, mt, gst);
1581 while (gst->to < end)
1583 line++, y += gst->height;
1584 gst->next = alloc_gstring (frame, mt, gst->from, control,
1586 gst->next->top = gstring;
1587 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1589 layout_glyph_string (frame, gst);
1590 if (gst->width <= gst->width_limit)
1592 truncate_gstring (frame, mt, gst);
1596 if (! control->disable_caching && pos < mtext_nchars (mt))
1598 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1599 MTEXTPROP_VOLATILE_STRONG);
1601 if (end > mtext_nchars (mt))
1602 end = mtext_nchars (mt);
1603 mtext_attach_property (mt, beg, end, prop);
1604 M17N_OBJECT_UNREF (prop);
1608 while (gstring->to <= pos)
1610 if (! gstring->next)
1612 gstring = gstring->next;
1614 gstring->control = *control;
1620 static MDrawControl control_noop;
1622 #define ASSURE_CONTROL(control) \
1624 control = &control_noop; \
1629 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1630 MText *mt, int from, int to,
1631 MDrawControl *control)
1633 MGlyphString *gstring;
1635 M_CHECK_POS_X (mt, from, -1);
1636 ASSURE_CONTROL (control);
1637 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1638 to = mtext_nchars (mt) + (control->cursor_width != 0);
1642 gstring = get_gstring (frame, mt, from, to, control);
1644 MERROR (MERROR_DRAW, -1);
1645 render_glyph_string (frame, win, x, y, gstring, from, to);
1649 y += gstring->line_descent;
1650 M17N_OBJECT_UNREF (gstring->top);
1651 gstring = get_gstring (frame, mt, from, to, control);
1652 y += gstring->line_ascent;
1653 render_glyph_string (frame, win, x, y, gstring, from, to);
1656 M17N_OBJECT_UNREF (gstring->top);
1663 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1669 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1670 if (g->g.from <= pos && g->g.to > pos)
1675 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1676 if (g->g.from <= pos && g->g.to > pos)
1683 /* for debugging... */
1687 dump_gstring (MGlyphString *gstring, int indent, int type)
1689 char *prefix = (char *) alloca (indent + 1);
1690 MGlyph *g, *first_g, *last_g;
1692 memset (prefix, 32, indent);
1695 fprintf (stderr, "(glyph-string");
1699 first_g = MGLYPH (0);
1700 last_g = first_g + gstring->used;
1704 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1705 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1708 for (g = first_g; g < last_g; g++)
1711 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1714 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1715 : g->type == GLYPH_ANCHOR ? "ANC"
1716 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1717 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1718 g->g.xadv, g->bidi_level);
1719 if (g->g.xoff || g->g.yoff)
1720 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1721 fprintf (stderr, ")");
1723 fprintf (stderr, ")");
1727 /* m17n-X internal APIs */
1732 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1734 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1735 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1737 Mcommon = msymbol ("common");
1739 McatCc = msymbol ("Cc");
1740 McatCf = msymbol ("Cf");
1742 MbidiR = msymbol ("R");
1743 MbidiAL = msymbol ("AL");
1744 MbidiRLE = msymbol ("RLE");
1745 MbidiRLO = msymbol ("RLO");
1746 MbidiBN = msymbol ("BN");
1747 MbidiS = msymbol ("S");
1748 MbidiNSM = msymbol ("NSM");
1750 #if FRIBIDI_INTERFACE_VERSION < 3
1751 fribidi_set_mirroring (TRUE);
1753 fribidi_set_mirroring (1);
1757 M_break_at_space = msymbol ("bs");
1758 M_break_at_word = msymbol ("bw");
1759 M_break_at_any = msymbol ("ba");
1760 M_kinsoku_bol = msymbol ("kb");
1761 M_kinsoku_eol = msymbol ("ke");
1763 mflt_enable_new_feature = 1;
1771 MLIST_FREE1 (&scratch_gstring, glyphs);
1772 M17N_OBJECT_UNREF (linebreak_table);
1773 linebreak_table = NULL;
1777 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1781 /*** @addtogroup m17nDraw */
1786 @brief Draw an M-text on a window.
1788 The mdraw_text () function draws the text between $FROM and $TO of
1789 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1791 The appearance of the text (size, style, color, etc) is specified
1792 by the value of the text property whose key is @c Mface. If the
1793 M-text or a part of the M-text does not have such a text property,
1794 the default face of $FRAME is used.
1796 The font used to draw a character in the M-text is selected from
1797 the value of the fontset property of a face by the following
1802 <li> Search the text properties given to the character for the one
1803 whose key is @c Mcharset; its value should be either a symbol
1804 specifying a charset or #Mnil. If the value is #Mnil,
1805 proceed to the next step.
1807 Otherwise, search the mapping table of the fontset for the
1808 charset. If no entry is found proceed to the next step.
1810 If an entry is found, use one of the fonts in the entry that
1811 has a glyph for the character and that matches best with the
1812 face properties. If no such font exists, proceed to the next
1815 <li> Get the character property "script" of the character. If it is
1816 inherited, get the script property from the previous
1817 characters. If there is no previous character, or none of
1818 them has the script property other than inherited, proceed to
1821 Search the text properties given to the character for the one
1822 whose key is @c Mlanguage; its value should be either a
1823 symbol specifying a language or @c Mnil.
1825 Search the mapping table of the fontset for the combination
1826 of the script and language. If no entry is found, proceed to
1829 If an entry is found, use one of the fonts in the entry that
1830 has a glyph for the character and that matches best with the
1831 face properties. If no such font exists, proceed to the next
1834 <li> Search the fall-back table of the fontset for a font that has
1835 a glyph of the character. If such a font is found, use that
1840 If no font is found by the algorithm above, this function draws an
1841 empty box for the character.
1843 This function draws only the glyph foreground. To specify the
1844 background color, use mdraw_image_text () or
1845 mdraw_text_with_control ().
1847 This function is the counterpart of <tt>XDrawString ()</tt>,
1848 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1849 in the X Window System.
1852 If the operation was successful, mdraw_text () returns 0. If an
1853 error is detected, it returns -1 and assigns an error code to the
1854 external variable #merror_code. */
1856 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1858 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1859 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1861 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1862 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1863 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1864 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1866 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1867 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1871 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1872 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1873 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1874 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1875 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1876 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1878 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1879 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1881 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1882 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1883 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1885 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1886 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1888 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1889 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1891 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1892 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1894 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1895 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1899 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1901 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1902 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1904 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1905 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1908 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1909 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1911 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1918 mdraw_image_text () */
1921 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1922 MText *mt, int from, int to)
1924 MDrawControl control;
1926 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1927 memset (&control, 0, sizeof control);
1928 control.as_image = 0;
1929 return draw_text (frame, win, x, y, mt, from, to, &control);
1936 @brief Draw an M-text on a window as an image.
1938 The mdraw_image_text () function draws the text between $FROM and
1939 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1940 coordinate ($X, $Y).
1942 The way to draw a text is the same as in mdraw_text () except that
1943 this function also draws the background with the color specified
1946 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1947 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1948 functions in the X Window System.
1951 If the operation was successful, mdraw_image_text () returns 0.
1952 If an error is detected, it returns -1 and assigns an error code
1953 to the external variable #merror_code. */
1956 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1958 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1959 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1960 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1962 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1963 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1965 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1966 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1970 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1971 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1973 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1983 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1984 MText *mt, int from, int to)
1986 MDrawControl control;
1988 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1989 memset (&control, 0, sizeof control);
1990 control.as_image = 1;
1991 return draw_text (frame, win, x, y, mt, from, to, &control);
1997 @brief Draw an M-text on a window with fine control.
1999 The mdraw_text_with_control () function draws the text between
2000 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2001 coordinate ($X, $Y).
2003 The way to draw a text is the same as in mdraw_text () except that
2004 this function also follows what specified in the drawing control
2007 For instance, if \<two_dimensional\> of $CONTROL is nonzero, this
2008 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2009 breaks lines and the following characters are drawn in the next
2010 line. See the documentation of the structure @ MDrawControl for
2014 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2016 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2017 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2020 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2021 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2023 ¤¿¤È¤¨¤Ð $CONTROL ¤Î \<two_dimensional\> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2024 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2025 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2028 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2029 MText *mt, int from, int to, MDrawControl *control)
2031 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2032 return draw_text (frame, win, x, y, mt, from, to, control);
2038 @brief Compute text pixel width.
2040 The mdraw_text_extents () function computes the width of text
2041 between $FROM and $TO of M-text $MT when it is drawn on a window
2042 of frame $FRAME using the mdraw_text_with_control () function with
2043 the drawing control object $CONTROL.
2045 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2046 the bounding box of character ink of the M-text, and stores the
2047 results in the members of the structure pointed to by
2048 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2049 surrounding box, the box is included in the bounding box.
2051 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2052 computes the bounding box that provides minimum spacing to other
2053 graphical features (such as surrounding box) for the M-text, and
2054 stores the results in the members of the structure pointed to by
2055 $OVERALL_LOGICAL_RETURN.
2057 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2058 computes the bounding box that provides minimum spacing to the
2059 other M-text drawn, and stores the results in the members of the
2060 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2061 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2062 min_line_ascent, min_line_descent, max_line_ascent, and
2063 max_line_descent of $CONTROL are all zero.
2066 This function returns the width of the text to be drawn in the
2067 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2068 text is drawn in multiple physical lines, it returns the width of
2069 the widest line. If an error occurs, it returns -1 and assigns an
2070 error code to the external variable #merror_code. */
2074 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2076 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2077 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2078 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2080 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2081 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2082 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2083 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2085 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2086 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2087 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2088 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2090 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2091 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2092 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2093 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2094 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2095 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2098 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2099 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2100 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2102 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2109 mdraw_text_extents (MFrame *frame,
2110 MText *mt, int from, int to, MDrawControl *control,
2111 MDrawMetric *overall_ink_return,
2112 MDrawMetric *overall_logical_return,
2113 MDrawMetric *overall_line_return)
2115 MGlyphString *gstring;
2117 int width, lbearing, rbearing;
2119 ASSURE_CONTROL (control);
2120 M_CHECK_POS_X (mt, from, -1);
2121 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2122 to = mtext_nchars (mt) + (control->cursor_width != 0);
2126 gstring = get_gstring (frame, mt, from, to, control);
2128 MERROR (MERROR_DRAW, -1);
2129 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2130 if (overall_ink_return)
2131 overall_ink_return->y = - gstring->physical_ascent;
2132 if (overall_logical_return)
2133 overall_logical_return->y = - gstring->ascent;
2134 if (overall_line_return)
2135 overall_line_return->y = - gstring->line_ascent;
2137 for (from = gstring->to; from < to; from = gstring->to)
2139 int this_width, this_lbearing, this_rbearing;
2141 y += gstring->line_descent;
2142 M17N_OBJECT_UNREF (gstring->top);
2143 gstring = get_gstring (frame, mt, from, to, control);
2144 this_width = gstring_width (gstring, from, to,
2145 &this_lbearing, &this_rbearing);
2146 y += gstring->line_ascent;
2147 if (width < this_width)
2149 if (rbearing < this_rbearing)
2150 rbearing = this_rbearing;
2151 if (lbearing > this_lbearing)
2152 lbearing = this_lbearing;
2154 if (overall_ink_return)
2156 overall_ink_return->x = lbearing;
2157 overall_ink_return->width = rbearing - lbearing;
2158 overall_ink_return->height
2159 = y + gstring->physical_descent - overall_ink_return->y;
2161 if (overall_logical_return)
2163 overall_logical_return->x = 0;
2164 overall_logical_return->width = width;
2165 overall_logical_return->height
2166 = y + gstring->descent - overall_logical_return->y;
2168 if (overall_line_return)
2170 overall_line_return->x = lbearing;
2171 overall_line_return->width = MAX (width, rbearing - lbearing);
2172 overall_line_return->height
2173 = y + gstring->line_descent - overall_line_return->y;
2176 M17N_OBJECT_UNREF (gstring->top);
2183 @brief Compute the text dimensions of each character of M-text.
2185 The mdraw_text_per_char_extents () function computes the drawn
2186 metric of each character between $FROM and $TO of M-text $MT
2187 assuming that they are drawn on a window of frame $FRAME using the
2188 mdraw_text_with_control () function with the drawing control
2191 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2192 $LOGICAL_ARRAY_RETURN. Each successive element of
2193 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2194 ink and logical metrics of successive characters respectively,
2195 relative to the drawing origin of the M-text. The number of
2196 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2197 been set is returned to $NUM_CHARS_RETURN.
2199 If $ARRAY_SIZE is too small to return all metrics, the function
2200 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2201 Otherwise, it returns zero.
2203 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2204 @c NULL, this function also computes the metrics of the overall
2205 text and stores the results in the members of the structure
2206 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2208 If $CONTROL->two_dimensional is nonzero, this function computes
2209 only the metrics of characters in the first line. */
2211 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2213 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2214 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2215 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2217 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2218 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2219 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2220 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2221 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2223 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2224 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2227 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2228 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2229 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2231 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2234 mdraw_text_per_char_extents (MFrame *frame,
2235 MText *mt, int from, int to,
2236 MDrawControl *control,
2237 MDrawMetric *ink_array_return,
2238 MDrawMetric *logical_array_return,
2240 int *num_chars_return,
2241 MDrawMetric *overall_ink_return,
2242 MDrawMetric *overall_logical_return)
2244 MGlyphString *gstring;
2248 ASSURE_CONTROL (control);
2249 *num_chars_return = to - from;
2250 if (array_size < *num_chars_return)
2251 MERROR (MERROR_DRAW, -1);
2252 if (overall_logical_return)
2253 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2254 if (overall_ink_return)
2255 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2257 M_CHECK_RANGE (mt, from, to, -1, 0);
2258 gstring = get_gstring (frame, mt, from, to, control);
2261 *num_chars_return = 0;
2265 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2266 if (g->g.from >= from && g->g.from < to)
2268 int start = g->g.from;
2270 int width = g->g.xadv;
2271 int lbearing = g->g.lbearing;
2272 int rbearing = g->g.rbearing;
2273 int ascent = g->g.ascent;
2274 int descent = g->g.descent;
2276 int logical_descent;
2278 if (g->rface->rfont)
2280 logical_ascent = g->rface->rfont->ascent;
2281 logical_descent = g->rface->rfont->descent;
2285 logical_ascent = g->rface->ascent;
2286 logical_descent = g->rface->descent;
2288 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2290 if (lbearing < width + g->g.lbearing)
2291 lbearing = width + g->g.lbearing;
2292 if (rbearing < width + g->g.rbearing)
2293 rbearing = width + g->g.rbearing;
2295 if (ascent < g->g.ascent)
2296 ascent = g->g.ascent;
2297 if (descent < g->g.descent)
2298 descent = g->g.descent;
2305 if (ink_array_return)
2307 ink_array_return[start - from].x = x + lbearing;
2308 ink_array_return[start - from].y = - ascent;
2309 ink_array_return[start - from].width = rbearing - lbearing;
2310 ink_array_return[start - from].height = ascent + descent;
2312 if (logical_array_return)
2314 logical_array_return[start - from].x = x;
2315 logical_array_return[start - from].y = - logical_descent;
2316 logical_array_return[start - from].height
2317 = logical_ascent + logical_descent;
2318 logical_array_return[start - from].width = width;
2326 if (overall_ink_return)
2328 overall_ink_return->y = - gstring->line_ascent;
2329 overall_ink_return->x = gstring->lbearing;
2330 overall_ink_return->width = x - gstring->lbearing;
2331 overall_ink_return->height = gstring->height;
2333 if (overall_logical_return)
2335 overall_logical_return->y = - gstring->ascent;
2336 overall_logical_return->x = 0;
2337 overall_logical_return->width = x;
2338 overall_logical_return->height = gstring->ascent + gstring->descent;
2341 M17N_OBJECT_UNREF (gstring->top);
2348 @brief Return the character position nearest to the coordinates.
2350 The mdraw_coordinates_position () function checks which character
2351 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2352 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2353 mdraw_text_with_control () function with the drawing control
2354 object $CONTROL. Here, the character position means the number of
2355 characters that precede the character in question in $MT, that is,
2356 the character position of the first character is 0.
2358 $FRAME is used only to get the default face information.
2361 If the glyph image of a character covers coordinate ($X, $Y),
2362 mdraw_coordinates_position () returns the character position of
2364 If $Y is less than the minimum Y-coordinate of the drawn area, it
2366 If $Y is greater than the maximum Y-coordinate of the drawn area,
2368 If $Y fits in with the drawn area but $X is less than the minimum
2369 X-coordinate, it returns the character position of the first
2370 character drawn on the line $Y.\n\n
2371 If $Y fits in with the drawn area but $X is greater than the
2372 maximum X-coordinate, it returns the character position of the
2373 last character drawn on the line $Y. */
2376 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2378 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2379 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2380 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2381 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2382 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2383 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2385 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2388 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2389 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2390 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2392 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2393 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2394 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2395 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2398 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2399 int x_offset, int y_offset, MDrawControl *control)
2401 MGlyphString *gstring;
2406 M_CHECK_POS_X (mt, from, -1);
2407 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2408 to = mtext_nchars (mt) + (control->cursor_width != 0);
2414 ASSURE_CONTROL (control);
2415 gstring = get_gstring (frame, mt, from, to, control);
2416 while (y + gstring->line_descent <= y_offset
2417 && gstring->to < to)
2420 y += gstring->line_descent;
2421 M17N_OBJECT_UNREF (gstring->top);
2422 gstring = get_gstring (frame, mt, from, to, control);
2423 y += gstring->line_ascent;
2426 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2427 if (! control->orientation_reversed)
2429 width = gstring->indent;
2430 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2431 if (g->g.from >= from && g->g.from < to)
2434 if (width > x_offset)
2440 width = - gstring->indent;
2441 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2442 if (g->g.from >= from && g->g.from < to)
2445 if (width < x_offset)
2449 if (g->type == GLYPH_ANCHOR
2450 && control->two_dimensional
2451 && g[-1].g.c == '\n')
2454 M17N_OBJECT_UNREF (gstring->top);
2462 @brief Compute information about a glyph.
2464 The mdraw_glyph_info () function computes information about a
2465 glyph that covers a character at position $POS of the M-text $MT
2466 assuming that the text is drawn from the character at $FROM of $MT
2467 on a window of frame $FRAME using the mdraw_text_with_control ()
2468 function with the drawing control object $CONTROL.
2470 The information is stored in the members of $INFO. */
2472 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2474 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2475 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2476 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2477 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2479 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2487 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2488 MDrawControl *control, MDrawGlyphInfo *info)
2490 MGlyphString *gstring;
2494 M_CHECK_RANGE_X (mt, from, pos, -1);
2496 ASSURE_CONTROL (control);
2497 gstring = get_gstring (frame, mt, from, pos + 1, control);
2499 MERROR (MERROR_DRAW, -1);
2500 while (gstring->to <= pos)
2502 y += gstring->line_descent;
2503 M17N_OBJECT_UNREF (gstring->top);
2504 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2505 y += gstring->line_ascent;
2507 info->line_from = gstring->from;
2508 if (info->line_from < from)
2509 info->line_from = from;
2510 info->line_to = gstring->to;
2513 if (! control->orientation_reversed)
2515 info->x = gstring->indent;
2516 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2517 info->x += g->g.xadv;
2521 info->x = - gstring->indent;
2522 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2523 info->x -= g->g.xadv;
2524 while (g[-1].g.to == g->g.to)
2527 info->from = g->g.from;
2529 info->metrics.x = g->g.lbearing;
2530 info->metrics.y = - gstring->line_ascent;
2531 info->metrics.height = gstring->height;
2532 info->metrics.width = - g->g.lbearing + g->g.xadv;
2533 if (g->rface->rfont)
2534 info->font = (MFont *) g->rface->rfont;
2537 /* info->logical_width is calculated later. */
2539 if (info->from > info->line_from)
2541 /* The logically previous glyph is on this line. */
2542 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2544 info->prev_from = g_tmp->g.from;
2546 else if (info->line_from > 0
2547 && gstring->from > 0)
2549 /* The logically previous glyph is on the previous line. */
2550 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2551 gstring->from, control);
2552 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2554 info->prev_from = g_tmp->g.from;
2555 M17N_OBJECT_UNREF (gst->top);
2558 info->prev_from = -1;
2560 if (GLYPH_INDEX (g) > 1)
2561 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2562 else if (! control->orientation_reversed)
2564 if (info->line_from > 0)
2568 int p = gstring->from - 1;
2570 gst = get_gstring (frame, mt, p, gstring->from, control);
2571 g_tmp = gst->glyphs + (gst->used - 2);
2572 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2573 M17N_OBJECT_UNREF (gst->top);
2576 info->left_from = info->left_to = -1;
2580 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2584 int p = gstring->to;
2586 gst = get_gstring (frame, mt, p, p + 1, control);
2587 g_tmp = gst->glyphs + (gst->used - 2);
2588 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2589 M17N_OBJECT_UNREF (gst->top);
2592 info->left_from = info->left_to = -1;
2595 if (info->to < gstring->to)
2597 /* The logically next glyph is on this line. */
2598 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2600 info->next_to = g_tmp->g.to;
2602 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2604 /* The logically next glyph is on the next line. */
2606 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2607 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2609 info->next_to = g_tmp->g.to;
2610 M17N_OBJECT_UNREF (gst->top);
2615 for (info->logical_width = (g++)->g.xadv;
2616 g->g.from == pos && g->type != GLYPH_ANCHOR;
2617 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2618 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2620 if (g->type != GLYPH_ANCHOR)
2621 info->right_from = g->g.from, info->right_to = g->g.to;
2622 else if (! control->orientation_reversed)
2624 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2627 M17N_OBJECT_UNREF (gstring->top);
2628 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2630 info->right_from = g->g.from, info->right_to = g->g.to;
2633 info->right_from = info->right_to = -1;
2637 if (info->line_from > 0)
2639 pos = gstring->from - 1;
2640 M17N_OBJECT_UNREF (gstring->top);
2641 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2643 info->right_from = g->g.from, info->right_to = g->g.to;
2646 info->right_from = info->right_to = -1;
2649 M17N_OBJECT_UNREF (gstring->top);
2656 @brief Compute information about glyph sequence.
2658 The mdraw_glyph_list () function computes information about glyphs
2659 corresponding to the text between $FROM and $TO of M-text $MT when
2660 it is drawn on a window of frame $FRAME using the
2661 mdraw_text_with_control () function with the drawing control
2662 object $CONTROL. $GLYPHS is an array of objects to store the
2663 information, and $ARRAY_SIZE is the array size.
2665 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2666 number of actually filled elements in the place pointed by
2667 $NUM_GLYPHS_RETURN, and returns 0.
2669 Otherwise, it stores the required array size in the place pointed
2670 by $NUM_GLYPHS_RETURN, and returns -1. */
2673 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2675 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2676 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2677 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2678 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2680 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2681 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2684 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2694 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2695 MDrawControl *control, MDrawGlyph *glyphs,
2696 int array_size, int *num_glyphs_return)
2698 MGlyphString *gstring;
2703 ASSURE_CONTROL (control);
2704 *num_glyphs_return = 0;
2705 M_CHECK_RANGE (mt, from, to, -1, 0);
2706 gstring = get_gstring (frame, mt, from, to, control);
2709 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2711 if (g->type == GLYPH_BOX
2712 || g->g.from < from || g->g.from >= to)
2714 if (g->type == GLYPH_PAD)
2716 if (g->left_padding)
2717 pad_width = g->g.xadv;
2721 glyphs[-1].x_advance += g->g.xadv;
2727 glyphs->from = g->g.from;
2728 glyphs->to = g->g.to;
2729 glyphs->glyph_code = g->g.code;
2730 glyphs->x_off = g->g.xoff + pad_width;
2731 glyphs->y_off = g->g.yoff;
2732 glyphs->lbearing = g->g.lbearing;
2733 glyphs->rbearing = g->g.rbearing;
2734 glyphs->ascent = g->g.ascent;
2735 glyphs->descent = g->g.descent;
2736 glyphs->x_advance = g->g.xadv + pad_width;
2737 glyphs->y_advance = 0;
2738 if (g->rface->rfont)
2740 glyphs->font = (MFont *) g->rface->rfont;
2741 #ifdef HAVE_FREETYPE
2743 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2744 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2746 #else /* not HAVE_FREETYPE */
2747 glyphs->font_type = Mx;
2748 #endif /* not HAVE_FREETYPE */
2749 glyphs->fontp = g->rface->rfont->fontp;
2753 glyphs->font = NULL;
2754 glyphs->font_type = Mnil;
2755 glyphs->fontp = NULL;
2762 M17N_OBJECT_UNREF (gstring->top);
2764 *num_glyphs_return = n;
2765 return (n <= array_size ? 0 : -1);
2771 @brief Draw one or more textitems.
2773 The mdraw_text_items () function draws one or more M-texts on
2774 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2775 of the textitems to be drawn and $NITEMS is the number of
2776 textitems in the array. */
2779 @brief textitem ¤òɽ¼¨¤¹¤ë.
2781 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2782 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2783 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2785 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2789 MTextItem, mdraw_text (). */
2792 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2793 MDrawTextItem *items, int nitems)
2795 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2797 while (nitems-- > 0)
2800 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2802 mdraw_text_with_control (frame, win, x, y,
2803 items->mt, 0, mtext_nchars (items->mt),
2805 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2806 items->control, NULL, NULL, NULL);
2809 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2815 @brief Option of line breaking for drawing text.
2817 The variable #mdraw_line_break_option specifies line breaking
2818 options by logical-or of the members of #MTextLineBreakOption. It
2819 controls the line breaking algorithm of the function
2820 mdraw_default_line_break (). */
2822 int mdraw_line_break_option;
2826 @brief Calculate a line breaking position.
2828 The function mdraw_default_line_break () calculates a line
2829 breaking position based on the line number $LINE and the
2830 coordinate $Y, when a line is too long to fit within the width
2831 limit. $POS is the position of the character next to the last one
2832 that fits within the limit. $FROM is the position of the first
2833 character of the line, and $TO is the position of the last
2834 character displayed on the line if there were not width limit.
2835 $LINE and $Y are reset to 0 when a line is broken by a newline
2836 character, and incremented each time when a long line is broken
2837 because of the width limit.
2840 This function returns a character position to break the
2845 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2847 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2848 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2849 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2850 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2851 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2852 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2853 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2856 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2860 mdraw_default_line_break (MText *mt, int pos,
2861 int from, int to, int line, int y)
2865 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2876 @brief Obtain per character dimension information.
2878 The mdraw_per_char_extents () function computes the text dimension
2879 of each character in M-text $MT. The faces given as text
2880 properties in $MT and the default face of frame $FRAME determine
2881 the fonts to draw the text. Each successive element in
2882 $ARRAY_RETURN is set to the drawn metrics of successive
2883 characters, which is relative to the origin of the drawing, and a
2884 rectangle for each character in $MT. The number of elements of
2885 $ARRAY_RETURN must be equal to or greater than the number of
2888 If pointer $OVERALL_RETURN is not @c NULL, this function also
2889 computes the extents of the overall text and stores the results in
2890 the members of the structure pointed to by $OVERALL_RETURN. */
2893 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2895 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2896 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2897 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2898 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2899 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2900 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2901 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2903 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2904 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2905 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2907 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2910 mdraw_per_char_extents (MFrame *frame, MText *mt,
2911 MDrawMetric *array_return,
2912 MDrawMetric *overall_return)
2914 int n = mtext_nchars (mt);
2916 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2917 n, &n, overall_return, NULL);
2921 @brief clear cached information.
2923 The mdraw_clear_cache () function clear cached information
2924 on M-text $MT that was attached by any of the drawing functions.
2925 When the behavior of `format' or `line_break'
2926 member functions of MDrawControl is changed, the cache must be cleared.
2931 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2933 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2934 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2935 ¤¢¤ë¤¤¤Ï `line_break'
2936 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2942 mdraw_clear_cache (MText *mt)
2944 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);