usp10: Add Arabic shaping.
This commit is contained in:
parent
a5fe688704
commit
32b9b63a42
|
@ -9,6 +9,7 @@ IMPORTS = gdi32 kernel32
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
bidi.c \
|
bidi.c \
|
||||||
mirror.c \
|
mirror.c \
|
||||||
|
shape.c \
|
||||||
shaping.c \
|
shaping.c \
|
||||||
usp10.c
|
usp10.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);
|
||||||
|
}
|
|
@ -141,18 +141,6 @@ static const SCRIPT_PROPERTIES *script_props[] =
|
||||||
&props[73]
|
&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 {
|
typedef struct {
|
||||||
int numGlyphs;
|
int numGlyphs;
|
||||||
WORD* glyphs;
|
WORD* glyphs;
|
||||||
|
@ -529,13 +517,6 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
|
||||||
#define Syriac_stop 0x074f
|
#define Syriac_stop 0x074f
|
||||||
#define Latin_start 0x0001
|
#define Latin_start 0x0001
|
||||||
#define Latin_stop 0x024f
|
#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 cnt = 0, index = 0;
|
||||||
int New_Script = SCRIPT_UNDEFINED;
|
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)
|
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex)
|
||||||
{
|
{
|
||||||
|
WCHAR *rChars = heap_alloc(sizeof(WCHAR) * cChars);
|
||||||
for (i = 0; i < cChars; i++)
|
for (i = 0; i < cChars; i++)
|
||||||
{
|
{
|
||||||
int idx = 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;
|
if (GetGlyphIndicesW(hdc, &chInput, 1, &glyph, 0) == GDI_ERROR) return S_FALSE;
|
||||||
pwOutGlyphs[i] = set_cache_glyph(psc, chInput, glyph);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
#define odd(x) ((x) & 1)
|
||||||
|
|
||||||
BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s,
|
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_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);
|
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);
|
||||||
|
|
Loading…
Reference in New Issue