1 /* draw.c -- drawing module.
2 Copyright (C) 2003, 2004
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., 59 Temple Place, Suite 330, Boston, MA
25 @brief Drawing M-text 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 layouting
39 @brief M-text ɽ¼¨¤Î¤¿¤á¤Î m17n-gui API
41 m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£É½
42 ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥ì¡¼¥à¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤È¥×¥í¥Ñ¥Æ¥£¤Ë´ð
43 ¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¿§¤ä²¼Àþ¤Ê¤É¤Î°À¤â¥Õ¥ì¡¼¥à¤Ë¤è¤Ã
48 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
49 /*** @addtogroup m17nInternal
56 #include <sys/types.h>
60 #include "m17n-misc.h"
64 #include "internal-gui.h"
69 #include <fribidi/fribidi.h>
70 #endif /* HAVE_FRIBIDI */
72 #define MAX(x, y) ((x) > (y) ? (x) : (y))
73 #define MIN(x, y) ((x) < (y) ? (x) : (y))
75 static MSymbol M_glyph_string;
78 static MSymbol Mlatin, Minherited;
79 /* Special categories */
80 static MSymbol McatCc, McatCf;
82 static MSymbol Mdepth;
85 /* Glyph-string composer. */
87 static MSymbol MbidiR;
88 static MSymbol MbidiAL;
89 static MSymbol MbidiRLE;
90 static MSymbol MbidiRLO;
91 static MSymbol MbidiBN;
92 static MSymbol MbidiS;
95 visual_order (MGlyphString *gstring)
97 int len = gstring->used - 2;
99 int *idx = alloca (sizeof (int) * len);
101 int bidi_sensitive = gstring->control.orientation_reversed;
103 MGlyph *g = MGLYPH (1);
106 FriBidiCharType base = (gstring->control.orientation_reversed
107 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
108 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
110 FriBidiStrIndex *indices;
111 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
112 #else /* not HAVE_FRIBIDI */
113 int *logical = alloca (sizeof (int) * len);
115 char *levels = alloca (len);
116 #endif /* not HAVE_FRIBIDI */
118 while (g->type != GLYPH_ANCHOR)
120 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
122 if (bidi == MbidiR || bidi == MbidiAL
123 || bidi == MbidiRLE || bidi == MbidiRLO)
130 idx[size] = GLYPH_INDEX (g);
131 logical[size++] = g++->c;
132 while (g->type != GLYPH_ANCHOR && g->combining_code)
136 if (! bidi_sensitive)
139 glyphs = alloca (sizeof (MGlyph) * gstring->used);
140 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
142 visual = alloca (sizeof (FriBidiChar) * size);
143 indices = alloca (sizeof (FriBidiStrIndex) * size);
145 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
146 #else /* not HAVE_FRIBIDI */
147 indices = alloca (sizeof (int) * size);
148 for (i = 0; i < size; i++)
154 for (j = i + 1; j < size && levels[j]; j++);
155 for (k = j--; i < k; i++, j--)
162 #endif /* not HAVE_FRIBIDI */
164 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
165 starts from gstring->glyphs[IDX[N]].
167 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
168 originally at LOGICAL[INDICES[N]]. */
170 for (i = 0, gidx = 1; i < size; i++)
175 glyphs[k].bidi_level = levels[j];
177 if (visual[i] != logical[j])
180 glyphs[k].c = visual[i];
181 if (glyphs[k].rface->rfont)
182 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
185 #endif /* not HAVE_FRIBIDI */
186 *(MGLYPH (gidx)) = glyphs[k];
188 k < gstring->used - 1 && glyphs[k].combining_code;
191 glyphs[k].bidi_level = levels[j];
192 *(MGLYPH (gidx)) = glyphs[k];
198 reorder_combining_chars (MGlyphString *gstring, int from, int to)
200 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
206 for (g = gbeg; g != gend; g++)
207 if (COMBINING_CODE_CLASS (g->combining_code) > 0
208 && (COMBINING_CODE_CLASS (g[-1].combining_code)
209 > COMBINING_CODE_CLASS (g->combining_code)))
220 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
221 displaying them on FRAME.
223 This function fills members <type>, <rface>, <c>, <pos>, <to>,
224 <code> of glyphs. The other members are filled by
225 layout_glyph_string. */
228 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
229 MGlyphString *gstring)
231 MRealizedFace *default_rface = frame->rface;
232 int stop, face_change, language_change, charset_change;
235 MSymbol language = Mnil, script = Mnil, charset = Mnil;
236 MRealizedFace *rface = default_rface;
238 int size = gstring->control.fixed_width;
242 MLIST_RESET (gstring);
243 gstring->from = from;
245 /* At first generate glyphs while using the member <enabled> as a
246 flag for rface re-checking. */
249 /** Put anchor glyphs at the head and tail. */
250 g_tmp.type = GLYPH_ANCHOR;
251 g_tmp.pos = g_tmp.to = from;
253 APPEND_GLYPH (gstring, g_tmp);
255 stop = face_change = charset_change = language_change = pos = from;
263 if (pos < mtext_nchars (mt))
264 c = mtext_ref_char (mt, pos);
267 g_tmp.category = Mnil;
270 if (c == ' ' || c == '\n' || c == '\t')
271 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
273 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
277 g_tmp.category = mchar_get_prop (c, Mcategory);
278 g_tmp.type = GLYPH_CHAR;
279 this_script = (MSymbol) mchar_get_prop (c, Mscript);
280 if (this_script == Minherited)
281 this_script = script;
284 if (pos == stop || script != this_script
285 || MGLYPH (last)->type != g_tmp.type)
288 if (non_ascii_found && g->type == GLYPH_CHAR)
289 while (g < gstring->glyphs + gstring->used)
290 g = mface__for_chars (script, language, charset,
291 g, gstring->glyphs + gstring->used, size);
292 last = gstring->used;
294 script = this_script;
297 if (pos < mtext_nchars (mt) && pos == language_change)
299 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
300 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
302 if (pos < mtext_nchars (mt) && pos == charset_change)
304 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
305 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
307 if (pos < mtext_nchars (mt) && pos == face_change)
310 int num = mtext_get_prop_values (mt, pos, Mface,
311 (void **) faces, 64);
313 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
315 ? mface__realize (frame, faces, num,
316 language, charset, size)
320 if (stop > language_change)
321 stop = language_change;
322 if (stop > charset_change)
323 stop = charset_change;
324 if (face_change < stop)
328 g_tmp.c = g_tmp.code = c;
335 else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
338 APPEND_GLYPH (gstring, g_tmp);
340 g_tmp.code = g_tmp.c + 0x40;
344 APPEND_GLYPH (gstring, g_tmp);
346 && gstring->control.two_dimensional)
352 /* Append an anchor glyph. */
353 g_tmp.type = GLYPH_ANCHOR;
355 g_tmp.code = MCHAR_INVALID_CODE;
356 g_tmp.pos = g_tmp.to = pos;
358 APPEND_GLYPH (gstring, g_tmp);
362 /* Next, run FLT if necessary. */
363 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
367 if (this->type == GLYPH_CHAR && this->rface->rfont)
371 if (this->rface->rfont->layouter != Mnil)
376 for (prev = MGLYPH (start - 1);
377 (prev->type == GLYPH_CHAR
378 && prev->category == McatCf
379 && (code = mfont__encode_char (this->rface->rfont, prev->c)
380 != MCHAR_INVALID_CODE));
385 (g->type == GLYPH_CHAR
386 && (g->rface->rfont == this->rface->rfont
387 || (g->category == McatCf
388 && ((code = mfont__encode_char (this->rface->rfont,
390 != MCHAR_INVALID_CODE))));
392 if (g->rface->rfont != this->rface->rfont)
394 i = mfont__flt_run (gstring, start, i, this->rface);
398 while (this->type == GLYPH_CHAR
401 && MSYMBOL_NAME (this->category)[0] == 'M'
402 && this->rface->rfont
403 && this->rface->rfont->layouter == Mnil)
405 int class = (int) mchar_get_prop (this->c,
408 = MAKE_COMBINING_CODE_BY_CLASS (class);
412 reorder_combining_chars (gstring, start, i);
420 /* At last, reorder glyphs visually if necessary. */
421 if (gstring->control.enable_bidi)
422 visual_order (gstring);
427 combining_code_from_class (int class)
432 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
433 else if (class == 200) /* below left attached */
434 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
435 else if (class == 202) /* below attached*/
436 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
437 else if (class == 204) /* below right attached */
438 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
439 else if (class == 208) /* left attached */
440 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
441 else if (class == 210) /* right attached */
442 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
443 else if (class == 212) /* above left attached */
444 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
445 else if (class == 214) /* above attached */
446 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
447 else if (class == 216) /* above right attached */
448 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
449 else if (class == 218) /* below left */
450 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
451 else if (class == 220) /* below */
452 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
453 else if (class == 222) /* below right */
454 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
455 else if (class == 224) /* left */
456 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
457 else if (class == 226) /* right */
458 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
459 else if (class == 228) /* above left */
460 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
461 else if (class == 230) /* above */
462 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
463 else if (class == 232) /* above right */
464 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
465 else if (class == 233) /* double below */
466 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
467 else if (class == 234) /* double above */
468 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
469 else if (class == 240) /* iota subscript */
470 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
472 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
478 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
480 int g_physical_ascent, g_physical_descent;
481 int g_width, g_lbearing, g_rbearing;
482 MGlyph *g = MGLYPH (from);
483 MGlyph *last_g = MGLYPH (to);
485 g_physical_ascent = gstring->physical_ascent;
486 g_physical_descent = gstring->physical_descent;
487 g_width = g_lbearing = g_rbearing = 0;
489 mfont__get_metric (gstring, from, to);
494 MRealizedFont *rfont = base->rface->rfont;
495 int size = rfont->font.property[MFONT_SIZE];
496 int width, lbearing, rbearing;
498 if (g == last_g || ! g->combining_code)
501 if (base->left_padding && base->lbearing < 0)
503 base->xoff = - base->lbearing;
504 base->width += base->xoff;
505 base->rbearing += base->xoff;
508 if (base->right_padding && base->rbearing > base->width)
510 base->width = base->rbearing;
512 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
513 rbearing = base->rbearing;
517 /* With combining glyphs. */
518 int left = -base->width;
520 int top = - base->ascent;
521 int bottom = base->descent;
522 int height = bottom - top;
523 int begin = base->pos;
528 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
529 rbearing = base->rbearing;
531 while (g != last_g && g->combining_code)
533 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
535 combining_code = g->combining_code;
536 if (COMBINING_BY_CLASS_P (combining_code))
537 g->combining_code = combining_code
538 = combining_code_from_class (COMBINING_CODE_CLASS
541 rfont = g->rface->rfont;
542 size = rfont->font.property[MFONT_SIZE];
543 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
545 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
547 base_x = COMBINING_CODE_BASE_X (combining_code);
548 base_y = COMBINING_CODE_BASE_Y (combining_code);
549 add_x = COMBINING_CODE_ADD_X (combining_code);
550 add_y = COMBINING_CODE_ADD_Y (combining_code);
554 else if (end < g->to)
557 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
560 if (g->xoff + g->width > right)
561 right = g->xoff + g->width;
562 width = right - left;
563 if (g->xoff + g->lbearing < left + lbearing)
564 lbearing = g->xoff + g->lbearing - left;
565 if (g->xoff + g->rbearing > left + rbearing)
566 rbearing = g->xoff + g->rbearing - left;
569 g->yoff = top + height * base_y / 2;
573 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
575 if (g->yoff - g->ascent < top)
576 top = g->yoff - g->ascent;
577 if (g->yoff + g->descent > bottom)
578 bottom = g->yoff + g->descent;
579 height = bottom - top;
585 base->ascent = - top;
586 base->descent = bottom;
587 base->lbearing = lbearing;
588 base->rbearing = rbearing;
589 if (left < - base->width)
591 base->xoff = - base->width - left;
592 base->width += base->xoff;
593 base->rbearing += base->xoff;
594 base->lbearing += base->xoff;
598 base->width += right;
599 base->rbearing += right;
600 base->right_padding = 1;
601 for (i = 1; base + i != g; i++)
602 base[i].xoff -= right;
605 for (i = 0; base + i != g; i++)
612 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
613 g_physical_descent = MAX (g_physical_descent, base->descent);
614 g_lbearing = MIN (g_lbearing, g_width + lbearing);
615 g_rbearing = MAX (g_rbearing, g_width + rbearing);
616 g_width += base->width;
619 gstring->physical_ascent = g_physical_ascent;
620 gstring->physical_descent = g_physical_descent;
621 gstring->sub_width = g_width;
622 gstring->sub_lbearing = g_lbearing;
623 gstring->sub_rbearing = g_rbearing;
627 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
628 by this function directly. Character glyphs are handled by
629 layouter functions registered in font drivers.
631 This function fill-in all the remaining members of glyphs. */
634 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
636 /* Default width of TAB. */
637 int tab_width = frame->space_width * (gstring->control.tab_width
638 ? gstring->control.tab_width : 8);
642 MDrawControl *control = &(gstring->control);
645 int box_line_height = 0;
646 int ignore_formatting_char = control->ignore_formatting_char;
648 gstring->ascent = gstring->descent = 0;
649 gstring->physical_ascent = gstring->physical_descent = 0;
650 gstring->width = gstring->lbearing = gstring->rbearing = 0;
654 while (g->type != GLYPH_ANCHOR)
656 if (box != g->rface->box)
658 int gidx = GLYPH_INDEX (g);
662 /* Insert the right side of the box. That glyph belongs
663 to the previous grapheme cluster. */
664 MGlyph box_glyph = g[-1];
666 box_glyph.type = GLYPH_BOX;
668 = (control->fixed_width
670 : box->inner_hmargin + box->width + box->outer_hmargin);
671 box_glyph.lbearing = 0;
672 box_glyph.rbearing = box_glyph.width;
674 box_glyph.right_padding = 1;
675 gstring->width += box_glyph.width;
676 gstring->rbearing += box_glyph.width;
677 INSERT_GLYPH (gstring, gidx, box_glyph);
684 /* Insert the left side of the box. That glyph belongs
685 to the following grapheme cluster. */
686 MGlyph box_glyph = *g;
687 int box_height = (box->width
688 + box->inner_vmargin + box->outer_vmargin);
690 if (box_line_height < box_height)
691 box_line_height = box_height;
692 box_glyph.type = GLYPH_BOX;
694 = (control->fixed_width
696 : box->inner_hmargin + box->width + box->outer_hmargin);
697 box_glyph.lbearing = 0;
698 box_glyph.rbearing = box_glyph.width;
700 box_glyph.left_padding = 1;
701 gstring->width += box_glyph.width;
702 gstring->rbearing += box_glyph.width;
703 INSERT_GLYPH (gstring, gidx, box_glyph);
709 if (g->category == McatCf && ignore_formatting_char)
710 g->type = GLYPH_SPACE;
712 if (g->type == GLYPH_CHAR)
714 MRealizedFace *rface = g->rface;
715 MRealizedFont *rfont = rface->rfont;
717 int from = GLYPH_INDEX (g);
719 for (g++; g->type == GLYPH_CHAR; g++)
720 if (! rfont != ! g->rface->rfont
721 || box != g->rface->box
722 || ((fromg->code == MCHAR_INVALID_CODE)
723 != (g->code == MCHAR_INVALID_CODE))
724 || (g->category == McatCf && ignore_formatting_char))
726 if (rfont && fromg->code != MCHAR_INVALID_CODE)
729 int to = GLYPH_INDEX (g);
731 layout_glyphs (frame, gstring, from, to);
732 extra_width = - gstring->sub_lbearing;
734 && (GLYPH_INDEX (g) > 1
735 || control->align_head))
739 pad.type = GLYPH_PAD;
742 pad.width = pad.rbearing = extra_width;
743 INSERT_GLYPH (gstring, from, pad);
745 gstring->sub_lbearing = 0;
746 gstring->sub_width += extra_width;
747 gstring->sub_rbearing += extra_width;
749 g = MGLYPH (from - 1);
750 if (g->type == GLYPH_SPACE)
752 /* The pad just inserted is absorbed (maybe
753 partially) by the previous space while
754 keeping at least some space width. For the
755 moment, we use the arbitrary width 2-pixel.
756 Perhaps, it should be decided by the current
757 face, or a default value of the current
758 frame, which is, however, not yet
760 if (extra_width + 2 < g->width)
762 g->width -= extra_width;
766 extra_width -= g->width - 2;
769 gstring->width -= extra_width;
770 gstring->rbearing -= extra_width;
774 extra_width = gstring->sub_rbearing - gstring->sub_width;
778 if (g->type == GLYPH_SPACE && box == g->rface->box)
782 pad.type = GLYPH_PAD;
785 pad.width = pad.rbearing = extra_width;
786 INSERT_GLYPH (gstring, to, pad);
790 g[-1].width += extra_width;
791 gstring->sub_width += extra_width;
794 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
795 gstring->lbearing = gstring->width + gstring->sub_lbearing;
796 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
797 gstring->rbearing = gstring->width + gstring->sub_rbearing;
798 gstring->width += gstring->sub_width;
799 if (gstring->ascent < rface->ascent)
800 gstring->ascent = rface->ascent;
801 if (gstring->descent < rface->descent)
802 gstring->descent = rface->descent;
807 for (; fromg < g; fromg++)
809 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
810 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
811 fromg->width = fromg->rbearing = 1;
813 fromg->width = fromg->rbearing = rface->space_width;
814 fromg->xoff = fromg->lbearing = 0;
815 fromg->ascent = fromg->descent = 0;
816 gstring->width += fromg->width;
817 gstring->rbearing += fromg->width;
819 if (gstring->ascent < frame->rface->ascent)
820 gstring->ascent = frame->rface->ascent;
821 if (gstring->descent < frame->descent)
822 gstring->descent = frame->rface->descent;
825 else if (g->type == GLYPH_SPACE)
828 g->width = g->rface->space_width;
829 else if (g->c == '\n')
831 g->width = control->cursor_width;
834 if (control->cursor_bidi)
836 else if (g->width < 0)
837 g->width = g->rface->space_width;
840 else if (g->c == '\t')
842 g->width = tab_width - ((gstring->indent + gstring->width)
848 if (g[-1].type == GLYPH_PAD)
850 /* This space glyph absorbs (maybe partially) the
851 previous padding glyph. */
852 g->width -= g[-1].width;
854 /* But, keep at least some space width. For the
855 moment, we use the arbitrary width 2-pixel. */
858 g->rbearing = g->width;
859 gstring->width += g->width;
860 gstring->rbearing += g->width;
863 if (gstring->ascent < g->rface->ascent)
864 gstring->ascent = g->rface->ascent;
865 if (gstring->descent < g->rface->descent)
866 gstring->descent = g->rface->descent;
872 gstring->width += g->width;
873 gstring->rbearing += g->width;
880 /* Insert the right side of the box. */
881 int gidx = GLYPH_INDEX (g);
882 MGlyph box_glyph = g[-1];
884 box_glyph.type = GLYPH_BOX;
886 = (control->fixed_width
888 : box->inner_hmargin + box->width + box->outer_hmargin);
889 box_glyph.lbearing = 0;
890 box_glyph.rbearing = box_glyph.width;
892 box_glyph.right_padding = 1;
893 gstring->width += box_glyph.width;
894 gstring->rbearing += box_glyph.width;
895 INSERT_GLYPH (gstring, gidx, box_glyph);
898 gstring->text_ascent = gstring->ascent;
899 gstring->text_descent = gstring->descent;
900 if (gstring->text_ascent < gstring->physical_ascent)
901 gstring->text_ascent = gstring->physical_ascent;
902 if (gstring->text_descent < gstring->physical_descent)
903 gstring->text_descent = gstring->physical_descent;
904 gstring->line_ascent = gstring->text_ascent;
905 gstring->line_descent = gstring->text_descent;
906 if (box_line_height > 0)
908 gstring->line_ascent += box_line_height;
909 gstring->physical_ascent = gstring->line_ascent;
910 gstring->line_descent += box_line_height;
911 gstring->physical_descent = gstring->line_descent;
914 if (gstring->line_ascent < control->min_line_ascent)
915 gstring->line_ascent = control->min_line_ascent;
916 else if (control->max_line_ascent
917 && control->max_line_ascent > control->min_line_ascent
918 && gstring->line_ascent > control->max_line_ascent)
919 gstring->line_ascent = control->max_line_ascent;
921 if (gstring->line_descent < control->min_line_descent)
922 gstring->line_descent = control->min_line_descent;
923 else if (control->max_line_descent
924 && control->max_line_descent > control->min_line_descent
925 && gstring->line_descent > control->max_line_descent)
926 gstring->line_descent = control->max_line_descent;
927 gstring->height = gstring->line_ascent + gstring->line_descent;
929 if (control->orientation_reversed
932 /* We must adjust TAB width for RTL orientation. */
933 width = gstring->indent;
935 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
937 if (g->type == GLYPH_CHAR && g->c == '\t')
939 int this_width = tab_width - (width % tab_width);
941 if (g[1].type == GLYPH_PAD)
942 this_width -= g[1].width;
943 if (g[-1].type == GLYPH_PAD)
944 this_width -= g[-1].width;
947 gstring->width += this_width - g->width;
948 gstring->rbearing += this_width - g->width;
949 g->width = this_width;
960 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
961 MGlyphString *gstring, int from, int to,
962 int *from_idx, int *to_idx, int *to_x)
964 MGlyph *g = MGLYPH (1);
965 MDrawRegion region = (MDrawRegion) NULL;
966 MDrawControl *control = &gstring->control;
969 int cursor_bidi = control->cursor_bidi;
971 if (control->with_cursor && control->cursor_width)
973 if (gstring->from <= control->cursor_pos
974 && gstring->to > control->cursor_pos)
975 cursor_pos = control->cursor_pos;
977 && gstring->from <= control->cursor_pos - 1
978 && gstring->to > control->cursor_pos - 1)
979 prev_pos = control->cursor_pos - 1;
982 *from_idx = *to_idx = 0;
983 while (g->type != GLYPH_ANCHOR)
985 if (g->pos >= from && g->pos < to)
987 MGlyph *fromg = g, *cursor = NULL;
988 MRealizedFace *rface = g->rface;
990 int cursor_width = 0;
994 *from_idx = GLYPH_INDEX (g);
995 while (g->pos >= from && g->pos < to
996 && g->rface == rface)
999 if (g->type != GLYPH_BOX
1000 && g->pos <= cursor_pos && g->to > cursor_pos)
1003 cursor = g, cursor_x = x + width;
1004 cursor_width += g->width;
1006 width += g++->width;
1009 && (control->as_image
1010 || rface->face.property[MFACE_BACKGROUND] != Mnil
1011 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
1013 int this_x = x, this_width = width;
1015 if (fromg->type == GLYPH_BOX)
1016 this_x += fromg->width, this_width -= fromg->width;
1017 if (g[-1].type == GLYPH_BOX)
1018 this_width -= g[-1].width;
1019 mwin__fill_space (frame, win, rface, 0,
1020 this_x, y - gstring->text_ascent, this_width,
1021 gstring->text_ascent + gstring->text_descent,
1022 control->clip_region);
1029 rect.y = y - gstring->text_ascent;
1030 rect.height = gstring->text_ascent + gstring->text_descent;
1033 rect.width = ((control->cursor_width > 0
1034 && control->cursor_width < cursor_width)
1035 ? control->cursor_width : cursor_width);
1039 if (cursor->bidi_level % 2)
1040 rect.x += cursor_width - 1;
1043 mwin__fill_space (frame, win, rface, 1,
1044 rect.x, rect.y, rect.width, rect.height,
1045 control->clip_region);
1047 region = mwin__region_from_rect (&rect);
1049 mwin__region_add_rect (region, &rect);
1050 mwin__verify_region (frame, region);
1053 if (cursor->bidi_level % 2)
1056 rect.width = cursor_width < 4 ? cursor_width : 4;
1057 mwin__fill_space (frame, win, rface, 1,
1058 rect.x, rect.y, rect.width, rect.height,
1059 control->clip_region);
1060 mwin__region_add_rect (region, &rect);
1061 mwin__verify_region (frame, region);
1073 if (fromg->type != GLYPH_BOX
1074 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1077 cursor = fromg, cursor_x = x + temp_width;
1078 cursor_width += fromg->width;
1080 temp_width += fromg++->width;
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 mwin__fill_space (frame, win, rface, 1,
1093 rect.x, rect.y, rect.width, rect.height,
1094 control->clip_region);
1096 region = mwin__region_from_rect (&rect);
1098 mwin__region_add_rect (region, &rect);
1099 mwin__verify_region (frame, region);
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 mwin__fill_space (frame, win, rface, 1,
1106 rect.x, rect.y, rect.width, rect.height,
1107 control->clip_region);
1108 mwin__region_add_rect (region, &rect);
1109 mwin__verify_region (frame, region);
1113 *to_idx = GLYPH_INDEX (g);
1123 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1124 MGlyphString *gstring, int from_idx, int to_idx,
1125 int reverse, MDrawRegion region)
1127 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1133 mwin__region_to_rect (region, &rect);
1136 while (g != gend && x + g->rbearing <= rect.x)
1139 width -= g++->width;
1140 while (! g->enabled && g != gend)
1144 rect.x += rect.width;
1145 if (rect.x < x + width)
1148 && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
1150 width -= (--gend)->width;
1151 while (! gend->enabled && g != gend)
1155 while (gend[-1].to == gend->to) gend++;
1163 MRealizedFace *rface = g->rface;
1164 int width = g->width;
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->code < 0) == (from_g->code < 0)
1173 width += g++->width;
1175 if (from_g->type == GLYPH_CHAR)
1177 MFontDriver *driver;
1179 if (rface->rfont && from_g->code >= 0)
1180 driver = rface->rfont->driver;
1182 driver = mfont__driver_list[MFONT_TYPE_WIN];
1183 (driver->render) (win, x, y, gstring, from_g, g,
1186 else if (from_g->type == GLYPH_BOX)
1188 /* Draw the left or right side of a box. If
1189 from_g->lbearing is nonzero, this is the left side,
1190 else this is the right side. */
1191 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1194 if (from_g->type != GLYPH_BOX)
1197 mwin__draw_hline (frame, win, gstring, rface, reverse,
1198 x, y, width, region);
1201 /* Draw the top and bottom side of a box. */
1202 mwin__draw_box (frame, win, gstring, from_g,
1203 x, y, width, region);
1214 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1215 int *from_x, int *to_x)
1218 int left_idx = *left, right_idx = *right;
1219 int left_x, right_x, x;
1221 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1224 if (x + g->rbearing > 0)
1226 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1228 left_idx = GLYPH_INDEX (g);
1233 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1236 if (x - g->width + g->lbearing < 0)
1238 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1240 right_idx = GLYPH_INDEX (g) + 1;
1245 if (*left == left_idx && *right == right_idx)
1248 if (*left != left_idx)
1250 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1255 if (*right != right_idx)
1257 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1267 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1272 if (from <= gstring->from && to >= gstring->to)
1275 *rbearing = gstring->rbearing;
1276 return gstring->width;
1281 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1282 if (g->pos >= from && g->pos < to)
1284 if (rbearing && width + g->rbearing > *rbearing)
1285 *rbearing = width + g->rbearing;
1293 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1294 MGlyphString *gstring, int from, int to)
1296 MDrawControl *control = &gstring->control;
1298 MDrawRegion clip_region, cursor_region;
1299 int from_idx, to_idx;
1302 if (control->orientation_reversed)
1303 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1305 x += gstring->indent;
1307 /* At first, draw all glyphs without cursor. */
1308 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1309 &from_idx, &to_idx, &to_x);
1311 if (control->partial_update)
1314 rect.width = to_x - x;
1315 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1317 rect.y = y - gstring->line_ascent;
1318 rect.height = gstring->height;
1319 clip_region = mwin__region_from_rect (&rect);
1320 if (control->clip_region)
1321 mwin__intersect_region (clip_region, control->clip_region);
1324 clip_region = control->clip_region;
1327 clip_region = control->clip_region;
1329 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1334 mwin__intersect_region (cursor_region, clip_region);
1335 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1338 if (clip_region != control->clip_region)
1339 mwin__free_region (clip_region);
1341 mwin__free_region (cursor_region);
1345 static int gstring_num;
1348 free_gstring (void *object)
1350 MGlyphString *gstring = (MGlyphString *) object;
1353 free_gstring (gstring->next);
1354 if (gstring->size > 0)
1355 free (gstring->glyphs);
1361 static MGlyphString scratch_gstring;
1363 static MGlyphString *
1364 alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control,
1367 MGlyphString *gstring;
1369 if (pos == mt->nchars)
1371 gstring = &scratch_gstring;
1375 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1376 MLIST_INIT1 (gstring, glyphs, 128);
1380 gstring->top = gstring;
1382 gstring->control = *control;
1383 gstring->indent = gstring->width_limit = 0;
1384 if (control->format)
1385 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1387 gstring->width_limit = control->max_line_width;
1388 gstring->anti_alias = control->anti_alias;
1389 if (gstring->anti_alias
1390 && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
1391 gstring->anti_alias = 0;
1395 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1398 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1406 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1407 a width of glyphs for the character at I of GSTRING->mt. If I is
1408 not a beginning of a grapheme cluster, the corresponding element
1410 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1411 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1412 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1413 pos_width[g->pos - gstring->from] += g->width;
1414 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1416 if (pos_width[i] > 0)
1418 if (width + pos_width[i] > gstring->width_limit)
1421 width += pos_width[i];
1424 pos = gstring->from + i;
1425 if (gstring->control.line_break)
1427 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1428 gstring->from, gstring->to, 0, 0);
1429 if (pos <= gstring->from || pos >= gstring->to)
1432 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1433 layout_glyph_string (frame, gstring);
1437 /* Return a gstring that covers a character at POS. */
1439 static MGlyphString *
1440 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1442 MGlyphString *gstring = NULL;
1444 if (pos < mtext_nchars (mt))
1446 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1449 && ((prop->start != 0
1450 && mtext_ref_char (mt, prop->start - 1) != '\n')
1451 || (prop->end < mtext_nchars (mt)
1452 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1454 mtext_detach_property (prop);
1459 gstring = prop->val;
1460 if (memcmp (control, &gstring->control,
1461 (char *) (&control->with_cursor)
1462 - (char *) (control)))
1464 mtext_detach_property (prop);
1469 else if (! control->cursor_width)
1477 offset = mtext_character (mt, pos, 0, '\n');
1482 offset -= gstring->from;
1484 for (gst = gstring; gst; gst = gst->next)
1488 gst->from += offset;
1490 for (i = 0; i < gst->used; i++)
1492 gst->glyphs[i].pos += offset;
1493 gst->glyphs[i].to += offset;
1496 M17N_OBJECT_REF (gstring);
1501 int line = 0, y = 0;
1503 if (control->two_dimensional)
1505 beg = mtext_character (mt, pos, 0, '\n');
1510 end = mtext_nchars (mt) + (control->cursor_width != 0);
1517 gstring = alloc_gstring (frame, mt, beg, control, line, y);
1518 compose_glyph_string (frame, mt, beg, end, gstring);
1519 layout_glyph_string (frame, gstring);
1521 if (control->two_dimensional
1522 && gstring->width_limit
1523 && gstring->width > gstring->width_limit)
1525 MGlyphString *gst = gstring;
1527 truncate_gstring (frame, mt, gst);
1528 while (gst->to < end)
1530 line++, y += gst->height;
1531 gst->next = alloc_gstring (frame, mt, gst->from, control,
1533 gst->next->top = gstring;
1534 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1536 layout_glyph_string (frame, gst);
1537 if (gst->width <= gst->width_limit)
1539 truncate_gstring (frame, mt, gst);
1543 if (! control->disable_caching && pos < mtext_nchars (mt))
1545 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1546 MTEXTPROP_VOLATILE_STRONG);
1548 if (end > mtext_nchars (mt))
1549 end = mtext_nchars (mt);
1550 mtext_attach_property (mt, beg, end, prop);
1551 M17N_OBJECT_UNREF (prop);
1555 while (gstring->to <= pos)
1557 if (! gstring->next)
1559 gstring = gstring->next;
1561 gstring->control = *control;
1567 static MDrawControl control_noop;
1569 #define ASSURE_CONTROL(control) \
1571 control = &control_noop; \
1576 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1577 MText *mt, int from, int to,
1578 MDrawControl *control)
1580 MGlyphString *gstring;
1582 M_CHECK_POS_X (mt, from, -1);
1583 ASSURE_CONTROL (control);
1584 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1585 to = mtext_nchars (mt) + (control->cursor_width != 0);
1589 gstring = get_gstring (frame, mt, from, to, control);
1591 MERROR (MERROR_DRAW, -1);
1592 render_glyph_string (frame, win, x, y, gstring, from, to);
1596 y += gstring->line_descent;
1597 M17N_OBJECT_UNREF (gstring->top);
1598 gstring = get_gstring (frame, mt, from, to, control);
1599 y += gstring->line_ascent;
1600 render_glyph_string (frame, win, x, y, gstring, from, to);
1603 M17N_OBJECT_UNREF (gstring->top);
1610 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1616 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1617 if (g->pos <= pos && g->to > pos)
1622 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1623 if (g->pos <= pos && g->to > pos)
1630 /* for debugging... */
1634 dump_combining_code (int code)
1636 char *vallign = "tcbB";
1637 char *hallign = "lcr";
1643 if (COMBINING_BY_CLASS_P (code))
1644 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1645 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1646 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1647 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1648 off_x = COMBINING_CODE_OFF_X (code) - 128;
1650 sprintf (work + 2, "+%d", off_y);
1652 sprintf (work + 2, "%d", off_y);
1653 else if (off_x == 0)
1654 sprintf (work + 2, ".");
1655 p = work + strlen (work);
1657 sprintf (p, ">%d", off_x);
1659 sprintf (p, "<%d", -off_x);
1661 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1662 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1668 dump_gstring (MGlyphString *gstring, int indent)
1670 char *prefix = (char *) alloca (indent + 1);
1671 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1673 memset (prefix, 32, indent);
1676 fprintf (stderr, "(glyph-string");
1678 for (g = MGLYPH (0); g < last_g; g++)
1680 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1682 g - gstring->glyphs,
1683 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1684 : g->type == GLYPH_ANCHOR ? "ANC"
1685 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1686 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1687 dump_combining_code (g->combining_code),
1688 g->width, g->bidi_level);
1689 fprintf (stderr, ")");
1693 /* m17n-X internal APIs */
1698 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1700 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1701 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1703 Mlatin = msymbol ("latin");
1704 Minherited = msymbol ("inherited");
1706 McatCc = msymbol ("Cc");
1707 McatCf = msymbol ("Cf");
1708 Mdepth = msymbol ("depth");
1710 MbidiR = msymbol ("R");
1711 MbidiAL = msymbol ("AL");
1712 MbidiRLE = msymbol ("RLE");
1713 MbidiRLO = msymbol ("RLO");
1714 MbidiBN = msymbol ("BN");
1715 MbidiS = msymbol ("S");
1717 fribidi_set_mirroring (TRUE);
1726 MLIST_FREE1 (&scratch_gstring, glyphs);
1730 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1734 /*** @addtogroup m17nDraw */
1739 @brief Draw an M-text on a window.
1741 The mdraw_text () function draws the text between $FROM and $TO of
1742 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1744 The appearance of the text (size, style, color, etc) is specified
1745 by the value of the text property whose key is @c Mface. If the
1746 M-text or a part of the M-text does not have such a text property,
1747 the default face of $FRAME is used.
1749 The font used to draw a character in the M-text is selected from
1750 the value of the fontset property of a face by the following
1755 <li> Search the text properties given to the character for the one
1756 whose key is @c Mcharset; its value should be either a symbol
1757 specifying a charset or Mnil. If the value is Mnil, proceed
1760 Otherwise, search the mapping table of the fontset for the
1761 charset. If no entry is found proceed to the next step. If
1762 an entry is found, use one of the fonts in the entry that has
1763 a glyph for the character and that matches best with the face
1764 properties. If no such font exists, proceed to the next
1767 <li> Get the character-property script of the character. If it is
1768 inherited, get the script property from the previous
1769 characters. If there is no previous character, or none of
1770 them has the script property other than inherited, proceed to
1773 Search the text properties given to the character for the one
1774 whose key is @c Mlanguage; its value should be either a
1775 symbol specifying a language or @c Mnil.
1777 Search the mapping table of the fontset for the combination
1778 of the script and language. If no entry is found, proceed to
1779 the next step. If an entry is found, use one of the fonts in
1780 the entry that has a glyph for the character and that matches
1781 best with the face properties. If no such font exists,
1782 proceed to the next step.
1784 <li> Search the fall-back table of the fontset for a font that has
1785 a glyph of the character. If such a font is found, use that
1790 If no font is found by the algorithm above, this function draws an
1791 empty box for the character.
1793 This function draws only the glyph foreground. To specify the
1794 background color, use mdraw_image_text () or
1795 mdraw_text_with_control ().
1797 This function is the counterpart of <tt>XDrawString ()</tt>,
1798 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1799 in the X Window System.
1802 If the operation was successful, mdraw_text () returns 0. If an
1803 error is detected, it returns -1 and assigns an error code to the
1804 external variable @c merror_code. */
1807 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òɽ¼¨¤¹¤ë
1809 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1810 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1813 ¥Ý¥¤¥ó¥¿ $RET_DESCENT ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢É½¼¨¤·¤¿¥Æ¥¥¹¥È¤Î¥Ç¥£¥»
1814 ¥ó¥È¤¬¤½¤³¤Ë³ÊǼ¤µ¤ì¤ë¡£
1816 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1817 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1818 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1819 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1821 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢$FACE ¤Î fontset ¥×¥í¥Ñ¥Æ¥£¤Î
1822 Ãͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1826 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1827 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤
1828 ¤º¤ì¤«¤Ç¤¢¤ë¡£¼¡¤Ë¥¡¼¤¬ @c Mscript ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1829 ¤³¤ÎÃͤϥ¹¥¯¥ê¥×¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£
1831 ¤É¤Á¤é¤â @c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1833 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤ò»È¤Ã
1834 ¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬
1835 ¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©
1836 ¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1838 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1839 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil
1840 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£@c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1842 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¸«¤Ä¤«¤Ã¤¿Ê¸»ú¥»¥Ã¥È»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã
1843 ¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©
1844 ¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê
1845 ¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1847 <li> ¸½ºß¤Îʸ»ú¼«¿È¤ò»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö
1848 ¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1852 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1853 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1855 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¿§¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë
1856 ¤Ï¡¢´Ø¿ô mdraw_image_text () ¤ò»È¤¦¤³¤È¡£
1858 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawString ()</tt>,
1859 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1862 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1863 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1865 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1872 mdraw_image_text () */
1875 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1876 MText *mt, int from, int to)
1878 MDrawControl control;
1880 memset (&control, 0, sizeof control);
1881 control.as_image = 0;
1882 return draw_text (frame, win, x, y, mt, from, to, &control);
1889 @brief Draw an M-text on a window as an image
1891 The mdraw_image_text () function draws the text between $FROM and
1892 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1893 coordinate ($X, $Y).
1895 The way to draw a text is the same as in mdraw_text () except that
1896 this function also draws the background with the color specified
1899 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1900 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1901 functions in the X Window System.
1904 If the operation was successful, mdraw_image_text () returns 0.
1905 If an error is detected, it returns -1 and assigns an error code
1906 to the external variable @c merror_code. */
1909 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯
1911 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1912 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1915 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1916 ¤Ï $FACE ¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1918 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1919 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1923 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1924 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1927 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1937 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1938 MText *mt, int from, int to)
1940 MDrawControl control;
1942 memset (&control, 0, sizeof control);
1943 control.as_image = 1;
1944 return draw_text (frame, win, x, y, mt, from, to, &control);
1950 @brief Draw an M-text on a window with fine control.
1952 The mdraw_text_with_control () function draws the text between
1953 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1954 coordinate ($X, $Y).
1956 The way to draw a text is the same as in mdraw_text () except that
1957 this function also follows what specified in the drawing control
1960 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1961 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1962 breaks lines and the following characters are drawn in the next
1963 line. See the documentation of the structure @ MDrawControl for
1967 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
1968 MText *mt, int from, int to, MDrawControl *control)
1970 return draw_text (frame, win, x, y, mt, from, to, control);
1976 @brief Compute text pixel width.
1978 The mdraw_text_extents () function computes the width of text
1979 between $FROM and $TO of M-text $MT when it is drawn on a window
1980 of frame $FRAME using the mdraw_text_with_control () function with
1981 the drawing control object $CONTROL.
1983 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
1984 the bounding box of character ink of the M-text, and stores the
1985 results in the members of the structure pointed to by
1986 $OVERALL_INK_RETURN. If the M-text has a face specifying a
1987 surrounding box, the box is included in the bounding box.
1989 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
1990 computes the bounding box that provides mininum spacing to other
1991 graphical features (such as surrounding box) for the M-text, and
1992 stores the results in the members of the structure pointed to by
1993 $OVERALL_LOGICAL_RETURN.
1995 If $OVERALL_LINE_RETURN is not @c NULL, this function also
1996 computes the bounding box that provides mininum spacing to the
1997 other M-text drawn, and stores the results in the members of the
1998 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
1999 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
2000 min_line_ascent, min_line_descent, max_line_ascent, and
2001 max_line_descent of $CONTROL are all zero.
2005 This function returns the width of the text to be drawn in the
2006 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
2007 text is drawn in multiple physical lines, it returns the width of
2008 the widest line. If an error occurs, it returns -1 and assigns an
2009 error code to the external variable @c merror_code. */
2012 @brief ¥Æ¥¥¹¥È¤ÎÉý¤ò·×»»¤¹¤ë
2014 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
2015 ¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
2017 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL °Ê³°¤Î¾ì¹ç¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥È
2018 Á´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢$OVERALL_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë
2019 ¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
2022 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפȤʤë¥Æ¥¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£¥¨¥é¡¼
2023 ¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
2026 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2033 mdraw_text_extents (MFrame *frame,
2034 MText *mt, int from, int to, MDrawControl *control,
2035 MDrawMetric *overall_ink_return,
2036 MDrawMetric *overall_logical_return,
2037 MDrawMetric *overall_line_return)
2039 MGlyphString *gstring;
2041 int width, rbearing;
2043 ASSURE_CONTROL (control);
2044 M_CHECK_POS_X (mt, from, -1);
2045 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2046 to = mtext_nchars (mt) + (control->cursor_width != 0);
2050 gstring = get_gstring (frame, mt, from, to, control);
2052 MERROR (MERROR_DRAW, -1);
2053 width = gstring_width (gstring, from, to, &rbearing);
2054 if (overall_ink_return)
2056 overall_ink_return->y = - gstring->physical_ascent;
2057 overall_ink_return->x = gstring->lbearing;
2059 if (overall_logical_return)
2061 overall_logical_return->y = - gstring->ascent;
2062 overall_logical_return->x = 0;
2064 if (overall_line_return)
2066 overall_line_return->y = - gstring->line_ascent;
2067 overall_line_return->x = gstring->lbearing;
2070 for (from = gstring->to; from < to; from = gstring->to)
2072 int this_width, this_rbearing;
2074 y += gstring->line_descent;
2075 M17N_OBJECT_UNREF (gstring->top);
2076 gstring = get_gstring (frame, mt, from, to, control);
2077 this_width = gstring_width (gstring, from, to, &this_rbearing);
2078 y += gstring->line_ascent;
2079 if (width < this_width)
2081 if (rbearing < this_rbearing)
2082 rbearing = this_rbearing;
2084 if (overall_ink_return)
2086 overall_ink_return->width = rbearing;
2087 overall_ink_return->height
2088 = y + gstring->physical_descent - overall_ink_return->y;
2090 if (overall_logical_return)
2092 overall_logical_return->width = width;
2093 overall_logical_return->height
2094 = y + gstring->descent - overall_logical_return->y;
2096 if (overall_line_return)
2098 overall_line_return->width = MAX (width, rbearing);
2099 overall_line_return->height
2100 = y + gstring->line_descent - overall_line_return->y;
2103 M17N_OBJECT_UNREF (gstring->top);
2110 @brief Compute the text dimensions of each character of M-text.
2112 The mdraw_text_per_char_extents () function computes the drawn
2113 metric of each character between $FROM and $TO of M-text $MT
2114 assuming that they are drawn on a window of frame $FRAME using the
2115 mdraw_text_with_control () function with the drawing control
2118 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2119 $LOGICAL_ARRAY_RETURN. Each successive element of
2120 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2121 ink and logical metrics of successive characters respectively,
2122 relative to the drawing origin of the M-text. The number of
2123 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2124 been set is returned to $NUM_CHARS_RETURN.
2126 If $ARRAY_SIZE is too small to return all metrics, the function
2127 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2128 Otherwise, it returns zero.
2130 If pointer $OVERALL_INK_RETURN an $OVERALL_LOGICAL_RETURN are not
2131 @c NULL, this function also computes the metrics of the overall
2132 text and stores the results in the members of the structure
2133 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2135 If $CONTROL->two_dimensional is nonzero, this function computes
2136 only the metrics of characters in the first line. */
2139 mdraw_text_per_char_extents (MFrame *frame,
2140 MText *mt, int from, int to,
2141 MDrawControl *control,
2142 MDrawMetric *ink_array_return,
2143 MDrawMetric *logical_array_return,
2145 int *num_chars_return,
2146 MDrawMetric *overall_ink_return,
2147 MDrawMetric *overall_logical_return)
2149 MGlyphString *gstring;
2153 ASSURE_CONTROL (control);
2154 *num_chars_return = to - from;
2155 if (array_size < *num_chars_return)
2157 if (overall_logical_return)
2158 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2159 if (overall_ink_return)
2160 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2162 M_CHECK_RANGE (mt, from, to, -1, 0);
2163 gstring = get_gstring (frame, mt, from, to, control);
2166 *num_chars_return = 0;
2170 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2171 if (g->pos >= from && g->pos < to)
2175 int width = g->width;
2176 int lbearing = g->lbearing;
2177 int rbearing = g->rbearing;
2178 int ascent = g->ascent;
2179 int descent = g->descent;
2180 int logical_ascent = g->rface->rfont->ascent;
2181 int logical_descent = g->rface->rfont->descent;
2183 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2185 if (lbearing < width + g->lbearing)
2186 lbearing = width + g->lbearing;
2187 if (rbearing < width + g->rbearing)
2188 rbearing = width + g->rbearing;
2190 if (ascent < g->ascent)
2192 if (descent < g->descent)
2193 descent = g->descent;
2200 ink_array_return[start - from].x = x + lbearing;
2201 ink_array_return[start - from].y = - ascent;
2202 ink_array_return[start - from].width = rbearing - lbearing;
2203 ink_array_return[start - from].height = ascent + descent;
2204 logical_array_return[start - from].x = x;
2205 logical_array_return[start - from].y = - logical_descent;
2206 logical_array_return[start - from].height
2207 = logical_ascent + logical_descent;
2208 logical_array_return[start - from].width = width;
2214 if (overall_ink_return)
2216 overall_ink_return->y = - gstring->line_ascent;
2217 overall_ink_return->x = gstring->lbearing;
2218 overall_ink_return->width = x - gstring->lbearing;
2219 overall_ink_return->height = gstring->height;
2221 if (overall_logical_return)
2223 overall_logical_return->y = - gstring->ascent;
2224 overall_logical_return->x = 0;
2225 overall_logical_return->width = x;
2226 overall_logical_return->height = gstring->ascent + gstring->descent;
2229 M17N_OBJECT_UNREF (gstring->top);
2236 @brief Return the character position nearest to the coordinates.
2238 The mdraw_coordinates_position () function checks which character
2239 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2240 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2241 mdraw_text_with_control () function with the drawing control
2242 object $CONTROL. Here, the character position means the number of
2243 characters that precede the character in question in $MT.
2245 $FRAME is used only to get the default face information.
2248 If the glyph image of a character covers coordinate ($X, $Y),
2249 mdraw_coordinates_position () returns the character position of
2251 If $Y is less than the minimum Y-coordinate of the drawn area, it
2252 returns $FROM.\n\n\n
2253 If $Y is greater than the maximum Y-coordinate of the drawn area,
2254 it returns $TO.\n\n\n
2255 If $Y fits in with the drawn area but $X is less than the minimum
2256 X-coordinate, it returns the character position of the first
2257 character drawn on the line $Y.\n\n\n
2258 If $Y fits in with the drawn area but $X is greater than the
2259 maximum X-coordinate, it returns the character position of the
2260 last character drawn on the line $Y. */
2263 @brief »ØÄꤷ¤¿ºÂɸ¤Ë¤¢¤ëʸ»ú¤Î°ÌÃÖ¤òÆÀ¤ë
2265 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢
2267 @li ´Ø¿ô mdraw_text () ¤ò»È¤Ã¤Æ
2268 @li M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
2269 @li ºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤Æ²¾¤ËÉÁ²è¤·¤¿¾ì¹ç
2271 ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ë¥Ù¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃÖ
2272 ¤È¤Ï¡¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç
2273 ¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2275 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2278 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2279 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2281 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2283 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2285 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2286 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2288 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2289 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2292 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2293 int x_offset, int y_offset, MDrawControl *control)
2295 MGlyphString *gstring;
2300 M_CHECK_POS_X (mt, from, -1);
2301 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2302 to = mtext_nchars (mt) + (control->cursor_width != 0);
2308 ASSURE_CONTROL (control);
2309 gstring = get_gstring (frame, mt, from, to, control);
2310 while (y + gstring->line_descent <= y_offset
2311 && gstring->to < to)
2314 y += gstring->line_descent;
2315 M17N_OBJECT_UNREF (gstring->top);
2316 gstring = get_gstring (frame, mt, from, to, control);
2317 y += gstring->line_ascent;
2320 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2321 if (! control->orientation_reversed)
2323 width = gstring->indent;
2324 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2325 if (g->pos >= from && g->pos < to)
2328 if (width > x_offset)
2334 width = - gstring->indent;
2335 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2336 if (g->pos >= from && g->pos < to)
2339 if (width < x_offset)
2344 M17N_OBJECT_UNREF (gstring->top);
2352 @brief Compute information about a glyph.
2354 The @c mdraw_glyph_info () function computes information about a
2355 glyph that covers a character at position $POS of the M-text $MT
2356 assuming that the text is drawn from the character at $FROM of $MT
2357 on a window of frame $FRAME using the mdraw_text_with_control ()
2358 function with the drawing control object $CONTROL.
2360 The information is stored in the members of $INFO. */
2368 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2369 MDrawControl *control, MDrawGlyphInfo *info)
2371 MGlyphString *gstring;
2375 M_CHECK_RANGE_X (mt, from, pos, -1);
2377 ASSURE_CONTROL (control);
2378 gstring = get_gstring (frame, mt, from, pos + 1, control);
2380 MERROR (MERROR_DRAW, -1);
2381 while (gstring->to <= pos)
2383 y += gstring->line_descent;
2384 M17N_OBJECT_UNREF (gstring->top);
2385 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2386 y += gstring->line_ascent;
2388 info->line_from = gstring->from;
2389 if (info->line_from < from)
2390 info->line_from = from;
2391 info->line_to = gstring->to;
2394 if (! control->orientation_reversed)
2396 info->x = gstring->indent;
2397 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2398 info->x += g->width;
2402 info->x = - gstring->indent;
2403 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2404 info->x -= g->width;
2405 while (g[-1].to == g->to)
2408 info->from = g->pos;
2410 info->this.x = g->lbearing;
2411 info->this.y = - gstring->line_ascent;
2412 info->this.height = gstring->height;
2413 if (g->rface->rfont)
2414 info->font = &g->rface->rfont->font;
2417 /* info->this.width is calculated later. */
2419 if (info->from > info->line_from)
2421 /* The logically previous glyph is on this line. */
2422 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2424 info->prev_from = g_tmp->pos;
2426 else if (info->line_from > 0)
2428 /* The logically previous glyph is on the previous line. */
2429 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2430 gstring->from, control);
2431 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2433 info->prev_from = g_tmp->pos;
2434 M17N_OBJECT_UNREF (gst->top);
2437 info->prev_from = -1;
2439 if (GLYPH_INDEX (g) > 1)
2440 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2441 else if (! control->orientation_reversed)
2443 if (info->line_from > 0)
2447 int p = gstring->from - 1;
2449 gst = get_gstring (frame, mt, p, gstring->from, control);
2450 g_tmp = gst->glyphs + (gst->used - 2);
2451 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2452 M17N_OBJECT_UNREF (gst->top);
2455 info->left_from = info->left_to = -1;
2459 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2463 int p = gstring->to;
2465 gst = get_gstring (frame, mt, p, p + 1, control);
2466 g_tmp = gst->glyphs + (gst->used - 2);
2467 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2468 M17N_OBJECT_UNREF (gst->top);
2471 info->left_from = info->left_to = -1;
2474 if (info->to < gstring->to)
2476 /* The logically next glyph is on this line. */
2477 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2479 info->next_to = g_tmp->to;
2481 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2483 /* The logically next glyph is on the next line. */
2485 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2486 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2488 info->next_to = g_tmp->to;
2489 M17N_OBJECT_UNREF (gst->top);
2494 for (info->this.width = (g++)->width;
2495 g->pos == pos && g->type != GLYPH_ANCHOR;
2496 info->this.width += (g++)->width);
2498 if (g->type != GLYPH_ANCHOR)
2499 info->right_from = g->pos, info->right_to = g->to;
2500 else if (! control->orientation_reversed)
2502 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2505 M17N_OBJECT_UNREF (gstring->top);
2506 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2508 info->right_from = g->pos, info->right_to = g->to;
2511 info->right_from = info->right_to = -1;
2515 if (info->line_from > 0)
2517 pos = gstring->from - 1;
2518 M17N_OBJECT_UNREF (gstring->top);
2519 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2521 info->right_from = g->pos, info->right_to = g->to;
2524 info->right_from = info->right_to = -1;
2527 M17N_OBJECT_UNREF (gstring->top);
2534 @brief Draw one or more textitems.
2536 The mdraw_text_items () function draws one or more M-texts on
2537 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2538 of the textitems to be drawn and $NITEMS is the number of
2539 textimtems in the array. */
2542 @brief textitem ¤òɽ¼¨¤¹¤ë
2544 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2545 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2546 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2549 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2553 MTextItem, mdraw_text (). */
2556 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2557 MDrawTextItem *items, int nitems)
2559 while (nitems-- > 0)
2562 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2564 mdraw_text_with_control (frame, win, x, y,
2565 items->mt, 0, mtext_nchars (items->mt),
2567 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2568 items->control, NULL, NULL, NULL);
2571 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2578 mdraw_default_line_break (MText *mt, int pos,
2579 int from, int to, int line, int y)
2581 int c = mtext_ref_char (mt, pos);
2584 if (c == ' ' || c == '\t')
2588 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2595 if (c == ' ' || c == '\t')
2598 c = mtext_ref_char (mt, pos);
2611 @brief Obtain per character dimension information.
2613 The mdraw_per_char_extents () function computes the text dimension
2614 of each character in M-text $MT. The faces given as text
2615 properties in $MT and the default face of frame $FRAME determine
2616 the fonts to draw the text. Each successive element in
2617 $ARRAY_RETURN is set to the drawn metrics of successive
2618 characters, which is relative to the origin of the drawing, and a
2619 rectangle for each character in $MT. The number of elements of
2620 $ARRAY_RETURN must be equal to or greater than the number of
2623 If pointer $OVERALL_RETURN is not @c NULL, this function also
2624 computes the extents of the overall text and stores the results in
2625 the members of the structure pointed to by $OVERALL_RETURN */
2628 @brief M-text ¤Îʸ»úËè¤Î¾ðÊó¤òÆÀ¤ë
2630 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2631 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2632 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤«¤é·èÄê
2633 ¤µ¤ì¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2634 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2635 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2636 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2638 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨
2639 ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·×»»¤ò $OVERALL_RETURN ¤Î»Ø¤¹Àè¤Ë³ÊǼ¤¹¤ë¡£
2641 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2644 mdraw_per_char_extents (MFrame *frame, MText *mt,
2645 MDrawMetric *array_return,
2646 MDrawMetric *overall_return)
2651 mdraw_clear_cache (MText *mt)
2653 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);