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
131 && g->combining_code)
135 if (! bidi_sensitive)
138 glyphs = alloca (sizeof (MGlyph) * gstring->used);
139 memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
141 visual = alloca (sizeof (FriBidiChar) * size);
142 indices = alloca (sizeof (FriBidiStrIndex) * size);
144 fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
145 #else /* not HAVE_FRIBIDI */
146 indices = alloca (sizeof (int) * size);
147 for (i = 0; i < size; i++)
153 for (j = i + 1; j < size && levels[j]; j++);
154 for (k = j--; i < k; i++, j--)
161 #endif /* not HAVE_FRIBIDI */
163 /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
164 starts from gstring->glyphs[IDX[N]].
166 INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
167 originally at LOGICAL[INDICES[N]]. */
169 for (i = 0, gidx = 1; i < size; i++)
173 int pos = glyphs[k].pos;
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
189 && (glyphs[k].pos == pos || glyphs[k].combining_code));
192 glyphs[k].bidi_level = levels[j];
193 *(MGLYPH (gidx)) = glyphs[k];
199 reorder_combining_chars (MGlyphString *gstring, int from, int to)
201 MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp;
207 for (g = gbeg; g != gend; g++)
208 if (COMBINING_CODE_CLASS (g->combining_code) > 0
209 && (COMBINING_CODE_CLASS (g[-1].combining_code)
210 > COMBINING_CODE_CLASS (g->combining_code)))
221 /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
222 displaying them on FRAME.
224 This function fills members <type>, <rface>, <c>, <pos>, <to>,
225 <code> of glyphs. The other members are filled by
226 layout_glyph_string. */
229 compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
230 MGlyphString *gstring)
232 MRealizedFace *default_rface = frame->rface;
233 int stop, face_change, language_change, charset_change;
236 MSymbol language = Mnil, script = Mnil, charset = Mnil;
237 MRealizedFace *rface = default_rface;
239 int size = gstring->control.fixed_width;
240 int ignore_formatting_char = gstring->control.ignore_formatting_char;
243 MLIST_RESET (gstring);
244 gstring->from = from;
246 /* At first generate glyphs while using the member <enabled> as a
247 flag for rface re-checking. */
250 /** Put anchor glyphs at the head and tail. */
251 g_tmp.type = GLYPH_ANCHOR;
252 g_tmp.pos = g_tmp.to = from;
254 APPEND_GLYPH (gstring, g_tmp);
256 stop = face_change = charset_change = language_change = pos = from;
257 g = gstring->glyphs + gstring->used;
264 if (pos < mtext_nchars (mt))
265 c = mtext_ref_char (mt, pos);
268 g_tmp.category = Mnil;
271 if (c == ' ' || c == '\n' || c == '\t')
272 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
274 g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
278 g_tmp.category = mchar_get_prop (c, Mcategory);
279 if (ignore_formatting_char && g_tmp.category == McatCf)
280 g_tmp.type = GLYPH_SPACE, this_script = Mnil;
283 g_tmp.type = GLYPH_CHAR;
284 this_script = (MSymbol) mchar_get_prop (c, Mscript);
285 if (this_script == Minherited)
286 this_script = script;
290 if (pos == stop || script != this_script || g->type != g_tmp.type)
292 if (non_ascii_found && g->type == GLYPH_CHAR)
293 while (g < gstring->glyphs + gstring->used)
294 g = mface__for_chars (script, language, charset,
295 g, gstring->glyphs + gstring->used, size);
296 g = gstring->glyphs + gstring->used;
298 script = this_script;
301 if (pos < mtext_nchars (mt) && pos == language_change)
303 language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
304 mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
306 if (pos < mtext_nchars (mt) && pos == charset_change)
308 charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
309 mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
311 if (pos < mtext_nchars (mt) && pos == face_change)
314 int num = mtext_get_prop_values (mt, pos, Mface,
315 (void **) faces, 64);
317 mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
319 ? mface__realize (frame, faces, num,
320 language, charset, size)
323 stop = language_change;
324 if (stop > charset_change)
325 stop = charset_change;
326 if (face_change < stop)
330 g_tmp.c = g_tmp.code = c;
337 else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
340 APPEND_GLYPH (gstring, g_tmp);
346 APPEND_GLYPH (gstring, g_tmp);
348 && gstring->control.two_dimensional)
354 /* Append an anchor glyph. */
355 g_tmp.type = GLYPH_ANCHOR;
357 g_tmp.code = MCHAR_INVALID_CODE;
358 g_tmp.pos = g_tmp.to = pos;
360 APPEND_GLYPH (gstring, g_tmp);
364 /* Next, run FLT if necessary. */
365 for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;)
369 if (this->type == GLYPH_CHAR && this->rface->rfont)
372 MGlyph *tmp = gstring->glyphs + i;
374 if (this->rface->rfont->layouter != Mnil)
376 while ((tmp->type == GLYPH_CHAR || tmp->type == GLYPH_SPACE)
377 && tmp->rface->rfont == this->rface->rfont
378 && tmp->code != MCHAR_INVALID_CODE)
380 i = mfont__flt_run (gstring, start, i,
381 this->rface->rfont->layouter,
382 this->rface->ascii_rface);
386 while (this->type == GLYPH_CHAR
389 && MSYMBOL_NAME (this->category)[0] == 'M'
390 && this->rface->rfont
391 && this->rface->rfont->layouter == Mnil)
393 int class = (int) mchar_get_prop (this->c,
396 = MAKE_COMBINING_CODE_BY_CLASS (class);
400 reorder_combining_chars (gstring, start, i);
408 /* At last, reorder glyphs visually if necessary. */
409 if (gstring->control.enable_bidi)
410 visual_order (gstring);
415 combining_code_from_class (int class)
420 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
421 else if (class == 200) /* below left attached */
422 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128);
423 else if (class == 202) /* below attached*/
424 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128);
425 else if (class == 204) /* below right attached */
426 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128);
427 else if (class == 208) /* left attached */
428 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128);
429 else if (class == 210) /* right attached */
430 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128);
431 else if (class == 212) /* above left attached */
432 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128);
433 else if (class == 214) /* above attached */
434 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128);
435 else if (class == 216) /* above right attached */
436 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128);
437 else if (class == 218) /* below left */
438 code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128);
439 else if (class == 220) /* below */
440 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
441 else if (class == 222) /* below right */
442 code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128);
443 else if (class == 224) /* left */
444 code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122);
445 else if (class == 226) /* right */
446 code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133);
447 else if (class == 228) /* above left */
448 code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128);
449 else if (class == 230) /* above */
450 code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128);
451 else if (class == 232) /* above right */
452 code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128);
453 else if (class == 233) /* double below */
454 code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128);
455 else if (class == 234) /* double above */
456 code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128);
457 else if (class == 240) /* iota subscript */
458 code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128);
460 code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128);
466 layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
468 int g_physical_ascent, g_physical_descent;
469 int g_width, g_lbearing, g_rbearing;
470 MGlyph *g = MGLYPH (from);
471 MGlyph *last_g = MGLYPH (to);
473 g_physical_ascent = gstring->physical_ascent;
474 g_physical_descent = gstring->physical_descent;
475 g_width = g_lbearing = g_rbearing = 0;
480 MRealizedFont *rfont = base->rface->rfont;
481 int size = rfont->font.property[MFONT_SIZE];
482 int width, lbearing, rbearing;
484 mfont__get_metric (rfont, base);
485 if (g == last_g || ! g->combining_code)
488 if (base->left_padding && base->lbearing < 0)
490 base->xoff = - base->lbearing;
491 base->width += base->xoff;
492 base->rbearing += base->xoff;
495 if (base->right_padding && base->rbearing > base->width)
497 base->width = base->rbearing;
499 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
500 rbearing = base->rbearing;
504 /* With combining glyphs. */
505 int left = -base->width;
507 int top = - base->ascent;
508 int bottom = base->descent;
509 int height = bottom - top;
510 int begin = base->pos;
515 lbearing = (base->lbearing < 0 ? base->lbearing : 0);
516 rbearing = base->rbearing;
518 while (g != last_g && g->combining_code)
520 int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
522 combining_code = g->combining_code;
523 if (COMBINING_BY_CLASS_P (combining_code))
524 g->combining_code = combining_code
525 = combining_code_from_class (COMBINING_CODE_CLASS
528 rfont = g->rface->rfont;
529 size = rfont->font.property[MFONT_SIZE];
530 off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
532 off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
534 base_x = COMBINING_CODE_BASE_X (combining_code);
535 base_y = COMBINING_CODE_BASE_Y (combining_code);
536 add_x = COMBINING_CODE_ADD_X (combining_code);
537 add_y = COMBINING_CODE_ADD_Y (combining_code);
541 else if (end < g->to)
544 mfont__get_metric (rfont, g);
545 g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
548 if (g->xoff + g->width > right)
549 right = g->xoff + g->width;
550 width = right - left;
551 if (g->xoff + g->lbearing < left + lbearing)
552 lbearing = g->xoff + g->lbearing - left;
553 if (g->xoff + g->rbearing > left + rbearing)
554 rbearing = g->xoff + g->rbearing - left;
557 g->yoff = top + height * base_y / 2;
561 g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
563 if (g->yoff - g->ascent < top)
564 top = g->yoff - g->ascent;
565 if (g->yoff + g->descent > bottom)
566 bottom = g->yoff + g->descent;
567 height = bottom - top;
573 base->ascent = - top;
574 base->descent = bottom;
575 if (left < - base->width)
577 base->xoff = - base->width - left;
578 base->width += base->xoff;
579 base->rbearing += base->xoff;
580 base->lbearing += base->xoff;
584 base->width += right;
585 base->rbearing += right;
586 base->right_padding = 1;
587 for (i = 1; base + i != g; i++)
588 base[i].xoff -= right;
591 for (i = 0; base + i != g; i++)
598 g_physical_ascent = MAX (g_physical_ascent, base->ascent);
599 g_physical_descent = MAX (g_physical_descent, base->descent);
600 g_lbearing = MIN (g_lbearing, g_width + lbearing);
601 g_rbearing = MAX (g_rbearing, g_width + rbearing);
602 g_width += base->width;
605 gstring->physical_ascent = g_physical_ascent;
606 gstring->physical_descent = g_physical_descent;
607 gstring->sub_width = g_width;
608 gstring->sub_lbearing = g_lbearing;
609 gstring->sub_rbearing = g_rbearing;
613 /** Decide the layout of glyphs in GSTRING. Space glyphs are handled
614 by this function directly. Character glyphs are handled by
615 layouter functions registered in font drivers.
617 This function fill-in all the remaining members of glyphs. */
620 layout_glyph_string (MFrame *frame, MGlyphString *gstring)
622 /* Default width of TAB. */
623 int tab_width = frame->space_width * (gstring->control.tab_width
624 ? gstring->control.tab_width : 8);
628 MDrawControl *control = &(gstring->control);
631 int box_line_height = 0;
633 gstring->ascent = gstring->descent = 0;
634 gstring->physical_ascent = gstring->physical_descent = 0;
635 gstring->width = gstring->lbearing = gstring->rbearing = 0;
639 while (g->type != GLYPH_ANCHOR)
641 if (box != g->rface->box)
643 int gidx = GLYPH_INDEX (g);
647 /* Insert the right side of the box. That glyph belongs
648 to the previous grapheme cluster. */
649 MGlyph box_glyph = g[-1];
651 box_glyph.type = GLYPH_BOX;
653 = (control->fixed_width
655 : box->inner_hmargin + box->width + box->outer_hmargin);
656 box_glyph.lbearing = 0;
657 box_glyph.rbearing = box_glyph.width;
659 box_glyph.right_padding = 1;
660 gstring->width += box_glyph.width;
661 gstring->rbearing += box_glyph.width;
662 INSERT_GLYPH (gstring, gidx, box_glyph);
669 /* Insert the left side of the box. That glyph belongs
670 to the following grapheme cluster. */
671 MGlyph box_glyph = *g;
672 int box_height = (box->width
673 + box->inner_vmargin + box->outer_vmargin);
675 if (box_line_height < box_height)
676 box_line_height = box_height;
677 box_glyph.type = GLYPH_BOX;
679 = (control->fixed_width
681 : box->inner_hmargin + box->width + box->outer_hmargin);
682 box_glyph.lbearing = 0;
683 box_glyph.rbearing = box_glyph.width;
685 box_glyph.left_padding = 1;
686 gstring->width += box_glyph.width;
687 gstring->rbearing += box_glyph.width;
688 INSERT_GLYPH (gstring, gidx, box_glyph);
694 if (g->type == GLYPH_CHAR)
696 MRealizedFace *rface = g->rface;
697 MRealizedFont *rfont = rface->rfont;
699 int from = GLYPH_INDEX (g);
701 for (g++; g->type == GLYPH_CHAR; g++)
702 if (! rfont != ! g->rface->rfont
703 || box != g->rface->box
704 || ((fromg->code == MCHAR_INVALID_CODE)
705 != (g->code == MCHAR_INVALID_CODE)))
707 if (rfont && fromg->code != MCHAR_INVALID_CODE)
710 int to = GLYPH_INDEX (g);
712 layout_glyphs (frame, gstring, from, to);
713 extra_width = - gstring->sub_lbearing;
715 && (GLYPH_INDEX (g) > 1
716 || control->align_head))
720 pad.type = GLYPH_PAD;
723 pad.width = pad.rbearing = extra_width;
724 INSERT_GLYPH (gstring, from, pad);
726 gstring->sub_lbearing = 0;
727 gstring->sub_width += extra_width;
728 gstring->sub_rbearing += extra_width;
730 g = MGLYPH (from - 1);
731 if (g->type == GLYPH_SPACE)
733 /* The pad just inserted is absorbed (maybe
734 partially) by the previous space while
735 keeping at least some space width. For the
736 moment, we use the arbitrary width 2-pixel.
737 Perhaps, it should be decided by the current
738 face, or a default value of the current
739 frame, which is, however, not yet
741 if (extra_width + 2 < g->width)
743 g->width -= extra_width;
747 extra_width -= g->width - 2;
750 gstring->width -= extra_width;
751 gstring->rbearing -= extra_width;
755 extra_width = gstring->sub_rbearing - gstring->sub_width;
759 if (g->type == GLYPH_SPACE && box == g->rface->box)
763 pad.type = GLYPH_PAD;
766 pad.width = pad.rbearing = extra_width;
767 INSERT_GLYPH (gstring, to, pad);
771 g[-1].width += extra_width;
772 gstring->sub_width += extra_width;
775 if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
776 gstring->lbearing = gstring->width + gstring->sub_lbearing;
777 if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
778 gstring->rbearing = gstring->width + gstring->sub_rbearing;
779 gstring->width += gstring->sub_width;
780 if (gstring->ascent < rface->ascent)
781 gstring->ascent = rface->ascent;
782 if (gstring->descent < rface->descent)
783 gstring->descent = rface->descent;
788 for (; fromg < g; fromg++)
790 if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
791 || (fromg->c >= 0x202A && fromg->c <= 0x202E))
792 fromg->width = fromg->rbearing = 1;
794 fromg->width = fromg->rbearing = rface->space_width;
795 fromg->xoff = fromg->lbearing = 0;
796 fromg->ascent = fromg->descent = 0;
797 gstring->width += fromg->width;
798 gstring->rbearing += fromg->width;
800 if (gstring->ascent < frame->rface->ascent)
801 gstring->ascent = frame->rface->ascent;
802 if (gstring->descent < frame->descent)
803 gstring->descent = frame->rface->descent;
806 else if (g->type == GLYPH_SPACE)
809 g->width = g->rface->space_width;
810 else if (g->c == '\n')
812 g->width = control->cursor_width;
815 if (control->cursor_bidi)
817 else if (g->width < 0)
818 g->width = g->rface->space_width;
821 else if (g->c == '\t')
823 g->width = tab_width - ((gstring->indent + gstring->width)
829 if (g[-1].type == GLYPH_PAD)
831 /* This space glyph absorbs (maybe partially) the
832 previous padding glyph. */
833 g->width -= g[-1].width;
835 /* But, keep at least some space width. For the
836 moment, we use the arbitrary width 2-pixel. */
839 g->rbearing = g->width;
840 gstring->width += g->width;
841 gstring->rbearing += g->width;
844 if (gstring->ascent < g->rface->ascent)
845 gstring->ascent = g->rface->ascent;
846 if (gstring->descent < g->rface->descent)
847 gstring->descent = g->rface->descent;
853 gstring->width += g->width;
854 gstring->rbearing += g->width;
861 /* Insert the right side of the box. */
862 int gidx = GLYPH_INDEX (g);
863 MGlyph box_glyph = g[-1];
865 box_glyph.type = GLYPH_BOX;
867 = (control->fixed_width
869 : box->inner_hmargin + box->width + box->outer_hmargin);
870 box_glyph.lbearing = 0;
871 box_glyph.rbearing = box_glyph.width;
873 box_glyph.right_padding = 1;
874 gstring->width += box_glyph.width;
875 gstring->rbearing += box_glyph.width;
876 INSERT_GLYPH (gstring, gidx, box_glyph);
879 gstring->text_ascent = gstring->ascent;
880 gstring->text_descent = gstring->descent;
881 if (gstring->text_ascent < gstring->physical_ascent)
882 gstring->text_ascent = gstring->physical_ascent;
883 if (gstring->text_descent < gstring->physical_descent)
884 gstring->text_descent = gstring->physical_descent;
885 gstring->line_ascent = gstring->text_ascent;
886 gstring->line_descent = gstring->text_descent;
887 if (box_line_height > 0)
889 gstring->line_ascent += box_line_height;
890 gstring->physical_ascent = gstring->line_ascent;
891 gstring->line_descent += box_line_height;
892 gstring->physical_descent = gstring->line_descent;
895 if (gstring->line_ascent < control->min_line_ascent)
896 gstring->line_ascent = control->min_line_ascent;
897 else if (control->max_line_ascent
898 && control->max_line_ascent > control->min_line_ascent
899 && gstring->line_ascent > control->max_line_ascent)
900 gstring->line_ascent = control->max_line_ascent;
902 if (gstring->line_descent < control->min_line_descent)
903 gstring->line_descent = control->min_line_descent;
904 else if (control->max_line_descent
905 && control->max_line_descent > control->min_line_descent
906 && gstring->line_descent > control->max_line_descent)
907 gstring->line_descent = control->max_line_descent;
908 gstring->height = gstring->line_ascent + gstring->line_descent;
910 if (control->orientation_reversed
913 /* We must adjust TAB width for RTL orientation. */
914 width = gstring->indent;
916 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
918 if (g->type == GLYPH_CHAR && g->c == '\t')
920 int this_width = tab_width - (width % tab_width);
922 if (g[1].type == GLYPH_PAD)
923 this_width -= g[1].width;
924 if (g[-1].type == GLYPH_PAD)
925 this_width -= g[-1].width;
928 gstring->width += this_width - g->width;
929 gstring->rbearing += this_width - g->width;
930 g->width = this_width;
941 draw_background (MFrame *frame, MDrawWindow win, int x, int y,
942 MGlyphString *gstring, int from, int to,
943 int *from_idx, int *to_idx, int *to_x)
945 MGlyph *g = MGLYPH (1);
946 MDrawRegion region = (MDrawRegion) NULL;
947 MDrawControl *control = &gstring->control;
950 int cursor_bidi = control->cursor_bidi;
952 if (control->with_cursor && control->cursor_width)
954 if (gstring->from <= control->cursor_pos
955 && gstring->to > control->cursor_pos)
956 cursor_pos = control->cursor_pos;
958 && gstring->from <= control->cursor_pos - 1
959 && gstring->to > control->cursor_pos - 1)
960 prev_pos = control->cursor_pos - 1;
963 *from_idx = *to_idx = 0;
964 while (g->type != GLYPH_ANCHOR)
966 if (g->pos >= from && g->pos < to)
968 MGlyph *fromg = g, *cursor = NULL;
969 MRealizedFace *rface = g->rface;
971 int cursor_width = 0;
975 *from_idx = GLYPH_INDEX (g);
976 while (g->pos >= from && g->pos < to
977 && g->rface == rface)
980 if (g->type != GLYPH_BOX
981 && g->pos <= cursor_pos && g->to > cursor_pos)
984 cursor = g, cursor_x = x + width;
985 cursor_width += g->width;
990 && (control->as_image
991 || rface->face.property[MFACE_BACKGROUND] != Mnil
992 || rface->face.property[MFACE_VIDEOMODE] == Mreverse))
994 int this_x = x, this_width = width;
996 if (fromg->type == GLYPH_BOX)
997 this_x += fromg->width, this_width -= fromg->width;
998 if (g[-1].type == GLYPH_BOX)
999 this_width -= g[-1].width;
1000 mwin__fill_space (frame, win, rface, 0,
1001 this_x, y - gstring->text_ascent, this_width,
1002 gstring->text_ascent + gstring->text_descent,
1003 control->clip_region);
1010 rect.y = y - gstring->text_ascent;
1011 rect.height = gstring->text_ascent + gstring->text_descent;
1014 rect.width = ((control->cursor_width > 0
1015 && control->cursor_width < cursor_width)
1016 ? control->cursor_width : cursor_width);
1020 if (cursor->bidi_level % 2)
1021 rect.x += cursor_width - 1;
1024 mwin__fill_space (frame, win, rface, 1,
1025 rect.x, rect.y, rect.width, rect.height,
1026 control->clip_region);
1028 region = mwin__region_from_rect (&rect);
1030 mwin__region_add_rect (region, &rect);
1031 mwin__verify_region (frame, region);
1034 if (cursor->bidi_level % 2)
1037 rect.width = cursor_width < 4 ? cursor_width : 4;
1038 mwin__fill_space (frame, win, rface, 1,
1039 rect.x, rect.y, rect.width, rect.height,
1040 control->clip_region);
1041 mwin__region_add_rect (region, &rect);
1042 mwin__verify_region (frame, region);
1054 if (fromg->type != GLYPH_BOX
1055 && fromg->pos <= prev_pos && fromg->to > prev_pos)
1058 cursor = fromg, cursor_x = x + temp_width;
1059 cursor_width += fromg->width;
1061 temp_width += fromg++->width;
1068 if (! (cursor->bidi_level % 2))
1069 rect.x += cursor_width - 1;
1070 rect.y = y - gstring->text_ascent;
1071 rect.height = gstring->text_ascent + gstring->text_descent;
1073 mwin__fill_space (frame, win, rface, 1,
1074 rect.x, rect.y, rect.width, rect.height,
1075 control->clip_region);
1077 region = mwin__region_from_rect (&rect);
1079 mwin__region_add_rect (region, &rect);
1080 mwin__verify_region (frame, region);
1081 rect.y += rect.height - 2;
1083 rect.width = cursor_width < 4 ? cursor_width : 4;
1084 if (! (cursor->bidi_level % 2))
1085 rect.x -= rect.width - 1;
1086 mwin__fill_space (frame, win, rface, 1,
1087 rect.x, rect.y, rect.width, rect.height,
1088 control->clip_region);
1089 mwin__region_add_rect (region, &rect);
1090 mwin__verify_region (frame, region);
1094 *to_idx = GLYPH_INDEX (g);
1104 render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width,
1105 MGlyphString *gstring, int from_idx, int to_idx,
1106 int reverse, MDrawRegion region)
1108 MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx);
1114 mwin__region_to_rect (region, &rect);
1117 while (g != gend && x + g->rbearing <= rect.x)
1120 width -= g++->width;
1121 while (! g->enabled && g != gend)
1125 rect.x += rect.width;
1126 if (rect.x < x + width)
1128 while (g != gend && x + width - gend[-1].width >= rect.x)
1130 width -= (--gend)->width;
1131 while (! gend->enabled && g != gend)
1135 while (gend[-1].to == gend->to) gend++;
1143 MRealizedFace *rface = g->rface;
1144 int width = g->width;
1145 MGlyph *from_g = g++;
1147 /* Handle the glyphs of the same type/face at once. */
1149 && g->type == from_g->type
1150 && g->rface == rface
1151 && (g->code < 0) == (from_g->code < 0)
1153 width += g++->width;
1155 if (from_g->type == GLYPH_CHAR)
1157 MFontDriver *driver;
1159 if (rface->rfont && from_g->code >= 0)
1160 driver = rface->rfont->driver;
1162 driver = mfont__driver_list[MFONT_TYPE_WIN];
1163 (driver->render) (win, x, y, gstring, from_g, g,
1166 else if (from_g->type == GLYPH_BOX)
1168 /* Draw the left or right side of a box. If
1169 from_g->lbearing is nonzero, this is the left side,
1170 else this is the right side. */
1171 mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
1174 if (from_g->type != GLYPH_BOX)
1177 mwin__draw_hline (frame, win, gstring, rface, reverse,
1178 x, y, width, region);
1181 /* Draw the top and bottom side of a box. */
1182 mwin__draw_box (frame, win, gstring, from_g,
1183 x, y, width, region);
1194 find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
1195 int *from_x, int *to_x)
1198 int left_idx = *left, right_idx = *right;
1199 int left_x, right_x, x;
1201 for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
1204 if (x + g->rbearing > 0)
1206 while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
1208 left_idx = GLYPH_INDEX (g);
1213 for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
1216 if (x - g->width + g->lbearing < 0)
1218 while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
1220 right_idx = GLYPH_INDEX (g) + 1;
1225 if (*left == left_idx && *right == right_idx)
1228 if (*left != left_idx)
1230 for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--)
1235 if (*right != right_idx)
1237 for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++)
1247 gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
1252 if (from <= gstring->from && to >= gstring->to)
1255 *rbearing = gstring->rbearing;
1256 return gstring->width;
1261 for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
1262 if (g->pos >= from && g->pos < to)
1264 if (rbearing && width + g->rbearing > *rbearing)
1265 *rbearing = width + g->rbearing;
1273 render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
1274 MGlyphString *gstring, int from, int to)
1276 MDrawControl *control = &gstring->control;
1278 MDrawRegion clip_region, cursor_region;
1279 int from_idx, to_idx;
1282 if (control->orientation_reversed)
1283 x -= gstring->indent + gstring_width (gstring, from, to, NULL);
1285 x += gstring->indent;
1287 /* At first, draw all glyphs without cursor. */
1288 cursor_region = draw_background (frame, win, x, y, gstring, from, to,
1289 &from_idx, &to_idx, &to_x);
1291 if (control->partial_update)
1294 rect.width = to_x - x;
1295 if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x))
1297 rect.y = y - gstring->line_ascent;
1298 rect.height = gstring->height;
1299 clip_region = mwin__region_from_rect (&rect);
1300 if (control->clip_region)
1301 mwin__intersect_region (clip_region, control->clip_region);
1304 clip_region = control->clip_region;
1307 clip_region = control->clip_region;
1309 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1314 mwin__intersect_region (cursor_region, clip_region);
1315 render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1318 if (clip_region != control->clip_region)
1319 mwin__free_region (clip_region);
1321 mwin__free_region (cursor_region);
1325 static int gstring_num;
1328 free_gstring (void *object)
1330 MGlyphString *gstring = (MGlyphString *) object;
1333 free_gstring (gstring->next);
1334 if (gstring->size > 0)
1335 free (gstring->glyphs);
1341 static MGlyphString scratch_gstring;
1343 static MGlyphString *
1344 alloc_gstring (MText *mt, int pos, MDrawControl *control, int line, int y)
1346 MGlyphString *gstring;
1348 if (pos == mt->nchars)
1350 gstring = &scratch_gstring;
1354 M17N_OBJECT (gstring, free_gstring, MERROR_DRAW);
1355 MLIST_INIT1 (gstring, glyphs, 128);
1359 gstring->top = gstring;
1361 gstring->control = *control;
1362 gstring->indent = gstring->width_limit = 0;
1363 if (control->format)
1364 (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit));
1366 gstring->width_limit = control->max_line_width;
1370 /* Truncate the line width of GSTRING to GSTRING->width_limit. */
1373 truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
1381 /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
1382 a width of glyphs for the character at I of GSTRING->mt. If I is
1383 not a beginning of a grapheme cluster, the corresponding element
1385 MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
1386 memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
1387 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1388 pos_width[g->pos - gstring->from] += g->width;
1389 for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
1391 if (pos_width[i] > 0)
1393 if (width + pos_width[i] > gstring->width_limit)
1396 width += pos_width[i];
1399 pos = gstring->from + i;
1400 if (gstring->control.line_break)
1402 pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
1403 gstring->from, gstring->to, 0, 0);
1404 if (pos <= gstring->from || pos >= gstring->to)
1407 compose_glyph_string (frame, mt, gstring->from, pos, gstring);
1408 layout_glyph_string (frame, gstring);
1412 /* Return a gstring that covers a character at POS. */
1414 static MGlyphString *
1415 get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control)
1417 MGlyphString *gstring = NULL;
1419 if (pos < mtext_nchars (mt))
1421 MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string);
1424 && ((prop->start != 0
1425 && mtext_ref_char (mt, prop->start - 1) != '\n')
1426 || (prop->end < mtext_nchars (mt)
1427 && mtext_ref_char (mt, prop->end - 1) != '\n')))
1429 mtext_detach_property (prop);
1434 gstring = prop->val;
1435 if (memcmp (control, &gstring->control,
1436 (char *) (&control->with_cursor)
1437 - (char *) (control)))
1439 mtext_detach_property (prop);
1444 else if (! control->cursor_width)
1452 offset = mtext_character (mt, pos, 0, '\n');
1457 offset -= gstring->from;
1459 for (gst = gstring; gst; gst = gst->next)
1463 gst->from += offset;
1465 for (i = 0; i < gst->used; i++)
1467 gst->glyphs[i].pos += offset;
1468 gst->glyphs[i].to += offset;
1471 M17N_OBJECT_REF (gstring);
1476 int line = 0, y = 0;
1478 if (control->two_dimensional)
1480 beg = mtext_character (mt, pos, 0, '\n');
1485 end = mtext_nchars (mt) + (control->cursor_width != 0);
1492 gstring = alloc_gstring (mt, beg, control, line, y);
1493 compose_glyph_string (frame, mt, beg, end, gstring);
1494 layout_glyph_string (frame, gstring);
1496 if (control->two_dimensional
1497 && gstring->width_limit
1498 && gstring->width > gstring->width_limit)
1500 MGlyphString *gst = gstring;
1502 truncate_gstring (frame, mt, gst);
1503 while (gst->to < end)
1505 line++, y += gst->height;
1506 gst->next = alloc_gstring (mt, gst->from, control, line, y);
1507 gst->next->top = gstring;
1508 compose_glyph_string (frame, mt, gst->to, end, gst->next);
1510 layout_glyph_string (frame, gst);
1511 if (gst->width <= gst->width_limit)
1513 truncate_gstring (frame, mt, gst);
1517 if (! control->disable_caching && pos < mtext_nchars (mt))
1519 MTextProperty *prop = mtext_property (M_glyph_string, gstring,
1520 MTEXTPROP_VOLATILE_STRONG);
1522 if (end > mtext_nchars (mt))
1523 end = mtext_nchars (mt);
1524 mtext_attach_property (mt, beg, end, prop);
1525 M17N_OBJECT_UNREF (prop);
1529 while (gstring->to <= pos)
1531 if (! gstring->next)
1533 gstring = gstring->next;
1535 gstring->control = *control;
1541 static MDrawControl control_noop;
1543 #define ASSURE_CONTROL(control) \
1545 control = &control_noop; \
1550 draw_text (MFrame *frame, MDrawWindow win, int x, int y,
1551 MText *mt, int from, int to,
1552 MDrawControl *control)
1554 MGlyphString *gstring;
1556 M_CHECK_POS_X (mt, from, -1);
1557 ASSURE_CONTROL (control);
1558 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
1559 to = mtext_nchars (mt) + (control->cursor_width != 0);
1563 gstring = get_gstring (frame, mt, from, to, control);
1565 MERROR (MERROR_DRAW, -1);
1566 render_glyph_string (frame, win, x, y, gstring, from, to);
1570 y += gstring->line_descent;
1571 M17N_OBJECT_UNREF (gstring->top);
1572 gstring = get_gstring (frame, mt, from, to, control);
1573 y += gstring->line_ascent;
1574 render_glyph_string (frame, win, x, y, gstring, from, to);
1577 M17N_OBJECT_UNREF (gstring->top);
1584 find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp)
1590 for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
1591 if (g->pos <= pos && g->to > pos)
1596 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
1597 if (g->pos <= pos && g->to > pos)
1604 /* for debugging... */
1608 dump_combining_code (int code)
1610 char *vallign = "tcbB";
1611 char *hallign = "lcr";
1617 if (COMBINING_BY_CLASS_P (code))
1618 code = combining_code_from_class (COMBINING_CODE_CLASS (code));
1619 work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
1620 work[1] = hallign[COMBINING_CODE_BASE_X (code)];
1621 off_y = COMBINING_CODE_OFF_Y (code) - 128;
1622 off_x = COMBINING_CODE_OFF_X (code) - 128;
1624 sprintf (work + 2, "+%d", off_y);
1626 sprintf (work + 2, "%d", off_y);
1627 else if (off_x == 0)
1628 sprintf (work + 2, "-");
1629 p = work + strlen (work);
1631 sprintf (p, ">%d", off_x);
1633 sprintf (p, "<%d", -off_x);
1635 p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
1636 p[1] = hallign[COMBINING_CODE_ADD_X (code)];
1642 dump_gstring (MGlyphString *gstring, int indent)
1644 char *prefix = (char *) alloca (indent + 1);
1645 MGlyph *g, *last_g = gstring->glyphs + gstring->used;
1647 memset (prefix, 32, indent);
1650 fprintf (stderr, "(glyph-string");
1652 for (g = MGLYPH (0); g < last_g; g++)
1654 "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
1656 g - gstring->glyphs,
1657 (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
1658 : g->type == GLYPH_ANCHOR ? "ANC"
1659 : g->type == GLYPH_BOX ? "BOX" : "CHR"),
1660 g->pos, g->to, g->c, g->code, (unsigned) g->rface,
1661 dump_combining_code (g->combining_code),
1662 g->width, g->bidi_level);
1663 fprintf (stderr, ")");
1667 /* m17n-X internal APIs */
1672 M_glyph_string = msymbol_as_managing_key (" glyph-string");
1674 memset (&scratch_gstring, 0, sizeof (scratch_gstring));
1675 MLIST_INIT1 (&scratch_gstring, glyphs, 3);
1677 Mlatin = msymbol ("latin");
1678 Minherited = msymbol ("inherited");
1680 McatCc = msymbol ("Cc");
1681 McatCf = msymbol ("Cf");
1683 MbidiR = msymbol ("R");
1684 MbidiAL = msymbol ("AL");
1685 MbidiRLE = msymbol ("RLE");
1686 MbidiRLO = msymbol ("RLO");
1687 MbidiBN = msymbol ("BN");
1688 MbidiS = msymbol ("S");
1690 fribidi_set_mirroring (TRUE);
1699 MLIST_FREE1 (&scratch_gstring, glyphs);
1703 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1707 /*** @addtogroup m17nDraw */
1712 @brief Draw an M-text on a window.
1714 The mdraw_text () function draws the text between $FROM and $TO of
1715 M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y).
1717 The appearance of the text (size, style, color, etc) is specified
1718 by the value of the text property whose key is @c Mface. If the
1719 M-text or a part of the M-text does not have such a text property,
1720 the default face of $FRAME is used.
1722 The font used to draw a character in the M-text is selected from
1723 the value of the fontset property of a face by the following
1728 <li> Search the text properties given to the character for the one
1729 whose key is @c Mcharset; its value should be either a symbol
1730 specifying a charset or Mnil. If the value is Mnil, proceed
1733 Otherwise, search the mapping table of the fontset for the
1734 charset. If no entry is found proceed to the next step. If
1735 an entry is found, use one of the fonts in the entry that has
1736 a glyph for the character and that matches best with the face
1737 properties. If no such font exists, proceed to the next
1740 <li> Get the character-property script of the character. If it is
1741 inherited, get the script property from the previous
1742 characters. If there is no previous character, or none of
1743 them has the script property other than inherited, proceed to
1746 Search the text properties given to the character for the one
1747 whose key is @c Mlanguage; its value should be either a
1748 symbol specifying a language or @c Mnil.
1750 Search the mapping table of the fontset for the combination
1751 of the script and language. If no entry is found, proceed to
1752 the next step. If an entry is found, use one of the fonts in
1753 the entry that has a glyph for the character and that matches
1754 best with the face properties. If no such font exists,
1755 proceed to the next step.
1757 <li> Search the fall-back table of the fontset for a font that has
1758 a glyph of the character. If such a font is found, use that
1763 If no font is found by the algorithm above, this function draws an
1764 empty box for the character.
1766 This function draws only the glyph foreground. To specify the
1767 background color, use mdraw_image_text () or
1768 mdraw_text_with_control ().
1770 This function is the counterpart of <tt>XDrawString ()</tt>,
1771 <tt>XmbDrawString ()</tt>, and <tt>XwcDrawString ()</tt> functions
1772 in the X Window System.
1775 If the operation was successful, mdraw_text () returns 0. If an
1776 error is detected, it returns -1 and assigns an error code to the
1777 external variable @c merror_code. */
1780 @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òɽ¼¨¤¹¤ë
1782 ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ
1783 ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò
1786 ¥Ý¥¤¥ó¥¿ $RET_DESCENT ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢É½¼¨¤·¤¿¥Æ¥¥¹¥È¤Î¥Ç¥£¥»
1787 ¥ó¥È¤¬¤½¤³¤Ë³ÊǼ¤µ¤ì¤ë¡£
1789 ¥Æ¥¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥¡¼¤¬ @c Mface
1790 ¤Ç¤¢¤ë¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï
1791 Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME
1792 ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£
1794 M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢$FACE ¤Î fontset ¥×¥í¥Ñ¥Æ¥£¤Î
1795 Ãͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
1799 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mlanguage ¤Ç¤¢
1800 ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤
1801 ¤º¤ì¤«¤Ç¤¢¤ë¡£¼¡¤Ë¥¡¼¤¬ @c Mscript ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£
1802 ¤³¤ÎÃͤϥ¹¥¯¥ê¥×¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£
1804 ¤É¤Á¤é¤â @c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1806 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤ò»È¤Ã
1807 ¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬
1808 ¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©
1809 ¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1811 <li> ¤½¤Îʸ»ú¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë
1812 ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil
1813 ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£@c Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1815 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¸«¤Ä¤«¤Ã¤¿Ê¸»ú¥»¥Ã¥È»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã
1816 ¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤ê¡¢¤«¤Ä¤½¤Î¥Õ¥©
1817 ¥ó¥È¤Ç¸½ºß¤Îʸ»ú¤¬É½¼¨¤Ç¤¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¤ò»È¤¦¡£¤½¤¦¤Ç¤Ê
1818 ¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£
1820 <li> ¸½ºß¤Îʸ»ú¼«¿È¤ò»È¤Ã¤Æ¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö
1821 ¥ë¤ò¤Ò¤¯¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
1825 °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú
1826 ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£
1828 ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¿§¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë
1829 ¤Ï¡¢´Ø¿ô mdraw_image_text () ¤ò»È¤¦¤³¤È¡£
1831 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawString ()</tt>,
1832 <tt>XmbDrawString ()</tt>, <tt>XwcDrawString ()</tt> ¤ËÁêÅö¤¹¤ë¡£
1835 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì
1836 ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1838 @latexonly \IPAlabel{mdraw_text} @endlatexonly */
1845 mdraw_image_text () */
1848 mdraw_text (MFrame *frame, MDrawWindow win, int x, int y,
1849 MText *mt, int from, int to)
1851 MDrawControl control;
1853 memset (&control, 0, sizeof control);
1854 control.as_image = 0;
1855 return draw_text (frame, win, x, y, mt, from, to, &control);
1862 @brief Draw an M-text on a window as an image
1864 The mdraw_image_text () function draws the text between $FROM and
1865 $TO of M-text $MT as image on window $WIN of frame $FRAME at
1866 coordinate ($X, $Y).
1868 The way to draw a text is the same as in mdraw_text () except that
1869 this function also draws the background with the color specified
1872 This function is the counterpart of <tt>XDrawImageString ()</tt>,
1873 <tt>XmbDrawImageString ()</tt>, and <tt>XwcDrawImageString ()</tt>
1874 functions in the X Window System.
1877 If the operation was successful, mdraw_image_text () returns 0.
1878 If an error is detected, it returns -1 and assigns an error code
1879 to the external variable @c merror_code. */
1882 @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯
1884 ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î
1885 ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥¥¹¥È¤ò²è
1888 ¥Æ¥¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç
1889 ¤Ï $FACE ¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£
1891 ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë <tt>XDrawImageString ()</tt>,
1892 <tt>XmbDrawImageString ()</tt>, <tt>XwcDrawImageString ()</tt> ¤Ë
1896 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
1897 ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ
1900 @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */
1910 mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y,
1911 MText *mt, int from, int to)
1913 MDrawControl control;
1915 memset (&control, 0, sizeof control);
1916 control.as_image = 1;
1917 return draw_text (frame, win, x, y, mt, from, to, &control);
1923 @brief Draw an M-text on a window with fine control.
1925 The mdraw_text_with_control () function draws the text between
1926 $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at
1927 coordinate ($X, $Y).
1929 The way to draw a text is the same as in mdraw_text () except that
1930 this function also follows what specified in the drawing control
1933 For instance, if <two_dimensional> of $CONTROL is nonzero, this
1934 function draw an M-text 2-dimensionally, i.e., newlines in M-text
1935 breaks lines and the following characters are drawn in the next
1936 line. See the documentation of the structure @ MDrawControl for
1940 mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
1941 MText *mt, int from, int to, MDrawControl *control)
1943 return draw_text (frame, win, x, y, mt, from, to, control);
1949 @brief Compute text pixel width.
1951 The mdraw_text_extents () function computes the width of text
1952 between $FROM and $TO of M-text $MT when it is drawn on a window
1953 of frame $FRAME using the mdraw_text_with_control () function with
1954 the drawing control object $CONTROL.
1956 If $OVERALL_INK_RETURN is not @c NULL, this function also computes
1957 the bounding box of character ink of the M-text, and stores the
1958 results in the members of the structure pointed to by
1959 $OVERALL_INK_RETURN. If the M-text has a face specifying a
1960 surrounding box, the box is included in the bounding box.
1962 If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also
1963 computes the bounding box that provides mininum spacing to other
1964 graphical features (such as surrounding box) for the M-text, and
1965 stores the results in the members of the structure pointed to by
1966 $OVERALL_LOGICAL_RETURN.
1968 If $OVERALL_LINE_RETURN is not @c NULL, this function also
1969 computes the bounding box that provides mininum spacing to the
1970 other M-text drawn, and stores the results in the members of the
1971 structure pointed to by $OVERALL_LINE_RETURN. This is a union of
1972 $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members
1973 min_line_ascent, min_line_descent, max_line_ascent, and
1974 max_line_descent of $CONTROL are all zero.
1978 This function returns the width of the text to be drawn in the
1979 unit of pixels. If $CONTROL->two_dimensional is nonzero and the
1980 text is drawn in multiple physical lines, it returns the width of
1981 the widest line. If an error occurs, it returns -1 and assigns an
1982 error code to the external variable @c merror_code. */
1985 @brief ¥Æ¥¥¹¥È¤ÎÉý¤ò·×»»¤¹¤ë
1987 ´Ø¿ô mdraw_text_extents () ¤Ï¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
1988 ¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£
1990 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL °Ê³°¤Î¾ì¹ç¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥¥¹¥È
1991 Á´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢$OVERALL_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë
1992 ¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£
1995 ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפȤʤë¥Æ¥¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£¥¨¥é¡¼
1996 ¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
1999 @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */
2006 mdraw_text_extents (MFrame *frame,
2007 MText *mt, int from, int to, MDrawControl *control,
2008 MDrawMetric *overall_ink_return,
2009 MDrawMetric *overall_logical_return,
2010 MDrawMetric *overall_line_return)
2012 MGlyphString *gstring;
2014 int width, rbearing;
2016 ASSURE_CONTROL (control);
2017 M_CHECK_POS_X (mt, from, -1);
2018 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2019 to = mtext_nchars (mt) + (control->cursor_width != 0);
2023 gstring = get_gstring (frame, mt, from, to, control);
2025 MERROR (MERROR_DRAW, -1);
2026 width = gstring_width (gstring, from, to, &rbearing);
2027 if (overall_ink_return)
2029 overall_ink_return->y = - gstring->physical_ascent;
2030 overall_ink_return->x = gstring->lbearing;
2032 if (overall_logical_return)
2034 overall_logical_return->y = - gstring->ascent;
2035 overall_logical_return->x = 0;
2037 if (overall_line_return)
2039 overall_line_return->y = - gstring->line_ascent;
2040 overall_line_return->x = gstring->lbearing;
2043 for (from = gstring->to; from < to; from = gstring->to)
2045 int this_width, this_rbearing;
2047 y += gstring->line_descent;
2048 M17N_OBJECT_UNREF (gstring->top);
2049 gstring = get_gstring (frame, mt, from, to, control);
2050 this_width = gstring_width (gstring, from, to, &this_rbearing);
2051 y += gstring->line_ascent;
2052 if (width < this_width)
2054 if (rbearing < this_rbearing)
2055 rbearing = this_rbearing;
2057 if (overall_ink_return)
2059 overall_ink_return->width = rbearing;
2060 overall_ink_return->height
2061 = y + gstring->physical_descent - overall_ink_return->y;
2063 if (overall_logical_return)
2065 overall_logical_return->width = width;
2066 overall_logical_return->height
2067 = y + gstring->descent - overall_logical_return->y;
2069 if (overall_line_return)
2071 overall_line_return->width = MAX (width, rbearing);
2072 overall_line_return->height
2073 = y + gstring->line_descent - overall_line_return->y;
2076 M17N_OBJECT_UNREF (gstring->top);
2083 @brief Compute the text dimensions of each character of M-text.
2085 The mdraw_text_per_char_extents () function computes the drawn
2086 metric of each character between $FROM and $TO of M-text $MT
2087 assuming that they are drawn on a window of frame $FRAME using the
2088 mdraw_text_with_control () function with the drawing control
2091 $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and
2092 $LOGICAL_ARRAY_RETURN. Each successive element of
2093 $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn
2094 ink and logical metrics of successive characters respectively,
2095 relative to the drawing origin of the M-text. The number of
2096 elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have
2097 been set is returned to $NUM_CHARS_RETURN.
2099 If $ARRAY_SIZE is too small to return all metrics, the function
2100 returns -1 and store the requested size in $NUM_CHARS_RETURN.
2101 Otherwise, it returns zero.
2103 If pointer $OVERALL_INK_RETURN an $OVERALL_LOGICAL_RETURN are not
2104 @c NULL, this function also computes the metrics of the overall
2105 text and stores the results in the members of the structure
2106 pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN.
2108 If $CONTROL->two_dimensional is nonzero, this function computes
2109 only the metrics of characters in the first line. */
2112 mdraw_text_per_char_extents (MFrame *frame,
2113 MText *mt, int from, int to,
2114 MDrawControl *control,
2115 MDrawMetric *ink_array_return,
2116 MDrawMetric *logical_array_return,
2118 int *num_chars_return,
2119 MDrawMetric *overall_ink_return,
2120 MDrawMetric *overall_logical_return)
2122 MGlyphString *gstring;
2126 ASSURE_CONTROL (control);
2127 *num_chars_return = to - from;
2128 if (array_size < *num_chars_return)
2130 if (overall_logical_return)
2131 memset (overall_logical_return, 0, sizeof (MDrawMetric));
2132 if (overall_ink_return)
2133 memset (overall_ink_return, 0, sizeof (MDrawMetric));
2135 M_CHECK_RANGE (mt, from, to, -1, 0);
2136 gstring = get_gstring (frame, mt, from, to, control);
2139 *num_chars_return = 0;
2143 for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
2144 if (g->pos >= from && g->pos < to)
2148 int width = g->width;
2149 int lbearing = g->lbearing;
2150 int rbearing = g->rbearing;
2151 int ascent = g->ascent;
2152 int descent = g->descent;
2153 int logical_ascent = g->rface->rfont->ascent;
2154 int logical_descent = g->rface->rfont->descent;
2156 for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
2158 if (lbearing < width + g->lbearing)
2159 lbearing = width + g->lbearing;
2160 if (rbearing < width + g->rbearing)
2161 rbearing = width + g->rbearing;
2163 if (ascent < g->ascent)
2165 if (descent < g->descent)
2166 descent = g->descent;
2173 ink_array_return[start - from].x = x + lbearing;
2174 ink_array_return[start - from].y = - ascent;
2175 ink_array_return[start - from].width = rbearing - lbearing;
2176 ink_array_return[start - from].height = ascent + descent;
2177 logical_array_return[start - from].x = x;
2178 logical_array_return[start - from].y = - logical_descent;
2179 logical_array_return[start - from].height
2180 = logical_ascent + logical_descent;
2181 logical_array_return[start - from].width = width;
2187 if (overall_ink_return)
2189 overall_ink_return->y = - gstring->line_ascent;
2190 overall_ink_return->x = gstring->lbearing;
2191 overall_ink_return->width = x - gstring->lbearing;
2192 overall_ink_return->height = gstring->height;
2194 if (overall_logical_return)
2196 overall_logical_return->y = - gstring->ascent;
2197 overall_logical_return->x = 0;
2198 overall_logical_return->width = x;
2199 overall_logical_return->height = gstring->ascent + gstring->descent;
2202 M17N_OBJECT_UNREF (gstring->top);
2209 @brief Return the character position nearest to the coordinates.
2211 The mdraw_coordinates_position () function checks which character
2212 is to be drawn at coordinate ($X, $Y) when the text between $FROM
2213 and $TO of M-text $MT is drawn at the coordinate (0, 0) using the
2214 mdraw_text_with_control () function with the drawing control
2215 object $CONTROL. Here, the character position means the number of
2216 characters that precede the character in question in $MT.
2218 $FRAME is used only to get the default face information.
2221 If the glyph image of a character covers coordinate ($X, $Y),
2222 mdraw_coordinates_position () returns the character position of
2224 If $Y is less than the minimum Y-coordinate of the drawn area, it
2225 returns $FROM.\n\n\n
2226 If $Y is greater than the maximum Y-coordinate of the drawn area,
2227 it returns $TO.\n\n\n
2228 If $Y fits in with the drawn area but $X is less than the minimum
2229 X-coordinate, it returns the character position of the first
2230 character drawn on the line $Y.\n\n\n
2231 If $Y fits in with the drawn area but $X is greater than the
2232 maximum X-coordinate, it returns the character position of the
2233 last character drawn on the line $Y. */
2236 @brief »ØÄꤷ¤¿ºÂɸ¤Ë¤¢¤ëʸ»ú¤Î°ÌÃÖ¤òÆÀ¤ë
2238 ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢
2240 @li ´Ø¿ô mdraw_text () ¤ò»È¤Ã¤Æ
2241 @li M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò
2242 @li ºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤Æ²¾¤ËÉÁ²è¤·¤¿¾ì¹ç
2244 ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ë¥Ù¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃÖ
2245 ¤È¤Ï¡¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç
2246 ¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£
2248 $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£
2251 ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô
2252 mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2254 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£
2256 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£
2258 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â
2259 ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£
2261 ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â
2262 Â礤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */
2265 mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to,
2266 int x_offset, int y_offset, MDrawControl *control)
2268 MGlyphString *gstring;
2273 M_CHECK_POS_X (mt, from, -1);
2274 if (to > mtext_nchars (mt) + (control->cursor_width != 0))
2275 to = mtext_nchars (mt) + (control->cursor_width != 0);
2281 ASSURE_CONTROL (control);
2282 gstring = get_gstring (frame, mt, from, to, control);
2283 while (y + gstring->line_descent <= y_offset
2284 && gstring->to < to)
2287 y += gstring->line_descent;
2288 M17N_OBJECT_UNREF (gstring->top);
2289 gstring = get_gstring (frame, mt, from, to, control);
2290 y += gstring->line_ascent;
2293 /* Accumulate width of glyphs in WIDTH until it exceeds X. */
2294 if (! control->orientation_reversed)
2296 width = gstring->indent;
2297 for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
2298 if (g->pos >= from && g->pos < to)
2301 if (width > x_offset)
2307 width = - gstring->indent;
2308 for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
2309 if (g->pos >= from && g->pos < to)
2312 if (width < x_offset)
2317 M17N_OBJECT_UNREF (gstring->top);
2325 @brief Compute information about a glyph.
2327 The @c mdraw_glyph_info () function computes information about a
2328 glyph that covers a character at position $POS of the M-text $MT
2329 assuming that the text is drawn from the character at $FROM of $MT
2330 on a window of frame $FRAME using the mdraw_text_with_control ()
2331 function with the drawing control object $CONTROL.
2333 The information is stored in the members of $INFO. */
2341 mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos,
2342 MDrawControl *control, MDrawGlyphInfo *info)
2344 MGlyphString *gstring;
2348 M_CHECK_RANGE_X (mt, from, pos, -1);
2350 ASSURE_CONTROL (control);
2351 gstring = get_gstring (frame, mt, from, pos + 1, control);
2353 MERROR (MERROR_DRAW, -1);
2354 while (gstring->to <= pos)
2356 y += gstring->line_descent;
2357 M17N_OBJECT_UNREF (gstring->top);
2358 gstring = get_gstring (frame, mt, gstring->to, pos + 1, control);
2359 y += gstring->line_ascent;
2361 info->line_from = gstring->from;
2362 if (info->line_from < from)
2363 info->line_from = from;
2364 info->line_to = gstring->to;
2367 if (! control->orientation_reversed)
2369 info->x = gstring->indent;
2370 for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
2371 info->x += g->width;
2375 info->x = - gstring->indent;
2376 for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
2377 info->x -= g->width;
2378 while (g[-1].to == g->to)
2381 info->from = g->pos;
2383 info->this.x = g->lbearing;
2384 info->this.y = - gstring->line_ascent;
2385 info->this.height = gstring->height;
2386 if (g->rface->rfont)
2387 info->font = &g->rface->rfont->font;
2390 /* info->this.width is calculated later. */
2392 if (info->from > info->line_from)
2394 /* The logically previous glyph is on this line. */
2395 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
2397 info->prev_from = g_tmp->pos;
2399 else if (info->line_from > 0)
2401 /* The logically previous glyph is on the previous line. */
2402 MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1,
2403 gstring->from, control);
2404 MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
2406 info->prev_from = g_tmp->pos;
2407 M17N_OBJECT_UNREF (gst->top);
2410 info->prev_from = -1;
2412 if (GLYPH_INDEX (g) > 1)
2413 info->left_from = g[-1].pos, info->left_to = g[-1].to;
2414 else if (! control->orientation_reversed)
2416 if (info->line_from > 0)
2420 int p = gstring->from - 1;
2422 gst = get_gstring (frame, mt, p, gstring->from, control);
2423 g_tmp = gst->glyphs + (gst->used - 2);
2424 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2425 M17N_OBJECT_UNREF (gst->top);
2428 info->left_from = info->left_to = -1;
2432 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2436 int p = gstring->to;
2438 gst = get_gstring (frame, mt, p, p + 1, control);
2439 g_tmp = gst->glyphs + (gst->used - 2);
2440 info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
2441 M17N_OBJECT_UNREF (gst->top);
2444 info->left_from = info->left_to = -1;
2447 if (info->to < gstring->to)
2449 /* The logically next glyph is on this line. */
2450 MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
2452 info->next_to = g_tmp->to;
2454 else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2456 /* The logically next glyph is on the next line. */
2458 MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
2459 MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
2461 info->next_to = g_tmp->to;
2462 M17N_OBJECT_UNREF (gst->top);
2467 for (info->this.width = (g++)->width;
2468 g->pos == pos && g->type != GLYPH_ANCHOR;
2469 info->this.width += (g++)->width);
2471 if (g->type != GLYPH_ANCHOR)
2472 info->right_from = g->pos, info->right_to = g->to;
2473 else if (! control->orientation_reversed)
2475 if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
2478 M17N_OBJECT_UNREF (gstring->top);
2479 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2481 info->right_from = g->pos, info->right_to = g->to;
2484 info->right_from = info->right_to = -1;
2488 if (info->line_from > 0)
2490 pos = gstring->from - 1;
2491 M17N_OBJECT_UNREF (gstring->top);
2492 gstring = get_gstring (frame, mt, pos, pos + 1, control);
2494 info->right_from = g->pos, info->right_to = g->to;
2497 info->right_from = info->right_to = -1;
2500 M17N_OBJECT_UNREF (gstring->top);
2507 @brief Draw one or more textitems.
2509 The mdraw_text_items () function draws one or more M-texts on
2510 window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array
2511 of the textitems to be drawn and $NITEMS is the number of
2512 textimtems in the array. */
2515 @brief textitem ¤òɽ¼¨¤¹¤ë
2517 ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼
2518 ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï
2519 ɽ¼¨¤¹¤Ù¤¥Æ¥¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î
2522 @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */
2526 MTextItem, mdraw_text (). */
2529 mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
2530 MDrawTextItem *items, int nitems)
2532 while (nitems-- > 0)
2535 mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface,
2537 mdraw_text_with_control (frame, win, x, y,
2538 items->mt, 0, mtext_nchars (items->mt),
2540 x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt),
2541 items->control, NULL, NULL, NULL);
2544 mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface);
2551 mdraw_default_line_break (MText *mt, int pos,
2552 int from, int to, int line, int y)
2554 int c = mtext_ref_char (mt, pos);
2557 if (c == ' ' || c == '\t')
2561 && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t'))
2568 if (c == ' ' || c == '\t')
2571 c = mtext_ref_char (mt, pos);
2584 @brief Obtain per character dimension information.
2586 The mdraw_per_char_extents () function computes the text dimension
2587 of each character in M-text $MT. The faces given as text
2588 properties in $MT and the default face of frame $FRAME determine
2589 the fonts to draw the text. Each successive element in
2590 $ARRAY_RETURN is set to the drawn metrics of successive
2591 characters, which is relative to the origin of the drawing, and a
2592 rectangle for each character in $MT. The number of elements of
2593 $ARRAY_RETURN must be equal to or greater than the number of
2596 If pointer $OVERALL_RETURN is not @c NULL, this function also
2597 computes the extents of the overall text and stores the results in
2598 the members of the structure pointed to by $OVERALL_RETURN */
2601 @brief M-text ¤Îʸ»úËè¤Î¾ðÊó¤òÆÀ¤ë
2603 ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2604 ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
2605 »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤«¤é·èÄê
2606 ¤µ¤ì¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
2607 ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
2608 ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
2609 ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
2611 ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ¼¨
2612 ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·×»»¤ò $OVERALL_RETURN ¤Î»Ø¤¹Àè¤Ë³ÊǼ¤¹¤ë¡£
2614 @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */
2617 mdraw_per_char_extents (MFrame *frame, MText *mt,
2618 MDrawMetric *array_return,
2619 MDrawMetric *overall_return)
2624 mdraw_clear_cache (MText *mt)
2626 mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string);