1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007
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];
243 reorder_combining_chars (MGlyphString *gstring, int from, int to)
245 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
251 for (g = gbeg; g != gend; g++)
252 if (COMBINING_CODE_CLASS (g->combining_code) > 0
253 && (COMBINING_CODE_CLASS (g[-1].combining_code)
254 > COMBINING_CODE_CLASS (g->combining_code)))
266 run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
268 MRealizedFont *rfont = rface->rfont;
269 MSymbol layouter = rface->layouter;
270 MFLTGlyphString flt_gstr;
271 MFLTFontForRealized font;
273 int from_pos = MGLYPH (from)->g.from;
277 flt = mflt_get (layouter);
278 flt_gstr.glyph_size = sizeof (MGlyph);
279 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
280 flt_gstr.used = gstring->used;
281 flt_gstr.allocated = gstring->size;
283 font.font.family = mfont_get_prop (rfont->font, Mfamily);
284 font.font.x_ppem = rfont->x_ppem;
285 font.font.y_ppem = rfont->y_ppem;
286 font.font.get_glyph_id = mfont__get_glyph_id;
287 font.font.get_metrics = mfont__get_metrics;
288 font.font.check_otf = rfont->driver->check_otf;
289 font.font.drive_otf = rfont->driver->drive_otf;
290 font.font.internal = NULL;
292 for (i = 0; i < 3; i++)
294 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
297 APPEND_GLYPH (gstring, *MGLYPH (0));
298 APPEND_GLYPH (gstring, *MGLYPH (0));
301 if (from + len != to)
302 gstring->used += to - (from + len);
303 for (i = from; i < to; i++)
305 MGlyph *g = MGLYPH (i);
307 g->g.from += from_pos - from;
308 g->g.to += from_pos - from + 1;
322 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
323 displaying them on FRAME.
325 This function fills these members:
326 pos, to, c, code, rface, bidi_level, categories, type, combining_code
327 The other members are filled by layout_glyph_string. */
330 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
331 MGlyphString *gstring)
333 MRealizedFace *default_rface = frame->rface;
334 int stop, face_change, language_change, charset_change, font_change;
335 MGlyph g_tmp, *g, *last_g;
337 MSymbol language = Mnil, script = Mnil, charset = Mnil;
338 MSymbol non_latin_script = Mnil;
339 MRealizedFace *rface = default_rface;
340 MRealizedFont *rfont;
341 int size = gstring->control.fixed_width;
342 int max_bidi_level = 0;
345 MLIST_RESET (gstring);
346 gstring->from = from;
348 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
349 <category> and <rface> members.*/
352 /** Put anchor glyphs at the head and tail. */
353 g_tmp.type = GLYPH_ANCHOR;
354 g_tmp.g.from = g_tmp.g.to = from;
355 APPEND_GLYPH (gstring, g_tmp);
356 stop = face_change = font_change = pos = from;
366 if (pos < mtext_nchars (mt))
368 MFont *font = rface->font;
372 if (pos == font_change)
374 font = mtext_get_prop (mt, pos, Mfont);
375 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
376 if (font_change == mtext_nchars (mt))
379 if (pos == face_change)
381 num = mtext_get_prop_values (mt, pos, Mface,
382 (void **) faces, 64);
383 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
384 if (face_change == mtext_nchars (mt))
389 faces[0] = &rface->face;
392 rface = mface__realize (frame, faces, num, size, font);
395 rface = default_rface;
397 if (stop > font_change)
399 if (stop > face_change)
403 if (pos < mtext_nchars (mt))
404 c = mtext_ref_char (mt, pos);
408 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
410 g_tmp.g.from = pos++;
413 category = mchar_get_prop (c, Mcategory);
414 if (category == McatCf)
415 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
416 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
417 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
419 g_tmp.category = GLYPH_CATEGORY_NORMAL;
421 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
425 ctrl[0] = ctrl[1] = g_tmp;
427 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
428 APPEND_GLYPH (gstring, ctrl[0]);
429 APPEND_GLYPH (gstring, ctrl[1]);
432 APPEND_GLYPH (gstring, g_tmp);
433 if (c == '\n' && gstring->control.two_dimensional)
436 /* Append an anchor glyph. */
438 g_tmp.type = GLYPH_ANCHOR;
439 g_tmp.g.from = g_tmp.g.to = pos;
440 APPEND_GLYPH (gstring, g_tmp);
443 if (gstring->control.enable_bidi)
444 max_bidi_level = analyse_bidi_level (gstring);
446 /* The next loop is to change each <rface> member for non-ASCII
447 characters if necessary. */
448 stop = charset_change = language_change = from;
449 rfont = default_rface->rfont;
450 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
456 /* Short cut for the obvious case. */
457 this_script = Mlatin;
460 this_script = (MSymbol) mchar_get_prop (c, Mscript);
461 if (this_script == Minherited || this_script == Mcommon)
465 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
467 if (MSYMBOL_NAME (category)[0] != 'Z')
468 this_script = script;
471 if (this_script == Mcommon && non_latin_script)
472 this_script = non_latin_script;
473 if (this_script == Mcommon)
475 /* Search forward for a character that explicitly
476 specifies a non-latin script. */
480 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
482 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
483 && sym != Minherited)
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->g.from != gstring->control.cursor_pos
553 && g->rface->layouter == this->rface->layouter
554 && (g->rface->rfont == this->rface->rfont
555 || (g->category == GLYPH_CATEGORY_FORMATTER
556 && (mfont__encode_char (NULL,
557 (MFont *) this->rface->rfont,
559 != MCHAR_INVALID_CODE))));
561 g->rface->rfont = this->rface->rfont;
562 i = run_flt (gstring, start, i, this->rface);
567 while (g->type == GLYPH_CHAR
569 && g->category == GLYPH_CATEGORY_MODIFIER
571 && g->rface->layouter == Mnil)
575 this->rface->layouter = Mcombining;
576 run_flt (gstring, start, i, this->rface);
579 mfont__get_metric (gstring, start, i);
587 /* At last, reorder glyphs visually if necessary. */
588 if (max_bidi_level > 0)
589 visual_order (gstring);
593 int width, lbearing, rbearing;
597 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
598 MSubTextExtents *extents)
600 int g_physical_ascent, g_physical_descent;
601 MGlyph *g = MGLYPH (from);
602 MGlyph *last_g = MGLYPH (to);
604 g_physical_ascent = gstring->physical_ascent;
605 g_physical_descent = gstring->physical_descent;
606 extents->width = extents->lbearing = extents->rbearing = 0;
608 for (g = MGLYPH (from); g < last_g; g++)
610 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
611 g_physical_descent = MAX (g_physical_descent, g->g.descent);
612 extents->lbearing = MIN (extents->lbearing,
613 extents->width + g->g.lbearing);
614 extents->rbearing = MAX (extents->rbearing,
615 extents->width + g->g.rbearing);
616 extents->width += g->g.xadv;
619 gstring->physical_ascent = g_physical_ascent;
620 gstring->physical_descent = g_physical_descent;
624 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
625 by this function directly. Character glyphs are handled by
626 layouter functions registered in font drivers.
628 This function fill-in all the remaining members of glyphs. */
631 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
633 /* Default width of TAB. */
634 int tab_width = frame->space_width * (gstring->control.tab_width
635 ? gstring->control.tab_width : 8);
639 MDrawControl *control = &(gstring->control);
642 int box_line_height = 0;
643 int ignore_formatting_char = control->ignore_formatting_char;
645 gstring->ascent = gstring->descent = 0;
646 gstring->physical_ascent = gstring->physical_descent = 0;
647 gstring->width = gstring->lbearing = gstring->rbearing = 0;
651 while (g->type != GLYPH_ANCHOR)
653 if (box != g->rface->box)
655 int gidx = GLYPH_INDEX (g);
659 /* Insert the right side of the box. That glyph belongs
660 to the previous grapheme cluster. */
661 MGlyph box_glyph = g[-1];
663 box_glyph.type = GLYPH_BOX;
665 = (control->fixed_width
667 : box->inner_hmargin + box->width + box->outer_hmargin);
668 box_glyph.g.lbearing = 0;
669 box_glyph.g.rbearing = box_glyph.g.xadv;
670 box_glyph.g.xoff = 0;
671 box_glyph.right_padding = 1;
672 gstring->width += box_glyph.g.xadv;
673 gstring->rbearing += box_glyph.g.xadv;
674 INSERT_GLYPH (gstring, gidx, box_glyph);
681 /* Insert the left side of the box. That glyph belongs
682 to the following grapheme cluster. */
683 MGlyph box_glyph = *g;
684 int box_height = (box->width
685 + box->inner_vmargin + box->outer_vmargin);
687 if (box_line_height < box_height)
688 box_line_height = box_height;
689 box_glyph.type = GLYPH_BOX;
691 = (control->fixed_width
693 : box->inner_hmargin + box->width + box->outer_hmargin);
694 box_glyph.g.lbearing = 0;
695 box_glyph.g.rbearing = box_glyph.g.xadv;
696 box_glyph.g.xoff = 0;
697 box_glyph.left_padding = 1;
698 gstring->width += box_glyph.g.xadv;
699 gstring->rbearing += box_glyph.g.xadv;
700 INSERT_GLYPH (gstring, gidx, box_glyph);
706 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
707 g->type = GLYPH_SPACE;
709 if (g->type == GLYPH_CHAR)
711 MRealizedFace *rface = g->rface;
712 MRealizedFont *rfont = rface->rfont;
714 int from = GLYPH_INDEX (g);
716 for (g++; g->type == GLYPH_CHAR; g++)
717 if (! rfont != ! g->rface->rfont
718 || box != g->rface->box
719 || ((fromg->g.code == MCHAR_INVALID_CODE)
720 != (g->g.code == MCHAR_INVALID_CODE))
721 || (g->category == GLYPH_CATEGORY_FORMATTER
722 && ignore_formatting_char))
724 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
727 int to = GLYPH_INDEX (g);
728 MSubTextExtents extents;
730 layout_glyphs (frame, gstring, from, to, &extents);
731 extra_width = - extents.lbearing;
733 && ! control->disable_overlapping_adjustment
734 && (! control->orientation_reversed
735 ? ((to > 1 || control->align_head)
736 && g->type != GLYPH_ANCHOR)
737 : (((g->type && GLYPH_ANCHOR) || control->align_head)
742 pad.type = GLYPH_PAD;
745 pad.g.xadv = pad.g.rbearing = extra_width;
746 pad.left_padding = 1;
747 INSERT_GLYPH (gstring, from, pad);
749 extents.lbearing = 0;
750 extents.width += extra_width;
751 extents.rbearing += extra_width;
753 g = MGLYPH (from - 1);
754 if (g->type == GLYPH_SPACE)
756 /* The pad just inserted is absorbed (maybe
757 partially) by the previous space while
758 keeping at least some space width. For the
759 moment, we use the arbitrary width 2-pixel.
760 Perhaps, it should be decided by the current
761 face, or a default value of the current
762 frame, which is, however, not yet
764 if (extra_width + 2 < g->g.xadv)
766 g->g.xadv -= extra_width;
770 extra_width = g->g.xadv - 2;
773 gstring->width -= extra_width;
774 gstring->rbearing -= extra_width;
779 extra_width = extents.rbearing - extents.width;
781 && ! control->disable_overlapping_adjustment
782 && (GLYPH_INDEX (g) < gstring->used - 1
783 || (control->orientation_reversed && control->align_head)))
785 if (g->type == GLYPH_SPACE && box == g->rface->box)
788 pad.type = GLYPH_PAD;
791 pad.g.xadv = pad.g.rbearing = extra_width;
792 INSERT_GLYPH (gstring, to, pad);
797 g[-1].g.xadv += extra_width;
798 extents.width += extra_width;
801 if (gstring->lbearing > gstring->width + extents.lbearing)
802 gstring->lbearing = gstring->width + extents.lbearing;
803 if (gstring->rbearing < gstring->width + extents.rbearing)
804 gstring->rbearing = gstring->width + extents.rbearing;
805 gstring->width += extents.width;
806 if (gstring->ascent < rface->ascent)
807 gstring->ascent = rface->ascent;
808 if (gstring->descent < rface->descent)
809 gstring->descent = rface->descent;
813 for (; fromg < g; fromg++)
815 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
816 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
817 fromg->g.xadv = fromg->g.rbearing = 1;
819 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
820 fromg->g.xoff = fromg->g.lbearing = 0;
821 fromg->g.ascent = fromg->g.descent = 0;
822 gstring->width += fromg->g.xadv;
823 gstring->rbearing += fromg->g.xadv;
825 if (gstring->ascent < frame->rface->ascent)
826 gstring->ascent = frame->rface->ascent;
827 if (gstring->descent < frame->descent)
828 gstring->descent = frame->rface->descent;
831 else if (g->type == GLYPH_SPACE)
834 g->g.xadv = g->rface->space_width;
835 else if (g->g.c == '\n')
837 g->g.xadv = control->cursor_width;
840 if (control->cursor_bidi)
842 else if (g->g.xadv < 0)
843 g->g.xadv = g->rface->space_width;
846 else if (g->g.c == '\t')
848 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
854 if (g[-1].type == GLYPH_PAD)
856 /* This space glyph absorbs (maybe partially) the
857 previous padding glyph. */
858 g->g.xadv -= g[-1].g.xadv;
860 /* But, keep at least some space width. For the
861 moment, we use the arbitrary width 2-pixel. */
864 g->g.rbearing = g->g.xadv;
865 gstring->width += g->g.xadv;
866 gstring->rbearing += g->g.xadv;
869 if (gstring->ascent < g->rface->ascent)
870 gstring->ascent = g->rface->ascent;
871 if (gstring->descent < g->rface->descent)
872 gstring->descent = g->rface->descent;
878 gstring->width += g->g.xadv;
879 gstring->rbearing += g->g.xadv;
886 /* Insert the right side of the box. */
887 int gidx = GLYPH_INDEX (g);
888 MGlyph box_glyph = g[-1];
890 box_glyph.type = GLYPH_BOX;
892 = (control->fixed_width
894 : box->inner_hmargin + box->width + box->outer_hmargin);
895 box_glyph.g.lbearing = 0;
896 box_glyph.g.rbearing = box_glyph.g.xadv;
897 box_glyph.g.xoff = 0;
898 box_glyph.right_padding = 1;
899 gstring->width += box_glyph.g.xadv;
900 gstring->rbearing += box_glyph.g.xadv;
901 INSERT_GLYPH (gstring, gidx, box_glyph);
904 gstring->text_ascent = gstring->ascent;
905 gstring->text_descent = gstring->descent;
906 if (gstring->text_ascent < gstring->physical_ascent)
907 gstring->text_ascent = gstring->physical_ascent;
908 if (gstring->text_descent < gstring->physical_descent)
909 gstring->text_descent = gstring->physical_descent;
910 gstring->line_ascent = gstring->text_ascent;
911 gstring->line_descent = gstring->text_descent;
912 if (box_line_height > 0)
914 gstring->line_ascent += box_line_height;
915 gstring->physical_ascent = gstring->line_ascent;
916 gstring->line_descent += box_line_height;
917 gstring->physical_descent = gstring->line_descent;
920 if (gstring->line_ascent < control->min_line_ascent)
921 gstring->line_ascent = control->min_line_ascent;
922 else if (control->max_line_ascent
923 && control->max_line_ascent > control->min_line_ascent
924 && gstring->line_ascent > control->max_line_ascent)
925 gstring->line_ascent = control->max_line_ascent;
927 if (gstring->line_descent < control->min_line_descent)
928 gstring->line_descent = control->min_line_descent;
929 else if (control->max_line_descent
930 && control->max_line_descent > control->min_line_descent
931 && gstring->line_descent > control->max_line_descent)
932 gstring->line_descent = control->max_line_descent;
933 gstring->height = gstring->line_ascent + gstring->line_descent;
935 if (control->orientation_reversed
938 /* We must adjust TAB width for RTL orientation. */
939 width = gstring->indent;
941 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
943 if (g->type == GLYPH_CHAR && g->g.c == '\t')
945 int this_width = tab_width - (width % tab_width);
947 if (g[1].type == GLYPH_PAD)
948 this_width -= g[1].g.xadv;
949 if (g[-1].type == GLYPH_PAD)
950 this_width -= g[-1].g.xadv;
953 gstring->width += this_width - g->g.xadv;
954 gstring->rbearing += this_width - g->g.xadv;
955 g->g.xadv = this_width;
966 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
967 MGlyphString *gstring, int from, int to,
968 int *from_idx, int *to_idx, int *to_x)
970 MGlyph *g = MGLYPH (1);
971 MDrawRegion region = (MDrawRegion) NULL;
972 MDrawControl *control = &gstring->control;
975 int cursor_bidi = control->cursor_bidi;
977 if (control->with_cursor && control->cursor_width)
979 if (gstring->from <= control->cursor_pos
980 && gstring->to > control->cursor_pos)
981 cursor_pos = control->cursor_pos;
984 && gstring->from <= control->cursor_pos - 1
985 && gstring->to > control->cursor_pos - 1)
986 prev_pos = control->cursor_pos - 1;
989 *from_idx = *to_idx = 0;
991 while (g->type != GLYPH_ANCHOR)
993 if (g->g.from >= from && g->g.from < to)
995 MGlyph *fromg = g, *cursor = NULL;
996 MRealizedFace *rface = g->rface;
998 int cursor_width = 0;
1002 *from_idx = GLYPH_INDEX (g);
1003 while (g->g.from >= from && g->g.from < to
1004 && g->rface == rface)
1007 if (g->type != GLYPH_BOX
1008 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1011 cursor = g, cursor_x = x + width;
1012 cursor_width += g->g.xadv;
1014 width += g++->g.xadv;
1017 && (control->as_image
1018 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1020 int this_x = x, this_width = width;
1022 if (fromg->type == GLYPH_BOX)
1023 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1024 if (g[-1].type == GLYPH_BOX)
1025 this_width -= g[-1].g.xadv;
1026 (frame->driver->fill_space)
1027 (frame, win, rface, 0,
1028 this_x, y - gstring->text_ascent, this_width,
1029 gstring->text_ascent + gstring->text_descent,
1030 control->clip_region);
1037 rect.y = y - gstring->text_ascent;
1038 rect.height = gstring->text_ascent + gstring->text_descent;
1041 rect.width = ((control->cursor_width > 0
1042 && control->cursor_width < cursor_width)
1043 ? control->cursor_width : cursor_width);
1047 if (cursor->bidi_level % 2)
1048 rect.x += cursor_width - rect.width;
1049 (*frame->driver->fill_space)
1050 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1051 control->clip_region);
1053 region = (*frame->driver->region_from_rect) (&rect);
1055 (*frame->driver->region_add_rect) (region, &rect);
1058 if (cursor->bidi_level % 2)
1061 rect.width = cursor_width < 4 ? cursor_width : 4;
1062 (*frame->driver->fill_space)
1063 (frame, win, rface, 1,
1064 rect.x, rect.y, rect.width, rect.height,
1065 control->clip_region);
1066 (*frame->driver->region_add_rect) (region, &rect);
1078 if (fromg->type != GLYPH_BOX
1079 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1082 cursor = fromg, cursor_x = x + temp_width;
1083 cursor_width += fromg->g.xadv;
1085 temp_width += fromg++->g.xadv;
1092 if (! (cursor->bidi_level % 2))
1093 rect.x += cursor_width - 1;
1094 rect.y = y - gstring->text_ascent;
1095 rect.height = gstring->text_ascent + gstring->text_descent;
1097 (*frame->driver->fill_space)
1098 (frame, win, rface, 1,
1099 rect.x, rect.y, rect.width, rect.height,
1100 control->clip_region);
1102 region = (*frame->driver->region_from_rect) (&rect);
1104 (*frame->driver->region_add_rect) (region, &rect);
1105 rect.y += rect.height - 2;
1107 rect.width = cursor_width < 4 ? cursor_width : 4;
1108 if (! (cursor->bidi_level % 2))
1109 rect.x -= rect.width - 1;
1110 (*frame->driver->fill_space) (frame, win, rface, 1,
1111 rect.x, rect.y, rect.width, rect.height,
1112 control->clip_region);
1113 (*frame->driver->region_add_rect) (region, &rect);
1117 *to_idx = GLYPH_INDEX (g);
1127 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1128 MGlyphString *gstring, int from_idx, int to_idx,
1129 int reverse, MDrawRegion region)
1131 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1137 (*frame->driver->region_to_rect) (region, &rect);
1140 while (g != gend && x + g->g.rbearing <= rect.x)
1143 width -= g++->g.xadv;
1144 while (! g->enabled && g != gend)
1148 rect.x += rect.width;
1149 if (rect.x < x + width)
1152 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1154 width -= (--gend)->g.xadv;
1155 while (! gend->enabled && g != gend)
1159 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1168 MRealizedFace *rface = g->rface;
1169 int width = g->g.xadv;
1170 MGlyph *from_g = g++;
1172 /* Handle the glyphs of the same type/face at once. */
1174 && g->type == from_g->type
1175 && g->rface == rface
1176 && ((g->g.code == MCHAR_INVALID_CODE)
1177 == (from_g->g.code == MCHAR_INVALID_CODE))
1179 width += g++->g.xadv;
1181 if (from_g->type == GLYPH_CHAR)
1183 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1184 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1187 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1190 else if (from_g->type == GLYPH_BOX)
1192 /* Draw the left or right side of a box. If
1193 from_g->lbearing is nonzero, this is the left side,
1194 else this is the right side. */
1195 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1198 if (from_g->type != GLYPH_BOX)
1201 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1202 x, y, width, region);
1205 /* Draw the top and bottom side of a box. */
1206 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1207 x, y, width, region);
1218 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1219 int *from_x, int *to_x)
1222 int left_idx = *left, right_idx = *right;
1223 int left_x, right_x, x;
1225 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1228 if (x + g->g.rbearing > 0)
1230 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1232 left_idx = GLYPH_INDEX (g);
1237 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1240 if (x - g->g.xadv + g->g.lbearing < 0)
1242 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1244 right_idx = GLYPH_INDEX (g) + 1;
1249 if (*left == left_idx && *right == right_idx)
1252 if (*left != left_idx)
1254 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1259 if (*right != right_idx)
1261 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1271 gstring_width (MGlyphString *gstring, int from, int to,
1272 int *lbearing, int *rbearing)
1277 if (from <= gstring->from && to >= gstring->to)
1280 *lbearing = gstring->lbearing;
1282 *rbearing = gstring->rbearing;
1283 return gstring->width;
1290 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1291 if (g->g.from >= from && g->g.from < to)
1293 if (lbearing && width + g->g.lbearing < *lbearing)
1294 *lbearing = width + g->g.lbearing;
1295 if (rbearing && width + g->g.rbearing > *rbearing)
1296 *rbearing = width + g->g.rbearing;
1304 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1305 MGlyphString *gstring, int from, int to)
1307 MDrawControl *control = &gstring->control;
1309 MDrawRegion clip_region, cursor_region;
1310 int from_idx, to_idx;
1315 if (control->orientation_reversed)
1316 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1318 x += gstring->indent;
1320 /* At first, draw all glyphs without cursor. */
1321 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1322 &from_idx, &to_idx, &to_x);
1324 if (control->partial_update)
1327 rect.width = to_x - x;
1328 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1330 rect.y = y - gstring->line_ascent;
1331 rect.height = gstring->height;
1332 clip_region = (*frame->driver->region_from_rect) (&rect);
1333 if (control->clip_region)
1334 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1337 clip_region = control->clip_region;
1340 clip_region = control->clip_region;
1342 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1347 (*frame->driver->intersect_region) (cursor_region, clip_region);
1348 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1351 if (clip_region != control->clip_region)
1352 (*frame->driver->free_region) (clip_region);
1354 (*frame->driver->free_region) (cursor_region);
1358 static int gstring_num;
1361 free_gstring (void *object)
1363 MGlyphString *gstring = (MGlyphString *) object;
1366 free_gstring (gstring->next);
1367 if (gstring->size > 0)
1368 free (gstring->glyphs);
1374 static MGlyphString scratch_gstring;
1376 static MGlyphString *
1377 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1380 MGlyphString *gstring;
1382 if (pos == mt->nchars)
1386 gstring = &scratch_gstring;
1387 if (gstring->size == 0)
1392 g_tmp.type = GLYPH_ANCHOR;
1393 APPEND_GLYPH (gstring, g_tmp);
1394 APPEND_GLYPH (gstring, g_tmp);
1395 APPEND_GLYPH (gstring, g_tmp);
1396 gstring->glyphs[1].type = GLYPH_SPACE;
1397 gstring->glyphs[1].g.c = '\n';
1398 gstring->glyphs[1].g.code = '\n';
1400 gstring->from = pos;
1402 g->rface = frame->rface;
1403 g->g.from = g->g.to = pos;
1405 g->rface = frame->rface;
1406 g->g.from = pos++, g->g.to = pos;
1408 g->rface = frame->rface;
1409 g->g.from = g->g.to = pos;
1414 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1415 MLIST_INIT1 (gstring, glyphs, 128);
1419 gstring->frame = frame;
1420 gstring->tick = frame->tick;
1421 gstring->top = gstring;
1422 gstring->control = *control;
1423 gstring->indent = gstring->width_limit = 0;
1424 if (control->format)
1425 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1427 gstring->width_limit = control->max_line_width;
1428 gstring->anti_alias = control->anti_alias;
1432 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1435 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1438 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1446 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1447 a width of glyphs for the character at I of MT. If I is not a
1448 beginning of a grapheme cluster, the corresponding element is
1450 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1451 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1452 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1453 pos_width[g->g.from - gstring->from] += g->g.xadv;
1454 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1456 if (pos_width[i] > 0)
1458 if (width + pos_width[i] > gstring->width_limit)
1461 width += pos_width[i];
1464 pos = gstring->from + i;
1465 if (gstring->control.line_break)
1467 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1468 gstring->from, gstring->from + i,
1470 if (pos <= gstring->from)
1472 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1475 else if (pos >= gstring->to)
1480 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1483 if (pos < gstring->to)
1485 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1486 layout_glyph_string (frame, gstring);
1491 /* Return a gstring that covers a character at POS. */
1493 static MGlyphString *
1494 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1496 MGlyphString *gstring = NULL;
1498 if (pos < mtext_nchars (mt))
1500 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1503 && ((prop->start != 0
1504 && mtext_ref_char (mt, prop->start - 1) != '\n')
1505 || (prop->end < mtext_nchars (mt)
1506 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1508 mtext_detach_property (prop);
1513 gstring = prop->val;
1514 if (gstring->frame != frame
1515 || gstring->tick != frame->tick
1516 || memcmp (control, &gstring->control,
1517 (char *) (&control->with_cursor)
1518 - (char *) (control))
1519 || control->cursor_pos != gstring->control.cursor_pos
1520 || control->cursor_width != gstring->control.cursor_width
1521 || control->cursor_bidi != gstring->control.cursor_bidi)
1523 mtext_detach_property (prop);
1528 else if (! control->cursor_width)
1536 offset = mtext_character (mt, pos, 0, '\n');
1541 offset -= gstring->from;
1543 for (gst = gstring; gst; gst = gst->next)
1547 gst->from += offset;
1549 for (i = 0; i < gst->used; i++)
1551 gst->glyphs[i].g.from += offset;
1552 gst->glyphs[i].g.to += offset;
1555 M17N_OBJECT_REF (gstring);
1560 int line = 0, y = 0;
1562 if (pos < mtext_nchars (mt))
1564 beg = mtext_character (mt, pos, 0, '\n');
1572 end = mtext_nchars (mt) + (control->cursor_width != 0);
1573 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1574 if (beg < mtext_nchars (mt))
1575 compose_glyph_string (frame, mt, beg, end, gstring);
1576 layout_glyph_string (frame, gstring);
1578 if (gstring->width_limit
1579 && gstring->width > gstring->width_limit)
1581 MGlyphString *gst = gstring;
1583 truncate_gstring (frame, mt, gst);
1584 while (gst->to < end)
1586 line++, y += gst->height;
1587 gst->next = alloc_gstring (frame, mt, gst->from, control,
1589 gst->next->top = gstring;
1590 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1592 layout_glyph_string (frame, gst);
1593 if (gst->width <= gst->width_limit)
1595 truncate_gstring (frame, mt, gst);
1599 if (! control->disable_caching && pos < mtext_nchars (mt))
1601 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1602 MTEXTPROP_VOLATILE_STRONG);
1604 if (end > mtext_nchars (mt))
1605 end = mtext_nchars (mt);
1606 mtext_attach_property (mt, beg, end, prop);
1607 M17N_OBJECT_UNREF (prop);
1611 while (gstring->to <= pos)
1613 if (! gstring->next)
1615 gstring = gstring->next;
1617 gstring->control = *control;
1623 static MDrawControl control_noop;
1625 #define ASSURE_CONTROL(control) \
1627 control = &control_noop; \
1632 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1633 MText *mt, int from, int to,
1634 MDrawControl *control)
1636 MGlyphString *gstring;
1638 M_CHECK_POS_X (mt, from, -1);
1639 ASSURE_CONTROL (control);
1640 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1641 to = mtext_nchars (mt) + (control->cursor_width != 0);
1645 gstring = get_gstring (frame, mt, from, to, control);
1647 MERROR (MERROR_DRAW, -1);
1648 render_glyph_string (frame, win, x, y, gstring, from, to);
1652 y += gstring->line_descent;
1653 M17N_OBJECT_UNREF (gstring->top);
1654 gstring = get_gstring (frame, mt, from, to, control);
1655 y += gstring->line_ascent;
1656 render_glyph_string (frame, win, x, y, gstring, from, to);
1659 M17N_OBJECT_UNREF (gstring->top);
1666 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1672 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1673 if (g->g.from <= pos && g->g.to > pos)
1678 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1679 if (g->g.from <= pos && g->g.to > pos)
1686 /* for debugging... */
1690 dump_gstring (MGlyphString *gstring, int indent, int type)
1692 char *prefix = (char *) alloca (indent + 1);
1693 MGlyph *g, *first_g, *last_g;
1695 memset (prefix, 32, indent);
1698 fprintf (stderr, "(glyph-string");
1702 first_g = MGLYPH (0);
1703 last_g = first_g + gstring->used;
1707 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1708 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1711 for (g = first_g; g < last_g; g++)
1714 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1717 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1718 : g->type == GLYPH_ANCHOR ? "ANC"
1719 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1720 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1721 g->g.xadv, g->bidi_level);
1722 if (g->g.xoff || g->g.yoff)
1723 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1724 fprintf (stderr, ")");
1726 fprintf (stderr, ")");
1730 /* m17n-X internal APIs */
1735 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1737 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1738 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1740 Mcommon = msymbol ("common");
1742 McatCc = msymbol ("Cc");
1743 McatCf = msymbol ("Cf");
1745 MbidiR = msymbol ("R");
1746 MbidiAL = msymbol ("AL");
1747 MbidiRLE = msymbol ("RLE");
1748 MbidiRLO = msymbol ("RLO");
1749 MbidiBN = msymbol ("BN");
1750 MbidiS = msymbol ("S");
1751 MbidiNSM = msymbol ("NSM");
1753 #if FRIBIDI_INTERFACE_VERSION < 3
1754 fribidi_set_mirroring (TRUE);
1756 fribidi_set_mirroring (1);
1760 M_break_at_space = msymbol ("bs");
1761 M_break_at_word = msymbol ("bw");
1762 M_break_at_any = msymbol ("ba");
1763 M_kinsoku_bol = msymbol ("kb");
1764 M_kinsoku_eol = msymbol ("ke");
1772 MLIST_FREE1 (&scratch_gstring, glyphs);
1773 M17N_OBJECT_UNREF (linebreak_table);
1774 linebreak_table = NULL;
1778 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1782 /*** @addtogroup m17nDraw */
1787 @brief Draw an M-text on a window.
1789 The mdraw_text () function draws the text between $FROM and $TO of
1790 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1792 The appearance of the text (size, style, color, etc) is specified
1793 by the value of the text property whose key is @c Mface. If the
1794 M-text or a part of the M-text does not have such a text property,
1795 the default face of $FRAME is used.
1797 The font used to draw a character in the M-text is selected from
1798 the value of the fontset property of a face by the following
1803 <li> Search the text properties given to the character for the one
1804 whose key is @c Mcharset; its value should be either a symbol
1805 specifying a charset or #Mnil. If the value is #Mnil,
1806 proceed to the next step.
1808 Otherwise, search the mapping table of the fontset for the
1809 charset. If no entry is found proceed to the next step.
1811 If an entry is found, use one of the fonts in the entry that
1812 has a glyph for the character and that matches best with the
1813 face properties. If no such font exists, proceed to the next
1816 <li> Get the character property "script" of the character. If it is
1817 inherited, get the script property from the previous
1818 characters. If there is no previous character, or none of
1819 them has the script property other than inherited, proceed to
1822 Search the text properties given to the character for the one
1823 whose key is @c Mlanguage; its value should be either a
1824 symbol specifying a language or @c Mnil.
1826 Search the mapping table of the fontset for the combination
1827 of the script and language. If no entry is found, proceed to
1830 If an entry is found, use one of the fonts in the entry that
1831 has a glyph for the character and that matches best with the
1832 face properties. If no such font exists, proceed to the next
1835 <li> Search the fall-back table of the fontset for a font that has
1836 a glyph of the character. If such a font is found, use that
1841 If no font is found by the algorithm above, this function draws an
1842 empty box for the character.
1844 This function draws only the glyph foreground. To specify the
1845 background color, use mdraw_image_text () or
1846 mdraw_text_with_control ().
1848 This function is the counterpart of <tt>XDrawString ()</tt>,
1849 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1850 in the X Window System.
1853 If the operation was successful, mdraw_text () returns 0. If an
1854 error is detected, it returns -1 and assigns an error code to the
1855 external variable #merror_code. */
1857 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1859 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1860 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1862 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1863 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1864 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1865 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1867 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1868 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1872 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1873 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1874 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1875 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1876 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1877 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1879 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1880 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1882 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1883 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1884 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1886 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1887 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1889 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1890 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1892 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1893 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1895 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1896 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1900 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1902 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1903 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1905 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1906 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1909 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1910 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1912 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1919 mdraw_image_text () */
1922 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1923 MText *mt, int from, int to)
1925 MDrawControl control;
1927 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1928 memset (&control, 0, sizeof control);
1929 control.as_image = 0;
1930 return draw_text (frame, win, x, y, mt, from, to, &control);
1937 @brief Draw an M-text on a window as an image.
1939 The mdraw_image_text () function draws the text between $FROM and
1940 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1941 coordinate ($X, $Y).
1943 The way to draw a text is the same as in mdraw_text () except that
1944 this function also draws the background with the color specified
1947 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1948 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1949 functions in the X Window System.
1952 If the operation was successful, mdraw_image_text () returns 0.
1953 If an error is detected, it returns -1 and assigns an error code
1954 to the external variable #merror_code. */
1957 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1959 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1960 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1961 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1963 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1964 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1966 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1967 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1971 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1972 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1974 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1984 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1985 MText *mt, int from, int to)
1987 MDrawControl control;
1989 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1990 memset (&control, 0, sizeof control);
1991 control.as_image = 1;
1992 return draw_text (frame, win, x, y, mt, from, to, &control);
1998 @brief Draw an M-text on a window with fine control.
2000 The mdraw_text_with_control () function draws the text between
2001 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2002 coordinate ($X, $Y).
2004 The way to draw a text is the same as in mdraw_text () except that
2005 this function also follows what specified in the drawing control
2008 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2009 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2010 breaks lines and the following characters are drawn in the next
2011 line. See the documentation of the structure @ MDrawControl for
2015 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2017 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2018 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2021 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2022 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2024 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2025 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2026 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2029 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2030 MText *mt, int from, int to, MDrawControl *control)
2032 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2033 return draw_text (frame, win, x, y, mt, from, to, control);
2039 @brief Compute text pixel width.
2041 The mdraw_text_extents () function computes the width of text
2042 between $FROM and $TO of M-text $MT when it is drawn on a window
2043 of frame $FRAME using the mdraw_text_with_control () function with
2044 the drawing control object $CONTROL.
2046 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2047 the bounding box of character ink of the M-text, and stores the
2048 results in the members of the structure pointed to by
2049 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2050 surrounding box, the box is included in the bounding box.
2052 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2053 computes the bounding box that provides minimum spacing to other
2054 graphical features (such as surrounding box) for the M-text, and
2055 stores the results in the members of the structure pointed to by
2056 $OVERALL_LOGICAL_RETURN.
2058 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2059 computes the bounding box that provides minimum spacing to the
2060 other M-text drawn, and stores the results in the members of the
2061 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2062 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2063 min_line_ascent, min_line_descent, max_line_ascent, and
2064 max_line_descent of $CONTROL are all zero.
2067 This function returns the width of the text to be drawn in the
2068 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2069 text is drawn in multiple physical lines, it returns the width of
2070 the widest line. If an error occurs, it returns -1 and assigns an
2071 error code to the external variable #merror_code. */
2075 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2077 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2078 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2079 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2081 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2082 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2083 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2084 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2086 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2087 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2088 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2089 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2091 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2092 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2093 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2094 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2095 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2096 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2099 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2100 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2101 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2103 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2110 mdraw_text_extents (MFrame *frame,
2111 MText *mt, int from, int to, MDrawControl *control,
2112 MDrawMetric *overall_ink_return,
2113 MDrawMetric *overall_logical_return,
2114 MDrawMetric *overall_line_return)
2116 MGlyphString *gstring;
2118 int width, lbearing, rbearing;
2120 ASSURE_CONTROL (control);
2121 M_CHECK_POS_X (mt, from, -1);
2122 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2123 to = mtext_nchars (mt) + (control->cursor_width != 0);
2127 gstring = get_gstring (frame, mt, from, to, control);
2129 MERROR (MERROR_DRAW, -1);
2130 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2131 if (overall_ink_return)
2132 overall_ink_return->y = - gstring->physical_ascent;
2133 if (overall_logical_return)
2134 overall_logical_return->y = - gstring->ascent;
2135 if (overall_line_return)
2136 overall_line_return->y = - gstring->line_ascent;
2138 for (from = gstring->to; from < to; from = gstring->to)
2140 int this_width, this_lbearing, this_rbearing;
2142 y += gstring->line_descent;
2143 M17N_OBJECT_UNREF (gstring->top);
2144 gstring = get_gstring (frame, mt, from, to, control);
2145 this_width = gstring_width (gstring, from, to,
2146 &this_lbearing, &this_rbearing);
2147 y += gstring->line_ascent;
2148 if (width < this_width)
2150 if (rbearing < this_rbearing)
2151 rbearing = this_rbearing;
2152 if (lbearing > this_lbearing)
2153 lbearing = this_lbearing;
2155 if (overall_ink_return)
2157 overall_ink_return->x = lbearing;
2158 overall_ink_return->width = rbearing - lbearing;
2159 overall_ink_return->height
2160 = y + gstring->physical_descent - overall_ink_return->y;
2162 if (overall_logical_return)
2164 overall_logical_return->x = 0;
2165 overall_logical_return->width = width;
2166 overall_logical_return->height
2167 = y + gstring->descent - overall_logical_return->y;
2169 if (overall_line_return)
2171 overall_line_return->x = lbearing;
2172 overall_line_return->width = MAX (width, rbearing - lbearing);
2173 overall_line_return->height
2174 = y + gstring->line_descent - overall_line_return->y;
2177 M17N_OBJECT_UNREF (gstring->top);
2184 @brief Compute the text dimensions of each character of M-text.
2186 The mdraw_text_per_char_extents () function computes the drawn
2187 metric of each character between $FROM and $TO of M-text $MT
2188 assuming that they are drawn on a window of frame $FRAME using the
2189 mdraw_text_with_control () function with the drawing control
2192 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2193 $LOGICAL_ARRAY_RETURN. Each successive element of
2194 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2195 ink and logical metrics of successive characters respectively,
2196 relative to the drawing origin of the M-text. The number of
2197 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2198 been set is returned to $NUM_CHARS_RETURN.
2200 If $ARRAY_SIZE is too small to return all metrics, the function
2201 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2202 Otherwise, it returns zero.
2204 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2205 @c NULL, this function also computes the metrics of the overall
2206 text and stores the results in the members of the structure
2207 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2209 If $CONTROL->two_dimensional is nonzero, this function computes
2210 only the metrics of characters in the first line. */
2212 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2214 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2215 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2216 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2218 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2219 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2220 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2221 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2222 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2224 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2225 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2228 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2229 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2230 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2232 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2235 mdraw_text_per_char_extents (MFrame *frame,
2236 MText *mt, int from, int to,
2237 MDrawControl *control,
2238 MDrawMetric *ink_array_return,
2239 MDrawMetric *logical_array_return,
2241 int *num_chars_return,
2242 MDrawMetric *overall_ink_return,
2243 MDrawMetric *overall_logical_return)
2245 MGlyphString *gstring;
2249 ASSURE_CONTROL (control);
2250 *num_chars_return = to - from;
2251 if (array_size < *num_chars_return)
2252 MERROR (MERROR_DRAW, -1);
2253 if (overall_logical_return)
2254 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2255 if (overall_ink_return)
2256 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2258 M_CHECK_RANGE (mt, from, to, -1, 0);
2259 gstring = get_gstring (frame, mt, from, to, control);
2262 *num_chars_return = 0;
2266 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2267 if (g->g.from >= from && g->g.from < to)
2269 int start = g->g.from;
2271 int width = g->g.xadv;
2272 int lbearing = g->g.lbearing;
2273 int rbearing = g->g.rbearing;
2274 int ascent = g->g.ascent;
2275 int descent = g->g.descent;
2277 int logical_descent;
2279 if (g->rface->rfont)
2281 logical_ascent = g->rface->rfont->ascent;
2282 logical_descent = g->rface->rfont->descent;
2286 logical_ascent = g->rface->ascent;
2287 logical_descent = g->rface->descent;
2289 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2291 if (lbearing < width + g->g.lbearing)
2292 lbearing = width + g->g.lbearing;
2293 if (rbearing < width + g->g.rbearing)
2294 rbearing = width + g->g.rbearing;
2296 if (ascent < g->g.ascent)
2297 ascent = g->g.ascent;
2298 if (descent < g->g.descent)
2299 descent = g->g.descent;
2306 if (ink_array_return)
2308 ink_array_return[start - from].x = x + lbearing;
2309 ink_array_return[start - from].y = - ascent;
2310 ink_array_return[start - from].width = rbearing - lbearing;
2311 ink_array_return[start - from].height = ascent + descent;
2313 if (logical_array_return)
2315 logical_array_return[start - from].x = x;
2316 logical_array_return[start - from].y = - logical_descent;
2317 logical_array_return[start - from].height
2318 = logical_ascent + logical_descent;
2319 logical_array_return[start - from].width = width;
2327 if (overall_ink_return)
2329 overall_ink_return->y = - gstring->line_ascent;
2330 overall_ink_return->x = gstring->lbearing;
2331 overall_ink_return->width = x - gstring->lbearing;
2332 overall_ink_return->height = gstring->height;
2334 if (overall_logical_return)
2336 overall_logical_return->y = - gstring->ascent;
2337 overall_logical_return->x = 0;
2338 overall_logical_return->width = x;
2339 overall_logical_return->height = gstring->ascent + gstring->descent;
2342 M17N_OBJECT_UNREF (gstring->top);
2349 @brief Return the character position nearest to the coordinates.
2351 The mdraw_coordinates_position () function checks which character
2352 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2353 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2354 mdraw_text_with_control () function with the drawing control
2355 object $CONTROL. Here, the character position means the number of
2356 characters that precede the character in question in $MT, that is,
2357 the character position of the first character is 0.
2359 $FRAME is used only to get the default face information.
2362 If the glyph image of a character covers coordinate ($X, $Y),
2363 mdraw_coordinates_position () returns the character position of
2365 If $Y is less than the minimum Y-coordinate of the drawn area, it
2367 If $Y is greater than the maximum Y-coordinate of the drawn area,
2369 If $Y fits in with the drawn area but $X is less than the minimum
2370 X-coordinate, it returns the character position of the first
2371 character drawn on the line $Y.\n\n
2372 If $Y fits in with the drawn area but $X is greater than the
2373 maximum X-coordinate, it returns the character position of the
2374 last character drawn on the line $Y. */
2377 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2379 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2380 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2381 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2382 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2383 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2384 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2386 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2389 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2390 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2392 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2393 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2394 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2395 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2396 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2399 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2400 int x_offset, int y_offset, MDrawControl *control)
2402 MGlyphString *gstring;
2407 M_CHECK_POS_X (mt, from, -1);
2408 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2409 to = mtext_nchars (mt) + (control->cursor_width != 0);
2415 ASSURE_CONTROL (control);
2416 gstring = get_gstring (frame, mt, from, to, control);
2417 while (y + gstring->line_descent <= y_offset
2418 && gstring->to < to)
2421 y += gstring->line_descent;
2422 M17N_OBJECT_UNREF (gstring->top);
2423 gstring = get_gstring (frame, mt, from, to, control);
2424 y += gstring->line_ascent;
2427 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2428 if (! control->orientation_reversed)
2430 width = gstring->indent;
2431 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2432 if (g->g.from >= from && g->g.from < to)
2435 if (width > x_offset)
2441 width = - gstring->indent;
2442 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2443 if (g->g.from >= from && g->g.from < to)
2446 if (width < x_offset)
2450 if (g->type == GLYPH_ANCHOR
2451 && control->two_dimensional
2452 && g[-1].g.c == '\n')
2455 M17N_OBJECT_UNREF (gstring->top);
2463 @brief Compute information about a glyph.
2465 The mdraw_glyph_info () function computes information about a
2466 glyph that covers a character at position $POS of the M-text $MT
2467 assuming that the text is drawn from the character at $FROM of $MT
2468 on a window of frame $FRAME using the mdraw_text_with_control ()
2469 function with the drawing control object $CONTROL.
2471 The information is stored in the members of $INFO. */
2473 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2475 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2476 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2477 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2478 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2480 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2488 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2489 MDrawControl *control, MDrawGlyphInfo *info)
2491 MGlyphString *gstring;
2495 M_CHECK_RANGE_X (mt, from, pos, -1);
2497 ASSURE_CONTROL (control);
2498 gstring = get_gstring (frame, mt, from, pos + 1, control);
2500 MERROR (MERROR_DRAW, -1);
2501 while (gstring->to <= pos)
2503 y += gstring->line_descent;
2504 M17N_OBJECT_UNREF (gstring->top);
2505 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2506 y += gstring->line_ascent;
2508 info->line_from = gstring->from;
2509 if (info->line_from < from)
2510 info->line_from = from;
2511 info->line_to = gstring->to;
2514 if (! control->orientation_reversed)
2516 info->x = gstring->indent;
2517 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2518 info->x += g->g.xadv;
2522 info->x = - gstring->indent;
2523 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2524 info->x -= g->g.xadv;
2525 while (g[-1].g.to == g->g.to)
2528 info->from = g->g.from;
2530 info->metrics.x = g->g.lbearing;
2531 info->metrics.y = - gstring->line_ascent;
2532 info->metrics.height = gstring->height;
2533 info->metrics.width = - g->g.lbearing + g->g.xadv;
2534 if (g->rface->rfont)
2535 info->font = (MFont *) g->rface->rfont;
2538 /* info->logical_width is calculated later. */
2540 if (info->from > info->line_from)
2542 /* The logically previous glyph is on this line. */
2543 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2545 info->prev_from = g_tmp->g.from;
2547 else if (info->line_from > 0
2548 && gstring->from > 0)
2550 /* The logically previous glyph is on the previous line. */
2551 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2552 gstring->from, control);
2553 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2555 info->prev_from = g_tmp->g.from;
2556 M17N_OBJECT_UNREF (gst->top);
2559 info->prev_from = -1;
2561 if (GLYPH_INDEX (g) > 1)
2562 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2563 else if (! control->orientation_reversed)
2565 if (info->line_from > 0)
2569 int p = gstring->from - 1;
2571 gst = get_gstring (frame, mt, p, gstring->from, control);
2572 g_tmp = gst->glyphs + (gst->used - 2);
2573 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2574 M17N_OBJECT_UNREF (gst->top);
2577 info->left_from = info->left_to = -1;
2581 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2585 int p = gstring->to;
2587 gst = get_gstring (frame, mt, p, p + 1, control);
2588 g_tmp = gst->glyphs + (gst->used - 2);
2589 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2590 M17N_OBJECT_UNREF (gst->top);
2593 info->left_from = info->left_to = -1;
2596 if (info->to < gstring->to)
2598 /* The logically next glyph is on this line. */
2599 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2601 info->next_to = g_tmp->g.to;
2603 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2605 /* The logically next glyph is on the next line. */
2607 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2608 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2610 info->next_to = g_tmp->g.to;
2611 M17N_OBJECT_UNREF (gst->top);
2616 for (info->logical_width = (g++)->g.xadv;
2617 g->g.from == pos && g->type != GLYPH_ANCHOR;
2618 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2619 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2621 if (g->type != GLYPH_ANCHOR)
2622 info->right_from = g->g.from, info->right_to = g->g.to;
2623 else if (! control->orientation_reversed)
2625 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2628 M17N_OBJECT_UNREF (gstring->top);
2629 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2631 info->right_from = g->g.from, info->right_to = g->g.to;
2634 info->right_from = info->right_to = -1;
2638 if (info->line_from > 0)
2640 pos = gstring->from - 1;
2641 M17N_OBJECT_UNREF (gstring->top);
2642 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2644 info->right_from = g->g.from, info->right_to = g->g.to;
2647 info->right_from = info->right_to = -1;
2650 M17N_OBJECT_UNREF (gstring->top);
2657 @brief Compute information about glyph sequence.
2659 The mdraw_glyph_list () function computes information about glyphs
2660 corresponding to the text between $FROM and $TO of M-text $MT when
2661 it is drawn on a window of frame $FRAME using the
2662 mdraw_text_with_control () function with the drawing control
2663 object $CONTROL. $GLYPHS is an array of objects to store the
2664 information, and $ARRAY_SIZE is the array size.
2666 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2667 number of actually filled elements in the place pointed by
2668 $NUM_GLYPHS_RETURN, and returns 0.
2670 Otherwise, it stores the required array size in the place pointed
2671 by $NUM_GLYPHS_RETURN, and returns -1. */
2674 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2676 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2677 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2678 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2679 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2681 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2682 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2685 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2695 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2696 MDrawControl *control, MDrawGlyph *glyphs,
2697 int array_size, int *num_glyphs_return)
2699 MGlyphString *gstring;
2704 ASSURE_CONTROL (control);
2705 *num_glyphs_return = 0;
2706 M_CHECK_RANGE (mt, from, to, -1, 0);
2707 gstring = get_gstring (frame, mt, from, to, control);
2710 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2712 if (g->type == GLYPH_BOX
2713 || g->g.from < from || g->g.from >= to)
2715 if (g->type == GLYPH_PAD)
2717 if (g->left_padding)
2718 pad_width = g->g.xadv;
2722 glyphs[-1].x_advance += g->g.xadv;
2728 glyphs->from = g->g.from;
2729 glyphs->to = g->g.to;
2730 glyphs->glyph_code = g->g.code;
2731 glyphs->x_off = g->g.xoff + pad_width;
2732 glyphs->y_off = g->g.yoff;
2733 glyphs->lbearing = g->g.lbearing;
2734 glyphs->rbearing = g->g.rbearing;
2735 glyphs->ascent = g->g.ascent;
2736 glyphs->descent = g->g.descent;
2737 glyphs->x_advance = g->g.xadv + pad_width;
2738 glyphs->y_advance = 0;
2739 if (g->rface->rfont)
2741 glyphs->font = (MFont *) g->rface->rfont;
2742 #ifdef HAVE_FREETYPE
2744 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2745 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2747 #else /* not HAVE_FREETYPE */
2748 glyphs->font_type = Mx;
2749 #endif /* not HAVE_FREETYPE */
2750 glyphs->fontp = g->rface->rfont->fontp;
2754 glyphs->font = NULL;
2755 glyphs->font_type = Mnil;
2756 glyphs->fontp = NULL;
2763 M17N_OBJECT_UNREF (gstring->top);
2765 *num_glyphs_return = n;
2766 return (n <= array_size ? 0 : -1);
2772 @brief Draw one or more textitems.
2774 The mdraw_text_items () function draws one or more M-texts on
2775 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2776 of the textitems to be drawn and $NITEMS is the number of
2777 textitems in the array. */
2780 @brief textitem ¤òɽ¼¨¤¹¤ë.
2782 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2783 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2784 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2786 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2790 MTextItem, mdraw_text (). */
2793 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2794 MDrawTextItem *items, int nitems)
2796 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2798 while (nitems-- > 0)
2801 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2803 mdraw_text_with_control (frame, win, x, y,
2804 items->mt, 0, mtext_nchars (items->mt),
2806 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2807 items->control, NULL, NULL, NULL);
2810 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2816 @brief Option of line breaking for drawing text.
2818 The variable #mdraw_line_break_option specifies line breaking
2819 options by logical-or of the members of #MTextLineBreakOption. It
2820 controls the line breaking algorithm of the function
2821 mdraw_default_line_break (). */
2823 int mdraw_line_break_option;
2827 @brief Calculate a line breaking position.
2829 The function mdraw_default_line_break () calculates a line
2830 breaking position based on the line number $LINE and the
2831 coordinate $Y, when a line is too long to fit within the width
2832 limit. $POS is the position of the character next to the last one
2833 that fits within the limit. $FROM is the position of the first
2834 character of the line, and $TO is the position of the last
2835 character displayed on the line if there were not width limit.
2836 $LINE and $Y are reset to 0 when a line is broken by a newline
2837 character, and incremented each time when a long line is broken
2838 because of the width limit.
2841 This function returns a character position to break the
2846 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2848 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2849 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2850 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2851 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2852 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2853 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2854 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2857 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2861 mdraw_default_line_break (MText *mt, int pos,
2862 int from, int to, int line, int y)
2866 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2877 @brief Obtain per character dimension information.
2879 The mdraw_per_char_extents () function computes the text dimension
2880 of each character in M-text $MT. The faces given as text
2881 properties in $MT and the default face of frame $FRAME determine
2882 the fonts to draw the text. Each successive element in
2883 $ARRAY_RETURN is set to the drawn metrics of successive
2884 characters, which is relative to the origin of the drawing, and a
2885 rectangle for each character in $MT. The number of elements of
2886 $ARRAY_RETURN must be equal to or greater than the number of
2889 If pointer $OVERALL_RETURN is not @c NULL, this function also
2890 computes the extents of the overall text and stores the results in
2891 the members of the structure pointed to by $OVERALL_RETURN. */
2894 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2896 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2897 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2898 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2899 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2900 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2901 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2902 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2904 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2905 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2906 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2908 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2911 mdraw_per_char_extents (MFrame *frame, MText *mt,
2912 MDrawMetric *array_return,
2913 MDrawMetric *overall_return)
2915 int n = mtext_nchars (mt);
2917 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2918 n, &n, overall_return, NULL);
2922 @brief clear cached information.
2924 The mdraw_clear_cache () function clear cached information
2925 on M-text $MT that was attached by any of the drawing functions.
2926 When the behavior of `format' or `line_break'
2927 member functions of MDrawControl is changed, the cache must be cleared.
2932 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2934 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2935 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2936 ¤¢¤ë¤¤¤Ï `line_break'
2937 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2943 mdraw_clear_cache (MText *mt)
2945 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);