1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 @brief Drawing M-texts on a window.
27 The m17n GUI API provides functions to draw M-texts.
29 The fonts used for drawing are selected automatically based on the
30 fontset and the properties of a face. A face also specifies the
31 appearance of M-texts, i.e. font size, color, underline, etc.
33 The drawing format of M-texts can be controlled in a variety of
34 ways, which provides powerful 2-dimensional layout
39 @brief M-text ¤ò¥¦¥£¥ó¥É¥¦¤ËÉÁ²è¤¹¤ë.
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£
43 ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face
44 ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â
47 M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤¤ë¡£
52 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
53 /*** @addtogroup m17nInternal
60 #include <sys/types.h>
64 #include "m17n-misc.h"
69 #include "internal-gui.h"
70 #include "internal-flt.h"
75 #include <fribidi/fribidi.h>
76 #endif /* HAVE_FRIBIDI */
78 #define MAX(x, y) ((x) > (y) ? (x) : (y))
79 #define MIN(x, y) ((x) < (y) ? (x) : (y))
81 static MSymbol M_glyph_string;
84 static MSymbol Mcommon;
85 /* Special categories */
86 static MSymbol McatCc, McatCf;
88 static MCharTable *linebreak_table;
89 static MSymbol M_break_at_space, M_break_at_word, M_break_at_any;
90 static MSymbol M_kinsoku_bol, M_kinsoku_eol;
93 /* Glyph-string composer. */
95 static MSymbol MbidiR;
96 static MSymbol MbidiAL;
97 static MSymbol MbidiRLE;
98 static MSymbol MbidiRLO;
99 static MSymbol MbidiBN;
100 static MSymbol MbidiS;
101 static MSymbol MbidiNSM;
104 analyse_bidi_level (MGlyphString *gstring)
106 int len = gstring->used - 2;
107 int bidi_sensitive = gstring->control.orientation_reversed;
112 FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
113 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
114 FriBidiLevel *levels;
115 FriBidiStrIndex *indices;
116 #else /* not HAVE_FRIBIDI */
117 int *logical = alloca (sizeof (int) * len);
118 char *levels = alloca (len);
120 memset (levels, 0, sizeof (int) * len);
121 #endif /* not HAVE_FRIBIDI */
123 for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
128 #endif /* not HAVE_FRIBIDI */
131 MSymbol bidi = (MSymbol) mchar_get_prop (g->g.c, Mbidi_category);
133 if (bidi == MbidiR || bidi == MbidiAL
134 || bidi == MbidiRLE || bidi == MbidiRLO)
139 #endif /* not HAVE_FRIBIDI */
142 else if (bidi == MbidiNSM && i > 0 && levels[i - 1])
144 #endif /* not HAVE_FRIBIDI */
149 if (! bidi_sensitive)
153 levels = alloca (sizeof (FriBidiLevel) * (len + 1));
154 indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
156 fribidi_log2vis (logical, len, &base, NULL, NULL, indices, levels);
157 #endif /* not HAVE_FRIBIDI */
159 MGLYPH (0)->bidi_level = 0;
161 for (g = MGLYPH (1), i = 0; i < len; g++, i++)
163 g->bidi_level = levels[i];
164 if (max_level < g->bidi_level)
165 max_level = g->bidi_level;
167 MGLYPH (i)->bidi_level = 0;
172 visual_order (MGlyphString *gstring)
174 MGlyph *glyphs = alloca (sizeof (MGlyph) * gstring->used);
177 memcpy (glyphs, gstring->glyphs, sizeof (MGlyph) * gstring->used);
179 for (i = gidx = 0; i < gstring->used - 1; gidx++)
181 int level = glyphs[i].bidi_level;
183 gstring->glyphs[gidx] = glyphs[i];
184 glyphs[i].rface = NULL;
188 int prev_level = glyphs[i - 1].bidi_level;
190 if (prev_level == level)
192 else if (prev_level > level)
194 for (; glyphs[i - 1].bidi_level > level; i--);
195 if (glyphs[i].bidi_level % 2)
196 for (level = glyphs[i].bidi_level;
197 glyphs[i + 1].bidi_level == level; i++);
200 for (i++; ! glyphs[i].rface; i++);
204 int next_level = glyphs[i + 1].bidi_level;
206 if (next_level == level)
208 else if (next_level > level)
210 for (; glyphs[i + 1].bidi_level > level; i++);
211 if ((glyphs[i].bidi_level % 2) == 0)
212 for (level = glyphs[i].bidi_level;
213 glyphs[i - 1].bidi_level == level; i--);
219 for (i--; glyphs[i].bidi_level >= level; i--);
220 if (! glyphs[i].rface)
221 for (i = save; ! glyphs[i].rface; i++);
225 for (i = 1; i < gstring->used - 1; i++)
227 MGlyph *g = gstring->glyphs + i;
229 for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++);
232 memcpy (glyphs + i, gstring->glyphs + i,
233 sizeof (MGlyph) * (j - i + 1));
235 g[j - i] = glyphs[i];
243 reorder_combining_chars (MGlyphString *gstring, int from, int to)
245 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
251 for (g = gbeg; g != gend; g++)
252 if (COMBINING_CODE_CLASS (g->combining_code) > 0
253 && (COMBINING_CODE_CLASS (g[-1].combining_code)
254 > COMBINING_CODE_CLASS (g->combining_code)))
266 run_flt (MGlyphString *gstring, int from, int to, MRealizedFont *rfont,
269 MFLTGlyphString flt_gstr;
270 MFLTFontForRealized font;
272 int from_pos = MGLYPH (from)->g.from;
276 flt = mflt_get (layouter);
277 flt_gstr.glyph_size = sizeof (MGlyph);
278 flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
279 flt_gstr.used = gstring->used;
280 flt_gstr.allocated = gstring->size;
282 font.font.family = mfont_get_prop (rfont->font, Mfamily);
283 font.font.x_ppem = rfont->x_ppem;
284 font.font.y_ppem = rfont->y_ppem;
285 font.font.get_glyph_id = mfont__get_glyph_id;
286 font.font.get_metrics = mfont__get_metrics;
287 font.font.check_otf = rfont->driver->check_otf;
288 font.font.drive_otf = rfont->driver->drive_otf;
289 font.font.internal = NULL;
291 for (i = 0; i < 3; i++)
293 to = mflt_run (&flt_gstr, from, to, &font.font, flt);
296 APPEND_GLYPH (gstring, *MGLYPH (0));
297 APPEND_GLYPH (gstring, *MGLYPH (0));
300 if (from + len != to)
301 gstring->used += to - (from + len);
302 for (i = from; i < to; i++)
304 MGlyph *g = MGLYPH (i);
306 g->g.from += from_pos - from;
307 g->g.to += from_pos - from + 1;
320 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
321 displaying them on FRAME.
323 This function fills these members:
324 pos, to, c, code, rface, bidi_level, categories, type, combining_code
325 The other members are filled by layout_glyph_string. */
328 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
329 MGlyphString *gstring)
331 MRealizedFace *default_rface = frame->rface;
332 int stop, face_change, language_change, charset_change, font_change;
333 MGlyph g_tmp, *g, *last_g;
335 MSymbol language = Mnil, script = Mnil, charset = Mnil;
336 MSymbol non_latin_script = Mnil;
337 MRealizedFace *rface = default_rface;
338 MRealizedFont *rfont;
339 int size = gstring->control.fixed_width;
340 int max_bidi_level = 0;
343 MLIST_RESET (gstring);
344 gstring->from = from;
346 /* At first generate glyphs with <pos>, <to>, <c>, <type>,
347 <category> and <rface> members.*/
350 /** Put anchor glyphs at the head and tail. */
351 g_tmp.type = GLYPH_ANCHOR;
352 g_tmp.g.from = g_tmp.g.to = from;
353 APPEND_GLYPH (gstring, g_tmp);
354 stop = face_change = font_change = pos = from;
364 if (pos < mtext_nchars (mt))
366 MFont *font = rface->font;
370 if (pos == font_change)
372 font = mtext_get_prop (mt, pos, Mfont);
373 mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0);
374 if (font_change == mtext_nchars (mt))
377 if (pos == face_change)
379 num = mtext_get_prop_values (mt, pos, Mface,
380 (void **) faces, 64);
381 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
382 if (face_change == mtext_nchars (mt))
387 faces[0] = &rface->face;
390 rface = mface__realize (frame, faces, num, size, font);
393 rface = default_rface;
395 if (stop > font_change)
397 if (stop > face_change)
401 if (pos < mtext_nchars (mt))
402 c = mtext_ref_char (mt, pos);
406 = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
408 g_tmp.g.from = pos++;
411 category = mchar_get_prop (c, Mcategory);
412 if (category == McatCf)
413 g_tmp.category = GLYPH_CATEGORY_FORMATTER;
414 else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M')
415 g_tmp.category = GLYPH_CATEGORY_MODIFIER;
417 g_tmp.category = GLYPH_CATEGORY_NORMAL;
419 if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR)
423 ctrl[0] = ctrl[1] = g_tmp;
425 ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
426 APPEND_GLYPH (gstring, ctrl[0]);
427 APPEND_GLYPH (gstring, ctrl[1]);
430 APPEND_GLYPH (gstring, g_tmp);
431 if (c == '\n' && gstring->control.two_dimensional)
434 /* Append an anchor glyph. */
436 g_tmp.type = GLYPH_ANCHOR;
437 g_tmp.g.from = g_tmp.g.to = pos;
438 APPEND_GLYPH (gstring, g_tmp);
441 if (gstring->control.enable_bidi)
442 max_bidi_level = analyse_bidi_level (gstring);
444 /* The next loop is to change each <rface> member for non-ASCII
445 characters if necessary. */
446 stop = charset_change = language_change = from;
447 rfont = default_rface->rfont;
448 for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
454 /* Short cut for the obvious case. */
455 this_script = Mlatin;
458 this_script = (MSymbol) mchar_get_prop (c, Mscript);
459 if (this_script == Minherited || this_script == Mcommon)
463 MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
465 if (MSYMBOL_NAME (category)[0] != 'Z')
466 this_script = script;
469 if (this_script == Mcommon && non_latin_script)
470 this_script = non_latin_script;
471 if (this_script == Mcommon)
473 /* Search forward for a character that explicitly
474 specifies a non-latin script. */
478 for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
480 && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
481 && sym != Minherited)
490 if (pos == stop || script != this_script || g->rface->rfont != rfont)
493 last_g = mface__for_chars (script, language, charset,
495 script = this_script;
496 if (script != Mnil && script != Mlatin)
497 non_latin_script = script;
498 rfont = g->rface->ascii_rface->rfont;
501 if (pos < mtext_nchars (mt) && pos == language_change)
503 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
504 mtext_prop_range (mt, Mlanguage, pos, NULL,
505 &language_change, 0);
507 if (pos < mtext_nchars (mt) && pos == charset_change)
509 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
510 mtext_prop_range (mt, Mcharset, pos, NULL,
514 if (stop > language_change)
515 stop = language_change;
516 if (stop > charset_change)
517 stop = charset_change;
522 last_g = mface__for_chars (script, language, charset, last_g, g, size);
524 /* The next loop is to run FLT or perform the default combining if
526 for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;)
530 if (this->type == GLYPH_CHAR && this->rface->rfont)
534 if (this->rface->layouter != Mnil)
536 MGlyph *prev = MGLYPH (start - 1);
538 while (prev->type == GLYPH_CHAR
539 && prev->category == GLYPH_CATEGORY_FORMATTER
540 && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
542 != MCHAR_INVALID_CODE))
545 prev->rface->rfont = this->rface->rfont;
549 (g->type == GLYPH_CHAR
550 && g->rface->layouter == this->rface->layouter
551 && (g->rface->rfont == this->rface->rfont
552 || (g->category == GLYPH_CATEGORY_FORMATTER
553 && (mfont__encode_char (NULL,
554 (MFont *) this->rface->rfont,
556 != MCHAR_INVALID_CODE))));
558 g->rface->rfont = this->rface->rfont;
559 i = run_flt (gstring, start, i, this->rface->rfont,
560 this->rface->layouter);
565 while (g->type == GLYPH_CHAR
567 && g->category == GLYPH_CATEGORY_MODIFIER
569 && g->rface->layouter == Mnil)
572 run_flt (gstring, start, i, this->rface->rfont, Mcombining);
574 mfont__get_metric (gstring, start, i);
582 /* At last, reorder glyphs visually if necessary. */
583 if (max_bidi_level > 0)
584 visual_order (gstring);
588 int width, lbearing, rbearing;
592 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
593 MSubTextExtents *extents)
595 int g_physical_ascent, g_physical_descent;
596 MGlyph *g = MGLYPH (from);
597 MGlyph *last_g = MGLYPH (to);
599 g_physical_ascent = gstring->physical_ascent;
600 g_physical_descent = gstring->physical_descent;
601 extents->width = extents->lbearing = extents->rbearing = 0;
603 for (g = MGLYPH (from); g < last_g; g++)
605 g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
606 g_physical_descent = MAX (g_physical_descent, g->g.descent);
607 extents->lbearing = MIN (extents->lbearing,
608 extents->width + g->g.lbearing);
609 extents->rbearing = MAX (extents->rbearing,
610 extents->width + g->g.rbearing);
611 extents->width += g->g.xadv;
614 gstring->physical_ascent = g_physical_ascent;
615 gstring->physical_descent = g_physical_descent;
619 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
620 by this function directly. Character glyphs are handled by
621 layouter functions registered in font drivers.
623 This function fill-in all the remaining members of glyphs. */
626 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
628 /* Default width of TAB. */
629 int tab_width = frame->space_width * (gstring->control.tab_width
630 ? gstring->control.tab_width : 8);
634 MDrawControl *control = &(gstring->control);
637 int box_line_height = 0;
638 int ignore_formatting_char = control->ignore_formatting_char;
640 gstring->ascent = gstring->descent = 0;
641 gstring->physical_ascent = gstring->physical_descent = 0;
642 gstring->width = gstring->lbearing = gstring->rbearing = 0;
646 while (g->type != GLYPH_ANCHOR)
648 if (box != g->rface->box)
650 int gidx = GLYPH_INDEX (g);
654 /* Insert the right side of the box. That glyph belongs
655 to the previous grapheme cluster. */
656 MGlyph box_glyph = g[-1];
658 box_glyph.type = GLYPH_BOX;
660 = (control->fixed_width
662 : box->inner_hmargin + box->width + box->outer_hmargin);
663 box_glyph.g.lbearing = 0;
664 box_glyph.g.rbearing = box_glyph.g.xadv;
665 box_glyph.g.xoff = 0;
666 box_glyph.right_padding = 1;
667 gstring->width += box_glyph.g.xadv;
668 gstring->rbearing += box_glyph.g.xadv;
669 INSERT_GLYPH (gstring, gidx, box_glyph);
676 /* Insert the left side of the box. That glyph belongs
677 to the following grapheme cluster. */
678 MGlyph box_glyph = *g;
679 int box_height = (box->width
680 + box->inner_vmargin + box->outer_vmargin);
682 if (box_line_height < box_height)
683 box_line_height = box_height;
684 box_glyph.type = GLYPH_BOX;
686 = (control->fixed_width
688 : box->inner_hmargin + box->width + box->outer_hmargin);
689 box_glyph.g.lbearing = 0;
690 box_glyph.g.rbearing = box_glyph.g.xadv;
691 box_glyph.g.xoff = 0;
692 box_glyph.left_padding = 1;
693 gstring->width += box_glyph.g.xadv;
694 gstring->rbearing += box_glyph.g.xadv;
695 INSERT_GLYPH (gstring, gidx, box_glyph);
701 if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char)
702 g->type = GLYPH_SPACE;
704 if (g->type == GLYPH_CHAR)
706 MRealizedFace *rface = g->rface;
707 MRealizedFont *rfont = rface->rfont;
709 int from = GLYPH_INDEX (g);
711 for (g++; g->type == GLYPH_CHAR; g++)
712 if (! rfont != ! g->rface->rfont
713 || box != g->rface->box
714 || ((fromg->g.code == MCHAR_INVALID_CODE)
715 != (g->g.code == MCHAR_INVALID_CODE))
716 || (g->category == GLYPH_CATEGORY_FORMATTER
717 && ignore_formatting_char))
719 if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
722 int to = GLYPH_INDEX (g);
723 MSubTextExtents extents;
725 layout_glyphs (frame, gstring, from, to, &extents);
726 extra_width = - extents.lbearing;
728 && ! control->disable_overlapping_adjustment
729 && (! control->orientation_reversed
730 ? ((to > 1 || control->align_head)
731 && g->type != GLYPH_ANCHOR)
732 : (((g->type && GLYPH_ANCHOR) || control->align_head)
737 pad.type = GLYPH_PAD;
740 pad.g.xadv = pad.g.rbearing = extra_width;
741 pad.left_padding = 1;
742 INSERT_GLYPH (gstring, from, pad);
744 extents.lbearing = 0;
745 extents.width += extra_width;
746 extents.rbearing += extra_width;
748 g = MGLYPH (from - 1);
749 if (g->type == GLYPH_SPACE)
751 /* The pad just inserted is absorbed (maybe
752 partially) by the previous space while
753 keeping at least some space width. For the
754 moment, we use the arbitrary width 2-pixel.
755 Perhaps, it should be decided by the current
756 face, or a default value of the current
757 frame, which is, however, not yet
759 if (extra_width + 2 < g->g.xadv)
761 g->g.xadv -= extra_width;
765 extra_width = g->g.xadv - 2;
768 gstring->width -= extra_width;
769 gstring->rbearing -= extra_width;
774 extra_width = extents.rbearing - extents.width;
776 && ! control->disable_overlapping_adjustment
777 && (GLYPH_INDEX (g) < gstring->used - 1
778 || (control->orientation_reversed && control->align_head)))
780 if (g->type == GLYPH_SPACE && box == g->rface->box)
783 pad.type = GLYPH_PAD;
786 pad.g.xadv = pad.g.rbearing = extra_width;
787 INSERT_GLYPH (gstring, to, pad);
792 g[-1].g.xadv += extra_width;
793 extents.width += extra_width;
796 if (gstring->lbearing > gstring->width + extents.lbearing)
797 gstring->lbearing = gstring->width + extents.lbearing;
798 if (gstring->rbearing < gstring->width + extents.rbearing)
799 gstring->rbearing = gstring->width + extents.rbearing;
800 gstring->width += extents.width;
801 if (gstring->ascent < rface->ascent)
802 gstring->ascent = rface->ascent;
803 if (gstring->descent < rface->descent)
804 gstring->descent = rface->descent;
808 for (; fromg < g; fromg++)
810 if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
811 || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
812 fromg->g.xadv = fromg->g.rbearing = 1;
814 fromg->g.xadv = fromg->g.rbearing = rface->space_width;
815 fromg->g.xoff = fromg->g.lbearing = 0;
816 fromg->g.ascent = fromg->g.descent = 0;
817 gstring->width += fromg->g.xadv;
818 gstring->rbearing += fromg->g.xadv;
820 if (gstring->ascent < frame->rface->ascent)
821 gstring->ascent = frame->rface->ascent;
822 if (gstring->descent < frame->descent)
823 gstring->descent = frame->rface->descent;
826 else if (g->type == GLYPH_SPACE)
829 g->g.xadv = g->rface->space_width;
830 else if (g->g.c == '\n')
832 g->g.xadv = control->cursor_width;
835 if (control->cursor_bidi)
837 else if (g->g.xadv < 0)
838 g->g.xadv = g->rface->space_width;
841 else if (g->g.c == '\t')
843 g->g.xadv = tab_width - ((gstring->indent + gstring->width)
849 if (g[-1].type == GLYPH_PAD)
851 /* This space glyph absorbs (maybe partially) the
852 previous padding glyph. */
853 g->g.xadv -= g[-1].g.xadv;
855 /* But, keep at least some space width. For the
856 moment, we use the arbitrary width 2-pixel. */
859 g->g.rbearing = g->g.xadv;
860 gstring->width += g->g.xadv;
861 gstring->rbearing += g->g.xadv;
864 if (gstring->ascent < g->rface->ascent)
865 gstring->ascent = g->rface->ascent;
866 if (gstring->descent < g->rface->descent)
867 gstring->descent = g->rface->descent;
873 gstring->width += g->g.xadv;
874 gstring->rbearing += g->g.xadv;
881 /* Insert the right side of the box. */
882 int gidx = GLYPH_INDEX (g);
883 MGlyph box_glyph = g[-1];
885 box_glyph.type = GLYPH_BOX;
887 = (control->fixed_width
889 : box->inner_hmargin + box->width + box->outer_hmargin);
890 box_glyph.g.lbearing = 0;
891 box_glyph.g.rbearing = box_glyph.g.xadv;
892 box_glyph.g.xoff = 0;
893 box_glyph.right_padding = 1;
894 gstring->width += box_glyph.g.xadv;
895 gstring->rbearing += box_glyph.g.xadv;
896 INSERT_GLYPH (gstring, gidx, box_glyph);
899 gstring->text_ascent = gstring->ascent;
900 gstring->text_descent = gstring->descent;
901 if (gstring->text_ascent < gstring->physical_ascent)
902 gstring->text_ascent = gstring->physical_ascent;
903 if (gstring->text_descent < gstring->physical_descent)
904 gstring->text_descent = gstring->physical_descent;
905 gstring->line_ascent = gstring->text_ascent;
906 gstring->line_descent = gstring->text_descent;
907 if (box_line_height > 0)
909 gstring->line_ascent += box_line_height;
910 gstring->physical_ascent = gstring->line_ascent;
911 gstring->line_descent += box_line_height;
912 gstring->physical_descent = gstring->line_descent;
915 if (gstring->line_ascent < control->min_line_ascent)
916 gstring->line_ascent = control->min_line_ascent;
917 else if (control->max_line_ascent
918 && control->max_line_ascent > control->min_line_ascent
919 && gstring->line_ascent > control->max_line_ascent)
920 gstring->line_ascent = control->max_line_ascent;
922 if (gstring->line_descent < control->min_line_descent)
923 gstring->line_descent = control->min_line_descent;
924 else if (control->max_line_descent
925 && control->max_line_descent > control->min_line_descent
926 && gstring->line_descent > control->max_line_descent)
927 gstring->line_descent = control->max_line_descent;
928 gstring->height = gstring->line_ascent + gstring->line_descent;
930 if (control->orientation_reversed
933 /* We must adjust TAB width for RTL orientation. */
934 width = gstring->indent;
936 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
938 if (g->type == GLYPH_CHAR && g->g.c == '\t')
940 int this_width = tab_width - (width % tab_width);
942 if (g[1].type == GLYPH_PAD)
943 this_width -= g[1].g.xadv;
944 if (g[-1].type == GLYPH_PAD)
945 this_width -= g[-1].g.xadv;
948 gstring->width += this_width - g->g.xadv;
949 gstring->rbearing += this_width - g->g.xadv;
950 g->g.xadv = this_width;
961 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
962 MGlyphString *gstring, int from, int to,
963 int *from_idx, int *to_idx, int *to_x)
965 MGlyph *g = MGLYPH (1);
966 MDrawRegion region = (MDrawRegion) NULL;
967 MDrawControl *control = &gstring->control;
970 int cursor_bidi = control->cursor_bidi;
972 if (control->with_cursor && control->cursor_width)
974 if (gstring->from <= control->cursor_pos
975 && gstring->to > control->cursor_pos)
976 cursor_pos = control->cursor_pos;
979 && gstring->from <= control->cursor_pos - 1
980 && gstring->to > control->cursor_pos - 1)
981 prev_pos = control->cursor_pos - 1;
984 *from_idx = *to_idx = 0;
986 while (g->type != GLYPH_ANCHOR)
988 if (g->g.from >= from && g->g.from < to)
990 MGlyph *fromg = g, *cursor = NULL;
991 MRealizedFace *rface = g->rface;
993 int cursor_width = 0;
997 *from_idx = GLYPH_INDEX (g);
998 while (g->g.from >= from && g->g.from < to
999 && g->rface == rface)
1002 if (g->type != GLYPH_BOX
1003 && g->g.from <= cursor_pos && g->g.to > cursor_pos)
1006 cursor = g, cursor_x = x + width;
1007 cursor_width += g->g.xadv;
1009 width += g++->g.xadv;
1012 && (control->as_image
1013 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1015 int this_x = x, this_width = width;
1017 if (fromg->type == GLYPH_BOX)
1018 this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
1019 if (g[-1].type == GLYPH_BOX)
1020 this_width -= g[-1].g.xadv;
1021 (frame->driver->fill_space)
1022 (frame, win, rface, 0,
1023 this_x, y - gstring->text_ascent, this_width,
1024 gstring->text_ascent + gstring->text_descent,
1025 control->clip_region);
1032 rect.y = y - gstring->text_ascent;
1033 rect.height = gstring->text_ascent + gstring->text_descent;
1036 rect.width = ((control->cursor_width > 0
1037 && control->cursor_width < cursor_width)
1038 ? control->cursor_width : cursor_width);
1042 if (cursor->bidi_level % 2)
1043 rect.x += cursor_width - rect.width;
1044 (*frame->driver->fill_space)
1045 (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
1046 control->clip_region);
1048 region = (*frame->driver->region_from_rect) (&rect);
1050 (*frame->driver->region_add_rect) (region, &rect);
1053 if (cursor->bidi_level % 2)
1056 rect.width = cursor_width < 4 ? cursor_width : 4;
1057 (*frame->driver->fill_space)
1058 (frame, win, rface, 1,
1059 rect.x, rect.y, rect.width, rect.height,
1060 control->clip_region);
1061 (*frame->driver->region_add_rect) (region, &rect);
1073 if (fromg->type != GLYPH_BOX
1074 && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
1077 cursor = fromg, cursor_x = x + temp_width;
1078 cursor_width += fromg->g.xadv;
1080 temp_width += fromg++->g.xadv;
1087 if (! (cursor->bidi_level % 2))
1088 rect.x += cursor_width - 1;
1089 rect.y = y - gstring->text_ascent;
1090 rect.height = gstring->text_ascent + gstring->text_descent;
1092 (*frame->driver->fill_space)
1093 (frame, win, rface, 1,
1094 rect.x, rect.y, rect.width, rect.height,
1095 control->clip_region);
1097 region = (*frame->driver->region_from_rect) (&rect);
1099 (*frame->driver->region_add_rect) (region, &rect);
1100 rect.y += rect.height - 2;
1102 rect.width = cursor_width < 4 ? cursor_width : 4;
1103 if (! (cursor->bidi_level % 2))
1104 rect.x -= rect.width - 1;
1105 (*frame->driver->fill_space) (frame, win, rface, 1,
1106 rect.x, rect.y, rect.width, rect.height,
1107 control->clip_region);
1108 (*frame->driver->region_add_rect) (region, &rect);
1112 *to_idx = GLYPH_INDEX (g);
1122 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1123 MGlyphString *gstring, int from_idx, int to_idx,
1124 int reverse, MDrawRegion region)
1126 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1132 (*frame->driver->region_to_rect) (region, &rect);
1135 while (g != gend && x + g->g.rbearing <= rect.x)
1138 width -= g++->g.xadv;
1139 while (! g->enabled && g != gend)
1143 rect.x += rect.width;
1144 if (rect.x < x + width)
1147 && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
1149 width -= (--gend)->g.xadv;
1150 while (! gend->enabled && g != gend)
1154 while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
1163 MRealizedFace *rface = g->rface;
1164 int width = g->g.xadv;
1165 MGlyph *from_g = g++;
1167 /* Handle the glyphs of the same type/face at once. */
1169 && g->type == from_g->type
1170 && g->rface == rface
1171 && ((g->g.code == MCHAR_INVALID_CODE)
1172 == (from_g->g.code == MCHAR_INVALID_CODE))
1174 width += g++->g.xadv;
1176 if (from_g->type == GLYPH_CHAR)
1178 if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
1179 (rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
1182 (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
1185 else if (from_g->type == GLYPH_BOX)
1187 /* Draw the left or right side of a box. If
1188 from_g->lbearing is nonzero, this is the left side,
1189 else this is the right side. */
1190 (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
1193 if (from_g->type != GLYPH_BOX)
1196 (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
1197 x, y, width, region);
1200 /* Draw the top and bottom side of a box. */
1201 (*frame->driver->draw_box) (frame, win, gstring, from_g,
1202 x, y, width, region);
1213 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1214 int *from_x, int *to_x)
1217 int left_idx = *left, right_idx = *right;
1218 int left_x, right_x, x;
1220 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1223 if (x + g->g.rbearing > 0)
1225 while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
1227 left_idx = GLYPH_INDEX (g);
1232 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1235 if (x - g->g.xadv + g->g.lbearing < 0)
1237 while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
1239 right_idx = GLYPH_INDEX (g) + 1;
1244 if (*left == left_idx && *right == right_idx)
1247 if (*left != left_idx)
1249 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1254 if (*right != right_idx)
1256 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1266 gstring_width (MGlyphString *gstring, int from, int to,
1267 int *lbearing, int *rbearing)
1272 if (from <= gstring->from && to >= gstring->to)
1275 *lbearing = gstring->lbearing;
1277 *rbearing = gstring->rbearing;
1278 return gstring->width;
1285 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1286 if (g->g.from >= from && g->g.from < to)
1288 if (lbearing && width + g->g.lbearing < *lbearing)
1289 *lbearing = width + g->g.lbearing;
1290 if (rbearing && width + g->g.rbearing > *rbearing)
1291 *rbearing = width + g->g.rbearing;
1299 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1300 MGlyphString *gstring, int from, int to)
1302 MDrawControl *control = &gstring->control;
1304 MDrawRegion clip_region, cursor_region;
1305 int from_idx, to_idx;
1310 if (control->orientation_reversed)
1311 x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
1313 x += gstring->indent;
1315 /* At first, draw all glyphs without cursor. */
1316 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1317 &from_idx, &to_idx, &to_x);
1319 if (control->partial_update)
1322 rect.width = to_x - x;
1323 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1325 rect.y = y - gstring->line_ascent;
1326 rect.height = gstring->height;
1327 clip_region = (*frame->driver->region_from_rect) (&rect);
1328 if (control->clip_region)
1329 (*frame->driver->intersect_region) (clip_region, control->clip_region);
1332 clip_region = control->clip_region;
1335 clip_region = control->clip_region;
1337 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1342 (*frame->driver->intersect_region) (cursor_region, clip_region);
1343 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1346 if (clip_region != control->clip_region)
1347 (*frame->driver->free_region) (clip_region);
1349 (*frame->driver->free_region) (cursor_region);
1353 static int gstring_num;
1356 free_gstring (void *object)
1358 MGlyphString *gstring = (MGlyphString *) object;
1361 free_gstring (gstring->next);
1362 if (gstring->size > 0)
1363 free (gstring->glyphs);
1369 static MGlyphString scratch_gstring;
1371 static MGlyphString *
1372 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1375 MGlyphString *gstring;
1377 if (pos == mt->nchars)
1381 gstring = &scratch_gstring;
1382 if (gstring->size == 0)
1387 g_tmp.type = GLYPH_ANCHOR;
1388 APPEND_GLYPH (gstring, g_tmp);
1389 APPEND_GLYPH (gstring, g_tmp);
1390 APPEND_GLYPH (gstring, g_tmp);
1391 gstring->glyphs[1].type = GLYPH_SPACE;
1392 gstring->glyphs[1].g.c = '\n';
1393 gstring->glyphs[1].g.code = '\n';
1395 gstring->from = pos;
1397 g->rface = frame->rface;
1398 g->g.from = g->g.to = pos;
1400 g->rface = frame->rface;
1401 g->g.from = pos++, g->g.to = pos;
1403 g->rface = frame->rface;
1404 g->g.from = g->g.to = pos;
1409 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1410 MLIST_INIT1 (gstring, glyphs, 128);
1414 gstring->frame = frame;
1415 gstring->tick = frame->tick;
1416 gstring->top = gstring;
1417 gstring->control = *control;
1418 gstring->indent = gstring->width_limit = 0;
1419 if (control->format)
1420 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1422 gstring->width_limit = control->max_line_width;
1423 gstring->anti_alias = control->anti_alias;
1427 static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos,
1430 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1433 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1441 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1442 a width of glyphs for the character at I of MT. If I is not a
1443 beginning of a grapheme cluster, the corresponding element is
1445 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1446 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1447 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1448 pos_width[g->g.from - gstring->from] += g->g.xadv;
1449 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1451 if (pos_width[i] > 0)
1453 if (width + pos_width[i] > gstring->width_limit)
1456 width += pos_width[i];
1459 pos = gstring->from + i;
1460 if (gstring->control.line_break)
1462 pos = (*gstring->control.line_break) (mt, gstring->from + i,
1463 gstring->from, gstring->from + i,
1465 if (pos <= gstring->from)
1467 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1470 else if (pos >= gstring->to)
1475 g = find_glyph_in_gstring (gstring, gstring->from, 1);
1478 if (pos < gstring->to)
1480 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1481 layout_glyph_string (frame, gstring);
1486 /* Return a gstring that covers a character at POS. */
1488 static MGlyphString *
1489 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1491 MGlyphString *gstring = NULL;
1493 if (pos < mtext_nchars (mt))
1495 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1498 && ((prop->start != 0
1499 && mtext_ref_char (mt, prop->start - 1) != '\n')
1500 || (prop->end < mtext_nchars (mt)
1501 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1503 mtext_detach_property (prop);
1508 gstring = prop->val;
1509 if (gstring->frame != frame
1510 || gstring->tick != frame->tick
1511 || memcmp (control, &gstring->control,
1512 (char *) (&control->with_cursor)
1513 - (char *) (control))
1514 || control->cursor_width != gstring->control.cursor_width
1515 || control->cursor_bidi != gstring->control.cursor_bidi)
1517 mtext_detach_property (prop);
1522 else if (! control->cursor_width)
1530 offset = mtext_character (mt, pos, 0, '\n');
1535 offset -= gstring->from;
1537 for (gst = gstring; gst; gst = gst->next)
1541 gst->from += offset;
1543 for (i = 0; i < gst->used; i++)
1545 gst->glyphs[i].g.from += offset;
1546 gst->glyphs[i].g.to += offset;
1549 M17N_OBJECT_REF (gstring);
1554 int line = 0, y = 0;
1556 if (pos < mtext_nchars (mt))
1558 beg = mtext_character (mt, pos, 0, '\n');
1566 end = mtext_nchars (mt) + (control->cursor_width != 0);
1567 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1568 if (beg < mtext_nchars (mt))
1569 compose_glyph_string (frame, mt, beg, end, gstring);
1570 layout_glyph_string (frame, gstring);
1572 if (gstring->width_limit
1573 && gstring->width > gstring->width_limit)
1575 MGlyphString *gst = gstring;
1577 truncate_gstring (frame, mt, gst);
1578 while (gst->to < end)
1580 line++, y += gst->height;
1581 gst->next = alloc_gstring (frame, mt, gst->from, control,
1583 gst->next->top = gstring;
1584 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1586 layout_glyph_string (frame, gst);
1587 if (gst->width <= gst->width_limit)
1589 truncate_gstring (frame, mt, gst);
1593 if (! control->disable_caching && pos < mtext_nchars (mt))
1595 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1596 MTEXTPROP_VOLATILE_STRONG);
1598 if (end > mtext_nchars (mt))
1599 end = mtext_nchars (mt);
1600 mtext_attach_property (mt, beg, end, prop);
1601 M17N_OBJECT_UNREF (prop);
1605 while (gstring->to <= pos)
1607 if (! gstring->next)
1609 gstring = gstring->next;
1611 gstring->control = *control;
1617 static MDrawControl control_noop;
1619 #define ASSURE_CONTROL(control) \
1621 control = &control_noop; \
1626 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1627 MText *mt, int from, int to,
1628 MDrawControl *control)
1630 MGlyphString *gstring;
1632 M_CHECK_POS_X (mt, from, -1);
1633 ASSURE_CONTROL (control);
1634 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1635 to = mtext_nchars (mt) + (control->cursor_width != 0);
1639 gstring = get_gstring (frame, mt, from, to, control);
1641 MERROR (MERROR_DRAW, -1);
1642 render_glyph_string (frame, win, x, y, gstring, from, to);
1646 y += gstring->line_descent;
1647 M17N_OBJECT_UNREF (gstring->top);
1648 gstring = get_gstring (frame, mt, from, to, control);
1649 y += gstring->line_ascent;
1650 render_glyph_string (frame, win, x, y, gstring, from, to);
1653 M17N_OBJECT_UNREF (gstring->top);
1660 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1666 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1667 if (g->g.from <= pos && g->g.to > pos)
1672 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1673 if (g->g.from <= pos && g->g.to > pos)
1680 /* for debugging... */
1684 dump_gstring (MGlyphString *gstring, int indent, int type)
1686 char *prefix = (char *) alloca (indent + 1);
1687 MGlyph *g, *first_g, *last_g;
1689 memset (prefix, 32, indent);
1692 fprintf (stderr, "(glyph-string");
1696 first_g = MGLYPH (0);
1697 last_g = first_g + gstring->used;
1701 first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
1702 last_g = first_g + ((MFLTGlyphString *) gstring)->used;
1705 for (g = first_g; g < last_g; g++)
1708 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
1711 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1712 : g->type == GLYPH_ANCHOR ? "ANC"
1713 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1714 g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
1715 g->g.xadv, g->bidi_level);
1716 if (g->g.xoff || g->g.yoff)
1717 fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
1718 fprintf (stderr, ")");
1720 fprintf (stderr, ")");
1724 /* m17n-X internal APIs */
1729 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1731 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1732 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1734 Mcommon = msymbol ("common");
1736 McatCc = msymbol ("Cc");
1737 McatCf = msymbol ("Cf");
1739 MbidiR = msymbol ("R");
1740 MbidiAL = msymbol ("AL");
1741 MbidiRLE = msymbol ("RLE");
1742 MbidiRLO = msymbol ("RLO");
1743 MbidiBN = msymbol ("BN");
1744 MbidiS = msymbol ("S");
1745 MbidiNSM = msymbol ("NSM");
1747 fribidi_set_mirroring (TRUE);
1750 M_break_at_space = msymbol ("bs");
1751 M_break_at_word = msymbol ("bw");
1752 M_break_at_any = msymbol ("ba");
1753 M_kinsoku_bol = msymbol ("kb");
1754 M_kinsoku_eol = msymbol ("ke");
1762 MLIST_FREE1 (&scratch_gstring, glyphs);
1763 M17N_OBJECT_UNREF (linebreak_table);
1764 linebreak_table = NULL;
1768 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1772 /*** @addtogroup m17nDraw */
1777 @brief Draw an M-text on a window.
1779 The mdraw_text () function draws the text between $FROM and $TO of
1780 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1782 The appearance of the text (size, style, color, etc) is specified
1783 by the value of the text property whose key is @c Mface. If the
1784 M-text or a part of the M-text does not have such a text property,
1785 the default face of $FRAME is used.
1787 The font used to draw a character in the M-text is selected from
1788 the value of the fontset property of a face by the following
1793 <li> Search the text properties given to the character for the one
1794 whose key is @c Mcharset; its value should be either a symbol
1795 specifying a charset or #Mnil. If the value is #Mnil,
1796 proceed to the next step.
1798 Otherwise, search the mapping table of the fontset for the
1799 charset. If no entry is found proceed to the next step.
1801 If an entry is found, use one of the fonts in the entry that
1802 has a glyph for the character and that matches best with the
1803 face properties. If no such font exists, proceed to the next
1806 <li> Get the character property "script" of the character. If it is
1807 inherited, get the script property from the previous
1808 characters. If there is no previous character, or none of
1809 them has the script property other than inherited, proceed to
1812 Search the text properties given to the character for the one
1813 whose key is @c Mlanguage; its value should be either a
1814 symbol specifying a language or @c Mnil.
1816 Search the mapping table of the fontset for the combination
1817 of the script and language. If no entry is found, proceed to
1820 If an entry is found, use one of the fonts in the entry that
1821 has a glyph for the character and that matches best with the
1822 face properties. If no such font exists, proceed to the next
1825 <li> Search the fall-back table of the fontset for a font that has
1826 a glyph of the character. If such a font is found, use that
1831 If no font is found by the algorithm above, this function draws an
1832 empty box for the character.
1834 This function draws only the glyph foreground. To specify the
1835 background color, use mdraw_image_text () or
1836 mdraw_text_with_control ().
1838 This function is the counterpart of <tt>XDrawString ()</tt>,
1839 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1840 in the X Window System.
1843 If the operation was successful, mdraw_text () returns 0. If an
1844 error is detected, it returns -1 and assigns an error code to the
1845 external variable #merror_code. */
1847 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë.
1849 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1850 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤òÉÁ²è¤¹¤ë¡£
1852 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1853 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text
1854 ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1855 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£
1857 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset
1858 ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1862 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset
1863 ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil
1864 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1865 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset
1866 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£
1867 ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1869 ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£
1870 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1872 <li> ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£
1873 ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script"
1874 ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1876 ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1877 ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
1879 ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset
1880 ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1882 ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£
1883 ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1885 <li> ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back
1886 ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1890 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1892 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô
1893 mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£
1895 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô <tt>XDrawString ()</tt>,
1896 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1899 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
1900 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1902 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1909 mdraw_image_text () */
1912 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1913 MText *mt, int from, int to)
1915 MDrawControl control;
1917 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1918 memset (&control, 0, sizeof control);
1919 control.as_image = 0;
1920 return draw_text (frame, win, x, y, mt, from, to, &control);
1927 @brief Draw an M-text on a window as an image.
1929 The mdraw_image_text () function draws the text between $FROM and
1930 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1931 coordinate ($X, $Y).
1933 The way to draw a text is the same as in mdraw_text () except that
1934 this function also draws the background with the color specified
1937 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1938 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1939 functions in the X Window System.
1942 If the operation was successful, mdraw_image_text () returns 0.
1943 If an error is detected, it returns -1 and assigns an error code
1944 to the external variable #merror_code. */
1947 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯.
1949 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN
1950 ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO
1951 ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£
1953 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text ()
1954 ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1956 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1957 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt>
1961 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0
1962 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1964 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1974 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1975 MText *mt, int from, int to)
1977 MDrawControl control;
1979 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
1980 memset (&control, 0, sizeof control);
1981 control.as_image = 1;
1982 return draw_text (frame, win, x, y, mt, from, to, &control);
1988 @brief Draw an M-text on a window with fine control.
1990 The mdraw_text_with_control () function draws the text between
1991 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1992 coordinate ($X, $Y).
1994 The way to draw a text is the same as in mdraw_text () except that
1995 this function also follows what specified in the drawing control
1998 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1999 function draw an M-text 2-dimensionally, i.e., newlines in M-text
2000 breaks lines and the following characters are drawn in the next
2001 line. See the documentation of the structure @ MDrawControl for
2005 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤¤ÇÉÁ¤¯.
2007 ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦
2008 $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹
2011 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È
2012 $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
2014 ¤¿¤È¤¨¤Ð $CONTROL ¤Î <two_dimensional> ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï
2015 M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ
2016 @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/
2019 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
2020 MText *mt, int from, int to, MDrawControl *control)
2022 M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
2023 return draw_text (frame, win, x, y, mt, from, to, control);
2029 @brief Compute text pixel width.
2031 The mdraw_text_extents () function computes the width of text
2032 between $FROM and $TO of M-text $MT when it is drawn on a window
2033 of frame $FRAME using the mdraw_text_with_control () function with
2034 the drawing control object $CONTROL.
2036 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
2037 the bounding box of character ink of the M-text, and stores the
2038 results in the members of the structure pointed to by
2039 $OVERALL_INK_RETURN. If the M-text has a face specifying a
2040 surrounding box, the box is included in the bounding box.
2042 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
2043 computes the bounding box that provides minimum spacing to other
2044 graphical features (such as surrounding box) for the M-text, and
2045 stores the results in the members of the structure pointed to by
2046 $OVERALL_LOGICAL_RETURN.
2048 If $OVERALL_LINE_RETURN is not @c NULL, this function also
2049 computes the bounding box that provides minimum spacing to the
2050 other M-text drawn, and stores the results in the members of the
2051 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
2052 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2053 min_line_ascent, min_line_descent, max_line_ascent, and
2054 max_line_descent of $CONTROL are all zero.
2057 This function returns the width of the text to be drawn in the
2058 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2059 text is drawn in multiple physical lines, it returns the width of
2060 the widest line. If an error occurs, it returns -1 and assigns an
2061 error code to the external variable #merror_code. */
2065 @brief ¥Æ¥¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë.
2067 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2068 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2069 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2071 $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2072 ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN
2073 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box)
2074 ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£
2076 $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text
2077 ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡË
2078 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN
2079 ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2081 $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text
2082 ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢
2083 $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È
2084 $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent,
2085 max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃͤÏ
2086 $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣
2089 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional
2090 ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï
2091 -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2093 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2100 mdraw_text_extents (MFrame *frame,
2101 MText *mt, int from, int to, MDrawControl *control,
2102 MDrawMetric *overall_ink_return,
2103 MDrawMetric *overall_logical_return,
2104 MDrawMetric *overall_line_return)
2106 MGlyphString *gstring;
2108 int width, lbearing, rbearing;
2110 ASSURE_CONTROL (control);
2111 M_CHECK_POS_X (mt, from, -1);
2112 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2113 to = mtext_nchars (mt) + (control->cursor_width != 0);
2117 gstring = get_gstring (frame, mt, from, to, control);
2119 MERROR (MERROR_DRAW, -1);
2120 width = gstring_width (gstring, from, to, &lbearing, &rbearing);
2121 if (overall_ink_return)
2122 overall_ink_return->y = - gstring->physical_ascent;
2123 if (overall_logical_return)
2124 overall_logical_return->y = - gstring->ascent;
2125 if (overall_line_return)
2126 overall_line_return->y = - gstring->line_ascent;
2128 for (from = gstring->to; from < to; from = gstring->to)
2130 int this_width, this_lbearing, this_rbearing;
2132 y += gstring->line_descent;
2133 M17N_OBJECT_UNREF (gstring->top);
2134 gstring = get_gstring (frame, mt, from, to, control);
2135 this_width = gstring_width (gstring, from, to,
2136 &this_lbearing, &this_rbearing);
2137 y += gstring->line_ascent;
2138 if (width < this_width)
2140 if (rbearing < this_rbearing)
2141 rbearing = this_rbearing;
2142 if (lbearing > this_lbearing)
2143 lbearing = this_lbearing;
2145 if (overall_ink_return)
2147 overall_ink_return->x = lbearing;
2148 overall_ink_return->width = rbearing - lbearing;
2149 overall_ink_return->height
2150 = y + gstring->physical_descent - overall_ink_return->y;
2152 if (overall_logical_return)
2154 overall_logical_return->x = 0;
2155 overall_logical_return->width = width;
2156 overall_logical_return->height
2157 = y + gstring->descent - overall_logical_return->y;
2159 if (overall_line_return)
2161 overall_line_return->x = lbearing;
2162 overall_line_return->width = MAX (width, rbearing - lbearing);
2163 overall_line_return->height
2164 = y + gstring->line_descent - overall_line_return->y;
2167 M17N_OBJECT_UNREF (gstring->top);
2174 @brief Compute the text dimensions of each character of M-text.
2176 The mdraw_text_per_char_extents () function computes the drawn
2177 metric of each character between $FROM and $TO of M-text $MT
2178 assuming that they are drawn on a window of frame $FRAME using the
2179 mdraw_text_with_control () function with the drawing control
2182 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2183 $LOGICAL_ARRAY_RETURN. Each successive element of
2184 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2185 ink and logical metrics of successive characters respectively,
2186 relative to the drawing origin of the M-text. The number of
2187 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2188 been set is returned to $NUM_CHARS_RETURN.
2190 If $ARRAY_SIZE is too small to return all metrics, the function
2191 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2192 Otherwise, it returns zero.
2194 If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not
2195 @c NULL, this function also computes the metrics of the overall
2196 text and stores the results in the members of the structure
2197 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2199 If $CONTROL->two_dimensional is nonzero, this function computes
2200 only the metrics of characters in the first line. */
2202 @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë.
2204 ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2205 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO
2206 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£
2208 $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2209 ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN
2210 ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text
2211 ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È
2212 $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£
2214 $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1
2215 ¤òÊÖ¤·¡¢É¬ÍפÊÂ礤µ¤ò $NUM_CHARS_RETURN ¤ËÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 0
2218 ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL
2219 ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò
2220 $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£
2222 $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */
2225 mdraw_text_per_char_extents (MFrame *frame,
2226 MText *mt, int from, int to,
2227 MDrawControl *control,
2228 MDrawMetric *ink_array_return,
2229 MDrawMetric *logical_array_return,
2231 int *num_chars_return,
2232 MDrawMetric *overall_ink_return,
2233 MDrawMetric *overall_logical_return)
2235 MGlyphString *gstring;
2239 ASSURE_CONTROL (control);
2240 *num_chars_return = to - from;
2241 if (array_size < *num_chars_return)
2242 MERROR (MERROR_DRAW, -1);
2243 if (overall_logical_return)
2244 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2245 if (overall_ink_return)
2246 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2248 M_CHECK_RANGE (mt, from, to, -1, 0);
2249 gstring = get_gstring (frame, mt, from, to, control);
2252 *num_chars_return = 0;
2256 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
2257 if (g->g.from >= from && g->g.from < to)
2259 int start = g->g.from;
2261 int width = g->g.xadv;
2262 int lbearing = g->g.lbearing;
2263 int rbearing = g->g.rbearing;
2264 int ascent = g->g.ascent;
2265 int descent = g->g.descent;
2267 int logical_descent;
2269 if (g->rface->rfont)
2271 logical_ascent = g->rface->rfont->ascent;
2272 logical_descent = g->rface->rfont->descent;
2276 logical_ascent = g->rface->ascent;
2277 logical_descent = g->rface->descent;
2279 for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
2281 if (lbearing < width + g->g.lbearing)
2282 lbearing = width + g->g.lbearing;
2283 if (rbearing < width + g->g.rbearing)
2284 rbearing = width + g->g.rbearing;
2286 if (ascent < g->g.ascent)
2287 ascent = g->g.ascent;
2288 if (descent < g->g.descent)
2289 descent = g->g.descent;
2296 if (ink_array_return)
2298 ink_array_return[start - from].x = x + lbearing;
2299 ink_array_return[start - from].y = - ascent;
2300 ink_array_return[start - from].width = rbearing - lbearing;
2301 ink_array_return[start - from].height = ascent + descent;
2303 if (logical_array_return)
2305 logical_array_return[start - from].x = x;
2306 logical_array_return[start - from].y = - logical_descent;
2307 logical_array_return[start - from].height
2308 = logical_ascent + logical_descent;
2309 logical_array_return[start - from].width = width;
2317 if (overall_ink_return)
2319 overall_ink_return->y = - gstring->line_ascent;
2320 overall_ink_return->x = gstring->lbearing;
2321 overall_ink_return->width = x - gstring->lbearing;
2322 overall_ink_return->height = gstring->height;
2324 if (overall_logical_return)
2326 overall_logical_return->y = - gstring->ascent;
2327 overall_logical_return->x = 0;
2328 overall_logical_return->width = x;
2329 overall_logical_return->height = gstring->ascent + gstring->descent;
2332 M17N_OBJECT_UNREF (gstring->top);
2339 @brief Return the character position nearest to the coordinates.
2341 The mdraw_coordinates_position () function checks which character
2342 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2343 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2344 mdraw_text_with_control () function with the drawing control
2345 object $CONTROL. Here, the character position means the number of
2346 characters that precede the character in question in $MT, that is,
2347 the character position of the first character is 0.
2349 $FRAME is used only to get the default face information.
2352 If the glyph image of a character covers coordinate ($X, $Y),
2353 mdraw_coordinates_position () returns the character position of
2355 If $Y is less than the minimum Y-coordinate of the drawn area, it
2357 If $Y is greater than the maximum Y-coordinate of the drawn area,
2359 If $Y fits in with the drawn area but $X is less than the minimum
2360 X-coordinate, it returns the character position of the first
2361 character drawn on the line $Y.\n\n
2362 If $Y fits in with the drawn area but $X is greater than the
2363 maximum X-coordinate, it returns the character position of the
2364 last character drawn on the line $Y. */
2367 @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë.
2369 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô
2370 mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢
2371 M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0)
2372 ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y)
2373 ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º
2374 M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2376 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2379 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2380 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2381 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n
2382 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n
2383 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2384 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n
2385 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2386 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2389 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2390 int x_offset, int y_offset, MDrawControl *control)
2392 MGlyphString *gstring;
2397 M_CHECK_POS_X (mt, from, -1);
2398 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2399 to = mtext_nchars (mt) + (control->cursor_width != 0);
2405 ASSURE_CONTROL (control);
2406 gstring = get_gstring (frame, mt, from, to, control);
2407 while (y + gstring->line_descent <= y_offset
2408 && gstring->to < to)
2411 y += gstring->line_descent;
2412 M17N_OBJECT_UNREF (gstring->top);
2413 gstring = get_gstring (frame, mt, from, to, control);
2414 y += gstring->line_ascent;
2417 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2418 if (! control->orientation_reversed)
2420 width = gstring->indent;
2421 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
2422 if (g->g.from >= from && g->g.from < to)
2425 if (width > x_offset)
2431 width = - gstring->indent;
2432 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2433 if (g->g.from >= from && g->g.from < to)
2436 if (width < x_offset)
2440 if (g->type == GLYPH_ANCHOR
2441 && control->two_dimensional
2442 && g[-1].g.c == '\n')
2445 M17N_OBJECT_UNREF (gstring->top);
2453 @brief Compute information about a glyph.
2455 The mdraw_glyph_info () function computes information about a
2456 glyph that covers a character at position $POS of the M-text $MT
2457 assuming that the text is drawn from the character at $FROM of $MT
2458 on a window of frame $FRAME using the mdraw_text_with_control ()
2459 function with the drawing control object $CONTROL.
2461 The information is stored in the members of $INFO. */
2463 @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2465 ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2466 ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2467 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS
2468 ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£
2470 ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */
2478 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2479 MDrawControl *control, MDrawGlyphInfo *info)
2481 MGlyphString *gstring;
2485 M_CHECK_RANGE_X (mt, from, pos, -1);
2487 ASSURE_CONTROL (control);
2488 gstring = get_gstring (frame, mt, from, pos + 1, control);
2490 MERROR (MERROR_DRAW, -1);
2491 while (gstring->to <= pos)
2493 y += gstring->line_descent;
2494 M17N_OBJECT_UNREF (gstring->top);
2495 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2496 y += gstring->line_ascent;
2498 info->line_from = gstring->from;
2499 if (info->line_from < from)
2500 info->line_from = from;
2501 info->line_to = gstring->to;
2504 if (! control->orientation_reversed)
2506 info->x = gstring->indent;
2507 for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
2508 info->x += g->g.xadv;
2512 info->x = - gstring->indent;
2513 for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
2514 info->x -= g->g.xadv;
2515 while (g[-1].g.to == g->g.to)
2518 info->from = g->g.from;
2520 info->metrics.x = g->g.lbearing;
2521 info->metrics.y = - gstring->line_ascent;
2522 info->metrics.height = gstring->height;
2523 info->metrics.width = - g->g.lbearing + g->g.xadv;
2524 if (g->rface->rfont)
2525 info->font = (MFont *) g->rface->rfont;
2528 /* info->logical_width is calculated later. */
2530 if (info->from > info->line_from)
2532 /* The logically previous glyph is on this line. */
2533 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2535 info->prev_from = g_tmp->g.from;
2537 else if (info->line_from > 0
2538 && gstring->from > 0)
2540 /* The logically previous glyph is on the previous line. */
2541 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2542 gstring->from, control);
2543 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2545 info->prev_from = g_tmp->g.from;
2546 M17N_OBJECT_UNREF (gst->top);
2549 info->prev_from = -1;
2551 if (GLYPH_INDEX (g) > 1)
2552 info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
2553 else if (! control->orientation_reversed)
2555 if (info->line_from > 0)
2559 int p = gstring->from - 1;
2561 gst = get_gstring (frame, mt, p, gstring->from, control);
2562 g_tmp = gst->glyphs + (gst->used - 2);
2563 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2564 M17N_OBJECT_UNREF (gst->top);
2567 info->left_from = info->left_to = -1;
2571 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2575 int p = gstring->to;
2577 gst = get_gstring (frame, mt, p, p + 1, control);
2578 g_tmp = gst->glyphs + (gst->used - 2);
2579 info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
2580 M17N_OBJECT_UNREF (gst->top);
2583 info->left_from = info->left_to = -1;
2586 if (info->to < gstring->to)
2588 /* The logically next glyph is on this line. */
2589 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2591 info->next_to = g_tmp->g.to;
2593 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2595 /* The logically next glyph is on the next line. */
2597 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2598 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2600 info->next_to = g_tmp->g.to;
2601 M17N_OBJECT_UNREF (gst->top);
2606 for (info->logical_width = (g++)->g.xadv;
2607 g->g.from == pos && g->type != GLYPH_ANCHOR;
2608 info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
2609 info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
2611 if (g->type != GLYPH_ANCHOR)
2612 info->right_from = g->g.from, info->right_to = g->g.to;
2613 else if (! control->orientation_reversed)
2615 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2618 M17N_OBJECT_UNREF (gstring->top);
2619 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2621 info->right_from = g->g.from, info->right_to = g->g.to;
2624 info->right_from = info->right_to = -1;
2628 if (info->line_from > 0)
2630 pos = gstring->from - 1;
2631 M17N_OBJECT_UNREF (gstring->top);
2632 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2634 info->right_from = g->g.from, info->right_to = g->g.to;
2637 info->right_from = info->right_to = -1;
2640 M17N_OBJECT_UNREF (gstring->top);
2647 @brief Compute information about glyph sequence.
2649 The mdraw_glyph_list () function computes information about glyphs
2650 corresponding to the text between $FROM and $TO of M-text $MT when
2651 it is drawn on a window of frame $FRAME using the
2652 mdraw_text_with_control () function with the drawing control
2653 object $CONTROL. $GLYPHS is an array of objects to store the
2654 information, and $ARRAY_SIZE is the array size.
2656 If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
2657 number of actually filled elements in the place pointed by
2658 $NUM_GLYPHS_RETURN, and returns 0.
2660 Otherwise, it stores the required array size in the place pointed
2661 by $NUM_GLYPHS_RETURN, and returns -1. */
2664 @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
2666 ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control ()
2667 ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO
2668 ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS
2669 ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
2671 ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢
2672 $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£
2675 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢
2685 mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
2686 MDrawControl *control, MDrawGlyph *glyphs,
2687 int array_size, int *num_glyphs_return)
2689 MGlyphString *gstring;
2694 ASSURE_CONTROL (control);
2695 *num_glyphs_return = 0;
2696 M_CHECK_RANGE (mt, from, to, -1, 0);
2697 gstring = get_gstring (frame, mt, from, to, control);
2700 for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
2702 if (g->type == GLYPH_BOX
2703 || g->g.from < from || g->g.from >= to)
2705 if (g->type == GLYPH_PAD)
2707 if (g->left_padding)
2708 pad_width = g->g.xadv;
2712 glyphs[-1].x_advance += g->g.xadv;
2718 glyphs->from = g->g.from;
2719 glyphs->to = g->g.to;
2720 glyphs->glyph_code = g->g.code;
2721 glyphs->x_off = g->g.xoff + pad_width;
2722 glyphs->y_off = g->g.yoff;
2723 glyphs->lbearing = g->g.lbearing;
2724 glyphs->rbearing = g->g.rbearing;
2725 glyphs->ascent = g->g.ascent;
2726 glyphs->descent = g->g.descent;
2727 glyphs->x_advance = g->g.xadv + pad_width;
2728 glyphs->y_advance = 0;
2729 if (g->rface->rfont)
2731 glyphs->font = (MFont *) g->rface->rfont;
2733 = (glyphs->font->source == MFONT_SOURCE_X ? Mx
2734 : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype
2736 glyphs->fontp = g->rface->rfont->fontp;
2740 glyphs->font = NULL;
2741 glyphs->font_type = Mnil;
2742 glyphs->fontp = NULL;
2749 M17N_OBJECT_UNREF (gstring->top);
2751 *num_glyphs_return = n;
2752 return (n <= array_size ? 0 : -1);
2758 @brief Draw one or more textitems.
2760 The mdraw_text_items () function draws one or more M-texts on
2761 window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array
2762 of the textitems to be drawn and $NITEMS is the number of
2763 textitems in the array. */
2766 @brief textitem ¤òɽ¼¨¤¹¤ë.
2768 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à
2769 $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS
2770 ¤Ïɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£
2772 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2776 MTextItem, mdraw_text (). */
2779 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2780 MDrawTextItem *items, int nitems)
2782 if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
2784 while (nitems-- > 0)
2787 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2789 mdraw_text_with_control (frame, win, x, y,
2790 items->mt, 0, mtext_nchars (items->mt),
2792 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2793 items->control, NULL, NULL, NULL);
2796 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2802 @brief Option of line breaking for drawing text.
2804 The variable #mdraw_line_break_option specifies line breaking
2805 options by logical-or of the members of #MTextLineBreakOption. It
2806 controls the line breaking algorithm of the function
2807 mdraw_default_line_break (). */
2809 int mdraw_line_break_option;
2813 @brief Calculate a line breaking position.
2815 The function mdraw_default_line_break () calculates a line
2816 breaking position based on the line number $LINE and the
2817 coordinate $Y, when a line is too long to fit within the width
2818 limit. $POS is the position of the character next to the last one
2819 that fits within the limit. $FROM is the position of the first
2820 character of the line, and $TO is the position of the last
2821 character displayed on the line if there were not width limit.
2822 $LINE and $Y are reset to 0 when a line is broken by a newline
2823 character, and incremented each time when a long line is broken
2824 because of the width limit.
2826 @return This function returns a character position to break the
2831 @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë.
2833 ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ
2834 $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£
2835 $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2836 $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO
2837 ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£
2838 $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0
2839 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£
2842 ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2846 mdraw_default_line_break (MText *mt, int pos,
2847 int from, int to, int line, int y)
2851 p = mtext_line_break (mt, pos, mdraw_line_break_option, &after);
2862 @brief Obtain per character dimension information.
2864 The mdraw_per_char_extents () function computes the text dimension
2865 of each character in M-text $MT. The faces given as text
2866 properties in $MT and the default face of frame $FRAME determine
2867 the fonts to draw the text. Each successive element in
2868 $ARRAY_RETURN is set to the drawn metrics of successive
2869 characters, which is relative to the origin of the drawing, and a
2870 rectangle for each character in $MT. The number of elements of
2871 $ARRAY_RETURN must be equal to or greater than the number of
2874 If pointer $OVERALL_RETURN is not @c NULL, this function also
2875 computes the extents of the overall text and stores the results in
2876 the members of the structure pointed to by $OVERALL_RETURN. */
2879 @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
2881 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT
2882 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢
2883 $MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME
2884 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT
2885 Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢
2886 ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN
2887 ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2889 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL
2890 ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò
2891 $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£
2893 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2896 mdraw_per_char_extents (MFrame *frame, MText *mt,
2897 MDrawMetric *array_return,
2898 MDrawMetric *overall_return)
2900 int n = mtext_nchars (mt);
2902 mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
2903 n, &n, overall_return, NULL);
2907 @brief clear cached information.
2909 The mdraw_clear_cache () function clear cached information
2910 on M-text $MT that was attached by any of the drawing functions.
2911 When the behavior of `format' or `line_break'
2912 member functions of MDrawControl is changed, the cache must be cleared.
2917 @brief ¥¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹.
2919 ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT
2920 ¤ËÉղ䵤줿¥¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format'
2921 ¤¢¤ë¤¤¤Ï `line_break'
2922 ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
2928 mdraw_clear_cache (MText *mt)
2930 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);