From af02c0e29c0b2af9ea2468c106492ba34bccb495 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 2 Jun 2011 14:56:55 -0500 Subject: [PATCH] usp10: Add Telugu script. --- dlls/usp10/shape.c | 105 +++++++++++++++++++++++++++++++++++- dlls/usp10/tests/usp10.c | 11 ++++ dlls/usp10/usp10.c | 11 +++- dlls/usp10/usp10_internal.h | 2 + 4 files changed, 127 insertions(+), 2 deletions(-) diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index 6bc640c1742..0c5f2e2e644 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -50,7 +50,7 @@ static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); - +static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); typedef VOID (*ShapeCharGlyphPropProc)( HDC , ScriptCache*, SCRIPT_ANALYSIS*, const WCHAR*, const INT, const WORD*, const INT, WORD*, SCRIPT_CHARPROP*, SCRIPT_GLYPHPROP*); @@ -65,6 +65,7 @@ static void ShapeCharGlyphProp_Gurmukhi( HDC hdc, ScriptCache *psc, SCRIPT_ANALY static void ShapeCharGlyphProp_Gujarati( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); static void ShapeCharGlyphProp_Oriya( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); static void ShapeCharGlyphProp_Tamil( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Telugu( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); extern const unsigned short wine_shaping_table[]; extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4]; @@ -588,6 +589,46 @@ static OPENTYPE_FEATURE_RECORD tamil_features[] = { MS_MAKE_TAG('c','a','l','t'), 1}, }; +static const char* required_telugu_features[] = +{ + "nukt", + "akhn", + "rphf", + "pref", + "half", + "pstf", + "cjct", + "pres", + "abvs", + "blws", + "psts", + "haln", + "calt", + NULL +}; + +static OPENTYPE_FEATURE_RECORD telugu_features[] = +{ + /* Localized forms */ + { MS_MAKE_TAG('l','o','c','l'), 1}, + /* Base forms */ + { MS_MAKE_TAG('n','u','k','t'), 1}, + { MS_MAKE_TAG('a','k','h','n'), 1}, + { MS_MAKE_TAG('r','p','h','f'), 1}, + { MS_MAKE_TAG('p','r','e','f'), 1}, + { MS_MAKE_TAG('b','l','w','f'), 1}, + { MS_MAKE_TAG('h','a','l','f'), 1}, + { MS_MAKE_TAG('p','s','t','f'), 1}, + { MS_MAKE_TAG('c','j','c','t'), 1}, + /* Presentation forms */ + { MS_MAKE_TAG('p','r','e','s'), 1}, + { MS_MAKE_TAG('a','b','v','s'), 1}, + { MS_MAKE_TAG('b','l','w','s'), 1}, + { MS_MAKE_TAG('p','s','t','s'), 1}, + { MS_MAKE_TAG('h','a','l','n'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, +}; + typedef struct ScriptShapeDataTag { TEXTRANGE_PROPERTIES defaultTextRange; const char** requiredFeatures; @@ -637,6 +678,8 @@ static const ScriptShapeData ShapingData[] = {{ oriya_features, 13}, required_oriya_features, "orya", "ory2", ContextualShape_Oriya, ShapeCharGlyphProp_Oriya}, {{ tamil_features, 12}, required_tamil_features, "taml", "tam2", ContextualShape_Tamil, ShapeCharGlyphProp_Tamil}, {{ tamil_features, 12}, required_tamil_features, "taml", "tam2", ContextualShape_Tamil, ShapeCharGlyphProp_Tamil}, + {{ telugu_features, 15}, required_telugu_features, "telu", "tel2", ContextualShape_Telugu, ShapeCharGlyphProp_Telugu}, + {{ telugu_features, 15}, required_telugu_features, "telu", "tel2", ContextualShape_Telugu, ShapeCharGlyphProp_Telugu}, }; static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) @@ -2360,6 +2403,61 @@ static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps HeapFree(GetProcessHeap(),0,input); } +static int telugu_lex(WCHAR c) +{ + switch (c) + { + case 0x0C4D: return lex_Halant; + case 0x0C55: return lex_Mantra_above; + case 0x0C56: return lex_Mantra_below; + case 0x200C: return lex_ZWNJ; + case 0x200D: return lex_ZWJ; + default: + if (c>=0x0C01 && c<=0x0C03) return lex_Mantra_post; + else if (c>=0x0C05 && c<=0x0C14) return lex_Vowel; + else if (c>=0x0C15 && c<=0x0C39) return lex_Consonant; + else if (c>=0x0C3E && c<=0x0C40) return lex_Mantra_above; + else if (c>=0x0C41 && c<=0x0C44) return lex_Mantra_post; + else if (c>=0x0C46 && c<=0x0C47) return lex_Mantra_above; + else if (c>=0x0C4A && c<=0x0C4C) return lex_Mantra_above; + else if (c>=0x0C58 && c<=0x0C59) return lex_Consonant; + else if (c>=0x0C60 && c<=0x0C61) return lex_Vowel; + else if (c>=0x0C62 && c<=0x0C63) return lex_Mantra_below; + else return lex_Generic; + } +} + +static const VowelComponents Telugu_vowels[] = { + {0x0C48, {0x0C46,0x0C56,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels */ + DecomposeVowels(hdc, input, &cCount, Telugu_vowels); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( input, cCount, telugu_lex, Reorder_Like_Bengali); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + HeapFree(GetProcessHeap(),0,input); +} + static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) { int i,k; @@ -2748,6 +2846,11 @@ static void ShapeCharGlyphProp_Tamil( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, tamil_lex); } +static void ShapeCharGlyphProp_Telugu( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, telugu_lex); +} + void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) { if (ShapingData[psa->eScript].charGlyphPropProc) diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index c4934fbc927..b19d0cdcb21 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -132,6 +132,8 @@ static inline void _test_items_ok(LPCWSTR string, DWORD cchString, #define gujr_tag MS_MAKE_TAG('g','u','j','r') #define orya_tag MS_MAKE_TAG('o','r','y','a') #define taml_tag MS_MAKE_TAG('t','a','m','l') +#define telu_tag MS_MAKE_TAG('t','e','l','u') +#define knda_tag MS_MAKE_TAG('k','n','d','a') static void test_ScriptItemize( void ) { @@ -243,6 +245,11 @@ static void test_ScriptItemize( void ) static const itemTest t161[2] = {{{0,0,0,0,0},0,0,0,0,taml_tag},{{0,0,0,0,0},5,0,0,0,-1}}; static const itemTest t162[2] = {{{0,0,0,0,0},0,0,0,2,taml_tag},{{0,0,0,0,0},5,0,0,0,-1}}; + /* Telugu */ + static const WCHAR test17[] = {0x0c24, 0x0c46, 0x0c32, 0x0c41, 0x0c17, 0x0c41}; + static const itemTest t171[2] = {{{0,0,0,0,0},0,0,0,0,telu_tag},{{0,0,0,0,0},6,0,0,0,-1}}; + static const itemTest t172[2] = {{{0,0,0,0,0},0,0,0,2,telu_tag},{{0,0,0,0,0},6,0,0,0,-1}}; + SCRIPT_ITEM items[15]; SCRIPT_CONTROL Control; SCRIPT_STATE State; @@ -291,6 +298,7 @@ static void test_ScriptItemize( void ) test_items_ok(test14,7,NULL,NULL,1,t141,FALSE,0); test_items_ok(test15,5,NULL,NULL,1,t151,FALSE,0); test_items_ok(test16,5,NULL,NULL,1,t161,FALSE,0); + test_items_ok(test17,6,NULL,NULL,1,t171,FALSE,0); State.uBidiLevel = 0; test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); @@ -313,6 +321,7 @@ static void test_ScriptItemize( void ) test_items_ok(test14,7,&Control,&State,1,t141,FALSE,0); test_items_ok(test15,5,&Control,&State,1,t151,FALSE,0); test_items_ok(test16,5,&Control,&State,1,t161,FALSE,0); + test_items_ok(test17,6,&Control,&State,1,t171,FALSE,0); State.uBidiLevel = 1; test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); @@ -335,6 +344,7 @@ static void test_ScriptItemize( void ) test_items_ok(test14,7,&Control,&State,1,t142,FALSE,0); test_items_ok(test15,5,&Control,&State,1,t152,FALSE,0); test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); + test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); State.uBidiLevel = 1; Control.fMergeNeutralItems = TRUE; @@ -358,6 +368,7 @@ static void test_ScriptItemize( void ) test_items_ok(test14,7,&Control,&State,1,t142,FALSE,0); test_items_ok(test15,5,&Control,&State,1,t152,FALSE,0); test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); + test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); } static inline void _test_shape_ok(int valid, HDC hdc, LPCWSTR string, diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index 84c27092f0e..6a706d2b7b9 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -89,6 +89,8 @@ static const scriptRange scriptRanges[] = { { Script_Oriya, 0xb00, 0xb7f, Script_Oriya_Numeric, 0}, /* Tamil: U+0B80–U+0BFF */ { Script_Tamil, 0xb80, 0xbff, Script_Tamil_Numeric, 0}, + /* Telugu: U+0C00–U+0C7F */ + { Script_Telugu, 0xc00, 0xc7f, Script_Telugu_Numeric, 0}, /* Sinhala: U+0D80–U+0DFF */ { Script_Sinhala, 0xd80, 0xdff, 0, 0}, /* Thai: U+0E00–U+0E7F */ @@ -259,6 +261,12 @@ static const scriptData scriptInformation[] = { {{Script_Tamil_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, {LANG_TAMIL, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, MS_MAKE_TAG('t','a','m','l')}, + {{Script_Telugu, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TELUGU, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('t','e','l','u')}, + {{Script_Telugu_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TELUGU, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','e','l','u')}, }; static const SCRIPT_PROPERTIES *script_props[] = @@ -281,7 +289,8 @@ static const SCRIPT_PROPERTIES *script_props[] = &scriptInformation[30].props, &scriptInformation[31].props, &scriptInformation[32].props, &scriptInformation[33].props, &scriptInformation[34].props, &scriptInformation[35].props, - &scriptInformation[36].props, &scriptInformation[37].props + &scriptInformation[36].props, &scriptInformation[37].props, + &scriptInformation[38].props, &scriptInformation[39].props }; typedef struct { diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 67eeb51d8cb..8f6d869ee8d 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -65,6 +65,8 @@ #define Script_Oriya_Numeric 35 #define Script_Tamil 36 #define Script_Tamil_Numeric 37 +#define Script_Telugu 38 +#define Script_Telugu_Numeric 39 #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)