gdi: Implement neutrals resolving in BiDi.

This commit is contained in:
Maarten Lankhorst 2007-09-15 15:16:38 +02:00 committed by Alexandre Julliard
parent 6554e5b1a1
commit 032543e54d
1 changed files with 160 additions and 0 deletions

View File

@ -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])