[PATCH] gdi: Implement explicit resolving in BiDi

Maarten Lankhorst m.b.lankhorst at gmail.com
Sat Sep 15 08:03:22 CDT 2007


---
 dlls/gdi32/bidi.c |  124 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/dlls/gdi32/bidi.c b/dlls/gdi32/bidi.c
index 11a41a7..60c55bb 100644
--- a/dlls/gdi32/bidi.c
+++ b/dlls/gdi32/bidi.c
@@ -36,6 +36,7 @@
 WINE_DEFAULT_DEBUG_CHANNEL(bidi);
 
 #define ASSERT(x) if (!(x)) FIXME("assert failed: %s\n", #x); else ;
+#define MAX_LEVEL 61
 
 /* HELPER FUNCTIONS AND DECLARATIONS */
 
@@ -221,6 +222,114 @@ static int resolveParagraphs(WORD *types, int cch)
     return ich;
 }
 
+/* RESOLVE EXPLICIT */
+
+static WORD GreaterEven(int i)
+{
+    return odd(i) ? i + 1 : i + 2;
+}
+
+static WORD GreaterOdd(int i)
+{
+    return odd(i) ? i + 2 : i + 1;
+}
+
+/*------------------------------------------------------------------------
+    Function: resolveExplicit
+
+    Recursively resolves explicit embedding levels and overrides.
+    Implements rules X1-X9, of the Unicode Bidirectional Algorithm.
+
+    Input: Base embedding level and direction
+           Character count
+
+    Output: Array of embedding levels
+
+    In/Out: Array of direction classes
+
+
+    Note: The function uses two simple counters to keep track of
+          matching explicit codes and PDF. Use the default argument for
+          the outermost call. The nesting counter counts the recursion
+          depth and not the embedding level.
+------------------------------------------------------------------------*/
+
+static int resolveExplicit(int level, int dir, WORD *pcls, WORD *plevel, int cch, int nNest)
+{
+    /* always called with a valid nesting level
+       nesting levels are != embedding levels */
+    int nLastValid = nNest;
+    int ich = 0;
+
+    /* check input values */
+    ASSERT(nNest >= 0 && level >= 0 && level <= MAX_LEVEL);
+
+    /* process the text */
+    for (; ich < cch; ich++)
+    {
+        WORD cls = pcls[ich];
+        switch (cls)
+        {
+        case LRO:
+        case LRE:
+            nNest++;
+            if (GreaterEven(level) <= MAX_LEVEL - (cls == LRO ? 2 : 0))
+            {
+                plevel[ich] = GreaterEven(level);
+                pcls[ich] = BN;
+                ich += resolveExplicit(plevel[ich], (cls == LRE ? N : L),
+                            &pcls[ich+1], &plevel[ich+1],
+                             cch - (ich+1), nNest);
+                nNest--;
+                continue;
+            }
+            cls = pcls[ich] = BN;
+            break;
+
+        case RLO:
+        case RLE:
+            nNest++;
+            if (GreaterOdd(level) <= MAX_LEVEL - (cls == RLO ? 2 : 0))
+            {
+                plevel[ich] = GreaterOdd(level);
+                pcls[ich] = BN;
+                ich += resolveExplicit(plevel[ich], (cls == RLE ? N : R),
+                                &pcls[ich+1], &plevel[ich+1],
+                                 cch - (ich+1), nNest);
+                nNest--;
+                continue;
+            }
+            cls = pcls[ich] = BN;
+            break;
+
+        case PDF:
+            cls = pcls[ich] = BN;
+            if (nNest)
+            {
+                if (nLastValid < nNest)
+                {
+                    nNest--;
+                }
+                else
+                {
+                    cch = ich; /* break the loop, but complete body */
+                }
+            }
+        }
+
+        /* Apply the override */
+        if (dir != N)
+        {
+            cls = dir;
+        }
+        plevel[ich] = level;
+        if (pcls[ich] != BN)
+            pcls[ich] = cls;
+    }
+
+    return ich;
+}
+
 /*************************************************************
  *    BIDI_Reorder
  */
@@ -310,10 +419,17 @@ BOOL BIDI_Reorder(
             }
         }
 
-        /* Temporary stub: Assume everything is in the direction we want */
-        memset(levels, baselevel, i * sizeof(WORD));
-        if (baselevel)
-            reverse(lpOutString, i);
+        /* resolve explicit */
+        resolveExplicit(baselevel, forcedir, chartype, levels, i, 0);
+
+        /* Temporary stub: Just reverse the odd levels */
+        for (j = lastgood = 0; j < i; ++j)
+            if (levels[j] != levels[lastgood])
+            {
+                if (odd(levels[lastgood]))
+                    reverse(lpOutString + done + lastgood, j - 1);
+                lastgood = j;
+            }
 
         if (lpOrder)
         {
-- 
1.5.2.5


--------------090607040306040304070602--



More information about the wine-patches mailing list