diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index 1c8d064683b..850e9291ed1 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -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);