From be9369e7fe9c71a8e432363811ede5ba2a7d09e8 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Wed, 14 Dec 2011 07:27:56 -0600 Subject: [PATCH] usp10: Add Mongolian script. --- dlls/usp10/shape.c | 78 +++++++++++++++++++++++++++++++++++++ dlls/usp10/tests/usp10.c | 12 ++++++ dlls/usp10/usp10.c | 13 ++++++- dlls/usp10/usp10_internal.h | 2 + 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/dlls/usp10/shape.c b/dlls/usp10/shape.c index 578f7ce7d06..02457cb0104 100644 --- a/dlls/usp10/shape.c +++ b/dlls/usp10/shape.c @@ -54,6 +54,7 @@ static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *p 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); static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Mongolian(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*); @@ -581,6 +582,14 @@ static OPENTYPE_FEATURE_RECORD ethiopic_features[] = { MS_MAKE_TAG('l','i','g','a'), 1}, }; +static OPENTYPE_FEATURE_RECORD mongolian_features[] = +{ + { MS_MAKE_TAG('c','c','m','p'), 1}, + { MS_MAKE_TAG('l','o','c','l'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, + { MS_MAKE_TAG('r','l','i','g'), 1}, +}; + typedef struct ScriptShapeDataTag { TEXTRANGE_PROPERTIES defaultTextRange; const char** requiredFeatures; @@ -655,6 +664,8 @@ static const ScriptShapeData ShapingData[] = {{ no_features, 0}, NULL, "yi ", "", NULL, NULL}, {{ ethiopic_features, 4}, NULL, "ethi", "", NULL, NULL}, {{ ethiopic_features, 4}, NULL, "ethi", "", NULL, NULL}, + {{ mongolian_features, 4}, NULL, "mong", "", ContextualShape_Mongolian, NULL}, + {{ mongolian_features, 4}, NULL, "mong", "", ContextualShape_Mongolian, NULL}, }; static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) @@ -3048,6 +3059,73 @@ static void ContextualShape_Khmer(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *ps HeapFree(GetProcessHeap(),0,syllables); } +static inline BOOL mongolian_wordbreak(WCHAR chr) +{ + return ((chr == 0x0020) || (chr == 0x200C) || (chr == 0x202F) || (chr == 0x180E) || (chr == 0x1800) || (chr == 0x1802) || (chr == 0x1803) || (chr == 0x1805) || (chr == 0x1808) || (chr == 0x1809) || (chr == 0x1807)); +} + +static void ContextualShape_Mongolian(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + INT *context_shape; + INT dirL; + int i; + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + if (!psa->fLogicalOrder && psa->fRTL) + dirL = -1; + else + dirL = 1; + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (!psc->GSUB_Table) + return; + + context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + + for (i = 0; i < cChars; i++) + { + if (i == 0 || mongolian_wordbreak(pwcChars[i-1])) + { + if ((i == cChars-1) || mongolian_wordbreak(pwcChars[i+1])) + context_shape[i] = Xn; + else + context_shape[i] = Xl; + } + else + { + if ((i == cChars-1) || mongolian_wordbreak(pwcChars[i+1])) + context_shape[i] = Xr; + else + context_shape[i] = Xm; + } + } + + /* Contextual Shaping */ + i = 0; + while(i < *pcGlyphs) + { + 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) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); + i = nextIndex; + } + else + i++; + } + + HeapFree(GetProcessHeap(),0,context_shape); +} + 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; diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index 464dd2abf42..43edc76401f 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -159,6 +159,7 @@ static inline void _test_items_ok(LPCWSTR string, DWORD cchString, #define hang_tag MS_MAKE_TAG('h','a','n','g') #define yi_tag MS_MAKE_TAG('y','i',' ',' ') #define ethi_tag MS_MAKE_TAG('e','t','h','i') +#define mong_tag MS_MAKE_TAG('m','o','n','g') static void test_ScriptItemize( void ) { @@ -372,6 +373,13 @@ static void test_ScriptItemize( void ) static const itemTest t342[2] = {{{0,0,0,0,0},0,0,0,2,ethi_tag,FALSE},{{0,0,0,0,0},3,0,0,0,-1,FALSE}}; static const int b342[2] = {2,2}; + /* Mongolian */ + static const WCHAR test35[] = {0x182e,0x1823,0x1829,0x182d,0x1823,0x182f,0x0020,0x182a,0x1822,0x1834,0x1822,0x182d,0x180c}; + static const itemTest t351[2] = {{{0,0,0,0,0},0,0,0,0,mong_tag,FALSE},{{0,0,0,0,0},13,0,0,0,-1,FALSE}}; + static const itemTest t352[2] = {{{0,0,0,0,0},0,0,0,2,mong_tag,TRUE,{-1,1,1,1,-1}},{{0,0,0,0,0},13,0,0,0,-1,FALSE}}; + static const int b351[2] = {2,2}; + static const int b352[2] = {2,3}; + SCRIPT_ITEM items[15]; SCRIPT_CONTROL Control; SCRIPT_STATE State; @@ -439,6 +447,7 @@ static void test_ScriptItemize( void ) test_items_ok(test32,3,NULL,NULL,1,t321,FALSE,0); test_items_ok(test33,4,NULL,NULL,1,t331,FALSE,0); test_items_ok(test34,3,NULL,NULL,1,t341,FALSE,0); + test_items_ok(test35,13,NULL,NULL,1,t351,FALSE,b351); State.uBidiLevel = 0; test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); @@ -480,6 +489,7 @@ static void test_ScriptItemize( void ) test_items_ok(test32,3,&Control,&State,1,t321,FALSE,0); test_items_ok(test33,4,&Control,&State,1,t331,FALSE,0); test_items_ok(test34,3,&Control,&State,1,t341,FALSE,0); + test_items_ok(test35,13,&Control,&State,1,t351,FALSE,b351); State.uBidiLevel = 1; test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); @@ -521,6 +531,7 @@ static void test_ScriptItemize( void ) test_items_ok(test32,3,&Control,&State,1,t322,FALSE,0); test_items_ok(test33,4,&Control,&State,1,t332,FALSE,0); test_items_ok(test34,3,&Control,&State,1,t342,FALSE,b342); + test_items_ok(test35,13,&Control,&State,1,t352,FALSE,b352); State.uBidiLevel = 1; Control.fMergeNeutralItems = TRUE; @@ -563,6 +574,7 @@ static void test_ScriptItemize( void ) test_items_ok(test32,3,&Control,&State,1,t322,FALSE,0); test_items_ok(test33,4,&Control,&State,1,t332,FALSE,0); test_items_ok(test34,3,&Control,&State,1,t342,FALSE,b342); + test_items_ok(test35,13,&Control,&State,1,t352,FALSE,b352); } 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 3a1ff9f7822..5d7ba3326f5 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -118,6 +118,8 @@ static const scriptRange scriptRanges[] = { { Script_Ethiopic, 0x1200, 0x139f, 0, 0}, /* Khmer: U+1780–U+17FF */ { Script_Khmer, 0x1780, 0x17ff, Script_Khmer_Numeric, 0}, + /* Mongolian: U+1800–U+18AF */ + { Script_Mongolian, 0x1800, 0x18af, Script_Mongolian_Numeric, 0}, /* Tai Le: U+1950–U+197F */ { Script_Tai_Le, 0x1950, 0x197f, 0, 0}, /* New Tai Lue: U+1980–U+19DF */ @@ -522,6 +524,14 @@ static const scriptData scriptInformation[] = { {0x5e, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, MS_MAKE_TAG('e','t','h','i'), {'N','y','a','l','a'}}, + {{Script_Mongolian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('m','o','n','g'), + {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i'}}, + {{Script_Mongolian_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MONGOLIAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('m','o','n','g'), + {'M','o','n','g','o','l','i','a','n',' ','B','a','i','t','i'}}, }; static const SCRIPT_PROPERTIES *script_props[] = @@ -556,7 +566,8 @@ static const SCRIPT_PROPERTIES *script_props[] = &scriptInformation[54].props, &scriptInformation[55].props, &scriptInformation[56].props, &scriptInformation[57].props, &scriptInformation[58].props, &scriptInformation[59].props, - &scriptInformation[60].props, &scriptInformation[61].props + &scriptInformation[60].props, &scriptInformation[61].props, + &scriptInformation[62].props, &scriptInformation[63].props }; typedef struct { diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index aa72f08784c..1b3f31cb854 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -93,6 +93,8 @@ /* Unicode Chapter 13 */ #define Script_Ethiopic 60 #define Script_Ethiopic_Numeric 61 +#define Script_Mongolian 62 +#define Script_Mongolian_Numeric 63 #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)