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);
}
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;
}
}
MRealizedFace *rface = default_rface;
MRealizedFont *rfont;
int size = gstring->control.fixed_width;
+ int max_bidi_level = 0;
int i;
MLIST_RESET (gstring);
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 <rface> member for non-ASCII
characters if necessary. */
stop = charset_change = language_change = from;
}
/* At last, reorder glyphs visually if necessary. */
- if (gstring->control.enable_bidi)
+ if (max_bidi_level > 0)
visual_order (gstring);
}