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 font_id (MFLTFont *font)
268 return ((MFLTFontForRealized *) font)->rfont->id;
272 run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface)
274 MRealizedFont *rfont = rface->rfont;
275 MSymbol layouter = rface->layouter;
276 MFLTGlyphString flt_gstr;
277 MFLTFontForRealized font;
279 int from_pos = MGLYPH (from)->g.from;
283 flt = mflt_get (layouter);
284 flt_gstr.glyph_size = sizeof (MGlyph);
285 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
286 flt_gstr.used = gstring->used;
287 flt_gstr.allocated = gstring->size;
289 font.font.family = mfont_get_prop (rfont->font, Mfamily);
290 font.font.x_ppem = rfont->x_ppem;
291 font.font.y_ppem = rfont->y_ppem;
292 font.font.get_glyph_id = mfont__get_glyph_id;
293 font.font.get_metrics = mfont__get_metrics;
294 font.font.check_otf = rfont->driver->check_otf;
295 font.font.drive_otf = rfont->driver->drive_otf;
296 font.font.internal = NULL;
298 mflt_font_id = font_id;
299 mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature;
300 for (i = 0; i < 3; i++)
302 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
305 APPEND_GLYPH (gstring, *MGLYPH (0));
306 APPEND_GLYPH (gstring, *MGLYPH (0));
309 if (from + len != to)
310 gstring->used += to - (from + len);
311 for (i = from; i < to; i++)
313 MGlyph *g = MGLYPH (i);
315 g->g.from += from_pos - from;
316 g->g.to += from_pos - from + 1;
330 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
331 displaying them on FRAME.
333 This function fills these members:
334 pos, to, c, code, rface, bidi_level, categories, type, combining_code
335 The other members are filled by layout_glyph_string. */
338 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
339 MGlyphString *gstring)
341 MRealizedFace *default_rface = frame->rface;
342 int stop, face_change, language_change, charset_change, font_change;
343 MGlyph g_tmp, *g, *last_g;
345 MSymbol language = Mnil, script = Mnil, charset = Mnil;
346 MSymbol non_latin_script = Mnil;
347 MRealizedFace *rface = default_rface;
348 MRealizedFont *rfont;
349 int size = gstring->control.fixed_width;
350 int max_bidi_level = 0;
353 MLIST_RESET (gstring);
354 gstring->from = from;
356 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
357 <category> and <rface> members.*/
360 /** Put anchor glyphs at the head and tail. */
361 g_tmp.type = GLYPH_ANCHOR;
362 g_tmp.g.from = g_tmp.g.to = from;
363 APPEND_GLYPH (gstring, g_tmp);
364 stop = face_change = font_change = pos = from;
374 if (pos < mtext_nchars (mt))
376 MFont *font = rface->font;
380 if (pos == font_change)
382 font = mtext_get_prop (mt, pos, Mfont);
383 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
384 if (font_change == mtext_nchars (mt))
387 if (pos == face_change)
389 num = mtext_get_prop_values (mt, pos, Mface,
390 (void **) faces, 64);
391 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
392 if (face_change == mtext_nchars (mt))
397 faces[0] = &rface->face;
400 rface = mface__realize (frame, faces, num, size, font);
403 rface = default_rface;
405 if (stop > font_change)
407 if (stop > face_change)
411 if (pos < mtext_nchars (mt))
412 c = mtext_ref_char (mt, pos);
416 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
418 g_tmp.g.from = pos++;
421 category = mchar_get_prop (c, Mcategory);
422 if (category == McatCf)
423 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
424 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
425 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
427 g_tmp.category = GLYPH_CATEGORY_NORMAL;
429 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
433 ctrl[0] = ctrl[1] = g_tmp;
435 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
436 APPEND_GLYPH (gstring, ctrl[0]);
437 APPEND_GLYPH (gstring, ctrl[1]);
440 APPEND_GLYPH (gstring, g_tmp);
441 if (c == '\n' && gstring->control.two_dimensional)
444 /* Append an anchor glyph. */
446 g_tmp.type = GLYPH_ANCHOR;
447 g_tmp.g.from = g_tmp.g.to = pos;
448 APPEND_GLYPH (gstring, g_tmp);
451 if (gstring->control.enable_bidi)
452 max_bidi_level = analyse_bidi_level (gstring);
454 /* The next loop is to change each <rface> member for non-ASCII
455 characters if necessary. */
456 stop = charset_change = language_change = from;
457 rfont = default_rface->rfont;
458 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
464 /* Short cut for the obvious case. */
465 this_script = Mlatin;
468 this_script = (MSymbol) mchar_get_prop (c, Mscript);
469 if (this_script == Minherited || this_script == Mcommon)
473 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
475 if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z')
476 this_script = script;
479 if (this_script == Mcommon && non_latin_script)
480 this_script = non_latin_script;
481 if (this_script == Mcommon)
483 /* Search forward for a character that explicitly
484 specifies a non-latin script. */
488 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
490 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
491 && sym != Minherited)
500 if (pos == stop || script != this_script || g->rface->rfont != rfont)
503 last_g = mface__for_chars (script, language, charset,
505 script = this_script;
506 if (script != Mnil && script != Mlatin)
507 non_latin_script = script;
508 rfont = g->rface->ascii_rface->rfont;
511 if (pos < mtext_nchars (mt) && pos == language_change)
513 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
514 mtext_prop_range (mt, Mlanguage, pos, NULL,
515 &language_change, 0);
517 if (pos < mtext_nchars (mt) && pos == charset_change)
519 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
520 mtext_prop_range (mt, Mcharset, pos, NULL,
524 if (stop > language_change)
525 stop = language_change;
526 if (stop > charset_change)
527 stop = charset_change;
532 last_g = mface__for_chars (script, language, charset, last_g, g, size);
534 /* The next loop is to run FLT or perform the default combining if
536 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
540 if (this->type == GLYPH_CHAR && this->rface->rfont)
544 if (this->rface->layouter != Mnil)
546 MGlyph *prev = MGLYPH (start - 1);
548 while (prev->type == GLYPH_CHAR
549 && prev->category == GLYPH_CATEGORY_FORMATTER
550 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
552 != MCHAR_INVALID_CODE))
554 prev->rface->rfont = this->rface->rfont;
559 (g->type == GLYPH_CHAR
560 && g->g.from != gstring->control.cursor_pos
561 && g->rface->layouter == this->rface->layouter
562 && (g->rface->rfont == this->rface->rfont
563 || (g->category == GLYPH_CATEGORY_FORMATTER
564 && (mfont__encode_char (NULL,
565 (MFont *) this->rface->rfont,
567 != MCHAR_INVALID_CODE))));
569 g->rface->rfont = this->rface->rfont;
570 i = run_flt (gstring, start, i, this->rface);
575 while (g->type == GLYPH_CHAR
577 && g->category == GLYPH_CATEGORY_MODIFIER
579 && g->rface->layouter == Mnil)
583 this->rface->layouter = Mcombining;
584 run_flt (gstring, start, i, this->rface);
587 mfont__get_metric (gstring, start, i);
595 /* At last, reorder glyphs visually if necessary. */
596 if (max_bidi_level > 0)
597 visual_order (gstring);
601 int width, lbearing, rbearing;
605 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
606 MSubTextExtents *extents)
608 int g_physical_ascent, g_physical_descent;
609 MGlyph *g = MGLYPH (from);
610 MGlyph *last_g = MGLYPH (to);
612 g_physical_ascent = gstring->physical_ascent;
613 g_physical_descent = gstring->physical_descent;
614 extents->width = extents->lbearing = extents->rbearing = 0;
616 for (g = MGLYPH (from); g < last_g; g++)
618 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
619 g_physical_descent = MAX (g_physical_descent, g->g.descent);
620 extents->lbearing = MIN (extents->lbearing,
621 extents->width + g->g.lbearing);
622 extents->rbearing = MAX (extents->rbearing,
623 extents->width + g->g.rbearing);
624 extents->width += g->g.xadv;
627 gstring->physical_ascent = g_physical_ascent;
628 gstring->physical_descent = g_physical_descent;
632 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
633 by this function directly. Character glyphs are handled by
634 layouter functions registered in font drivers.
636 This function fill-in all the remaining members of glyphs. */
639 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
641 /* Default width of TAB. */
642 int tab_width = frame->space_width * (gstring->control.tab_width
643 ? gstring->control.tab_width : 8);
647 MDrawControl *control = &(gstring->control);
650 int box_line_height = 0;
651 int ignore_formatting_char = control->ignore_formatting_char;
653 gstring->ascent = gstring->descent = 0;
654 gstring->physical_ascent = gstring->physical_descent = 0;
655 gstring->width = gstring->lbearing = gstring->rbearing = 0;
659 while (g->type != GLYPH_ANCHOR)
661 if (box != g->rface->box)
663 int gidx = GLYPH_INDEX (g);
667 /* Insert the right side of the box. That glyph belongs
668 to the previous grapheme cluster. */
669 MGlyph box_glyph = g[-1];
671 box_glyph.type = GLYPH_BOX;
673 = (control->fixed_width
675 : box->inner_hmargin + box->width + box->outer_hmargin);
676 box_glyph.g.lbearing = 0;
677 box_glyph.g.rbearing = box_glyph.g.xadv;
678 box_glyph.g.xoff = 0;
679 box_glyph.right_padding = 1;
680 gstring->width += box_glyph.g.xadv;
681 gstring->rbearing += box_glyph.g.xadv;
682 INSERT_GLYPH (gstring, gidx, box_glyph);
689 /* Insert the left side of the box. That glyph belongs
690 to the following grapheme cluster. */
691 MGlyph box_glyph = *g;
692 int box_height = (box->width
693 + box->inner_vmargin + box->outer_vmargin);
695 if (box_line_height < box_height)
696 box_line_height = box_height;
697 box_glyph.type = GLYPH_BOX;
699 = (control->fixed_width
701 : box->inner_hmargin + box->width + box->outer_hmargin);
702 box_glyph.g.lbearing = 0;
703 box_glyph.g.rbearing = box_glyph.g.xadv;
704 box_glyph.g.xoff = 0;
705 box_glyph.left_padding = 1;
706 gstring->width += box_glyph.g.xadv;
707 gstring->rbearing += box_glyph.g.xadv;
708 INSERT_GLYPH (gstring, gidx, box_glyph);
714 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
715 g->type = GLYPH_SPACE;
717 if (g->type == GLYPH_CHAR)
719 MRealizedFace *rface = g->rface;
720 MRealizedFont *rfont = rface->rfont;
722 int from = GLYPH_INDEX (g);
724 for (g++; g->type == GLYPH_CHAR; g++)
725 if (! rfont != ! g->rface->rfont
726 || box != g->rface->box
727 || ((fromg->g.code == MCHAR_INVALID_CODE)
728 != (g->g.code == MCHAR_INVALID_CODE))
729 || (g->category == GLYPH_CATEGORY_FORMATTER
730 && ignore_formatting_char))
732 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
735 int to = GLYPH_INDEX (g);
736 MSubTextExtents extents;
738 layout_glyphs (frame, gstring, from, to, &extents);
739 extra_width = - extents.lbearing;
741 && ! control->disable_overlapping_adjustment
742 && (! control->orientation_reversed
743 ? ((to > 1 || control->align_head)
744 && g->type != GLYPH_ANCHOR)
745 : (((g->type && GLYPH_ANCHOR) || control->align_head)
750 pad.type = GLYPH_PAD;
753 pad.g.xadv = pad.g.rbearing = extra_width;
754 pad.left_padding = 1;
755 INSERT_GLYPH (gstring, from, pad);
757 extents.lbearing = 0;
758 extents.width += extra_width;
759 extents.rbearing += extra_width;
761 g = MGLYPH (from - 1);
762 if (g->type == GLYPH_SPACE)
764 /* The pad just inserted is absorbed (maybe
765 partially) by the previous space while
766 keeping at least some space width. For the
767 moment, we use the arbitrary width 2-pixel.
768 Perhaps, it should be decided by the current
769 face, or a default value of the current
770 frame, which is, however, not yet
772 if (extra_width + 2 < g->g.xadv)
774 g->g.xadv -= extra_width;
778 extra_width = g->g.xadv - 2;
781 gstring->width -= extra_width;
782 gstring->rbearing -= extra_width;
787 extra_width = extents.rbearing - extents.width;
789 && ! control->disable_overlapping_adjustment
790 && (GLYPH_INDEX (g) < gstring->used - 1
791 || (control->orientation_reversed && control->align_head)))
793 if (g->type == GLYPH_SPACE && box == g->rface->box)
796 pad.type = GLYPH_PAD;
799 pad.g.xadv = pad.g.rbearing = extra_width;
800 INSERT_GLYPH (gstring, to, pad);
805 g[-1].g.xadv += extra_width;
806 extents.width += extra_width;
809 if (gstring->lbearing > gstring->width + extents.lbearing)
810 gstring->lbearing = gstring->width + extents.lbearing;
811 if (gstring->rbearing < gstring->width + extents.rbearing)
812 gstring->rbearing = gstring->width + extents.rbearing;
813 gstring->width += extents.width;
814 if (gstring->ascent < rface->ascent)
815 gstring->ascent = rface->ascent;
816 if (gstring->descent < rface->descent)
817 gstring->descent = rface->descent;
821 for (; fromg < g; fromg++)
823 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
824 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
825 fromg->g.xadv = fromg->g.rbearing = 1;
827 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
828 fromg->g.xoff = fromg->g.lbearing = 0;
829 fromg->g.ascent = fromg->g.descent = 0;
830 gstring->width += fromg->g.xadv;
831 gstring->rbearing += fromg->g.xadv;
833 if (gstring->ascent < frame->rface->ascent)
834 gstring->ascent = frame->rface->ascent;
835 if (gstring->descent < frame->descent)
836 gstring->descent = frame->rface->descent;
839 else if (g->type == GLYPH_SPACE)
842 g->g.xadv = g->rface->space_width;
843 else if (g->g.c == '\n')
845 g->g.xadv = control->cursor_width;
848 if (control->cursor_bidi)
850 else if (g->g.xadv < 0)
851 g->g.xadv = g->rface->space_width;
854 else if (g->g.c == '\t')
856 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
862 if (g[-1].type == GLYPH_PAD)
864 /* This space glyph absorbs (maybe partially) the
865 previous padding glyph. */
866 g->g.xadv -= g[-1].g.xadv;
868 /* But, keep at least some space width. For the
869 moment, we use the arbitrary width 2-pixel. */
872 g->g.rbearing = g->g.xadv;
873 gstring->width += g->g.xadv;
874 gstring->rbearing += g->g.xadv;
877 if (gstring->ascent < g->rface->ascent)
878 gstring->ascent = g->rface->ascent;
879 if (gstring->descent < g->rface->descent)
880 gstring->descent = g->rface->descent;
886 gstring->width += g->g.xadv;
887 gstring->rbearing += g->g.xadv;
894 /* Insert the right side of the box. */
895 int gidx = GLYPH_INDEX (g);
896 MGlyph box_glyph = g[-1];
898 box_glyph.type = GLYPH_BOX;
900 = (control->fixed_width
902 : box->inner_hmargin + box->width + box->outer_hmargin);
903 box_glyph.g.lbearing = 0;
904 box_glyph.g.rbearing = box_glyph.g.xadv;
905 box_glyph.g.xoff = 0;
906 box_glyph.right_padding = 1;
907 gstring->width += box_glyph.g.xadv;
908 gstring->rbearing += box_glyph.g.xadv;
909 INSERT_GLYPH (gstring, gidx, box_glyph);
912 gstring->text_ascent = gstring->ascent;
913 gstring->text_descent = gstring->descent;
914 if (gstring->text_ascent < gstring->physical_ascent)
915 gstring->text_ascent = gstring->physical_ascent;
916 if (gstring->text_descent < gstring->physical_descent)
917 gstring->text_descent = gstring->physical_descent;
918 gstring->line_ascent = gstring->text_ascent;
919 gstring->line_descent = gstring->text_descent;
920 if (box_line_height > 0)
922 gstring->line_ascent += box_line_height;
923 gstring->physical_ascent = gstring->line_ascent;
924 gstring->line_descent += box_line_height;
925 gstring->physical_descent = gstring->line_descent;
928 if (gstring->line_ascent < control->min_line_ascent)
929 gstring->line_ascent = control->min_line_ascent;
930 else if (control->max_line_ascent
931 && control->max_line_ascent > control->min_line_ascent
932 && gstring->line_ascent > control->max_line_ascent)
933 gstring->line_ascent = control->max_line_ascent;
935 if (gstring->line_descent < control->min_line_descent)
936 gstring->line_descent = control->min_line_descent;
937 else if (control->max_line_descent
938 && control->max_line_descent > control->min_line_descent
939 && gstring->line_descent > control->max_line_descent)
940 gstring->line_descent = control->max_line_descent;
941 gstring->height = gstring->line_ascent + gstring->line_descent;
943 if (control->orientation_reversed
946 /* We must adjust TAB width for RTL orientation. */
947 width = gstring->indent;
949 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
951 if (g->type == GLYPH_CHAR && g->g.c == '\t')
953 int this_width = tab_width - (width % tab_width);
955 if (g[1].type == GLYPH_PAD)
956 this_width -= g[1].g.xadv;
957 if (g[-1].type == GLYPH_PAD)
958 this_width -= g[-1].g.xadv;
961 gstring->width += this_width - g->g.xadv;
962 gstring->rbearing += this_width - g->g.xadv;
963 g->g.xadv = this_width;
974 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
975 MGlyphString *gstring, int from, int to,
976 int *from_idx, int *to_idx, int *to_x)
978 MGlyph *g = MGLYPH (1);
979 MDrawRegion region = (MDrawRegion) NULL;
980 MDrawControl *control = &gstring->control;
983 int cursor_bidi = control->cursor_bidi;
985 if (control->with_cursor && control->cursor_width)
987 if (gstring->from <= control->cursor_pos
988 && gstring->to > control->cursor_pos)
989 cursor_pos = control->cursor_pos;
992 && gstring->from <= control->cursor_pos - 1
993 && gstring->to > control->cursor_pos - 1)
994 prev_pos = control->cursor_pos - 1;
997 *from_idx = *to_idx = 0;
999 while (g->type != GLYPH_ANCHOR)
1001 if (g->g.from >= from && g->g.from < to)
1003 MGlyph *fromg = g, *cursor = NULL;
1004 MRealizedFace *rface = g->rface;
1006 int cursor_width = 0;
1010 *from_idx = GLYPH_INDEX (g);
1011 while (g->g.from >= from && g->g.from < to
1012 && g->rface == rface)
1015 if (g->type != GLYPH_BOX
1016 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1019 cursor = g, cursor_x = x + width;
1020 cursor_width += g->g.xadv;
1022 width += g++->g.xadv;
1025 && (control->as_image
1026 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1028 int this_x = x, this_width = width;
1030 if (fromg->type == GLYPH_BOX)
1031 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1032 if (g[-1].type == GLYPH_BOX)
1033 this_width -= g[-1].g.xadv;
1034 (frame->driver->fill_space)
1035 (frame, win, rface, 0,
1036 this_x, y - gstring->text_ascent, this_width,
1037 gstring->text_ascent + gstring->text_descent,
1038 control->clip_region);
1045 rect.y = y - gstring->text_ascent;
1046 rect.height = gstring->text_ascent + gstring->text_descent;
1049 rect.width = ((control->cursor_width > 0
1050 && control->cursor_width < cursor_width)
1051 ? control->cursor_width : cursor_width);
1055 if (cursor->bidi_level % 2)
1056 rect.x += cursor_width - rect.width;
1057 (*frame->driver->fill_space)
1058 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1059 control->clip_region);
1061 region = (*frame->driver->region_from_rect) (&rect);
1063 (*frame->driver->region_add_rect) (region, &rect);
1066 if (cursor->bidi_level % 2)
1069 rect.width = cursor_width < 4 ? cursor_width : 4;
1070 (*frame->driver->fill_space)
1071 (frame, win, rface, 1,
1072 rect.x, rect.y, rect.width, rect.height,
1073 control->clip_region);
1074 (*frame->driver->region_add_rect) (region, &rect);
1086 if (fromg->type != GLYPH_BOX
1087 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1090 cursor = fromg, cursor_x = x + temp_width;
1091 cursor_width += fromg->g.xadv;
1093 temp_width += fromg++->g.xadv;
1100 if (! (cursor->bidi_level % 2))
1101 rect.x += cursor_width - 1;
1102 rect.y = y - gstring->text_ascent;
1103 rect.height = gstring->text_ascent + gstring->text_descent;
1105 (*frame->driver->fill_space)
1106 (frame, win, rface, 1,
1107 rect.x, rect.y, rect.width, rect.height,
1108 control->clip_region);
1110 region = (*frame->driver->region_from_rect) (&rect);
1112 (*frame->driver->region_add_rect) (region, &rect);
1113 rect.y += rect.height - 2;
1115 rect.width = cursor_width < 4 ? cursor_width : 4;
1116 if (! (cursor->bidi_level % 2))
1117 rect.x -= rect.width - 1;
1118 (*frame->driver->fill_space) (frame, win, rface, 1,
1119 rect.x, rect.y, rect.width, rect.height,
1120 control->clip_region);
1121 (*frame->driver->region_add_rect) (region, &rect);
1125 *to_idx = GLYPH_INDEX (g);
1135 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1136 MGlyphString *gstring, int from_idx, int to_idx,
1137 int reverse, MDrawRegion region)
1139 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1145 (*frame->driver->region_to_rect) (region, &rect);
1148 while (g != gend && x + g->g.rbearing <= rect.x)
1151 width -= g++->g.xadv;
1152 while (! g->enabled && g != gend)
1156 rect.x += rect.width;
1157 if (rect.x < x + width)
1160 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1162 width -= (--gend)->g.xadv;
1163 while (! gend->enabled && g != gend)
1167 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1176 MRealizedFace *rface = g->rface;
1177 int width = g->g.xadv;
1178 MGlyph *from_g = g++;
1180 /* Handle the glyphs of the same type/face at once. */
1182 && g->type == from_g->type
1183 && g->rface == rface
1184 && ((g->g.code == MCHAR_INVALID_CODE)
1185 == (from_g->g.code == MCHAR_INVALID_CODE))
1187 width += g++->g.xadv;
1189 if (from_g->type == GLYPH_CHAR)
1191 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1192 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1195 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1198 else if (from_g->type == GLYPH_BOX)
1200 /* Draw the left or right side of a box. If
1201 from_g->lbearing is nonzero, this is the left side,
1202 else this is the right side. */
1203 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1206 if (from_g->type != GLYPH_BOX)
1209 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1210 x, y, width, region);
1213 /* Draw the top and bottom side of a box. */
1214 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1215 x, y, width, region);
1226 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1227 int *from_x, int *to_x)
1230 int left_idx = *left, right_idx = *right;
1231 int left_x, right_x, x;
1233 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1236 if (x + g->g.rbearing > 0)
1238 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1240 left_idx = GLYPH_INDEX (g);
1245 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1248 if (x - g->g.xadv + g->g.lbearing < 0)
1250 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1252 right_idx = GLYPH_INDEX (g) + 1;
1257 if (*left == left_idx && *right == right_idx)
1260 if (*left != left_idx)
1262 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1267 if (*right != right_idx)
1269 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1279 gstring_width (MGlyphString *gstring, int from, int to,
1280 int *lbearing, int *rbearing)
1285 if (from <= gstring->from && to >= gstring->to)
1288 *lbearing = gstring->lbearing;
1290 *rbearing = gstring->rbearing;
1291 return gstring->width;
1298 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1299 if (g->g.from >= from && g->g.from < to)
1301 if (lbearing && width + g->g.lbearing < *lbearing)
1302 *lbearing = width + g->g.lbearing;
1303 if (rbearing && width + g->g.rbearing > *rbearing)
1304 *rbearing = width + g->g.rbearing;
1312 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1313 MGlyphString *gstring, int from, int to)
1315 MDrawControl *control = &gstring->control;
1317 MDrawRegion clip_region, cursor_region;
1318 int from_idx, to_idx;
1323 if (control->orientation_reversed)
1324 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1326 x += gstring->indent;
1328 /* At first, draw all glyphs without cursor. */
1329 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1330 &from_idx, &to_idx, &to_x);
1332 if (control->partial_update)
1335 rect.width = to_x - x;
1336 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1338 rect.y = y - gstring->line_ascent;
1339 rect.height = gstring->height;
1340 clip_region = (*frame->driver->region_from_rect) (&rect);
1341 if (control->clip_region)
1342 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1345 clip_region = control->clip_region;
1348 clip_region = control->clip_region;
1350 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1355 (*frame->driver->intersect_region) (cursor_region, clip_region);
1356 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1359 if (clip_region != control->clip_region)
1360 (*frame->driver->free_region) (clip_region);
1362 (*frame->driver->free_region) (cursor_region);
1366 static int gstring_num;
1369 free_gstring (void *object)
1371 MGlyphString *gstring = (MGlyphString *) object;
1374 free_gstring (gstring->next);
1375 if (gstring->size > 0)
1376 free (gstring->glyphs);
1382 static MGlyphString scratch_gstring;
1384 static MGlyphString *
1385 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1388 MGlyphString *gstring;
1390 if (pos == mt->nchars)
1394 gstring = &scratch_gstring;
1395 if (gstring->size == 0)
1400 g_tmp.type = GLYPH_ANCHOR;
1401 APPEND_GLYPH (gstring, g_tmp);
1402 APPEND_GLYPH (gstring, g_tmp);
1403 APPEND_GLYPH (gstring, g_tmp);
1404 gstring->glyphs[1].type = GLYPH_SPACE;
1405 gstring->glyphs[1].g.c = '\n';
1406 gstring->glyphs[1].g.code = '\n';
1408 gstring->from = pos;
1410 g->rface = frame->rface;
1411 g->g.from = g->g.to = pos;
1413 g->rface = frame->rface;
1414 g->g.from = pos++, g->g.to = pos;
1416 g->rface = frame->rface;
1417 g->g.from = g->g.to = pos;
1422 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1423 MLIST_INIT1 (gstring, glyphs, 128);
1427 gstring->frame = frame;
1428 gstring->tick = frame->tick;
1429 gstring->top = gstring;
1430 gstring->control = *control;
1431 gstring->indent = gstring->width_limit = 0;
1432 if (control->format)
1433 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1435 gstring->width_limit = control->max_line_width;
1436 gstring->anti_alias = control->anti_alias;
1440 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1443 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1446 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1454 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1455 a width of glyphs for the character at I of MT. If I is not a
1456 beginning of a grapheme cluster, the corresponding element is
1458 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1459 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1460 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1461 pos_width[g->g.from - gstring->from] += g->g.xadv;
1462 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1464 if (pos_width[i] > 0)
1466 if (width + pos_width[i] > gstring->width_limit)
1469 width += pos_width[i];
1472 pos = gstring->from + i;
1473 if (gstring->control.line_break)
1475 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1476 gstring->from, gstring->from + i,
1478 if (pos <= gstring->from)
1480 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1483 else if (pos >= gstring->to)
1488 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1491 if (pos < gstring->to)
1493 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1494 layout_glyph_string (frame, gstring);
1499 /* Return a gstring that covers a character at POS. */
1501 static MGlyphString *
1502 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1504 MGlyphString *gstring = NULL;
1506 if (pos < mtext_nchars (mt))
1508 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1511 && ((prop->start != 0
1512 && mtext_ref_char (mt, prop->start - 1) != '\n')
1513 || (prop->end < mtext_nchars (mt)
1514 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1516 mtext_detach_property (prop);
1521 gstring = prop->val;
1522 if (gstring->frame != frame
1523 || gstring->tick != frame->tick
1524 || memcmp (control, &gstring->control,
1525 (char *) (&control->with_cursor)
1526 - (char *) (control))
1527 || control->cursor_pos != gstring->control.cursor_pos
1528 || control->cursor_width != gstring->control.cursor_width
1529 || control->cursor_bidi != gstring->control.cursor_bidi)
1531 mtext_detach_property (prop);
1536 else if (! control->cursor_width)
1544 offset = mtext_character (mt, pos, 0, '\n');
1549 offset -= gstring->from;
1551 for (gst = gstring; gst; gst = gst->next)
1555 gst->from += offset;
1557 for (i = 0; i < gst->used; i++)
1559 gst->glyphs[i].g.from += offset;
1560 gst->glyphs[i].g.to += offset;
1563 M17N_OBJECT_REF (gstring);
1568 int line = 0, y = 0;
1570 if (pos < mtext_nchars (mt))
1572 beg = mtext_character (mt, pos, 0, '\n');
1580 end = mtext_nchars (mt) + (control->cursor_width != 0);
1581 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1582 if (beg < mtext_nchars (mt))
1583 compose_glyph_string (frame, mt, beg, end, gstring);
1584 layout_glyph_string (frame, gstring);
1586 if (gstring->width_limit
1587 && gstring->width > gstring->width_limit)
1589 MGlyphString *gst = gstring;
1591 truncate_gstring (frame, mt, gst);
1592 while (gst->to < end)
1594 line++, y += gst->height;
1595 gst->next = alloc_gstring (frame, mt, gst->from, control,
1597 gst->next->top = gstring;
1598 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1600 layout_glyph_string (frame, gst);
1601 if (gst->width <= gst->width_limit)
1603 truncate_gstring (frame, mt, gst);
1607 if (! control->disable_caching && pos < mtext_nchars (mt))
1609 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1610 MTEXTPROP_VOLATILE_STRONG);
1612 if (end > mtext_nchars (mt))
1613 end = mtext_nchars (mt);
1614 mtext_attach_property (mt, beg, end, prop);
1615 M17N_OBJECT_UNREF (prop);
1619 while (gstring->to <= pos)
1621 if (! gstring->next)
1623 gstring = gstring->next;
1625 gstring->control = *control;
1631 static MDrawControl control_noop;
1633 #define ASSURE_CONTROL(control) \
1635 control = &control_noop; \
1640 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1641 MText *mt, int from, int to,
1642 MDrawControl *control)
1644 MGlyphString *gstring;
1646 M_CHECK_POS_X (mt, from, -1);
1647 ASSURE_CONTROL (control);
1648 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1649 to = mtext_nchars (mt) + (control->cursor_width != 0);
1653 gstring = get_gstring (frame, mt, from, to, control);
1655 MERROR (MERROR_DRAW, -1);
1656 render_glyph_string (frame, win, x, y, gstring, from, to);
1660 y += gstring->line_descent;
1661 M17N_OBJECT_UNREF (gstring->top);
1662 gstring = get_gstring (frame, mt, from, to, control);
1663 y += gstring->line_ascent;
1664 render_glyph_string (frame, win, x, y, gstring, from, to);
1667 M17N_OBJECT_UNREF (gstring->top);
1674 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1680 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1681 if (g->g.from <= pos && g->g.to > pos)
1686 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1687 if (g->g.from <= pos && g->g.to > pos)
1694 /* for debugging... */
1698 dump_gstring (MGlyphString *gstring, int indent, int type)
1700 char *prefix = (char *) alloca (indent + 1);
1701 MGlyph *g, *first_g, *last_g;
1703 memset (prefix, 32, indent);
1706 fprintf (stderr, "(glyph-string");
1710 first_g = MGLYPH (0);
1711 last_g = first_g + gstring->used;
1715 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1716 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1719 for (g = first_g; g < last_g; g++)
1722 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1725 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1726 : g->type == GLYPH_ANCHOR ? "ANC"
1727 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1728 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1729 g->g.xadv, g->bidi_level);
1730 if (g->g.xoff || g->g.yoff)
1731 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1732 fprintf (stderr, ")");
1734 fprintf (stderr, ")");
1738 /* m17n-X internal APIs */
1743 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1745 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1746 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1748 Mcommon = msymbol ("common");
1750 McatCc = msymbol ("Cc");
1751 McatCf = msymbol ("Cf");
1753 MbidiR = msymbol ("R");
1754 MbidiAL = msymbol ("AL");
1755 MbidiRLE = msymbol ("RLE");
1756 MbidiRLO = msymbol ("RLO");
1757 MbidiBN = msymbol ("BN");
1758 MbidiS = msymbol ("S");
1759 MbidiNSM = msymbol ("NSM");
1761 #if FRIBIDI_INTERFACE_VERSION < 3
1762 fribidi_set_mirroring (TRUE);
1764 fribidi_set_mirroring (1);
1768 M_break_at_space = msymbol ("bs");
1769 M_break_at_word = msymbol ("bw");
1770 M_break_at_any = msymbol ("ba");
1771 M_kinsoku_bol = msymbol ("kb");
1772 M_kinsoku_eol = msymbol ("ke");
1780 MLIST_FREE1 (&scratch_gstring, glyphs);
1781 M17N_OBJECT_UNREF (linebreak_table);
1782 linebreak_table = NULL;
1786 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1790 /*** @addtogroup m17nDraw */
1795 @brief Draw an M-text on a window.
1797 The mdraw_text () function draws the text between $FROM and $TO of
1798 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1800 The appearance of the text (size, style, color, etc) is specified
1801 by the value of the text property whose key is @c Mface. If the
1802 M-text or a part of the M-text does not have such a text property,
1803 the default face of $FRAME is used.
1805 The font used to draw a character in the M-text is selected from
1806 the value of the fontset property of a face by the following
1811 <li> Search the text properties given to the character for the one
1812 whose key is @c Mcharset; its value should be either a symbol
1813 specifying a charset or #Mnil. If the value is #Mnil,
1814 proceed to the next step.
1816 Otherwise, search the mapping table of the fontset for the
1817 charset. If no entry is found proceed to the next step.
1819 If an entry is found, use one of the fonts in the entry that
1820 has a glyph for the character and that matches best with the
1821 face properties. If no such font exists, proceed to the next
1824 <li> Get the character property "script" of the character. If it is
1825 inherited, get the script property from the previous
1826 characters. If there is no previous character, or none of
1827 them has the script property other than inherited, proceed to
1830 Search the text properties given to the character for the one
1831 whose key is @c Mlanguage; its value should be either a
1832 symbol specifying a language or @c Mnil.
1834 Search the mapping table of the fontset for the combination
1835 of the script and language. If no entry is found, proceed to
1838 If an entry is found, use one of the fonts in the entry that
1839 has a glyph for the character and that matches best with the
1840 face properties. If no such font exists, proceed to the next
1843 <li> Search the fall-back table of the fontset for a font that has
1844 a glyph of the character. If such a font is found, use that
1849 If no font is found by the algorithm above, this function draws an
1850 empty box for the character.
1852 This function draws only the glyph foreground. To specify the
1853 background color, use mdraw_image_text () or
1854 mdraw_text_with_control ().
1856 This function is the counterpart of <tt>XDrawString ()</tt>,
1857 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1858 in the X Window System.
1861 If the operation was successful, mdraw_text () returns 0. If an
1862 error is detected, it returns -1 and assigns an error code to the
1863 external variable #merror_code. */
1865 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1867 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1868 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1870 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1871 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1872 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1873 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1875 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1876 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1880 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1881 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1882 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1883 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1884 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1885 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1887 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1888 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1890 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1891 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1892 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1894 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1895 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1897 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1898 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1900 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1901 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1903 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1904 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1908 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1910 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1911 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1913 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1914 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1917 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1918 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1920 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1927 mdraw_image_text () */
1930 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1931 MText *mt, int from, int to)
1933 MDrawControl control;
1935 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1936 memset (&control, 0, sizeof control);
1937 control.as_image = 0;
1938 return draw_text (frame, win, x, y, mt, from, to, &control);
1945 @brief Draw an M-text on a window as an image.
1947 The mdraw_image_text () function draws the text between $FROM and
1948 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1949 coordinate ($X, $Y).
1951 The way to draw a text is the same as in mdraw_text () except that
1952 this function also draws the background with the color specified
1955 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1956 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1957 functions in the X Window System.
1960 If the operation was successful, mdraw_image_text () returns 0.
1961 If an error is detected, it returns -1 and assigns an error code
1962 to the external variable #merror_code. */
1965 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1967 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1968 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1969 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1971 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1972 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1974 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1975 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1979 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1980 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1982 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1992 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1993 MText *mt, int from, int to)
1995 MDrawControl control;
1997 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1998 memset (&control, 0, sizeof control);
1999 control.as_image = 1;
2000 return draw_text (frame, win, x, y, mt, from, to, &control);
2006 @brief Draw an M-text on a window with fine control.
2008 The mdraw_text_with_control () function draws the text between
2009 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
2010 coordinate ($X, $Y).
2012 The way to draw a text is the same as in mdraw_text () except that
2013 this function also follows what specified in the drawing control
2016 For instance, if \<two_dimensional\> of $CONTROL is nonzero, this
2017 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2018 breaks lines and the following characters are drawn in the next
2019 line. See the documentation of the structure @ MDrawControl for
2023 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2025 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2026 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2029 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2030 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2032 ¤¿¤È¤¨¤Ð $CONTROL ¤Î \<two_dimensional\> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2033 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2034 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2037 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2038 MText *mt, int from, int to, MDrawControl *control)
2040 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2041 return draw_text (frame, win, x, y, mt, from, to, control);
2047 @brief Compute text pixel width.
2049 The mdraw_text_extents () function computes the width of text
2050 between $FROM and $TO of M-text $MT when it is drawn on a window
2051 of frame $FRAME using the mdraw_text_with_control () function with
2052 the drawing control object $CONTROL.
2054 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2055 the bounding box of character ink of the M-text, and stores the
2056 results in the members of the structure pointed to by
2057 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2058 surrounding box, the box is included in the bounding box.
2060 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2061 computes the bounding box that provides minimum spacing to other
2062 graphical features (such as surrounding box) for the M-text, and
2063 stores the results in the members of the structure pointed to by
2064 $OVERALL_LOGICAL_RETURN.
2066 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2067 computes the bounding box that provides minimum spacing to the
2068 other M-text drawn, and stores the results in the members of the
2069 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2070 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2071 min_line_ascent, min_line_descent, max_line_ascent, and
2072 max_line_descent of $CONTROL are all zero.
2075 This function returns the width of the text to be drawn in the
2076 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2077 text is drawn in multiple physical lines, it returns the width of
2078 the widest line. If an error occurs, it returns -1 and assigns an
2079 error code to the external variable #merror_code. */
2083 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2085 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2086 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2087 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2089 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2090 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2091 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2092 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2094 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2095 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2096 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2097 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2099 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2100 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2101 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2102 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2103 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2104 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2107 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2108 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2109 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2111 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2118 mdraw_text_extents (MFrame *frame,
2119 MText *mt, int from, int to, MDrawControl *control,
2120 MDrawMetric *overall_ink_return,
2121 MDrawMetric *overall_logical_return,
2122 MDrawMetric *overall_line_return)
2124 MGlyphString *gstring;
2126 int width, lbearing, rbearing;
2128 ASSURE_CONTROL (control);
2129 M_CHECK_POS_X (mt, from, -1);
2130 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2131 to = mtext_nchars (mt) + (control->cursor_width != 0);
2135 gstring = get_gstring (frame, mt, from, to, control);
2137 MERROR (MERROR_DRAW, -1);
2138 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2139 if (overall_ink_return)
2140 overall_ink_return->y = - gstring->physical_ascent;
2141 if (overall_logical_return)
2142 overall_logical_return->y = - gstring->ascent;
2143 if (overall_line_return)
2144 overall_line_return->y = - gstring->line_ascent;
2146 for (from = gstring->to; from < to; from = gstring->to)
2148 int this_width, this_lbearing, this_rbearing;
2150 y += gstring->line_descent;
2151 M17N_OBJECT_UNREF (gstring->top);
2152 gstring = get_gstring (frame, mt, from, to, control);
2153 this_width = gstring_width (gstring, from, to,
2154 &this_lbearing, &this_rbearing);
2155 y += gstring->line_ascent;
2156 if (width < this_width)
2158 if (rbearing < this_rbearing)
2159 rbearing = this_rbearing;
2160 if (lbearing > this_lbearing)
2161 lbearing = this_lbearing;
2163 if (overall_ink_return)
2165 overall_ink_return->x = lbearing;
2166 overall_ink_return->width = rbearing - lbearing;
2167 overall_ink_return->height
2168 = y + gstring->physical_descent - overall_ink_return->y;
2170 if (overall_logical_return)
2172 overall_logical_return->x = 0;
2173 overall_logical_return->width = width;
2174 overall_logical_return->height
2175 = y + gstring->descent - overall_logical_return->y;
2177 if (overall_line_return)
2179 overall_line_return->x = lbearing;
2180 overall_line_return->width = MAX (width, rbearing - lbearing);
2181 overall_line_return->height
2182 = y + gstring->line_descent - overall_line_return->y;
2185 M17N_OBJECT_UNREF (gstring->top);
2192 @brief Compute the text dimensions of each character of M-text.
2194 The mdraw_text_per_char_extents () function computes the drawn
2195 metric of each character between $FROM and $TO of M-text $MT
2196 assuming that they are drawn on a window of frame $FRAME using the
2197 mdraw_text_with_control () function with the drawing control
2200 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2201 $LOGICAL_ARRAY_RETURN. Each successive element of
2202 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2203 ink and logical metrics of successive characters respectively,
2204 relative to the drawing origin of the M-text. The number of
2205 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2206 been set is returned to $NUM_CHARS_RETURN.
2208 If $ARRAY_SIZE is too small to return all metrics, the function
2209 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2210 Otherwise, it returns zero.
2212 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2213 @c NULL, this function also computes the metrics of the overall
2214 text and stores the results in the members of the structure
2215 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2217 If $CONTROL->two_dimensional is nonzero, this function computes
2218 only the metrics of characters in the first line. */
2220 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2222 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2223 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2224 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2226 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2227 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2228 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2229 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2230 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2232 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2233 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2236 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2237 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2238 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2240 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2243 mdraw_text_per_char_extents (MFrame *frame,
2244 MText *mt, int from, int to,
2245 MDrawControl *control,
2246 MDrawMetric *ink_array_return,
2247 MDrawMetric *logical_array_return,
2249 int *num_chars_return,
2250 MDrawMetric *overall_ink_return,
2251 MDrawMetric *overall_logical_return)
2253 MGlyphString *gstring;
2257 ASSURE_CONTROL (control);
2258 *num_chars_return = to - from;
2259 if (array_size < *num_chars_return)
2260 MERROR (MERROR_DRAW, -1);
2261 if (overall_logical_return)
2262 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2263 if (overall_ink_return)
2264 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2266 M_CHECK_RANGE (mt, from, to, -1, 0);
2267 gstring = get_gstring (frame, mt, from, to, control);
2270 *num_chars_return = 0;
2274 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2275 if (g->g.from >= from && g->g.from < to)
2277 int start = g->g.from;
2279 int width = g->g.xadv;
2280 int lbearing = g->g.lbearing;
2281 int rbearing = g->g.rbearing;
2282 int ascent = g->g.ascent;
2283 int descent = g->g.descent;
2285 int logical_descent;
2287 if (g->rface->rfont)
2289 logical_ascent = g->rface->rfont->ascent;
2290 logical_descent = g->rface->rfont->descent;
2294 logical_ascent = g->rface->ascent;
2295 logical_descent = g->rface->descent;
2297 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2299 if (lbearing < width + g->g.lbearing)
2300 lbearing = width + g->g.lbearing;
2301 if (rbearing < width + g->g.rbearing)
2302 rbearing = width + g->g.rbearing;
2304 if (ascent < g->g.ascent)
2305 ascent = g->g.ascent;
2306 if (descent < g->g.descent)
2307 descent = g->g.descent;
2314 if (ink_array_return)
2316 ink_array_return[start - from].x = x + lbearing;
2317 ink_array_return[start - from].y = - ascent;
2318 ink_array_return[start - from].width = rbearing - lbearing;
2319 ink_array_return[start - from].height = ascent + descent;
2321 if (logical_array_return)
2323 logical_array_return[start - from].x = x;
2324 logical_array_return[start - from].y = - logical_descent;
2325 logical_array_return[start - from].height
2326 = logical_ascent + logical_descent;
2327 logical_array_return[start - from].width = width;
2335 if (overall_ink_return)
2337 overall_ink_return->y = - gstring->line_ascent;
2338 overall_ink_return->x = gstring->lbearing;
2339 overall_ink_return->width = x - gstring->lbearing;
2340 overall_ink_return->height = gstring->height;
2342 if (overall_logical_return)
2344 overall_logical_return->y = - gstring->ascent;
2345 overall_logical_return->x = 0;
2346 overall_logical_return->width = x;
2347 overall_logical_return->height = gstring->ascent + gstring->descent;
2350 M17N_OBJECT_UNREF (gstring->top);
2357 @brief Return the character position nearest to the coordinates.
2359 The mdraw_coordinates_position () function checks which character
2360 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2361 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2362 mdraw_text_with_control () function with the drawing control
2363 object $CONTROL. Here, the character position means the number of
2364 characters that precede the character in question in $MT, that is,
2365 the character position of the first character is 0.
2367 $FRAME is used only to get the default face information.
2370 If the glyph image of a character covers coordinate ($X, $Y),
2371 mdraw_coordinates_position () returns the character position of
2373 If $Y is less than the minimum Y-coordinate of the drawn area, it
2375 If $Y is greater than the maximum Y-coordinate of the drawn area,
2377 If $Y fits in with the drawn area but $X is less than the minimum
2378 X-coordinate, it returns the character position of the first
2379 character drawn on the line $Y.\n\n
2380 If $Y fits in with the drawn area but $X is greater than the
2381 maximum X-coordinate, it returns the character position of the
2382 last character drawn on the line $Y. */
2385 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2387 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2388 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2389 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2390 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2391 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2392 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2394 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2397 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2398 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2399 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2400 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2401 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2402 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2403 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2404 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2407 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2408 int x_offset, int y_offset, MDrawControl *control)
2410 MGlyphString *gstring;
2415 M_CHECK_POS_X (mt, from, -1);
2416 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2417 to = mtext_nchars (mt) + (control->cursor_width != 0);
2423 ASSURE_CONTROL (control);
2424 gstring = get_gstring (frame, mt, from, to, control);
2425 while (y + gstring->line_descent <= y_offset
2426 && gstring->to < to)
2429 y += gstring->line_descent;
2430 M17N_OBJECT_UNREF (gstring->top);
2431 gstring = get_gstring (frame, mt, from, to, control);
2432 y += gstring->line_ascent;
2435 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2436 if (! control->orientation_reversed)
2438 width = gstring->indent;
2439 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2440 if (g->g.from >= from && g->g.from < to)
2443 if (width > x_offset)
2449 width = - gstring->indent;
2450 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2451 if (g->g.from >= from && g->g.from < to)
2454 if (width < x_offset)
2458 if (g->type == GLYPH_ANCHOR
2459 && control->two_dimensional
2460 && g[-1].g.c == '\n')
2463 M17N_OBJECT_UNREF (gstring->top);
2471 @brief Compute information about a glyph.
2473 The mdraw_glyph_info () function computes information about a
2474 glyph that covers a character at position $POS of the M-text $MT
2475 assuming that the text is drawn from the character at $FROM of $MT
2476 on a window of frame $FRAME using the mdraw_text_with_control ()
2477 function with the drawing control object $CONTROL.
2479 The information is stored in the members of $INFO. */
2481 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2483 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2484 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2485 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2486 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2488 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2496 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2497 MDrawControl *control, MDrawGlyphInfo *info)
2499 MGlyphString *gstring;
2503 M_CHECK_RANGE_X (mt, from, pos, -1);
2505 ASSURE_CONTROL (control);
2506 gstring = get_gstring (frame, mt, from, pos + 1, control);
2508 MERROR (MERROR_DRAW, -1);
2509 while (gstring->to <= pos)
2511 y += gstring->line_descent;
2512 M17N_OBJECT_UNREF (gstring->top);
2513 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2514 y += gstring->line_ascent;
2516 info->line_from = gstring->from;
2517 if (info->line_from < from)
2518 info->line_from = from;
2519 info->line_to = gstring->to;
2522 if (! control->orientation_reversed)
2524 info->x = gstring->indent;
2525 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2526 info->x += g->g.xadv;
2530 info->x = - gstring->indent;
2531 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2532 info->x -= g->g.xadv;
2533 while (g[-1].g.to == g->g.to)
2536 info->from = g->g.from;
2538 info->metrics.x = g->g.lbearing;
2539 info->metrics.y = - gstring->line_ascent;
2540 info->metrics.height = gstring->height;
2541 info->metrics.width = - g->g.lbearing + g->g.xadv;
2542 if (g->rface->rfont)
2543 info->font = (MFont *) g->rface->rfont;
2546 /* info->logical_width is calculated later. */
2548 if (info->from > info->line_from)
2550 /* The logically previous glyph is on this line. */
2551 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2553 info->prev_from = g_tmp->g.from;
2555 else if (info->line_from > 0
2556 && gstring->from > 0)
2558 /* The logically previous glyph is on the previous line. */
2559 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2560 gstring->from, control);
2561 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2563 info->prev_from = g_tmp->g.from;
2564 M17N_OBJECT_UNREF (gst->top);
2567 info->prev_from = -1;
2569 if (GLYPH_INDEX (g) > 1)
2570 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2571 else if (! control->orientation_reversed)
2573 if (info->line_from > 0)
2577 int p = gstring->from - 1;
2579 gst = get_gstring (frame, mt, p, gstring->from, control);
2580 g_tmp = gst->glyphs + (gst->used - 2);
2581 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2582 M17N_OBJECT_UNREF (gst->top);
2585 info->left_from = info->left_to = -1;
2589 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2593 int p = gstring->to;
2595 gst = get_gstring (frame, mt, p, p + 1, control);
2596 g_tmp = gst->glyphs + (gst->used - 2);
2597 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2598 M17N_OBJECT_UNREF (gst->top);
2601 info->left_from = info->left_to = -1;
2604 if (info->to < gstring->to)
2606 /* The logically next glyph is on this line. */
2607 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2609 info->next_to = g_tmp->g.to;
2611 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2613 /* The logically next glyph is on the next line. */
2615 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2616 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2618 info->next_to = g_tmp->g.to;
2619 M17N_OBJECT_UNREF (gst->top);
2624 for (info->logical_width = (g++)->g.xadv;
2625 g->g.from == pos && g->type != GLYPH_ANCHOR;
2626 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2627 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2629 if (g->type != GLYPH_ANCHOR)
2630 info->right_from = g->g.from, info->right_to = g->g.to;
2631 else if (! control->orientation_reversed)
2633 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2636 M17N_OBJECT_UNREF (gstring->top);
2637 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2639 info->right_from = g->g.from, info->right_to = g->g.to;
2642 info->right_from = info->right_to = -1;
2646 if (info->line_from > 0)
2648 pos = gstring->from - 1;
2649 M17N_OBJECT_UNREF (gstring->top);
2650 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2652 info->right_from = g->g.from, info->right_to = g->g.to;
2655 info->right_from = info->right_to = -1;
2658 M17N_OBJECT_UNREF (gstring->top);
2665 @brief Compute information about glyph sequence.
2667 The mdraw_glyph_list () function computes information about glyphs
2668 corresponding to the text between $FROM and $TO of M-text $MT when
2669 it is drawn on a window of frame $FRAME using the
2670 mdraw_text_with_control () function with the drawing control
2671 object $CONTROL. $GLYPHS is an array of objects to store the
2672 information, and $ARRAY_SIZE is the array size.
2674 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2675 number of actually filled elements in the place pointed by
2676 $NUM_GLYPHS_RETURN, and returns 0.
2678 Otherwise, it stores the required array size in the place pointed
2679 by $NUM_GLYPHS_RETURN, and returns -1. */
2682 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2684 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2685 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2686 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2687 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2689 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2690 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2693 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2703 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2704 MDrawControl *control, MDrawGlyph *glyphs,
2705 int array_size, int *num_glyphs_return)
2707 MGlyphString *gstring;
2712 ASSURE_CONTROL (control);
2713 *num_glyphs_return = 0;
2714 M_CHECK_RANGE (mt, from, to, -1, 0);
2715 gstring = get_gstring (frame, mt, from, to, control);
2718 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2720 if (g->type == GLYPH_BOX
2721 || g->g.from < from || g->g.from >= to)
2723 if (g->type == GLYPH_PAD)
2725 if (g->left_padding)
2726 pad_width = g->g.xadv;
2730 glyphs[-1].x_advance += g->g.xadv;
2736 glyphs->from = g->g.from;
2737 glyphs->to = g->g.to;
2738 glyphs->glyph_code = g->g.code;
2739 glyphs->x_off = g->g.xoff + pad_width;
2740 glyphs->y_off = g->g.yoff;
2741 glyphs->lbearing = g->g.lbearing;
2742 glyphs->rbearing = g->g.rbearing;
2743 glyphs->ascent = g->g.ascent;
2744 glyphs->descent = g->g.descent;
2745 glyphs->x_advance = g->g.xadv + pad_width;
2746 glyphs->y_advance = 0;
2747 if (g->rface->rfont)
2749 glyphs->font = (MFont *) g->rface->rfont;
2750 #ifdef HAVE_FREETYPE
2752 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2753 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2755 #else /* not HAVE_FREETYPE */
2756 glyphs->font_type = Mx;
2757 #endif /* not HAVE_FREETYPE */
2758 glyphs->fontp = g->rface->rfont->fontp;
2762 glyphs->font = NULL;
2763 glyphs->font_type = Mnil;
2764 glyphs->fontp = NULL;
2771 M17N_OBJECT_UNREF (gstring->top);
2773 *num_glyphs_return = n;
2774 return (n <= array_size ? 0 : -1);
2780 @brief Draw one or more textitems.
2782 The mdraw_text_items () function draws one or more M-texts on
2783 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2784 of the textitems to be drawn and $NITEMS is the number of
2785 textitems in the array. */
2788 @brief textitem ¤òɽ¼¨¤¹¤ë.
2790 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2791 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2792 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2794 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2798 MTextItem, mdraw_text (). */
2801 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2802 MDrawTextItem *items, int nitems)
2804 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2806 while (nitems-- > 0)
2809 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2811 mdraw_text_with_control (frame, win, x, y,
2812 items->mt, 0, mtext_nchars (items->mt),
2814 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2815 items->control, NULL, NULL, NULL);
2818 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2824 @brief Option of line breaking for drawing text.
2826 The variable #mdraw_line_break_option specifies line breaking
2827 options by logical-or of the members of #MTextLineBreakOption. It
2828 controls the line breaking algorithm of the function
2829 mdraw_default_line_break (). */
2831 int mdraw_line_break_option;
2835 @brief Calculate a line breaking position.
2837 The function mdraw_default_line_break () calculates a line
2838 breaking position based on the line number $LINE and the
2839 coordinate $Y, when a line is too long to fit within the width
2840 limit. $POS is the position of the character next to the last one
2841 that fits within the limit. $FROM is the position of the first
2842 character of the line, and $TO is the position of the last
2843 character displayed on the line if there were not width limit.
2844 $LINE and $Y are reset to 0 when a line is broken by a newline
2845 character, and incremented each time when a long line is broken
2846 because of the width limit.
2849 This function returns a character position to break the
2854 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2856 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2857 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2858 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2859 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2860 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2861 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2862 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2865 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2869 mdraw_default_line_break (MText *mt, int pos,
2870 int from, int to, int line, int y)
2874 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2885 @brief Obtain per character dimension information.
2887 The mdraw_per_char_extents () function computes the text dimension
2888 of each character in M-text $MT. The faces given as text
2889 properties in $MT and the default face of frame $FRAME determine
2890 the fonts to draw the text. Each successive element in
2891 $ARRAY_RETURN is set to the drawn metrics of successive
2892 characters, which is relative to the origin of the drawing, and a
2893 rectangle for each character in $MT. The number of elements of
2894 $ARRAY_RETURN must be equal to or greater than the number of
2897 If pointer $OVERALL_RETURN is not @c NULL, this function also
2898 computes the extents of the overall text and stores the results in
2899 the members of the structure pointed to by $OVERALL_RETURN. */
2902 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2904 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2905 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2906 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2907 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2908 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2909 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2910 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2912 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2913 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2914 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2916 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2919 mdraw_per_char_extents (MFrame *frame, MText *mt,
2920 MDrawMetric *array_return,
2921 MDrawMetric *overall_return)
2923 int n = mtext_nchars (mt);
2925 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2926 n, &n, overall_return, NULL);
2930 @brief clear cached information.
2932 The mdraw_clear_cache () function clear cached information
2933 on M-text $MT that was attached by any of the drawing functions.
2934 When the behavior of `format' or `line_break'
2935 member functions of MDrawControl is changed, the cache must be cleared.
2940 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2942 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2943 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2944 ¤¢¤ë¤¤¤Ï `line_break'
2945 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2951 mdraw_clear_cache (MText *mt)
2953 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);