usp10: Fix Contextual Shaping for Languages with RTL write order.

Including Arabic, Syriac, Phags pa, and Mongolian.

Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Aric Stewart 2017-01-27 11:31:15 -06:00 committed by Alexandre Julliard
parent 915acd68de
commit 10e9adfb27
1 changed files with 94 additions and 30 deletions

View File

@ -1072,6 +1072,8 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@ -1115,8 +1117,12 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
}
/* Contextual Shaping */
i = 0;
while(i < *pcGlyphs)
if (dirL > 0)
char_index = glyph_index = 0;
else
char_index = glyph_index = cChars-1;
while(char_index < cChars && char_index >= 0)
{
BOOL shaped = FALSE;
@ -1124,29 +1130,34 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
{
INT nextIndex;
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
/* Apply the contextual feature */
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
i = nextIndex;
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
UpdateClusters(glyph_index, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
char_index += dirL;
glyph_index = nextIndex;
}
shaped = (nextIndex > GSUB_E_NOGLYPH);
}
if (!shaped)
{
if (context_shape[i] == Xn)
if (context_shape[char_index] == Xn)
{
WORD newGlyph = pwOutGlyphs[i];
if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <= LAST_ARABIC_CHAR)
WORD newGlyph = pwOutGlyphs[glyph_index];
if (pwcChars[char_index] >= FIRST_ARABIC_CHAR && pwcChars[char_index] <= LAST_ARABIC_CHAR)
{
/* fall back to presentation form B */
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;
WCHAR context_char = wine_shaping_forms[pwcChars[char_index] - FIRST_ARABIC_CHAR][context_shape[char_index]];
if (context_char != pwcChars[char_index] && GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000)
pwOutGlyphs[glyph_index] = newGlyph;
}
}
i++;
char_index += dirL;
glyph_index += dirL;
}
}
@ -1293,6 +1304,8 @@ static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@ -1355,19 +1368,45 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)))
}
/* Contextual Shaping */
i = 0;
while(i < *pcGlyphs)
if (dirL > 0)
char_index = glyph_index = 0;
else
char_index = glyph_index = cChars-1;
while(char_index < cChars && char_index >= 0)
{
INT nextIndex;
INT nextIndex, offset = 0;
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
/* Apply CCMP first */
apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, "ccmp");
if (prevCount != *pcGlyphs)
{
offset = *pcGlyphs - prevCount;
if (dirL < 0)
glyph_index -= offset * dirL;
}
/* Apply the contextual feature */
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
i = nextIndex;
char_index += dirL;
if (!offset)
glyph_index = nextIndex;
else
{
offset = *pcGlyphs - prevCount;
glyph_index += dirL * (offset + 1);
}
}
else
i++;
{
char_index += dirL;
glyph_index += dirL;
}
}
HeapFree(GetProcessHeap(),0,context_shape);
@ -1427,6 +1466,8 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
INT *context_shape;
INT dirR, dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@ -1475,24 +1516,36 @@ static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
}
/* Contextual Shaping */
i = 0;
while(i < *pcGlyphs)
if (dirL > 0)
char_index = glyph_index = 0;
else
char_index = glyph_index = cChars-1;
while(char_index < cChars && char_index >= 0)
{
if (context_shape[i] >= 0)
if (context_shape[char_index] >= 0)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
i = nextIndex;
glyph_index = nextIndex;
char_index += dirL;
}
else
i++;
{
char_index += dirL;
glyph_index += dirL;
}
}
else
i++;
{
char_index += dirL;
glyph_index += dirL;
}
}
HeapFree(GetProcessHeap(),0,context_shape);
@ -2769,6 +2822,8 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
INT *context_shape;
INT dirL;
int i;
int char_index;
int glyph_index;
if (*pcGlyphs != cChars)
{
@ -2805,19 +2860,28 @@ static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS
}
/* Contextual Shaping */
i = 0;
while(i < *pcGlyphs)
if (dirL > 0)
char_index = glyph_index = 0;
else
char_index = glyph_index = cChars-1;
while(char_index < cChars && char_index >= 0)
{
INT nextIndex;
INT prevCount = *pcGlyphs;
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]);
nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index, dirL, pcGlyphs, contextual_features[context_shape[char_index]]);
if (nextIndex > GSUB_E_NOGLYPH)
{
UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust);
i = nextIndex;
glyph_index = nextIndex;
char_index += dirL;
}
else
i++;
{
char_index += dirL;
glyph_index += dirL;
}
}
HeapFree(GetProcessHeap(),0,context_shape);