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))
547 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_width != gstring->control.cursor_width
1519 || control->cursor_bidi != gstring->control.cursor_bidi)
1521 mtext_detach_property (prop);
1526 else if (! control->cursor_width)
1534 offset = mtext_character (mt, pos, 0, '\n');
1539 offset -= gstring->from;
1541 for (gst = gstring; gst; gst = gst->next)
1545 gst->from += offset;
1547 for (i = 0; i < gst->used; i++)
1549 gst->glyphs[i].g.from += offset;
1550 gst->glyphs[i].g.to += offset;
1553 M17N_OBJECT_REF (gstring);
1558 int line = 0, y = 0;
1560 if (pos < mtext_nchars (mt))
1562 beg = mtext_character (mt, pos, 0, '\n');
1570 end = mtext_nchars (mt) + (control->cursor_width != 0);
1571 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1572 if (beg < mtext_nchars (mt))
1573 compose_glyph_string (frame, mt, beg, end, gstring);
1574 layout_glyph_string (frame, gstring);
1576 if (gstring->width_limit
1577 && gstring->width > gstring->width_limit)
1579 MGlyphString *gst = gstring;
1581 truncate_gstring (frame, mt, gst);
1582 while (gst->to < end)
1584 line++, y += gst->height;
1585 gst->next = alloc_gstring (frame, mt, gst->from, control,
1587 gst->next->top = gstring;
1588 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1590 layout_glyph_string (frame, gst);
1591 if (gst->width <= gst->width_limit)
1593 truncate_gstring (frame, mt, gst);
1597 if (! control->disable_caching && pos < mtext_nchars (mt))
1599 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1600 MTEXTPROP_VOLATILE_STRONG);
1602 if (end > mtext_nchars (mt))
1603 end = mtext_nchars (mt);
1604 mtext_attach_property (mt, beg, end, prop);
1605 M17N_OBJECT_UNREF (prop);
1609 while (gstring->to <= pos)
1611 if (! gstring->next)
1613 gstring = gstring->next;
1615 gstring->control = *control;
1621 static MDrawControl control_noop;
1623 #define ASSURE_CONTROL(control) \
1625 control = &control_noop; \
1630 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1631 MText *mt, int from, int to,
1632 MDrawControl *control)
1634 MGlyphString *gstring;
1636 M_CHECK_POS_X (mt, from, -1);
1637 ASSURE_CONTROL (control);
1638 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1639 to = mtext_nchars (mt) + (control->cursor_width != 0);
1643 gstring = get_gstring (frame, mt, from, to, control);
1645 MERROR (MERROR_DRAW, -1);
1646 render_glyph_string (frame, win, x, y, gstring, from, to);
1650 y += gstring->line_descent;
1651 M17N_OBJECT_UNREF (gstring->top);
1652 gstring = get_gstring (frame, mt, from, to, control);
1653 y += gstring->line_ascent;
1654 render_glyph_string (frame, win, x, y, gstring, from, to);
1657 M17N_OBJECT_UNREF (gstring->top);
1664 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1670 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1671 if (g->g.from <= pos && g->g.to > pos)
1676 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1677 if (g->g.from <= pos && g->g.to > pos)
1684 /* for debugging... */
1688 dump_gstring (MGlyphString *gstring, int indent, int type)
1690 char *prefix = (char *) alloca (indent + 1);
1691 MGlyph *g, *first_g, *last_g;
1693 memset (prefix, 32, indent);
1696 fprintf (stderr, "(glyph-string");
1700 first_g = MGLYPH (0);
1701 last_g = first_g + gstring->used;
1705 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1706 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1709 for (g = first_g; g < last_g; g++)
1712 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1715 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1716 : g->type == GLYPH_ANCHOR ? "ANC"
1717 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1718 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1719 g->g.xadv, g->bidi_level);
1720 if (g->g.xoff || g->g.yoff)
1721 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1722 fprintf (stderr, ")");
1724 fprintf (stderr, ")");
1728 /* m17n-X internal APIs */
1733 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1735 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1736 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1738 Mcommon = msymbol ("common");
1740 McatCc = msymbol ("Cc");
1741 McatCf = msymbol ("Cf");
1743 MbidiR = msymbol ("R");
1744 MbidiAL = msymbol ("AL");
1745 MbidiRLE = msymbol ("RLE");
1746 MbidiRLO = msymbol ("RLO");
1747 MbidiBN = msymbol ("BN");
1748 MbidiS = msymbol ("S");
1749 MbidiNSM = msymbol ("NSM");
1751 fribidi_set_mirroring (TRUE);
1754 M_break_at_space = msymbol ("bs");
1755 M_break_at_word = msymbol ("bw");
1756 M_break_at_any = msymbol ("ba");
1757 M_kinsoku_bol = msymbol ("kb");
1758 M_kinsoku_eol = msymbol ("ke");
1766 MLIST_FREE1 (&scratch_gstring, glyphs);
1767 M17N_OBJECT_UNREF (linebreak_table);
1768 linebreak_table = NULL;
1772 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1776 /*** @addtogroup m17nDraw */
1781 @brief Draw an M-text on a window.
1783 The mdraw_text () function draws the text between $FROM and $TO of
1784 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1786 The appearance of the text (size, style, color, etc) is specified
1787 by the value of the text property whose key is @c Mface. If the
1788 M-text or a part of the M-text does not have such a text property,
1789 the default face of $FRAME is used.
1791 The font used to draw a character in the M-text is selected from
1792 the value of the fontset property of a face by the following
1797 <li> Search the text properties given to the character for the one
1798 whose key is @c Mcharset; its value should be either a symbol
1799 specifying a charset or #Mnil. If the value is #Mnil,
1800 proceed to the next step.
1802 Otherwise, search the mapping table of the fontset for the
1803 charset. If no entry is found proceed to the next step.
1805 If an entry is found, use one of the fonts in the entry that
1806 has a glyph for the character and that matches best with the
1807 face properties. If no such font exists, proceed to the next
1810 <li> Get the character property "script" of the character. If it is
1811 inherited, get the script property from the previous
1812 characters. If there is no previous character, or none of
1813 them has the script property other than inherited, proceed to
1816 Search the text properties given to the character for the one
1817 whose key is @c Mlanguage; its value should be either a
1818 symbol specifying a language or @c Mnil.
1820 Search the mapping table of the fontset for the combination
1821 of the script and language. If no entry is found, proceed to
1824 If an entry is found, use one of the fonts in the entry that
1825 has a glyph for the character and that matches best with the
1826 face properties. If no such font exists, proceed to the next
1829 <li> Search the fall-back table of the fontset for a font that has
1830 a glyph of the character. If such a font is found, use that
1835 If no font is found by the algorithm above, this function draws an
1836 empty box for the character.
1838 This function draws only the glyph foreground. To specify the
1839 background color, use mdraw_image_text () or
1840 mdraw_text_with_control ().
1842 This function is the counterpart of <tt>XDrawString ()</tt>,
1843 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1844 in the X Window System.
1847 If the operation was successful, mdraw_text () returns 0. If an
1848 error is detected, it returns -1 and assigns an error code to the
1849 external variable #merror_code. */
1851 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1853 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1854 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1856 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1857 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1858 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1859 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1861 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1862 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1866 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1867 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1868 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1869 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1870 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1871 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1873 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1874 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1876 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1877 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1878 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1880 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1881 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1883 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1884 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1886 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1887 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1889 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1890 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1894 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1896 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1897 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1899 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1900 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1903 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1904 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1906 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1913 mdraw_image_text () */
1916 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1917 MText *mt, int from, int to)
1919 MDrawControl control;
1921 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1922 memset (&control, 0, sizeof control);
1923 control.as_image = 0;
1924 return draw_text (frame, win, x, y, mt, from, to, &control);
1931 @brief Draw an M-text on a window as an image.
1933 The mdraw_image_text () function draws the text between $FROM and
1934 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1935 coordinate ($X, $Y).
1937 The way to draw a text is the same as in mdraw_text () except that
1938 this function also draws the background with the color specified
1941 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1942 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1943 functions in the X Window System.
1946 If the operation was successful, mdraw_image_text () returns 0.
1947 If an error is detected, it returns -1 and assigns an error code
1948 to the external variable #merror_code. */
1951 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1953 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1954 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1955 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1957 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1958 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1960 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1961 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1965 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1966 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1968 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1978 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1979 MText *mt, int from, int to)
1981 MDrawControl control;
1983 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1984 memset (&control, 0, sizeof control);
1985 control.as_image = 1;
1986 return draw_text (frame, win, x, y, mt, from, to, &control);
1992 @brief Draw an M-text on a window with fine control.
1994 The mdraw_text_with_control () function draws the text between
1995 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1996 coordinate ($X, $Y).
1998 The way to draw a text is the same as in mdraw_text () except that
1999 this function also follows what specified in the drawing control
2002 For instance, if <two_dimensional> of $CONTROL is nonzero, this
2003 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2004 breaks lines and the following characters are drawn in the next
2005 line. See the documentation of the structure @ MDrawControl for
2009 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2011 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2012 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2015 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2016 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2018 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2019 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2020 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2023 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2024 MText *mt, int from, int to, MDrawControl *control)
2026 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2027 return draw_text (frame, win, x, y, mt, from, to, control);
2033 @brief Compute text pixel width.
2035 The mdraw_text_extents () function computes the width of text
2036 between $FROM and $TO of M-text $MT when it is drawn on a window
2037 of frame $FRAME using the mdraw_text_with_control () function with
2038 the drawing control object $CONTROL.
2040 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2041 the bounding box of character ink of the M-text, and stores the
2042 results in the members of the structure pointed to by
2043 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2044 surrounding box, the box is included in the bounding box.
2046 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2047 computes the bounding box that provides minimum spacing to other
2048 graphical features (such as surrounding box) for the M-text, and
2049 stores the results in the members of the structure pointed to by
2050 $OVERALL_LOGICAL_RETURN.
2052 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2053 computes the bounding box that provides minimum spacing to the
2054 other M-text drawn, and stores the results in the members of the
2055 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2056 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2057 min_line_ascent, min_line_descent, max_line_ascent, and
2058 max_line_descent of $CONTROL are all zero.
2061 This function returns the width of the text to be drawn in the
2062 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2063 text is drawn in multiple physical lines, it returns the width of
2064 the widest line. If an error occurs, it returns -1 and assigns an
2065 error code to the external variable #merror_code. */
2069 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2071 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2072 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2073 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2075 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2076 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2077 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2078 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2080 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2081 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2082 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2083 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2085 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2086 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2087 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2088 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2089 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2090 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2093 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2094 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2095 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2097 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2104 mdraw_text_extents (MFrame *frame,
2105 MText *mt, int from, int to, MDrawControl *control,
2106 MDrawMetric *overall_ink_return,
2107 MDrawMetric *overall_logical_return,
2108 MDrawMetric *overall_line_return)
2110 MGlyphString *gstring;
2112 int width, lbearing, rbearing;
2114 ASSURE_CONTROL (control);
2115 M_CHECK_POS_X (mt, from, -1);
2116 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2117 to = mtext_nchars (mt) + (control->cursor_width != 0);
2121 gstring = get_gstring (frame, mt, from, to, control);
2123 MERROR (MERROR_DRAW, -1);
2124 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2125 if (overall_ink_return)
2126 overall_ink_return->y = - gstring->physical_ascent;
2127 if (overall_logical_return)
2128 overall_logical_return->y = - gstring->ascent;
2129 if (overall_line_return)
2130 overall_line_return->y = - gstring->line_ascent;
2132 for (from = gstring->to; from < to; from = gstring->to)
2134 int this_width, this_lbearing, this_rbearing;
2136 y += gstring->line_descent;
2137 M17N_OBJECT_UNREF (gstring->top);
2138 gstring = get_gstring (frame, mt, from, to, control);
2139 this_width = gstring_width (gstring, from, to,
2140 &this_lbearing, &this_rbearing);
2141 y += gstring->line_ascent;
2142 if (width < this_width)
2144 if (rbearing < this_rbearing)
2145 rbearing = this_rbearing;
2146 if (lbearing > this_lbearing)
2147 lbearing = this_lbearing;
2149 if (overall_ink_return)
2151 overall_ink_return->x = lbearing;
2152 overall_ink_return->width = rbearing - lbearing;
2153 overall_ink_return->height
2154 = y + gstring->physical_descent - overall_ink_return->y;
2156 if (overall_logical_return)
2158 overall_logical_return->x = 0;
2159 overall_logical_return->width = width;
2160 overall_logical_return->height
2161 = y + gstring->descent - overall_logical_return->y;
2163 if (overall_line_return)
2165 overall_line_return->x = lbearing;
2166 overall_line_return->width = MAX (width, rbearing - lbearing);
2167 overall_line_return->height
2168 = y + gstring->line_descent - overall_line_return->y;
2171 M17N_OBJECT_UNREF (gstring->top);
2178 @brief Compute the text dimensions of each character of M-text.
2180 The mdraw_text_per_char_extents () function computes the drawn
2181 metric of each character between $FROM and $TO of M-text $MT
2182 assuming that they are drawn on a window of frame $FRAME using the
2183 mdraw_text_with_control () function with the drawing control
2186 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2187 $LOGICAL_ARRAY_RETURN. Each successive element of
2188 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2189 ink and logical metrics of successive characters respectively,
2190 relative to the drawing origin of the M-text. The number of
2191 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2192 been set is returned to $NUM_CHARS_RETURN.
2194 If $ARRAY_SIZE is too small to return all metrics, the function
2195 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2196 Otherwise, it returns zero.
2198 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2199 @c NULL, this function also computes the metrics of the overall
2200 text and stores the results in the members of the structure
2201 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2203 If $CONTROL->two_dimensional is nonzero, this function computes
2204 only the metrics of characters in the first line. */
2206 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2208 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2209 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2210 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2212 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2213 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2214 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2215 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2216 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2218 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2219 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2222 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2223 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2224 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2226 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2229 mdraw_text_per_char_extents (MFrame *frame,
2230 MText *mt, int from, int to,
2231 MDrawControl *control,
2232 MDrawMetric *ink_array_return,
2233 MDrawMetric *logical_array_return,
2235 int *num_chars_return,
2236 MDrawMetric *overall_ink_return,
2237 MDrawMetric *overall_logical_return)
2239 MGlyphString *gstring;
2243 ASSURE_CONTROL (control);
2244 *num_chars_return = to - from;
2245 if (array_size < *num_chars_return)
2246 MERROR (MERROR_DRAW, -1);
2247 if (overall_logical_return)
2248 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2249 if (overall_ink_return)
2250 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2252 M_CHECK_RANGE (mt, from, to, -1, 0);
2253 gstring = get_gstring (frame, mt, from, to, control);
2256 *num_chars_return = 0;
2260 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2261 if (g->g.from >= from && g->g.from < to)
2263 int start = g->g.from;
2265 int width = g->g.xadv;
2266 int lbearing = g->g.lbearing;
2267 int rbearing = g->g.rbearing;
2268 int ascent = g->g.ascent;
2269 int descent = g->g.descent;
2271 int logical_descent;
2273 if (g->rface->rfont)
2275 logical_ascent = g->rface->rfont->ascent;
2276 logical_descent = g->rface->rfont->descent;
2280 logical_ascent = g->rface->ascent;
2281 logical_descent = g->rface->descent;
2283 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2285 if (lbearing < width + g->g.lbearing)
2286 lbearing = width + g->g.lbearing;
2287 if (rbearing < width + g->g.rbearing)
2288 rbearing = width + g->g.rbearing;
2290 if (ascent < g->g.ascent)
2291 ascent = g->g.ascent;
2292 if (descent < g->g.descent)
2293 descent = g->g.descent;
2300 if (ink_array_return)
2302 ink_array_return[start - from].x = x + lbearing;
2303 ink_array_return[start - from].y = - ascent;
2304 ink_array_return[start - from].width = rbearing - lbearing;
2305 ink_array_return[start - from].height = ascent + descent;
2307 if (logical_array_return)
2309 logical_array_return[start - from].x = x;
2310 logical_array_return[start - from].y = - logical_descent;
2311 logical_array_return[start - from].height
2312 = logical_ascent + logical_descent;
2313 logical_array_return[start - from].width = width;
2321 if (overall_ink_return)
2323 overall_ink_return->y = - gstring->line_ascent;
2324 overall_ink_return->x = gstring->lbearing;
2325 overall_ink_return->width = x - gstring->lbearing;
2326 overall_ink_return->height = gstring->height;
2328 if (overall_logical_return)
2330 overall_logical_return->y = - gstring->ascent;
2331 overall_logical_return->x = 0;
2332 overall_logical_return->width = x;
2333 overall_logical_return->height = gstring->ascent + gstring->descent;
2336 M17N_OBJECT_UNREF (gstring->top);
2343 @brief Return the character position nearest to the coordinates.
2345 The mdraw_coordinates_position () function checks which character
2346 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2347 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2348 mdraw_text_with_control () function with the drawing control
2349 object $CONTROL. Here, the character position means the number of
2350 characters that precede the character in question in $MT, that is,
2351 the character position of the first character is 0.
2353 $FRAME is used only to get the default face information.
2356 If the glyph image of a character covers coordinate ($X, $Y),
2357 mdraw_coordinates_position () returns the character position of
2359 If $Y is less than the minimum Y-coordinate of the drawn area, it
2361 If $Y is greater than the maximum Y-coordinate of the drawn area,
2363 If $Y fits in with the drawn area but $X is less than the minimum
2364 X-coordinate, it returns the character position of the first
2365 character drawn on the line $Y.\n\n
2366 If $Y fits in with the drawn area but $X is greater than the
2367 maximum X-coordinate, it returns the character position of the
2368 last character drawn on the line $Y. */
2371 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2373 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2374 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2375 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2376 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2377 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2378 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2380 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2383 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2384 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2385 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2386 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2387 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2388 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2389 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2390 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2393 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2394 int x_offset, int y_offset, MDrawControl *control)
2396 MGlyphString *gstring;
2401 M_CHECK_POS_X (mt, from, -1);
2402 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2403 to = mtext_nchars (mt) + (control->cursor_width != 0);
2409 ASSURE_CONTROL (control);
2410 gstring = get_gstring (frame, mt, from, to, control);
2411 while (y + gstring->line_descent <= y_offset
2412 && gstring->to < to)
2415 y += gstring->line_descent;
2416 M17N_OBJECT_UNREF (gstring->top);
2417 gstring = get_gstring (frame, mt, from, to, control);
2418 y += gstring->line_ascent;
2421 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2422 if (! control->orientation_reversed)
2424 width = gstring->indent;
2425 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2426 if (g->g.from >= from && g->g.from < to)
2429 if (width > x_offset)
2435 width = - gstring->indent;
2436 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2437 if (g->g.from >= from && g->g.from < to)
2440 if (width < x_offset)
2444 if (g->type == GLYPH_ANCHOR
2445 && control->two_dimensional
2446 && g[-1].g.c == '\n')
2449 M17N_OBJECT_UNREF (gstring->top);
2457 @brief Compute information about a glyph.
2459 The mdraw_glyph_info () function computes information about a
2460 glyph that covers a character at position $POS of the M-text $MT
2461 assuming that the text is drawn from the character at $FROM of $MT
2462 on a window of frame $FRAME using the mdraw_text_with_control ()
2463 function with the drawing control object $CONTROL.
2465 The information is stored in the members of $INFO. */
2467 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2469 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2470 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2471 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2472 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2474 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2482 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2483 MDrawControl *control, MDrawGlyphInfo *info)
2485 MGlyphString *gstring;
2489 M_CHECK_RANGE_X (mt, from, pos, -1);
2491 ASSURE_CONTROL (control);
2492 gstring = get_gstring (frame, mt, from, pos + 1, control);
2494 MERROR (MERROR_DRAW, -1);
2495 while (gstring->to <= pos)
2497 y += gstring->line_descent;
2498 M17N_OBJECT_UNREF (gstring->top);
2499 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2500 y += gstring->line_ascent;
2502 info->line_from = gstring->from;
2503 if (info->line_from < from)
2504 info->line_from = from;
2505 info->line_to = gstring->to;
2508 if (! control->orientation_reversed)
2510 info->x = gstring->indent;
2511 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2512 info->x += g->g.xadv;
2516 info->x = - gstring->indent;
2517 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2518 info->x -= g->g.xadv;
2519 while (g[-1].g.to == g->g.to)
2522 info->from = g->g.from;
2524 info->metrics.x = g->g.lbearing;
2525 info->metrics.y = - gstring->line_ascent;
2526 info->metrics.height = gstring->height;
2527 info->metrics.width = - g->g.lbearing + g->g.xadv;
2528 if (g->rface->rfont)
2529 info->font = (MFont *) g->rface->rfont;
2532 /* info->logical_width is calculated later. */
2534 if (info->from > info->line_from)
2536 /* The logically previous glyph is on this line. */
2537 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2539 info->prev_from = g_tmp->g.from;
2541 else if (info->line_from > 0
2542 && gstring->from > 0)
2544 /* The logically previous glyph is on the previous line. */
2545 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2546 gstring->from, control);
2547 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2549 info->prev_from = g_tmp->g.from;
2550 M17N_OBJECT_UNREF (gst->top);
2553 info->prev_from = -1;
2555 if (GLYPH_INDEX (g) > 1)
2556 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2557 else if (! control->orientation_reversed)
2559 if (info->line_from > 0)
2563 int p = gstring->from - 1;
2565 gst = get_gstring (frame, mt, p, gstring->from, control);
2566 g_tmp = gst->glyphs + (gst->used - 2);
2567 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2568 M17N_OBJECT_UNREF (gst->top);
2571 info->left_from = info->left_to = -1;
2575 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2579 int p = gstring->to;
2581 gst = get_gstring (frame, mt, p, p + 1, control);
2582 g_tmp = gst->glyphs + (gst->used - 2);
2583 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2584 M17N_OBJECT_UNREF (gst->top);
2587 info->left_from = info->left_to = -1;
2590 if (info->to < gstring->to)
2592 /* The logically next glyph is on this line. */
2593 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2595 info->next_to = g_tmp->g.to;
2597 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2599 /* The logically next glyph is on the next line. */
2601 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2602 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2604 info->next_to = g_tmp->g.to;
2605 M17N_OBJECT_UNREF (gst->top);
2610 for (info->logical_width = (g++)->g.xadv;
2611 g->g.from == pos && g->type != GLYPH_ANCHOR;
2612 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2613 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2615 if (g->type != GLYPH_ANCHOR)
2616 info->right_from = g->g.from, info->right_to = g->g.to;
2617 else if (! control->orientation_reversed)
2619 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2622 M17N_OBJECT_UNREF (gstring->top);
2623 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2625 info->right_from = g->g.from, info->right_to = g->g.to;
2628 info->right_from = info->right_to = -1;
2632 if (info->line_from > 0)
2634 pos = gstring->from - 1;
2635 M17N_OBJECT_UNREF (gstring->top);
2636 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2638 info->right_from = g->g.from, info->right_to = g->g.to;
2641 info->right_from = info->right_to = -1;
2644 M17N_OBJECT_UNREF (gstring->top);
2651 @brief Compute information about glyph sequence.
2653 The mdraw_glyph_list () function computes information about glyphs
2654 corresponding to the text between $FROM and $TO of M-text $MT when
2655 it is drawn on a window of frame $FRAME using the
2656 mdraw_text_with_control () function with the drawing control
2657 object $CONTROL. $GLYPHS is an array of objects to store the
2658 information, and $ARRAY_SIZE is the array size.
2660 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2661 number of actually filled elements in the place pointed by
2662 $NUM_GLYPHS_RETURN, and returns 0.
2664 Otherwise, it stores the required array size in the place pointed
2665 by $NUM_GLYPHS_RETURN, and returns -1. */
2668 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2670 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2671 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2672 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2673 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2675 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2676 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2679 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2689 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2690 MDrawControl *control, MDrawGlyph *glyphs,
2691 int array_size, int *num_glyphs_return)
2693 MGlyphString *gstring;
2698 ASSURE_CONTROL (control);
2699 *num_glyphs_return = 0;
2700 M_CHECK_RANGE (mt, from, to, -1, 0);
2701 gstring = get_gstring (frame, mt, from, to, control);
2704 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2706 if (g->type == GLYPH_BOX
2707 || g->g.from < from || g->g.from >= to)
2709 if (g->type == GLYPH_PAD)
2711 if (g->left_padding)
2712 pad_width = g->g.xadv;
2716 glyphs[-1].x_advance += g->g.xadv;
2722 glyphs->from = g->g.from;
2723 glyphs->to = g->g.to;
2724 glyphs->glyph_code = g->g.code;
2725 glyphs->x_off = g->g.xoff + pad_width;
2726 glyphs->y_off = g->g.yoff;
2727 glyphs->lbearing = g->g.lbearing;
2728 glyphs->rbearing = g->g.rbearing;
2729 glyphs->ascent = g->g.ascent;
2730 glyphs->descent = g->g.descent;
2731 glyphs->x_advance = g->g.xadv + pad_width;
2732 glyphs->y_advance = 0;
2733 if (g->rface->rfont)
2735 glyphs->font = (MFont *) g->rface->rfont;
2737 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2738 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2740 glyphs->fontp = g->rface->rfont->fontp;
2744 glyphs->font = NULL;
2745 glyphs->font_type = Mnil;
2746 glyphs->fontp = NULL;
2753 M17N_OBJECT_UNREF (gstring->top);
2755 *num_glyphs_return = n;
2756 return (n <= array_size ? 0 : -1);
2762 @brief Draw one or more textitems.
2764 The mdraw_text_items () function draws one or more M-texts on
2765 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2766 of the textitems to be drawn and $NITEMS is the number of
2767 textitems in the array. */
2770 @brief textitem ¤òɽ¼¨¤¹¤ë.
2772 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2773 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2774 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2776 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2780 MTextItem, mdraw_text (). */
2783 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2784 MDrawTextItem *items, int nitems)
2786 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2788 while (nitems-- > 0)
2791 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2793 mdraw_text_with_control (frame, win, x, y,
2794 items->mt, 0, mtext_nchars (items->mt),
2796 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2797 items->control, NULL, NULL, NULL);
2800 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2806 @brief Option of line breaking for drawing text.
2808 The variable #mdraw_line_break_option specifies line breaking
2809 options by logical-or of the members of #MTextLineBreakOption. It
2810 controls the line breaking algorithm of the function
2811 mdraw_default_line_break (). */
2813 int mdraw_line_break_option;
2817 @brief Calculate a line breaking position.
2819 The function mdraw_default_line_break () calculates a line
2820 breaking position based on the line number $LINE and the
2821 coordinate $Y, when a line is too long to fit within the width
2822 limit. $POS is the position of the character next to the last one
2823 that fits within the limit. $FROM is the position of the first
2824 character of the line, and $TO is the position of the last
2825 character displayed on the line if there were not width limit.
2826 $LINE and $Y are reset to 0 when a line is broken by a newline
2827 character, and incremented each time when a long line is broken
2828 because of the width limit.
2830 @return This function returns a character position to break the
2835 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2837 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2838 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2839 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2840 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2841 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2842 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2843 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2846 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2850 mdraw_default_line_break (MText *mt, int pos,
2851 int from, int to, int line, int y)
2855 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2866 @brief Obtain per character dimension information.
2868 The mdraw_per_char_extents () function computes the text dimension
2869 of each character in M-text $MT. The faces given as text
2870 properties in $MT and the default face of frame $FRAME determine
2871 the fonts to draw the text. Each successive element in
2872 $ARRAY_RETURN is set to the drawn metrics of successive
2873 characters, which is relative to the origin of the drawing, and a
2874 rectangle for each character in $MT. The number of elements of
2875 $ARRAY_RETURN must be equal to or greater than the number of
2878 If pointer $OVERALL_RETURN is not @c NULL, this function also
2879 computes the extents of the overall text and stores the results in
2880 the members of the structure pointed to by $OVERALL_RETURN. */
2883 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2885 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2886 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2887 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2888 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2889 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2890 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2891 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2893 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2894 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2895 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2897 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2900 mdraw_per_char_extents (MFrame *frame, MText *mt,
2901 MDrawMetric *array_return,
2902 MDrawMetric *overall_return)
2904 int n = mtext_nchars (mt);
2906 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2907 n, &n, overall_return, NULL);
2911 @brief clear cached information.
2913 The mdraw_clear_cache () function clear cached information
2914 on M-text $MT that was attached by any of the drawing functions.
2915 When the behavior of `format' or `line_break'
2916 member functions of MDrawControl is changed, the cache must be cleared.
2921 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2923 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2924 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2925 ¤¢¤ë¤¤¤Ï `line_break'
2926 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2932 mdraw_clear_cache (MText *mt)
2934 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);