From f4d142e27714fe38d711cff4ce42c2f83778eb1f Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 12 Aug 2010 14:59:04 -0500 Subject: [PATCH] usp10: Update pwLogClust with glyph transformations. --- dlls/usp10/shape.c | 110 +++++++++++++++++++++++++++++++----- dlls/usp10/usp10.c | 35 ++++++------ dlls/usp10/usp10_internal.h | 4 +- 3 files changed, 115 insertions(+), 34 deletions(-) diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index 1d4da21f765..df84b1fd831 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -38,10 +38,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); #define LAST_ARABIC_CHAR 0x06ff typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*, - WCHAR*, INT, WORD*, INT*, INT); + WCHAR*, INT, WORD*, INT*, INT, WORD*); -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); +static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); extern const unsigned short wine_shaping_table[]; extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4]; @@ -810,7 +810,75 @@ static VOID *load_gsub_table(HDC hdc) return GSUB_Table; } -static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, const char* feat) +static void UpdateClusters(int nextIndex, int changeCount, int write_dir, int chars, WORD* pwLogClust ) +{ + if (changeCount == 0) + return; + else + { + int i; + int target_glyph = nextIndex - 1; + int target_index = -1; + int replacing_glyph = -1; + int changed = 0; + + if (write_dir > 0) + for (i = 0; i < chars; i++) + { + if (pwLogClust[i] == target_glyph) + { + target_index = i; + break; + } + } + else + for (i = chars - 1; i >= 0; i--) + { + if (pwLogClust[i] == target_glyph) + { + target_index = i; + break; + } + } + if (target_index == -1) + { + ERR("Unable to find target glyph\n"); + return; + } + + if (changeCount < 0) + { + /* merge glyphs */ + for(i = target_index; i < chars && i >= 0; i+=write_dir) + { + if (pwLogClust[i] == target_glyph) + continue; + if(pwLogClust[i] == replacing_glyph) + pwLogClust[i] = target_glyph; + else + { + changed--; + if (changed >= changeCount) + { + replacing_glyph = pwLogClust[i]; + pwLogClust[i] = target_glyph; + } + else + break; + } + } + } + + /* renumber trailing indexes*/ + for(i = target_index; i < chars && i >= 0; i+=write_dir) + { + if (pwLogClust[i] != target_glyph) + pwLogClust[i] += changeCount; + } + } +} + +static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, const char* feat, WORD *pwLogClust ) { int i; @@ -827,9 +895,13 @@ static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, W while(i < *pcGlyphs) { INT nextIndex; + INT prevCount = *pcGlyphs; nextIndex = GSUB_apply_feature(psc->GSUB_Table, feature, pwOutGlyphs, i, write_dir, pcGlyphs); if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust); i = nextIndex; + } else i++; } @@ -896,7 +968,7 @@ static inline BOOL word_break_causing(WCHAR chr) /* * ContextualShape_Arabic */ -static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs) +static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { CHAR *context_type; INT *context_shape; @@ -954,9 +1026,13 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p if (psc->GSUB_Table) { INT nextIndex; + INT prevCount = *pcGlyphs; nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); if (nextIndex > GSUB_E_NOGLYPH) + { i = nextIndex; + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); + } shaped = (nextIndex > GSUB_E_NOGLYPH); } @@ -986,7 +1062,7 @@ static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p #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) +static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { CHAR *context_type; INT *context_shape; @@ -1057,22 +1133,26 @@ right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) 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]]); + INT prevCount = *pcGlyphs; + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); 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) +void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { if (ShapingData[psa->eScript].contextProc) - ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs); + ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); } -void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, const TEXTRANGE_PROPERTIES *rpRangeProperties) +void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust) { int i; INT dirL; @@ -1094,14 +1174,14 @@ void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa for (i = 0; i < rpRangeProperties->cotfRecords; i++) { if (rpRangeProperties->potfRecords[i].lParameter > 0) - apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, (const char*)&rpRangeProperties->potfRecords[i].tagFeature); + apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); } } -void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs) +void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) { - const TEXTRANGE_PROPERTIES *rpRangeProperties; - rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange; +const TEXTRANGE_PROPERTIES *rpRangeProperties; +rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange; - SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, rpRangeProperties); + SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); } diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index 2c75d84b46c..a601a029ae8 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -1176,6 +1176,22 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; if (!pwLogClust) return E_FAIL; + /* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */ + for (i = 0; i < cChars; i++) + { + int idx = i; + if (rtl) idx = cChars - 1 - i; + /* FIXME: set to better values */ + psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; + psva[i].fClusterStart = 1; + psva[i].fDiacritic = 0; + psva[i].fZeroWidth = 0; + psva[i].fReserved = 0; + psva[i].fShapeReserved = 0; + + pwLogClust[i] = idx; + } + if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) { WCHAR *rChars = heap_alloc(sizeof(WCHAR) * cChars); @@ -1198,8 +1214,8 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, } rChars[i] = chInput; } - SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs); - SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs); + SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); heap_free(rChars); } else @@ -1214,21 +1230,6 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, } } - /* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */ - for (i = 0; i < cChars; i++) - { - int idx = i; - if (rtl) idx = cChars - 1 - i; - /* FIXME: set to better values */ - psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; - psva[i].fClusterStart = 1; - psva[i].fDiacritic = 0; - psva[i].fZeroWidth = 0; - psva[i].fReserved = 0; - psva[i].fShapeReserved = 0; - - pwLogClust[i] = idx; - } return S_OK; } diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 5aeb2b66339..fe796b0bbfc 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -57,5 +57,5 @@ 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_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs); -void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs); +void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust);