From: handa Date: Wed, 7 Nov 2007 12:03:04 +0000 (+0000) Subject: (analyse_bidi_level): New function. X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=19c057e9d10e0f5339ef8bdb43721cc2d9585efd;p=m17n%2Fm17n-lib.git (analyse_bidi_level): New function. (visual_order): Do reordering using the already decided bidi-level. (compose_glyph_string): Decide bidi-level before calling flt. --- diff --git a/src/draw.c b/src/draw.c index 6d81532..101eb04 100644 --- a/src/draw.c +++ b/src/draw.c @@ -100,23 +100,21 @@ 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 = 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); @@ -149,63 +147,94 @@ visual_order (MGlyphString *gstring) } if (! bidi_sensitive) - return; + return 0; - glyphs = alloca (sizeof (MGlyph) * len); - memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len); #ifdef HAVE_FRIBIDI - visual = alloca (sizeof (FriBidiChar) * (len + 1)); - indices = alloca (sizeof (FriBidiStrIndex) * (len + 1)); 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++) { - if (levels[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; gidx++) + { + 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; - for (i = 0; i < len;) - { - /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */ - int j = indices[i]; - /* Length of grapheme-cluster */ - int seglen; + 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; - g = glyphs + i; -#ifdef HAVE_FRIBIDI - if (visual[j] != logical[i]) - { - /* Mirrored. */ - g->g.c = visual[j]; - if (g->rface->rfont) - g->g.code = mfont__encode_char (NULL, (MFont *) g->rface->rfont, - NULL, g->g.c); + for (i--; glyphs[i].bidi_level >= level; i--); + if (! glyphs[i].rface) + for (i = save; ! glyphs[i].rface; i++); + } } -#endif /* HAVE_FRIBIDI */ - g->bidi_level = levels[i]; - for (seglen = 1, g++; - i + seglen < len && glyphs[i].g.from == glyphs[i + seglen].g.from; - seglen++, g++) + } + for (i = 1; i < gstring->used - 1; i++) + { + MGlyph *g = gstring->glyphs + i; + + for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++); + if (j > i) { - g->bidi_level = levels[i]; - if (indices[i + seglen] < j) - j = indices[i + seglen]; + memcpy (glyphs + i, gstring->glyphs + i, + sizeof (MGlyph) * (j - i + 1)); + for (; i <= j; i++) + g[j - i] = glyphs[i]; + i--; } - memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen); - i += seglen; } } @@ -308,6 +337,7 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, MRealizedFace *rface = default_rface; MRealizedFont *rfont; int size = gstring->control.fixed_width; + int max_bidi_level = 0; int i; MLIST_RESET (gstring); @@ -408,6 +438,9 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to, 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; @@ -547,7 +580,7 @@ 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); }