commit d6fa37a3e298e73f7a943a699f28a4f480ebba54 Author: Aric Stewart Date: Thu Sep 9 11:12:45 2010 -0500 usp10: Implement handling fMergeNeutralItems diff --git a/dlls/usp10/bidi.c b/dlls/usp10/bidi.c index 9c5884d..abc37c1 100644 --- a/dlls/usp10/bidi.c +++ b/dlls/usp10/bidi.c @@ -883,3 +883,38 @@ int BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, B return ich; } + +BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, + WORD* lpStrength) +{ + int i; + classify(lpString, lpStrength, uCount, c); + + for ( i = 0; i < uCount; i++) + { + switch(lpStrength[i]) + { + case L: + case LRE: + case LRO: + case R: + case AL: + case RLE: + case RLO: + lpStrength[i] = 1; + break; + case PDF: + case EN: + case ES: + case ET: + case AN: + case CS: + case BN: + lpStrength[i] = 2; + break; + default: /* Neutrals and NSM */ + lpStrength[i] = 0; + } + } + return TRUE; +} diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index 815c943..d04b536 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -41,7 +41,8 @@ typedef struct _itemTest { static inline void _test_items_ok(LPCWSTR string, DWORD cchString, SCRIPT_CONTROL *Control, SCRIPT_STATE *State, - DWORD nItems, const itemTest* items, BOOL nItemsToDo) + DWORD nItems, const itemTest* items, BOOL nItemsToDo, + INT nItemsBroken) { HRESULT hr; int x, outnItems; @@ -49,6 +50,11 @@ static inline void _test_items_ok(LPCWSTR string, DWORD cchString, hr = ScriptItemize(string, cchString, 15, Control, State, outpItems, &outnItems); winetest_ok(!hr, "ScriptItemize should return S_OK not %08x\n", hr); + if (nItemsBroken && broken(nItemsBroken == outnItems)) + { + winetest_win_skip("This test broken on this platform\n"); + return; + } if (nItemsToDo) todo_wine winetest_ok(outnItems == nItems, "Wrong number of items\n"); else @@ -75,7 +81,7 @@ static inline void _test_items_ok(LPCWSTR string, DWORD cchString, } } -#define test_items_ok(a,b,c,d,e,f,g) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_items_ok(a,b,c,d,e,f,g) +#define test_items_ok(a,b,c,d,e,f,g,h) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_items_ok(a,b,c,d,e,f,g,h) static void test_ScriptItemize( void ) @@ -90,6 +96,11 @@ static void test_ScriptItemize( void ) static const itemTest t22[5] = {{{0,0,0,1},0,0,0,2},{{0,0,0,0},6,1,1,1},{{0,0,1,0},13,0,1,2},{{0,0,0,0},15,0,0,0},{{0,0,0,0},16,0,0,0}}; static const itemTest t23[5] = {{{0,0,1,0},0,0,1,2},{{0,0,0,0},6,1,1,1},{{0,0,1,0},13,0,1,2},{{0,0,0,0},15,1,1,1},{{0,0,0,0},16,0,0,0}}; + static const WCHAR test2b[] = {'A','B','C','-','D','E','F',' ',0x0621,0x0623,0x0624,0}; + static const itemTest t2b1[5] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},3,0,0,0},{{0,0,0,0},4,0,0,0},{{0,0,0,0},8,1,1,1},{{0,0,0,0},11,0,0,0}}; + static const itemTest t2b2[5] = {{{0,0,0,0},0,0,0,2},{{0,0,0,0},3,0,0,2},{{0,0,0,0},4,0,0,2},{{0,0,0,0},7,1,1,1},{{0,0,0,0},11,0,0,0}}; + static const itemTest t2b3[3] = {{{0,0,0,0},0,0,0,2},{{0,0,0,0},7,1,1,1},{{0,0,0,0},11,0,0,0}}; + /* Thai */ static const WCHAR test3[] = {0x0e04,0x0e27,0x0e32,0x0e21,0x0e1e,0x0e22,0x0e32,0x0e22,0x0e32, 0x0e21 @@ -103,7 +114,8 @@ static void test_ScriptItemize( void ) static const WCHAR test4[] = {'1','2','3','-','5','2',' ','i','s',' ','7','1','.',0}; static const itemTest t41[6] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},3,0,0,0},{{0,0,0,0},4,0,0,0},{{0,0,0,0},7,0,0,0},{{0,0,0,0},10,0,0,0},{{0,0,0,0},12,0,0,0}}; - static const itemTest t42[5] = {{{0,0,1,0},0,0,1,2},{{0,0,0,0},6,1,1,1},{{0,0,0,0},7,0,0,2},{{1,0,0,1},10,0,0,2},{{1,0,0,0},12,0,0,0}}; + static const itemTest t42[5] = {{{0,0,1,0},0,0,1,2},{{0,0,0,0},6,1,1,1},{{0,0,0,0},7,0,0,2},{{0,0,0,0},10,0,0,2},{{0,0,0,0},12,0,0,0}}; + static const itemTest t43[4] = {{{0,0,1,0},0,0,1,2},{{0,0,0,0},6,1,1,1},{{0,0,0,0},7,0,0,2},{{0,0,0,0},12,0,0,0}}; /* Arabic */ static const WCHAR test5[] = @@ -117,6 +129,7 @@ static void test_ScriptItemize( void ) static const WCHAR test6[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd, '.',0}; static const itemTest t61[3] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},4,0,0,0},{{0,0,0,0},5,0,0,0}}; static const itemTest t62[3] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},4,1,1,1},{{0,0,0,0},5,0,0,0}}; + static const itemTest t63[2] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},5,0,0,0}}; static const WCHAR test7[] = {'p','a','r','t',' ','o','n','e',' ',0x05d7, 0x05dc, 0x05e7, ' ', 0x05e9, 0x05ea, 0x05d9, 0x05d9, 0x05dd, ' ','p','a','r','t',' ','t','h','r','e','e', 0}; static const itemTest t71[4] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},9,1,1,1},{{0,0,0,0},19,0,0,0},{{0,0,0,0},29,0,0,0}}; static const itemTest t72[4] = {{{0,0,0,0},0,0,0,0},{{0,0,0,0},9,1,1,1},{{0,0,0,0},18,0,0,0},{{0,0,0,0},29,0,0,0}}; @@ -128,6 +141,7 @@ static void test_ScriptItemize( void ) static const WCHAR test9[] = {0x0710, 0x0712, 0x0712, 0x0714, '.',0}; static const itemTest t91[3] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},4,0,0,0},{{0,0,0,0},5,0,0,0}}; static const itemTest t92[3] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},4,1,1,1},{{0,0,0,0},5,0,0,0}}; + static const itemTest t93[2] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},5,0,0,0}}; static const WCHAR test10[] = {0x0717, 0x0718, 0x071a, 0x071b,0}; static const itemTest t101[2] = {{{0,0,0,0},0,1,1,1},{{0,0,0,0},4,0,0,0}}; @@ -153,40 +167,57 @@ static void test_ScriptItemize( void ) hr = ScriptItemize(test1, 0, 10, NULL, NULL, items, &nItems); ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n"); - test_items_ok(test1,4,NULL,NULL,1,t11,FALSE); - test_items_ok(test2,16,NULL,NULL,6,t21,FALSE); - test_items_ok(test3,41,NULL,NULL,1,t31,FALSE); - test_items_ok(test4,12,NULL,NULL,5,t41,FALSE); - test_items_ok(test5,38,NULL,NULL,1,t51,FALSE); - test_items_ok(test6,5,NULL,NULL,2,t61,FALSE); - test_items_ok(test7,29,NULL,NULL,3,t71,FALSE); - test_items_ok(test8,4,NULL,NULL,1,t81,FALSE); - test_items_ok(test9,5,NULL,NULL,2,t91,FALSE); - test_items_ok(test10,4,NULL,NULL,1,t101,FALSE); + test_items_ok(test1,4,NULL,NULL,1,t11,FALSE,0); + test_items_ok(test2,16,NULL,NULL,6,t21,FALSE,0); + test_items_ok(test2b,11,NULL,NULL,4,t2b1,FALSE,0); + test_items_ok(test3,41,NULL,NULL,1,t31,FALSE,0); + test_items_ok(test4,12,NULL,NULL,5,t41,FALSE,0); + test_items_ok(test5,38,NULL,NULL,1,t51,FALSE,0); + test_items_ok(test6,5,NULL,NULL,2,t61,FALSE,0); + test_items_ok(test7,29,NULL,NULL,3,t71,FALSE,0); + test_items_ok(test8,4,NULL,NULL,1,t81,FALSE,0); + test_items_ok(test9,5,NULL,NULL,2,t91,FALSE,0); + test_items_ok(test10,4,NULL,NULL,1,t101,FALSE,0); State.uBidiLevel = 0; - test_items_ok(test1,4,&Control,&State,1,t11,FALSE); - test_items_ok(test2,16,&Control,&State,4,t22,FALSE); - test_items_ok(test3,41,&Control,&State,1,t31,FALSE); - test_items_ok(test4,12,&Control,&State,5,t41,FALSE); - test_items_ok(test5,38,&Control,&State,1,t51,FALSE); - test_items_ok(test6,5,&Control,&State,2,t61,FALSE); - test_items_ok(test7,29,&Control,&State,3,t72,FALSE); - test_items_ok(test8,4,&Control,&State,1,t81,FALSE); - test_items_ok(test9,5,&Control,&State,2,t91,FALSE); - test_items_ok(test10,4,&Control,&State,1,t101,FALSE); + test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); + test_items_ok(test2,16,&Control,&State,4,t22,FALSE,0); + test_items_ok(test2b,11,&Control,&State,4,t2b1,FALSE,0); + test_items_ok(test3,41,&Control,&State,1,t31,FALSE,0); + test_items_ok(test4,12,&Control,&State,5,t41,FALSE,0); + test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); + test_items_ok(test6,5,&Control,&State,2,t61,FALSE,0); + test_items_ok(test7,29,&Control,&State,3,t72,FALSE,0); + test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); + test_items_ok(test9,5,&Control,&State,2,t91,FALSE,0); + test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); + + State.uBidiLevel = 1; + test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); + test_items_ok(test2,16,&Control,&State,4,t23,FALSE,0); + test_items_ok(test2b,11,&Control,&State,4,t2b2,FALSE,0); + test_items_ok(test3,41,&Control,&State,1,t32,FALSE,0); + test_items_ok(test4,12,&Control,&State,4,t42,FALSE,0); + test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); + test_items_ok(test6,5,&Control,&State,2,t62,FALSE,0); + test_items_ok(test7,29,&Control,&State,3,t73,FALSE,0); + test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); + test_items_ok(test9,5,&Control,&State,2,t92,FALSE,0); + test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); State.uBidiLevel = 1; - test_items_ok(test1,4,&Control,&State,1,t12,FALSE); - test_items_ok(test2,16,&Control,&State,4,t23,FALSE); - test_items_ok(test3,41,&Control,&State,1,t32,FALSE); - test_items_ok(test4,12,&Control,&State,4,t42,TRUE); - test_items_ok(test5,38,&Control,&State,1,t51,FALSE); - test_items_ok(test6,5,&Control,&State,2,t62,FALSE); - test_items_ok(test7,29,&Control,&State,3,t73,FALSE); - test_items_ok(test8,4,&Control,&State,1,t81,FALSE); - test_items_ok(test9,5,&Control,&State,2,t92,FALSE); - test_items_ok(test10,4,&Control,&State,1,t101,FALSE); + Control.fMergeNeutralItems = TRUE; + test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); + test_items_ok(test2,16,&Control,&State,4,t23,FALSE,0); + test_items_ok(test2b,11,&Control,&State,2,t2b3,FALSE,4); + test_items_ok(test3,41,&Control,&State,1,t32,FALSE,0); + test_items_ok(test4,12,&Control,&State,3,t43,FALSE,4); + test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); + test_items_ok(test6,5,&Control,&State,1,t63,FALSE,2); + test_items_ok(test7,29,&Control,&State,3,t73,FALSE,0); + test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); + test_items_ok(test9,5,&Control,&State,1,t93,FALSE,2); + test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); } diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index e63c132..83dbfab 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -599,9 +599,10 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem #define Numeric_space 0x0020 - int cnt = 0, index = 0; + int cnt = 0, index = 0, str = 0; int New_Script = SCRIPT_UNDEFINED; WORD *levels = NULL; + WORD *strength = NULL; WORD baselevel = 0; TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, @@ -622,11 +623,19 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem for (i = 0; i < cInChars; i++) if (levels[i]!=levels[0]) break; - if (i >= cInChars) + if (i >= cInChars && !odd(baselevel)) { heap_free(levels); levels = NULL; } + else + { + if (!psControl->fMergeNeutralItems) + { + strength = heap_alloc_zero(cInChars * sizeof(WORD)); + BIDI_GetStrengths(pwcInChars, cInChars, psControl, strength); + } + } } pItems[index].iCharPos = 0; @@ -645,21 +654,28 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem pItems[index].a.fRTL = odd(baselevel); } - TRACE("New_Level=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n", - levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript, index, cnt, + if (strength) + str = strength[0]; + + TRACE("New_Level=%i New_Strength=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n", + levels?levels[cnt]:-1, str, New_Script, pItems[index].a.eScript, index, cnt, pItems[index].iCharPos); for (cnt=1; cnt < cInChars; cnt++) { - if (levels && (levels[cnt] == pItems[index].a.s.uBidiLevel)) + if (levels && (levels[cnt] == pItems[index].a.s.uBidiLevel && (!strength || (strength[cnt] == 0 || strength[cnt] == str)))) continue; if(pwcInChars[cnt] != Numeric_space) New_Script = get_char_script(pwcInChars[cnt]); - if ((levels && (levels[cnt] != pItems[index].a.s.uBidiLevel)) || New_Script != pItems[index].a.eScript || New_Script == Script_Control) + if ((levels && (levels[cnt] != pItems[index].a.s.uBidiLevel || (strength && (strength[cnt] != str)))) || New_Script != pItems[index].a.eScript || New_Script == Script_Control) { - TRACE("New_Level = %i, New_Script=%d, eScript=%d ", levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript); + TRACE("New_Level = %i, New_Strength = %i, New_Script=%d, eScript=%d ", levels?levels[cnt]:-1, strength?strength[cnt]:str, New_Script, pItems[index].a.eScript); + + if (strength && strength[cnt] != 0) + str = strength[cnt]; + index++; if (index+1 > cMaxItems) return E_OUTOFMEMORY; @@ -700,6 +716,7 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem /* Set SCRIPT_ITEM */ pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */ heap_free(levels); + heap_free(strength); return S_OK; } diff --git a/dlls/usp10/usp10_internal.h b/dlls/usp10/usp10_internal.h index 74fe275..fe5d852 100644 --- a/dlls/usp10/usp10_internal.h +++ b/dlls/usp10/usp10_internal.h @@ -69,7 +69,8 @@ typedef struct { BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s, const SCRIPT_CONTROL *c, WORD *lpOutLevels ); - +BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, + WORD* lpStrength); 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, WORD *pwLogClust);