Aric Stewart : usp10: Add Arabic shaping.

Alexandre Julliard julliard at winehq.org
Thu May 20 11:02:55 CDT 2010


Module: wine
Branch: master
Commit: 32b9b63a424143509dd3e0978bbf246f15a71448
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=32b9b63a424143509dd3e0978bbf246f15a71448

Author: Aric Stewart <aric at codeweavers.com>
Date:   Wed May 19 09:17:00 2010 -0500

usp10: Add Arabic shaping.

---

 dlls/usp10/Makefile.in      |    1 +
 dlls/usp10/shape.c          |  152 +++++++++++++++++++++++++++++++++++++++++++
 dlls/usp10/usp10.c          |   23 +------
 dlls/usp10/usp10_internal.h |   21 ++++++
 4 files changed, 178 insertions(+), 19 deletions(-)

diff --git a/dlls/usp10/Makefile.in b/dlls/usp10/Makefile.in
index 027bdfb..f52aafb 100644
--- a/dlls/usp10/Makefile.in
+++ b/dlls/usp10/Makefile.in
@@ -9,6 +9,7 @@ IMPORTS   = gdi32 kernel32
 C_SRCS = \
 	bidi.c \
 	mirror.c \
+	shape.c \
 	shaping.c \
 	usp10.c
 
diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c
new file mode 100644
index 0000000..c743c04
--- /dev/null
+++ b/dlls/usp10/shape.c
@@ -0,0 +1,152 @@
+/*
+ * Implementation of Shaping for the Uniscribe Script Processor (usp10.dll)
+ *
+ * Copyright 2010 CodeWeavers, Aric Stewart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "usp10.h"
+
+#include "usp10_internal.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
+
+#define FIRST_ARABIC_CHAR 0x0600
+#define LAST_ARABIC_CHAR  0x06ff
+
+extern const unsigned short wine_shaping_table[];
+extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4];
+
+enum joining_types {
+    jtU,
+    jtT,
+    jtR,
+    jtL,
+    jtD,
+    jtC
+};
+
+enum joined_forms {
+    Xn=0,
+    Xl,
+    Xr,
+    Xm
+};
+
+static CHAR neighbour_joining_type(int i, int delta, const CHAR* context_type, INT cchLen, SCRIPT_ANALYSIS *psa)
+{
+    if (i + delta < 0)
+    {
+        if (psa->fLinkBefore)
+            return jtR;
+        else
+            return jtU;
+    }
+    if ( i+ delta >= cchLen)
+    {
+        if (psa->fLinkAfter)
+            return jtL;
+        else
+            return jtU;
+    }
+
+    i += delta;
+
+    if (context_type[i] == jtT)
+        return neighbour_joining_type(i,delta,context_type,cchLen,psa);
+    else
+        return context_type[i];
+}
+
+static inline BOOL right_join_causing(CHAR joining_type)
+{
+    return (joining_type == jtR || joining_type == jtD || joining_type == jtC);
+}
+
+static inline BOOL left_join_causing(CHAR joining_type)
+{
+    return (joining_type == jtL || joining_type == jtD || joining_type == jtC);
+}
+
+/* SHAPE_ShapeArabicGlyphs
+ */
+void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT cMaxGlyphs)
+{
+    CHAR *context_type;
+    INT *context_shape;
+    INT dirR, dirL;
+    int i;
+
+    if (psa->eScript != Script_Arabic)
+        return;
+
+    if (!psa->fLogicalOrder && psa->fRTL)
+    {
+        dirR = -1;
+        dirL = 1;
+    }
+    else
+    {
+        dirR = 1;
+        dirL = -1;
+    }
+
+    context_type = HeapAlloc(GetProcessHeap(),0,cChars);
+    context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars);
+
+    for (i = 0; i < cChars; i++)
+        context_type[i] = wine_shaping_table[wine_shaping_table[pwcChars[i] >> 8] + (pwcChars[i] & 0xff)];
+
+    for (i = 0; i < cChars; i++)
+    {
+        if (context_type[i] == jtR && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
+            context_shape[i] = Xr;
+        else if (context_type[i] == jtL && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
+            context_shape[i] = Xl;
+        else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)) && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
+            context_shape[i] = Xm;
+        else if (context_type[i] == jtD && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
+            context_shape[i] = Xr;
+        else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)))
+            context_shape[i] = Xl;
+        else
+            context_shape[i] = Xn;
+    }
+
+    for (i = 0; i < cChars; i++)
+    {
+        WORD newGlyph = pwOutGlyphs[i];
+
+        if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <= LAST_ARABIC_CHAR)
+        {
+            WCHAR context_char = wine_shaping_forms[pwcChars[i] - FIRST_ARABIC_CHAR][context_shape[i]];
+            if (context_char != pwcChars[i] && GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000)
+                pwOutGlyphs[i] = newGlyph;
+        }
+    }
+
+    HeapFree(GetProcessHeap(),0,context_shape);
+    HeapFree(GetProcessHeap(),0,context_type);
+}
diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c
index b9294e2..70d3738 100644
--- a/dlls/usp10/usp10.c
+++ b/dlls/usp10/usp10.c
@@ -141,18 +141,6 @@ static const SCRIPT_PROPERTIES *script_props[] =
     &props[73]
 };
 
