Module: wine
Branch: master
Commit: 032543e54dec387ae0089fe9e5dd0cc0fbc2d253
URL: http://source.winehq.org/git/wine.git/?a=commit;h=032543e54dec387ae0089fe9e…
Author: Maarten Lankhorst <m.b.lankhorst(a)gmail.com>
Date: Sat Sep 15 15:16:38 2007 +0200
gdi: Implement neutrals resolving in BiDi.
---
dlls/gdi32/bidi.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/dlls/gdi32/bidi.c b/dlls/gdi32/bidi.c
index 0c9103a..59f3fff 100644
--- a/dlls/gdi32/bidi.c
+++ b/dlls/gdi32/bidi.c
@@ -613,6 +613,163 @@ static void resolveWeak(int baselevel, WORD *pcls, WORD *plevel, int cch)
SetDeferredRun(pcls, cchRun, ich, clsRun);
}
+/* RESOLVE NEUTRAL TYPES */
+
+/* action values */
+enum neutralactions
+{
+ /* action to resolve previous input */
+ nL = L, /* resolve EN to L */
+ En = 3 << 4, /* resolve neutrals run to embedding level direction */
+ Rn = R << 4, /* resolve neutrals run to strong right */
+ Ln = L << 4, /* resolved neutrals run to strong left */
+ In = (1<<8), /* increment count of deferred neutrals */
+ LnL = (1<<4)+L, /* set run and EN to L */
+};
+
+static int GetDeferredNeutrals(int action, int level)
+{
+ action = (action >> 4) & 0xF;
+ if (action == (En >> 4))
+ return EmbeddingDirection(level);
+ else
+ return action;
+}
+
+static int GetResolvedNeutrals(int action)
+{
+ action = action & 0xF;
+ if (action == In)
+ return 0;
+ else
+ return action;
+}
+
+/* state values */
+enum resolvestates
+{
+ /* new temporary class */
+ r, /* R and characters resolved to R */
+ l, /* L and characters resolved to L */
+ rn, /* N preceded by right */
+ ln, /* N preceded by left */
+ a, /* AN preceded by left (the abbrev 'la' is used up above) */
+ na, /* N preceeded by a */
+} ;
+
+
+/*------------------------------------------------------------------------
+ Notes:
+
+ By rule W7, whenever a EN is 'dominated' by an L (including start of
+ run with embedding direction = L) it is resolved to, and further treated
+ as L.
+
+ This leads to the need for 'a' and 'na' states.
+------------------------------------------------------------------------*/
+
+static const int actionNeutrals[][5] =
+{
+/* N, L, R, AN, EN = cls */
+ { In, 0, 0, 0, 0 }, /* r right */
+ { In, 0, 0, 0, L }, /* l left */
+
+ { In, En, Rn, Rn, Rn }, /* rn N preceded by right */
+ { In, Ln, En, En, LnL}, /* ln N preceded by left */
+
+ { In, 0, 0, 0, L }, /* a AN preceded by left */
+ { In, En, Rn, Rn, En }, /* na N preceded by a */
+} ;
+
+static const int stateNeutrals[][5] =
+{
+/* N, L, R, AN, EN */
+ { rn, l, r, r, r }, /* r right */
+ { ln, l, r, a, l }, /* l left */
+
+ { rn, l, r, r, r }, /* rn N preceded by right */
+ { ln, l, r, a, l }, /* ln N preceded by left */
+
+ { na, l, r, a, l }, /* a AN preceded by left */
+ { na, l, r, a, l }, /* na N preceded by la */
+} ;
+
+/*------------------------------------------------------------------------
+ Function: resolveNeutrals
+
+ Resolves the directionality of neutral character types.
+
+ Implements rules W7, N1 and N2 of the Unicode Bidi Algorithm.
+
+ Input: Array of embedding levels
+ Character count
+ Baselevel
+
+ In/Out: Array of directional classes
+
+ Note: On input only these directional classes are expected
+ R, L, N, AN, EN and BN
+
+ W8 resolves a number of ENs to L
+------------------------------------------------------------------------*/
+static void resolveNeutrals(int baselevel, WORD *pcls, const WORD *plevel, int cch)
+{
+ /* the state at the start of text depends on the base level */
+ int state = odd(baselevel) ? r : l;
+ int cls;
+
+ int cchRun = 0;
+ int level = baselevel;
+
+ int action, clsRun, clsNew;
+ int ich = 0;
+ for (; ich < cch; ich++)
+ {
+ /* ignore boundary neutrals */
+ if (pcls[ich] == BN)
+ {
+ /* include in the count for a deferred run */
+ if (cchRun)
+ cchRun++;
+
+ /* skip any further processing */
+ continue;
+ }
+
+ ASSERT(pcls[ich] < 5); /* "Only N, L, R, AN, EN are allowed" */
+ cls = pcls[ich];
+
+ action = actionNeutrals[state][cls];
+
+ /* resolve the directionality for deferred runs */
+ clsRun = GetDeferredNeutrals(action, level);
+ if (clsRun != N)
+ {
+ SetDeferredRun(pcls, cchRun, ich, clsRun);
+ cchRun = 0;
+ }
+
+ /* resolve the directionality class at the current location */
+ clsNew = GetResolvedNeutrals(action);
+ if (clsNew != N)
+ pcls[ich] = clsNew;
+
+ if (In & action)
+ cchRun++;
+
+ state = stateNeutrals[state][cls];
+ level = plevel[ich];
+ }
+
+ /* resolve any deferred runs */
+ cls = EmbeddingDirection(level); /* eor has type of current level */
+
+ /* resolve the directionality for deferred runs */
+ clsRun = GetDeferredNeutrals(actionNeutrals[state][cls], level);
+ if (clsRun != N)
+ SetDeferredRun(pcls, cchRun, ich, clsRun);
+}
+
/*************************************************************
* BIDI_Reorder
*/
@@ -708,6 +865,9 @@ BOOL BIDI_Reorder(
/* resolve weak */
resolveWeak(baselevel, chartype, levels, i);
+ /* resolve neutrals */
+ resolveNeutrals(baselevel, chartype, levels, i);
+
/* Temporary stub: Just reverse the odd levels */
for (j = lastgood = 0; j < i; ++j)
if (levels[j] != levels[lastgood])