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;
83 /* Glyph-string composer. */
85 static MSymbol MbidiR;
86 static MSymbol MbidiAL;
87 static MSymbol MbidiRLE;
88 static MSymbol MbidiRLO;
89 static MSymbol MbidiBN;
90 static MSymbol MbidiS;
93 visual_order (MGlyphString *gstring)
95 int len = gstring->used - 2;
97 int *idx = alloca (sizeof (int) * len);
99 int bidi_sensitive = gstring->control.orientation_reversed;
101 MGlyph *g = MGLYPH (1);
104 FriBidiCharType base = (gstring->control.orientation_reversed
105 ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
106 FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
108 FriBidiStrIndex *indices;
109 FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
110 #else /* not HAVE_FRIBIDI */
111 int *logical = alloca (sizeof (int) * len);
113 char *levels = alloca (len);
114 #endif /* not HAVE_FRIBIDI */
116 while (g->type != GLYPH_ANCHOR)
118 MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
120 if (bidi == MbidiR || bidi == MbidiAL
121 || bidi == MbidiRLE || bidi == MbidiRLO)
128 idx[size] = GLYPH_INDEX (g);
129 logical[size++] = g++->c;
130 while (g->type != GLYPH_ANCHOR && g->combining_code)
134 if (! bidi_sensitive)
137 glyphs = alloca (sizeof (MGlyph) * gstring->used);
138 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
140 visual = alloca (sizeof (FriBidiChar) * size);
141 indices = alloca (sizeof (FriBidiStrIndex) * size);
143 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
144 #else /* not HAVE_FRIBIDI */
145 indices = alloca (sizeof (int) * size);
146 for (i = 0; i < size; i++)
152 for (j = i + 1; j < size && levels[j]; j++);
153 for (k = j--; i < k; i++, j--)
160 #endif /* not HAVE_FRIBIDI */
162 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
163 starts from gstring->glyphs[IDX[N]].
165 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
166 originally at LOGICAL[INDICES[N]]. */
168 for (i = 0, gidx = 1; i < size; i++)
172 int pos = glyphs[k].pos;
174 glyphs[k].bidi_level = levels[j];
176 if (visual[i] != logical[j])
179 glyphs[k].c = visual[i];
180 if (glyphs[k].rface->rfont)
181 glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
184 #endif /* not HAVE_FRIBIDI */
185 *(MGLYPH (gidx)) = glyphs[k];
187 k < gstring->used - 1 && glyphs[k].combining_code;
190 glyphs[k].bidi_level = levels[j];
191 *(MGLYPH (gidx)) = glyphs[k];
197 reorder_combining_chars (MGlyphString *gstring, int from, int to)
199 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
205 for (g = gbeg; g != gend; g++)
206 if (COMBINING_CODE_CLASS (g->combining_code) > 0
207 && (COMBINING_CODE_CLASS (g[-1].combining_code)
208 > COMBINING_CODE_CLASS (g->combining_code)))
219 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
220 displaying them on FRAME.
222 This function fills members <type>, <rface>, <c>, <pos>, <to>,
223 <code> of glyphs. The other members are filled by
224 layout_glyph_string. */
227 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
228 MGlyphString *gstring)
230 MRealizedFace *default_rface = frame->rface;
231 int stop, face_change, language_change, charset_change;
234 MSymbol language = Mnil, script = Mnil, charset = Mnil;
235 MRealizedFace *rface = default_rface;
237 int size = gstring->control.fixed_width;
238 int ignore_formatting_char = gstring->control.ignore_formatting_char;
241 MLIST_RESET (gstring);
242 gstring->from = from;
244 /* At first generate glyphs while using the member <enabled> as a
245 flag for rface re-checking. */
248 /** Put anchor glyphs at the head and tail. */
249 g_tmp.type = GLYPH_ANCHOR;
250 g_tmp.pos = g_tmp.to = from;
252 APPEND_GLYPH (gstring, g_tmp);
254 stop = face_change = charset_change = language_change = pos = from;
255 g = gstring->glyphs + gstring->used;
262 if (pos < mtext_nchars (mt))
263 c = mtext_ref_char (mt, pos);
266 g_tmp.category = Mnil;
269 if (c == ' ' || c == '\n' || c == '\t')
270 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
272 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
276 g_tmp.category = mchar_get_prop (c, Mcategory);
277 if (ignore_formatting_char && g_tmp.category == McatCf)
278 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
281 g_tmp.type = GLYPH_CHAR;
282 this_script = (MSymbol) mchar_get_prop (c, Mscript);
283 if (this_script == Minherited)
284 this_script = script;
288 if (pos == stop || script != this_script || g->type != g_tmp.type)
290 if (non_ascii_found && g->type == GLYPH_CHAR)
291 while (g < gstring->glyphs + gstring->used)
292 g = mface__for_chars (script, language, charset,
293 g, gstring->glyphs + gstring->used, size);
294 g = gstring->glyphs + gstring->used;
296 script = this_script;
299 if (pos < mtext_nchars (mt) && pos == language_change)
301 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
302 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
304 if (pos < mtext_nchars (mt) && pos == charset_change)
306 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
307 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
309 if (pos < mtext_nchars (mt) && pos == face_change)
312 int num = mtext_get_prop_values (mt, pos, Mface,
313 (void **) faces, 64);
315 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
317 ? mface__realize (frame, faces, num,
318 language, charset, size)
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);
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)
370 MGlyph *tmp = gstring->glyphs + i;
372 if (this->rface->rfont->layouter != Mnil)
374 while ((tmp->type == GLYPH_CHAR || tmp->type == GLYPH_SPACE)
375 && tmp->rface->rfont == this->rface->rfont
376 && tmp->code != MCHAR_INVALID_CODE)
378 i = mfont__flt_run (gstring, start, i,
379 this->rface->rfont->layouter,
380 this->rface->ascii_rface);
384 while (this->type == GLYPH_CHAR
387 && MSYMBOL_NAME (this->category)[0] == 'M'
388 && this->rface->rfont
389 && this->rface->rfont->layouter == Mnil)
391 int class = (int) mchar_get_prop (this->c,
394 = MAKE_COMBINING_CODE_BY_CLASS (class);
398 reorder_combining_chars (gstring, start, i);
406 /* At last, reorder glyphs visually if necessary. */
407 if (gstring->control.enable_bidi)
408 visual_order (gstring);
413 combining_code_from_class (int class)
418 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
419 else if (class == 200) /* below left attached */
420 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
421 else if (class == 202) /* below attached*/
422 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
423 else if (class == 204) /* below right attached */
424 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
425 else if (class == 208) /* left attached */
426 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
427 else if (class == 210) /* right attached */
428 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
429 else if (class == 212) /* above left attached */
430 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
431 else if (class == 214) /* above attached */
432 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
433 else if (class == 216) /* above right attached */
434 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
435 else if (class == 218) /* below left */
436 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
437 else if (class == 220) /* below */
438 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
439 else if (class == 222) /* below right */
440 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
441 else if (class == 224) /* left */
442 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
443 else if (class == 226) /* right */
444 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
445 else if (class == 228) /* above left */
446 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
447 else if (class == 230) /* above */
448 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
449 else if (class == 232) /* above right */
450 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
451 else if (class == 233) /* double below */
452 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
453 else if (class == 234) /* double above */
454 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
455 else if (class == 240) /* iota subscript */
456 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
458 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
464 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
466 int g_physical_ascent, g_physical_descent;
467 int g_width, g_lbearing, g_rbearing;
468 MGlyph *g = MGLYPH (from);
469 MGlyph *last_g = MGLYPH (to);
471 g_physical_ascent = gstring->physical_ascent;
472 g_physical_descent = gstring->physical_descent;
473 g_width = g_lbearing = g_rbearing = 0;
478 MRealizedFont *rfont = base->rface->rfont;
479 int size = rfont->font.property[MFONT_SIZE];
480 int width, lbearing, rbearing;
482 mfont__get_metric (rfont, base);
483 if (g == last_g || ! g->combining_code)
486 if (base->left_padding && base->lbearing < 0)
488 base->xoff = - base->lbearing;
489 base->width += base->xoff;
490 base->rbearing += base->xoff;
493 if (base->right_padding && base->rbearing > base->width)
495 base->width = base->rbearing;
497 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
498 rbearing = base->rbearing;
502 /* With combining glyphs. */
503 int left = -base->width;
505 int top = - base->ascent;
506 int bottom = base->descent;
507 int height = bottom - top;
508 int begin = base->pos;
513 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
514 rbearing = base->rbearing;
516 while (g != last_g && g->combining_code)
518 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
520 combining_code = g->combining_code;
521 if (COMBINING_BY_CLASS_P (combining_code))
522 g->combining_code = combining_code
523 = combining_code_from_class (COMBINING_CODE_CLASS
526 rfont = g->rface->rfont;
527 size = rfont->font.property[MFONT_SIZE];
528 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
530 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
532 base_x = COMBINING_CODE_BASE_X (combining_code);
533 base_y = COMBINING_CODE_BASE_Y (combining_code);
534 add_x = COMBINING_CODE_ADD_X (combining_code);
535 add_y = COMBINING_CODE_ADD_Y (combining_code);
539 else if (end < g->to)
542 mfont__get_metric (rfont, g);
543 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
546 if (g->xoff + g->width > right)
547 right = g->xoff + g->width;
548 width = right - left;
549 if (g->xoff + g->lbearing < left + lbearing)
550 lbearing = g->xoff + g->lbearing - left;
551 if (g->xoff + g->rbearing > left + rbearing)
552 rbearing = g->xoff + g->rbearing - left;
555 g->yoff = top + height * base_y / 2;
559 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
561 if (g->yoff - g->ascent < top)
562 top = g->yoff - g->ascent;
563 if (g->yoff + g->descent > bottom)
564 bottom = g->yoff + g->descent;
565 height = bottom - top;
571 base->ascent = - top;
572 base->descent = bottom;
573 if (left < - base->width)
575 base->xoff = - base->width - left;
576 base->width += base->xoff;
577 base->rbearing += base->xoff;
578 base->lbearing += base->xoff;
582 base->width += right;
583 base->rbearing += right;
584 base->right_padding = 1;
585 for (i = 1; base + i != g; i++)
586 base[i].xoff -= right;
589 for (i = 0; base + i != g; i++)
596 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
597 g_physical_descent = MAX (g_physical_descent, base->descent);
598 g_lbearing = MIN (g_lbearing, g_width + lbearing);
599 g_rbearing = MAX (g_rbearing, g_width + rbearing);
600 g_width += base->width;
603 gstring->physical_ascent = g_physical_ascent;
604 gstring->physical_descent = g_physical_descent;
605 gstring->sub_width = g_width;
606 gstring->sub_lbearing = g_lbearing;
607 gstring->sub_rbearing = g_rbearing;
611 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
612 by this function directly. Character glyphs are handled by
613 layouter functions registered in font drivers.
615 This function fill-in all the remaining members of glyphs. */
618 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
620 /* Default width of TAB. */
621 int tab_width = frame->space_width * (gstring->control.tab_width
622 ? gstring->control.tab_width : 8);
626 MDrawControl *control = &(gstring->control);
629 int box_line_height = 0;
631 gstring->ascent = gstring->descent = 0;
632 gstring->physical_ascent = gstring->physical_descent = 0;
633 gstring->width = gstring->lbearing = gstring->rbearing = 0;
637 while (g->type != GLYPH_ANCHOR)
639 if (box != g->rface->box)
641 int gidx = GLYPH_INDEX (g);
645 /* Insert the right side of the box. That glyph belongs
646 to the previous grapheme cluster. */
647 MGlyph box_glyph = g[-1];
649 box_glyph.type = GLYPH_BOX;
651 = (control->fixed_width
653 : box->inner_hmargin + box->width + box->outer_hmargin);
654 box_glyph.lbearing = 0;
655 box_glyph.rbearing = box_glyph.width;
657 box_glyph.right_padding = 1;
658 gstring->width += box_glyph.width;
659 gstring->rbearing += box_glyph.width;
660 INSERT_GLYPH (gstring, gidx, box_glyph);
667 /* Insert the left side of the box. That glyph belongs
668 to the following grapheme cluster. */
669 MGlyph box_glyph = *g;
670 int box_height = (box->width
671 + box->inner_vmargin + box->outer_vmargin);
673 if (box_line_height < box_height)
674 box_line_height = box_height;
675 box_glyph.type = GLYPH_BOX;
677 = (control->fixed_width
679 : box->inner_hmargin + box->width + box->outer_hmargin);
680 box_glyph.lbearing = 0;
681 box_glyph.rbearing = box_glyph.width;
683 box_glyph.left_padding = 1;
684 gstring->width += box_glyph.width;
685 gstring->rbearing += box_glyph.width;
686 INSERT_GLYPH (gstring, gidx, box_glyph);
692 if (g->type == GLYPH_CHAR)
694 MRealizedFace *rface = g->rface;
695 MRealizedFont *rfont = rface->rfont;
697 int from = GLYPH_INDEX (g);
699 for (g++; g->type == GLYPH_CHAR; g++)
700 if (! rfont != ! g->rface->rfont
701 || box != g->rface->box
702 || ((fromg->code == MCHAR_INVALID_CODE)
703 != (g->code == MCHAR_INVALID_CODE)))
705 if (rfont && fromg->code != MCHAR_INVALID_CODE)
708 int to = GLYPH_INDEX (g);
710 layout_glyphs (frame, gstring, from, to);
711 extra_width = - gstring->sub_lbearing;
713 && (GLYPH_INDEX (g) > 1
714 || control->align_head))
718 pad.type = GLYPH_PAD;
721 pad.width = pad.rbearing = extra_width;
722 INSERT_GLYPH (gstring, from, pad);
724 gstring->sub_lbearing = 0;
725 gstring->sub_width += extra_width;
726 gstring->sub_rbearing += extra_width;
728 g = MGLYPH (from - 1);
729 if (g->type == GLYPH_SPACE)
731 /* The pad just inserted is absorbed (maybe
732 partially) by the previous space while
733 keeping at least some space width. For the
734 moment, we use the arbitrary width 2-pixel.
735 Perhaps, it should be decided by the current
736 face, or a default value of the current
737 frame, which is, however, not yet
739 if (extra_width + 2 < g->width)
741 g->width -= extra_width;
745 extra_width -= g->width - 2;
748 gstring->width -= extra_width;
749 gstring->rbearing -= extra_width;
753 extra_width = gstring->sub_rbearing - gstring->sub_width;
757 if (g->type == GLYPH_SPACE && box == g->rface->box)
761 pad.type = GLYPH_PAD;
764 pad.width = pad.rbearing = extra_width;
765 INSERT_GLYPH (gstring, to, pad);
769 g[-1].width += extra_width;
770 gstring->sub_width += extra_width;
773 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
774 gstring->lbearing = gstring->width + gstring->sub_lbearing;
775 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
776 gstring->rbearing = gstring->width + gstring->sub_rbearing;
777 gstring->width += gstring->sub_width;
778 if (gstring->ascent < rface->ascent)
779 gstring->ascent = rface->ascent;
780 if (gstring->descent < rface->descent)
781 gstring->descent = rface->descent;
786 for (; fromg < g; fromg++)
788 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
789 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
790 fromg->width = fromg->rbearing = 1;
792 fromg->width = fromg->rbearing = rface->space_width;
793 fromg->xoff = fromg->lbearing = 0;
794 fromg->ascent = fromg->descent = 0;
795 gstring->width += fromg->width;
796 gstring->rbearing += fromg->width;
798 if (gstring->ascent < frame->rface->ascent)
799 gstring->ascent = frame->rface->ascent;
800 if (gstring->descent < frame->descent)
801 gstring->descent = frame->rface->descent;
804 else if (g->type == GLYPH_SPACE)
807 g->width = g->rface->space_width;
808 else if (g->c == '\n')
810 g->width = control->cursor_width;
813 if (control->cursor_bidi)
815 else if (g->width < 0)
816 g->width = g->rface->space_width;
819 else if (g->c == '\t')
821 g->width = tab_width - ((gstring->indent + gstring->width)
827 if (g[-1].type == GLYPH_PAD)
829 /* This space glyph absorbs (maybe partially) the
830 previous padding glyph. */
831 g->width -= g[-1].width;
833 /* But, keep at least some space width. For the
834 moment, we use the arbitrary width 2-pixel. */
837 g->rbearing = g->width;
838 gstring->width += g->width;
839 gstring->rbearing += g->width;
842 if (gstring->ascent < g->rface->ascent)
843 gstring->ascent = g->rface->ascent;
844 if (gstring->descent < g->rface->descent)
845 gstring->descent = g->rface->descent;
851 gstring->width += g->width;
852 gstring->rbearing += g->width;
859 /* Insert the right side of the box. */
860 int gidx = GLYPH_INDEX (g);
861 MGlyph box_glyph = g[-1];
863 box_glyph.type = GLYPH_BOX;
865 = (control->fixed_width
867 : box->inner_hmargin + box->width + box->outer_hmargin);
868 box_glyph.lbearing = 0;
869 box_glyph.rbearing = box_glyph.width;
871 box_glyph.right_padding = 1;
872 gstring->width += box_glyph.width;
873 gstring->rbearing += box_glyph.width;
874 INSERT_GLYPH (gstring, gidx, box_glyph);
877 gstring->text_ascent = gstring->ascent;
878 gstring->text_descent = gstring->descent;
879 if (gstring->text_ascent < gstring->physical_ascent)
880 gstring->text_ascent = gstring->physical_ascent;
881 if (gstring->text_descent < gstring->physical_descent)
882 gstring->text_descent = gstring->physical_descent;
883 gstring->line_ascent = gstring->text_ascent;
884 gstring->line_descent = gstring->text_descent;
885 if (box_line_height > 0)
887 gstring->line_ascent += box_line_height;
888 gstring->physical_ascent = gstring->line_ascent;
889 gstring->line_descent += box_line_height;
890 gstring->physical_descent = gstring->line_descent;
893 if (gstring->line_ascent < control->min_line_ascent)
894 gstring->line_ascent = control->min_line_ascent;
895 else if (control->max_line_ascent
896 && control->max_line_ascent > control->min_line_ascent
897 && gstring->line_ascent > control->max_line_ascent)
898 gstring->line_ascent = control->max_line_ascent;
900 if (gstring->line_descent < control->min_line_descent)
901 gstring->line_descent = control->min_line_descent;
902 else if (control->max_line_descent
903 && control->max_line_descent > control->min_line_descent
904 && gstring->line_descent > control->max_line_descent)
905 gstring->line_descent = control->max_line_descent;
906 gstring->height = gstring->line_ascent + gstring->line_descent;
908 if (control->orientation_reversed
911 /* We must adjust TAB width for RTL orientation. */
912 width = gstring->indent;
914 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
916 if (g->type == GLYPH_CHAR && g->c == '\t')
918 int this_width = tab_width - (width % tab_width);
920 if (g[1].type == GLYPH_PAD)
921 this_width -= g[1].width;
922 if (g[-1].type == GLYPH_PAD)
923 this_width -= g[-1].width;
926 gstring->width += this_width - g->width;
927 gstring->rbearing += this_width - g->width;
928 g->width = this_width;
939 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
940 MGlyphString *gstring, int from, int to,
941 int *from_idx, int *to_idx, int *to_x)
943 MGlyph *g = MGLYPH (1);
944 MDrawRegion region = (MDrawRegion) NULL;
945 MDrawControl *control = &gstring->control;
948 int cursor_bidi = control->cursor_bidi;
950 if (control->with_cursor && control->cursor_width)
952 if (gstring->from <= control->cursor_pos
953 && gstring->to > control->cursor_pos)
954 cursor_pos = control->cursor_pos;
956 && gstring->from <= control->cursor_pos - 1
957 && gstring->to > control->cursor_pos - 1)
958 prev_pos = control->cursor_pos - 1;
961 *from_idx = *to_idx = 0;
962 while (g->type != GLYPH_ANCHOR)
964 if (g->pos >= from && g->pos < to)
966 MGlyph *fromg = g, *cursor = NULL;
967 MRealizedFace *rface = g->rface;
969 int cursor_width = 0;
973 *from_idx = GLYPH_INDEX (g);
974 while (g->pos >= from && g->pos < to
975 && g->rface == rface)
978 if (g->type != GLYPH_BOX
979 && g->pos <= cursor_pos && g->to > cursor_pos)
982 cursor = g, cursor_x = x + width;
983 cursor_width += g->width;
988 && (control->as_image
989 || rface->face.property[MFACE_BACKGROUND] != Mnil
990 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
992 int this_x = x, this_width = width;
994 if (fromg->type == GLYPH_BOX)
995 this_x += fromg->width, this_width -= fromg->width;
996 if (g[-1].type == GLYPH_BOX)
997 this_width -= g[-1].width;
998 mwin__fill_space (frame, win, rface, 0,
999 this_x, y - gstring->text_ascent, this_width,
1000 gstring->text_ascent + gstring->text_descent,
1001 control->clip_region);
1008 rect.y = y - gstring->text_ascent;
1009 rect.height = gstring->text_ascent + gstring->text_descent;
1012 rect.width = ((control->cursor_width > 0
1013 && control->cursor_width < cursor_width)
1014 ? control->cursor_width : cursor_width);
1018 if (cursor->bidi_level % 2)
1019 rect.x += cursor_width - 1;
1022 mwin__fill_space (frame, win, rface, 1,
1023 rect.x, rect.y, rect.width, rect.height,
1024 control->clip_region);
1026 region = mwin__region_from_rect (&rect);
1028 mwin__region_add_rect (region, &rect);
1029 mwin__verify_region (frame, region);
1032 if (cursor->bidi_level % 2)
1035 rect.width = cursor_width < 4 ? cursor_width : 4;
1036 mwin__fill_space (frame, win, rface, 1,
1037 rect.x, rect.y, rect.width, rect.height,
1038 control->clip_region);
1039 mwin__region_add_rect (region, &rect);
1040 mwin__verify_region (frame, region);
1052 if (fromg->type != GLYPH_BOX
1053 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1056 cursor = fromg, cursor_x = x + temp_width;
1057 cursor_width += fromg->width;
1059 temp_width += fromg++->width;
1066 if (! (cursor->bidi_level % 2))
1067 rect.x += cursor_width - 1;
1068 rect.y = y - gstring->text_ascent;
1069 rect.height = gstring->text_ascent + gstring->text_descent;
1071 mwin__fill_space (frame, win, rface, 1,
1072 rect.x, rect.y, rect.width, rect.height,
1073 control->clip_region);
1075 region = mwin__region_from_rect (&rect);
1077 mwin__region_add_rect (region, &rect);
1078 mwin__verify_region (frame, region);
1079 rect.y += rect.height - 2;
1081 rect.width = cursor_width < 4 ? cursor_width : 4;
1082 if (! (cursor->bidi_level % 2))
1083 rect.x -= rect.width - 1;
1084 mwin__fill_space (frame, win, rface, 1,
1085 rect.x, rect.y, rect.width, rect.height,
1086 control->clip_region);
1087 mwin__region_add_rect (region, &rect);
1088 mwin__verify_region (frame, region);
1092 *to_idx = GLYPH_INDEX (g);
1102 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1103 MGlyphString *gstring, int from_idx, int to_idx,
1104 int reverse, MDrawRegion region)
1106 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1112 mwin__region_to_rect (region, &rect);
1115 while (g != gend && x + g->rbearing <= rect.x)
1118 width -= g++->width;
1119 while (! g->enabled && g != gend)
1123 rect.x += rect.width;
1124 if (rect.x < x + width)
1126 while (g != gend && x + width - gend[-1].width >= rect.x)
1128 width -= (--gend)->width;
1129 while (! gend->enabled && g != gend)
1133 while (gend[-1].to == gend->to) gend++;
1141 MRealizedFace *rface = g->rface;
1142 int width = g->width;
1143 MGlyph *from_g = g++;
1145 /* Handle the glyphs of the same type/face at once. */
1147 && g->type == from_g->type
1148 && g->rface == rface
1149 && (g->code < 0) == (from_g->code < 0)
1151 width += g++->width;
1153 if (from_g->type == GLYPH_CHAR)
1155 MFontDriver *driver;
1157 if (rface->rfont && from_g->code >= 0)
1158 driver = rface->rfont->driver;
1160 driver = mfont__driver_list[MFONT_TYPE_WIN];
1161 (driver->render) (win, x, y, gstring, from_g, g,
1164 else if (from_g->type == GLYPH_BOX)
1166 /* Draw the left or right side of a box. If
1167 from_g->lbearing is nonzero, this is the left side,
1168 else this is the right side. */
1169 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1172 if (from_g->type != GLYPH_BOX)
1175 mwin__draw_hline (frame, win, gstring, rface, reverse,
1176 x, y, width, region);
1179 /* Draw the top and bottom side of a box. */
1180 mwin__draw_box (frame, win, gstring, from_g,
1181 x, y, width, region);
1192 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1193 int *from_x, int *to_x)
1196 int left_idx = *left, right_idx = *right;
1197 int left_x, right_x, x;
1199 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1202 if (x + g->rbearing > 0)
1204 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1206 left_idx = GLYPH_INDEX (g);
1211 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1214 if (x - g->width + g->lbearing < 0)
1216 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1218 right_idx = GLYPH_INDEX (g) + 1;
1223 if (*left == left_idx && *right == right_idx)
1226 if (*left != left_idx)
1228 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1233 if (*right != right_idx)
1235 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1245 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1250 if (from <= gstring->from && to >= gstring->to)
1253 *rbearing = gstring->rbearing;
1254 return gstring->width;
1259 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1260 if (g->pos >= from && g->pos < to)
1262 if (rbearing && width + g->rbearing > *rbearing)
1263 *rbearing = width + g->rbearing;
1271 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1272 MGlyphString *gstring, int from, int to)
1274 MDrawControl *control = &gstring->control;
1276 MDrawRegion clip_region, cursor_region;
1277 int from_idx, to_idx;
1280 if (control->orientation_reversed)
1281 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1283 x += gstring->indent;
1285 /* At first, draw all glyphs without cursor. */
1286 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1287 &from_idx, &to_idx, &to_x);
1289 if (control->partial_update)
1292 rect.width = to_x - x;
1293 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1295 rect.y = y - gstring->line_ascent;
1296 rect.height = gstring->height;
1297 clip_region = mwin__region_from_rect (&rect);
1298 if (control->clip_region)
1299 mwin__intersect_region (clip_region, control->clip_region);
1302 clip_region = control->clip_region;
1305 clip_region = control->clip_region;
1307 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1312 mwin__intersect_region (cursor_region, clip_region);
1313 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1316 if (clip_region != control->clip_region)
1317 mwin__free_region (clip_region);
1319 mwin__free_region (cursor_region);
1323 static int gstring_num;
1326 free_gstring (void *object)
1328 MGlyphString *gstring = (MGlyphString *) object;
1331 free_gstring (gstring->next);
1332 if (gstring->size > 0)
1333 free (gstring->glyphs);
1339 static MGlyphString scratch_gstring;
1341 static MGlyphString *
1342 alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y)
1344 MGlyphString *gstring;
1346 if (pos == mt->nchars)
1348 gstring = &scratch_gstring;
1352 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1353 MLIST_INIT1 (gstring, glyphs, 128);
1357 gstring->top = gstring;
1359 gstring->control = *control;
1360 gstring->indent = gstring->width_limit = 0;
1361 if (control->format)
1362 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1364 gstring->width_limit = control->max_line_width;
1368 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1371 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1379 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1380 a width of glyphs for the character at I of GSTRING->mt. If I is
1381 not a beginning of a grapheme cluster, the corresponding element
1383 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1384 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1385 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1386 pos_width[g->pos - gstring->from] += g->width;
1387 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1389 if (pos_width[i] > 0)
1391 if (width + pos_width[i] > gstring->width_limit)
1394 width += pos_width[i];
1397 pos = gstring->from + i;
1398 if (gstring->control.line_break)
1400 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1401 gstring->from, gstring->to, 0, 0);
1402 if (pos <= gstring->from || pos >= gstring->to)
1405 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1406 layout_glyph_string (frame, gstring);
1410 /* Return a gstring that covers a character at POS. */
1412 static MGlyphString *
1413 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1415 MGlyphString *gstring = NULL;
1417 if (pos < mtext_nchars (mt))
1419 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1422 && ((prop->start != 0
1423 && mtext_ref_char (mt, prop->start - 1) != '\n')
1424 || (prop->end < mtext_nchars (mt)
1425 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1427 mtext_detach_property (prop);
1432 gstring = prop->val;
1433 if (memcmp (control, &gstring->control,
1434 (char *) (&control->with_cursor)
1435 - (char *) (control)))
1437 mtext_detach_property (prop);
1442 else if (! control->cursor_width)
1450 offset = mtext_character (mt, pos, 0, '\n');
1455 offset -= gstring->from;
1457 for (gst = gstring; gst; gst = gst->next)
1461 gst->from += offset;
1463 for (i = 0; i < gst->used; i++)
1465 gst->glyphs[i].pos += offset;
1466 gst->glyphs[i].to += offset;
1469 M17N_OBJECT_REF (gstring);
1474 int line = 0, y = 0;
1476 if (control->two_dimensional)
1478 beg = mtext_character (mt, pos, 0, '\n');
1483 end = mtext_nchars (mt) + (control->cursor_width != 0);
1490 gstring = alloc_gstring (mt, beg, control, line, y);
1491 compose_glyph_string (frame, mt, beg, end, gstring);
1492 layout_glyph_string (frame, gstring);
1494 if (control->two_dimensional
1495 && gstring->width_limit
1496 && gstring->width > gstring->width_limit)
1498 MGlyphString *gst = gstring;
1500 truncate_gstring (frame, mt, gst);
1501 while (gst->to < end)
1503 line++, y += gst->height;
1504 gst->next = alloc_gstring (mt, gst->from, control, line, y);
1505 gst->next->top = gstring;
1506 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1508 layout_glyph_string (frame, gst);
1509 if (gst->width <= gst->width_limit)
1511 truncate_gstring (frame, mt, gst);
1515 if (! control->disable_caching && pos < mtext_nchars (mt))
1517 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1518 MTEXTPROP_VOLATILE_STRONG);
1520 if (end > mtext_nchars (mt))
1521 end = mtext_nchars (mt);
1522 mtext_attach_property (mt, beg, end, prop);
1523 M17N_OBJECT_UNREF (prop);
1527 while (gstring->to <= pos)
1529 if (! gstring->next)
1531 gstring = gstring->next;
1533 gstring->control = *control;
1539 static MDrawControl control_noop;
1541 #define ASSURE_CONTROL(control) \
1543 control = &control_noop; \
1548 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1549 MText *mt, int from, int to,
1550 MDrawControl *control)
1552 MGlyphString *gstring;
1554 M_CHECK_POS_X (mt, from, -1);
1555 ASSURE_CONTROL (control);
1556 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1557 to = mtext_nchars (mt) + (control->cursor_width != 0);
1561 gstring = get_gstring (frame, mt, from, to, control);
1563 MERROR (MERROR_DRAW, -1);
1564 render_glyph_string (frame, win, x, y, gstring, from, to);
1568 y += gstring->line_descent;
1569 M17N_OBJECT_UNREF (gstring->top);
1570 gstring = get_gstring (frame, mt, from, to, control);
1571 y += gstring->line_ascent;
1572 render_glyph_string (frame, win, x, y, gstring, from, to);
1575 M17N_OBJECT_UNREF (gstring->top);
1582 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1588 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1589 if (g->pos <= pos && g->to > pos)
1594 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1595 if (g->pos <= pos && g->to > pos)
1602 /* for debugging... */
1606 dump_combining_code (int code)
1608 char *vallign = "tcbB";
1609 char *hallign = "lcr";
1615 if (COMBINING_BY_CLASS_P (code))
1616 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1617 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1618 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1619 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1620 off_x = COMBINING_CODE_OFF_X (code) - 128;
1622 sprintf (work + 2, "+%d", off_y);
1624 sprintf (work + 2, "%d", off_y);
1625 else if (off_x == 0)
1626 sprintf (work + 2, "-");
1627 p = work + strlen (work);
1629 sprintf (p, ">%d", off_x);
1631 sprintf (p, "<%d", -off_x);
1633 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1634 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1640 dump_gstring (MGlyphString *gstring, int indent)
1642 char *prefix = (char *) alloca (indent + 1);
1643 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1645 memset (prefix, 32, indent);
1648 fprintf (stderr, "(glyph-string");
1650 for (g = MGLYPH (0); g < last_g; g++)
1652 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1654 g - gstring->glyphs,
1655 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1656 : g->type == GLYPH_ANCHOR ? "ANC"
1657 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1658 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1659 dump_combining_code (g->combining_code),
1660 g->width, g->bidi_level);
1661 fprintf (stderr, ")");
1665 /* m17n-X internal APIs */
1670 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1672 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1673 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1675 Mlatin = msymbol ("latin");
1676 Minherited = msymbol ("inherited");
1678 McatCc = msymbol ("Cc");
1679 McatCf = msymbol ("Cf");
1681 MbidiR = msymbol ("R");
1682 MbidiAL = msymbol ("AL");
1683 MbidiRLE = msymbol ("RLE");
1684 MbidiRLO = msymbol ("RLO");
1685 MbidiBN = msymbol ("BN");
1686 MbidiS = msymbol ("S");
1688 fribidi_set_mirroring (TRUE);
1697 MLIST_FREE1 (&scratch_gstring, glyphs);
1701 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1705 /*** @addtogroup m17nDraw */
1710 @brief Draw an M-text on a window.
1712 The mdraw_text () function draws the text between $FROM and $TO of
1713 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1715 The appearance of the text (size, style, color, etc) is specified
1716 by the value of the text property whose key is @c Mface. If the
1717 M-text or a part of the M-text does not have such a text property,
1718 the default face of $FRAME is used.
1720 The font used to draw a character in the M-text is selected from
1721 the value of the fontset property of a face by the following
1726 <li> Search the text properties given to the character for the one
1727 whose key is @c Mcharset; its value should be either a symbol
1728 specifying a charset or Mnil. If the value is Mnil, proceed
1731 Otherwise, search the mapping table of the fontset for the
1732 charset. If no entry is found proceed to the next step. If
1733 an entry is found, use one of the fonts in the entry that has
1734 a glyph for the character and that matches best with the face
1735 properties. If no such font exists, proceed to the next
1738 <li> Get the character-property script of the character. If it is
1739 inherited, get the script property from the previous
1740 characters. If there is no previous character, or none of
1741 them has the script property other than inherited, proceed to
1744 Search the text properties given to the character for the one
1745 whose key is @c Mlanguage; its value should be either a
1746 symbol specifying a language or @c Mnil.
1748 Search the mapping table of the fontset for the combination
1749 of the script and language. If no entry is found, proceed to
1750 the next step. If an entry is found, use one of the fonts in
1751 the entry that has a glyph for the character and that matches
1752 best with the face properties. If no such font exists,
1753 proceed to the next step.
1755 <li> Search the fall-back table of the fontset for a font that has
1756 a glyph of the character. If such a font is found, use that
1761 If no font is found by the algorithm above, this function draws an
1762 empty box for the character.
1764 This function draws only the glyph foreground. To specify the
1765 background color, use mdraw_image_text () or
1766 mdraw_text_with_control ().
1768 This function is the counterpart of <tt>XDrawString ()</tt>,
1769 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1770 in the X Window System.
1773 If the operation was successful, mdraw_text () returns 0. If an
1774 error is detected, it returns -1 and assigns an error code to the
1775 external variable @c merror_code. */
1778 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òɽ¼¨¤¹¤ë
1780 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1781 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1784 ¥Ý¥¤¥ó¥¿ $RET_DESCENT ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢É½¼¨¤·¤¿¥Æ¥¥¹¥È¤Î¥Ç¥£¥»
1785 ¥ó¥È¤¬¤½¤³¤Ë³ÊǼ¤µ¤ì¤ë¡£
1787 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1788 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1789 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1790 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1792 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢$FACE ¤Î fontset ¥×¥í¥Ñ¥Æ¥£¤Î
1793 Ãͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1797 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1798 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤
1799 ¤º¤ì¤«¤Ç¤¢¤ë¡£¼¡¤Ë¥¡¼¤¬ @c Mscript ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1800 ¤³¤ÎÃͤϥ¹¥¯¥ê¥×¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£
1802 ¤É¤Á¤é¤â @c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1804 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤ò»È¤Ã
1805 ¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬
1806 ¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©
1807 ¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1809 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1810 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil
1811 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£@c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1813 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¸«¤Ä¤«¤Ã¤¿Ê¸»ú¥»¥Ã¥È»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã
1814 ¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©
1815 ¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê
1816 ¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1818 <li> ¸½ºß¤Îʸ»ú¼«¿È¤ò»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö
1819 ¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1823 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1824 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1826 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¿§¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë
1827 ¤Ï¡¢´Ø¿ô mdraw_image_text () ¤ò»È¤¦¤³¤È¡£
1829 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawString ()</tt>,
1830 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1833 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1834 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1836 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1843 mdraw_image_text () */
1846 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1847 MText *mt, int from, int to)
1849 MDrawControl control;
1851 memset (&control, 0, sizeof control);
1852 control.as_image = 0;
1853 return draw_text (frame, win, x, y, mt, from, to, &control);
1860 @brief Draw an M-text on a window as an image
1862 The mdraw_image_text () function draws the text between $FROM and
1863 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1864 coordinate ($X, $Y).
1866 The way to draw a text is the same as in mdraw_text () except that
1867 this function also draws the background with the color specified
1870 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1871 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1872 functions in the X Window System.
1875 If the operation was successful, mdraw_image_text () returns 0.
1876 If an error is detected, it returns -1 and assigns an error code
1877 to the external variable @c merror_code. */
1880 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯
1882 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1883 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1886 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1887 ¤Ï $FACE ¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1889 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1890 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1894 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1895 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1898 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1908 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1909 MText *mt, int from, int to)
1911 MDrawControl control;
1913 memset (&control, 0, sizeof control);
1914 control.as_image = 1;
1915 return draw_text (frame, win, x, y, mt, from, to, &control);
1921 @brief Draw an M-text on a window with fine control.
1923 The mdraw_text_with_control () function draws the text between
1924 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1925 coordinate ($X, $Y).
1927 The way to draw a text is the same as in mdraw_text () except that
1928 this function also follows what specified in the drawing control
1931 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1932 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1933 breaks lines and the following characters are drawn in the next
1934 line. See the documentation of the structure @ MDrawControl for
1938 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
1939 MText *mt, int from, int to, MDrawControl *control)
1941 return draw_text (frame, win, x, y, mt, from, to, control);
1947 @brief Compute text pixel width.
1949 The mdraw_text_extents () function computes the width of text
1950 between $FROM and $TO of M-text $MT when it is drawn on a window
1951 of frame $FRAME using the mdraw_text_with_control () function with
1952 the drawing control object $CONTROL.
1954 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
1955 the bounding box of character ink of the M-text, and stores the
1956 results in the members of the structure pointed to by
1957 $OVERALL_INK_RETURN. If the M-text has a face specifying a
1958 surrounding box, the box is included in the bounding box.
1960 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
1961 computes the bounding box that provides mininum spacing to other
1962 graphical features (such as surrounding box) for the M-text, and
1963 stores the results in the members of the structure pointed to by
1964 $OVERALL_LOGICAL_RETURN.
1966 If $OVERALL_LINE_RETURN is not @c NULL, this function also
1967 computes the bounding box that provides mininum spacing to the
1968 other M-text drawn, and stores the results in the members of the
1969 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
1970 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
1971 min_line_ascent, min_line_descent, max_line_ascent, and
1972 max_line_descent of $CONTROL are all zero.
1976 This function returns the width of the text to be drawn in the
1977 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
1978 text is drawn in multiple physical lines, it returns the width of
1979 the widest line. If an error occurs, it returns -1 and assigns an
1980 error code to the external variable @c merror_code. */
1983 @brief ¥Æ¥¥¹¥È¤ÎÉý¤ò·×»»¤¹¤ë
1985 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
1986 ¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
1988 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL °Ê³°¤Î¾ì¹ç¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥È
1989 Á´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢$OVERALL_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë
1990 ¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
1993 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפȤʤë¥Æ¥¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£¥¨¥é¡¼
1994 ¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
1997 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2004 mdraw_text_extents (MFrame *frame,
2005 MText *mt, int from, int to, MDrawControl *control,
2006 MDrawMetric *overall_ink_return,
2007 MDrawMetric *overall_logical_return,
2008 MDrawMetric *overall_line_return)
2010 MGlyphString *gstring;
2012 int width, rbearing;
2014 ASSURE_CONTROL (control);
2015 M_CHECK_POS_X (mt, from, -1);
2016 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2017 to = mtext_nchars (mt) + (control->cursor_width != 0);
2021 gstring = get_gstring (frame, mt, from, to, control);
2023 MERROR (MERROR_DRAW, -1);
2024 width = gstring_width (gstring, from, to, &rbearing);
2025 if (overall_ink_return)
2027 overall_ink_return->y = - gstring->physical_ascent;
2028 overall_ink_return->x = gstring->lbearing;
2030 if (overall_logical_return)
2032 overall_logical_return->y = - gstring->ascent;
2033 overall_logical_return->x = 0;
2035 if (overall_line_return)
2037 overall_line_return->y = - gstring->line_ascent;
2038 overall_line_return->x = gstring->lbearing;
2041 for (from = gstring->to; from < to; from = gstring->to)
2043 int this_width, this_rbearing;
2045 y += gstring->line_descent;
2046 M17N_OBJECT_UNREF (gstring->top);
2047 gstring = get_gstring (frame, mt, from, to, control);
2048 this_width = gstring_width (gstring, from, to, &this_rbearing);
2049 y += gstring->line_ascent;
2050 if (width < this_width)
2052 if (rbearing < this_rbearing)
2053 rbearing = this_rbearing;
2055 if (overall_ink_return)
2057 overall_ink_return->width = rbearing;
2058 overall_ink_return->height
2059 = y + gstring->physical_descent - overall_ink_return->y;
2061 if (overall_logical_return)
2063 overall_logical_return->width = width;
2064 overall_logical_return->height
2065 = y + gstring->descent - overall_logical_return->y;
2067 if (overall_line_return)
2069 overall_line_return->width = MAX (width, rbearing);
2070 overall_line_return->height
2071 = y + gstring->line_descent - overall_line_return->y;
2074 M17N_OBJECT_UNREF (gstring->top);
2081 @brief Compute the text dimensions of each character of M-text.
2083 The mdraw_text_per_char_extents () function computes the drawn
2084 metric of each character between $FROM and $TO of M-text $MT
2085 assuming that they are drawn on a window of frame $FRAME using the
2086 mdraw_text_with_control () function with the drawing control
2089 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2090 $LOGICAL_ARRAY_RETURN. Each successive element of
2091 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2092 ink and logical metrics of successive characters respectively,
2093 relative to the drawing origin of the M-text. The number of
2094 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2095 been set is returned to $NUM_CHARS_RETURN.
2097 If $ARRAY_SIZE is too small to return all metrics, the function
2098 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2099 Otherwise, it returns zero.
2101 If pointer $OVERALL_INK_RETURN an $OVERALL_LOGICAL_RETURN are not
2102 @c NULL, this function also computes the metrics of the overall
2103 text and stores the results in the members of the structure
2104 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2106 If $CONTROL->two_dimensional is nonzero, this function computes
2107 only the metrics of characters in the first line. */
2110 mdraw_text_per_char_extents (MFrame *frame,
2111 MText *mt, int from, int to,
2112 MDrawControl *control,
2113 MDrawMetric *ink_array_return,
2114 MDrawMetric *logical_array_return,
2116 int *num_chars_return,
2117 MDrawMetric *overall_ink_return,
2118 MDrawMetric *overall_logical_return)
2120 MGlyphString *gstring;
2124 ASSURE_CONTROL (control);
2125 *num_chars_return = to - from;
2126 if (array_size < *num_chars_return)
2128 if (overall_logical_return)
2129 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2130 if (overall_ink_return)
2131 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2133 M_CHECK_RANGE (mt, from, to, -1, 0);
2134 gstring = get_gstring (frame, mt, from, to, control);
2137 *num_chars_return = 0;
2141 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2142 if (g->pos >= from && g->pos < to)
2146 int width = g->width;
2147 int lbearing = g->lbearing;
2148 int rbearing = g->rbearing;
2149 int ascent = g->ascent;
2150 int descent = g->descent;
2151 int logical_ascent = g->rface->rfont->ascent;
2152 int logical_descent = g->rface->rfont->descent;
2154 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2156 if (lbearing < width + g->lbearing)
2157 lbearing = width + g->lbearing;
2158 if (rbearing < width + g->rbearing)
2159 rbearing = width + g->rbearing;
2161 if (ascent < g->ascent)
2163 if (descent < g->descent)
2164 descent = g->descent;
2171 ink_array_return[start - from].x = x + lbearing;
2172 ink_array_return[start - from].y = - ascent;
2173 ink_array_return[start - from].width = rbearing - lbearing;
2174 ink_array_return[start - from].height = ascent + descent;
2175 logical_array_return[start - from].x = x;
2176 logical_array_return[start - from].y = - logical_descent;
2177 logical_array_return[start - from].height
2178 = logical_ascent + logical_descent;
2179 logical_array_return[start - from].width = width;
2185 if (overall_ink_return)
2187 overall_ink_return->y = - gstring->line_ascent;
2188 overall_ink_return->x = gstring->lbearing;
2189 overall_ink_return->width = x - gstring->lbearing;
2190 overall_ink_return->height = gstring->height;
2192 if (overall_logical_return)
2194 overall_logical_return->y = - gstring->ascent;
2195 overall_logical_return->x = 0;
2196 overall_logical_return->width = x;
2197 overall_logical_return->height = gstring->ascent + gstring->descent;
2200 M17N_OBJECT_UNREF (gstring->top);
2207 @brief Return the character position nearest to the coordinates.
2209 The mdraw_coordinates_position () function checks which character
2210 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2211 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2212 mdraw_text_with_control () function with the drawing control
2213 object $CONTROL. Here, the character position means the number of
2214 characters that precede the character in question in $MT.
2216 $FRAME is used only to get the default face information.
2219 If the glyph image of a character covers coordinate ($X, $Y),
2220 mdraw_coordinates_position () returns the character position of
2222 If $Y is less than the minimum Y-coordinate of the drawn area, it
2223 returns $FROM.\n\n\n
2224 If $Y is greater than the maximum Y-coordinate of the drawn area,
2225 it returns $TO.\n\n\n
2226 If $Y fits in with the drawn area but $X is less than the minimum
2227 X-coordinate, it returns the character position of the first
2228 character drawn on the line $Y.\n\n\n
2229 If $Y fits in with the drawn area but $X is greater than the
2230 maximum X-coordinate, it returns the character position of the
2231 last character drawn on the line $Y. */
2234 @brief »ØÄꤷ¤¿ºÂɸ¤Ë¤¢¤ëʸ»ú¤Î°ÌÃÖ¤òÆÀ¤ë
2236 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢
2238 @li ´Ø¿ô mdraw_text () ¤ò»È¤Ã¤Æ
2239 @li M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
2240 @li ºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤Æ²¾¤ËÉÁ²è¤·¤¿¾ì¹ç
2242 ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ë¥Ù¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃÖ
2243 ¤È¤Ï¡¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç
2244 ¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2246 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2249 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2250 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2252 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2254 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2256 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2257 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2259 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2260 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2263 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2264 int x_offset, int y_offset, MDrawControl *control)
2266 MGlyphString *gstring;
2271 M_CHECK_POS_X (mt, from, -1);
2272 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2273 to = mtext_nchars (mt) + (control->cursor_width != 0);
2279 ASSURE_CONTROL (control);
2280 gstring = get_gstring (frame, mt, from, to, control);
2281 while (y + gstring->line_descent <= y_offset
2282 && gstring->to < to)
2285 y += gstring->line_descent;
2286 M17N_OBJECT_UNREF (gstring->top);
2287 gstring = get_gstring (frame, mt, from, to, control);
2288 y += gstring->line_ascent;
2291 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2292 if (! control->orientation_reversed)
2294 width = gstring->indent;
2295 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2296 if (g->pos >= from && g->pos < to)
2299 if (width > x_offset)
2305 width = - gstring->indent;
2306 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2307 if (g->pos >= from && g->pos < to)
2310 if (width < x_offset)
2315 M17N_OBJECT_UNREF (gstring->top);
2323 @brief Compute information about a glyph.
2325 The @c mdraw_glyph_info () function computes information about a
2326 glyph that covers a character at position $POS of the M-text $MT
2327 assuming that the text is drawn from the character at $FROM of $MT
2328 on a window of frame $FRAME using the mdraw_text_with_control ()
2329 function with the drawing control object $CONTROL.
2331 The information is stored in the members of $INFO. */
2339 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2340 MDrawControl *control, MDrawGlyphInfo *info)
2342 MGlyphString *gstring;
2346 M_CHECK_RANGE_X (mt, from, pos, -1);
2348 ASSURE_CONTROL (control);
2349 gstring = get_gstring (frame, mt, from, pos + 1, control);
2351 MERROR (MERROR_DRAW, -1);
2352 while (gstring->to <= pos)
2354 y += gstring->line_descent;
2355 M17N_OBJECT_UNREF (gstring->top);
2356 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2357 y += gstring->line_ascent;
2359 info->line_from = gstring->from;
2360 if (info->line_from < from)
2361 info->line_from = from;
2362 info->line_to = gstring->to;
2365 if (! control->orientation_reversed)
2367 info->x = gstring->indent;
2368 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2369 info->x += g->width;
2373 info->x = - gstring->indent;
2374 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2375 info->x -= g->width;
2376 while (g[-1].to == g->to)
2379 info->from = g->pos;
2381 info->this.x = g->lbearing;
2382 info->this.y = - gstring->line_ascent;
2383 info->this.height = gstring->height;
2384 if (g->rface->rfont)
2385 info->font = &g->rface->rfont->font;
2388 /* info->this.width is calculated later. */
2390 if (info->from > info->line_from)
2392 /* The logically previous glyph is on this line. */
2393 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2395 info->prev_from = g_tmp->pos;
2397 else if (info->line_from > 0)
2399 /* The logically previous glyph is on the previous line. */
2400 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2401 gstring->from, control);
2402 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2404 info->prev_from = g_tmp->pos;
2405 M17N_OBJECT_UNREF (gst->top);
2408 info->prev_from = -1;
2410 if (GLYPH_INDEX (g) > 1)
2411 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2412 else if (! control->orientation_reversed)
2414 if (info->line_from > 0)
2418 int p = gstring->from - 1;
2420 gst = get_gstring (frame, mt, p, gstring->from, control);
2421 g_tmp = gst->glyphs + (gst->used - 2);
2422 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2423 M17N_OBJECT_UNREF (gst->top);
2426 info->left_from = info->left_to = -1;
2430 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2434 int p = gstring->to;
2436 gst = get_gstring (frame, mt, p, p + 1, control);
2437 g_tmp = gst->glyphs + (gst->used - 2);
2438 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2439 M17N_OBJECT_UNREF (gst->top);
2442 info->left_from = info->left_to = -1;
2445 if (info->to < gstring->to)
2447 /* The logically next glyph is on this line. */
2448 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2450 info->next_to = g_tmp->to;
2452 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2454 /* The logically next glyph is on the next line. */
2456 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2457 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2459 info->next_to = g_tmp->to;
2460 M17N_OBJECT_UNREF (gst->top);
2465 for (info->this.width = (g++)->width;
2466 g->pos == pos && g->type != GLYPH_ANCHOR;
2467 info->this.width += (g++)->width);
2469 if (g->type != GLYPH_ANCHOR)
2470 info->right_from = g->pos, info->right_to = g->to;
2471 else if (! control->orientation_reversed)
2473 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2476 M17N_OBJECT_UNREF (gstring->top);
2477 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2479 info->right_from = g->pos, info->right_to = g->to;
2482 info->right_from = info->right_to = -1;
2486 if (info->line_from > 0)
2488 pos = gstring->from - 1;
2489 M17N_OBJECT_UNREF (gstring->top);
2490 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2492 info->right_from = g->pos, info->right_to = g->to;
2495 info->right_from = info->right_to = -1;
2498 M17N_OBJECT_UNREF (gstring->top);
2505 @brief Draw one or more textitems.
2507 The mdraw_text_items () function draws one or more M-texts on
2508 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2509 of the textitems to be drawn and $NITEMS is the number of
2510 textimtems in the array. */
2513 @brief textitem ¤òɽ¼¨¤¹¤ë
2515 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2516 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2517 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2520 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2524 MTextItem, mdraw_text (). */
2527 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2528 MDrawTextItem *items, int nitems)
2530 while (nitems-- > 0)
2533 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2535 mdraw_text_with_control (frame, win, x, y,
2536 items->mt, 0, mtext_nchars (items->mt),
2538 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2539 items->control, NULL, NULL, NULL);
2542 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2549 mdraw_default_line_break (MText *mt, int pos,
2550 int from, int to, int line, int y)
2552 int c = mtext_ref_char (mt, pos);
2555 if (c == ' ' || c == '\t')
2559 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2566 if (c == ' ' || c == '\t')
2569 c = mtext_ref_char (mt, pos);
2582 @brief Obtain per character dimension information.
2584 The mdraw_per_char_extents () function computes the text dimension
2585 of each character in M-text $MT. The faces given as text
2586 properties in $MT and the default face of frame $FRAME determine
2587 the fonts to draw the text. Each successive element in
2588 $ARRAY_RETURN is set to the drawn metrics of successive
2589 characters, which is relative to the origin of the drawing, and a
2590 rectangle for each character in $MT. The number of elements of
2591 $ARRAY_RETURN must be equal to or greater than the number of
2594 If pointer $OVERALL_RETURN is not @c NULL, this function also
2595 computes the extents of the overall text and stores the results in
2596 the members of the structure pointed to by $OVERALL_RETURN */
2599 @brief M-text ¤Îʸ»úËè¤Î¾ðÊó¤òÆÀ¤ë
2601 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2602 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2603 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤«¤é·èÄê
2604 ¤µ¤ì¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2605 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2606 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2607 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2609 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨
2610 ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·×»»¤ò $OVERALL_RETURN ¤Î»Ø¤¹Àè¤Ë³ÊǼ¤¹¤ë¡£
2612 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2615 mdraw_per_char_extents (MFrame *frame, MText *mt,
2616 MDrawMetric *array_return,
2617 MDrawMetric *overall_return)
2622 mdraw_clear_cache (MText *mt)
2624 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);