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 FriBidiParType 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;
228 int level = g->bidi_level;
230 for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++);
231 if ((level % 2) && j > i)
233 memcpy (glyphs + i, gstring->glyphs + i,
234 sizeof (MGlyph) * (j - i + 1));
236 g[j - i] = glyphs[i];
243 font_id (MFLTFont *font)
245 return ((MFLTFontForRealized *) font)->rfont->id;
249 run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
251 MRealizedFont *rfont = rface->rfont;
252 MSymbol layouter = rface->layouter;
253 MFLTGlyphString flt_gstr;
254 MFLTFontForRealized font;
256 int from_pos = MGLYPH (from)->g.from;
261 flt = mflt_get (layouter);
262 flt_gstr.glyph_size = sizeof (MGlyph);
263 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
264 flt_gstr.used = gstring->used;
265 flt_gstr.allocated = gstring->size;
267 font.font.family = mfont_get_prop (rfont->font, Mfamily);
268 font.font.x_ppem = rfont->x_ppem;
269 font.font.y_ppem = rfont->y_ppem;
270 font.font.get_glyph_id = mfont__get_glyph_id;
271 font.font.get_metrics = mfont__get_metrics;
272 font.font.check_otf = rfont->driver->check_otf;
273 font.font.drive_otf = rfont->driver->drive_otf;
274 font.font.internal = NULL;
276 mflt_font_id = font_id;
277 mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature;
278 mflt_try_otf = rfont->driver->try_otf;
279 for (i = 0; i < 3; i++)
281 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
284 APPEND_GLYPH (gstring, *MGLYPH (0));
285 APPEND_GLYPH (gstring, *MGLYPH (0));
288 if (from + len != to)
289 gstring->used += to - (from + len);
290 for (i = from, catcode = -1; i < to; i++)
292 MGlyph *g = MGLYPH (i);
294 g->g.from += from_pos - from;
295 g->g.to += from_pos - from + 1;
305 if (catcode < 0 || g->g.from != g[-1].g.from)
307 MSymbol category = mchar_get_prop (g->g.c, Mcategory);
309 catcode = (category == McatCf
310 ? GLYPH_CATEGORY_FORMATTER
311 : category != Mnil && MSYMBOL_NAME (category)[0] == 'M'
312 ? GLYPH_CATEGORY_MODIFIER
313 : GLYPH_CATEGORY_NORMAL);
315 g->category = catcode;
320 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
321 displaying them on FRAME.
323 This function fills these members:
324 pos, to, c, code, rface, bidi_level, categories, type, combining_code
325 The other members are filled by layout_glyph_string. */
328 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
329 MGlyphString *gstring)
331 MRealizedFace *default_rface = frame->rface;
332 int stop, face_change, language_change, charset_change, font_change;
333 MGlyph g_tmp, *g, *last_g;
335 MSymbol language = Mnil, script = Mnil, charset = Mnil;
336 MSymbol non_latin_script = Mnil;
337 MRealizedFace *rface = default_rface;
338 MRealizedFont *rfont;
339 int size = gstring->control.fixed_width;
340 int max_bidi_level = 0;
343 MLIST_RESET (gstring);
344 gstring->from = from;
346 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
347 <category> and <rface> members.*/
350 /** Put anchor glyphs at the head and tail. */
351 g_tmp.type = GLYPH_ANCHOR;
352 g_tmp.g.from = g_tmp.g.to = from;
353 APPEND_GLYPH (gstring, g_tmp);
354 stop = face_change = font_change = pos = from;
364 if (pos < mtext_nchars (mt))
366 MFont *font = rface->font;
370 if (pos == font_change)
372 font = mtext_get_prop (mt, pos, Mfont);
373 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
374 if (font_change == mtext_nchars (mt))
377 if (pos == face_change)
379 num = mtext_get_prop_values (mt, pos, Mface,
380 (void **) faces, 64);
381 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
382 if (face_change == mtext_nchars (mt))
387 faces[0] = &rface->face;
390 rface = mface__realize (frame, faces, num, size, font);
393 rface = default_rface;
395 if (stop > font_change)
397 if (stop > face_change)
401 if (pos < mtext_nchars (mt))
402 c = mtext_ref_char (mt, pos);
406 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
408 g_tmp.g.from = pos++;
411 category = mchar_get_prop (c, Mcategory);
412 if (category == McatCf)
413 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
414 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
415 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
417 g_tmp.category = GLYPH_CATEGORY_NORMAL;
419 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
423 ctrl[0] = ctrl[1] = g_tmp;
425 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
426 APPEND_GLYPH (gstring, ctrl[0]);
427 APPEND_GLYPH (gstring, ctrl[1]);
430 APPEND_GLYPH (gstring, g_tmp);
431 if (c == '\n' && gstring->control.two_dimensional)
434 /* Append an anchor glyph. */
436 g_tmp.type = GLYPH_ANCHOR;
437 g_tmp.g.from = g_tmp.g.to = pos;
438 APPEND_GLYPH (gstring, g_tmp);
441 if (gstring->control.enable_bidi)
442 max_bidi_level = analyse_bidi_level (gstring);
444 /* The next loop is to change each <rface> member for non-ASCII
445 characters if necessary. */
446 stop = charset_change = language_change = from;
447 rfont = default_rface->rfont;
448 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
454 /* Short cut for the obvious case. */
455 this_script = Mlatin;
458 this_script = (MSymbol) mchar_get_prop (c, Mscript);
459 if (this_script == Minherited || this_script == Mcommon)
463 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
465 if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z')
466 this_script = script;
469 if (this_script == Mcommon && non_latin_script)
470 this_script = non_latin_script;
471 if (this_script == Mcommon)
473 /* Search forward for a character that explicitly
474 specifies a non-latin script. */
478 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
480 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
481 && sym != Minherited)
487 if (this_script == Minherited || this_script == Mcommon)
488 this_script = (MSymbol) mchar_get_prop (c, Mblock);
492 if (pos == stop || script != this_script || g->rface->rfont != rfont)
495 last_g = mface__for_chars (script, language, charset,
497 script = this_script;
498 if (script != Mnil && script != Mlatin)
499 non_latin_script = script;
500 rfont = g->rface->ascii_rface->rfont;
503 if (pos < mtext_nchars (mt) && pos == language_change)
505 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
506 mtext_prop_range (mt, Mlanguage, pos, NULL,
507 &language_change, 0);
509 if (pos < mtext_nchars (mt) && pos == charset_change)
511 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
512 mtext_prop_range (mt, Mcharset, pos, NULL,
516 if (stop > language_change)
517 stop = language_change;
518 if (stop > charset_change)
519 stop = charset_change;
524 last_g = mface__for_chars (script, language, charset, last_g, g, size);
526 /* The next loop is to run FLT or perform the default combining if
528 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
532 if (this->type == GLYPH_CHAR && this->rface->rfont)
536 if (this->rface->layouter != Mnil)
538 MGlyph *prev = MGLYPH (start - 1);
540 while (prev->type == GLYPH_CHAR
541 && prev->category == GLYPH_CATEGORY_FORMATTER
542 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
544 != MCHAR_INVALID_CODE))
546 prev->rface->rfont = this->rface->rfont;
551 (g->type == GLYPH_CHAR
552 && g->rface->layouter == this->rface->layouter
553 && (g->rface->rfont == this->rface->rfont
554 || (g->category == GLYPH_CATEGORY_FORMATTER
555 && (mfont__encode_char (NULL,
556 (MFont *) this->rface->rfont,
558 != MCHAR_INVALID_CODE))));
560 g->rface->rfont = this->rface->rfont;
561 i = run_flt (gstring, start, i, this->rface);
566 while (g->type == GLYPH_CHAR
568 && g->category == GLYPH_CATEGORY_MODIFIER
570 && g->rface->layouter == Mnil)
574 this->rface->layouter = Mcombining;
575 run_flt (gstring, start, i, this->rface);
578 mfont__get_metric (gstring, start, i);
586 /* At last, reorder glyphs visually if necessary. */
587 if (max_bidi_level > 0)
588 visual_order (gstring);
592 int width, lbearing, rbearing;
596 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
597 MSubTextExtents *extents)
599 int g_physical_ascent, g_physical_descent;
600 MGlyph *g = MGLYPH (from);
601 MGlyph *last_g = MGLYPH (to);
603 g_physical_ascent = gstring->physical_ascent;
604 g_physical_descent = gstring->physical_descent;
605 extents->width = extents->lbearing = extents->rbearing = 0;
607 for (g = MGLYPH (from); g < last_g; g++)
609 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
610 g_physical_descent = MAX (g_physical_descent, g->g.descent);
611 extents->lbearing = MIN (extents->lbearing,
612 extents->width + g->g.lbearing);
613 extents->rbearing = MAX (extents->rbearing,
614 extents->width + g->g.rbearing);
615 extents->width += g->g.xadv;
618 gstring->physical_ascent = g_physical_ascent;
619 gstring->physical_descent = g_physical_descent;
623 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
624 by this function directly. Character glyphs are handled by
625 layouter functions registered in font drivers.
627 This function fill-in all the remaining members of glyphs. */
630 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
632 /* Default width of TAB. */
633 int tab_width = frame->space_width * (gstring->control.tab_width
634 ? gstring->control.tab_width : 8);
638 MDrawControl *control = &(gstring->control);
641 int box_line_height = 0;
642 int ignore_formatting_char = control->ignore_formatting_char;
644 gstring->ascent = gstring->descent = 0;
645 gstring->physical_ascent = gstring->physical_descent = 0;
646 gstring->width = gstring->lbearing = gstring->rbearing = 0;
650 while (g->type != GLYPH_ANCHOR)
652 if (box != g->rface->box)
654 int gidx = GLYPH_INDEX (g);
658 /* Insert the right side of the box. That glyph belongs
659 to the previous grapheme cluster. */
660 MGlyph box_glyph = g[-1];
662 box_glyph.type = GLYPH_BOX;
664 = (control->fixed_width
666 : box->inner_hmargin + box->width + box->outer_hmargin);
667 box_glyph.g.lbearing = 0;
668 box_glyph.g.rbearing = box_glyph.g.xadv;
669 box_glyph.g.xoff = 0;
670 box_glyph.right_padding = 1;
671 gstring->width += box_glyph.g.xadv;
672 gstring->rbearing += box_glyph.g.xadv;
673 INSERT_GLYPH (gstring, gidx, box_glyph);
680 /* Insert the left side of the box. That glyph belongs
681 to the following grapheme cluster. */
682 MGlyph box_glyph = *g;
683 int box_height = (box->width
684 + box->inner_vmargin + box->outer_vmargin);
686 if (box_line_height < box_height)
687 box_line_height = box_height;
688 box_glyph.type = GLYPH_BOX;
690 = (control->fixed_width
692 : box->inner_hmargin + box->width + box->outer_hmargin);
693 box_glyph.g.lbearing = 0;
694 box_glyph.g.rbearing = box_glyph.g.xadv;
695 box_glyph.g.xoff = 0;
696 box_glyph.left_padding = 1;
697 gstring->width += box_glyph.g.xadv;
698 gstring->rbearing += box_glyph.g.xadv;
699 INSERT_GLYPH (gstring, gidx, box_glyph);
705 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
706 g->type = GLYPH_SPACE;
708 if (g->type == GLYPH_CHAR)
710 MRealizedFace *rface = g->rface;
711 MRealizedFont *rfont = rface->rfont;
713 int from = GLYPH_INDEX (g);
715 for (g++; g->type == GLYPH_CHAR; g++)
716 if (! rfont != ! g->rface->rfont
717 || box != g->rface->box
718 || ((fromg->g.code == MCHAR_INVALID_CODE)
719 != (g->g.code == MCHAR_INVALID_CODE))
720 || (g->category == GLYPH_CATEGORY_FORMATTER
721 && ignore_formatting_char))
723 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
726 int to = GLYPH_INDEX (g);
727 MSubTextExtents extents;
729 layout_glyphs (frame, gstring, from, to, &extents);
730 extra_width = - extents.lbearing;
732 && ! control->disable_overlapping_adjustment
733 && (! control->orientation_reversed
734 ? ((to > 1 || control->align_head)
735 && g->type != GLYPH_ANCHOR)
736 : (((g->type && GLYPH_ANCHOR) || control->align_head)
741 pad.type = GLYPH_PAD;
744 pad.g.xadv = pad.g.rbearing = extra_width;
745 pad.left_padding = 1;
746 INSERT_GLYPH (gstring, from, pad);
748 extents.lbearing = 0;
749 extents.width += extra_width;
750 extents.rbearing += extra_width;
752 g = MGLYPH (from - 1);
753 if (g->type == GLYPH_SPACE)
755 /* The pad just inserted is absorbed (maybe
756 partially) by the previous space while
757 keeping at least some space width. For the
758 moment, we use the arbitrary width 2-pixel.
759 Perhaps, it should be decided by the current
760 face, or a default value of the current
761 frame, which is, however, not yet
763 if (extra_width + 2 < g->g.xadv)
765 g->g.xadv -= extra_width;
769 extra_width = g->g.xadv - 2;
772 gstring->width -= extra_width;
773 gstring->rbearing -= extra_width;
778 extra_width = extents.rbearing - extents.width;
780 && ! control->disable_overlapping_adjustment
781 && (GLYPH_INDEX (g) < gstring->used - 1
782 || (control->orientation_reversed && control->align_head)))
784 if (g->type == GLYPH_SPACE && box == g->rface->box)
787 pad.type = GLYPH_PAD;
790 pad.g.xadv = pad.g.rbearing = extra_width;
791 INSERT_GLYPH (gstring, to, pad);
796 g[-1].g.xadv += extra_width;
797 extents.width += extra_width;
800 if (gstring->lbearing > gstring->width + extents.lbearing)
801 gstring->lbearing = gstring->width + extents.lbearing;
802 if (gstring->rbearing < gstring->width + extents.rbearing)
803 gstring->rbearing = gstring->width + extents.rbearing;
804 gstring->width += extents.width;
805 if (gstring->ascent < rface->ascent)
806 gstring->ascent = rface->ascent;
807 if (gstring->descent < rface->descent)
808 gstring->descent = rface->descent;
812 for (; fromg < g; fromg++)
814 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
815 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
816 fromg->g.xadv = fromg->g.rbearing = 1;
818 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
819 fromg->g.xoff = fromg->g.lbearing = 0;
820 fromg->g.ascent = fromg->g.descent = 0;
821 gstring->width += fromg->g.xadv;
822 gstring->rbearing += fromg->g.xadv;
824 if (gstring->ascent < frame->rface->ascent)
825 gstring->ascent = frame->rface->ascent;
826 if (gstring->descent < frame->descent)
827 gstring->descent = frame->rface->descent;
830 else if (g->type == GLYPH_SPACE)
833 g->g.xadv = g->rface->space_width;
834 else if (g->g.c == '\n')
836 g->g.xadv = control->cursor_width;
839 if (control->cursor_bidi)
841 else if (g->g.xadv < 0)
842 g->g.xadv = g->rface->space_width;
845 else if (g->g.c == '\t')
847 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
853 if (g[-1].type == GLYPH_PAD)
855 /* This space glyph absorbs (maybe partially) the
856 previous padding glyph. */
857 g->g.xadv -= g[-1].g.xadv;
859 /* But, keep at least some space width. For the
860 moment, we use the arbitrary width 2-pixel. */
863 g->g.rbearing = g->g.xadv;
864 gstring->width += g->g.xadv;
865 gstring->rbearing += g->g.xadv;
868 if (gstring->ascent < g->rface->ascent)
869 gstring->ascent = g->rface->ascent;
870 if (gstring->descent < g->rface->descent)
871 gstring->descent = g->rface->descent;
877 gstring->width += g->g.xadv;
878 gstring->rbearing += g->g.xadv;
885 /* Insert the right side of the box. */
886 int gidx = GLYPH_INDEX (g);
887 MGlyph box_glyph = g[-1];
889 box_glyph.type = GLYPH_BOX;
891 = (control->fixed_width
893 : box->inner_hmargin + box->width + box->outer_hmargin);
894 box_glyph.g.lbearing = 0;
895 box_glyph.g.rbearing = box_glyph.g.xadv;
896 box_glyph.g.xoff = 0;
897 box_glyph.right_padding = 1;
898 gstring->width += box_glyph.g.xadv;
899 gstring->rbearing += box_glyph.g.xadv;
900 INSERT_GLYPH (gstring, gidx, box_glyph);
903 gstring->text_ascent = gstring->ascent;
904 gstring->text_descent = gstring->descent;
905 if (gstring->text_ascent < gstring->physical_ascent)
906 gstring->text_ascent = gstring->physical_ascent;
907 if (gstring->text_descent < gstring->physical_descent)
908 gstring->text_descent = gstring->physical_descent;
909 gstring->line_ascent = gstring->text_ascent;
910 gstring->line_descent = gstring->text_descent;
911 if (box_line_height > 0)
913 gstring->line_ascent += box_line_height;
914 gstring->physical_ascent = gstring->line_ascent;
915 gstring->line_descent += box_line_height;
916 gstring->physical_descent = gstring->line_descent;
919 if (gstring->line_ascent < control->min_line_ascent)
920 gstring->line_ascent = control->min_line_ascent;
921 else if (control->max_line_ascent
922 && control->max_line_ascent > control->min_line_ascent
923 && gstring->line_ascent > control->max_line_ascent)
924 gstring->line_ascent = control->max_line_ascent;
926 if (gstring->line_descent < control->min_line_descent)
927 gstring->line_descent = control->min_line_descent;
928 else if (control->max_line_descent
929 && control->max_line_descent > control->min_line_descent
930 && gstring->line_descent > control->max_line_descent)
931 gstring->line_descent = control->max_line_descent;
932 gstring->height = gstring->line_ascent + gstring->line_descent;
934 if (control->orientation_reversed
937 /* We must adjust TAB width for RTL orientation. */
938 width = gstring->indent;
940 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
942 if (g->type == GLYPH_CHAR && g->g.c == '\t')
944 int this_width = tab_width - (width % tab_width);
946 if (g[1].type == GLYPH_PAD)
947 this_width -= g[1].g.xadv;
948 if (g[-1].type == GLYPH_PAD)
949 this_width -= g[-1].g.xadv;
952 gstring->width += this_width - g->g.xadv;
953 gstring->rbearing += this_width - g->g.xadv;
954 g->g.xadv = this_width;
965 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
966 MGlyphString *gstring, int from, int to,
967 int *from_idx, int *to_idx, int *to_x)
969 MGlyph *g = MGLYPH (1);
970 MDrawRegion region = (MDrawRegion) NULL;
971 MDrawControl *control = &gstring->control;
974 int cursor_bidi = control->cursor_bidi;
976 if (control->with_cursor && control->cursor_width)
978 if (gstring->from <= control->cursor_pos
979 && gstring->to > control->cursor_pos)
980 cursor_pos = control->cursor_pos;
983 && gstring->from <= control->cursor_pos - 1
984 && gstring->to > control->cursor_pos - 1)
985 prev_pos = control->cursor_pos - 1;
988 *from_idx = *to_idx = 0;
990 while (g->type != GLYPH_ANCHOR)
992 if (g->g.from >= from && g->g.from < to)
994 MGlyph *fromg = g, *cursor = NULL;
995 MRealizedFace *rface = g->rface;
997 int cursor_width = 0;
1001 *from_idx = GLYPH_INDEX (g);
1002 while (g->g.from >= from && g->g.from < to
1003 && g->rface == rface)
1006 if (g->type != GLYPH_BOX
1007 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1010 cursor = g, cursor_x = x + width;
1011 cursor_width += g->g.xadv;
1013 width += g++->g.xadv;
1016 && (control->as_image
1017 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1019 int this_x = x, this_width = width;
1021 if (fromg->type == GLYPH_BOX)
1022 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1023 if (g[-1].type == GLYPH_BOX)
1024 this_width -= g[-1].g.xadv;
1025 (frame->driver->fill_space)
1026 (frame, win, rface, 0,
1027 this_x, y - gstring->text_ascent, this_width,
1028 gstring->text_ascent + gstring->text_descent,
1029 control->clip_region);
1036 rect.y = y - gstring->text_ascent;
1037 rect.height = gstring->text_ascent + gstring->text_descent;
1040 rect.width = ((control->cursor_width > 0
1041 && control->cursor_width < cursor_width)
1042 ? control->cursor_width : cursor_width);
1046 if (cursor->bidi_level % 2)
1047 rect.x += cursor_width - rect.width;
1048 (*frame->driver->fill_space)
1049 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1050 control->clip_region);
1052 region = (*frame->driver->region_from_rect) (&rect);
1054 (*frame->driver->region_add_rect) (region, &rect);
1057 if (cursor->bidi_level % 2)
1060 rect.width = cursor_width < 4 ? cursor_width : 4;
1061 (*frame->driver->fill_space)
1062 (frame, win, rface, 1,
1063 rect.x, rect.y, rect.width, rect.height,
1064 control->clip_region);
1065 (*frame->driver->region_add_rect) (region, &rect);
1077 if (fromg->type != GLYPH_BOX
1078 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1081 cursor = fromg, cursor_x = x + temp_width;
1082 cursor_width += fromg->g.xadv;
1084 temp_width += fromg++->g.xadv;
1091 if (! (cursor->bidi_level % 2))
1092 rect.x += cursor_width - 1;
1093 rect.y = y - gstring->text_ascent;
1094 rect.height = gstring->text_ascent + gstring->text_descent;
1096 (*frame->driver->fill_space)
1097 (frame, win, rface, 1,
1098 rect.x, rect.y, rect.width, rect.height,
1099 control->clip_region);
1101 region = (*frame->driver->region_from_rect) (&rect);
1103 (*frame->driver->region_add_rect) (region, &rect);
1104 rect.y += rect.height - 2;
1106 rect.width = cursor_width < 4 ? cursor_width : 4;
1107 if (! (cursor->bidi_level % 2))
1108 rect.x -= rect.width - 1;
1109 (*frame->driver->fill_space) (frame, win, rface, 1,
1110 rect.x, rect.y, rect.width, rect.height,
1111 control->clip_region);
1112 (*frame->driver->region_add_rect) (region, &rect);
1116 *to_idx = GLYPH_INDEX (g);
1126 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1127 MGlyphString *gstring, int from_idx, int to_idx,
1128 int reverse, MDrawRegion region)
1130 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1136 (*frame->driver->region_to_rect) (region, &rect);
1139 while (g != gend && x + g->g.rbearing <= rect.x)
1142 width -= g++->g.xadv;
1143 while (! g->enabled && g != gend)
1147 rect.x += rect.width;
1148 if (rect.x < x + width)
1151 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1153 width -= (--gend)->g.xadv;
1154 while (! gend->enabled && g != gend)
1158 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1167 MRealizedFace *rface = g->rface;
1168 int width = g->g.xadv;
1169 MGlyph *from_g = g++;
1171 /* Handle the glyphs of the same type/face at once. */
1173 && g->type == from_g->type
1174 && g->rface == rface
1175 && ((g->g.code == MCHAR_INVALID_CODE)
1176 == (from_g->g.code == MCHAR_INVALID_CODE))
1178 width += g++->g.xadv;
1180 if (from_g->type == GLYPH_CHAR)
1182 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1183 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1186 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1189 else if (from_g->type == GLYPH_BOX)
1191 /* Draw the left or right side of a box. If
1192 from_g->lbearing is nonzero, this is the left side,
1193 else this is the right side. */
1194 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1197 if (from_g->type != GLYPH_BOX)
1200 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1201 x, y, width, region);
1204 /* Draw the top and bottom side of a box. */
1205 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1206 x, y, width, region);
1217 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1218 int *from_x, int *to_x)
1221 int left_idx = *left, right_idx = *right;
1222 int left_x, right_x, x;
1224 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1227 if (x + g->g.rbearing > 0)
1229 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1231 left_idx = GLYPH_INDEX (g);
1236 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1239 if (x - g->g.xadv + g->g.lbearing < 0)
1241 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1243 right_idx = GLYPH_INDEX (g) + 1;
1248 if (*left == left_idx && *right == right_idx)
1251 if (*left != left_idx)
1253 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1258 if (*right != right_idx)
1260 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1270 gstring_width (MGlyphString *gstring, int from, int to,
1271 int *lbearing, int *rbearing)
1276 if (from <= gstring->from && to >= gstring->to)
1279 *lbearing = gstring->lbearing;
1281 *rbearing = gstring->rbearing;
1282 return gstring->width;
1289 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1290 if (g->g.from >= from && g->g.from < to)
1292 if (lbearing && width + g->g.lbearing < *lbearing)
1293 *lbearing = width + g->g.lbearing;
1294 if (rbearing && width + g->g.rbearing > *rbearing)
1295 *rbearing = width + g->g.rbearing;
1303 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1304 MGlyphString *gstring, int from, int to)
1306 MDrawControl *control = &gstring->control;
1308 MDrawRegion clip_region, cursor_region;
1309 int from_idx, to_idx;
1314 if (control->orientation_reversed)
1315 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1317 x += gstring->indent;
1319 /* At first, draw all glyphs without cursor. */
1320 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1321 &from_idx, &to_idx, &to_x);
1323 if (control->partial_update)
1326 rect.width = to_x - x;
1327 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1329 rect.y = y - gstring->line_ascent;
1330 rect.height = gstring->height;
1331 clip_region = (*frame->driver->region_from_rect) (&rect);
1332 if (control->clip_region)
1333 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1336 clip_region = control->clip_region;
1339 clip_region = control->clip_region;
1341 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1346 (*frame->driver->intersect_region) (cursor_region, clip_region);
1347 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1350 if (clip_region != control->clip_region)
1351 (*frame->driver->free_region) (clip_region);
1353 (*frame->driver->free_region) (cursor_region);
1357 static int gstring_num;
1360 free_gstring (void *object)
1362 MGlyphString *gstring = (MGlyphString *) object;
1365 free_gstring (gstring->next);
1366 if (gstring->size > 0)
1367 free (gstring->glyphs);
1373 static MGlyphString scratch_gstring;
1375 static MGlyphString *
1376 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1379 MGlyphString *gstring;
1381 if (pos == mt->nchars)
1385 gstring = &scratch_gstring;
1386 if (gstring->size == 0)
1391 g_tmp.type = GLYPH_ANCHOR;
1392 APPEND_GLYPH (gstring, g_tmp);
1393 APPEND_GLYPH (gstring, g_tmp);
1394 APPEND_GLYPH (gstring, g_tmp);
1395 gstring->glyphs[1].type = GLYPH_SPACE;
1396 gstring->glyphs[1].g.c = '\n';
1397 gstring->glyphs[1].g.code = '\n';
1399 gstring->from = pos;
1401 g->rface = frame->rface;
1402 g->g.from = g->g.to = pos;
1404 g->rface = frame->rface;
1405 g->g.from = pos++, g->g.to = pos;
1407 g->rface = frame->rface;
1408 g->g.from = g->g.to = pos;
1413 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1414 MLIST_INIT1 (gstring, glyphs, 128);
1418 gstring->frame = frame;
1419 gstring->tick = frame->tick;
1420 gstring->top = gstring;
1421 gstring->control = *control;
1422 gstring->indent = gstring->width_limit = 0;
1423 if (control->format)
1424 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1426 gstring->width_limit = control->max_line_width;
1427 gstring->anti_alias = control->anti_alias;
1431 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1434 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1437 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1445 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1446 a width of glyphs for the character at I of MT. If I is not a
1447 beginning of a grapheme cluster, the corresponding element is
1449 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1450 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1451 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1452 pos_width[g->g.from - gstring->from] += g->g.xadv;
1453 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1455 if (pos_width[i] > 0)
1457 if (width + pos_width[i] > gstring->width_limit)
1460 width += pos_width[i];
1463 pos = gstring->from + i;
1464 if (gstring->control.line_break)
1466 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1467 gstring->from, gstring->from + i,
1469 if (pos <= gstring->from)
1471 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1474 else if (pos >= gstring->to)
1479 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1482 if (pos < gstring->to)
1484 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1485 layout_glyph_string (frame, gstring);
1490 /* Return a gstring that covers a character at POS. */
1492 static MGlyphString *
1493 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1495 MGlyphString *gstring = NULL;
1497 if (pos < mtext_nchars (mt))
1499 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1502 && ((prop->start != 0
1503 && mtext_ref_char (mt, prop->start - 1) != '\n')
1504 || (prop->end < mtext_nchars (mt)
1505 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1507 mtext_detach_property (prop);
1512 gstring = prop->val;
1513 if (gstring->frame != frame
1514 || gstring->tick != frame->tick
1515 || memcmp (control, &gstring->control,
1516 (char *) (&control->with_cursor)
1517 - (char *) (control))
1518 || control->cursor_pos != gstring->control.cursor_pos
1519 || control->cursor_width != gstring->control.cursor_width
1520 || control->cursor_bidi != gstring->control.cursor_bidi)
1522 mtext_detach_property (prop);
1527 else if (! control->cursor_width)
1535 offset = mtext_character (mt, pos, 0, '\n');
1540 offset -= gstring->from;
1542 for (gst = gstring; gst; gst = gst->next)
1546 gst->from += offset;
1548 for (i = 0; i < gst->used; i++)
1550 gst->glyphs[i].g.from += offset;
1551 gst->glyphs[i].g.to += offset;
1554 M17N_OBJECT_REF (gstring);
1559 int line = 0, y = 0;
1561 if (pos < mtext_nchars (mt))
1563 beg = mtext_character (mt, pos, 0, '\n');
1571 end = mtext_nchars (mt) + (control->cursor_width != 0);
1572 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1573 if (beg < mtext_nchars (mt))
1574 compose_glyph_string (frame, mt, beg, end, gstring);
1575 layout_glyph_string (frame, gstring);
1577 if (gstring->width_limit
1578 && gstring->width > gstring->width_limit)
1580 MGlyphString *gst = gstring;
1582 truncate_gstring (frame, mt, gst);
1583 while (gst->to < end)
1585 line++, y += gst->height;
1586 gst->next = alloc_gstring (frame, mt, gst->from, control,
1588 gst->next->top = gstring;
1589 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1591 layout_glyph_string (frame, gst);
1592 if (gst->width <= gst->width_limit)
1594 truncate_gstring (frame, mt, gst);
1598 if (! control->disable_caching && pos < mtext_nchars (mt))
1600 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1601 MTEXTPROP_VOLATILE_STRONG);
1603 if (end > mtext_nchars (mt))
1604 end = mtext_nchars (mt);
1605 mtext_attach_property (mt, beg, end, prop);
1606 M17N_OBJECT_UNREF (prop);
1610 while (gstring->to <= pos)
1612 if (! gstring->next)
1614 gstring = gstring->next;
1616 gstring->control = *control;
1622 static MDrawControl control_noop;
1624 #define ASSURE_CONTROL(control) \
1626 control = &control_noop; \
1631 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1632 MText *mt, int from, int to,
1633 MDrawControl *control)
1635 MGlyphString *gstring;
1637 M_CHECK_POS_X (mt, from, -1);
1638 ASSURE_CONTROL (control);
1639 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1640 to = mtext_nchars (mt) + (control->cursor_width != 0);
1644 gstring = get_gstring (frame, mt, from, to, control);
1646 MERROR (MERROR_DRAW, -1);
1647 render_glyph_string (frame, win, x, y, gstring, from, to);
1651 y += gstring->line_descent;
1652 M17N_OBJECT_UNREF (gstring->top);
1653 gstring = get_gstring (frame, mt, from, to, control);
1654 y += gstring->line_ascent;
1655 render_glyph_string (frame, win, x, y, gstring, from, to);
1658 M17N_OBJECT_UNREF (gstring->top);
1665 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1671 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1672 if (g->g.from <= pos && g->g.to > pos)
1677 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1678 if (g->g.from <= pos && g->g.to > pos)
1685 /* for debugging... */
1689 dump_gstring (MGlyphString *gstring, int indent, int type)
1691 char *prefix = (char *) alloca (indent + 1);
1692 MGlyph *g, *first_g, *last_g;
1694 memset (prefix, 32, indent);
1697 fprintf (stderr, "(glyph-string");
1701 first_g = MGLYPH (0);
1702 last_g = first_g + gstring->used;
1706 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1707 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1710 for (g = first_g; g < last_g; g++)
1713 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1716 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1717 : g->type == GLYPH_ANCHOR ? "ANC"
1718 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1719 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1720 g->g.xadv, g->bidi_level);
1721 if (g->g.xoff || g->g.yoff)
1722 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1723 fprintf (stderr, ")");
1725 fprintf (stderr, ")");
1729 /* m17n-X internal APIs */
1734 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1736 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1737 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1739 Mcommon = msymbol ("common");
1741 McatCc = msymbol ("Cc");
1742 McatCf = msymbol ("Cf");
1744 MbidiR = msymbol ("R");
1745 MbidiAL = msymbol ("AL");
1746 MbidiRLE = msymbol ("RLE");
1747 MbidiRLO = msymbol ("RLO");
1748 MbidiBN = msymbol ("BN");
1749 MbidiS = msymbol ("S");
1750 MbidiNSM = msymbol ("NSM");
1752 #if FRIBIDI_INTERFACE_VERSION < 3
1753 fribidi_set_mirroring (TRUE);
1755 fribidi_set_mirroring (1);
1759 M_break_at_space = msymbol ("bs");
1760 M_break_at_word = msymbol ("bw");
1761 M_break_at_any = msymbol ("ba");
1762 M_kinsoku_bol = msymbol ("kb");
1763 M_kinsoku_eol = msymbol ("ke");
1765 mflt_enable_new_feature = 1;
1773 MLIST_FREE1 (&scratch_gstring, glyphs);
1774 M17N_OBJECT_UNREF (linebreak_table);
1775 linebreak_table = NULL;
1779 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1783 /*** @addtogroup m17nDraw */
1788 @brief Draw an M-text on a window.
1790 The mdraw_text () function draws the text between $FROM and $TO of
1791 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1793 The appearance of the text (size, style, color, etc) is specified
1794 by the value of the text property whose key is @c Mface. If the
1795 M-text or a part of the M-text does not have such a text property,
1796 the default face of $FRAME is used.
1798 The font used to draw a character in the M-text is selected from
1799 the value of the fontset property of a face by the following
1804 <li> Search the text properties given to the character for the one
1805 whose key is @c Mcharset; its value should be either a symbol
1806 specifying a charset or #Mnil. If the value is #Mnil,
1807 proceed to the next step.
1809 Otherwise, search the mapping table of the fontset for the
1810 charset. If no entry is found proceed to the next step.
1812 If an entry is found, use one of the fonts in the entry that
1813 has a glyph for the character and that matches best with the
1814 face properties. If no such font exists, proceed to the next
1817 <li> Get the character property "script" of the character. If it is
1818 inherited, get the script property from the previous
1819 characters. If there is no previous character, or none of
1820 them has the script property other than inherited, proceed to
1823 Search the text properties given to the character for the one
1824 whose key is @c Mlanguage; its value should be either a
1825 symbol specifying a language or @c Mnil.
1827 Search the mapping table of the fontset for the combination
1828 of the script and language. If no entry is found, proceed to
1831 If an entry is found, use one of the fonts in the entry that
1832 has a glyph for the character and that matches best with the
1833 face properties. If no such font exists, proceed to the next
1836 <li> Search the fall-back table of the fontset for a font that has
1837 a glyph of the character. If such a font is found, use that
1842 If no font is found by the algorithm above, this function draws an
1843 empty box for the character.
1845 This function draws only the glyph foreground. To specify the
1846 background color, use mdraw_image_text () or
1847 mdraw_text_with_control ().
1849 This function is the counterpart of <tt>XDrawString ()</tt>,
1850 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1851 in the X Window System.
1854 If the operation was successful, mdraw_text () returns 0. If an
1855 error is detected, it returns -1 and assigns an error code to the
1856 external variable #merror_code. */
1858 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1860 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1861 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1863 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1864 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1865 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1866 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1868 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1869 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1873 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1874 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1875 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1876 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1877 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1878 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1880 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1881 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1883 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1884 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1885 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1887 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1888 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1890 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1891 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1893 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1894 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1896 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1897 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1901 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1903 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1904 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1906 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1907 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1910 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1911 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1913 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1920 mdraw_image_text () */
1923 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1924 MText *mt, int from, int to)
1926 MDrawControl control;
1928 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1929 memset (&control, 0, sizeof control);
1930 control.as_image = 0;
1931 return draw_text (frame, win, x, y, mt, from, to, &control);
1938 @brief Draw an M-text on a window as an image.
1940 The mdraw_image_text () function draws the text between $FROM and
1941 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1942 coordinate ($X, $Y).
1944 The way to draw a text is the same as in mdraw_text () except that
1945 this function also draws the background with the color specified
1948 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1949 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1950 functions in the X Window System.
1953 If the operation was successful, mdraw_image_text () returns 0.
1954 If an error is detected, it returns -1 and assigns an error code
1955 to the external variable #merror_code. */
1958 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1960 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1961 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1962 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1964 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1965 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1967 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1968 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1972 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1973 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1975 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1985 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1986 MText *mt, int from, int to)
1988 MDrawControl control;
1990 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1991 memset (&control, 0, sizeof control);
1992 control.as_image = 1;
1993 return draw_text (frame, win, x, y, mt, from, to, &control);
1999 @brief Draw an M-text on a window with fine control.
2001 The mdraw_text_with_control () function draws the text between
2002 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2003 coordinate ($X, $Y).
2005 The way to draw a text is the same as in mdraw_text () except that
2006 this function also follows what specified in the drawing control
2009 For instance, if \<two_dimensional\> of $CONTROL is nonzero, this
2010 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2011 breaks lines and the following characters are drawn in the next
2012 line. See the documentation of the structure @ MDrawControl for
2016 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2018 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2019 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2022 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2023 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2025 ¤¿¤È¤¨¤Ð $CONTROL ¤Î \<two_dimensional\> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2026 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2027 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2030 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2031 MText *mt, int from, int to, MDrawControl *control)
2033 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2034 return draw_text (frame, win, x, y, mt, from, to, control);
2040 @brief Compute text pixel width.
2042 The mdraw_text_extents () function computes the width of text
2043 between $FROM and $TO of M-text $MT when it is drawn on a window
2044 of frame $FRAME using the mdraw_text_with_control () function with
2045 the drawing control object $CONTROL.
2047 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2048 the bounding box of character ink of the M-text, and stores the
2049 results in the members of the structure pointed to by
2050 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2051 surrounding box, the box is included in the bounding box.
2053 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2054 computes the bounding box that provides minimum spacing to other
2055 graphical features (such as surrounding box) for the M-text, and
2056 stores the results in the members of the structure pointed to by
2057 $OVERALL_LOGICAL_RETURN.
2059 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2060 computes the bounding box that provides minimum spacing to the
2061 other M-text drawn, and stores the results in the members of the
2062 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2063 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2064 min_line_ascent, min_line_descent, max_line_ascent, and
2065 max_line_descent of $CONTROL are all zero.
2068 This function returns the width of the text to be drawn in the
2069 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2070 text is drawn in multiple physical lines, it returns the width of
2071 the widest line. If an error occurs, it returns -1 and assigns an
2072 error code to the external variable #merror_code. */
2076 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2078 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2079 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2080 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2082 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2083 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2084 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2085 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2087 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2088 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2089 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2090 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2092 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2093 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2094 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2095 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2096 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2097 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2100 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2101 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2102 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2104 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2111 mdraw_text_extents (MFrame *frame,
2112 MText *mt, int from, int to, MDrawControl *control,
2113 MDrawMetric *overall_ink_return,
2114 MDrawMetric *overall_logical_return,
2115 MDrawMetric *overall_line_return)
2117 MGlyphString *gstring;
2119 int width, lbearing, rbearing;
2121 ASSURE_CONTROL (control);
2122 M_CHECK_POS_X (mt, from, -1);
2123 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2124 to = mtext_nchars (mt) + (control->cursor_width != 0);
2128 gstring = get_gstring (frame, mt, from, to, control);
2130 MERROR (MERROR_DRAW, -1);
2131 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2132 if (overall_ink_return)
2133 overall_ink_return->y = - gstring->physical_ascent;
2134 if (overall_logical_return)
2135 overall_logical_return->y = - gstring->ascent;
2136 if (overall_line_return)
2137 overall_line_return->y = - gstring->line_ascent;
2139 for (from = gstring->to; from < to; from = gstring->to)
2141 int this_width, this_lbearing, this_rbearing;
2143 y += gstring->line_descent;
2144 M17N_OBJECT_UNREF (gstring->top);
2145 gstring = get_gstring (frame, mt, from, to, control);
2146 this_width = gstring_width (gstring, from, to,
2147 &this_lbearing, &this_rbearing);
2148 y += gstring->line_ascent;
2149 if (width < this_width)
2151 if (rbearing < this_rbearing)
2152 rbearing = this_rbearing;
2153 if (lbearing > this_lbearing)
2154 lbearing = this_lbearing;
2156 if (overall_ink_return)
2158 overall_ink_return->x = lbearing;
2159 overall_ink_return->width = rbearing - lbearing;
2160 overall_ink_return->height
2161 = y + gstring->physical_descent - overall_ink_return->y;
2163 if (overall_logical_return)
2165 overall_logical_return->x = 0;
2166 overall_logical_return->width = width;
2167 overall_logical_return->height
2168 = y + gstring->descent - overall_logical_return->y;
2170 if (overall_line_return)
2172 overall_line_return->x = lbearing;
2173 overall_line_return->width = MAX (width, rbearing - lbearing);
2174 overall_line_return->height
2175 = y + gstring->line_descent - overall_line_return->y;
2178 M17N_OBJECT_UNREF (gstring->top);
2185 @brief Compute the text dimensions of each character of M-text.
2187 The mdraw_text_per_char_extents () function computes the drawn
2188 metric of each character between $FROM and $TO of M-text $MT
2189 assuming that they are drawn on a window of frame $FRAME using the
2190 mdraw_text_with_control () function with the drawing control
2193 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2194 $LOGICAL_ARRAY_RETURN. Each successive element of
2195 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2196 ink and logical metrics of successive characters respectively,
2197 relative to the drawing origin of the M-text. The number of
2198 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2199 been set is returned to $NUM_CHARS_RETURN.
2201 If $ARRAY_SIZE is too small to return all metrics, the function
2202 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2203 Otherwise, it returns zero.
2205 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2206 @c NULL, this function also computes the metrics of the overall
2207 text and stores the results in the members of the structure
2208 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2210 If $CONTROL->two_dimensional is nonzero, this function computes
2211 only the metrics of characters in the first line. */
2213 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2215 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2216 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2217 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2219 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2220 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2221 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2222 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2223 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2225 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2226 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2229 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2230 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2231 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2233 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2236 mdraw_text_per_char_extents (MFrame *frame,
2237 MText *mt, int from, int to,
2238 MDrawControl *control,
2239 MDrawMetric *ink_array_return,
2240 MDrawMetric *logical_array_return,
2242 int *num_chars_return,
2243 MDrawMetric *overall_ink_return,
2244 MDrawMetric *overall_logical_return)
2246 MGlyphString *gstring;
2250 ASSURE_CONTROL (control);
2251 *num_chars_return = to - from;
2252 if (array_size < *num_chars_return)
2253 MERROR (MERROR_DRAW, -1);
2254 if (overall_logical_return)
2255 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2256 if (overall_ink_return)
2257 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2259 M_CHECK_RANGE (mt, from, to, -1, 0);
2260 gstring = get_gstring (frame, mt, from, to, control);
2263 *num_chars_return = 0;
2267 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2268 if (g->g.from >= from && g->g.from < to)
2270 int start = g->g.from;
2272 int width = g->g.xadv;
2273 int lbearing = g->g.lbearing;
2274 int rbearing = g->g.rbearing;
2275 int ascent = g->g.ascent;
2276 int descent = g->g.descent;
2278 int logical_descent;
2280 if (g->rface->rfont)
2282 logical_ascent = g->rface->rfont->ascent;
2283 logical_descent = g->rface->rfont->descent;
2287 logical_ascent = g->rface->ascent;
2288 logical_descent = g->rface->descent;
2290 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2292 if (lbearing < width + g->g.lbearing)
2293 lbearing = width + g->g.lbearing;
2294 if (rbearing < width + g->g.rbearing)
2295 rbearing = width + g->g.rbearing;
2297 if (ascent < g->g.ascent)
2298 ascent = g->g.ascent;
2299 if (descent < g->g.descent)
2300 descent = g->g.descent;
2307 if (ink_array_return)
2309 ink_array_return[start - from].x = x + lbearing;
2310 ink_array_return[start - from].y = - ascent;
2311 ink_array_return[start - from].width = rbearing - lbearing;
2312 ink_array_return[start - from].height = ascent + descent;
2314 if (logical_array_return)
2316 logical_array_return[start - from].x = x;
2317 logical_array_return[start - from].y = - logical_descent;
2318 logical_array_return[start - from].height
2319 = logical_ascent + logical_descent;
2320 logical_array_return[start - from].width = width;
2328 if (overall_ink_return)
2330 overall_ink_return->y = - gstring->line_ascent;
2331 overall_ink_return->x = gstring->lbearing;
2332 overall_ink_return->width = x - gstring->lbearing;
2333 overall_ink_return->height = gstring->height;
2335 if (overall_logical_return)
2337 overall_logical_return->y = - gstring->ascent;
2338 overall_logical_return->x = 0;
2339 overall_logical_return->width = x;
2340 overall_logical_return->height = gstring->ascent + gstring->descent;
2343 M17N_OBJECT_UNREF (gstring->top);
2350 @brief Return the character position nearest to the coordinates.
2352 The mdraw_coordinates_position () function checks which character
2353 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2354 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2355 mdraw_text_with_control () function with the drawing control
2356 object $CONTROL. Here, the character position means the number of
2357 characters that precede the character in question in $MT, that is,
2358 the character position of the first character is 0.
2360 $FRAME is used only to get the default face information.
2363 If the glyph image of a character covers coordinate ($X, $Y),
2364 mdraw_coordinates_position () returns the character position of
2366 If $Y is less than the minimum Y-coordinate of the drawn area, it
2368 If $Y is greater than the maximum Y-coordinate of the drawn area,
2370 If $Y fits in with the drawn area but $X is less than the minimum
2371 X-coordinate, it returns the character position of the first
2372 character drawn on the line $Y.\n\n
2373 If $Y fits in with the drawn area but $X is greater than the
2374 maximum X-coordinate, it returns the character position of the
2375 last character drawn on the line $Y. */
2378 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2380 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2381 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2382 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2383 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2384 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2385 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2387 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2390 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2391 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2392 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2393 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2394 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2395 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2396 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2397 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2400 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2401 int x_offset, int y_offset, MDrawControl *control)
2403 MGlyphString *gstring;
2408 M_CHECK_POS_X (mt, from, -1);
2409 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2410 to = mtext_nchars (mt) + (control->cursor_width != 0);
2416 ASSURE_CONTROL (control);
2417 gstring = get_gstring (frame, mt, from, to, control);
2418 while (y + gstring->line_descent <= y_offset
2419 && gstring->to < to)
2422 y += gstring->line_descent;
2423 M17N_OBJECT_UNREF (gstring->top);
2424 gstring = get_gstring (frame, mt, from, to, control);
2425 y += gstring->line_ascent;
2428 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2429 if (! control->orientation_reversed)
2431 width = gstring->indent;
2432 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2433 if (g->g.from >= from && g->g.from < to)
2436 if (width > x_offset)
2442 width = - gstring->indent;
2443 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2444 if (g->g.from >= from && g->g.from < to)
2447 if (width < x_offset)
2451 if (g->type == GLYPH_ANCHOR
2452 && control->two_dimensional
2453 && g[-1].g.c == '\n')
2456 M17N_OBJECT_UNREF (gstring->top);
2464 @brief Compute information about a glyph.
2466 The mdraw_glyph_info () function computes information about a
2467 glyph that covers a character at position $POS of the M-text $MT
2468 assuming that the text is drawn from the character at $FROM of $MT
2469 on a window of frame $FRAME using the mdraw_text_with_control ()
2470 function with the drawing control object $CONTROL.
2472 The information is stored in the members of $INFO. */
2474 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2476 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2477 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2478 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2479 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2481 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2489 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2490 MDrawControl *control, MDrawGlyphInfo *info)
2492 MGlyphString *gstring;
2496 M_CHECK_RANGE_X (mt, from, pos, -1);
2498 ASSURE_CONTROL (control);
2499 gstring = get_gstring (frame, mt, from, pos + 1, control);
2501 MERROR (MERROR_DRAW, -1);
2502 while (gstring->to <= pos)
2504 y += gstring->line_descent;
2505 M17N_OBJECT_UNREF (gstring->top);
2506 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2507 y += gstring->line_ascent;
2509 info->line_from = gstring->from;
2510 if (info->line_from < from)
2511 info->line_from = from;
2512 info->line_to = gstring->to;
2515 if (! control->orientation_reversed)
2517 info->x = gstring->indent;
2518 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2519 info->x += g->g.xadv;
2523 info->x = - gstring->indent;
2524 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2525 info->x -= g->g.xadv;
2526 while (g[-1].g.to == g->g.to)
2529 info->from = g->g.from;
2531 info->metrics.x = g->g.lbearing;
2532 info->metrics.y = - gstring->line_ascent;
2533 info->metrics.height = gstring->height;
2534 info->metrics.width = - g->g.lbearing + g->g.xadv;
2535 if (g->rface->rfont)
2536 info->font = (MFont *) g->rface->rfont;
2539 /* info->logical_width is calculated later. */
2541 if (info->from > info->line_from)
2543 /* The logically previous glyph is on this line. */
2544 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2546 info->prev_from = g_tmp->g.from;
2548 else if (info->line_from > 0
2549 && gstring->from > 0)
2551 /* The logically previous glyph is on the previous line. */
2552 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2553 gstring->from, control);
2554 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2556 info->prev_from = g_tmp->g.from;
2557 M17N_OBJECT_UNREF (gst->top);
2560 info->prev_from = -1;
2562 if (GLYPH_INDEX (g) > 1)
2563 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2564 else if (! control->orientation_reversed)
2566 if (info->line_from > 0)
2570 int p = gstring->from - 1;
2572 gst = get_gstring (frame, mt, p, gstring->from, control);
2573 g_tmp = gst->glyphs + (gst->used - 2);
2574 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2575 M17N_OBJECT_UNREF (gst->top);
2578 info->left_from = info->left_to = -1;
2582 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2586 int p = gstring->to;
2588 gst = get_gstring (frame, mt, p, p + 1, control);
2589 g_tmp = gst->glyphs + (gst->used - 2);
2590 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2591 M17N_OBJECT_UNREF (gst->top);
2594 info->left_from = info->left_to = -1;
2597 if (info->to < gstring->to)
2599 /* The logically next glyph is on this line. */
2600 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2602 info->next_to = g_tmp->g.to;
2604 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2606 /* The logically next glyph is on the next line. */
2608 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2609 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2611 info->next_to = g_tmp->g.to;
2612 M17N_OBJECT_UNREF (gst->top);
2617 for (info->logical_width = (g++)->g.xadv;
2618 g->g.from == pos && g->type != GLYPH_ANCHOR;
2619 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2620 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2622 if (g->type != GLYPH_ANCHOR)
2623 info->right_from = g->g.from, info->right_to = g->g.to;
2624 else if (! control->orientation_reversed)
2626 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2629 M17N_OBJECT_UNREF (gstring->top);
2630 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2632 info->right_from = g->g.from, info->right_to = g->g.to;
2635 info->right_from = info->right_to = -1;
2639 if (info->line_from > 0)
2641 pos = gstring->from - 1;
2642 M17N_OBJECT_UNREF (gstring->top);
2643 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2645 info->right_from = g->g.from, info->right_to = g->g.to;
2648 info->right_from = info->right_to = -1;
2651 M17N_OBJECT_UNREF (gstring->top);
2658 @brief Compute information about glyph sequence.
2660 The mdraw_glyph_list () function computes information about glyphs
2661 corresponding to the text between $FROM and $TO of M-text $MT when
2662 it is drawn on a window of frame $FRAME using the
2663 mdraw_text_with_control () function with the drawing control
2664 object $CONTROL. $GLYPHS is an array of objects to store the
2665 information, and $ARRAY_SIZE is the array size.
2667 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2668 number of actually filled elements in the place pointed by
2669 $NUM_GLYPHS_RETURN, and returns 0.
2671 Otherwise, it stores the required array size in the place pointed
2672 by $NUM_GLYPHS_RETURN, and returns -1. */
2675 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2677 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2678 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2679 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2680 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2682 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2683 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2686 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2696 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2697 MDrawControl *control, MDrawGlyph *glyphs,
2698 int array_size, int *num_glyphs_return)
2700 MGlyphString *gstring;
2705 ASSURE_CONTROL (control);
2706 *num_glyphs_return = 0;
2707 M_CHECK_RANGE (mt, from, to, -1, 0);
2708 gstring = get_gstring (frame, mt, from, to, control);
2711 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2713 if (g->type == GLYPH_BOX
2714 || g->g.from < from || g->g.from >= to)
2716 if (g->type == GLYPH_PAD)
2718 if (g->left_padding)
2719 pad_width = g->g.xadv;
2723 glyphs[-1].x_advance += g->g.xadv;
2729 glyphs->from = g->g.from;
2730 glyphs->to = g->g.to;
2731 glyphs->glyph_code = g->g.code;
2732 glyphs->x_off = g->g.xoff + pad_width;
2733 glyphs->y_off = g->g.yoff;
2734 glyphs->lbearing = g->g.lbearing;
2735 glyphs->rbearing = g->g.rbearing;
2736 glyphs->ascent = g->g.ascent;
2737 glyphs->descent = g->g.descent;
2738 glyphs->x_advance = g->g.xadv + pad_width;
2739 glyphs->y_advance = 0;
2740 if (g->rface->rfont)
2742 glyphs->font = (MFont *) g->rface->rfont;
2743 #ifdef HAVE_FREETYPE
2745 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2746 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2748 #else /* not HAVE_FREETYPE */
2749 glyphs->font_type = Mx;
2750 #endif /* not HAVE_FREETYPE */
2751 glyphs->fontp = g->rface->rfont->fontp;
2755 glyphs->font = NULL;
2756 glyphs->font_type = Mnil;
2757 glyphs->fontp = NULL;
2764 M17N_OBJECT_UNREF (gstring->top);
2766 *num_glyphs_return = n;
2767 return (n <= array_size ? 0 : -1);
2773 @brief Draw one or more textitems.
2775 The mdraw_text_items () function draws one or more M-texts on
2776 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2777 of the textitems to be drawn and $NITEMS is the number of
2778 textitems in the array. */
2781 @brief textitem ¤òɽ¼¨¤¹¤ë.
2783 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2784 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2785 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2787 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2791 MTextItem, mdraw_text (). */
2794 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2795 MDrawTextItem *items, int nitems)
2797 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2799 while (nitems-- > 0)
2802 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2804 mdraw_text_with_control (frame, win, x, y,
2805 items->mt, 0, mtext_nchars (items->mt),
2807 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2808 items->control, NULL, NULL, NULL);
2811 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2817 @brief Option of line breaking for drawing text.
2819 The variable #mdraw_line_break_option specifies line breaking
2820 options by logical-or of the members of #MTextLineBreakOption. It
2821 controls the line breaking algorithm of the function
2822 mdraw_default_line_break (). */
2824 int mdraw_line_break_option;
2828 @brief Calculate a line breaking position.
2830 The function mdraw_default_line_break () calculates a line
2831 breaking position based on the line number $LINE and the
2832 coordinate $Y, when a line is too long to fit within the width
2833 limit. $POS is the position of the character next to the last one
2834 that fits within the limit. $FROM is the position of the first
2835 character of the line, and $TO is the position of the last
2836 character displayed on the line if there were not width limit.
2837 $LINE and $Y are reset to 0 when a line is broken by a newline
2838 character, and incremented each time when a long line is broken
2839 because of the width limit.
2842 This function returns a character position to break the
2847 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2849 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2850 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2851 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2852 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2853 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2854 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2855 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2858 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2862 mdraw_default_line_break (MText *mt, int pos,
2863 int from, int to, int line, int y)
2867 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2878 @brief Obtain per character dimension information.
2880 The mdraw_per_char_extents () function computes the text dimension
2881 of each character in M-text $MT. The faces given as text
2882 properties in $MT and the default face of frame $FRAME determine
2883 the fonts to draw the text. Each successive element in
2884 $ARRAY_RETURN is set to the drawn metrics of successive
2885 characters, which is relative to the origin of the drawing, and a
2886 rectangle for each character in $MT. The number of elements of
2887 $ARRAY_RETURN must be equal to or greater than the number of
2890 If pointer $OVERALL_RETURN is not @c NULL, this function also
2891 computes the extents of the overall text and stores the results in
2892 the members of the structure pointed to by $OVERALL_RETURN. */
2895 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2897 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2898 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2899 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2900 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2901 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2902 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2903 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2905 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2906 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2907 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2909 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2912 mdraw_per_char_extents (MFrame *frame, MText *mt,
2913 MDrawMetric *array_return,
2914 MDrawMetric *overall_return)
2916 int n = mtext_nchars (mt);
2918 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2919 n, &n, overall_return, NULL);
2923 @brief clear cached information.
2925 The mdraw_clear_cache () function clear cached information
2926 on M-text $MT that was attached by any of the drawing functions.
2927 When the behavior of `format' or `line_break'
2928 member functions of MDrawControl is changed, the cache must be cleared.
2933 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2935 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2936 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2937 ¤¢¤ë¤¤¤Ï `line_break'
2938 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2944 mdraw_clear_cache (MText *mt)
2946 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);