X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fdraw.c;h=f5b23cf2fb1302c9081604e7ee9457a504c7650c;hb=15a6499fb848caba6a48d2051f868d0844fbc88e;hp=070c8def3e2ce099167cde579b8439f580deb539;hpb=c4b6399ce280d86cdb04c3209c3424940a36e0c8;p=m17n%2Fm17n-lib.git diff --git a/src/draw.c b/src/draw.c index 070c8de..f5b23cf 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,5 +1,5 @@ /* draw.c -- drawing module. - Copyright (C) 2003, 2004 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO112 @@ -17,7 +17,7 @@ You should have received a copy of the GNU Lesser General Public License along with the m17n library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 02111-1307, USA. */ /***en @@ -31,7 +31,7 @@ appearance of M-texts, i.e. font size, color, underline, etc. The drawing format of M-texts can be controlled in a variety of - ways, which provides powerful 2-dimensional layouting + ways, which provides powerful 2-dimensional layout facility. */ /***ja @@ -40,12 +40,11 @@ m17n-gui API ¤Ë¤Ï¡¢M-text ¤òɽ¼¨¤¹¤ë¤¿¤á¤Î´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡£ - ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face ¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å - ¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É - ¤¨¤â face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£ + ɽ¼¨¤ËÍѤ¤¤é¤ì¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤È face + ¤Î¥×¥í¥Ñ¥Æ¥£¤Ë´ð¤Å¤¤¤Æ¼«Æ°Åª¤Ë·èÄꤵ¤ì¤ë¡£¤Þ¤¿¡¢¥Õ¥©¥ó¥È¤Î¥µ¥¤¥º¤ä¿§¤ä²¼Àþ¤Ê¤É¤Î¸«±É¤¨¤â + face ¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£ - M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤­¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆó¼¡ - ¸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤­¤ë¡£ + M-text ¤ÎÉÁ²è¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¿ÍͤÊÊýË¡¤ÇÀ©¸æ¤Ç¤­¤ë¤Î¤Ç¡¢¶¯ÎϤÊÆ󼡸µ¥ì¥¤¥¢¥¦¥Èµ¡Ç½¤¬¼Â¸½¤Ç¤­¤ë¡£ */ /*=*/ @@ -65,8 +64,10 @@ #include "m17n-misc.h" #include "internal.h" #include "symbol.h" +#include "mtext.h" #include "textprop.h" #include "internal-gui.h" +#include "internal-flt.h" #include "face.h" #include "font.h" @@ -80,10 +81,14 @@ static MSymbol M_glyph_string; /* Special scripts */ -static MSymbol Mlatin, Minherited; +static MSymbol Mcommon; /* Special categories */ static MSymbol McatCc, McatCf; +static MCharTable *linebreak_table; +static MSymbol M_break_at_space, M_break_at_word, M_break_at_any; +static MSymbol M_kinsoku_bol, M_kinsoku_eol; + /* Glyph-string composer. */ @@ -93,211 +98,405 @@ static MSymbol MbidiRLE; static MSymbol MbidiRLO; static MSymbol MbidiBN; static MSymbol MbidiS; +static MSymbol MbidiNSM; -static void -visual_order (MGlyphString *gstring) +static int +analyse_bidi_level (MGlyphString *gstring) { int len = gstring->used - 2; - MGlyph *glyphs; int bidi_sensitive = gstring->control.orientation_reversed; + int max_level; MGlyph *g; int i; #ifdef HAVE_FRIBIDI - FriBidiCharType base = (gstring->control.orientation_reversed - ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR); + FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR; FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len); - FriBidiChar *visual; - FriBidiStrIndex *indices; FriBidiLevel *levels; + FriBidiStrIndex *indices; #else /* not HAVE_FRIBIDI */ int *logical = alloca (sizeof (int) * len); - int *indices; char *levels = alloca (len); + + memset (levels, 0, sizeof (int) * len); #endif /* not HAVE_FRIBIDI */ for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++) { - MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category); - - if (bidi == MbidiR || bidi == MbidiAL - || bidi == MbidiRLE || bidi == MbidiRLO) + if (! bidi_sensitive +#ifndef HAVE_FRIBIDI + || 1 +#endif /* not HAVE_FRIBIDI */ + ) { - bidi_sensitive = 1; + MSymbol bidi = (MSymbol) mchar_get_prop (g->g.c, Mbidi_category); + + if (bidi == MbidiR || bidi == MbidiAL + || bidi == MbidiRLE || bidi == MbidiRLO) + { + bidi_sensitive = 1; +#ifndef HAVE_FRIBIDI + levels[i] = 1; +#endif /* not HAVE_FRIBIDI */ + } #ifndef HAVE_FRIBIDI - levels[i] = 1; + else if (bidi == MbidiNSM && i > 0 && levels[i - 1]) + levels[i] = 1; #endif /* not HAVE_FRIBIDI */ } - logical[i] = g->c; + logical[i] = g->g.c; } if (! bidi_sensitive) - return; + return 0; - glyphs = alloca (sizeof (MGlyph) * gstring->used - 2); - memcpy (glyphs, gstring->glyphs + 1, (sizeof (MGlyph) * gstring->used - 2)); #ifdef HAVE_FRIBIDI - visual = alloca (sizeof (FriBidiChar) * len); - indices = alloca (sizeof (FriBidiStrIndex) * len); - levels = alloca (sizeof (FriBidiLevel) * len); + levels = alloca (sizeof (FriBidiLevel) * (len + 1)); + indices = alloca (sizeof (FriBidiStrIndex) * (len + 1)); - fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels); -#else /* not HAVE_FRIBIDI */ - indices = alloca (sizeof (int) * len); - for (i = 0; i < len; i++) + fribidi_log2vis (logical, len, &base, NULL, NULL, indices, levels); +#endif /* not HAVE_FRIBIDI */ + + MGLYPH (0)->bidi_level = 0; + max_level = 0; + for (g = MGLYPH (1), i = 0; i < len; g++, i++) + { + g->bidi_level = levels[i]; + if (max_level < g->bidi_level) + max_level = g->bidi_level; + } + MGLYPH (i)->bidi_level = 0; + return max_level; +} + +static void +visual_order (MGlyphString *gstring) +{ + MGlyph *glyphs = alloca (sizeof (MGlyph) * gstring->used); + int i, j, gidx; + + memcpy (glyphs, gstring->glyphs, sizeof (MGlyph) * gstring->used); + + for (i = gidx = 0; i < gstring->used - 1; gidx++) { - if (levels[i]) + int level = glyphs[i].bidi_level; + + gstring->glyphs[gidx] = glyphs[i]; + glyphs[i].rface = NULL; + + if (level % 2) { - int j, k; + int prev_level = glyphs[i - 1].bidi_level; - for (j = i + 1; j < len && levels[j]; j++); - for (k = j--; i < k; i++, j--) - indices[i] = j; - i--; + if (prev_level == level) + i--; + else if (prev_level > level) + { + for (; glyphs[i - 1].bidi_level > level; i--); + if (glyphs[i].bidi_level % 2) + for (level = glyphs[i].bidi_level; + glyphs[i + 1].bidi_level == level; i++); + } + else + for (i++; ! glyphs[i].rface; i++); } else - indices[i] = i; - } -#endif /* not HAVE_FRIBIDI */ + { + int next_level = glyphs[i + 1].bidi_level; + + if (next_level == level) + i++; + else if (next_level > level) + { + for (; glyphs[i + 1].bidi_level > level; i++); + if ((glyphs[i].bidi_level % 2) == 0) + for (level = glyphs[i].bidi_level; + glyphs[i - 1].bidi_level == level; i--); + } + else + { + int save = i + 1; - for (i = 0; i < len; i++) + for (i--; glyphs[i].bidi_level >= level; i--); + if (! glyphs[i].rface) + for (i = save; ! glyphs[i].rface; i++); + } + } + } + for (i = 1; i < gstring->used - 1; i++) { - int j = indices[i]; + MGlyph *g = gstring->glyphs + i; - g = MGLYPH (j + 1); - if (i != j) - *g = glyphs[i]; - g->bidi_level = levels[i]; -#ifdef HAVE_FRIBIDI - if (visual[j] != logical[i]) + for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++); + if (j > i) { - /* Mirrored. */ - g->c = visual[j]; - if (g->rface->rfont) - g->code = mfont__encode_char (g->rface->rfont, g->c); + memcpy (glyphs + i, gstring->glyphs + i, + sizeof (MGlyph) * (j - i + 1)); + for (; i <= j; i++) + g[j - i] = glyphs[i]; + i--; } -#endif /* HAVE_FRIBIDI */ } } -static void -reorder_combining_chars (MGlyphString *gstring, int from, int to) +static MSymbol +font_id (MFLTFont *font) { - MGlyph *g, *gbeg = MGLYPH (from + 1), *gend = MGLYPH (to), temp; - int reordered = 1; - - while (reordered) + return ((MFLTFontForRealized *) font)->rfont->id; +} + +static int +run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface) +{ + MRealizedFont *rfont = rface->rfont; + MSymbol layouter = rface->layouter; + MFLTGlyphString flt_gstr; + MFLTFontForRealized font; + MFLT *flt; + int from_pos = MGLYPH (from)->g.from; + int len = to - from; + int catcode; + int i; + + flt = mflt_get (layouter); + flt_gstr.glyph_size = sizeof (MGlyph); + flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs); + flt_gstr.used = gstring->used; + flt_gstr.allocated = gstring->size; + flt_gstr.r2l = 0; + font.font.family = mfont_get_prop (rfont->font, Mfamily); + font.font.x_ppem = rfont->x_ppem; + font.font.y_ppem = rfont->y_ppem; + font.font.get_glyph_id = mfont__get_glyph_id; + font.font.get_metrics = mfont__get_metrics; + font.font.check_otf = rfont->driver->check_otf; + font.font.drive_otf = rfont->driver->drive_otf; + font.font.internal = NULL; + font.rfont = rfont; + mflt_font_id = font_id; + mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature; + mflt_try_otf = rfont->driver->try_otf; + for (i = 0; i < 3; i++) { - reordered = 0; - for (g = gbeg; g != gend; g++) - if (COMBINING_CODE_CLASS (g->combining_code) > 0 - && (COMBINING_CODE_CLASS (g[-1].combining_code) - > COMBINING_CODE_CLASS (g->combining_code))) - { - reordered = 1; - temp = *g; - *g = g[-1]; - g[-1] = temp; - } + to = mflt_run (&flt_gstr, from, to, &font.font, flt); + if (to != -2) + break; + APPEND_GLYPH (gstring, *MGLYPH (0)); + APPEND_GLYPH (gstring, *MGLYPH (0)); + gstring->used -= 2; } -} + if (from + len != to) + gstring->used += to - (from + len); + for (i = from, catcode = -1; i < to; i++) + { + MGlyph *g = MGLYPH (i); + + g->g.from += from_pos - from; + g->g.to += from_pos - from + 1; + g->g.xadv >>= 6; + g->g.yadv >>= 6; + g->g.ascent >>= 6; + g->g.descent >>= 6; + g->g.lbearing >>= 6; + g->g.rbearing >>= 6; + g->g.xoff >>= 6; + g->g.yoff >>= 6; + g->rface = rface; + if (catcode < 0 || g->g.from != g[-1].g.from) + { + MSymbol category = mchar_get_prop (g->g.c, Mcategory); + catcode = (category == McatCf + ? GLYPH_CATEGORY_FORMATTER + : category != Mnil && MSYMBOL_NAME (category)[0] == 'M' + ? GLYPH_CATEGORY_MODIFIER + : GLYPH_CATEGORY_NORMAL); + } + g->category = catcode; + } + return to; +} /** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for displaying them on FRAME. - This function fills members , , , , , - of glyphs. The other members are filled by - layout_glyph_string. */ + This function fills these members: + pos, to, c, code, rface, bidi_level, categories, type, combining_code + The other members are filled by layout_glyph_string. */ static void compose_glyph_string (MFrame *frame, MText *mt, int from, int to, MGlyphString *gstring) { MRealizedFace *default_rface = frame->rface; - int stop, face_change, language_change, charset_change; - MGlyph g_tmp, *g; + int stop, face_change, language_change, charset_change, font_change; + MGlyph g_tmp, *g, *last_g; int pos; MSymbol language = Mnil, script = Mnil, charset = Mnil; MSymbol non_latin_script = Mnil; MRealizedFace *rface = default_rface; + MRealizedFont *rfont; int size = gstring->control.fixed_width; + int max_bidi_level = 0; int i; - int last; MLIST_RESET (gstring); gstring->from = from; - /* At first generate glyphs while using the member as a - flag for rface re-checking. */ + /* At first generate glyphs with , , , , + and members.*/ INIT_GLYPH (g_tmp); /** Put anchor glyphs at the head and tail. */ g_tmp.type = GLYPH_ANCHOR; - g_tmp.pos = g_tmp.to = from; - g_tmp.c = 0; + g_tmp.g.from = g_tmp.g.to = from; APPEND_GLYPH (gstring, g_tmp); - - stop = face_change = charset_change = language_change = pos = from; - last = 0; + stop = face_change = font_change = pos = from; while (1) { int c; - MSymbol this_script; + MSymbol category; + + if (pos == stop) + { + if (pos == to) + break; + if (pos < mtext_nchars (mt)) + { + MFont *font = rface->font; + MFace *faces[64]; + int num; + + if (pos == font_change) + { + font = mtext_get_prop (mt, pos, Mfont); + mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0); + if (font_change == mtext_nchars (mt)) + font_change++; + } + if (pos == face_change) + { + num = mtext_get_prop_values (mt, pos, Mface, + (void **) faces, 64); + mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1); + if (face_change == mtext_nchars (mt)) + face_change++; + } + else + { + faces[0] = &rface->face; + num = 1; + } + rface = mface__realize (frame, faces, num, size, font); + } + else + rface = default_rface; + stop = to; + if (stop > font_change) + stop = font_change; + if (stop > face_change) + stop = face_change; + } if (pos < mtext_nchars (mt)) c = mtext_ref_char (mt, pos); else c = '\n'; - g_tmp.category = mchar_get_prop (c, Mcategory); - if (c < 0x100) + g_tmp.type + = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR; + g_tmp.g.c = c; + g_tmp.g.from = pos++; + g_tmp.g.to = pos; + g_tmp.rface = rface; + category = mchar_get_prop (c, Mcategory); + if (category == McatCf) + g_tmp.category = GLYPH_CATEGORY_FORMATTER; + else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M') + g_tmp.category = GLYPH_CATEGORY_MODIFIER; + else + g_tmp.category = GLYPH_CATEGORY_NORMAL; + + if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR) { - /* Short cut for the obvious case. */ - g_tmp.type = (c == ' ' || c == '\n' || c == '\t' - ? GLYPH_SPACE : GLYPH_CHAR); - this_script = (MSYMBOL_NAME (g_tmp.category)[0] == 'L' - ? Mlatin : Mnil); + MGlyph ctrl[2]; + + ctrl[0] = ctrl[1] = g_tmp; + ctrl[0].g.c = '^'; + ctrl[1].g.c = c < ' ' ? c + 0x40 : '?'; + APPEND_GLYPH (gstring, ctrl[0]); + APPEND_GLYPH (gstring, ctrl[1]); } else + APPEND_GLYPH (gstring, g_tmp); + if (c == '\n' && gstring->control.two_dimensional) + break; + } + /* Append an anchor glyph. */ + INIT_GLYPH (g_tmp); + g_tmp.type = GLYPH_ANCHOR; + g_tmp.g.from = g_tmp.g.to = pos; + APPEND_GLYPH (gstring, g_tmp); + gstring->to = pos; + + if (gstring->control.enable_bidi) + max_bidi_level = analyse_bidi_level (gstring); + + /* The next loop is to change each member for non-ASCII + characters if necessary. */ + stop = charset_change = language_change = from; + rfont = default_rface->rfont; + for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + { + int c = g->g.c; + MSymbol this_script; + + if (c < 0x100) + /* Short cut for the obvious case. */ + this_script = Mlatin; + else { - g_tmp.type = GLYPH_CHAR; this_script = (MSymbol) mchar_get_prop (c, Mscript); - if (this_script == Minherited || this_script == Mnil) - this_script = script; - if (this_script == Mnil) + if (this_script == Minherited || this_script == Mcommon) + { + if (g > MGLYPH (1)) + { + MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory); + + if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z') + this_script = script; + } + } + if (this_script == Mcommon && non_latin_script) this_script = non_latin_script; - if (this_script == Mnil) + if (this_script == Mcommon) { /* Search forward for a character that explicitly specifies a non-latin script. */ - int c1; MSymbol sym; + MGlyph *g1; - for (i = pos + 1; i < to; i++) - if ((c1 = mtext_ref_char (mt, i)) >= 0x100 - && (sym = mchar_get_prop (c1, Mscript)) != Mnil + for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++) + if (g1->g.c >= 0x100 + && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon && sym != Minherited) { this_script = sym; break; } } + if (this_script == Minherited || this_script == Mcommon) + this_script = (MSymbol) mchar_get_prop (c, Mblock); } - if (pos == stop || script != this_script - || MGLYPH (last)->type != g_tmp.type) + pos = g->g.from; + if (pos == stop || script != this_script || g->rface->rfont != rfont) { - g = MGLYPH (last); - if (g->type != GLYPH_ANCHOR) - while (g < gstring->glyphs + gstring->used) - g = mface__for_chars (script == Mnil ? Mlatin : script, - language, charset, - g, gstring->glyphs + gstring->used, size); - if (pos == to) - break; - last = gstring->used; + while (last_g < g) + last_g = mface__for_chars (script, language, charset, + last_g, g, size); script = this_script; if (script != Mnil && script != Mlatin) non_latin_script = script; + rfont = g->rface->ascii_rface->rfont; if (pos == stop) { if (pos < mtext_nchars (mt) && pos == language_change) @@ -312,63 +511,20 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0); } - if (pos < mtext_nchars (mt) && pos == face_change) - { - MFace *faces[64]; - int num = mtext_get_prop_values (mt, pos, Mface, - (void **) faces, 64); - - mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1); - rface = (num > 0 - ? mface__realize (frame, faces, num, - language, charset, size) - : default_rface); - } stop = to; if (stop > language_change) stop = language_change; if (stop > charset_change) stop = charset_change; - if (face_change < stop) - stop = face_change; } } - - g_tmp.c = c; - g_tmp.pos = pos++; - g_tmp.to = pos; - g_tmp.rface = rface; - - if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR) - { - MGlyph ctrl[2]; - - ctrl[0] = ctrl[1] = g_tmp; - ctrl[0].c = '^'; - ctrl[1].c = c < ' ' ? c + 0x40 : '?'; - mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size); - APPEND_GLYPH (gstring, ctrl[0]); - APPEND_GLYPH (gstring, ctrl[1]); - } - else - APPEND_GLYPH (gstring, g_tmp); - if (c == '\n' - && gstring->control.two_dimensional) - break; } + while (last_g < g) + last_g = mface__for_chars (script, language, charset, last_g, g, size); - /* Append an anchor glyph. */ - g_tmp.type = GLYPH_ANCHOR; - g_tmp.c = 0; - g_tmp.code = MCHAR_INVALID_CODE; - g_tmp.pos = g_tmp.to = pos; - g_tmp.rface = NULL; - APPEND_GLYPH (gstring, g_tmp); - - gstring->to = pos; - - /* Next, run FLT if necessary. */ - for (i = 1, g = MGLYPH (i); g->type != GLYPH_ANCHOR;) + /* The next loop is to run FLT or perform the default combining if + necessary. */ + for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;) { MGlyph *this = g; @@ -376,53 +532,49 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, { int start = i++; - if (this->rface->rfont->layouter != Mnil) + if (this->rface->layouter != Mnil) { - MGlyph *prev; - unsigned code; + MGlyph *prev = MGLYPH (start - 1); - for (prev = MGLYPH (start - 1); - (prev->type == GLYPH_CHAR - && prev->category == McatCf - && (code = mfont__encode_char (this->rface->rfont, prev->c) - != MCHAR_INVALID_CODE)); - start--, prev--) - prev->code = code; + while (prev->type == GLYPH_CHAR + && prev->category == GLYPH_CATEGORY_FORMATTER + && (mfont__encode_char (NULL, (MFont *) this->rface->rfont, + NULL, prev->g.c) + != MCHAR_INVALID_CODE)) + { + prev->rface->rfont = this->rface->rfont; + start--, prev--; + } for (g++; (g->type == GLYPH_CHAR + && g->rface->layouter == this->rface->layouter && (g->rface->rfont == this->rface->rfont - || (g->category == McatCf - && ((code = mfont__encode_char (this->rface->rfont, - g->c)) + || (g->category == GLYPH_CATEGORY_FORMATTER + && (mfont__encode_char (NULL, + (MFont *) this->rface->rfont, + NULL, g->g.c) != MCHAR_INVALID_CODE)))); i++, g++) - if (g->rface->rfont != this->rface->rfont) - { - g->rface->rfont = this->rface->rfont; - g->code = code; - } - i = mfont__flt_run (gstring, start, i, this->rface); + g->rface->rfont = this->rface->rfont; + i = run_flt (gstring, start, i, this->rface); } else { - while (this->type == GLYPH_CHAR - && this->c >= 0x100 - && this->category - && MSYMBOL_NAME (this->category)[0] == 'M' - && this->rface->rfont - && this->rface->rfont->layouter == Mnil) + g++; + while (g->type == GLYPH_CHAR + && g->g.c >= 0x100 + && g->category == GLYPH_CATEGORY_MODIFIER + && g->rface->rfont + && g->rface->layouter == Mnil) + i++, g++; + if (start + 1 < i) { - int class = (int) mchar_get_prop (this->c, - Mcombining_class); - this->combining_code - = MAKE_COMBINING_CODE_BY_CLASS (class); - i++, this++; + this->rface->layouter = Mcombining; + run_flt (gstring, start, i, this->rface); } - if (start + 1 < i) - reorder_combining_chars (gstring, start, i); - if (this->type == GLYPH_ANCHOR) - break; + else + mfont__get_metric (gstring, start, i); } g = MGLYPH (i); } @@ -431,248 +583,39 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, } /* At last, reorder glyphs visually if necessary. */ - if (gstring->control.enable_bidi) + if (max_bidi_level > 0) visual_order (gstring); } - -static int -combining_code_from_class (int class) -{ - int code; - - if (class < 200) - code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128); - else if (class == 200) /* below left attached */ - code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128); - else if (class == 202) /* below attached*/ - code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128); - else if (class == 204) /* below right attached */ - code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128); - else if (class == 208) /* left attached */ - code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128); - else if (class == 210) /* right attached */ - code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128); - else if (class == 212) /* above left attached */ - code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128); - else if (class == 214) /* above attached */ - code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128); - else if (class == 216) /* above right attached */ - code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128); - else if (class == 218) /* below left */ - code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128); - else if (class == 220) /* below */ - code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128); - else if (class == 222) /* below right */ - code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128); - else if (class == 224) /* left */ - code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122); - else if (class == 226) /* right */ - code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133); - else if (class == 228) /* above left */ - code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128); - else if (class == 230) /* above */ - code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128); - else if (class == 232) /* above right */ - code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128); - else if (class == 233) /* double below */ - code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128); - else if (class == 234) /* double above */ - code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128); - else if (class == 240) /* iota subscript */ - code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128); - else /* unknown */ - code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128); - return code; -} - +typedef struct { + int width, lbearing, rbearing; +} MSubTextExtents; static void -layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to) +layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to, + MSubTextExtents *extents) { int g_physical_ascent, g_physical_descent; - int g_width, g_lbearing, g_rbearing; MGlyph *g = MGLYPH (from); MGlyph *last_g = MGLYPH (to); - int i; g_physical_ascent = gstring->physical_ascent; g_physical_descent = gstring->physical_descent; - g_width = g_lbearing = g_rbearing = 0; - - for (i = from; i < to;) - { - if ( MGLYPH (i)->otf_encoded) - i++; - else - { - int j = i++; - - while (i < to && ! MGLYPH (i)->otf_encoded) i++; - mfont__get_metric (gstring, j, i); - } - } + extents->width = extents->lbearing = extents->rbearing = 0; - while (g < last_g) + for (g = MGLYPH (from); g < last_g; g++) { - MGlyph *base = g++; - MRealizedFont *rfont = base->rface->rfont; - int size = rfont->font.property[MFONT_SIZE]; - int width, lbearing, rbearing; - - if (base->bidi_sensitive && (base->bidi_level % 2)) - { - MGlyph *g1 = base, temp; - - base->bidi_sensitive = 0; - while (g->bidi_sensitive && (g->bidi_level % 2)) - g++->bidi_sensitive = 0; - while (g1 < g) - temp = *g1, *g1++ = *g, *g-- = temp; - g = base + 1; - } - - if (g == last_g || ! g->combining_code) - { - /* No combining. */ - if (base->width == 0 && GLYPH_INDEX (base) > from) - { - MGlyph *prev = base - 1; - - if (base->pos < prev->pos) - prev->pos = base->pos; - else - base->pos = prev->pos; - if (base->to > prev->to) - prev->to = base->to; - else - base->to = prev->to; - } - - if (base->left_padding && base->lbearing < 0) - { - base->xoff = - base->lbearing; - base->width += base->xoff; - base->rbearing += base->xoff; - base->lbearing = 0; - } - if (base->right_padding && base->rbearing > base->width) - { - base->width = base->rbearing; - } - lbearing = (base->xoff + base->lbearing < 0 - ? base->xoff + base->lbearing : 0); - rbearing = base->xoff + base->rbearing; - } - else - { - /* With combining glyphs. */ - int left = -base->width; - int right = 0; - int top = - base->ascent; - int bottom = base->descent; - int height = bottom - top; - int begin = base->pos; - int end = base->to; - int i; - - width = base->width; - lbearing = (base->lbearing < 0 ? base->lbearing : 0); - rbearing = base->rbearing; - - while (g != last_g && g->combining_code) - { - int combining_code, base_x, base_y, add_x, add_y, off_x, off_y; - - combining_code = g->combining_code; - if (COMBINING_BY_CLASS_P (combining_code)) - g->combining_code = combining_code - = combining_code_from_class (COMBINING_CODE_CLASS - (combining_code)); - - rfont = g->rface->rfont; - size = rfont->font.property[MFONT_SIZE]; - off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128) - / 1000); - off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128) - / 1000); - base_x = COMBINING_CODE_BASE_X (combining_code); - base_y = COMBINING_CODE_BASE_Y (combining_code); - add_x = COMBINING_CODE_ADD_X (combining_code); - add_y = COMBINING_CODE_ADD_Y (combining_code); - - if (begin > g->pos) - begin = g->pos; - else if (end < g->to) - end = g->to; - - g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x; - if (g->xoff < left) - left = g->xoff; - if (g->xoff + g->width > right) - right = g->xoff + g->width; - width = right - left; - if (g->xoff + g->lbearing < left + lbearing) - lbearing = g->xoff + g->lbearing - left; - if (g->xoff + g->rbearing > left + rbearing) - rbearing = g->xoff + g->rbearing - left; - - if (base_y < 3) - g->yoff = top + height * base_y / 2; - else - g->yoff = 0; - if (add_y < 3) - g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent; - g->yoff -= off_y; - if (g->yoff - g->ascent < top) - top = g->yoff - g->ascent; - if (g->yoff + g->descent > bottom) - bottom = g->yoff + g->descent; - height = bottom - top; - - g->width = 0; - g++; - } - - base->ascent = - top; - base->descent = bottom; - base->lbearing = lbearing; - base->rbearing = rbearing; - if (left < - base->width) - { - base->xoff = - base->width - left; - base->width += base->xoff; - base->rbearing += base->xoff; - base->lbearing += base->xoff; - } - if (right > 0) - { - base->width += right; - base->rbearing += right; - base->right_padding = 1; - for (i = 1; base + i != g; i++) - base[i].xoff -= right; - } - - for (i = 0; base + i != g; i++) - { - base[i].pos = begin; - base[i].to = end; - } - } - - g_physical_ascent = MAX (g_physical_ascent, base->ascent); - g_physical_descent = MAX (g_physical_descent, base->descent); - g_lbearing = MIN (g_lbearing, g_width + lbearing); - g_rbearing = MAX (g_rbearing, g_width + rbearing); - g_width += base->width; + g_physical_ascent = MAX (g_physical_ascent, g->g.ascent); + g_physical_descent = MAX (g_physical_descent, g->g.descent); + extents->lbearing = MIN (extents->lbearing, + extents->width + g->g.lbearing); + extents->rbearing = MAX (extents->rbearing, + extents->width + g->g.rbearing); + extents->width += g->g.xadv; } gstring->physical_ascent = g_physical_ascent; gstring->physical_descent = g_physical_descent; - gstring->sub_width = g_width; - gstring->sub_lbearing = g_lbearing; - gstring->sub_rbearing = g_rbearing; } @@ -716,16 +659,16 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) MGlyph box_glyph = g[-1]; box_glyph.type = GLYPH_BOX; - box_glyph.width + box_glyph.g.xadv = (control->fixed_width ? frame->space_width : box->inner_hmargin + box->width + box->outer_hmargin); - box_glyph.lbearing = 0; - box_glyph.rbearing = box_glyph.width; - box_glyph.xoff = 0; + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; box_glyph.right_padding = 1; - gstring->width += box_glyph.width; - gstring->rbearing += box_glyph.width; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; INSERT_GLYPH (gstring, gidx, box_glyph); gidx++; g = MGLYPH (gidx); @@ -742,23 +685,23 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) if (box_line_height < box_height) box_line_height = box_height; box_glyph.type = GLYPH_BOX; - box_glyph.width + box_glyph.g.xadv = (control->fixed_width ? frame->space_width : box->inner_hmargin + box->width + box->outer_hmargin); - box_glyph.lbearing = 0; - box_glyph.rbearing = box_glyph.width; - box_glyph.xoff = 0; + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; box_glyph.left_padding = 1; - gstring->width += box_glyph.width; - gstring->rbearing += box_glyph.width; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; INSERT_GLYPH (gstring, gidx, box_glyph); gidx++; g = MGLYPH (gidx); } } - if (g->category == McatCf && ignore_formatting_char) + if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char) g->type = GLYPH_SPACE; if (g->type == GLYPH_CHAR) @@ -771,33 +714,39 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) for (g++; g->type == GLYPH_CHAR; g++) if (! rfont != ! g->rface->rfont || box != g->rface->box - || ((fromg->code == MCHAR_INVALID_CODE) - != (g->code == MCHAR_INVALID_CODE)) - || (g->category == McatCf && ignore_formatting_char)) + || ((fromg->g.code == MCHAR_INVALID_CODE) + != (g->g.code == MCHAR_INVALID_CODE)) + || (g->category == GLYPH_CATEGORY_FORMATTER + && ignore_formatting_char)) break; - if (rfont && fromg->code != MCHAR_INVALID_CODE) + if (rfont && fromg->g.code != MCHAR_INVALID_CODE) { int extra_width; int to = GLYPH_INDEX (g); + MSubTextExtents extents; - layout_glyphs (frame, gstring, from, to); - extra_width = - gstring->sub_lbearing; + layout_glyphs (frame, gstring, from, to, &extents); + extra_width = - extents.lbearing; if (extra_width > 0 - && (GLYPH_INDEX (g) > 1 - || control->align_head)) + && ! control->disable_overlapping_adjustment + && (! control->orientation_reversed + ? ((to > 1 || control->align_head) + && g->type != GLYPH_ANCHOR) + : (((g->type && GLYPH_ANCHOR) || control->align_head) + && to > 1))) { g = MGLYPH (from); pad = *g; pad.type = GLYPH_PAD; - pad.xoff = 0; - pad.lbearing = 0; - pad.width = pad.rbearing = extra_width; + pad.g.xoff = 0; + pad.g.lbearing = 0; + pad.g.xadv = pad.g.rbearing = extra_width; pad.left_padding = 1; INSERT_GLYPH (gstring, from, pad); to++; - gstring->sub_lbearing = 0; - gstring->sub_width += extra_width; - gstring->sub_rbearing += extra_width; + extents.lbearing = 0; + extents.width += extra_width; + extents.rbearing += extra_width; g = MGLYPH (from - 1); if (g->type == GLYPH_SPACE) @@ -810,65 +759,66 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) face, or a default value of the current frame, which is, however, not yet implemented. */ - if (extra_width + 2 < g->width) + if (extra_width + 2 < g->g.xadv) { - g->width -= extra_width; + g->g.xadv -= extra_width; } else { - extra_width -= g->width - 2; - g->width = 2; + extra_width = g->g.xadv - 2; + g->g.xadv = 2; } gstring->width -= extra_width; gstring->rbearing -= extra_width; } } - extra_width = gstring->sub_rbearing - gstring->sub_width; - if (extra_width > 0) + g = MGLYPH (to); + extra_width = extents.rbearing - extents.width; + if (extra_width > 0 + && ! control->disable_overlapping_adjustment + && (GLYPH_INDEX (g) < gstring->used - 1 + || (control->orientation_reversed && control->align_head))) { - g = MGLYPH (to); if (g->type == GLYPH_SPACE && box == g->rface->box) { - g--; - pad = *g; + pad = g[-1]; pad.type = GLYPH_PAD; - pad.xoff = 0; - pad.lbearing = 0; - pad.width = pad.rbearing = extra_width; - pad.rbearing = 1; + pad.g.xoff = 0; + pad.g.lbearing = 0; + pad.g.xadv = pad.g.rbearing = extra_width; INSERT_GLYPH (gstring, to, pad); to++; + g = MGLYPH (to); } else - g[-1].width += extra_width; - gstring->sub_width += extra_width; + g[-1].g.xadv += extra_width; + extents.width += extra_width; } - if (gstring->lbearing > gstring->width + gstring->sub_lbearing) - gstring->lbearing = gstring->width + gstring->sub_lbearing; - if (gstring->rbearing < gstring->width + gstring->sub_rbearing) - gstring->rbearing = gstring->width + gstring->sub_rbearing; - gstring->width += gstring->sub_width; + if (gstring->lbearing > gstring->width + extents.lbearing) + gstring->lbearing = gstring->width + extents.lbearing; + if (gstring->rbearing < gstring->width + extents.rbearing) + gstring->rbearing = gstring->width + extents.rbearing; + gstring->width += extents.width; if (gstring->ascent < rface->ascent) gstring->ascent = rface->ascent; if (gstring->descent < rface->descent) gstring->descent = rface->descent; - g = MGLYPH (to); } else { for (; fromg < g; fromg++) { - if ((fromg->c >= 0x200B && fromg->c <= 0x200F) - || (fromg->c >= 0x202A && fromg->c <= 0x202E)) - fromg->width = fromg->rbearing = 1; + if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F) + || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E)) + fromg->g.xadv = fromg->g.rbearing = 1; else - fromg->width = fromg->rbearing = rface->space_width; - fromg->xoff = fromg->lbearing = 0; - fromg->ascent = fromg->descent = 0; - gstring->width += fromg->width; - gstring->rbearing += fromg->width; + fromg->g.xadv = fromg->g.rbearing = rface->space_width; + fromg->g.xoff = fromg->g.lbearing = 0; + fromg->g.ascent = fromg->g.descent = 0; + gstring->width += fromg->g.xadv; + gstring->rbearing += fromg->g.xadv; } if (gstring->ascent < frame->rface->ascent) gstring->ascent = frame->rface->ascent; @@ -878,40 +828,40 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) } else if (g->type == GLYPH_SPACE) { - if (g->c == ' ') - g->width = g->rface->space_width; - else if (g->c == '\n') + if (g->g.c == ' ') + g->g.xadv = g->rface->space_width; + else if (g->g.c == '\n') { - g->width = control->cursor_width; - if (g->width) + g->g.xadv = control->cursor_width; + if (g->g.xadv) { if (control->cursor_bidi) - g->width = 3; - else if (g->width < 0) - g->width = g->rface->space_width; + g->g.xadv = 3; + else if (g->g.xadv < 0) + g->g.xadv = g->rface->space_width; } } - else if (g->c == '\t') + else if (g->g.c == '\t') { - g->width = tab_width - ((gstring->indent + gstring->width) - % tab_width); + g->g.xadv = tab_width - ((gstring->indent + gstring->width) + % tab_width); tab_found = 1; } else - g->width = 1; + g->g.xadv = 1; if (g[-1].type == GLYPH_PAD) { /* This space glyph absorbs (maybe partially) the previous padding glyph. */ - g->width -= g[-1].width; - if (g->width < 1) + g->g.xadv -= g[-1].g.xadv; + if (g->g.xadv < 1) /* But, keep at least some space width. For the moment, we use the arbitrary width 2-pixel. */ - g->width = 2; + g->g.xadv = 2; } - g->rbearing = g->width; - gstring->width += g->width; - gstring->rbearing += g->width; + g->g.rbearing = g->g.xadv; + gstring->width += g->g.xadv; + gstring->rbearing += g->g.xadv; if (g->rface->rfont) { if (gstring->ascent < g->rface->ascent) @@ -923,8 +873,8 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) } else { - gstring->width += g->width; - gstring->rbearing += g->width; + gstring->width += g->g.xadv; + gstring->rbearing += g->g.xadv; g++; } } @@ -936,16 +886,16 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) MGlyph box_glyph = g[-1]; box_glyph.type = GLYPH_BOX; - box_glyph.width + box_glyph.g.xadv = (control->fixed_width ? frame->space_width : box->inner_hmargin + box->width + box->outer_hmargin); - box_glyph.lbearing = 0; - box_glyph.rbearing = box_glyph.width; - box_glyph.xoff = 0; + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; box_glyph.right_padding = 1; - gstring->width += box_glyph.width; - gstring->rbearing += box_glyph.width; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; INSERT_GLYPH (gstring, gidx, box_glyph); } @@ -988,23 +938,23 @@ layout_glyph_string (MFrame *frame, MGlyphString *gstring) for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) { - if (g->type == GLYPH_CHAR && g->c == '\t') + if (g->type == GLYPH_CHAR && g->g.c == '\t') { int this_width = tab_width - (width % tab_width); if (g[1].type == GLYPH_PAD) - this_width -= g[1].width; + this_width -= g[1].g.xadv; if (g[-1].type == GLYPH_PAD) - this_width -= g[-1].width; + this_width -= g[-1].g.xadv; if (this_width < 2) this_width = 2; - gstring->width += this_width - g->width; - gstring->rbearing += this_width - g->width; - g->width = this_width; + gstring->width += this_width - g->g.xadv; + gstring->rbearing += this_width - g->g.xadv; + g->g.xadv = this_width; width += this_width; } else - width += g->width; + width += g->g.xadv; } } } @@ -1035,9 +985,10 @@ draw_background (MFrame *frame, MDrawWindow win, int x, int y, } *from_idx = *to_idx = 0; + *to_x = x; while (g->type != GLYPH_ANCHOR) { - if (g->pos >= from && g->pos < to) + if (g->g.from >= from && g->g.from < to) { MGlyph *fromg = g, *cursor = NULL; MRealizedFace *rface = g->rface; @@ -1047,18 +998,18 @@ draw_background (MFrame *frame, MDrawWindow win, int x, int y, if (! *from_idx) *from_idx = GLYPH_INDEX (g); - while (g->pos >= from && g->pos < to + while (g->g.from >= from && g->g.from < to && g->rface == rface) { g->enabled = 1; if (g->type != GLYPH_BOX - && g->pos <= cursor_pos && g->to > cursor_pos) + && g->g.from <= cursor_pos && g->g.to > cursor_pos) { if (! cursor) cursor = g, cursor_x = x + width; - cursor_width += g->width; + cursor_width += g->g.xadv; } - width += g++->width; + width += g++->g.xadv; } if (width > 0 && (control->as_image @@ -1067,9 +1018,9 @@ draw_background (MFrame *frame, MDrawWindow win, int x, int y, int this_x = x, this_width = width; if (fromg->type == GLYPH_BOX) - this_x += fromg->width, this_width -= fromg->width; + this_x += fromg->g.xadv, this_width -= fromg->g.xadv; if (g[-1].type == GLYPH_BOX) - this_width -= g[-1].width; + this_width -= g[-1].g.xadv; (frame->driver->fill_space) (frame, win, rface, 0, this_x, y - gstring->text_ascent, this_width, @@ -1123,13 +1074,13 @@ draw_background (MFrame *frame, MDrawWindow win, int x, int y, while (fromg < g) { if (fromg->type != GLYPH_BOX - && fromg->pos <= prev_pos && fromg->to > prev_pos) + && fromg->g.from <= prev_pos && fromg->g.to > prev_pos) { if (! cursor) cursor = fromg, cursor_x = x + temp_width; - cursor_width += fromg->width; + cursor_width += fromg->g.xadv; } - temp_width += fromg++->width; + temp_width += fromg++->g.xadv; } if (cursor) { @@ -1184,10 +1135,10 @@ render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width, (*frame->driver->region_to_rect) (region, &rect); if (rect.x > x) { - while (g != gend && x + g->rbearing <= rect.x) + while (g != gend && x + g->g.rbearing <= rect.x) { - x += g->width; - width -= g++->width; + x += g->g.xadv; + width -= g++->g.xadv; while (! g->enabled && g != gend) g++; } @@ -1196,14 +1147,15 @@ render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width, if (rect.x < x + width) { while (g != gend - && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x)) + && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x)) { - width -= (--gend)->width; + width -= (--gend)->g.xadv; while (! gend->enabled && g != gend) gend--; } if (g != gend) - while (gend[-1].to == gend->to) gend++; + while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to) + gend++; } } @@ -1212,21 +1164,21 @@ render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width, if (g->enabled) { MRealizedFace *rface = g->rface; - int width = g->width; + int width = g->g.xadv; MGlyph *from_g = g++; /* Handle the glyphs of the same type/face at once. */ while (g != gend && g->type == from_g->type && g->rface == rface - && ((g->code == MCHAR_INVALID_CODE) - == (from_g->code == MCHAR_INVALID_CODE)) + && ((g->g.code == MCHAR_INVALID_CODE) + == (from_g->g.code == MCHAR_INVALID_CODE)) && g->enabled) - width += g++->width; + width += g++->g.xadv; if (from_g->type == GLYPH_CHAR) { - if (rface->rfont && from_g->code != MCHAR_INVALID_CODE) + if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE) (rface->rfont->driver->render) (win, x, y, gstring, from_g, g, reverse, region); else @@ -1270,11 +1222,11 @@ find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right, for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--) { - x -= g->width; - if (x + g->rbearing > 0) + x -= g->g.xadv; + if (x + g->g.rbearing > 0) { - while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR) - x -= (--g)->width; + while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR) + x -= (--g)->g.xadv; left_idx = GLYPH_INDEX (g); left_x = x; } @@ -1282,11 +1234,11 @@ find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right, for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++) { - x += g->width; - if (x - g->width + g->lbearing < 0) + x += g->g.xadv; + if (x - g->g.xadv + g->g.lbearing < 0) { - while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR) - x += (++g)->width; + while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR) + x += (++g)->g.xadv; right_idx = GLYPH_INDEX (g) + 1; right_x = x; } @@ -1314,26 +1266,33 @@ find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right, static int -gstring_width (MGlyphString *gstring, int from, int to, int *rbearing) +gstring_width (MGlyphString *gstring, int from, int to, + int *lbearing, int *rbearing) { MGlyph *g; int width; if (from <= gstring->from && to >= gstring->to) { + if (lbearing) + *lbearing = gstring->lbearing; if (rbearing) *rbearing = gstring->rbearing; return gstring->width; } + if (lbearing) + *lbearing = 0; if (rbearing) *rbearing = 0; for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++) - if (g->pos >= from && g->pos < to) + if (g->g.from >= from && g->g.from < to) { - if (rbearing && width + g->rbearing > *rbearing) - *rbearing = width + g->rbearing; - width += g->width; + if (lbearing && width + g->g.lbearing < *lbearing) + *lbearing = width + g->g.lbearing; + if (rbearing && width + g->g.rbearing > *rbearing) + *rbearing = width + g->g.rbearing; + width += g->g.xadv; } return width; } @@ -1349,8 +1308,10 @@ render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y, int from_idx, to_idx; int to_x; + if (from == to) + return; if (control->orientation_reversed) - x -= gstring->indent + gstring_width (gstring, from, to, NULL); + x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL); else x += gstring->indent; @@ -1418,7 +1379,33 @@ alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control, if (pos == mt->nchars) { + MGlyph *g; + gstring = &scratch_gstring; + if (gstring->size == 0) + { + MGlyph g_tmp; + + INIT_GLYPH (g_tmp); + g_tmp.type = GLYPH_ANCHOR; + APPEND_GLYPH (gstring, g_tmp); + APPEND_GLYPH (gstring, g_tmp); + APPEND_GLYPH (gstring, g_tmp); + gstring->glyphs[1].type = GLYPH_SPACE; + gstring->glyphs[1].g.c = '\n'; + gstring->glyphs[1].g.code = '\n'; + } + gstring->from = pos; + g = MGLYPH (0); + g->rface = frame->rface; + g->g.from = g->g.to = pos; + g++; + g->rface = frame->rface; + g->g.from = pos++, g->g.to = pos; + g++; + g->rface = frame->rface; + g->g.from = g->g.to = pos; + gstring->to = pos; } else { @@ -1430,7 +1417,6 @@ alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control, gstring->frame = frame; gstring->tick = frame->tick; gstring->top = gstring; - gstring->mt = mt; gstring->control = *control; gstring->indent = gstring->width_limit = 0; if (control->format) @@ -1441,6 +1427,9 @@ alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control, return gstring; } +static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos, + int forwardp); + /* Truncate the line width of GSTRING to GSTRING->width_limit. */ static void @@ -1453,13 +1442,13 @@ truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring) int pos; /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is - a width of glyphs for the character at I of GSTRING->mt. If I is - not a beginning of a grapheme cluster, the corresponding element - is 0. */ + a width of glyphs for the character at I of MT. If I is not a + beginning of a grapheme cluster, the corresponding element is + 0. */ MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW); memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from)); for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) - pos_width[g->pos - gstring->from] += g->width; + pos_width[g->g.from - gstring->from] += g->g.xadv; for (i = 0, width = 0; i < gstring->to - gstring->from; i++) { if (pos_width[i] > 0) @@ -1473,13 +1462,27 @@ truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring) pos = gstring->from + i; if (gstring->control.line_break) { - pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i, - gstring->from, gstring->to, 0, 0); - if (pos <= gstring->from || pos >= gstring->to) - return; + pos = (*gstring->control.line_break) (mt, gstring->from + i, + gstring->from, gstring->from + i, + 0, 0); + if (pos <= gstring->from) + { + g = find_glyph_in_gstring (gstring, gstring->from, 1); + pos = g->g.to; + } + else if (pos >= gstring->to) + pos = gstring->to; + } + else if (i == 0) + { + g = find_glyph_in_gstring (gstring, gstring->from, 1); + pos = g->g.to; + } + if (pos < gstring->to) + { + compose_glyph_string (frame, mt, gstring->from, pos, gstring); + layout_glyph_string (frame, gstring); } - compose_glyph_string (frame, mt, gstring->from, pos, gstring); - layout_glyph_string (frame, gstring); } @@ -1510,7 +1513,10 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) || gstring->tick != frame->tick || memcmp (control, &gstring->control, (char *) (&control->with_cursor) - - (char *) (control))) + - (char *) (control)) + || control->cursor_pos != gstring->control.cursor_pos + || control->cursor_width != gstring->control.cursor_width + || control->cursor_bidi != gstring->control.cursor_bidi) { mtext_detach_property (prop); gstring = NULL; @@ -1540,8 +1546,8 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) gst->to += offset; for (i = 0; i < gst->used; i++) { - gst->glyphs[i].pos += offset; - gst->glyphs[i].to += offset; + gst->glyphs[i].g.from += offset; + gst->glyphs[i].g.to += offset; } } M17N_OBJECT_REF (gstring); @@ -1551,26 +1557,23 @@ get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) int beg, end; int line = 0, y = 0; - if (control->two_dimensional) + if (pos < mtext_nchars (mt)) { beg = mtext_character (mt, pos, 0, '\n'); if (beg < 0) beg = 0; else beg++; - end = mtext_nchars (mt) + (control->cursor_width != 0); } else - { - beg = pos; - end = to; - } + beg = pos; + end = mtext_nchars (mt) + (control->cursor_width != 0); gstring = alloc_gstring (frame, mt, beg, control, line, y); - compose_glyph_string (frame, mt, beg, end, gstring); + if (beg < mtext_nchars (mt)) + compose_glyph_string (frame, mt, beg, end, gstring); layout_glyph_string (frame, gstring); end = gstring->to; - if (control->two_dimensional - && gstring->width_limit + if (gstring->width_limit && gstring->width > gstring->width_limit) { MGlyphString *gst = gstring; @@ -1665,13 +1668,13 @@ find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp) if (forwardp) { for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) - if (g->pos <= pos && g->to > pos) + if (g->g.from <= pos && g->g.to > pos) break; } else { for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) - if (g->pos <= pos && g->to > pos) + if (g->g.from <= pos && g->g.to > pos) break; } return g; @@ -1681,62 +1684,43 @@ find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp) /* for debugging... */ char work[16]; -char * -dump_combining_code (int code) -{ - char *vallign = "tcbB"; - char *hallign = "lcr"; - char *p; - int off_x, off_y; - - if (! code) - return "none"; - if (COMBINING_BY_CLASS_P (code)) - code = combining_code_from_class (COMBINING_CODE_CLASS (code)); - work[0] = vallign[COMBINING_CODE_BASE_Y (code)]; - work[1] = hallign[COMBINING_CODE_BASE_X (code)]; - off_y = COMBINING_CODE_OFF_Y (code) - 128; - off_x = COMBINING_CODE_OFF_X (code) - 128; - if (off_y > 0) - sprintf (work + 2, "+%d", off_y); - else if (off_y < 0) - sprintf (work + 2, "%d", off_y); - else if (off_x == 0) - sprintf (work + 2, "."); - p = work + strlen (work); - if (off_x > 0) - sprintf (p, ">%d", off_x); - else if (off_x < 0) - sprintf (p, "<%d", -off_x); - p += strlen (p); - p[0] = vallign[COMBINING_CODE_ADD_Y (code)]; - p[1] = hallign[COMBINING_CODE_ADD_X (code)]; - p[2] = '\0'; - return work; -} - void -dump_gstring (MGlyphString *gstring, int indent) +dump_gstring (MGlyphString *gstring, int indent, int type) { char *prefix = (char *) alloca (indent + 1); - MGlyph *g, *last_g = gstring->glyphs + gstring->used; + MGlyph *g, *first_g, *last_g; memset (prefix, 32, indent); prefix[indent] = 0; fprintf (stderr, "(glyph-string"); - for (g = MGLYPH (0); g < last_g; g++) - fprintf (stderr, - "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)", - prefix, - g - gstring->glyphs, - (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD" - : g->type == GLYPH_ANCHOR ? "ANC" - : g->type == GLYPH_BOX ? "BOX" : "CHR"), - g->pos, g->to, g->c, g->code, (unsigned) g->rface, - dump_combining_code (g->combining_code), - g->width, g->bidi_level); + if (type == 0) + { + first_g = MGLYPH (0); + last_g = first_g + gstring->used; + } + else + { + first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs; + last_g = first_g + ((MFLTGlyphString *) gstring)->used; + } + + for (g = first_g; g < last_g; g++) + { + fprintf (stderr, + "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d", + prefix, + g - first_g, + (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD" + : g->type == GLYPH_ANCHOR ? "ANC" + : g->type == GLYPH_BOX ? "BOX" : "CHR"), + g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface, + g->g.xadv, g->bidi_level); + if (g->g.xoff || g->g.yoff) + fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff); + fprintf (stderr, ")"); + } fprintf (stderr, ")"); } @@ -1751,8 +1735,7 @@ mdraw__init () memset (&scratch_gstring, 0, sizeof (scratch_gstring)); MLIST_INIT1 (&scratch_gstring, glyphs, 3); - Mlatin = msymbol ("latin"); - Minherited = msymbol ("inherited"); + Mcommon = msymbol ("common"); McatCc = msymbol ("Cc"); McatCf = msymbol ("Cf"); @@ -1763,9 +1746,22 @@ mdraw__init () MbidiRLO = msymbol ("RLO"); MbidiBN = msymbol ("BN"); MbidiS = msymbol ("S"); + MbidiNSM = msymbol ("NSM"); #ifdef HAVE_FRIBIDI +#if FRIBIDI_INTERFACE_VERSION < 3 fribidi_set_mirroring (TRUE); +#else + fribidi_set_mirroring (1); #endif +#endif + + M_break_at_space = msymbol ("bs"); + M_break_at_word = msymbol ("bw"); + M_break_at_any = msymbol ("ba"); + M_kinsoku_bol = msymbol ("kb"); + M_kinsoku_eol = msymbol ("ke"); + + mflt_enable_new_feature = 1; return 0; } @@ -1774,6 +1770,8 @@ void mdraw__fini () { MLIST_FREE1 (&scratch_gstring, glyphs); + M17N_OBJECT_UNREF (linebreak_table); + linebreak_table = NULL; } /*** @} */ @@ -1829,7 +1827,7 @@ mdraw__fini () of the script and language. If no entry is found, proceed to the next step. - If an entry is found, use one of the fonts in the entry that + If an entry is found, use one of the fonts in the entry that has a glyph for the character and that matches best with the face properties. If no such font exists, proceed to the next step. @@ -1859,67 +1857,57 @@ mdraw__fini () @brief ¥¦¥£¥ó¥É¥¦¤Ë M-text ¤òÉÁ²è¤¹¤ë. ´Ø¿ô mdraw_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ - ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥­¥¹¥È¤ò - ÉÁ²è¤¹¤ë¡£ + ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥­¥¹¥È¤òÉÁ²è¤¹¤ë¡£ ¥Æ¥­¥¹¥È¤Î¸«±É¤¨¡Ê¥Õ¥©¥ó¥È¡¢¥¹¥¿¥¤¥ë¡¢¿§¤Ê¤É¡Ë¤Ï¡¢¥­¡¼¤¬ @c Mface - ¤Ç¤¢¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text ¤Î°ìÉô¤¢¤ë¤¤¤Ï - Á´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME - ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤¬ÍѤ¤¤é¤ì¤ë¡£ + ¤Ç¤¢¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤˤè¤Ã¤Æ·è¤Þ¤ë¡£M-text + ¤Î°ìÉô¤¢¤ë¤¤¤ÏÁ´Éô¤Ë¤½¤Î¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬ÉÕ¤¤¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ë¤Ï¡¢$FRAME + ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤òÂå¤ï¤ê¤ËÍѤ¤¤ë¡£ - M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset ¥×¥í¥Ñ¥Æ¥£ - ¤ÎÃͤ«¤é°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£ + M-text ¤Î³Æʸ»ú¤òɽ¼¨¤¹¤ë¥Õ¥©¥ó¥È¤Ï¡¢¥Õ¥§¡¼¥¹¤Î fontset + ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤΤ¦¤Á¤«¤é¡¢°Ê²¼¤Î¥¢¥ë¥´¥ê¥º¥à¤ÇÁª¤Ð¤ì¤ë¡£
    -
  1. ¤½¤Îʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë - ¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil - ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£¤½¤¦¤Ç¤Ê - ¤±¤ì¤Ð¡¢¤½¤Î¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤é¤½¤Îʸ»ú¥»¥Ã - ¥ÈÍѤΤâ¤Î¤òõ¤¹¡£¥Õ¥©¥ó¥È¤¬¤ß¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë - ¿Ê¤à¡£ +
  2. ¤½¤Îʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ @c Mcharset + ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤÏʸ»ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« #Mnil + ¤Î¤É¤Á¤é¤«¤Ç¤¢¤ë¡£#Mnil ¤Ê¤é¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ + ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢fontset + ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£ + ̵¤±¤ì¤Ð¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ - ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ - »úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ - ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê - ¤à¡£ + ¤½¤Îʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ¹¤ë¤â¤Î¤ò»È¤¦¡£ + ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ -
  3. ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£·Ñ - ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¤ò - Ä´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê - ¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ +
  4. ¤½¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" ¡Ê¥¹¥¯¥ê¥×¥È¡Ë¤òÄ´¤Ù¤ë¡£ + ¤½¤Î¥×¥í¥Ñ¥Æ¥£¤¬·Ñ¾µ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¤½¤ì°ÊÁ°¤Îʸ»ú¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£ "script" + ¤òÄ´¤Ù¤ë¡£Á°¤Îʸ»ú¤¬¤Ê¤«¤Ã¤¿¤ê¡¢¤½¤Îʸ»ú¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ - ¤½¤Îʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ @c Mlanguage ¤Ç¤¢ - ¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î - ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ + ¤½¤Îʸ»ú¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼¤¬ @c Mlanguage ¤Ç¤¢¤ë¤â¤Î¤ÎÃͤòÄ´¤Ù¤ë¡£ + ¤³¤ÎÃͤϸÀ¸ì¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤« @c Mnil ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ - ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»ÍѤΥե©¥ó¥È - ¥»¥Ã¥È¤ò¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã - ¥×¤Ë¿Ê¤à¡£ + ¤½¤Î¸À¸ì¤È¥¹¥¯¥ê¥×¥È¤ÎÁȤ߹ç¤ï¤»¤¬ fontset + ¤Î¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ - ¤½¤Î¤è¤¦¤Êʸ»ú¥»¥Ã¥ÈÍѤΥե©¥ó¥È¤¬¤ß¤Ä¤«¤ì¤Ð¡¢¤½¤ì¤é¤Î¤¦¤Á¸½ - ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹ç - Ãפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã - ¥×¤Ë¿Ê¤à¡£ + ¸«¤Ä¤«¤Ã¤¿¤Ð¤¢¤¤¤Ë¤Ï¡¢¤½¤ì¤é¤Î¥Õ¥©¥ó¥È¤Î¤¦¤Á¸½ºß¤Îʸ»úÍѤΥ°¥ê¥Õ¤ò»ý¤Á¡¢¥Õ¥§¡¼¥¹¤Î³Æ¥×¥í¥Ñ¥Æ¥£¤ËºÇ¤â¤è¤¯¹çÃפ·¤Æ¤¤¤ë¤â¤Î¤ò»È¤¦¡£ + ¤½¤Î¤è¤¦¤Ê¥Õ¥©¥ó¥È¤¬Ìµ¤±¤ì¤Ð¼¡¤Î¥¹¥Æ¥Ã¥×¤Ë¿Ê¤à¡£ -
  5. ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Îfall-back¥Æ¡¼ - ¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£ +
  6. ¤½¤Îʸ»ú¤Î¥°¥ê¥Õ¤ò»ý¤Ä¥Õ¥©¥ó¥È¤ò¡¢¥Õ¥©¥ó¥È¥»¥Ã¥È¤Î fall-back + ¥Æ¡¼¥Ö¥ë¤«¤éõ¤¹¡£¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤ì¤Ð¤½¤ì¤ò»È¤¦¡£
