Module: wine Branch: master Commit: 32b9b63a424143509dd3e0978bbf246f15a71448 URL: http://source.winehq.org/git/wine.git/?a=commit;h=32b9b63a424143509dd3e0978b...
Author: Aric Stewart aric@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);