From 8d83e5d370bb9689bf51a8fb193f14f023d6bf42 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 2 Jun 2011 14:57:09 -0500 Subject: [PATCH] ups10: Add Malayalam script. --- dlls/usp10/shape.c | 75 +++++++++++++++++++++++++++++++++++++ dlls/usp10/tests/usp10.c | 10 +++++ dlls/usp10/usp10.c | 11 +++++- dlls/usp10/usp10_internal.h | 2 + 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index b535cd558fc..825da4ef1ed 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -52,6 +52,7 @@ static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps 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); static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Malayalam(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*); @@ -68,6 +69,7 @@ static void ShapeCharGlyphProp_Oriya( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS 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 ); static void ShapeCharGlyphProp_Kannada( 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_Malayalam( 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]; @@ -684,6 +686,8 @@ static const ScriptShapeData ShapingData[] = {{ telugu_features, 15}, required_telugu_features, "telu", "tel2", ContextualShape_Telugu, ShapeCharGlyphProp_Telugu}, {{ telugu_features, 15}, required_telugu_features, "knda", "knd2", ContextualShape_Kannada, ShapeCharGlyphProp_Kannada}, {{ telugu_features, 15}, required_telugu_features, "knda", "knd2", ContextualShape_Kannada, ShapeCharGlyphProp_Kannada}, + {{ telugu_features, 15}, required_telugu_features, "mlym", "mlm2", ContextualShape_Malayalam, ShapeCharGlyphProp_Malayalam}, + {{ telugu_features, 15}, required_telugu_features, "mlym", "mlm2", ContextualShape_Malayalam, ShapeCharGlyphProp_Malayalam}, }; static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) @@ -1980,6 +1984,18 @@ static void Reorder_Like_Kannada(LPWSTR pwChar, INT start, INT main, INT end, le Reorder_Mantra_precede_syllable(pwChar, start, main, end, lexical); } +static void Reorder_Like_Malayalam(LPWSTR pwChar, INT start, INT main, INT end, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",start,main,end); + if (start == main && main == end) return; + + main = Indic_FindBaseConsonant(pwChar, start, main, end, lexical); + if (lexical(pwChar[main]) == lex_Vowel) return; + + Reorder_Ra_follows_mantra_post(pwChar, start, main, end, lexical); + Reorder_Mantra_precede_base(pwChar, start, main, end, lexical); +} + static int sinhala_lex(WCHAR c) { switch (c) @@ -2551,6 +2567,60 @@ static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS * HeapFree(GetProcessHeap(),0,input); } +static int malayalam_lex(WCHAR c) +{ + switch (c) + { + case 0x0D35: return lex_Consonant; + case 0x0D4D: return lex_Halant; + case 0x0D57: return lex_Mantra_post; + case 0x200C: return lex_ZWNJ; + case 0x200D: return lex_ZWJ; + default: + if (c>=0x0D02 && c<=0x0D03) return lex_Modifier; + else if (c>=0x0D05 && c<=0x0D14) return lex_Vowel; + else if (c>=0x0D15 && c<=0x0D39) return lex_Consonant; + else if (c>=0x0D3E && c<=0x0D44) return lex_Mantra_post; + else if (c>=0x0D46 && c<=0x0D48) return lex_Mantra_pre; + else if (c>=0x0D60 && c<=0x0D61) return lex_Vowel; + else if (c>=0x0D62 && c<=0x0D63) return lex_Mantra_below; + else return lex_Generic; + } +} + +static const VowelComponents Malayalam_vowels[] = { + {0x0D4A, {0x0D46,0x0D3E,0x0000}}, + {0x0D4B, {0x0D47,0x0D3E,0x0000}}, + {0x0D4C, {0x0D46,0x0D57,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static void ContextualShape_Malayalam(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, Malayalam_vowels); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( input, cCount, malayalam_lex, Reorder_Like_Malayalam); + 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; @@ -2949,6 +3019,11 @@ static void ShapeCharGlyphProp_Kannada( HDC hdc, ScriptCache *psc, SCRIPT_ANALYS ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, kannada_lex); } +static void ShapeCharGlyphProp_Malayalam( 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, malayalam_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 e85a529f7f2..53f572e4ef4 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -134,6 +134,7 @@ static inline void _test_items_ok(LPCWSTR string, DWORD cchString, #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') +#define mlym_tag MS_MAKE_TAG('m','l','y','m') static void test_ScriptItemize( void ) { @@ -255,6 +256,11 @@ static void test_ScriptItemize( void ) static const itemTest t181[2] = {{{0,0,0,0,0},0,0,0,0,knda_tag},{{0,0,0,0,0},5,0,0,0,-1}}; static const itemTest t182[2] = {{{0,0,0,0,0},0,0,0,2,knda_tag},{{0,0,0,0,0},5,0,0,0,-1}}; + /* Malayalam */ + static const WCHAR test19[] = {0x0d2e, 0x0d32, 0x0d2f, 0x0d3e, 0x0d33, 0x0d02}; + static const itemTest t191[2] = {{{0,0,0,0,0},0,0,0,0,mlym_tag},{{0,0,0,0,0},6,0,0,0,-1}}; + static const itemTest t192[2] = {{{0,0,0,0,0},0,0,0,2,mlym_tag},{{0,0,0,0,0},6,0,0,0,-1}}; + SCRIPT_ITEM items[15]; SCRIPT_CONTROL Control; SCRIPT_STATE State; @@ -305,6 +311,7 @@ static void test_ScriptItemize( void ) test_items_ok(test16,5,NULL,NULL,1,t161,FALSE,0); test_items_ok(test17,6,NULL,NULL,1,t171,FALSE,0); test_items_ok(test18,5,NULL,NULL,1,t181,FALSE,0); + test_items_ok(test19,6,NULL,NULL,1,t191,FALSE,0); State.uBidiLevel = 0; test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); @@ -329,6 +336,7 @@ static void test_ScriptItemize( void ) test_items_ok(test16,5,&Control,&State,1,t161,FALSE,0); test_items_ok(test17,6,&Control,&State,1,t171,FALSE,0); test_items_ok(test18,5,&Control,&State,1,t181,FALSE,0); + test_items_ok(test19,6,&Control,&State,1,t191,FALSE,0); State.uBidiLevel = 1; test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); @@ -353,6 +361,7 @@ static void test_ScriptItemize( void ) test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); test_items_ok(test18,5,&Control,&State,1,t182,FALSE,0); + test_items_ok(test19,6,&Control,&State,1,t192,FALSE,0); State.uBidiLevel = 1; Control.fMergeNeutralItems = TRUE; @@ -378,6 +387,7 @@ static void test_ScriptItemize( void ) test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); test_items_ok(test18,5,&Control,&State,1,t182,FALSE,0); + test_items_ok(test19,6,&Control,&State,1,t192,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 cf0aa6337ec..6d7f6cdf798 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -93,6 +93,8 @@ static const scriptRange scriptRanges[] = { { Script_Telugu, 0xc00, 0xc7f, Script_Telugu_Numeric, 0}, /* Kannada: U+0C80–U+0CFF */ { Script_Kannada, 0xc80, 0xcff, Script_Kannada_Numeric, 0}, + /* Malayalam: U+0D00–U+0D7F */ + { Script_Malayalam, 0xd00, 0xd7f, Script_Malayalam_Numeric, 0}, /* Sinhala: U+0D80–U+0DFF */ { Script_Sinhala, 0xd80, 0xdff, 0, 0}, /* Thai: U+0E00–U+0E7F */ @@ -275,6 +277,12 @@ static const scriptData scriptInformation[] = { {{Script_Kannada_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, {LANG_KANNADA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, MS_MAKE_TAG('k','n','d','a')}, + {{Script_Malayalam, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MALAYALAM, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('m','l','y','m')}, + {{Script_Malayalam_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MALAYALAM, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('m','l','y','m')}, }; static const SCRIPT_PROPERTIES *script_props[] = @@ -299,7 +307,8 @@ static const SCRIPT_PROPERTIES *script_props[] = &scriptInformation[34].props, &scriptInformation[35].props, &scriptInformation[36].props, &scriptInformation[37].props, &scriptInformation[38].props, &scriptInformation[39].props, - &scriptInformation[40].props, &scriptInformation[41].props + &scriptInformation[40].props, &scriptInformation[41].props, + &scriptInformation[42].props, &scriptInformation[43].props }; typedef struct { diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 2763477d7e6..38d937b06fc 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -69,6 +69,8 @@ #define Script_Telugu_Numeric 39 #define Script_Kannada 40 #define Script_Kannada_Numeric 41 +#define Script_Malayalam 42 +#define Script_Malayalam_Numeric 43 #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)