- °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú - ¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£ + °Ê¾å¤Î¥¢¥ë¥´¥ê¥º¥à¤Ç¥Õ¥©¥ó¥È¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¤½¤Îʸ»ú¤È¤·¤Æ¶õ¤Î»Í³Ñ·Á¤òɽ¼¨¤¹¤ë¡£ - ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢ - ´Ø¿ô mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦ - ¤³¤È¡£ + ¤³¤Î´Ø¿ô¤¬ÉÁ²è¤¹¤ë¤Î¤Ï¥°¥ê¥Õ¤ÎÁ°·Ê¤À¤±¤Ç¤¢¤ë¡£ÇØ·Ê¿§¤ò»ØÄꤹ¤ë¤Ë¤Ï¡¢´Ø¿ô + mdraw_image_text () ¤«´Ø¿ô mdraw_text_with_control () ¤ò»È¤¦¤³¤È¡£ ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë´Ø¿ô XDrawString (), XmbDrawString (), XwcDrawString () ¤ËÁêÅö¤¹¤ë¡£ @return - ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì - ¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ + ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_text () ¤Ï 0 ÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï + -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ @latexonly \IPAlabel{mdraw_text} @endlatexonly */ @@ -1968,21 +1956,20 @@ mdraw_text (MFrame *frame, MDrawWindow win, int x, int y, /***ja @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò²èÁü¤È¤·¤ÆÉÁ¤¯. - ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤Î - ºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥­¥¹¥È¤ò²è - Áü¤È¤·¤ÆÉÁ¤¯¡£ + ´Ø¿ô mdraw_image_text () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN + ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO + ¤Þ¤Ç¤Î¥Æ¥­¥¹¥È¤ò²èÁü¤È¤·¤ÆÉÁ¤¯¡£ - ¥Æ¥­¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç - ¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£ + ¥Æ¥­¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () + ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ç¤Ï¥Õ¥§¡¼¥¹¤Ç»ØÄꤵ¤ì¤¿¿§¤ÇÇطʤâÉÁ¤¯ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£ ¤³¤Î´Ø¿ô¤Ï¡¢X ¥¦¥£¥ó¥É¥¦¤Ë¤ª¤±¤ë XDrawImageString (), - XmbDrawImageString (), XwcDrawImageString () ¤Ë - ÁêÅö¤¹¤ë¡£ + XmbDrawImageString (), XwcDrawImageString () + ¤ËÁêÅö¤¹¤ë¡£ @return - ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð - ¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #m_errro ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ - ¤ë¡£ + ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mdraw_image_text () ¤Ï 0 + ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */ @@ -2018,26 +2005,25 @@ mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y, this function also follows what specified in the drawing control object $CONTROL. - For instance, if of $CONTROL is nonzero, this + For instance, if \ of $CONTROL is nonzero, this function draw an M-text 2-dimensionally, i.e., newlines in M-text breaks lines and the following characters are drawn in the next line. See the documentation of the structure @ MDrawControl for more detail. */ /***ja - @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤òÉÁ¤¯¡Ê¾ÜºÙ¤ÊÀ©¸æ¤Ä¤­¡Ë. + @brief ¥Ç¥£¥¹¥×¥ì¥¤¤ËM-text ¤ò¾ÜºÙ¤ÊÀ©¸æ¤Ä¤­¤ÇÉÁ¤¯. ´Ø¿ô mdraw_text_with_control () ¤Ï¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ë¡¢M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥­¥¹ ¥È¤òÉÁ¤¯¡£ - ¥Æ¥­¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤Ï - ÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È $CONTROL ¤Ç¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£ + ¥Æ¥­¥¹¥È¤ÎÉÁ²èÊýË¡¤Ï mdraw_text () ¤È¤Û¤ÜƱ¤¸¤Ç¤¢¤ë¤¬¡¢¤³¤Î´Ø¿ô¤ÏÉÁ²èÀ©¸æÍѤΥª¥Ö¥¸¥§¥¯¥È + $CONTROL ¤Î»Ø¼¨¤Ë¤â½¾¤¦ÅÀ¤¬°Û¤Ê¤Ã¤Æ¤¤¤ë¡£ - ¤¿¤È¤¨¤Ð $CONTROL ¤Î ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô - ¤ÏM-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯ - ʸ»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³ - ¤È¡£*/ + ¤¿¤È¤¨¤Ð $CONTROL ¤Î \ ¤¬¥¼¥í¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï + M-text ¤ò2¼¡¸µÅª¤ËÉÁ¤¯¡£¤¹¤Ê¤ï¤Á M-text Ãæ¤Î²þ¹Ô¤Ç¹Ô¤ò²þ¤á¡¢Â³¤¯Ê¸»ú¤Ï¼¡¤Î¹Ô¤ËÉÁ¤¯¡£¾ÜºÙ¤Ï¹½Â¤ÂÎ + @ MDrawControl ¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£*/ int mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y, @@ -2064,13 +2050,13 @@ mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y, surrounding box, the box is included in the bounding box. If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also - computes the bounding box that provides mininum spacing to other + computes the bounding box that provides minimum spacing to other graphical features (such as surrounding box) for the M-text, and stores the results in the members of the structure pointed to by $OVERALL_LOGICAL_RETURN. If $OVERALL_LINE_RETURN is not @c NULL, this function also - computes the bounding box that provides mininum spacing to the + computes the bounding box that provides minimum spacing to the other M-text drawn, and stores the results in the members of the structure pointed to by $OVERALL_LINE_RETURN. This is a union of $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members @@ -2088,31 +2074,31 @@ mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y, /***ja @brief ¥Æ¥­¥¹¥È¤ÎÉý¡Ê¥Ô¥¯¥»¥ëñ°Ì¡Ë¤ò·×»»¤¹¤ë. - ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ - ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO + ´Ø¿ô mdraw_text_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () + ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤ËɬÍפȤʤëÉý¤òÊÖ¤¹¡£ - $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text ¤Îʸ - »ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN ¤¬ - »Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ(surrounding box) + $OVERALL_INK_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text + ¤Îʸ»ú¤Î¥¤¥ó¥¯¤Î¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_INK_RETURN + ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£M-text ¤Ë°Ï¤ßÏÈ (surrounding box) ¤ò»ØÄꤹ¤ë¥Õ¥§¡¼¥¹¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤â¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤Ë´Þ¤à¡£ $OVERALL_LOGICAL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï M-text - ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏȤʤɡˤȤδ֤κǾ®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨ - ¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN ¤¬»Ø¤¹¹½ - ¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£ + ¤È¾¤Î graphical feature ¡Ê°Ï¤ßÏÈ¤Ê¤É¡Ë + ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢$OVERALL_LOGICAL_RETURN + ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£ $OVERALL_LINE_RETURN ¤¬ @c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¾¤Î M-text ¤È¤Î´Ö¤ÎºÇ¾®¤Î¥¹¥Ú¡¼¥¹¤ò¼¨¤¹¥Ð¥¦¥ó¥Ç¥£¥ó¥°¥Ü¥Ã¥¯¥¹¤â·×»»¤·¡¢ - $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª - ¥Ö¥¸¥§¥¯¥È $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent, + $OVERALL_LINE_RETURN ¤¬»Ø¤¹¹½Â¤ÂΤΥá¥ó¥Ð¤Ë¤½¤Î·ë²Ì¤òÀßÄꤹ¤ë¡£¥ª¥Ö¥¸¥§¥¯¥È + $CONTROL ¤Î¥á¥ó¥Ð min_line_ascent, min_line_descent, max_line_ascent, max_line_descent ¤¬¤¹¤Ù¤Æ0¤Î»þ¤Ë¤Ï¡¢¤³¤ÎÃÍ¤Ï $OVERALL_INK_RETURN ¤È$OVERALL_LOGICAL_RETURN ¤ÎϤȤʤ롣 - @return ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ­¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£ - $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥­¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ - ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³° - ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ + @return + ¤³¤Î´Ø¿ô¤Ïɽ¼¨¤ËɬÍפʥƥ­¥¹¥È¤ÎÉý¤ò¥Ô¥¯¥»¥ëñ°Ì¤ÇÊÖ¤¹¡£$CONTROL->two_dimensional + ¤¬0¤Ç¤Ê¤¯¡¢¥Æ¥­¥¹¥È¤¬Ê£¿ô¤Î¹Ô¤ËÅϤäÆÉÁ¤«¤ì¤ë¾ì¹ç¤Ë¤Ï¡¢ºÇÂç¤ÎÉý¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬À¸¤¸¤¿¾ì¹ç¤Ï + -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */ @@ -2129,7 +2115,7 @@ mdraw_text_extents (MFrame *frame, { MGlyphString *gstring; int y = 0; - int width, rbearing; + int width, lbearing, rbearing; ASSURE_CONTROL (control); M_CHECK_POS_X (mt, from, -1); @@ -2141,52 +2127,49 @@ mdraw_text_extents (MFrame *frame, gstring = get_gstring (frame, mt, from, to, control); if (! gstring) MERROR (MERROR_DRAW, -1); - width = gstring_width (gstring, from, to, &rbearing); + width = gstring_width (gstring, from, to, &lbearing, &rbearing); if (overall_ink_return) - { - overall_ink_return->y = - gstring->physical_ascent; - overall_ink_return->x = gstring->lbearing; - } + overall_ink_return->y = - gstring->physical_ascent; if (overall_logical_return) - { - overall_logical_return->y = - gstring->ascent; - overall_logical_return->x = 0; - } + overall_logical_return->y = - gstring->ascent; if (overall_line_return) - { - overall_line_return->y = - gstring->line_ascent; - overall_line_return->x = gstring->lbearing; - } + overall_line_return->y = - gstring->line_ascent; for (from = gstring->to; from < to; from = gstring->to) { - int this_width, this_rbearing; + int this_width, this_lbearing, this_rbearing; y += gstring->line_descent; M17N_OBJECT_UNREF (gstring->top); gstring = get_gstring (frame, mt, from, to, control); - this_width = gstring_width (gstring, from, to, &this_rbearing); + this_width = gstring_width (gstring, from, to, + &this_lbearing, &this_rbearing); y += gstring->line_ascent; if (width < this_width) width = this_width; if (rbearing < this_rbearing) rbearing = this_rbearing; + if (lbearing > this_lbearing) + lbearing = this_lbearing; } if (overall_ink_return) { - overall_ink_return->width = rbearing; + overall_ink_return->x = lbearing; + overall_ink_return->width = rbearing - lbearing; overall_ink_return->height = y + gstring->physical_descent - overall_ink_return->y; } if (overall_logical_return) { + overall_logical_return->x = 0; overall_logical_return->width = width; overall_logical_return->height = y + gstring->descent - overall_logical_return->y; } if (overall_line_return) { - overall_line_return->width = MAX (width, rbearing); + overall_line_return->x = lbearing; + overall_line_return->width = MAX (width, rbearing - lbearing); overall_line_return->height = y + gstring->line_descent - overall_line_return->y; } @@ -2228,15 +2211,14 @@ mdraw_text_extents (MFrame *frame, /***ja @brief M-text ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë. - ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô - mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤ - ¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ - ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£ + ´Ø¿ô mdraw_text_per_char_extents () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () + ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ M-text $MT ¤Î $FROM ¤«¤é $TO + ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤Ëɽ¼¨¤¹¤ëºÝ¤Î³Æʸ»ú¤Î¥µ¥¤¥º¤ò·×»»¤¹¤ë¡£ - $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î - ¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN ¤Î³ÆÍ× - ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text¤Îɽ¼¨¸¶ÅÀ¤«¤é¤Î - ÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È + $ARRAY_SIZE ¤Ë¤è¤Ã¤Æ $INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN + ¤Î¥µ¥¤¥º¤ò»ØÄꤹ¤ë¡£$INK_ARRAY_RETURN ¤È$LOGICAL_ARRAY_RETURN + ¤Î³ÆÍ×ÁǤϡ¢¤½¤ì¤¾¤ìʸ»ú¤ÎÉÁ²è¥¤¥ó¥¯¤ÈÏÀÍý¥µ¥¤¥º¡ÊM-text + ¤Îɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ͡ˤˤè¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£ÀßÄꤵ¤ì¤¿ $INK_ARRAY_RETURN ¤È $LOGICAL_ARRAY_RETURN ¤ÎÍ×ÁǤοô¤Ï¡¢$NUM_CHARS_RETURN ¤ËÌᤵ¤ì¤ë¡£ $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤ÎÀ£Ë¡¤òÌ᤻¤Ê¤¤¤Û¤É¾®¤µ¤¤¾ì¹ç¤Ë¤Ï¡¢´Ø¿ô¤Ï -1 @@ -2245,11 +2227,9 @@ mdraw_text_extents (MFrame *frame, ¥Ý¥¤¥ó¥¿ $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤¬@c NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¥Æ¥­¥¹¥ÈÁ´ÂΤΥµ¥¤¥º¤â·×»»¤·¡¢·ë²Ì¤ò - $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á - ¥ó¥Ð¤ËÊݸ¤¹¤ë¡£ + $OVERALL_INK_RETURN ¤È $OVERALL_LOGICAL_RETURN ¤Ç»Ø¤µ¤ì¤ë¹½Â¤¤Î¥á¥ó¥Ð¤ËÊݸ¤¹¤ë¡£ - $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú - ¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */ + $CONTROL->two_dimensional ¤¬0¤Ç¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤ÏºÇ½é¤Î¹Ô¤Îʸ»ú¤Î¥µ¥¤¥º¤À¤±¤ò·×»»¤¹¤ë¡£ */ int mdraw_text_per_char_extents (MFrame *frame, @@ -2283,48 +2263,65 @@ mdraw_text_per_char_extents (MFrame *frame, return 0; } - for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;) - if (g->pos >= from && g->pos < to) + for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++) + if (g->g.from >= from && g->g.from < to) { - int start = g->pos; - int end = g->to; - int width = g->width; - int lbearing = g->lbearing; - int rbearing = g->rbearing; - int ascent = g->ascent; - int descent = g->descent; - int logical_ascent = g->rface->rfont->ascent; - int logical_descent = g->rface->rfont->descent; - - for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++) + int start = g->g.from; + int end = g->g.to; + int width = g->g.xadv; + int lbearing = g->g.lbearing; + int rbearing = g->g.rbearing; + int ascent = g->g.ascent; + int descent = g->g.descent; + int logical_ascent; + int logical_descent; + + if (g->rface->rfont) + { + logical_ascent = g->rface->rfont->ascent; + logical_descent = g->rface->rfont->descent; + } + else { - if (lbearing < width + g->lbearing) - lbearing = width + g->lbearing; - if (rbearing < width + g->rbearing) - rbearing = width + g->rbearing; - width += g->width; - if (ascent < g->ascent) - ascent = g->ascent; - if (descent < g->descent) - descent = g->descent; + logical_ascent = g->rface->ascent; + logical_descent = g->rface->descent; + } + for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++) + { + if (lbearing < width + g->g.lbearing) + lbearing = width + g->g.lbearing; + if (rbearing < width + g->g.rbearing) + rbearing = width + g->g.rbearing; + width += g->g.xadv; + if (ascent < g->g.ascent) + ascent = g->g.ascent; + if (descent < g->g.descent) + descent = g->g.descent; } if (end > to) end = to; while (start < end) { - ink_array_return[start - from].x = x + lbearing; - ink_array_return[start - from].y = - ascent; - ink_array_return[start - from].width = rbearing - lbearing; - ink_array_return[start - from].height = ascent + descent; - logical_array_return[start - from].x = x; - logical_array_return[start - from].y = - logical_descent; - logical_array_return[start - from].height - = logical_ascent + logical_descent; - logical_array_return[start - from].width = width; + if (ink_array_return) + { + ink_array_return[start - from].x = x + lbearing; + ink_array_return[start - from].y = - ascent; + ink_array_return[start - from].width = rbearing - lbearing; + ink_array_return[start - from].height = ascent + descent; + } + if (logical_array_return) + { + logical_array_return[start - from].x = x; + logical_array_return[start - from].y = - logical_descent; + logical_array_return[start - from].height + = logical_ascent + logical_descent; + logical_array_return[start - from].width = width; + } start++; } x += width; + g--; } if (overall_ink_return) @@ -2366,12 +2363,12 @@ mdraw_text_per_char_extents (MFrame *frame, mdraw_coordinates_position () returns the character position of that character.\n\n If $Y is less than the minimum Y-coordinate of the drawn area, it - returns $FROM.\n\n\n + returns $FROM.\n\n If $Y is greater than the maximum Y-coordinate of the drawn area, - it returns $TO.\n\n\n + it returns $TO.\n\n If $Y fits in with the drawn area but $X is less than the minimum X-coordinate, it returns the character position of the first - character drawn on the line $Y.\n\n\n + character drawn on the line $Y.\n\n If $Y fits in with the drawn area but $X is greater than the maximum X-coordinate, it returns the character position of the last character drawn on the line $Y. */ @@ -2380,25 +2377,21 @@ mdraw_text_per_char_extents (MFrame *frame, @brief »ØÄꤷ¤¿ºÂɸ¤ËºÇ¤â¶á¤¤Ê¸»ú¤Îʸ»ú°ÌÃÖ¤òÆÀ¤ë. ´Ø¿ô mdraw_coordinates_position () ¤Ï¡¢´Ø¿ô - mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤ - ¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è - ¤·¤¿¾ì¹ç¤Ë¡¢ºÂɸ ($X, $Y) ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Ç - ʸ»ú°ÌÃ֤Ȥϡ¢Åö³º M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨ - ¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£ + mdraw_text_with_control () ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤Æ¡¢ + M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤òºÂɸ (0, 0) + ¤òµ¯ÅÀ¤È¤·¤ÆÉÁ²è¤¹¤ëºÝ¤Ë¡¢ºÂɸ ($X, $Y) + ¤ËÉÁ²è¤µ¤ì¤ëʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£¤³¤³¤Çʸ»ú°ÌÃ֤Ȥϡ¢Åö³º + M-text Ãæ¤Ë¤ª¤¤¤Æ¤½¤Îʸ»ú¤¬ºÇ½é¤«¤é²¿ÈÖÌܤ«¤ò¼¨¤¹À°¿ô¤Ç¤¢¤ë¡£¤¿¤À¤·ºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤Ï0¤È¤¹¤ë¡£ $FRAME ¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¥Õ¥§¡¼¥¹¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤À¤±¤ËÍѤ¤¤é¤ì¤ë¡£ @return ºÂɸ ($X, $Y) ¤¬¤¢¤ëʸ»ú¤Î¥°¥ê¥Õ¤Çʤ¤ï¤ì¤ë¾ì¹ç¡¢ ´Ø¿ô - mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ - - ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£ - - ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礭¤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£ - + mdraw_coordinates_position () ¤Ï¤½¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n + ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®YºÂɸ¤è¤ê¤â¾®¤µ¤¤¤Ê¤é¤Ð $FROM ¤òÊÖ¤¹¡£\n\n + ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤ÎºÇÂçYºÂɸ¤è¤ê¤âÂ礭¤¤¤Ê¤é¤Ð $TO ¤òÊÖ¤¹¡£\n\n ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇ¾®XºÂɸ¤è¤ê¤â - ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ - + ¾®¤µ¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ½é¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£\n\n ¤â¤· $Y ¤¬ÉÁ²èÎΰè¤Ë¾è¤Ã¤Æ¤¤¤Æ¤«¤Ä $X ¤¬ÉÁ²èÎΰè¤ÎºÇÂçXºÂɸ¤è¤ê¤â Â礭¤¤¾ì¹ç¤Ï¡¢Ä¾Àþ y = $Y ¾å¤ËÉÁ²è¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Îʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */ @@ -2435,10 +2428,10 @@ mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to, if (! control->orientation_reversed) { width = gstring->indent; - for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++) - if (g->pos >= from && g->pos < to) + for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + if (g->g.from >= from && g->g.from < to) { - width += g->width; + width += g->g.xadv; if (width > x_offset) break; } @@ -2447,14 +2440,18 @@ mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to, { width = - gstring->indent; for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) - if (g->pos >= from && g->pos < to) + if (g->g.from >= from && g->g.from < to) { - width -= g->width; + width -= g->g.xadv; if (width < x_offset) break; } } - from = g->pos; + if (g->type == GLYPH_ANCHOR + && control->two_dimensional + && g[-1].g.c == '\n') + g--; + from = g->g.from; M17N_OBJECT_UNREF (gstring->top); return from; @@ -2475,10 +2472,10 @@ mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to, /***ja @brief ¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë. - ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ - ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO - ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS ¤Îʸ - »ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£ + ´Ø¿ô mdraw_glyph_info () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () + ¤¬ÉÁ ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO + ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¡¢M-text ¤Îʸ»ú°ÌÃÖ $POS + ¤Îʸ»ú¤òʤ¤¦¥°¥ê¥Õ¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë¡£ ¾ðÊó¤Ï$INFO ¤Î¥á¥ó¥Ð¤ËÊÝ»ý¤µ¤ì¤ë¡£ */ @@ -2517,26 +2514,25 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, if (! control->orientation_reversed) { info->x = gstring->indent; - for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++) - info->x += g->width; + for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++) + info->x += g->g.xadv; } else { info->x = - gstring->indent; - for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--) - info->x -= g->width; - while (g[-1].to == g->to) + for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--) + info->x -= g->g.xadv; + while (g[-1].g.to == g->g.to) g--; } - info->from = g->pos; - info->to = g->to; - info->glyph_code = g->code; - info->this.x = g->lbearing; - info->this.y = - gstring->line_ascent; - info->this.height = gstring->height; - info->this.width = - g->lbearing + g->width; + info->from = g->g.from; + info->to = g->g.to; + info->metrics.x = g->g.lbearing; + info->metrics.y = - gstring->line_ascent; + info->metrics.height = gstring->height; + info->metrics.width = - g->g.lbearing + g->g.xadv; if (g->rface->rfont) - info->font = &g->rface->rfont->font; + info->font = (MFont *) g->rface->rfont; else info->font = NULL; /* info->logical_width is calculated later. */ @@ -2546,23 +2542,24 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, /* The logically previous glyph is on this line. */ MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1); - info->prev_from = g_tmp->pos; + info->prev_from = g_tmp->g.from; } - else if (info->line_from > 0) + else if (info->line_from > 0 + && gstring->from > 0) { /* The logically previous glyph is on the previous line. */ MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1, gstring->from, control); MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1); - info->prev_from = g_tmp->pos; + info->prev_from = g_tmp->g.from; M17N_OBJECT_UNREF (gst->top); } else info->prev_from = -1; if (GLYPH_INDEX (g) > 1) - info->left_from = g[-1].pos, info->left_to = g[-1].to; + info->left_from = g[-1].g.from, info->left_to = g[-1].g.to; else if (! control->orientation_reversed) { if (info->line_from > 0) @@ -2573,7 +2570,7 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, gst = get_gstring (frame, mt, p, gstring->from, control); g_tmp = gst->glyphs + (gst->used - 2); - info->left_from = g_tmp->pos, info->left_to = g_tmp->to; + info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to; M17N_OBJECT_UNREF (gst->top); } else @@ -2589,7 +2586,7 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, gst = get_gstring (frame, mt, p, p + 1, control); g_tmp = gst->glyphs + (gst->used - 2); - info->left_from = g_tmp->pos, info->left_to = g_tmp->to; + info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to; M17N_OBJECT_UNREF (gst->top); } else @@ -2601,7 +2598,7 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, /* The logically next glyph is on this line. */ MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0); - info->next_to = g_tmp->to; + info->next_to = g_tmp->g.to; } else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt)) { @@ -2610,19 +2607,19 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control); MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0); - info->next_to = g_tmp->to; + info->next_to = g_tmp->g.to; M17N_OBJECT_UNREF (gst->top); } else info->next_to = -1; - for (info->logical_width = (g++)->width; - g->pos == pos && g->type != GLYPH_ANCHOR; - info->this.width += g->width, info->logical_width += (g++)->width); - info->this.width += g[-1].rbearing - g[-1].width; + for (info->logical_width = (g++)->g.xadv; + g->g.from == pos && g->type != GLYPH_ANCHOR; + info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv); + info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv; if (g->type != GLYPH_ANCHOR) - info->right_from = g->pos, info->right_to = g->to; + info->right_from = g->g.from, info->right_to = g->g.to; else if (! control->orientation_reversed) { if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt)) @@ -2631,7 +2628,7 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, M17N_OBJECT_UNREF (gstring->top); gstring = get_gstring (frame, mt, pos, pos + 1, control); g = MGLYPH (1); - info->right_from = g->pos, info->right_to = g->to; + info->right_from = g->g.from, info->right_to = g->g.to; } else info->right_from = info->right_to = -1; @@ -2644,7 +2641,7 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, M17N_OBJECT_UNREF (gstring->top); gstring = get_gstring (frame, mt, pos, pos + 1, control); g = MGLYPH (1); - info->right_from = g->pos, info->right_to = g->to; + info->right_from = g->g.from, info->right_to = g->g.to; } else info->right_from = info->right_to = -1; @@ -2656,9 +2653,47 @@ mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, /*=*/ +/***en + @brief Compute information about glyph sequence. + + The mdraw_glyph_list () function computes information about glyphs + corresponding to the text between $FROM and $TO of M-text $MT when + it is drawn on a window of frame $FRAME using the + mdraw_text_with_control () function with the drawing control + object $CONTROL. $GLYPHS is an array of objects to store the + information, and $ARRAY_SIZE is the array size. + + If $ARRAY_SIZE is large enough to cover all glyphs, it stores the + number of actually filled elements in the place pointed by + $NUM_GLYPHS_RETURN, and returns 0. + + Otherwise, it stores the required array size in the place pointed + by $NUM_GLYPHS_RETURN, and returns -1. */ + +/***ja + @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë. + + ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () + ¤¬ÉÁ²èÀ©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO + ¤Þ¤Ç¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS + ¤¬»Ø¤¹ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£ + + ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç¤¢¤ì¤Ð¡¢ + $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄꤷ 0 ¤òÊÖ¤¹¡£ + + + ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢$NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤ËɬÍפÊÇÛÎó¤Î¥µ¥¤¥º¤òÀßÄꤷ¡¢ + -1 ¤òÊÖ¤¹¡£ + */ + +/*** + @seealso + MDrawGlyph +*/ + int mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to, - MDrawControl *control, MDrawGlyphInfo *info, + MDrawControl *control, MDrawGlyph *glyphs, int array_size, int *num_glyphs_return) { MGlyphString *gstring; @@ -2675,38 +2710,53 @@ mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to, for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++) { if (g->type == GLYPH_BOX - || g->pos < from || g->pos >= to) + || g->g.from < from || g->g.from >= to) continue; if (g->type == GLYPH_PAD) { if (g->left_padding) - pad_width = g->width; + pad_width = g->g.xadv; else if (n > 0) { pad_width = 0; - info[-1].x += g->width; - info[-1].logical_width += g->width; + glyphs[-1].x_advance += g->g.xadv; } continue; } if (n < array_size) { - info->from = g->pos; - info->to = g->to; - info->glyph_code = g->code; - info->x = g->xoff + pad_width; - info->y = g->yoff; - info->this.x = g->lbearing; - info->this.y = - g->ascent; - info->this.height = g->ascent + g->descent; - info->this.width = g->rbearing - g->lbearing; - info->logical_width = g->width + pad_width; + glyphs->from = g->g.from; + glyphs->to = g->g.to; + glyphs->glyph_code = g->g.code; + glyphs->x_off = g->g.xoff + pad_width; + glyphs->y_off = g->g.yoff; + glyphs->lbearing = g->g.lbearing; + glyphs->rbearing = g->g.rbearing; + glyphs->ascent = g->g.ascent; + glyphs->descent = g->g.descent; + glyphs->x_advance = g->g.xadv + pad_width; + glyphs->y_advance = 0; if (g->rface->rfont) - info->font = &g->rface->rfont->font; + { + glyphs->font = (MFont *) g->rface->rfont; +#ifdef HAVE_FREETYPE + glyphs->font_type + = (glyphs->font->source == MFONT_SOURCE_X ? Mx + : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype + : Mxft); +#else /* not HAVE_FREETYPE */ + glyphs->font_type = Mx; +#endif /* not HAVE_FREETYPE */ + glyphs->fontp = g->rface->rfont->fontp; + } else - info->font = NULL; + { + glyphs->font = NULL; + glyphs->font_type = Mnil; + glyphs->fontp = NULL; + } pad_width = 0; - info++; + glyphs++; } n++; } @@ -2722,17 +2772,16 @@ mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to, @brief Draw one or more textitems. The mdraw_text_items () function draws one or more M-texts on - window $WIN of $FRAME at coordinate ($X, $Y). $ITEMS is an array + window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array of the textitems to be drawn and $NITEMS is the number of - textimtems in the array. */ + textitems in the array. */ /***ja @brief textitem ¤òɽ¼¨¤¹¤ë. - ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥­¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼ - ¥à $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS ¤Ï - ɽ¼¨¤¹¤Ù¤­¥Æ¥­¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î - ¸Ä¿ô¤Ç¤¢¤ë¡£ + ´Ø¿ô mdraw_text_items () ¤Ï¡¢°ì¸Ä°Ê¾å¤Î¥Æ¥­¥¹¥È¥¢¥¤¥Æ¥à¤ò¡¢¥Õ¥ì¡¼¥à + $FRAME ¤Î¥¦¥£¥ó¥É¥¦ $WIN ¤ÎºÂɸ ($X, $Y) ¤Ëɽ¼¨¤¹¤ë¡£$ITEMS + ¤Ïɽ¼¨¤¹¤Ù¤­¥Æ¥­¥¹¥È¥¢¥¤¥Æ¥à¤ÎÇÛÎó¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¤½¤Î¸Ä¿ô¤Ç¤¢¤ë¡£ @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */ @@ -2763,69 +2812,63 @@ mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y, } /*=*/ -/***en - @brief calculate a line breaking position. - - The function mdraw_default_line_break () calculates a line - breaking position based on the line number $LINE and the - coordinate $Y, when a line is too long to fit within the width - limit. $POS is the position of the character next to the last - one that fits within the limit. $FROM is the position of the - first character of the line, and TO is the position of the last - character displayed on the line if there were not width limit. - LINE and Y are reset to 0 when a line is broken by a newline - character, and incremented each time when a long line is broken - because of the width limit. +/***en + @brief Option of line breaking for drawing text. - @return - This function returns a character position to break the - line. + The variable #mdraw_line_break_option specifies line breaking + options by logical-or of the members of #MTextLineBreakOption. It + controls the line breaking algorithm of the function + mdraw_default_line_break (). */ + +int mdraw_line_break_option; +/*=*/ +/***en + @brief Calculate a line breaking position. + + The function mdraw_default_line_break () calculates a line + breaking position based on the line number $LINE and the + coordinate $Y, when a line is too long to fit within the width + limit. $POS is the position of the character next to the last one + that fits within the limit. $FROM is the position of the first + character of the line, and $TO is the position of the last + character displayed on the line if there were not width limit. + $LINE and $Y are reset to 0 when a line is broken by a newline + character, and incremented each time when a long line is broken + because of the width limit. + + @return + This function returns a character position to break the + line. */ + /***ja @brief ²þ¹Ô°ÌÃÖ¤ò·×»»¤¹¤ë. - ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì - ¹ç¤Ë¹Ô¤ò²þ¤á¤ë°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ LINE ¤ÈºÂɸ Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£ - $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£$FROM ¤Ï - ¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ë - ɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ LINE ¤È Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ - ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ - ¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£ + ´Ø¿ô mdraw_default_line_break () ¤Ï¡¢¹Ô¤¬ºÇÂçÉýÃæ¤Ë¼ý¤Þ¤é¤Ê¤¤¾ì¹ç¤Î²þ¹Ô°ÌÃÖ¤ò¡¢¹ÔÈÖ¹æ + $LINE ¤ÈºÂɸ $Y ¤Ë´ð¤Å¤¤¤Æ·×»»¤¹¤ë¡£ + $POS ¤ÏºÇÂçÉý¤Ë¼ý¤Þ¤ëºÇ¸å¤Îʸ»ú¤Î¼¡¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ + $FROM ¤Ï¤½¤Î¹Ô¤ÎºÇ½é¤Îʸ»ú¤Î°ÌÃÖ¡¢$TO + ¤ÏºÇÂçÉý¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤½¤Î¹Ô¤Ëɽ¼¨¤µ¤ì¤ëºÇ¸å¤Îʸ»ú¤Î°ÌÃ֤Ǥ¢¤ë¡£ + $LINE ¤È $Y ¤Ï²þ¹Ôʸ»ú¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿ºÝ¤Ë¤Ï 0 + ¤Ë¥ê¥»¥Ã¥È¤µ¤ì¡¢ºÇÂçÉý¤Ë¤è¤Ã¤Æ¹Ô¤¬²þ¤Þ¤Ã¤¿¾ì¹ç¤Ë¤Ï 1 ¤Å¤ÄÁý¤ä¤µ¤ì¤ë¡£ @return - ¤³¤Î´Ø¿ô¤Ï¹Ô¤ò²þ¤á¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ + ¤³¤Î´Ø¿ô¤Ï²þ¹Ô¤¹¤ëʸ»ú°ÌÃÖ¤òÊÖ¤¹¡£ */ int mdraw_default_line_break (MText *mt, int pos, int from, int to, int line, int y) { - int c = mtext_ref_char (mt, pos); - int orig_pos = pos; - - if (c == ' ' || c == '\t') - { - pos++; - while (pos < to - && ((c = mtext_ref_char (mt, pos)) == ' ' || c == '\t')) - pos++; - } - else - { - while (pos > from) - { - if (c == ' ' || c == '\t') - break; - pos--; - c = mtext_ref_char (mt, pos); - } - if (pos == from) - pos = orig_pos; - else - pos++; - } - return pos; + int p, after; + + p = mtext_line_break (mt, pos, mdraw_line_break_option, &after); + if (p < from) + p = from; + else if (p >= to) + p = to; + return p; } /*=*/ @@ -2850,17 +2893,17 @@ mdraw_default_line_break (MText *mt, int pos, /***ja @brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë. - ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï - ¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç - »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ - ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï - ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤« - ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì - ¤Ð¤Ê¤é¤Ê¤¤¡£ + ´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT + Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϤò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢ + $MT ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç»ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME + ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢$MT + Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈϰϾðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£É½¼¨ÈϰϾðÊó¤È¤Ï¡¢ + ɽ¼¨¸¶ÅÀ¤«¤é¤ÎÁêÂаÌÃ֤ȳÆʸ»ú¤ÎÀê¤á¤ëĹÊý·Á¤Ç¤¢¤ë¡£$ARRAY_RETURN + ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text Ãæ¤Îʸ»ú¿ô°Ê¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£ - ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥­¥¹¥ÈÁ´ÂΤÎɽ - ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ - ¤¹¤ë¡£ + ¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL + ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥­¥¹¥ÈÁ´ÂΤÎɽ¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò + $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ¤¹¤ë¡£ @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */ @@ -2880,7 +2923,7 @@ mdraw_per_char_extents (MFrame *frame, MText *mt, The mdraw_clear_cache () function clear cached information on M-text $MT that was attached by any of the drawing functions. - When the behaviour of `format' or `line_break' + When the behavior of `format' or `line_break' member functions of MDrawControl is changed, the cache must be cleared. @seealso @@ -2888,10 +2931,11 @@ mdraw_per_char_extents (MFrame *frame, MText *mt, /***ja @brief ¥­¥ã¥Ã¥·¥å¾ðÊó¤ò¾Ã¤¹. - ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT ¤ËÉղà - ¤µ¤ì¤¿¥­¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' ¤¢ - ¤ë¤¤¤Ï `line_break' ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥­¥ã¥Ã¥·¥å - ¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ + ´Ø¿ô mdraw_clear_cache () ¤ÏÉÁ²è´Ø¿ô¤Ë¤è¤Ã¤Æ M-text $MT + ¤ËÉղ䵤줿¥­¥ã¥Ã¥·¥å¾ðÊó¤ò¤¹¤Ù¤Æ¾Ãµî¤¹¤ë¡£MDrawControl ¤Î `format' + ¤¢¤ë¤¤¤Ï `line_break' + ¥á¥ó¥Ð´Ø¿ô¤Î¿¶Éñ¤¤¤¬ÊѤï¤Ã¤¿¾ì¹ç¤Ë¤Ï¥­¥ã¥Ã¥·¥å¤ò¾Ãµî¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ + @seealso MDrawControl */