-#define GLYPH_BLOCK_SHIFT 8
-#define GLYPH_BLOCK_SIZE  (1UL << GLYPH_BLOCK_SHIFT)
-#define GLYPH_BLOCK_MASK  (GLYPH_BLOCK_SIZE - 1)
-#define GLYPH_MAX         65536
-
-typedef struct {
-    LOGFONTW lf;
-    TEXTMETRICW tm;
-    WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE];
-    ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
-} ScriptCache;
-
 typedef struct {
     int numGlyphs;
     WORD* glyphs;
@@ -529,13 +517,6 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
 #define Syriac_stop   0x074f
 #define Latin_start   0x0001
 #define Latin_stop    0x024f
-#define Script_Syriac  8
-#define Script_Hebrew  7
-#define Script_Arabic  6
-#define Script_Latin   1
-#define Script_Numeric 5
-#define Script_CR      22
-#define Script_LF      23
 
     int   cnt = 0, index = 0;
     int   New_Script = SCRIPT_UNDEFINED;
@@ -1395,6 +1376,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
 
     if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex)
     {
+        WCHAR *rChars = heap_alloc(sizeof(WCHAR) * cChars);
         for (i = 0; i < cChars; i++)
         {
             int idx = i;
@@ -1411,7 +1393,10 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
                 if (GetGlyphIndicesW(hdc, &chInput, 1, &glyph, 0) == GDI_ERROR) return S_FALSE;
                 pwOutGlyphs[i] = set_cache_glyph(psc, chInput, glyph);
             }
+            rChars[i] = chInput;
         }
+        SHAPE_ShapeArabicGlyphs(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, cMaxGlyphs);
+        heap_free(rChars);
     }
     else
     {
diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h
index 60e4eff..dfe3460 100644
--- a/dlls/usp10/usp10_internal.h
+++ b/dlls/usp10/usp10_internal.h
@@ -19,6 +19,26 @@
  *
  */
 
+#define Script_Syriac  8
+#define Script_Hebrew  7
+#define Script_Arabic  6
+#define Script_Latin   1
+#define Script_Numeric 5
+#define Script_CR      22
+#define Script_LF      23
+
+#define GLYPH_BLOCK_SHIFT 8
+#define GLYPH_BLOCK_SIZE  (1UL << GLYPH_BLOCK_SHIFT)
+#define GLYPH_BLOCK_MASK  (GLYPH_BLOCK_SIZE - 1)
+#define GLYPH_MAX         65536
+
+typedef struct {
+    LOGFONTW lf;
+    TEXTMETRICW tm;
+    WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE];
+    ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
+} ScriptCache;
+
 #define odd(x) ((x) & 1)
 
 BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s,
@@ -26,3 +46,4 @@ BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s,
 
 INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
 INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
+void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT cMaxGlyphs);




More information about the wine-cvs mailing list