usp10: Add Syriac contextual shaping.

This commit is contained in:
Aric Stewart 2010-08-12 14:58:46 -05:00 committed by Alexandre Julliard
parent 0401f6c088
commit 4ffd3e6af6
1 changed files with 120 additions and 3 deletions

View File

@ -41,6 +41,7 @@ typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*,
WCHAR*, INT, WORD*, INT*, INT);
static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs);
extern const unsigned short wine_shaping_table[];
extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4];
@ -58,7 +59,11 @@ enum joined_forms {
Xn=0,
Xr,
Xl,
Xm
Xm,
/* Syriac Alaph */
Afj,
Afn,
Afx
};
#ifdef WORDS_BIGENDIAN
@ -244,7 +249,11 @@ static const char* contextual_features[] =
"isol",
"fina",
"init",
"medi"
"medi",
/* Syriac Alaph */
"med2",
"fin2",
"fin3"
};
static OPENTYPE_FEATURE_RECORD standard_features[] =
@ -294,7 +303,7 @@ static const ScriptShapeData ShapingData[] =
{{ arabic_features, 6}, "arab", ContextualShape_Arabic},
{{ arabic_features, 6}, "arab", ContextualShape_Arabic},
{{ hebrew_features, 1}, "hebr", NULL},
{{ syriac_features, 4}, "syrc", NULL},
{{ syriac_features, 4}, "syrc", ContextualShape_Syriac},
{{ arabic_features, 6}, "arab", ContextualShape_Arabic},
};
@ -829,6 +838,18 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W
return GSUB_E_NOFEATURE;
}
static WCHAR neighbour_char(int i, int delta, const WCHAR* chars, INT cchLen)
{
if (i + delta < 0)
return 0;
if ( i+ delta >= cchLen)
return 0;
i += delta;
return chars[i];
}
static CHAR neighbour_joining_type(int i, int delta, const CHAR* context_type, INT cchLen, SCRIPT_ANALYSIS *psa)
{
if (i + delta < 0)
@ -864,6 +885,14 @@ static inline BOOL left_join_causing(CHAR joining_type)
return (joining_type == jtR || joining_type == jtD || joining_type == jtC);
}
static inline BOOL word_break_causing(WCHAR chr)
{
/* we are working within a string of characters already guareented to
be within one script, Syriac, so we do not worry about any characers
other than the space character outside of that range */
return (chr == 0 || chr == 0x20 );
}
/*
* ContextualShape_Arabic
*/
@ -949,6 +978,94 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
HeapFree(GetProcessHeap(),0,context_type);
}
/*
* ContextualShape_Syriac
*/
#define ALAPH 0x710
#define DALATH 0x715
#define RISH 0x72A
static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
{
CHAR *context_type;
INT *context_shape;
INT dirR, dirL;
int i;
if (*pcGlyphs != cChars)
{
ERR("Number of Glyphs and Chars need to match at the beginning\n");
return;
}
if (!psa->fLogicalOrder && psa->fRTL)
{
dirR = 1;
dirL = -1;
}
else
{
dirR = -1;
dirL = 1;
}
if (!psc->GSUB_Table)
psc->GSUB_Table = load_gsub_table(hdc);
if (!psc->GSUB_Table)
return;
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 (pwcChars[i] == ALAPH)
{
WCHAR rchar = neighbour_char(i,dirR,pwcChars,cChars);
if (left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
context_shape[i] = Afj;
else if ( rchar != DALATH && rchar != RISH &&
!left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) &&
word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
context_shape[i] = Afn;
else if ( (rchar == DALATH || rchar == RISH) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars)))
context_shape[i] = Afx;
}
else 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;
}
/* Contextual Shaping */
i = 0;
while(i < *pcGlyphs)
{
INT nextIndex;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc->GSUB_Table, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
if (nextIndex > GSUB_E_NOGLYPH)
i = nextIndex;
}
HeapFree(GetProcessHeap(),0,context_shape);
HeapFree(GetProcessHeap(),0,context_type);
}
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs)
{
if (ShapingData[psa->eScript].contextProc)