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];
242 font_id (MFLTFont *font)
244 return ((MFLTFontForRealized *) font)->rfont->id;
248 run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
250 MRealizedFont *rfont = rface->rfont;
251 MSymbol layouter = rface->layouter;
252 MFLTGlyphString flt_gstr;
253 MFLTFontForRealized font;
255 int from_pos = MGLYPH (from)->g.from;
260 flt = mflt_get (layouter);
261 flt_gstr.glyph_size = sizeof (MGlyph);
262 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
263 flt_gstr.used = gstring->used;
264 flt_gstr.allocated = gstring->size;
266 font.font.family = mfont_get_prop (rfont->font, Mfamily);
267 font.font.x_ppem = rfont->x_ppem;
268 font.font.y_ppem = rfont->y_ppem;
269 font.font.get_glyph_id = mfont__get_glyph_id;
270 font.font.get_metrics = mfont__get_metrics;
271 font.font.check_otf = rfont->driver->check_otf;
272 font.font.drive_otf = rfont->driver->drive_otf;
273 font.font.internal = NULL;
275 mflt_font_id = font_id;
276 mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature;
277 for (i = 0; i < 3; i++)
279 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
282 APPEND_GLYPH (gstring, *MGLYPH (0));
283 APPEND_GLYPH (gstring, *MGLYPH (0));
286 if (from + len != to)
287 gstring->used += to - (from + len);
288 for (i = from, catcode = -1; i < to; i++)
290 MGlyph *g = MGLYPH (i);
292 g->g.from += from_pos - from;
293 g->g.to += from_pos - from + 1;
303 if (catcode < 0 || g->g.from != g[-1].g.from)
305 MSymbol category = mchar_get_prop (g->g.c, Mcategory);
307 catcode = (category == McatCf
308 ? GLYPH_CATEGORY_FORMATTER
309 : category != Mnil && MSYMBOL_NAME (category)[0] == 'M'
310 ? GLYPH_CATEGORY_MODIFIER
311 : GLYPH_CATEGORY_NORMAL);
313 g->category = catcode;
318 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
319 displaying them on FRAME.
321 This function fills these members:
322 pos, to, c, code, rface, bidi_level, categories, type, combining_code
323 The other members are filled by layout_glyph_string. */
326 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
327 MGlyphString *gstring)
329 MRealizedFace *default_rface = frame->rface;
330 int stop, face_change, language_change, charset_change, font_change;
331 MGlyph g_tmp, *g, *last_g;
333 MSymbol language = Mnil, script = Mnil, charset = Mnil;
334 MSymbol non_latin_script = Mnil;
335 MRealizedFace *rface = default_rface;
336 MRealizedFont *rfont;
337 int size = gstring->control.fixed_width;
338 int max_bidi_level = 0;
341 MLIST_RESET (gstring);
342 gstring->from = from;
344 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
345 <category> and <rface> members.*/
348 /** Put anchor glyphs at the head and tail. */
349 g_tmp.type = GLYPH_ANCHOR;
350 g_tmp.g.from = g_tmp.g.to = from;
351 APPEND_GLYPH (gstring, g_tmp);
352 stop = face_change = font_change = pos = from;
362 if (pos < mtext_nchars (mt))
364 MFont *font = rface->font;
368 if (pos == font_change)
370 font = mtext_get_prop (mt, pos, Mfont);
371 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
372 if (font_change == mtext_nchars (mt))
375 if (pos == face_change)
377 num = mtext_get_prop_values (mt, pos, Mface,
378 (void **) faces, 64);
379 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
380 if (face_change == mtext_nchars (mt))
385 faces[0] = &rface->face;
388 rface = mface__realize (frame, faces, num, size, font);
391 rface = default_rface;
393 if (stop > font_change)
395 if (stop > face_change)
399 if (pos < mtext_nchars (mt))
400 c = mtext_ref_char (mt, pos);
404 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
406 g_tmp.g.from = pos++;
409 category = mchar_get_prop (c, Mcategory);
410 if (category == McatCf)
411 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
412 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
413 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
415 g_tmp.category = GLYPH_CATEGORY_NORMAL;
417 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
421 ctrl[0] = ctrl[1] = g_tmp;
423 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
424 APPEND_GLYPH (gstring, ctrl[0]);
425 APPEND_GLYPH (gstring, ctrl[1]);
428 APPEND_GLYPH (gstring, g_tmp);
429 if (c == '\n' && gstring->control.two_dimensional)
432 /* Append an anchor glyph. */
434 g_tmp.type = GLYPH_ANCHOR;
435 g_tmp.g.from = g_tmp.g.to = pos;
436 APPEND_GLYPH (gstring, g_tmp);
439 if (gstring->control.enable_bidi)
440 max_bidi_level = analyse_bidi_level (gstring);
442 /* The next loop is to change each <rface> member for non-ASCII
443 characters if necessary. */
444 stop = charset_change = language_change = from;
445 rfont = default_rface->rfont;
446 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
452 /* Short cut for the obvious case. */
453 this_script = Mlatin;
456 this_script = (MSymbol) mchar_get_prop (c, Mscript);
457 if (this_script == Minherited || this_script == Mcommon)
461 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
463 if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z')
464 this_script = script;
467 if (this_script == Mcommon && non_latin_script)
468 this_script = non_latin_script;
469 if (this_script == Mcommon)
471 /* Search forward for a character that explicitly
472 specifies a non-latin script. */
476 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
478 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
479 && sym != Minherited)
488 if (pos == stop || script != this_script || g->rface->rfont != rfont)
491 last_g = mface__for_chars (script, language, charset,
493 script = this_script;
494 if (script != Mnil && script != Mlatin)
495 non_latin_script = script;
496 rfont = g->rface->ascii_rface->rfont;
499 if (pos < mtext_nchars (mt) && pos == language_change)
501 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
502 mtext_prop_range (mt, Mlanguage, pos, NULL,
503 &language_change, 0);
505 if (pos < mtext_nchars (mt) && pos == charset_change)
507 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
508 mtext_prop_range (mt, Mcharset, pos, NULL,
512 if (stop > language_change)
513 stop = language_change;
514 if (stop > charset_change)
515 stop = charset_change;
520 last_g = mface__for_chars (script, language, charset, last_g, g, size);
522 /* The next loop is to run FLT or perform the default combining if
524 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
528 if (this->type == GLYPH_CHAR && this->rface->rfont)
532 if (this->rface->layouter != Mnil)
534 MGlyph *prev = MGLYPH (start - 1);
536 while (prev->type == GLYPH_CHAR
537 && prev->category == GLYPH_CATEGORY_FORMATTER
538 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
540 != MCHAR_INVALID_CODE))
542 prev->rface->rfont = this->rface->rfont;
547 (g->type == GLYPH_CHAR
548 && g->g.from != gstring->control.cursor_pos
549 && g->rface->layouter == this->rface->layouter
550 && (g->rface->rfont == this->rface->rfont
551 || (g->category == GLYPH_CATEGORY_FORMATTER
552 && (mfont__encode_char (NULL,
553 (MFont *) this->rface->rfont,
555 != MCHAR_INVALID_CODE))));
557 g->rface->rfont = this->rface->rfont;
558 i = run_flt (gstring, start, i, this->rface);
563 while (g->type == GLYPH_CHAR
565 && g->category == GLYPH_CATEGORY_MODIFIER
567 && g->rface->layouter == Mnil)
571 this->rface->layouter = Mcombining;
572 run_flt (gstring, start, i, this->rface);
575 mfont__get_metric (gstring, start, i);
583 /* At last, reorder glyphs visually if necessary. */
584 if (max_bidi_level > 0)
585 visual_order (gstring);
589 int width, lbearing, rbearing;
593 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
594 MSubTextExtents *extents)
596 int g_physical_ascent, g_physical_descent;
597 MGlyph *g = MGLYPH (from);
598 MGlyph *last_g = MGLYPH (to);
600 g_physical_ascent = gstring->physical_ascent;
601 g_physical_descent = gstring->physical_descent;
602 extents->width = extents->lbearing = extents->rbearing = 0;
604 for (g = MGLYPH (from); g < last_g; g++)
606 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
607 g_physical_descent = MAX (g_physical_descent, g->g.descent);
608 extents->lbearing = MIN (extents->lbearing,
609 extents->width + g->g.lbearing);
610 extents->rbearing = MAX (extents->rbearing,
611 extents->width + g->g.rbearing);
612 extents->width += g->g.xadv;
615 gstring->physical_ascent = g_physical_ascent;
616 gstring->physical_descent = g_physical_descent;
620 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
621 by this function directly. Character glyphs are handled by
622 layouter functions registered in font drivers.
624 This function fill-in all the remaining members of glyphs. */
627 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
629 /* Default width of TAB. */
630 int tab_width = frame->space_width * (gstring->control.tab_width
631 ? gstring->control.tab_width : 8);
635 MDrawControl *control = &(gstring->control);
638 int box_line_height = 0;
639 int ignore_formatting_char = control->ignore_formatting_char;
641 gstring->ascent = gstring->descent = 0;
642 gstring->physical_ascent = gstring->physical_descent = 0;
643 gstring->width = gstring->lbearing = gstring->rbearing = 0;
647 while (g->type != GLYPH_ANCHOR)
649 if (box != g->rface->box)
651 int gidx = GLYPH_INDEX (g);
655 /* Insert the right side of the box. That glyph belongs
656 to the previous grapheme cluster. */
657 MGlyph box_glyph = g[-1];
659 box_glyph.type = GLYPH_BOX;
661 = (control->fixed_width
663 : box->inner_hmargin + box->width + box->outer_hmargin);
664 box_glyph.g.lbearing = 0;
665 box_glyph.g.rbearing = box_glyph.g.xadv;
666 box_glyph.g.xoff = 0;
667 box_glyph.right_padding = 1;
668 gstring->width += box_glyph.g.xadv;
669 gstring->rbearing += box_glyph.g.xadv;
670 INSERT_GLYPH (gstring, gidx, box_glyph);
677 /* Insert the left side of the box. That glyph belongs
678 to the following grapheme cluster. */
679 MGlyph box_glyph = *g;
680 int box_height = (box->width
681 + box->inner_vmargin + box->outer_vmargin);
683 if (box_line_height < box_height)
684 box_line_height = box_height;
685 box_glyph.type = GLYPH_BOX;
687 = (control->fixed_width
689 : box->inner_hmargin + box->width + box->outer_hmargin);
690 box_glyph.g.lbearing = 0;
691 box_glyph.g.rbearing = box_glyph.g.xadv;
692 box_glyph.g.xoff = 0;
693 box_glyph.left_padding = 1;
694 gstring->width += box_glyph.g.xadv;
695 gstring->rbearing += box_glyph.g.xadv;
696 INSERT_GLYPH (gstring, gidx, box_glyph);
702 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
703 g->type = GLYPH_SPACE;
705 if (g->type == GLYPH_CHAR)
707 MRealizedFace *rface = g->rface;
708 MRealizedFont *rfont = rface->rfont;
710 int from = GLYPH_INDEX (g);
712 for (g++; g->type == GLYPH_CHAR; g++)
713 if (! rfont != ! g->rface->rfont
714 || box != g->rface->box
715 || ((fromg->g.code == MCHAR_INVALID_CODE)
716 != (g->g.code == MCHAR_INVALID_CODE))
717 || (g->category == GLYPH_CATEGORY_FORMATTER
718 && ignore_formatting_char))
720 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
723 int to = GLYPH_INDEX (g);
724 MSubTextExtents extents;
726 layout_glyphs (frame, gstring, from, to, &extents);
727 extra_width = - extents.lbearing;
729 && ! control->disable_overlapping_adjustment
730 && (! control->orientation_reversed
731 ? ((to > 1 || control->align_head)
732 && g->type != GLYPH_ANCHOR)
733 : (((g->type && GLYPH_ANCHOR) || control->align_head)
738 pad.type = GLYPH_PAD;
741 pad.g.xadv = pad.g.rbearing = extra_width;
742 pad.left_padding = 1;
743 INSERT_GLYPH (gstring, from, pad);
745 extents.lbearing = 0;
746 extents.width += extra_width;
747 extents.rbearing += extra_width;
749 g = MGLYPH (from - 1);
750 if (g->type == GLYPH_SPACE)
752 /* The pad just inserted is absorbed (maybe
753 partially) by the previous space while
754 keeping at least some space width. For the
755 moment, we use the arbitrary width 2-pixel.
756 Perhaps, it should be decided by the current
757 face, or a default value of the current
758 frame, which is, however, not yet
760 if (extra_width + 2 < g->g.xadv)
762 g->g.xadv -= extra_width;
766 extra_width = g->g.xadv - 2;
769 gstring->width -= extra_width;
770 gstring->rbearing -= extra_width;
775 extra_width = extents.rbearing - extents.width;
777 && ! control->disable_overlapping_adjustment
778 && (GLYPH_INDEX (g) < gstring->used - 1
779 || (control->orientation_reversed && control->align_head)))
781 if (g->type == GLYPH_SPACE && box == g->rface->box)
784 pad.type = GLYPH_PAD;
787 pad.g.xadv = pad.g.rbearing = extra_width;
788 INSERT_GLYPH (gstring, to, pad);
793 g[-1].g.xadv += extra_width;
794 extents.width += extra_width;
797 if (gstring->lbearing > gstring->width + extents.lbearing)
798 gstring->lbearing = gstring->width + extents.lbearing;
799 if (gstring->rbearing < gstring->width + extents.rbearing)
800 gstring->rbearing = gstring->width + extents.rbearing;
801 gstring->width += extents.width;
802 if (gstring->ascent < rface->ascent)
803 gstring->ascent = rface->ascent;
804 if (gstring->descent < rface->descent)
805 gstring->descent = rface->descent;
809 for (; fromg < g; fromg++)
811 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
812 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
813 fromg->g.xadv = fromg->g.rbearing = 1;
815 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
816 fromg->g.xoff = fromg->g.lbearing = 0;
817 fromg->g.ascent = fromg->g.descent = 0;
818 gstring->width += fromg->g.xadv;
819 gstring->rbearing += fromg->g.xadv;
821 if (gstring->ascent < frame->rface->ascent)
822 gstring->ascent = frame->rface->ascent;
823 if (gstring->descent < frame->descent)
824 gstring->descent = frame->rface->descent;
827 else if (g->type == GLYPH_SPACE)
830 g->g.xadv = g->rface->space_width;
831 else if (g->g.c == '\n')
833 g->g.xadv = control->cursor_width;
836 if (control->cursor_bidi)
838 else if (g->g.xadv < 0)
839 g->g.xadv = g->rface->space_width;
842 else if (g->g.c == '\t')
844 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
850 if (g[-1].type == GLYPH_PAD)
852 /* This space glyph absorbs (maybe partially) the
853 previous padding glyph. */
854 g->g.xadv -= g[-1].g.xadv;
856 /* But, keep at least some space width. For the
857 moment, we use the arbitrary width 2-pixel. */
860 g->g.rbearing = g->g.xadv;
861 gstring->width += g->g.xadv;
862 gstring->rbearing += g->g.xadv;
865 if (gstring->ascent < g->rface->ascent)
866 gstring->ascent = g->rface->ascent;
867 if (gstring->descent < g->rface->descent)
868 gstring->descent = g->rface->descent;
874 gstring->width += g->g.xadv;
875 gstring->rbearing += g->g.xadv;
882 /* Insert the right side of the box. */
883 int gidx = GLYPH_INDEX (g);
884 MGlyph box_glyph = g[-1];
886 box_glyph.type = GLYPH_BOX;
888 = (control->fixed_width
890 : box->inner_hmargin + box->width + box->outer_hmargin);
891 box_glyph.g.lbearing = 0;
892 box_glyph.g.rbearing = box_glyph.g.xadv;
893 box_glyph.g.xoff = 0;
894 box_glyph.right_padding = 1;
895 gstring->width += box_glyph.g.xadv;
896 gstring->rbearing += box_glyph.g.xadv;
897 INSERT_GLYPH (gstring, gidx, box_glyph);
900 gstring->text_ascent = gstring->ascent;
901 gstring->text_descent = gstring->descent;
902 if (gstring->text_ascent < gstring->physical_ascent)
903 gstring->text_ascent = gstring->physical_ascent;
904 if (gstring->text_descent < gstring->physical_descent)
905 gstring->text_descent = gstring->physical_descent;
906 gstring->line_ascent = gstring->text_ascent;
907 gstring->line_descent = gstring->text_descent;
908 if (box_line_height > 0)
910 gstring->line_ascent += box_line_height;
911 gstring->physical_ascent = gstring->line_ascent;
912 gstring->line_descent += box_line_height;
913 gstring->physical_descent = gstring->line_descent;
916 if (gstring->line_ascent < control->min_line_ascent)
917 gstring->line_ascent = control->min_line_ascent;
918 else if (control->max_line_ascent
919 && control->max_line_ascent > control->min_line_ascent
920 && gstring->line_ascent > control->max_line_ascent)
921 gstring->line_ascent = control->max_line_ascent;
923 if (gstring->line_descent < control->min_line_descent)
924 gstring->line_descent = control->min_line_descent;
925 else if (control->max_line_descent
926 && control->max_line_descent > control->min_line_descent
927 && gstring->line_descent > control->max_line_descent)
928 gstring->line_descent = control->max_line_descent;
929 gstring->height = gstring->line_ascent + gstring->line_descent;
931 if (control->orientation_reversed
934 /* We must adjust TAB width for RTL orientation. */
935 width = gstring->indent;
937 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
939 if (g->type == GLYPH_CHAR && g->g.c == '\t')
941 int this_width = tab_width - (width % tab_width);
943 if (g[1].type == GLYPH_PAD)
944 this_width -= g[1].g.xadv;
945 if (g[-1].type == GLYPH_PAD)
946 this_width -= g[-1].g.xadv;
949 gstring->width += this_width - g->g.xadv;
950 gstring->rbearing += this_width - g->g.xadv;
951 g->g.xadv = this_width;
962 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
963 MGlyphString *gstring, int from, int to,
964 int *from_idx, int *to_idx, int *to_x)
966 MGlyph *g = MGLYPH (1);
967 MDrawRegion region = (MDrawRegion) NULL;
968 MDrawControl *control = &gstring->control;
971 int cursor_bidi = control->cursor_bidi;
973 if (control->with_cursor && control->cursor_width)
975 if (gstring->from <= control->cursor_pos
976 && gstring->to > control->cursor_pos)
977 cursor_pos = control->cursor_pos;
980 && gstring->from <= control->cursor_pos - 1
981 && gstring->to > control->cursor_pos - 1)
982 prev_pos = control->cursor_pos - 1;
985 *from_idx = *to_idx = 0;
987 while (g->type != GLYPH_ANCHOR)
989 if (g->g.from >= from && g->g.from < to)
991 MGlyph *fromg = g, *cursor = NULL;
992 MRealizedFace *rface = g->rface;
994 int cursor_width = 0;
998 *from_idx = GLYPH_INDEX (g);
999 while (g->g.from >= from && g->g.from < to
1000 && g->rface == rface)
1003 if (g->type != GLYPH_BOX
1004 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1007 cursor = g, cursor_x = x + width;
1008 cursor_width += g->g.xadv;
1010 width += g++->g.xadv;
1013 && (control->as_image
1014 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1016 int this_x = x, this_width = width;
1018 if (fromg->type == GLYPH_BOX)
1019 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1020 if (g[-1].type == GLYPH_BOX)
1021 this_width -= g[-1].g.xadv;
1022 (frame->driver->fill_space)
1023 (frame, win, rface, 0,
1024 this_x, y - gstring->text_ascent, this_width,
1025 gstring->text_ascent + gstring->text_descent,
1026 control->clip_region);
1033 rect.y = y - gstring->text_ascent;
1034 rect.height = gstring->text_ascent + gstring->text_descent;
1037 rect.width = ((control->cursor_width > 0
1038 && control->cursor_width < cursor_width)
1039 ? control->cursor_width : cursor_width);
1043 if (cursor->bidi_level % 2)
1044 rect.x += cursor_width - rect.width;
1045 (*frame->driver->fill_space)
1046 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1047 control->clip_region);
1049 region = (*frame->driver->region_from_rect) (&rect);
1051 (*frame->driver->region_add_rect) (region, &rect);
1054 if (cursor->bidi_level % 2)
1057 rect.width = cursor_width < 4 ? cursor_width : 4;
1058 (*frame->driver->fill_space)
1059 (frame, win, rface, 1,
1060 rect.x, rect.y, rect.width, rect.height,
1061 control->clip_region);
1062 (*frame->driver->region_add_rect) (region, &rect);
1074 if (fromg->type != GLYPH_BOX
1075 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1078 cursor = fromg, cursor_x = x + temp_width;
1079 cursor_width += fromg->g.xadv;
1081 temp_width += fromg++->g.xadv;
1088 if (! (cursor->bidi_level % 2))
1089 rect.x += cursor_width - 1;
1090 rect.y = y - gstring->text_ascent;
1091 rect.height = gstring->text_ascent + gstring->text_descent;
1093 (*frame->driver->fill_space)
1094 (frame, win, rface, 1,
1095 rect.x, rect.y, rect.width, rect.height,
1096 control->clip_region);
1098 region = (*frame->driver->region_from_rect) (&rect);
1100 (*frame->driver->region_add_rect) (region, &rect);
1101 rect.y += rect.height - 2;
1103 rect.width = cursor_width < 4 ? cursor_width : 4;
1104 if (! (cursor->bidi_level % 2))
1105 rect.x -= rect.width - 1;
1106 (*frame->driver->fill_space) (frame, win, rface, 1,
1107 rect.x, rect.y, rect.width, rect.height,
1108 control->clip_region);
1109 (*frame->driver->region_add_rect) (region, &rect);
1113 *to_idx = GLYPH_INDEX (g);
1123 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1124 MGlyphString *gstring, int from_idx, int to_idx,
1125 int reverse, MDrawRegion region)
1127 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1133 (*frame->driver->region_to_rect) (region, &rect);
1136 while (g != gend && x + g->g.rbearing <= rect.x)
1139 width -= g++->g.xadv;
1140 while (! g->enabled && g != gend)
1144 rect.x += rect.width;
1145 if (rect.x < x + width)
1148 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1150 width -= (--gend)->g.xadv;
1151 while (! gend->enabled && g != gend)
1155 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1164 MRealizedFace *rface = g->rface;
1165 int width = g->g.xadv;
1166 MGlyph *from_g = g++;
1168 /* Handle the glyphs of the same type/face at once. */
1170 && g->type == from_g->type
1171 && g->rface == rface
1172 && ((g->g.code == MCHAR_INVALID_CODE)
1173 == (from_g->g.code == MCHAR_INVALID_CODE))
1175 width += g++->g.xadv;
1177 if (from_g->type == GLYPH_CHAR)
1179 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1180 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1183 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1186 else if (from_g->type == GLYPH_BOX)
1188 /* Draw the left or right side of a box. If
1189 from_g->lbearing is nonzero, this is the left side,
1190 else this is the right side. */
1191 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1194 if (from_g->type != GLYPH_BOX)
1197 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1198 x, y, width, region);
1201 /* Draw the top and bottom side of a box. */
1202 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1203 x, y, width, region);
1214 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1215 int *from_x, int *to_x)
1218 int left_idx = *left, right_idx = *right;
1219 int left_x, right_x, x;
1221 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1224 if (x + g->g.rbearing > 0)
1226 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1228 left_idx = GLYPH_INDEX (g);
1233 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1236 if (x - g->g.xadv + g->g.lbearing < 0)
1238 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1240 right_idx = GLYPH_INDEX (g) + 1;
1245 if (*left == left_idx && *right == right_idx)
1248 if (*left != left_idx)
1250 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1255 if (*right != right_idx)
1257 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1267 gstring_width (MGlyphString *gstring, int from, int to,
1268 int *lbearing, int *rbearing)
1273 if (from <= gstring->from && to >= gstring->to)
1276 *lbearing = gstring->lbearing;
1278 *rbearing = gstring->rbearing;
1279 return gstring->width;
1286 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1287 if (g->g.from >= from && g->g.from < to)
1289 if (lbearing && width + g->g.lbearing < *lbearing)
1290 *lbearing = width + g->g.lbearing;
1291 if (rbearing && width + g->g.rbearing > *rbearing)
1292 *rbearing = width + g->g.rbearing;
1300 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1301 MGlyphString *gstring, int from, int to)
1303 MDrawControl *control = &gstring->control;
1305 MDrawRegion clip_region, cursor_region;
1306 int from_idx, to_idx;
1311 if (control->orientation_reversed)
1312 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1314 x += gstring->indent;
1316 /* At first, draw all glyphs without cursor. */
1317 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1318 &from_idx, &to_idx, &to_x);
1320 if (control->partial_update)
1323 rect.width = to_x - x;
1324 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1326 rect.y = y - gstring->line_ascent;
1327 rect.height = gstring->height;
1328 clip_region = (*frame->driver->region_from_rect) (&rect);
1329 if (control->clip_region)
1330 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1333 clip_region = control->clip_region;
1336 clip_region = control->clip_region;
1338 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1343 (*frame->driver->intersect_region) (cursor_region, clip_region);
1344 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1347 if (clip_region != control->clip_region)
1348 (*frame->driver->free_region) (clip_region);
1350 (*frame->driver->free_region) (cursor_region);
1354 static int gstring_num;
1357 free_gstring (void *object)
1359 MGlyphString *gstring = (MGlyphString *) object;
1362 free_gstring (gstring->next);
1363 if (gstring->size > 0)
1364 free (gstring->glyphs);
1370 static MGlyphString scratch_gstring;
1372 static MGlyphString *
1373 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1376 MGlyphString *gstring;
1378 if (pos == mt->nchars)
1382 gstring = &scratch_gstring;
1383 if (gstring->size == 0)
1388 g_tmp.type = GLYPH_ANCHOR;
1389 APPEND_GLYPH (gstring, g_tmp);
1390 APPEND_GLYPH (gstring, g_tmp);
1391 APPEND_GLYPH (gstring, g_tmp);
1392 gstring->glyphs[1].type = GLYPH_SPACE;
1393 gstring->glyphs[1].g.c = '\n';
1394 gstring->glyphs[1].g.code = '\n';
1396 gstring->from = pos;
1398 g->rface = frame->rface;
1399 g->g.from = g->g.to = pos;
1401 g->rface = frame->rface;
1402 g->g.from = pos++, g->g.to = pos;
1404 g->rface = frame->rface;
1405 g->g.from = g->g.to = pos;
1410 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1411 MLIST_INIT1 (gstring, glyphs, 128);
1415 gstring->frame = frame;
1416 gstring->tick = frame->tick;
1417 gstring->top = gstring;
1418 gstring->control = *control;
1419 gstring->indent = gstring->width_limit = 0;
1420 if (control->format)
1421 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1423 gstring->width_limit = control->max_line_width;
1424 gstring->anti_alias = control->anti_alias;
1428 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1431 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1434 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1442 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1443 a width of glyphs for the character at I of MT. If I is not a
1444 beginning of a grapheme cluster, the corresponding element is
1446 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1447 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1448 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1449 pos_width[g->g.from - gstring->from] += g->g.xadv;
1450 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1452 if (pos_width[i] > 0)
1454 if (width + pos_width[i] > gstring->width_limit)
1457 width += pos_width[i];
1460 pos = gstring->from + i;
1461 if (gstring->control.line_break)
1463 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1464 gstring->from, gstring->from + i,
1466 if (pos <= gstring->from)
1468 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1471 else if (pos >= gstring->to)
1476 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1479 if (pos < gstring->to)
1481 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1482 layout_glyph_string (frame, gstring);
1487 /* Return a gstring that covers a character at POS. */
1489 static MGlyphString *
1490 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1492 MGlyphString *gstring = NULL;
1494 if (pos < mtext_nchars (mt))
1496 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1499 && ((prop->start != 0
1500 && mtext_ref_char (mt, prop->start - 1) != '\n')
1501 || (prop->end < mtext_nchars (mt)
1502 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1504 mtext_detach_property (prop);
1509 gstring = prop->val;
1510 if (gstring->frame != frame
1511 || gstring->tick != frame->tick
1512 || memcmp (control, &gstring->control,
1513 (char *) (&control->with_cursor)
1514 - (char *) (control))
1515 || control->cursor_pos != gstring->control.cursor_pos
1516 || control->cursor_width != gstring->control.cursor_width
1517 || control->cursor_bidi != gstring->control.cursor_bidi)
1519 mtext_detach_property (prop);
1524 else if (! control->cursor_width)
1532 offset = mtext_character (mt, pos, 0, '\n');
1537 offset -= gstring->from;
1539 for (gst = gstring; gst; gst = gst->next)
1543 gst->from += offset;
1545 for (i = 0; i < gst->used; i++)
1547 gst->glyphs[i].g.from += offset;
1548 gst->glyphs[i].g.to += offset;
1551 M17N_OBJECT_REF (gstring);
1556 int line = 0, y = 0;
1558 if (pos < mtext_nchars (mt))
1560 beg = mtext_character (mt, pos, 0, '\n');
1568 end = mtext_nchars (mt) + (control->cursor_width != 0);
1569 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1570 if (beg < mtext_nchars (mt))
1571 compose_glyph_string (frame, mt, beg, end, gstring);
1572 layout_glyph_string (frame, gstring);
1574 if (gstring->width_limit
1575 && gstring->width > gstring->width_limit)
1577 MGlyphString *gst = gstring;
1579 truncate_gstring (frame, mt, gst);
1580 while (gst->to < end)
1582 line++, y += gst->height;
1583 gst->next = alloc_gstring (frame, mt, gst->from, control,
1585 gst->next->top = gstring;
1586 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1588 layout_glyph_string (frame, gst);
1589 if (gst->width <= gst->width_limit)
1591 truncate_gstring (frame, mt, gst);
1595 if (! control->disable_caching && pos < mtext_nchars (mt))
1597 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1598 MTEXTPROP_VOLATILE_STRONG);
1600 if (end > mtext_nchars (mt))
1601 end = mtext_nchars (mt);
1602 mtext_attach_property (mt, beg, end, prop);
1603 M17N_OBJECT_UNREF (prop);
1607 while (gstring->to <= pos)
1609 if (! gstring->next)
1611 gstring = gstring->next;
1613 gstring->control = *control;
1619 static MDrawControl control_noop;
1621 #define ASSURE_CONTROL(control) \
1623 control = &control_noop; \
1628 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1629 MText *mt, int from, int to,
1630 MDrawControl *control)
1632 MGlyphString *gstring;
1634 M_CHECK_POS_X (mt, from, -1);
1635 ASSURE_CONTROL (control);
1636 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1637 to = mtext_nchars (mt) + (control->cursor_width != 0);
1641 gstring = get_gstring (frame, mt, from, to, control);
1643 MERROR (MERROR_DRAW, -1);
1644 render_glyph_string (frame, win, x, y, gstring, from, to);
1648 y += gstring->line_descent;
1649 M17N_OBJECT_UNREF (gstring->top);
1650 gstring = get_gstring (frame, mt, from, to, control);
1651 y += gstring->line_ascent;
1652 render_glyph_string (frame, win, x, y, gstring, from, to);
1655 M17N_OBJECT_UNREF (gstring->top);
1662 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1668 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1669 if (g->g.from <= pos && g->g.to > pos)
1674 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1675 if (g->g.from <= pos && g->g.to > pos)
1682 /* for debugging... */
1686 dump_gstring (MGlyphString *gstring, int indent, int type)
1688 char *prefix = (char *) alloca (indent + 1);
1689 MGlyph *g, *first_g, *last_g;
1691 memset (prefix, 32, indent);
1694 fprintf (stderr, "(glyph-string");
1698 first_g = MGLYPH (0);
1699 last_g = first_g + gstring->used;
1703 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1704 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1707 for (g = first_g; g < last_g; g++)
1710 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1713 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1714 : g->type == GLYPH_ANCHOR ? "ANC"
1715 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1716 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1717 g->g.xadv, g->bidi_level);
1718 if (g->g.xoff || g->g.yoff)
1719 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1720 fprintf (stderr, ")");
1722 fprintf (stderr, ")");
1726 /* m17n-X internal APIs */
1731 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1733 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1734 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1736 Mcommon = msymbol ("common");
1738 McatCc = msymbol ("Cc");
1739 McatCf = msymbol ("Cf");
1741 MbidiR = msymbol ("R");
1742 MbidiAL = msymbol ("AL");
1743 MbidiRLE = msymbol ("RLE");
1744 MbidiRLO = msymbol ("RLO");
1745 MbidiBN = msymbol ("BN");
1746 MbidiS = msymbol ("S");
1747 MbidiNSM = msymbol ("NSM");
1749 #if FRIBIDI_INTERFACE_VERSION < 3
1750 fribidi_set_mirroring (TRUE);
1752 fribidi_set_mirroring (1);
1756 M_break_at_space = msymbol ("bs");
1757 M_break_at_word = msymbol ("bw");
1758 M_break_at_any = msymbol ("ba");
1759 M_kinsoku_bol = msymbol ("kb");
1760 M_kinsoku_eol = msymbol ("ke");
1768 MLIST_FREE1 (&scratch_gstring, glyphs);
1769 M17N_OBJECT_UNREF (linebreak_table);
1770 linebreak_table = NULL;
1774 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1778 /*** @addtogroup m17nDraw */
1783 @brief Draw an M-text on a window.
1785 The mdraw_text () function draws the text between $FROM and $TO of
1786 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1788 The appearance of the text (size, style, color, etc) is specified
1789 by the value of the text property whose key is @c Mface. If the
1790 M-text or a part of the M-text does not have such a text property,
1791 the default face of $FRAME is used.
1793 The font used to draw a character in the M-text is selected from
1794 the value of the fontset property of a face by the following
1799 <li> Search the text properties given to the character for the one
1800 whose key is @c Mcharset; its value should be either a symbol
1801 specifying a charset or #Mnil. If the value is #Mnil,
1802 proceed to the next step.
1804 Otherwise, search the mapping table of the fontset for the
1805 charset. If no entry is found proceed to the next step.
1807 If an entry is found, use one of the fonts in the entry that
1808 has a glyph for the character and that matches best with the
1809 face properties. If no such font exists, proceed to the next
1812 <li> Get the character property "script" of the character. If it is
1813 inherited, get the script property from the previous
1814 characters. If there is no previous character, or none of
1815 them has the script property other than inherited, proceed to
1818 Search the text properties given to the character for the one
1819 whose key is @c Mlanguage; its value should be either a
1820 symbol specifying a language or @c Mnil.
1822 Search the mapping table of the fontset for the combination
1823 of the script and language. If no entry is found, proceed to
1826 If an entry is found, use one of the fonts in the entry that
1827 has a glyph for the character and that matches best with the
1828 face properties. If no such font exists, proceed to the next
1831 <li> Search the fall-back table of the fontset for a font that has
1832 a glyph of the character. If such a font is found, use that
1837 If no font is found by the algorithm above, this function draws an
1838 empty box for the character.
1840 This function draws only the glyph foreground. To specify the
1841 background color, use mdraw_image_text () or
1842 mdraw_text_with_control ().
1844 This function is the counterpart of <tt>XDrawString ()</tt>,
1845 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1846 in the X Window System.
1849 If the operation was successful, mdraw_text () returns 0. If an
1850 error is detected, it returns -1 and assigns an error code to the
1851 external variable #merror_code. */
1853 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1855 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1856 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1858 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1859 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1860 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1861 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1863 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1864 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1868 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1869 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1870 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1871 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1872 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1873 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1875 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1876 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1878 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1879 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1880 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1882 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1883 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1885 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1886 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1888 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1889 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1891 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1892 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1896 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1898 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1899 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1901 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1902 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1905 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1906 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1908 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1915 mdraw_image_text () */
1918 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1919 MText *mt, int from, int to)
1921 MDrawControl control;
1923 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1924 memset (&control, 0, sizeof control);
1925 control.as_image = 0;
1926 return draw_text (frame, win, x, y, mt, from, to, &control);
1933 @brief Draw an M-text on a window as an image.
1935 The mdraw_image_text () function draws the text between $FROM and
1936 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1937 coordinate ($X, $Y).
1939 The way to draw a text is the same as in mdraw_text () except that
1940 this function also draws the background with the color specified
1943 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1944 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1945 functions in the X Window System.
1948 If the operation was successful, mdraw_image_text () returns 0.
1949 If an error is detected, it returns -1 and assigns an error code
1950 to the external variable #merror_code. */
1953 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1955 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1956 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1957 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1959 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1960 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1962 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1963 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1967 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1968 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1970 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1980 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1981 MText *mt, int from, int to)
1983 MDrawControl control;
1985 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1986 memset (&control, 0, sizeof control);
1987 control.as_image = 1;
1988 return draw_text (frame, win, x, y, mt, from, to, &control);
1994 @brief Draw an M-text on a window with fine control.
1996 The mdraw_text_with_control () function draws the text between
1997 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1998 coordinate ($X, $Y).
2000 The way to draw a text is the same as in mdraw_text () except that
2001 this function also follows what specified in the drawing control
2004 For instance, if \<two_dimensional\> of $CONTROL is nonzero, this
2005 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2006 breaks lines and the following characters are drawn in the next
2007 line. See the documentation of the structure @ MDrawControl for
2011 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2013 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2014 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2017 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2018 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2020 ¤¿¤È¤¨¤Ð $CONTROL ¤Î \<two_dimensional\> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2021 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2022 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2025 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2026 MText *mt, int from, int to, MDrawControl *control)
2028 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2029 return draw_text (frame, win, x, y, mt, from, to, control);
2035 @brief Compute text pixel width.
2037 The mdraw_text_extents () function computes the width of text
2038 between $FROM and $TO of M-text $MT when it is drawn on a window
2039 of frame $FRAME using the mdraw_text_with_control () function with
2040 the drawing control object $CONTROL.
2042 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2043 the bounding box of character ink of the M-text, and stores the
2044 results in the members of the structure pointed to by
2045 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2046 surrounding box, the box is included in the bounding box.
2048 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2049 computes the bounding box that provides minimum spacing to other
2050 graphical features (such as surrounding box) for the M-text, and
2051 stores the results in the members of the structure pointed to by
2052 $OVERALL_LOGICAL_RETURN.
2054 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2055 computes the bounding box that provides minimum spacing to the
2056 other M-text drawn, and stores the results in the members of the
2057 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2058 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2059 min_line_ascent, min_line_descent, max_line_ascent, and
2060 max_line_descent of $CONTROL are all zero.
2063 This function returns the width of the text to be drawn in the
2064 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2065 text is drawn in multiple physical lines, it returns the width of
2066 the widest line. If an error occurs, it returns -1 and assigns an
2067 error code to the external variable #merror_code. */
2071 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2073 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2074 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2075 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2077 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2078 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2079 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2080 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2082 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2083 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2084 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2085 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2087 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2088 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2089 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2090 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2091 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2092 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2095 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2096 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2097 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2099 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2106 mdraw_text_extents (MFrame *frame,
2107 MText *mt, int from, int to, MDrawControl *control,
2108 MDrawMetric *overall_ink_return,
2109 MDrawMetric *overall_logical_return,
2110 MDrawMetric *overall_line_return)
2112 MGlyphString *gstring;
2114 int width, lbearing, rbearing;
2116 ASSURE_CONTROL (control);
2117 M_CHECK_POS_X (mt, from, -1);
2118 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2119 to = mtext_nchars (mt) + (control->cursor_width != 0);
2123 gstring = get_gstring (frame, mt, from, to, control);
2125 MERROR (MERROR_DRAW, -1);
2126 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2127 if (overall_ink_return)
2128 overall_ink_return->y = - gstring->physical_ascent;
2129 if (overall_logical_return)
2130 overall_logical_return->y = - gstring->ascent;
2131 if (overall_line_return)
2132 overall_line_return->y = - gstring->line_ascent;
2134 for (from = gstring->to; from < to; from = gstring->to)
2136 int this_width, this_lbearing, this_rbearing;
2138 y += gstring->line_descent;
2139 M17N_OBJECT_UNREF (gstring->top);
2140 gstring = get_gstring (frame, mt, from, to, control);
2141 this_width = gstring_width (gstring, from, to,
2142 &this_lbearing, &this_rbearing);
2143 y += gstring->line_ascent;
2144 if (width < this_width)
2146 if (rbearing < this_rbearing)
2147 rbearing = this_rbearing;
2148 if (lbearing > this_lbearing)
2149 lbearing = this_lbearing;
2151 if (overall_ink_return)
2153 overall_ink_return->x = lbearing;
2154 overall_ink_return->width = rbearing - lbearing;
2155 overall_ink_return->height
2156 = y + gstring->physical_descent - overall_ink_return->y;
2158 if (overall_logical_return)
2160 overall_logical_return->x = 0;
2161 overall_logical_return->width = width;
2162 overall_logical_return->height
2163 = y + gstring->descent - overall_logical_return->y;
2165 if (overall_line_return)
2167 overall_line_return->x = lbearing;
2168 overall_line_return->width = MAX (width, rbearing - lbearing);
2169 overall_line_return->height
2170 = y + gstring->line_descent - overall_line_return->y;
2173 M17N_OBJECT_UNREF (gstring->top);
2180 @brief Compute the text dimensions of each character of M-text.
2182 The mdraw_text_per_char_extents () function computes the drawn
2183 metric of each character between $FROM and $TO of M-text $MT
2184 assuming that they are drawn on a window of frame $FRAME using the
2185 mdraw_text_with_control () function with the drawing control
2188 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2189 $LOGICAL_ARRAY_RETURN. Each successive element of
2190 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2191 ink and logical metrics of successive characters respectively,
2192 relative to the drawing origin of the M-text. The number of
2193 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2194 been set is returned to $NUM_CHARS_RETURN.
2196 If $ARRAY_SIZE is too small to return all metrics, the function
2197 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2198 Otherwise, it returns zero.
2200 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2201 @c NULL, this function also computes the metrics of the overall
2202 text and stores the results in the members of the structure
2203 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2205 If $CONTROL->two_dimensional is nonzero, this function computes
2206 only the metrics of characters in the first line. */
2208 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2210 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2211 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2212 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2214 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2215 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2216 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2217 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2218 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2220 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2221 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2224 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2225 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2226 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2228 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2231 mdraw_text_per_char_extents (MFrame *frame,
2232 MText *mt, int from, int to,
2233 MDrawControl *control,
2234 MDrawMetric *ink_array_return,
2235 MDrawMetric *logical_array_return,
2237 int *num_chars_return,
2238 MDrawMetric *overall_ink_return,
2239 MDrawMetric *overall_logical_return)
2241 MGlyphString *gstring;
2245 ASSURE_CONTROL (control);
2246 *num_chars_return = to - from;
2247 if (array_size < *num_chars_return)
2248 MERROR (MERROR_DRAW, -1);
2249 if (overall_logical_return)
2250 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2251 if (overall_ink_return)
2252 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2254 M_CHECK_RANGE (mt, from, to, -1, 0);
2255 gstring = get_gstring (frame, mt, from, to, control);
2258 *num_chars_return = 0;
2262 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2263 if (g->g.from >= from && g->g.from < to)
2265 int start = g->g.from;
2267 int width = g->g.xadv;
2268 int lbearing = g->g.lbearing;
2269 int rbearing = g->g.rbearing;
2270 int ascent = g->g.ascent;
2271 int descent = g->g.descent;
2273 int logical_descent;
2275 if (g->rface->rfont)
2277 logical_ascent = g->rface->rfont->ascent;
2278 logical_descent = g->rface->rfont->descent;
2282 logical_ascent = g->rface->ascent;
2283 logical_descent = g->rface->descent;
2285 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2287 if (lbearing < width + g->g.lbearing)
2288 lbearing = width + g->g.lbearing;
2289 if (rbearing < width + g->g.rbearing)
2290 rbearing = width + g->g.rbearing;
2292 if (ascent < g->g.ascent)
2293 ascent = g->g.ascent;
2294 if (descent < g->g.descent)
2295 descent = g->g.descent;
2302 if (ink_array_return)
2304 ink_array_return[start - from].x = x + lbearing;
2305 ink_array_return[start - from].y = - ascent;
2306 ink_array_return[start - from].width = rbearing - lbearing;
2307 ink_array_return[start - from].height = ascent + descent;
2309 if (logical_array_return)
2311 logical_array_return[start - from].x = x;
2312 logical_array_return[start - from].y = - logical_descent;
2313 logical_array_return[start - from].height
2314 = logical_ascent + logical_descent;
2315 logical_array_return[start - from].width = width;
2323 if (overall_ink_return)
2325 overall_ink_return->y = - gstring->line_ascent;
2326 overall_ink_return->x = gstring->lbearing;
2327 overall_ink_return->width = x - gstring->lbearing;
2328 overall_ink_return->height = gstring->height;
2330 if (overall_logical_return)
2332 overall_logical_return->y = - gstring->ascent;
2333 overall_logical_return->x = 0;
2334 overall_logical_return->width = x;
2335 overall_logical_return->height = gstring->ascent + gstring->descent;
2338 M17N_OBJECT_UNREF (gstring->top);
2345 @brief Return the character position nearest to the coordinates.
2347 The mdraw_coordinates_position () function checks which character
2348 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2349 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2350 mdraw_text_with_control () function with the drawing control
2351 object $CONTROL. Here, the character position means the number of
2352 characters that precede the character in question in $MT, that is,
2353 the character position of the first character is 0.
2355 $FRAME is used only to get the default face information.
2358 If the glyph image of a character covers coordinate ($X, $Y),
2359 mdraw_coordinates_position () returns the character position of
2361 If $Y is less than the minimum Y-coordinate of the drawn area, it
2363 If $Y is greater than the maximum Y-coordinate of the drawn area,
2365 If $Y fits in with the drawn area but $X is less than the minimum
2366 X-coordinate, it returns the character position of the first
2367 character drawn on the line $Y.\n\n
2368 If $Y fits in with the drawn area but $X is greater than the
2369 maximum X-coordinate, it returns the character position of the
2370 last character drawn on the line $Y. */
2373 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2375 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2376 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2377 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2378 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2379 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2380 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2382 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2385 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2386 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2387 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2388 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2389 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2390 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2391 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2392 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2395 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2396 int x_offset, int y_offset, MDrawControl *control)
2398 MGlyphString *gstring;
2403 M_CHECK_POS_X (mt, from, -1);
2404 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2405 to = mtext_nchars (mt) + (control->cursor_width != 0);
2411 ASSURE_CONTROL (control);
2412 gstring = get_gstring (frame, mt, from, to, control);
2413 while (y + gstring->line_descent <= y_offset
2414 && gstring->to < to)
2417 y += gstring->line_descent;
2418 M17N_OBJECT_UNREF (gstring->top);
2419 gstring = get_gstring (frame, mt, from, to, control);
2420 y += gstring->line_ascent;
2423 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2424 if (! control->orientation_reversed)
2426 width = gstring->indent;
2427 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2428 if (g->g.from >= from && g->g.from < to)
2431 if (width > x_offset)
2437 width = - gstring->indent;
2438 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2439 if (g->g.from >= from && g->g.from < to)
2442 if (width < x_offset)
2446 if (g->type == GLYPH_ANCHOR
2447 && control->two_dimensional
2448 && g[-1].g.c == '\n')
2451 M17N_OBJECT_UNREF (gstring->top);
2459 @brief Compute information about a glyph.
2461 The mdraw_glyph_info () function computes information about a
2462 glyph that covers a character at position $POS of the M-text $MT
2463 assuming that the text is drawn from the character at $FROM of $MT
2464 on a window of frame $FRAME using the mdraw_text_with_control ()
2465 function with the drawing control object $CONTROL.
2467 The information is stored in the members of $INFO. */
2469 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2471 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2472 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2473 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2474 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2476 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2484 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2485 MDrawControl *control, MDrawGlyphInfo *info)
2487 MGlyphString *gstring;
2491 M_CHECK_RANGE_X (mt, from, pos, -1);
2493 ASSURE_CONTROL (control);
2494 gstring = get_gstring (frame, mt, from, pos + 1, control);
2496 MERROR (MERROR_DRAW, -1);
2497 while (gstring->to <= pos)
2499 y += gstring->line_descent;
2500 M17N_OBJECT_UNREF (gstring->top);
2501 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2502 y += gstring->line_ascent;
2504 info->line_from = gstring->from;
2505 if (info->line_from < from)
2506 info->line_from = from;
2507 info->line_to = gstring->to;
2510 if (! control->orientation_reversed)
2512 info->x = gstring->indent;
2513 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2514 info->x += g->g.xadv;
2518 info->x = - gstring->indent;
2519 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2520 info->x -= g->g.xadv;
2521 while (g[-1].g.to == g->g.to)
2524 info->from = g->g.from;
2526 info->metrics.x = g->g.lbearing;
2527 info->metrics.y = - gstring->line_ascent;
2528 info->metrics.height = gstring->height;
2529 info->metrics.width = - g->g.lbearing + g->g.xadv;
2530 if (g->rface->rfont)
2531 info->font = (MFont *) g->rface->rfont;
2534 /* info->logical_width is calculated later. */
2536 if (info->from > info->line_from)
2538 /* The logically previous glyph is on this line. */
2539 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2541 info->prev_from = g_tmp->g.from;
2543 else if (info->line_from > 0
2544 && gstring->from > 0)
2546 /* The logically previous glyph is on the previous line. */
2547 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2548 gstring->from, control);
2549 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2551 info->prev_from = g_tmp->g.from;
2552 M17N_OBJECT_UNREF (gst->top);
2555 info->prev_from = -1;
2557 if (GLYPH_INDEX (g) > 1)
2558 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2559 else if (! control->orientation_reversed)
2561 if (info->line_from > 0)
2565 int p = gstring->from - 1;
2567 gst = get_gstring (frame, mt, p, gstring->from, control);
2568 g_tmp = gst->glyphs + (gst->used - 2);
2569 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2570 M17N_OBJECT_UNREF (gst->top);
2573 info->left_from = info->left_to = -1;
2577 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2581 int p = gstring->to;
2583 gst = get_gstring (frame, mt, p, p + 1, control);
2584 g_tmp = gst->glyphs + (gst->used - 2);
2585 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2586 M17N_OBJECT_UNREF (gst->top);
2589 info->left_from = info->left_to = -1;
2592 if (info->to < gstring->to)
2594 /* The logically next glyph is on this line. */
2595 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2597 info->next_to = g_tmp->g.to;
2599 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2601 /* The logically next glyph is on the next line. */
2603 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2604 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2606 info->next_to = g_tmp->g.to;
2607 M17N_OBJECT_UNREF (gst->top);
2612 for (info->logical_width = (g++)->g.xadv;
2613 g->g.from == pos && g->type != GLYPH_ANCHOR;
2614 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2615 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2617 if (g->type != GLYPH_ANCHOR)
2618 info->right_from = g->g.from, info->right_to = g->g.to;
2619 else if (! control->orientation_reversed)
2621 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2624 M17N_OBJECT_UNREF (gstring->top);
2625 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2627 info->right_from = g->g.from, info->right_to = g->g.to;
2630 info->right_from = info->right_to = -1;
2634 if (info->line_from > 0)
2636 pos = gstring->from - 1;
2637 M17N_OBJECT_UNREF (gstring->top);
2638 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2640 info->right_from = g->g.from, info->right_to = g->g.to;
2643 info->right_from = info->right_to = -1;
2646 M17N_OBJECT_UNREF (gstring->top);
2653 @brief Compute information about glyph sequence.
2655 The mdraw_glyph_list () function computes information about glyphs
2656 corresponding to the text between $FROM and $TO of M-text $MT when
2657 it is drawn on a window of frame $FRAME using the
2658 mdraw_text_with_control () function with the drawing control
2659 object $CONTROL. $GLYPHS is an array of objects to store the
2660 information, and $ARRAY_SIZE is the array size.
2662 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2663 number of actually filled elements in the place pointed by
2664 $NUM_GLYPHS_RETURN, and returns 0.
2666 Otherwise, it stores the required array size in the place pointed
2667 by $NUM_GLYPHS_RETURN, and returns -1. */
2670 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2672 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2673 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2674 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2675 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2677 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2678 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2681 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2691 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2692 MDrawControl *control, MDrawGlyph *glyphs,
2693 int array_size, int *num_glyphs_return)
2695 MGlyphString *gstring;
2700 ASSURE_CONTROL (control);
2701 *num_glyphs_return = 0;
2702 M_CHECK_RANGE (mt, from, to, -1, 0);
2703 gstring = get_gstring (frame, mt, from, to, control);
2706 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2708 if (g->type == GLYPH_BOX
2709 || g->g.from < from || g->g.from >= to)
2711 if (g->type == GLYPH_PAD)
2713 if (g->left_padding)
2714 pad_width = g->g.xadv;
2718 glyphs[-1].x_advance += g->g.xadv;
2724 glyphs->from = g->g.from;
2725 glyphs->to = g->g.to;
2726 glyphs->glyph_code = g->g.code;
2727 glyphs->x_off = g->g.xoff + pad_width;
2728 glyphs->y_off = g->g.yoff;
2729 glyphs->lbearing = g->g.lbearing;
2730 glyphs->rbearing = g->g.rbearing;
2731 glyphs->ascent = g->g.ascent;
2732 glyphs->descent = g->g.descent;
2733 glyphs->x_advance = g->g.xadv + pad_width;
2734 glyphs->y_advance = 0;
2735 if (g->rface->rfont)
2737 glyphs->font = (MFont *) g->rface->rfont;
2738 #ifdef HAVE_FREETYPE
2740 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2741 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2743 #else /* not HAVE_FREETYPE */
2744 glyphs->font_type = Mx;
2745 #endif /* not HAVE_FREETYPE */
2746 glyphs->fontp = g->rface->rfont->fontp;
2750 glyphs->font = NULL;
2751 glyphs->font_type = Mnil;
2752 glyphs->fontp = NULL;
2759 M17N_OBJECT_UNREF (gstring->top);
2761 *num_glyphs_return = n;
2762 return (n <= array_size ? 0 : -1);
2768 @brief Draw one or more textitems.
2770 The mdraw_text_items () function draws one or more M-texts on
2771 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2772 of the textitems to be drawn and $NITEMS is the number of
2773 textitems in the array. */
2776 @brief textitem ¤òɽ¼¨¤¹¤ë.
2778 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2779 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2780 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2782 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2786 MTextItem, mdraw_text (). */
2789 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2790 MDrawTextItem *items, int nitems)
2792 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2794 while (nitems-- > 0)
2797 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2799 mdraw_text_with_control (frame, win, x, y,
2800 items->mt, 0, mtext_nchars (items->mt),
2802 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2803 items->control, NULL, NULL, NULL);
2806 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2812 @brief Option of line breaking for drawing text.
2814 The variable #mdraw_line_break_option specifies line breaking
2815 options by logical-or of the members of #MTextLineBreakOption. It
2816 controls the line breaking algorithm of the function
2817 mdraw_default_line_break (). */
2819 int mdraw_line_break_option;
2823 @brief Calculate a line breaking position.
2825 The function mdraw_default_line_break () calculates a line
2826 breaking position based on the line number $LINE and the
2827 coordinate $Y, when a line is too long to fit within the width
2828 limit. $POS is the position of the character next to the last one
2829 that fits within the limit. $FROM is the position of the first
2830 character of the line, and $TO is the position of the last
2831 character displayed on the line if there were not width limit.
2832 $LINE and $Y are reset to 0 when a line is broken by a newline
2833 character, and incremented each time when a long line is broken
2834 because of the width limit.
2837 This function returns a character position to break the
2842 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2844 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2845 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2846 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2847 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2848 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2849 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2850 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2853 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2857 mdraw_default_line_break (MText *mt, int pos,
2858 int from, int to, int line, int y)
2862 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2873 @brief Obtain per character dimension information.
2875 The mdraw_per_char_extents () function computes the text dimension
2876 of each character in M-text $MT. The faces given as text
2877 properties in $MT and the default face of frame $FRAME determine
2878 the fonts to draw the text. Each successive element in
2879 $ARRAY_RETURN is set to the drawn metrics of successive
2880 characters, which is relative to the origin of the drawing, and a
2881 rectangle for each character in $MT. The number of elements of
2882 $ARRAY_RETURN must be equal to or greater than the number of
2885 If pointer $OVERALL_RETURN is not @c NULL, this function also
2886 computes the extents of the overall text and stores the results in
2887 the members of the structure pointed to by $OVERALL_RETURN. */
2890 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2892 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2893 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2894 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2895 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2896 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2897 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2898 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2900 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2901 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2902 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2904 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2907 mdraw_per_char_extents (MFrame *frame, MText *mt,
2908 MDrawMetric *array_return,
2909 MDrawMetric *overall_return)
2911 int n = mtext_nchars (mt);
2913 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2914 n, &n, overall_return, NULL);
2918 @brief clear cached information.
2920 The mdraw_clear_cache () function clear cached information
2921 on M-text $MT that was attached by any of the drawing functions.
2922 When the behavior of `format' or `line_break'
2923 member functions of MDrawControl is changed, the cache must be cleared.
2928 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2930 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2931 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2932 ¤¢¤ë¤¤¤Ï `line_break'
2933 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2939 mdraw_clear_cache (MText *mt)
2941 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);