1 /* 2 * Tests for usp10 dll 3 * 4 * Copyright 2006 Jeff Latimer 5 * Copyright 2006 Hans Leidekker 6 * Copyright 2010 CodeWeavers, Aric Stewart 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 * 22 * Notes: 23 * Uniscribe allows for processing of complex scripts such as joining 24 * and filtering characters and bi-directional text with custom line breaks. 25 */ 26 27 #include <assert.h> 28 #include <stdio.h> 29 30 #include <wine/test.h> 31 #include <winnls.h> 32 #include <wingdi.h> 33 #include <winuser.h> 34 //#include <windows.h> 35 #include <usp10.h> 36 37 typedef struct _itemTest { 38 char todo_flag[6]; 39 int iCharPos; 40 int fRTL; 41 int fLayoutRTL; 42 int uBidiLevel; 43 int fOverrideDirection; 44 ULONG scriptTag; 45 BOOL isBroken; 46 int broken_value[6]; 47 } itemTest; 48 49 typedef struct _shapeTest_char { 50 WORD wLogClust; 51 SCRIPT_CHARPROP CharProp; 52 } shapeTest_char; 53 54 typedef struct _shapeTest_glyph { 55 int Glyph; 56 SCRIPT_GLYPHPROP GlyphProp; 57 } shapeTest_glyph; 58 59 typedef struct _font_fingerprint { 60 WCHAR check[10]; 61 WORD result[10]; 62 } font_fingerprint; 63 64 /* Uniscribe 1.6 calls */ 65 static HRESULT (WINAPI *pScriptItemizeOpenType)( const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, ULONG *pScriptTags, int *pcItems); 66 67 static HRESULT (WINAPI *pScriptShapeOpenType)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, int cRanges, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs, SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs); 68 69 static HRESULT (WINAPI *pScriptGetFontScriptTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags); 70 static HRESULT (WINAPI *pScriptGetFontLanguageTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, int cMaxTags, OPENTYPE_TAG *pLangSysTags, int *pcTags); 71 static HRESULT (WINAPI *pScriptGetFontFeatureTags)( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags); 72 73 static inline void _test_items_ok(LPCWSTR string, DWORD cchString, 74 SCRIPT_CONTROL *Control, SCRIPT_STATE *State, 75 DWORD nItems, const itemTest* items, BOOL nItemsToDo, 76 const INT nItemsBroken[2]) 77 { 78 HRESULT hr; 79 int x, outnItems; 80 SCRIPT_ITEM outpItems[15]; 81 ULONG tags[15] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; 82 83 if (pScriptItemizeOpenType) 84 hr = pScriptItemizeOpenType(string, cchString, 15, Control, State, outpItems, tags, &outnItems); 85 else 86 hr = ScriptItemize(string, cchString, 15, Control, State, outpItems, &outnItems); 87 88 winetest_ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 89 if (nItemsBroken && (broken(nItemsBroken[0] == outnItems) || broken(nItemsBroken[1] == outnItems))) 90 { 91 winetest_win_skip("This test broken on this platform: nitems %d\n", outnItems); 92 return; 93 } 94 todo_wine_if (nItemsToDo) 95 winetest_ok(outnItems == nItems, "Wrong number of items (%u)\n", outnItems); 96 outnItems = min(outnItems, nItems); 97 for (x = 0; x <= outnItems; x++) 98 { 99 if (items[x].isBroken && broken(outpItems[x].iCharPos == items[x].broken_value[0])) 100 winetest_win_skip("This test broken on this platform: item %d CharPos %d\n", x, outpItems[x].iCharPos); 101 else todo_wine_if (items[x].todo_flag[0]) 102 winetest_ok(outpItems[x].iCharPos == items[x].iCharPos, "%i:Wrong CharPos (%i)\n",x,outpItems[x].iCharPos); 103 104 if (items[x].isBroken && broken(outpItems[x].a.fRTL== items[x].broken_value[1])) 105 winetest_win_skip("This test broken on this platform: item %d fRTL %d\n", x, outpItems[x].a.fRTL); 106 else todo_wine_if (items[x].todo_flag[1]) 107 winetest_ok(outpItems[x].a.fRTL == items[x].fRTL, "%i:Wrong fRTL(%i)\n",x,outpItems[x].a.fRTL); 108 109 if (items[x].isBroken && broken(outpItems[x].a.fLayoutRTL == items[x].broken_value[2])) 110 winetest_win_skip("This test broken on this platform: item %d fLayoutRTL %d\n", x, outpItems[x].a.fLayoutRTL); 111 else todo_wine_if (items[x].todo_flag[2]) 112 winetest_ok(outpItems[x].a.fLayoutRTL == items[x].fLayoutRTL, "%i:Wrong fLayoutRTL(%i)\n",x,outpItems[x].a.fLayoutRTL); 113 114 if (items[x].isBroken && broken(outpItems[x].a.s.uBidiLevel == items[x].broken_value[3])) 115 winetest_win_skip("This test broken on this platform: item %d BidiLevel %d\n", x, outpItems[x].a.s.uBidiLevel); 116 else todo_wine_if (items[x].todo_flag[3]) 117 winetest_ok(outpItems[x].a.s.uBidiLevel == items[x].uBidiLevel, "%i:Wrong BidiLevel(%i)\n",x,outpItems[x].a.s.uBidiLevel); 118 119 if (items[x].isBroken && broken(outpItems[x].a.s.fOverrideDirection == items[x].broken_value[4])) 120 winetest_win_skip("This test broken on this platform: item %d fOverrideDirection %d\n", x, outpItems[x].a.s.fOverrideDirection); 121 else todo_wine_if (items[x].todo_flag[4]) 122 winetest_ok(outpItems[x].a.s.fOverrideDirection == items[x].fOverrideDirection, "%i:Wrong fOverrideDirection(%i)\n",x,outpItems[x].a.s.fOverrideDirection); 123 124 if (x != outnItems) 125 winetest_ok(outpItems[x].a.eScript != SCRIPT_UNDEFINED, "%i: Undefined script\n",x); 126 if (pScriptItemizeOpenType) 127 { 128 if (items[x].isBroken && broken(tags[x] == items[x].broken_value[5])) 129 winetest_win_skip("This test broken on this platform: item %d Script Tag %x\n", x, tags[x]); 130 else todo_wine_if (items[x].todo_flag[5]) 131 winetest_ok(tags[x] == items[x].scriptTag,"%i:Incorrect Script Tag %x != %x\n",x,tags[x],items[x].scriptTag); 132 } 133 134 } 135 } 136 137 #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) 138 139 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ 140 ( ( (ULONG)_x4 << 24 ) | \ 141 ( (ULONG)_x3 << 16 ) | \ 142 ( (ULONG)_x2 << 8 ) | \ 143 (ULONG)_x1 ) 144 145 #define latn_tag MS_MAKE_TAG('l','a','t','n') 146 #define arab_tag MS_MAKE_TAG('a','r','a','b') 147 #define thai_tag MS_MAKE_TAG('t','h','a','i') 148 #define hebr_tag MS_MAKE_TAG('h','e','b','r') 149 #define syrc_tag MS_MAKE_TAG('s','y','r','c') 150 #define thaa_tag MS_MAKE_TAG('t','h','a','a') 151 #define deva_tag MS_MAKE_TAG('d','e','v','a') 152 #define beng_tag MS_MAKE_TAG('b','e','n','g') 153 #define guru_tag MS_MAKE_TAG('g','u','r','u') 154 #define gujr_tag MS_MAKE_TAG('g','u','j','r') 155 #define orya_tag MS_MAKE_TAG('o','r','y','a') 156 #define taml_tag MS_MAKE_TAG('t','a','m','l') 157 #define telu_tag MS_MAKE_TAG('t','e','l','u') 158 #define knda_tag MS_MAKE_TAG('k','n','d','a') 159 #define mlym_tag MS_MAKE_TAG('m','l','y','m') 160 #define mymr_tag MS_MAKE_TAG('m','y','m','r') 161 #define tale_tag MS_MAKE_TAG('t','a','l','e') 162 #define talu_tag MS_MAKE_TAG('t','a','l','u') 163 #define khmr_tag MS_MAKE_TAG('k','h','m','r') 164 #define hani_tag MS_MAKE_TAG('h','a','n','i') 165 #define bopo_tag MS_MAKE_TAG('b','o','p','o') 166 #define kana_tag MS_MAKE_TAG('k','a','n','a') 167 #define hang_tag MS_MAKE_TAG('h','a','n','g') 168 #define yi_tag MS_MAKE_TAG('y','i',' ',' ') 169 #define ethi_tag MS_MAKE_TAG('e','t','h','i') 170 #define mong_tag MS_MAKE_TAG('m','o','n','g') 171 #define tfng_tag MS_MAKE_TAG('t','f','n','g') 172 #define nko_tag MS_MAKE_TAG('n','k','o',' ') 173 #define vai_tag MS_MAKE_TAG('v','a','i',' ') 174 #define cher_tag MS_MAKE_TAG('c','h','e','r') 175 #define cans_tag MS_MAKE_TAG('c','a','n','s') 176 #define ogam_tag MS_MAKE_TAG('o','g','a','m') 177 #define runr_tag MS_MAKE_TAG('r','u','n','r') 178 #define brai_tag MS_MAKE_TAG('b','r','a','i') 179 #define dsrt_tag MS_MAKE_TAG('d','s','r','t') 180 #define osma_tag MS_MAKE_TAG('o','s','m','a') 181 #define math_tag MS_MAKE_TAG('m','a','t','h') 182 183 static void test_ScriptItemize( void ) 184 { 185 static const WCHAR test1[] = {'t', 'e', 's', 't',0}; 186 static const itemTest t11[2] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1}}; 187 static const itemTest t12[2] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 188 189 static const WCHAR test1b[] = {' ', ' ', ' ', ' ',0}; 190 static const itemTest t1b1[2] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 191 static const itemTest t1b2[2] = {{{0,0,0,0,0,0},0,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 192 193 static const WCHAR test1c[] = {' ', ' ', ' ', '1', '2', ' ',0}; 194 static const itemTest t1c1[2] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 195 static const itemTest t1c2[4] = {{{0,0,0,0,0,0},0,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},3,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},5,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 196 197 /* Arabic, English*/ 198 static const WCHAR test2[] = {'1','2','3','-','5','2',0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,'7','1','.',0}; 199 static const itemTest t21[7] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},6,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},15,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 200 static const itemTest t22[5] = {{{0,0,0,0,0,0},0,0,0,2,0,0,FALSE},{{0,0,0,0,0,0},6,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},15,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 201 static const itemTest t23[5] = {{{0,0,0,0,0,0},0,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},6,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},15,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 202 static const itemTest t24[5] = {{{0,0,0,0,0,0},0,0,0,0,1,0,FALSE}, 203 {{0,0,0,0,0,0},6,0,0,0,1,arab_tag,FALSE}, 204 {{0,0,0,0,0,0},13,0,1,0,1,0,FALSE}, 205 {{0,0,0,0,0,0},15,0,0,0,1,0,FALSE}, 206 {{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 207 208 static const WCHAR test2b[] = {'A','B','C','-','D','E','F',' ',0x0621,0x0623,0x0624,0}; 209 static const itemTest t2b1[5] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},8,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 210 static const itemTest t2b2[5] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,2,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 211 static const itemTest t2b3[3] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 212 static const itemTest t2b4[5] = {{{0,0,0,0,0,0},0,0,0,0,1,latn_tag,FALSE}, 213 {{0,0,0,0,0,0},3,0,0,0,1,0,FALSE}, 214 {{0,0,0,0,0,0},4,0,0,0,1,latn_tag,FALSE}, 215 {{0,0,0,0,0,0},8,0,0,0,1,arab_tag,FALSE}, 216 {{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 217 static const int b2[2] = {4,4}; 218 219 /* leading space */ 220 static const WCHAR test2c[] = {' ',0x0621,0x0623,0x0624,'A','B','C','-','D','E','F',0}; 221 static const itemTest t2c1[5] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 222 static const itemTest t2c2[6] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},1,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 223 static const itemTest t2c3[5] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},4,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,0,0,2,0,0,FALSE},{{0,0,0,0,0,0},8,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 224 static const itemTest t2c4[3] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},4,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 225 static const itemTest t2c5[5] = {{{0,0,0,0,0,0},0,0,0,0,1,arab_tag,FALSE}, 226 {{0,0,0,0,0,0},4,0,0,0,1,latn_tag,FALSE}, 227 {{0,0,0,0,0,0},7,0,0,0,1,0,FALSE}, 228 {{0,0,0,0,0,0},8,0,0,0,1,latn_tag,FALSE}, 229 {{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 230 231 /* trailing space */ 232 static const WCHAR test2d[] = {'A','B','C','-','D','E','F',0x0621,0x0623,0x0624,' ',0}; 233 static const itemTest t2d1[5] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 234 static const itemTest t2d2[6] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 235 static const itemTest t2d3[5] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,2,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 236 static const itemTest t2d4[3] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},7,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 237 static const itemTest t2d5[5] = {{{0,0,0,0,0,0},0,0,0,0,1,latn_tag,FALSE}, 238 {{0,0,0,0,0,0},3,0,0,0,1,0,FALSE}, 239 {{0,0,0,0,0,0},4,0,0,0,1,latn_tag,FALSE}, 240 {{0,0,0,0,0,0},7,0,0,0,1,arab_tag,FALSE}, 241 {{0,0,0,0,0,0},11,0,0,0,0,-1,FALSE}}; 242 243 /* Thai */ 244 static const WCHAR test3[] = 245 {0x0e04,0x0e27,0x0e32,0x0e21,0x0e1e,0x0e22,0x0e32,0x0e22,0x0e32, 0x0e21 246 ,0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e44,0x0e2b,0x0e19 247 ,0x0e04,0x0e27,0x0e32,0x0e21,0x0e2a, 0x0e33,0x0e40,0x0e23,0x0e47,0x0e08, 248 0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e19,0x0e31,0x0e48,0x0e19,0}; 249 250 static const itemTest t31[2] = {{{0,0,0,0,0,0},0,0,0,0,0,thai_tag,FALSE},{{0,0,0,0,0,0},41,0,0,0,0,-1,FALSE}}; 251 static const itemTest t32[2] = {{{0,0,0,0,0,0},0,0,0,2,0,thai_tag,FALSE},{{0,0,0,0,0,0},41,0,0,0,0,-1,FALSE}}; 252 253 static const WCHAR test4[] = {'1','2','3','-','5','2',' ','i','s',' ','7','1','.',0}; 254 255 static const itemTest t41[6] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},12,0,0,0,0,-1,FALSE}}; 256 static const itemTest t42[5] = {{{0,0,0,0,0,0},0,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},6,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},7,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},10,0,0,2,0,0,FALSE},{{0,0,0,0,0,0},12,0,0,0,0,-1,FALSE}}; 257 static const itemTest t43[4] = {{{0,0,0,0,0,0},0,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},6,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},7,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},12,0,0,0,0,-1,FALSE}}; 258 static const int b43[2] = {4,4}; 259 260 /* Arabic */ 261 static const WCHAR test5[] = {0x0627,0x0644,0x0635,0x0651,0x0650,0x062d,0x0629,0x064f,' ',0x062a,0x064e, 262 0x0627,0x062c,0x064c,' ',0x0639,0x064e,0x0644,0x0649,' ', 263 0x0631,0x064f,0x0624,0x0648,0x0633,0x0650,' ',0x0627,0x0644, 264 0x0623,0x0635,0x0650,0x062d,0x0651,0x064e,0x0627,0x0621,0x0650,0}; 265 static const itemTest t51[2] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},38,0,0,0,0,-1,FALSE}}; 266 static const itemTest t52[2] = {{{0,0,0,0,0,0},0,0,0,0,1,arab_tag,FALSE}, 267 {{0,0,0,0,0,0},38,0,0,0,0,-1,FALSE}}; 268 269 270 /* Hebrew */ 271 static const WCHAR test6[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd, '.',0}; 272 static const itemTest t61[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,TRUE,{-1,0,0,0,-1,-1}},{{0,0,0,0,0,0},4,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 273 static const itemTest t62[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE},{{0,0,0,0,0,0},4,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 274 static const itemTest t63[2] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 275 static const itemTest t64[3] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 276 {{0,0,0,0,0,0},4,0,0,0,1,0,FALSE}, 277 {{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 278 279 static const int b63[2] = {2,2}; 280 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}; 281 static const itemTest t71[4] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},9,1,1,1,0,hebr_tag,TRUE,{-1,0,0,0,-1,-1}},{{0,0,0,0,0,0},19,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},29,0,0,0,0,-1,FALSE}}; 282 static const itemTest t72[4] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},9,1,1,1,0,hebr_tag,FALSE},{{0,0,0,0,0,0},18,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},29,0,0,0,0,-1,FALSE}}; 283 static const itemTest t73[4] = {{{0,0,0,0,0,0},0,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},8,1,1,1,0,hebr_tag,FALSE},{{0,0,0,0,0,0},19,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},29,0,0,0,0,-1,FALSE}}; 284 static const itemTest t74[4] = {{{0,0,0,0,0,0},0,0,0,0,1,latn_tag,FALSE}, 285 {{0,0,0,0,0,0},9,0,0,0,1,hebr_tag,FALSE}, 286 {{0,0,0,0,0,0},19,0,0,0,1,latn_tag,FALSE}, 287 {{0,0,0,0,0,0},29,0,0,0,0,-1,FALSE}}; 288 289 static const WCHAR test8[] = {0x0633, 0x0644, 0x0627, 0x0645,0}; 290 static const itemTest t81[2] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 291 static const itemTest t82[2] = {{{0,0,0,0,0,0},0,0,0,0,1,arab_tag,FALSE}, 292 {{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 293 294 /* Syriac (Like Arabic )*/ 295 static const WCHAR test9[] = {0x0710, 0x0712, 0x0712, 0x0714, '.',0}; 296 static const itemTest t91[3] = {{{0,0,0,0,0,0},0,1,1,1,0,syrc_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 297 static const itemTest t92[3] = {{{0,0,0,0,0,0},0,1,1,1,0,syrc_tag},{{0,0,0,0,0,0},4,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 298 static const itemTest t93[2] = {{{0,0,0,0,0,0},0,1,1,1,0,syrc_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 299 static const itemTest t94[3] = {{{0,0,0,0,0,0},0,0,0,0,1,syrc_tag,FALSE}, 300 {{0,0,0,0,0,0},4,0,0,0,1,0,FALSE}, 301 {{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 302 static const int b93[2] = {2,2}; 303 304 static const WCHAR test10[] = {0x0717, 0x0718, 0x071a, 0x071b,0}; 305 static const itemTest t101[2] = {{{0,0,0,0,0,0},0,1,1,1,0,syrc_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 306 static const itemTest t102[2] = {{{0,0,0,0,0,0},0,0,0,0,1,syrc_tag,FALSE}, 307 {{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 308 309 /* Devanagari */ 310 static const WCHAR test11[] = {0x0926, 0x0947, 0x0935, 0x0928, 0x093e, 0x0917, 0x0930, 0x0940}; 311 static const itemTest t111[2] = {{{0,0,0,0,0,0},0,0,0,0,0,deva_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 312 static const itemTest t112[2] = {{{0,0,0,0,0,0},0,0,0,2,0,deva_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 313 314 /* Bengali */ 315 static const WCHAR test12[] = {0x09ac, 0x09be, 0x0982, 0x09b2, 0x09be}; 316 static const itemTest t121[2] = {{{0,0,0,0,0,0},0,0,0,0,0,beng_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 317 static const itemTest t122[2] = {{{0,0,0,0,0,0},0,0,0,2,0,beng_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 318 319 /* Gurmukhi */ 320 static const WCHAR test13[] = {0x0a17, 0x0a41, 0x0a30, 0x0a2e, 0x0a41, 0x0a16, 0x0a40}; 321 static const itemTest t131[2] = {{{0,0,0,0,0,0},0,0,0,0,0,guru_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 322 static const itemTest t132[2] = {{{0,0,0,0,0,0},0,0,0,2,0,guru_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 323 324 /* Gujarati */ 325 static const WCHAR test14[] = {0x0a97, 0x0ac1, 0x0a9c, 0x0ab0, 0x0abe, 0x0aa4, 0x0ac0}; 326 static const itemTest t141[2] = {{{0,0,0,0,0,0},0,0,0,0,0,gujr_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 327 static const itemTest t142[2] = {{{0,0,0,0,0,0},0,0,0,2,0,gujr_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 328 329 /* Oriya */ 330 static const WCHAR test15[] = {0x0b13, 0x0b21, 0x0b3c, 0x0b3f, 0x0b06}; 331 static const itemTest t151[2] = {{{0,0,0,0,0,0},0,0,0,0,0,orya_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 332 static const itemTest t152[2] = {{{0,0,0,0,0,0},0,0,0,2,0,orya_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 333 334 /* Tamil */ 335 static const WCHAR test16[] = {0x0ba4, 0x0bae, 0x0bbf, 0x0bb4, 0x0bcd}; 336 static const itemTest t161[2] = {{{0,0,0,0,0,0},0,0,0,0,0,taml_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 337 static const itemTest t162[2] = {{{0,0,0,0,0,0},0,0,0,2,0,taml_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 338 339 /* Telugu */ 340 static const WCHAR test17[] = {0x0c24, 0x0c46, 0x0c32, 0x0c41, 0x0c17, 0x0c41}; 341 static const itemTest t171[2] = {{{0,0,0,0,0,0},0,0,0,0,0,telu_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 342 static const itemTest t172[2] = {{{0,0,0,0,0,0},0,0,0,2,0,telu_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 343 344 /* Kannada */ 345 static const WCHAR test18[] = {0x0c95, 0x0ca8, 0x0ccd, 0x0ca8, 0x0ca1}; 346 static const itemTest t181[2] = {{{0,0,0,0,0,0},0,0,0,0,0,knda_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 347 static const itemTest t182[2] = {{{0,0,0,0,0,0},0,0,0,2,0,knda_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 348 349 /* Malayalam */ 350 static const WCHAR test19[] = {0x0d2e, 0x0d32, 0x0d2f, 0x0d3e, 0x0d33, 0x0d02}; 351 static const itemTest t191[2] = {{{0,0,0,0,0,0},0,0,0,0,0,mlym_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 352 static const itemTest t192[2] = {{{0,0,0,0,0,0},0,0,0,2,0,mlym_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 353 354 /* Diacritical */ 355 static const WCHAR test20[] = {0x0309,'a','b','c','d',0}; 356 static const itemTest t201[3] = {{{0,0,0,0,0,0},0,0,0,0,0x0,0,FALSE},{{0,0,0,0,0,0},1,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 357 static const itemTest t202[3] = {{{0,0,0,0,0,0},0,0,0,2,0,0,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},1,0,0,2,0,latn_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 358 359 static const WCHAR test21[] = {0x0710, 0x0712, 0x0308, 0x0712, 0x0714,0}; 360 static const itemTest t211[2] = {{{0,0,0,0,0,0},0,1,1,1,0,syrc_tag,FALSE},{{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 361 static const itemTest t212[2] = {{{0,0,0,0,0,0},0,0,0,0,1,syrc_tag,FALSE}, 362 {{0,0,0,0,0,0},5,0,0,0,0,-1,FALSE}}; 363 364 /* Latin Punctuation */ 365 static const WCHAR test22[] = {'#','$',',','!','\"','*',0}; 366 static const itemTest t221[3] = {{{0,0,0,0,0,0},0,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 367 static const itemTest t222[3] = {{{0,0,0,0,0,0},0,1,1,1,0,latn_tag,FALSE},{{0,0,0,0,0,0},3,1,1,1,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 368 static const itemTest t223[2] = {{{0,0,0,0,0,0},0,1,1,1,0,latn_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 369 static const int b222[2] = {1,1}; 370 static const int b223[2] = {2,2}; 371 372 /* Number 2*/ 373 static const WCHAR test23[] = {'1','2','3',0x00b2,0x00b3,0x2070,0}; 374 static const itemTest t231[3] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 375 static const itemTest t232[3] = {{{0,0,0,0,0,0},0,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},3,0,1,2,0,0,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 376 377 /* Myanmar */ 378 static const WCHAR test24[] = {0x1019,0x103c,0x1014,0x103a,0x1019,0x102c,0x1021,0x1000,0x1039,0x1001,0x101b,0x102c}; 379 static const itemTest t241[2] = {{{0,0,0,0,0,0},0,0,0,0,0,mymr_tag,FALSE},{{0,0,0,0,0,0},12,0,0,0,0,-1,FALSE}}; 380 static const itemTest t242[2] = {{{0,0,0,0,0,0},0,0,0,2,0,mymr_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},12,0,0,0,0,-1,FALSE}}; 381 382 /* Tai Le */ 383 static const WCHAR test25[] = {0x1956,0x196d,0x1970,0x1956,0x196c,0x1973,0x1951,0x1968,0x1952,0x1970}; 384 static const itemTest t251[2] = {{{0,0,0,0,0,0},0,0,0,0,0,tale_tag,TRUE,{-1,-1,-1,-1,-1,latn_tag}},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 385 static const itemTest t252[2] = {{{0,0,0,0,0,0},0,0,0,2,0,tale_tag,TRUE,{-1,1,1,1,-1,latn_tag}},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 386 387 /* New Tai Lue */ 388 static const WCHAR test26[] = {0x1992,0x19c4}; 389 static const itemTest t261[2] = {{{0,0,0,0,0,0},0,0,0,0,0,talu_tag,TRUE,{-1,-1,-1,-1,-1,latn_tag}},{{0,0,0,0,0,0},2,0,0,0,0,-1,FALSE}}; 390 static const itemTest t262[2] = {{{0,0,0,0,0,0},0,0,0,2,0,talu_tag,TRUE,{-1,1,1,1,-1,latn_tag}},{{0,0,0,0,0,0},2,0,0,0,0,-1,FALSE}}; 391 392 /* Khmer */ 393 static const WCHAR test27[] = {0x1781,0x17c1,0x1798,0x179a,0x1797,0x17b6,0x179f,0x17b6}; 394 static const itemTest t271[2] = {{{0,0,0,0,0,0},0,0,0,0,0,khmr_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 395 static const itemTest t272[2] = {{{0,0,0,0,0,0},0,0,0,2,0,khmr_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 396 397 /* CJK Han */ 398 static const WCHAR test28[] = {0x8bed,0x7d20,0x6587,0x5b57}; 399 static const itemTest t281[2] = {{{0,0,0,0,0,0},0,0,0,0,0,hani_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 400 static const itemTest t282[2] = {{{0,0,0,0,0,0},0,0,0,2,0,hani_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 401 402 /* Ideographic */ 403 static const WCHAR test29[] = {0x2ff0,0x2ff3,0x2ffb,0x2ff0,0x65e5,0x65e5,0x5de5,0x7f51,0x4e02,0x4e5e}; 404 static const itemTest t291[3] = {{{0,0,0,0,0,0},0,0,0,0,0,hani_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,hani_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 405 static const itemTest t292[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hani_tag,FALSE},{{0,0,0,0,0,0},4,0,0,2,0,hani_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 406 407 /* Bopomofo */ 408 static const WCHAR test30[] = {0x3113,0x3128,0x3127,0x3123,0x3108,0x3128,0x310f,0x3120}; 409 static const itemTest t301[2] = {{{0,0,0,0,0,0},0,0,0,0,0,bopo_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 410 static const itemTest t302[2] = {{{0,0,0,0,0,0},0,0,0,2,0,bopo_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 411 412 /* Kana */ 413 static const WCHAR test31[] = {0x3072,0x3089,0x304b,0x306a,0x30ab,0x30bf,0x30ab,0x30ca}; 414 static const itemTest t311[2] = {{{0,0,0,0,0,0},0,0,0,0,0,kana_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 415 static const itemTest t312[2] = {{{0,0,0,0,0,0},0,0,0,2,0,kana_tag,FALSE},{{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 416 static const int b311[2] = {2,2}; 417 static const int b312[2] = {2,2}; 418 419 /* Hangul */ 420 static const WCHAR test32[] = {0xd55c,0xad6d,0xc5b4}; 421 static const itemTest t321[2] = {{{0,0,0,0,0,0},0,0,0,0,0,hang_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 422 static const itemTest t322[2] = {{{0,0,0,0,0,0},0,0,0,2,0,hang_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 423 424 /* Yi */ 425 static const WCHAR test33[] = {0xa188,0xa320,0xa071,0xa0b7}; 426 static const itemTest t331[2] = {{{0,0,0,0,0,0},0,0,0,0,0,yi_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 427 static const itemTest t332[2] = {{{0,0,0,0,0,0},0,0,0,2,0,yi_tag,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 428 429 /* Ethiopic */ 430 static const WCHAR test34[] = {0x130d,0x12d5,0x12dd}; 431 static const itemTest t341[2] = {{{0,0,0,0,0,0},0,0,0,0,0,ethi_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 432 static const itemTest t342[2] = {{{0,0,0,0,0,0},0,0,0,2,0,ethi_tag,FALSE},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 433 static const int b342[2] = {2,2}; 434 435 /* Mongolian */ 436 static const WCHAR test35[] = {0x182e,0x1823,0x1829,0x182d,0x1823,0x182f,0x0020,0x182a,0x1822,0x1834,0x1822,0x182d,0x180c}; 437 static const itemTest t351[2] = {{{0,0,0,0,0,0},0,0,0,0,0,mong_tag,FALSE},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 438 static const int b351[2] = {2,2}; 439 static const itemTest t352[2] = {{{0,0,0,0,0,0},0,0,0,2,0,mong_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 440 static const int b352[2] = {2,3}; 441 static const itemTest t353[2] = {{{0,0,0,0,1,0},0,0,0,0,1,mong_tag,TRUE,{-1,-1,-1,-1,0,0}},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 442 443 /* Tifinagh */ 444 static const WCHAR test36[] = {0x2d5c,0x2d49,0x2d3c,0x2d49,0x2d4f,0x2d30,0x2d56}; 445 static const itemTest t361[2] = {{{0,0,0,0,0,0},0,0,0,0,0,tfng_tag,TRUE,{-1,-1,-1,-1,-1,latn_tag}},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 446 static const itemTest t362[2] = {{{0,0,0,0,0,0},0,0,0,2,0,tfng_tag,TRUE,{-1,1,1,1,-1,latn_tag}},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 447 448 /* N'Ko */ 449 static const WCHAR test37[] = {0x07d2,0x07de,0x07cf}; 450 static const itemTest t371[2] = {{{0,0,0,0,0,0},0,1,1,1,0,nko_tag,TRUE,{-1,0,0,0,-1,arab_tag}},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 451 static const itemTest t372[2] = {{{0,0,0,0,0,0},0,1,1,1,0,nko_tag,TRUE,{-1,0,0,2,-1,arab_tag}},{{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 452 static const itemTest t373[2] = {{{0,0,0,0,0,0},0,0,0,0,1,nko_tag,TRUE,{-1,-1,-1,2,0,arab_tag}}, {{0,0,0,0,0,0},3,0,0,0,0,-1,FALSE}}; 453 454 /* Vai */ 455 static const WCHAR test38[] = {0xa559,0xa524}; 456 static const itemTest t381[2] = {{{0,0,0,0,0,0},0,0,0,0,0,vai_tag,TRUE,{-1,-1,-1,-1,-1,latn_tag}},{{0,0,0,0,0,0},2,0,0,0,0,-1,FALSE}}; 457 static const itemTest t382[2] = {{{0,0,0,0,0,0},0,0,0,2,0,vai_tag,TRUE,{-1,1,1,1,-1,latn_tag}},{{0,0,0,0,0,0},2,0,0,0,0,-1,FALSE}}; 458 459 /* Cherokee */ 460 static const WCHAR test39[] = {0x13e3,0x13b3,0x13a9,0x0020,0x13a6,0x13ec,0x13c2,0x13af,0x13cd,0x13d7}; 461 static const itemTest t391[2] = {{{0,0,0,0,0,0},0,0,0,0,0,cher_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 462 static const itemTest t392[2] = {{{0,0,0,0,0,0},0,0,0,2,0,cher_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},10,0,0,0,0,-1,FALSE}}; 463 464 /* Canadian Aboriginal Syllabics */ 465 static const WCHAR test40[] = {0x1403,0x14c4,0x1483,0x144e,0x1450,0x1466}; 466 static const itemTest t401[2] = {{{0,0,0,0,0,0},0,0,0,0,0,cans_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 467 static const itemTest t402[2] = {{{0,0,0,0,0,0},0,0,0,2,0,cans_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 468 469 /* Ogham */ 470 static const WCHAR test41[] = {0x169b,0x1691,0x168c,0x1690,0x168b,0x169c}; 471 static const itemTest t411[2] = {{{0,0,0,0,0,0},0,0,0,0,0,ogam_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 472 static const itemTest t412[4] = {{{0,0,0,0,0,0},0,1,1,1,0,ogam_tag,FALSE},{{0,0,0,0,0,0},1,0,0,2,0,ogam_tag,FALSE},{{0,0,0,0,0,0},5,1,1,1,0,ogam_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 473 static const int b412[2] = {1,1}; 474 475 /* Runic */ 476 static const WCHAR test42[] = {0x16a0,0x16a1,0x16a2,0x16a3,0x16a4,0x16a5}; 477 static const itemTest t421[2] = {{{0,0,0,0,0,0},0,0,0,0,0,runr_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 478 static const itemTest t422[4] = {{{0,0,0,0,0,0},0,0,0,2,0,runr_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 479 480 /* Braille */ 481 static const WCHAR test43[] = {0x280f,0x2817,0x2811,0x280d,0x280a,0x2811,0x2817}; 482 static const itemTest t431[2] = {{{0,0,0,0,0,0},0,0,0,0,0,brai_tag,FALSE},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 483 static const itemTest t432[4] = {{{0,0,0,0,0,0},0,0,0,2,0,brai_tag,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 484 485 /* Private and Surrogates Area */ 486 static const WCHAR test44[] = {0xe000, 0xe001, 0xd800, 0xd801}; 487 static const itemTest t441[3] = {{{0,0,0,0,0,0},0,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},2,0,0,0,0,0,FALSE},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 488 static const itemTest t442[4] = {{{0,0,0,0,0,0},0,0,0,2,0,0,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},2,0,0,2,0,0,TRUE,{-1,1,1,1,-1,-1}},{{0,0,0,0,0,0},4,0,0,0,0,-1,FALSE}}; 489 490 /* Deseret */ 491 static const WCHAR test45[] = {0xd801,0xdc19,0xd801,0xdc32,0xd801,0xdc4c,0xd801,0xdc3c,0xd801,0xdc32,0xd801,0xdc4b,0xd801,0xdc2f,0xd801,0xdc4c,0xd801,0xdc3b,0xd801,0xdc32,0xd801,0xdc4a,0xd801,0xdc28}; 492 static const itemTest t451[2] = {{{0,0,0,0,0,0},0,0,0,0,0,dsrt_tag,TRUE,{-1,-1,-1,-1,-1,0x0}},{{0,0,0,0,0,0},24,0,0,0,0,-1,FALSE}}; 493 static const itemTest t452[2] = {{{0,0,0,0,0,0},0,0,0,2,0,dsrt_tag,TRUE,{-1,1,1,1,-1,0x0}},{{0,0,0,0,0,0},24,0,0,0,0,-1,FALSE}}; 494 495 /* Osmanya */ 496 static const WCHAR test46[] = {0xd801,0xdc8b,0xd801,0xdc98,0xd801,0xdc88,0xd801,0xdc91,0xd801,0xdc9b,0xd801,0xdc92,0xd801,0xdc95,0xd801,0xdc80}; 497 static const itemTest t461[2] = {{{0,0,0,0,0,0},0,0,0,0,0,osma_tag,TRUE,{-1,-1,-1,-1,-1,0x0}},{{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 498 static const itemTest t462[2] = {{{0,0,0,0,0,0},0,0,0,2,0,osma_tag,TRUE,{-1,1,1,1,-1,0x0}},{{0,0,0,0,0,0},16,0,0,0,0,-1,FALSE}}; 499 500 /* Mathematical Alphanumeric Symbols */ 501 static const WCHAR test47[] = {0xd835,0xdc00,0xd835,0xdc35,0xd835,0xdc6a,0xd835,0xdc9f,0xd835,0xdcd4,0xd835,0xdd09,0xd835,0xdd3e,0xd835,0xdd73,0xd835,0xdda8,0xd835,0xdddd,0xd835,0xde12,0xd835,0xde47,0xd835,0xde7c}; 502 static const itemTest t471[2] = {{{0,0,0,0,0,0},0,0,0,0,0,math_tag,TRUE,{-1,-1,-1,-1,-1,0x0}},{{0,0,0,0,0,0},26,0,0,0,0,-1,FALSE}}; 503 static const itemTest t472[2] = {{{0,0,0,0,0,0},0,0,0,2,0,math_tag,TRUE,{-1,1,1,1,-1,0x0}},{{0,0,0,0,0,0},26,0,0,0,0,-1,FALSE}}; 504 505 /* Mathematical and Numeric combinations */ 506 /* These have a leading hebrew character to force complicated itemization */ 507 static const WCHAR test48[] = {0x05e9,' ','1','2','3','.'}; 508 static const itemTest t481[4] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 509 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},5,0,0,0,0,0,FALSE}, 510 {{0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 511 static const itemTest t482[4] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 512 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 513 {{0,0,0,0,0,0},5,0,0,0,1,0,FALSE}, 514 {{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 515 516 static const WCHAR test49[] = {0x05e9,' ','1','2','.','1','2'}; 517 static const itemTest t491[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 518 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 519 static const itemTest t492[3] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 520 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 521 {{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 522 523 static const WCHAR test50[] = {0x05e9,' ','.','1','2','3'}; 524 static const itemTest t501[4] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 525 {{0,0,0,0,0},2,1,1,1,0,0,FALSE},{{0,0,0,0,0},3,0,1,2,0,0,FALSE}, 526 {{0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 527 static const itemTest t502[4] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 528 {{0,0,0,0,0,0},2,0,0,0,1,0,FALSE}, 529 {{0,0,0,0,0,0},3,0,1,0,1,0,FALSE}, 530 {{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 531 532 static const WCHAR test51[] = {0x05e9,' ','a','b','.','1','2'}; 533 static const itemTest t511[5] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 534 {{0,0,0,0,0},1,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0},4,0,0,0,0,0,FALSE}, 535 {{0,0,0,0,0},5,0,0,2,0,0,FALSE},{{0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 536 static const itemTest t512[5] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 537 {{0,0,0,0,0,0},2,0,0,0,1,latn_tag,FALSE}, 538 {{0,0,0,0,0,0},4,0,0,0,1,0,FALSE}, 539 {{0,0,0,0,0,0},5,0,0,0,1,0,FALSE}, 540 {{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 541 542 static const WCHAR test52[] = {0x05e9,' ','1','2','.','a','b'}; 543 static const itemTest t521[5] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 544 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},4,0,0,0,0,0,FALSE}, 545 {{0,0,0,0,0},5,0,0,0,0,latn_tag,FALSE},{{0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 546 static const itemTest t522[5] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 547 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 548 {{0,0,0,0,0,0},4,0,0,0,1,0,FALSE}, 549 {{0,0,0,0,0,0},5,0,0,0,1,latn_tag,FALSE}, 550 {{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 551 552 static const WCHAR test53[] = {0x05e9,' ','1','2','.','.','1','2'}; 553 static const itemTest t531[5] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 554 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},4,1,1,1,0,0,FALSE}, 555 {{0,0,0,0,0},6,0,1,2,0,0,FALSE},{{0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 556 static const itemTest t532[5] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 557 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 558 {{0,0,0,0,0,0},4,0,0,0,1,0,FALSE}, 559 {{0,0,0,0,0,0},6,0,1,0,1,0,FALSE}, 560 {{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 561 562 static const WCHAR test54[] = {0x05e9,' ','1','2','+','1','2'}; 563 static const itemTest t541[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 564 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 565 static const itemTest t542[3] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 566 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 567 {{0,0,0,0,0,0},7,0,0,0,0,-1,FALSE}}; 568 static const WCHAR test55[] = {0x05e9,' ','1','2','+','+','1','2'}; 569 static const itemTest t551[3] = {{{0,0,0,0,0,0},0,1,1,1,0,hebr_tag,FALSE}, 570 {{0,0,0,0,0},2,0,1,2,0,0,FALSE},{{0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 571 static const itemTest t552[3] = {{{0,0,0,0,0,0},0,0,0,0,1,hebr_tag,FALSE}, 572 {{0,0,0,0,0,0},2,0,1,0,1,0,FALSE}, 573 {{0,0,0,0,0,0},8,0,0,0,0,-1,FALSE}}; 574 575 /* ZWNJ */ 576 static const WCHAR test56[] = {0x0645, 0x06cc, 0x200c, 0x06a9, 0x0646, 0x0645}; /* میکنم */ 577 static const itemTest t561[] = {{{0,0,0,0,0,0},0,1,1,1,0,arab_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 578 static const itemTest t562[] = {{{0,0,0,0,0,0},0,0,0,0,1,arab_tag,FALSE},{{0,0,0,0,0,0},6,0,0,0,0,-1,FALSE}}; 579 580 /* Persian numerals and punctuation. */ 581 static const WCHAR test57[] = {0x06f1, 0x06f2, 0x066c, 0x06f3, 0x06f4, 0x06f5, 0x066c, /* ۱۲٬۳۴۵٬ */ 582 0x06f6, 0x06f7, 0x06f8, 0x066b, 0x06f9, 0x06f0}; /* ۶۷۸٫۹۰ */ 583 static const itemTest t571[] = {{{0,0,0,0,0,0}, 0,0,1,2,0,arab_tag,FALSE},{{0,0,0,0,0,0}, 2,0,1,2,0,arab_tag,FALSE}, 584 {{0,0,0,0,0,0}, 3,0,1,2,0,arab_tag,FALSE},{{0,0,0,0,0,0}, 6,0,1,2,0,arab_tag,FALSE}, 585 {{0,0,0,0,0,0}, 7,0,1,2,0,arab_tag,FALSE},{{0,0,0,0,0,0},10,0,1,2,0,arab_tag,FALSE}, 586 {{0,0,0,0,0,0},11,0,1,2,0,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 587 static const itemTest t572[] = {{{0,0,0,0,0,0}, 0,0,0,2,0,arab_tag,FALSE},{{0,0,1,0,0,0}, 2,0,1,2,0,arab_tag,FALSE}, 588 {{0,0,0,0,0,0}, 3,0,0,2,0,arab_tag,FALSE},{{0,0,1,0,0,0}, 6,0,1,2,0,arab_tag,FALSE}, 589 {{0,0,0,0,0,0}, 7,0,0,2,0,arab_tag,FALSE},{{0,0,1,0,0,0},10,0,1,2,0,arab_tag,FALSE}, 590 {{0,0,0,0,0,0},11,0,0,2,0,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 591 static const itemTest t573[] = {{{0,0,0,0,0,0}, 0,0,0,0,1,arab_tag,FALSE},{{0,0,0,0,0,0}, 2,0,0,0,1,arab_tag,FALSE}, 592 {{0,0,0,0,0,0}, 3,0,0,0,1,arab_tag,FALSE},{{0,0,0,0,0,0}, 6,0,0,0,1,arab_tag,FALSE}, 593 {{0,0,0,0,0,0}, 7,0,0,0,1,arab_tag,FALSE},{{0,0,0,0,0,0},10,0,0,0,1,arab_tag,FALSE}, 594 {{0,0,0,0,0,0},11,0,0,0,1,arab_tag,FALSE},{{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 595 /* Arabic numerals and punctuation. */ 596 static const WCHAR test58[] = {0x0661, 0x0662, 0x066c, 0x0663, 0x0664, 0x0665, 0x066c, /* ١٢٬٣٤٥٬ */ 597 0x0666, 0x0667, 0x0668, 0x066b, 0x0669, 0x0660}; /* ٦٧٨٫٩٠ */ 598 static const itemTest t581[] = {{{0,0,0,0,0,0}, 0,0,1,2,0,arab_tag,FALSE}, 599 {{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 600 static const itemTest t582[] = {{{0,0,1,1,1,0}, 0,0,0,0,1,arab_tag,FALSE}, 601 {{0,0,0,0,0,0},13,0,0,0,0,-1,FALSE}}; 602 603 SCRIPT_ITEM items[15]; 604 SCRIPT_CONTROL Control; 605 SCRIPT_STATE State; 606 HRESULT hr; 607 int nItems; 608 609 memset(&Control, 0, sizeof(Control)); 610 memset(&State, 0, sizeof(State)); 611 612 hr = ScriptItemize(NULL, 4, 10, &Control, &State, items, NULL); 613 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pwcInChars is NULL\n"); 614 615 hr = ScriptItemize(test1, 4, 10, &Control, &State, NULL, NULL); 616 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pItems is NULL\n"); 617 618 hr = ScriptItemize(test1, 4, 1, &Control, &State, items, NULL); 619 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cMaxItems < 2.\n"); 620 621 hr = ScriptItemize(test1, 0, 10, NULL, NULL, items, &nItems); 622 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n"); 623 624 test_items_ok(test1,4,NULL,NULL,1,t11,FALSE,0); 625 test_items_ok(test1b,4,NULL,NULL,1,t1b1,FALSE,0); 626 test_items_ok(test1c,6,NULL,NULL,1,t1c1,FALSE,0); 627 test_items_ok(test2,16,NULL,NULL,6,t21,FALSE,0); 628 test_items_ok(test2b,11,NULL,NULL,4,t2b1,FALSE,0); 629 test_items_ok(test2c,11,NULL,NULL,4,t2c1,FALSE,0); 630 test_items_ok(test2d,11,NULL,NULL,4,t2d1,FALSE,0); 631 test_items_ok(test3,41,NULL,NULL,1,t31,FALSE,0); 632 test_items_ok(test4,12,NULL,NULL,5,t41,FALSE,0); 633 test_items_ok(test5,38,NULL,NULL,1,t51,FALSE,0); 634 test_items_ok(test6,5,NULL,NULL,2,t61,FALSE,0); 635 test_items_ok(test7,29,NULL,NULL,3,t71,FALSE,0); 636 test_items_ok(test8,4,NULL,NULL,1,t81,FALSE,0); 637 test_items_ok(test9,5,NULL,NULL,2,t91,FALSE,0); 638 test_items_ok(test10,4,NULL,NULL,1,t101,FALSE,0); 639 test_items_ok(test11,8,NULL,NULL,1,t111,FALSE,0); 640 test_items_ok(test12,5,NULL,NULL,1,t121,FALSE,0); 641 test_items_ok(test13,7,NULL,NULL,1,t131,FALSE,0); 642 test_items_ok(test14,7,NULL,NULL,1,t141,FALSE,0); 643 test_items_ok(test15,5,NULL,NULL,1,t151,FALSE,0); 644 test_items_ok(test16,5,NULL,NULL,1,t161,FALSE,0); 645 test_items_ok(test17,6,NULL,NULL,1,t171,FALSE,0); 646 test_items_ok(test18,5,NULL,NULL,1,t181,FALSE,0); 647 test_items_ok(test19,6,NULL,NULL,1,t191,FALSE,0); 648 test_items_ok(test20,5,NULL,NULL,2,t201,FALSE,0); 649 test_items_ok(test21,5,NULL,NULL,1,t211,FALSE,0); 650 test_items_ok(test22,6,NULL,NULL,2,t221,FALSE,0); 651 test_items_ok(test23,6,NULL,NULL,2,t231,FALSE,0); 652 test_items_ok(test24,12,NULL,NULL,1,t241,FALSE,0); 653 test_items_ok(test25,10,NULL,NULL,1,t251,FALSE,0); 654 test_items_ok(test26,2,NULL,NULL,1,t261,FALSE,0); 655 test_items_ok(test27,8,NULL,NULL,1,t271,FALSE,0); 656 test_items_ok(test28,4,NULL,NULL,1,t281,FALSE,0); 657 test_items_ok(test29,10,NULL,NULL,2,t291,FALSE,0); 658 test_items_ok(test30,8,NULL,NULL,1,t301,FALSE,0); 659 test_items_ok(test31,8,NULL,NULL,1,t311,FALSE,b311); 660 test_items_ok(test32,3,NULL,NULL,1,t321,FALSE,0); 661 test_items_ok(test33,4,NULL,NULL,1,t331,FALSE,0); 662 test_items_ok(test34,3,NULL,NULL,1,t341,FALSE,0); 663 test_items_ok(test35,13,NULL,NULL,1,t351,FALSE,b351); 664 test_items_ok(test36,7,NULL,NULL,1,t361,FALSE,0); 665 test_items_ok(test37,3,NULL,NULL,1,t371,FALSE,0); 666 test_items_ok(test38,2,NULL,NULL,1,t381,FALSE,0); 667 test_items_ok(test39,10,NULL,NULL,1,t391,FALSE,0); 668 test_items_ok(test40,6,NULL,NULL,1,t401,FALSE,0); 669 test_items_ok(test41,6,NULL,NULL,1,t411,FALSE,0); 670 test_items_ok(test42,6,NULL,NULL,1,t421,FALSE,0); 671 test_items_ok(test43,7,NULL,NULL,1,t431,FALSE,0); 672 test_items_ok(test44,4,NULL,NULL,2,t441,FALSE,0); 673 test_items_ok(test45,24,NULL,NULL,1,t451,FALSE,0); 674 test_items_ok(test46,16,NULL,NULL,1,t461,FALSE,0); 675 test_items_ok(test47,26,NULL,NULL,1,t471,FALSE,0); 676 test_items_ok(test56,6,NULL,NULL,1,t561,FALSE,0); 677 test_items_ok(test57,13,NULL,NULL,7,t571,FALSE,0); 678 test_items_ok(test58,13,NULL,NULL,1,t581,FALSE,0); 679 680 State.uBidiLevel = 0; 681 test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); 682 test_items_ok(test1b,4,&Control,&State,1,t1b1,FALSE,0); 683 test_items_ok(test1c,6,&Control,&State,1,t1c1,FALSE,0); 684 test_items_ok(test2,16,&Control,&State,4,t22,FALSE,0); 685 test_items_ok(test2b,11,&Control,&State,4,t2b1,FALSE,0); 686 test_items_ok(test2c,11,&Control,&State,5,t2c2,FALSE,0); 687 test_items_ok(test2d,11,&Control,&State,5,t2d2,FALSE,0); 688 test_items_ok(test3,41,&Control,&State,1,t31,FALSE,0); 689 test_items_ok(test4,12,&Control,&State,5,t41,FALSE,0); 690 test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); 691 test_items_ok(test6,5,&Control,&State,2,t61,FALSE,0); 692 test_items_ok(test7,29,&Control,&State,3,t72,FALSE,0); 693 test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); 694 test_items_ok(test9,5,&Control,&State,2,t91,FALSE,0); 695 test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); 696 test_items_ok(test11,8,&Control,&State,1,t111,FALSE,0); 697 test_items_ok(test12,5,&Control,&State,1,t121,FALSE,0); 698 test_items_ok(test13,7,&Control,&State,1,t131,FALSE,0); 699 test_items_ok(test14,7,&Control,&State,1,t141,FALSE,0); 700 test_items_ok(test15,5,&Control,&State,1,t151,FALSE,0); 701 test_items_ok(test16,5,&Control,&State,1,t161,FALSE,0); 702 test_items_ok(test17,6,&Control,&State,1,t171,FALSE,0); 703 test_items_ok(test18,5,&Control,&State,1,t181,FALSE,0); 704 test_items_ok(test19,6,&Control,&State,1,t191,FALSE,0); 705 test_items_ok(test20,5,&Control,&State,2,t201,FALSE,0); 706 test_items_ok(test21,5,&Control,&State,1,t211,FALSE,0); 707 test_items_ok(test22,6,&Control,&State,2,t221,FALSE,0); 708 test_items_ok(test23,6,&Control,&State,2,t231,FALSE,0); 709 test_items_ok(test24,12,&Control,&State,1,t241,FALSE,0); 710 test_items_ok(test25,10,&Control,&State,1,t251,FALSE,0); 711 test_items_ok(test26,2,&Control,&State,1,t261,FALSE,0); 712 test_items_ok(test27,8,&Control,&State,1,t271,FALSE,0); 713 test_items_ok(test28,4,&Control,&State,1,t281,FALSE,0); 714 test_items_ok(test29,10,&Control,&State,2,t291,FALSE,0); 715 test_items_ok(test30,8,&Control,&State,1,t301,FALSE,0); 716 test_items_ok(test31,8,&Control,&State,1,t311,FALSE,b311); 717 test_items_ok(test32,3,&Control,&State,1,t321,FALSE,0); 718 test_items_ok(test33,4,&Control,&State,1,t331,FALSE,0); 719 test_items_ok(test34,3,&Control,&State,1,t341,FALSE,0); 720 test_items_ok(test35,13,&Control,&State,1,t351,FALSE,b351); 721 test_items_ok(test36,7,&Control,&State,1,t361,FALSE,0); 722 test_items_ok(test37,3,&Control,&State,1,t371,FALSE,0); 723 test_items_ok(test38,2,&Control,&State,1,t381,FALSE,0); 724 test_items_ok(test39,10,&Control,&State,1,t391,FALSE,0); 725 test_items_ok(test40,6,&Control,&State,1,t401,FALSE,0); 726 test_items_ok(test41,6,&Control,&State,1,t411,FALSE,0); 727 test_items_ok(test42,6,&Control,&State,1,t421,FALSE,0); 728 test_items_ok(test43,7,&Control,&State,1,t431,FALSE,0); 729 test_items_ok(test44,4,&Control,&State,2,t441,FALSE,0); 730 test_items_ok(test45,24,&Control,&State,1,t451,FALSE,0); 731 test_items_ok(test46,16,&Control,&State,1,t461,FALSE,0); 732 test_items_ok(test47,26,&Control,&State,1,t471,FALSE,0); 733 test_items_ok(test48,6,&Control,&State,3,t481,FALSE,0); 734 test_items_ok(test49,7,&Control,&State,2,t491,FALSE,0); 735 test_items_ok(test50,6,&Control,&State,3,t501,FALSE,0); 736 test_items_ok(test51,7,&Control,&State,4,t511,FALSE,0); 737 test_items_ok(test52,7,&Control,&State,4,t521,FALSE,0); 738 test_items_ok(test53,8,&Control,&State,4,t531,FALSE,0); 739 test_items_ok(test54,7,&Control,&State,2,t541,FALSE,0); 740 test_items_ok(test55,8,&Control,&State,2,t551,FALSE,0); 741 test_items_ok(test56,6,&Control,&State,1,t561,FALSE,0); 742 test_items_ok(test57,13,&Control,&State,7,t572,FALSE,0); 743 test_items_ok(test58,13,&Control,&State,1,t581,FALSE,0); 744 745 State.uBidiLevel = 1; 746 test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); 747 test_items_ok(test1b,4,&Control,&State,1,t1b2,FALSE,0); 748 test_items_ok(test1c,6,&Control,&State,3,t1c2,FALSE,0); 749 test_items_ok(test2,16,&Control,&State,4,t23,FALSE,0); 750 test_items_ok(test2b,11,&Control,&State,4,t2b2,FALSE,0); 751 test_items_ok(test2c,11,&Control,&State,4,t2c3,FALSE,0); 752 test_items_ok(test2d,11,&Control,&State,4,t2d3,FALSE,0); 753 test_items_ok(test3,41,&Control,&State,1,t32,FALSE,0); 754 test_items_ok(test4,12,&Control,&State,4,t42,FALSE,0); 755 test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); 756 test_items_ok(test6,5,&Control,&State,2,t62,FALSE,0); 757 test_items_ok(test7,29,&Control,&State,3,t73,FALSE,0); 758 test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); 759 test_items_ok(test9,5,&Control,&State,2,t92,FALSE,0); 760 test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); 761 test_items_ok(test11,8,&Control,&State,1,t112,FALSE,0); 762 test_items_ok(test12,5,&Control,&State,1,t122,FALSE,0); 763 test_items_ok(test13,7,&Control,&State,1,t132,FALSE,0); 764 test_items_ok(test14,7,&Control,&State,1,t142,FALSE,0); 765 test_items_ok(test15,5,&Control,&State,1,t152,FALSE,0); 766 test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); 767 test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); 768 test_items_ok(test18,5,&Control,&State,1,t182,FALSE,0); 769 test_items_ok(test19,6,&Control,&State,1,t192,FALSE,0); 770 test_items_ok(test20,5,&Control,&State,2,t202,FALSE,0); 771 test_items_ok(test21,5,&Control,&State,1,t211,FALSE,0); 772 test_items_ok(test22,6,&Control,&State,2,t222,FALSE,b222); 773 test_items_ok(test23,6,&Control,&State,2,t232,FALSE,0); 774 test_items_ok(test24,12,&Control,&State,1,t242,FALSE,0); 775 test_items_ok(test25,10,&Control,&State,1,t252,FALSE,0); 776 test_items_ok(test26,2,&Control,&State,1,t262,FALSE,0); 777 test_items_ok(test27,8,&Control,&State,1,t272,FALSE,0); 778 test_items_ok(test28,4,&Control,&State,1,t282,FALSE,0); 779 test_items_ok(test29,10,&Control,&State,2,t292,FALSE,0); 780 test_items_ok(test30,8,&Control,&State,1,t302,FALSE,0); 781 test_items_ok(test31,8,&Control,&State,1,t312,FALSE,b312); 782 test_items_ok(test32,3,&Control,&State,1,t322,FALSE,0); 783 test_items_ok(test33,4,&Control,&State,1,t332,FALSE,0); 784 test_items_ok(test34,3,&Control,&State,1,t342,FALSE,b342); 785 test_items_ok(test35,13,&Control,&State,1,t352,FALSE,b352); 786 test_items_ok(test36,7,&Control,&State,1,t362,FALSE,0); 787 test_items_ok(test37,3,&Control,&State,1,t372,FALSE,0); 788 test_items_ok(test38,2,&Control,&State,1,t382,FALSE,0); 789 test_items_ok(test39,10,&Control,&State,1,t392,FALSE,0); 790 test_items_ok(test40,6,&Control,&State,1,t402,FALSE,0); 791 test_items_ok(test41,6,&Control,&State,3,t412,FALSE,b412); 792 test_items_ok(test42,6,&Control,&State,1,t422,FALSE,0); 793 test_items_ok(test43,7,&Control,&State,1,t432,FALSE,0); 794 test_items_ok(test44,4,&Control,&State,2,t442,FALSE,0); 795 test_items_ok(test45,24,&Control,&State,1,t452,FALSE,0); 796 test_items_ok(test46,16,&Control,&State,1,t462,FALSE,0); 797 test_items_ok(test47,26,&Control,&State,1,t472,FALSE,0); 798 test_items_ok(test56,6,&Control,&State,1,t561,FALSE,0); 799 test_items_ok(test57,13,&Control,&State,7,t571,FALSE,0); 800 test_items_ok(test58,13,&Control,&State,1,t581,FALSE,0); 801 802 State.uBidiLevel = 1; 803 Control.fMergeNeutralItems = TRUE; 804 test_items_ok(test1,4,&Control,&State,1,t12,FALSE,0); 805 test_items_ok(test1b,4,&Control,&State,1,t1b2,FALSE,0); 806 test_items_ok(test1c,6,&Control,&State,3,t1c2,FALSE,0); 807 test_items_ok(test2,16,&Control,&State,4,t23,FALSE,0); 808 test_items_ok(test2b,11,&Control,&State,2,t2b3,FALSE,b2); 809 test_items_ok(test2c,11,&Control,&State,2,t2c4,FALSE,b2); 810 test_items_ok(test2d,11,&Control,&State,2,t2d4,FALSE,b2); 811 test_items_ok(test3,41,&Control,&State,1,t32,FALSE,0); 812 test_items_ok(test4,12,&Control,&State,3,t43,FALSE,b43); 813 test_items_ok(test5,38,&Control,&State,1,t51,FALSE,0); 814 test_items_ok(test6,5,&Control,&State,1,t63,FALSE,b63); 815 test_items_ok(test7,29,&Control,&State,3,t73,FALSE,0); 816 test_items_ok(test8,4,&Control,&State,1,t81,FALSE,0); 817 test_items_ok(test9,5,&Control,&State,1,t93,FALSE,b93); 818 test_items_ok(test10,4,&Control,&State,1,t101,FALSE,0); 819 test_items_ok(test11,8,&Control,&State,1,t112,FALSE,0); 820 test_items_ok(test12,5,&Control,&State,1,t122,FALSE,0); 821 test_items_ok(test13,7,&Control,&State,1,t132,FALSE,0); 822 test_items_ok(test14,7,&Control,&State,1,t142,FALSE,0); 823 test_items_ok(test15,5,&Control,&State,1,t152,FALSE,0); 824 test_items_ok(test16,5,&Control,&State,1,t162,FALSE,0); 825 test_items_ok(test17,6,&Control,&State,1,t172,FALSE,0); 826 test_items_ok(test18,5,&Control,&State,1,t182,FALSE,0); 827 test_items_ok(test19,6,&Control,&State,1,t192,FALSE,0); 828 test_items_ok(test20,5,&Control,&State,2,t202,FALSE,0); 829 test_items_ok(test21,5,&Control,&State,1,t211,FALSE,0); 830 test_items_ok(test22,6,&Control,&State,1,t223,FALSE,b223); 831 test_items_ok(test23,6,&Control,&State,2,t232,FALSE,0); 832 test_items_ok(test24,12,&Control,&State,1,t242,FALSE,0); 833 test_items_ok(test25,10,&Control,&State,1,t252,FALSE,0); 834 test_items_ok(test26,2,&Control,&State,1,t262,FALSE,0); 835 test_items_ok(test27,8,&Control,&State,1,t272,FALSE,0); 836 test_items_ok(test28,4,&Control,&State,1,t282,FALSE,0); 837 test_items_ok(test29,10,&Control,&State,2,t292,FALSE,0); 838 test_items_ok(test30,8,&Control,&State,1,t302,FALSE,0); 839 test_items_ok(test31,8,&Control,&State,1,t312,FALSE,b312); 840 test_items_ok(test32,3,&Control,&State,1,t322,FALSE,0); 841 test_items_ok(test33,4,&Control,&State,1,t332,FALSE,0); 842 test_items_ok(test34,3,&Control,&State,1,t342,FALSE,b342); 843 test_items_ok(test35,13,&Control,&State,1,t352,FALSE,b352); 844 test_items_ok(test36,7,&Control,&State,1,t362,FALSE,0); 845 test_items_ok(test37,3,&Control,&State,1,t372,FALSE,0); 846 test_items_ok(test38,2,&Control,&State,1,t382,FALSE,0); 847 test_items_ok(test39,10,&Control,&State,1,t392,FALSE,0); 848 test_items_ok(test40,6,&Control,&State,1,t402,FALSE,0); 849 test_items_ok(test41,6,&Control,&State,3,t412,FALSE,b412); 850 test_items_ok(test42,6,&Control,&State,1,t422,FALSE,0); 851 test_items_ok(test43,7,&Control,&State,1,t432,FALSE,0); 852 test_items_ok(test44,4,&Control,&State,2,t442,FALSE,0); 853 test_items_ok(test45,24,&Control,&State,1,t452,FALSE,0); 854 test_items_ok(test46,16,&Control,&State,1,t462,FALSE,0); 855 test_items_ok(test47,26,&Control,&State,1,t472,FALSE,0); 856 test_items_ok(test56,6,&Control,&State,1,t561,FALSE,0); 857 test_items_ok(test57,13,&Control,&State,7,t571,FALSE,0); 858 test_items_ok(test58,13,&Control,&State,1,t581,FALSE,0); 859 860 State.uBidiLevel = 0; 861 Control.fMergeNeutralItems = FALSE; 862 State.fOverrideDirection = 1; 863 test_items_ok(test1,4,&Control,&State,1,t11,FALSE,0); 864 test_items_ok(test1b,4,&Control,&State,1,t1b1,FALSE,0); 865 test_items_ok(test1c,6,&Control,&State,1,t1c1,FALSE,0); 866 test_items_ok(test2,16,&Control,&State,4,t24,FALSE,0); 867 test_items_ok(test2b,11,&Control,&State,4,t2b4,FALSE,0); 868 test_items_ok(test2c,11,&Control,&State,4,t2c5,FALSE,0); 869 test_items_ok(test2d,11,&Control,&State,4,t2d5,FALSE,0); 870 test_items_ok(test3,41,&Control,&State,1,t31,FALSE,0); 871 test_items_ok(test4,12,&Control,&State,5,t41,FALSE,0); 872 test_items_ok(test5,38,&Control,&State,1,t52,FALSE,0); 873 test_items_ok(test6,5,&Control,&State,2,t64,FALSE,0); 874 test_items_ok(test7,29,&Control,&State,3,t74,FALSE,0); 875 test_items_ok(test8,4,&Control,&State,1,t82,FALSE,0); 876 test_items_ok(test9,5,&Control,&State,2,t94,FALSE,0); 877 test_items_ok(test10,4,&Control,&State,1,t102,FALSE,0); 878 test_items_ok(test11,8,&Control,&State,1,t111,FALSE,0); 879 test_items_ok(test12,5,&Control,&State,1,t121,FALSE,0); 880 test_items_ok(test13,7,&Control,&State,1,t131,FALSE,0); 881 test_items_ok(test14,7,&Control,&State,1,t141,FALSE,0); 882 test_items_ok(test15,5,&Control,&State,1,t151,FALSE,0); 883 test_items_ok(test16,5,&Control,&State,1,t161,FALSE,0); 884 test_items_ok(test17,6,&Control,&State,1,t171,FALSE,0); 885 test_items_ok(test18,5,&Control,&State,1,t181,FALSE,0); 886 test_items_ok(test19,6,&Control,&State,1,t191,FALSE,0); 887 test_items_ok(test20,5,&Control,&State,2,t201,FALSE,0); 888 test_items_ok(test21,5,&Control,&State,1,t212,FALSE,0); 889 test_items_ok(test22,6,&Control,&State,2,t221,FALSE,0); 890 test_items_ok(test23,6,&Control,&State,2,t231,FALSE,0); 891 test_items_ok(test24,12,&Control,&State,1,t241,FALSE,0); 892 test_items_ok(test25,10,&Control,&State,1,t251,FALSE,0); 893 test_items_ok(test26,2,&Control,&State,1,t261,FALSE,0); 894 test_items_ok(test27,8,&Control,&State,1,t271,FALSE,0); 895 test_items_ok(test28,4,&Control,&State,1,t281,FALSE,0); 896 test_items_ok(test29,10,&Control,&State,2,t291,FALSE,0); 897 test_items_ok(test30,8,&Control,&State,1,t301,FALSE,0); 898 test_items_ok(test31,8,&Control,&State,1,t311,FALSE,b311); 899 test_items_ok(test32,3,&Control,&State,1,t321,FALSE,0); 900 test_items_ok(test33,4,&Control,&State,1,t331,FALSE,0); 901 test_items_ok(test34,3,&Control,&State,1,t341,FALSE,0); 902 test_items_ok(test35,13,&Control,&State,1,t353,FALSE,b351); 903 test_items_ok(test36,7,&Control,&State,1,t361,FALSE,0); 904 test_items_ok(test37,3,&Control,&State,1,t373,FALSE,0); 905 test_items_ok(test38,2,&Control,&State,1,t381,FALSE,0); 906 test_items_ok(test39,10,&Control,&State,1,t391,FALSE,0); 907 test_items_ok(test40,6,&Control,&State,1,t401,FALSE,0); 908 test_items_ok(test41,6,&Control,&State,1,t411,FALSE,0); 909 test_items_ok(test42,6,&Control,&State,1,t421,FALSE,0); 910 test_items_ok(test43,7,&Control,&State,1,t431,FALSE,0); 911 test_items_ok(test44,4,&Control,&State,2,t441,FALSE,0); 912 test_items_ok(test45,24,&Control,&State,1,t451,FALSE,0); 913 test_items_ok(test46,16,&Control,&State,1,t461,FALSE,0); 914 test_items_ok(test47,26,&Control,&State,1,t471,FALSE,0); 915 test_items_ok(test48,6,&Control,&State,3,t482,FALSE,0); 916 test_items_ok(test49,7,&Control,&State,2,t492,FALSE,0); 917 test_items_ok(test50,6,&Control,&State,3,t502,FALSE,0); 918 test_items_ok(test51,7,&Control,&State,4,t512,FALSE,0); 919 test_items_ok(test52,7,&Control,&State,4,t522,FALSE,0); 920 test_items_ok(test53,8,&Control,&State,4,t532,FALSE,0); 921 test_items_ok(test54,7,&Control,&State,2,t542,FALSE,0); 922 test_items_ok(test55,8,&Control,&State,2,t552,FALSE,0); 923 test_items_ok(test56,6,&Control,&State,1,t562,FALSE,0); 924 test_items_ok(test57,13,&Control,&State,7,t573,FALSE,0); 925 test_items_ok(test58,13,&Control,&State,1,t582,FALSE,0); 926 } 927 928 static void make_surrogate(DWORD i, WORD out[2]) 929 { 930 static const DWORD mask = (1 << 10) - 1; 931 932 if (i <= 0xffff) 933 { 934 out[0] = i; 935 out[1] = 0; 936 } 937 else 938 { 939 i -= 0x010000; 940 out[0] = ((i >> 10) & mask) + 0xd800; 941 out[1] = (i & mask) + 0xdc00; 942 } 943 } 944 945 static void test_ScriptItemize_surrogates(void) 946 { 947 HRESULT hr; 948 WCHAR surrogate[2]; 949 WORD Script_Surrogates; 950 SCRIPT_ITEM items[2]; 951 int num; 952 953 /* Find Script_Surrogates */ 954 surrogate[0] = 0xd800; 955 hr = ScriptItemize( surrogate, 1, 2, NULL, NULL, items, &num ); 956 ok( hr == S_OK, "got %08x\n", hr ); 957 ok( num == 1, "got %d\n", num ); 958 ok( items[0].a.eScript != SCRIPT_UNDEFINED, "got script %x\n", items[0].a.eScript ); 959 Script_Surrogates = items[0].a.eScript; 960 961 /* Show that an invalid character has script Script_Surrogates */ 962 make_surrogate( 0x01ffff, surrogate ); 963 hr = ScriptItemize( surrogate, 2, 2, NULL, NULL, items, &num ); 964 ok( hr == S_OK, "got %08x\n", hr ); 965 ok( num == 1, "got %d\n", num ); 966 ok( items[0].a.eScript == Script_Surrogates, "got script %x\n", items[0].a.eScript ); 967 } 968 969 static inline void _test_shape_ok(int valid, HDC hdc, LPCWSTR string, 970 DWORD cchString, SCRIPT_CONTROL *Control, 971 SCRIPT_STATE *State, DWORD item, DWORD nGlyphs, 972 const shapeTest_char *charItems, 973 const shapeTest_glyph *glyphItems, 974 const SCRIPT_GLYPHPROP *props2) 975 { 976 HRESULT hr; 977 int x, outnItems = 0, outnGlyphs = 0, outnGlyphs2 = 0; 978 const SCRIPT_PROPERTIES **script_properties; 979 SCRIPT_ITEM outpItems[15]; 980 SCRIPT_CACHE sc = NULL; 981 WORD *glyphs, *glyphs2; 982 WORD *logclust, *logclust2; 983 int maxGlyphs = cchString * 1.5; 984 SCRIPT_GLYPHPROP *glyphProp, *glyphProp2; 985 SCRIPT_CHARPROP *charProp, *charProp2; 986 int script_count; 987 WCHAR *string2; 988 ULONG tags[15]; 989 990 hr = ScriptGetProperties(&script_properties, &script_count); 991 winetest_ok(SUCCEEDED(hr), "Failed to get script properties, hr %#x.\n", hr); 992 993 hr = pScriptItemizeOpenType(string, cchString, 15, Control, State, outpItems, tags, &outnItems); 994 if (valid > 0) 995 winetest_ok(hr == S_OK, "ScriptItemizeOpenType should return S_OK not %08x\n", hr); 996 else if (hr != S_OK) 997 winetest_trace("ScriptItemizeOpenType should return S_OK not %08x\n", hr); 998 999 if (outnItems <= item) 1000 { 1001 if (valid > 0) 1002 winetest_win_skip("Did not get enough items\n"); 1003 else 1004 winetest_trace("Did not get enough items\n"); 1005 return; 1006 } 1007 1008 logclust = HeapAlloc(GetProcessHeap(), 0, sizeof(WORD) * cchString); 1009 memset(logclust,'a',sizeof(WORD) * cchString); 1010 charProp = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_CHARPROP) * cchString); 1011 memset(charProp,'a',sizeof(SCRIPT_CHARPROP) * cchString); 1012 glyphs = HeapAlloc(GetProcessHeap(), 0, sizeof(WORD) * maxGlyphs); 1013 memset(glyphs,'a',sizeof(WORD) * cchString); 1014 glyphProp = HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_GLYPHPROP) * maxGlyphs); 1015 memset(glyphProp,'a',sizeof(SCRIPT_GLYPHPROP) * cchString); 1016 1017 string2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*string2)); 1018 logclust2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*logclust2)); 1019 memset(logclust2, 'a', cchString * sizeof(*logclust2)); 1020 charProp2 = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(*charProp2)); 1021 memset(charProp2, 'a', cchString * sizeof(*charProp2)); 1022 glyphs2 = HeapAlloc(GetProcessHeap(), 0, maxGlyphs * sizeof(*glyphs2)); 1023 memset(glyphs2, 'a', maxGlyphs * sizeof(*glyphs2)); 1024 glyphProp2 = HeapAlloc(GetProcessHeap(), 0, maxGlyphs * sizeof(*glyphProp2)); 1025 memset(glyphProp2, 'a', maxGlyphs * sizeof(*glyphProp2)); 1026 1027 winetest_ok(!outpItems[item].a.fLogicalOrder, "Got unexpected fLogicalOrder %#x.\n", 1028 outpItems[item].a.fLogicalOrder); 1029 hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, string, cchString, maxGlyphs, logclust, charProp, glyphs, glyphProp, &outnGlyphs); 1030 if (valid > 0) 1031 winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); 1032 else if (hr != S_OK) 1033 winetest_trace("ScriptShapeOpenType failed (%x)\n",hr); 1034 if (FAILED(hr)) 1035 goto cleanup; 1036 1037 for (x = 0; x < cchString; x++) 1038 { 1039 if (valid > 0) 1040 winetest_ok(logclust[x] == charItems[x].wLogClust, "%i: invalid LogClust(%i)\n",x,logclust[x]); 1041 else if (logclust[x] != charItems[x].wLogClust) 1042 winetest_trace("%i: invalid LogClust(%i)\n",x,logclust[x]); 1043 if (valid > 0) 1044 winetest_ok(charProp[x].fCanGlyphAlone == charItems[x].CharProp.fCanGlyphAlone, "%i: invalid fCanGlyphAlone\n",x); 1045 else if (charProp[x].fCanGlyphAlone != charItems[x].CharProp.fCanGlyphAlone) 1046 winetest_trace("%i: invalid fCanGlyphAlone\n",x); 1047 } 1048 1049 if (valid > 0) 1050 winetest_ok(nGlyphs == outnGlyphs, "got incorrect number of glyphs (%i)\n",outnGlyphs); 1051 else if (nGlyphs != outnGlyphs) 1052 winetest_trace("got incorrect number of glyphs (%i)\n",outnGlyphs); 1053 for (x = 0; x < outnGlyphs; x++) 1054 { 1055 if (glyphItems[x].Glyph) 1056 { 1057 if (valid > 0) 1058 winetest_ok(glyphs[x]!=0, "%i: Glyph not present when it should be\n",x); 1059 else if (glyphs[x]==0) 1060 winetest_trace("%i: Glyph not present when it should be\n",x); 1061 } 1062 else 1063 { 1064 if (valid > 0) 1065 winetest_ok(glyphs[x]==0, "%i: Glyph present when it should not be\n",x); 1066 else if (glyphs[x]!=0) 1067 winetest_trace("%i: Glyph present when it should not be\n",x); 1068 } 1069 if (valid > 0) 1070 { 1071 todo_wine_if(tags[item] == syrc_tag && !x) 1072 winetest_ok(glyphProp[x].sva.uJustification == glyphItems[x].GlyphProp.sva.uJustification || 1073 (props2 && glyphProp[x].sva.uJustification == props2[x].sva.uJustification), 1074 "%i: uJustification incorrect (%i)\n",x,glyphProp[x].sva.uJustification); 1075 } 1076 else if (glyphProp[x].sva.uJustification != glyphItems[x].GlyphProp.sva.uJustification) 1077 { 1078 winetest_trace("%i: uJustification incorrect (%i)\n",x,glyphProp[x].sva.uJustification); 1079 } 1080 if (valid > 0) 1081 winetest_ok(glyphProp[x].sva.fClusterStart == glyphItems[x].GlyphProp.sva.fClusterStart || 1082 (props2 && glyphProp[x].sva.fClusterStart == props2[x].sva.fClusterStart), 1083 "%i: fClusterStart incorrect (%i)\n",x,glyphProp[x].sva.fClusterStart); 1084 else if (glyphProp[x].sva.fClusterStart != glyphItems[x].GlyphProp.sva.fClusterStart) 1085 winetest_trace("%i: fClusterStart incorrect (%i)\n",x,glyphProp[x].sva.fClusterStart); 1086 if (valid > 0) 1087 winetest_ok(glyphProp[x].sva.fDiacritic == glyphItems[x].GlyphProp.sva.fDiacritic || 1088 (props2 && glyphProp[x].sva.fDiacritic == props2[x].sva.fDiacritic), 1089 "%i: fDiacritic incorrect (%i)\n",x,glyphProp[x].sva.fDiacritic); 1090 else if (glyphProp[x].sva.fDiacritic != glyphItems[x].GlyphProp.sva.fDiacritic) 1091 winetest_trace("%i: fDiacritic incorrect (%i)\n",x,glyphProp[x].sva.fDiacritic); 1092 if (valid > 0) 1093 winetest_ok(glyphProp[x].sva.fZeroWidth == glyphItems[x].GlyphProp.sva.fZeroWidth || 1094 (props2 && glyphProp[x].sva.fZeroWidth == props2[x].sva.fZeroWidth), 1095 "%i: fZeroWidth incorrect (%i)\n",x,glyphProp[x].sva.fZeroWidth); 1096 else if (glyphProp[x].sva.fZeroWidth != glyphItems[x].GlyphProp.sva.fZeroWidth) 1097 winetest_trace("%i: fZeroWidth incorrect (%i)\n",x,glyphProp[x].sva.fZeroWidth); 1098 } 1099 1100 outpItems[item].a.fLogicalOrder = 1; 1101 hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, 1102 string, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); 1103 winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); 1104 /* Cluster maps are hard. */ 1105 if (tags[item] != thaa_tag && tags[item] != syrc_tag) 1106 { 1107 for (x = 0; x < cchString; ++x) 1108 { 1109 unsigned int compare_idx = outpItems[item].a.fRTL ? cchString - x - 1 : x; 1110 winetest_ok(logclust2[x] == logclust[compare_idx], 1111 "Got unexpected logclust2[%u] %#x, expected %#x.\n", 1112 x, logclust2[x], logclust[compare_idx]); 1113 winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, 1114 "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", 1115 x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); 1116 } 1117 } 1118 winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); 1119 for (x = 0; x < outnGlyphs2; ++x) 1120 { 1121 unsigned int compare_idx = outpItems[item].a.fRTL ? outnGlyphs2 - x - 1 : x; 1122 winetest_ok(glyphs2[x] == glyphs[compare_idx], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", 1123 x, glyphs2[x], glyphs[compare_idx]); 1124 winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[compare_idx].sva.uJustification, 1125 "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", 1126 x, glyphProp2[x].sva.uJustification, glyphProp[compare_idx].sva.uJustification); 1127 winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[compare_idx].sva.fClusterStart, 1128 "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", 1129 x, glyphProp2[x].sva.fClusterStart, glyphProp[compare_idx].sva.fClusterStart); 1130 winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[compare_idx].sva.fDiacritic, 1131 "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", 1132 x, glyphProp2[x].sva.fDiacritic, glyphProp[compare_idx].sva.fDiacritic); 1133 winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[compare_idx].sva.fZeroWidth, 1134 "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", 1135 x, glyphProp2[x].sva.fZeroWidth, glyphProp[compare_idx].sva.fZeroWidth); 1136 } 1137 1138 /* Most scripts get this wrong. For example, when the font has the 1139 * appropriate ligatures, "ttfffi" get rendered as "<ttf><ffi>", but 1140 * "<RLO>iffftt" gets rendered as "t<ft><ff>i". Arabic gets it right, 1141 * and there exist applications that depend on that. */ 1142 if (tags[item] == arab_tag && broken(script_count <= 75)) 1143 { 1144 winetest_win_skip("Test broken on this platform, skipping.\n"); 1145 } 1146 else if (tags[item] == arab_tag) 1147 { 1148 for (x = 0; x < cchString; ++x) 1149 { 1150 string2[x] = string[cchString - x - 1]; 1151 } 1152 outpItems[item].a.fLogicalOrder = 0; 1153 outpItems[item].a.fRTL = !outpItems[item].a.fRTL; 1154 hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, 1155 string2, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); 1156 winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); 1157 for (x = 0; x < cchString; ++x) 1158 { 1159 unsigned int compare_idx = cchString - x - 1; 1160 winetest_ok(logclust2[x] == logclust[compare_idx], 1161 "Got unexpected logclust2[%u] %#x, expected %#x.\n", 1162 x, logclust2[x], logclust[compare_idx]); 1163 winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, 1164 "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", 1165 x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); 1166 } 1167 winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); 1168 for (x = 0; x < outnGlyphs2; ++x) 1169 { 1170 winetest_ok(glyphs2[x] == glyphs[x], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", 1171 x, glyphs2[x], glyphs[x]); 1172 winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[x].sva.uJustification, 1173 "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", 1174 x, glyphProp2[x].sva.uJustification, glyphProp[x].sva.uJustification); 1175 winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[x].sva.fClusterStart, 1176 "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", 1177 x, glyphProp2[x].sva.fClusterStart, glyphProp[x].sva.fClusterStart); 1178 winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[x].sva.fDiacritic, 1179 "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", 1180 x, glyphProp2[x].sva.fDiacritic, glyphProp[x].sva.fDiacritic); 1181 winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[x].sva.fZeroWidth, 1182 "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", 1183 x, glyphProp2[x].sva.fZeroWidth, glyphProp[x].sva.fZeroWidth); 1184 } 1185 outpItems[item].a.fLogicalOrder = 1; 1186 hr = pScriptShapeOpenType(hdc, &sc, &outpItems[item].a, tags[item], 0x00000000, NULL, NULL, 0, 1187 string2, cchString, maxGlyphs, logclust2, charProp2, glyphs2, glyphProp2, &outnGlyphs2); 1188 winetest_ok(hr == S_OK, "ScriptShapeOpenType failed (%x)\n",hr); 1189 for (x = 0; x < cchString; ++x) 1190 { 1191 unsigned int compare_idx = outpItems[item].a.fRTL ? x : cchString - x - 1; 1192 winetest_ok(logclust2[x] == logclust[compare_idx], "Got unexpected logclust2[%u] %#x, expected %#x.\n", 1193 x, logclust2[x], logclust[compare_idx]); 1194 winetest_ok(charProp2[x].fCanGlyphAlone == charProp[compare_idx].fCanGlyphAlone, 1195 "Got unexpected charProp2[%u].fCanGlyphAlone %#x, expected %#x.\n", 1196 x, charProp2[x].fCanGlyphAlone, charProp[compare_idx].fCanGlyphAlone); 1197 } 1198 winetest_ok(outnGlyphs2 == outnGlyphs, "Got unexpected glyph count %u.\n", outnGlyphs2); 1199 for (x = 0; x < outnGlyphs2; ++x) 1200 { 1201 unsigned int compare_idx = outpItems[item].a.fRTL ? outnGlyphs2 - x - 1 : x; 1202 winetest_ok(glyphs2[x] == glyphs[compare_idx], "Got unexpected glyphs2[%u] %#x, expected %#x.\n", 1203 x, glyphs2[x], glyphs[compare_idx]); 1204 winetest_ok(glyphProp2[x].sva.uJustification == glyphProp[compare_idx].sva.uJustification, 1205 "Got unexpected glyphProp2[%u].sva.uJustification %#x, expected %#x.\n", 1206 x, glyphProp2[x].sva.uJustification, glyphProp[compare_idx].sva.uJustification); 1207 winetest_ok(glyphProp2[x].sva.fClusterStart == glyphProp[compare_idx].sva.fClusterStart, 1208 "Got unexpected glyphProp2[%u].sva.fClusterStart %#x, expected %#x.\n", 1209 x, glyphProp2[x].sva.fClusterStart, glyphProp[compare_idx].sva.fClusterStart); 1210 winetest_ok(glyphProp2[x].sva.fDiacritic == glyphProp[compare_idx].sva.fDiacritic, 1211 "Got unexpected glyphProp2[%u].sva.fDiacritic %#x, expected %#x.\n", 1212 x, glyphProp2[x].sva.fDiacritic, glyphProp[compare_idx].sva.fDiacritic); 1213 winetest_ok(glyphProp2[x].sva.fZeroWidth == glyphProp[compare_idx].sva.fZeroWidth, 1214 "Got unexpected glyphProp2[%u].sva.fZeroWidth %#x, expected %#x.\n", 1215 x, glyphProp2[x].sva.fZeroWidth, glyphProp[compare_idx].sva.fZeroWidth); 1216 } 1217 } 1218 1219 cleanup: 1220 HeapFree(GetProcessHeap(),0,string2); 1221 HeapFree(GetProcessHeap(),0,logclust2); 1222 HeapFree(GetProcessHeap(),0,charProp2); 1223 HeapFree(GetProcessHeap(),0,glyphs2); 1224 HeapFree(GetProcessHeap(),0,glyphProp2); 1225 1226 HeapFree(GetProcessHeap(),0,logclust); 1227 HeapFree(GetProcessHeap(),0,charProp); 1228 HeapFree(GetProcessHeap(),0,glyphs); 1229 HeapFree(GetProcessHeap(),0,glyphProp); 1230 ScriptFreeCache(&sc); 1231 } 1232 1233 #define test_shape_ok(a,b,c,d,e,f,g,h,i) \ 1234 (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_shape_ok(1,a,b,c,d,e,f,g,h,i,NULL) 1235 1236 #define test_shape_ok_valid(v,a,b,c,d,e,f,g,h,i) \ 1237 (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_shape_ok(v,a,b,c,d,e,f,g,h,i,NULL) 1238 1239 #define test_shape_ok_valid_props2(v,a,b,c,d,e,f,g,h,i,j) \ 1240 (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_shape_ok(v,a,b,c,d,e,f,g,h,i,j) 1241 1242 typedef struct tagRangeP { 1243 BYTE range; 1244 LOGFONTA lf; 1245 } fontEnumParam; 1246 1247 static int CALLBACK enumFontProc( const LOGFONTA *lpelfe, const TEXTMETRICA *lpntme, DWORD FontType, LPARAM lParam ) 1248 { 1249 NEWTEXTMETRICEXA *ntme = (NEWTEXTMETRICEXA*)lpntme; 1250 fontEnumParam *rp = (fontEnumParam*) lParam; 1251 int idx = 0; 1252 DWORD i; 1253 DWORD mask = 0; 1254 1255 if (FontType != TRUETYPE_FONTTYPE) 1256 return 1; 1257 1258 i = rp->range; 1259 while (i >= sizeof(DWORD)*8) 1260 { 1261 idx++; 1262 i -= (sizeof(DWORD)*8); 1263 } 1264 if (idx > 3) 1265 return 0; 1266 1267 mask = 1 << i; 1268 1269 if (ntme->ntmFontSig.fsUsb[idx] & mask) 1270 { 1271 memcpy(&(rp->lf),lpelfe,sizeof(LOGFONTA)); 1272 return 0; 1273 } 1274 return 1; 1275 } 1276 1277 static int _find_font_for_range(HDC hdc, const CHAR *recommended, BYTE range, const WCHAR check, HFONT *hfont, HFONT *origFont, const font_fingerprint *fingerprint) 1278 { 1279 int rc = 0; 1280 fontEnumParam lParam; 1281 1282 lParam.range = range; 1283 memset(&lParam.lf,0,sizeof(LOGFONTA)); 1284 *hfont = NULL; 1285 1286 if (recommended) 1287 { 1288 lstrcpyA(lParam.lf.lfFaceName, recommended); 1289 if (!EnumFontFamiliesExA(hdc, &lParam.lf, enumFontProc, (LPARAM)&lParam, 0)) 1290 { 1291 *hfont = CreateFontIndirectA(&lParam.lf); 1292 if (*hfont) 1293 { 1294 winetest_trace("using font %s\n",lParam.lf.lfFaceName); 1295 *origFont = SelectObject(hdc,*hfont); 1296 if (fingerprint) 1297 { 1298 WORD output[10]; 1299 int i; 1300 if (GetGlyphIndicesW(hdc, fingerprint->check, 10, output, 0) != GDI_ERROR) 1301 { 1302 for (i=0; i < 10; i++) 1303 if (output[i] != fingerprint->result[i]) 1304 { 1305 winetest_trace("found font does not match fingerprint\n"); 1306 SelectObject(hdc,*origFont); 1307 DeleteObject(*hfont); 1308 *hfont = NULL; 1309 break; 1310 } 1311 if (i == 10) rc = 1; 1312 } 1313 } 1314 else rc = 1; 1315 } 1316 } 1317 if (!rc) 1318 winetest_skip("Font %s is not available.\n", recommended); 1319 } 1320 1321 if (!*hfont) 1322 { 1323 memset(&lParam.lf,0,sizeof(LOGFONTA)); 1324 lParam.lf.lfCharSet = DEFAULT_CHARSET; 1325 1326 if (!EnumFontFamiliesExA(hdc, &lParam.lf, enumFontProc, (LPARAM)&lParam, 0) && lParam.lf.lfFaceName[0]) 1327 { 1328 *hfont = CreateFontIndirectA(&lParam.lf); 1329 if (*hfont) 1330 winetest_trace("trying font %s: failures will only be warnings\n",lParam.lf.lfFaceName); 1331 } 1332 } 1333 1334 if (*hfont) 1335 { 1336 WORD glyph = 0; 1337 1338 *origFont = SelectObject(hdc,*hfont); 1339 if (GetGlyphIndicesW(hdc, &check, 1, &glyph, 0) == GDI_ERROR || glyph == 0) 1340 { 1341 winetest_trace(" Font fails to contain required glyphs\n"); 1342 SelectObject(hdc,*origFont); 1343 DeleteObject(*hfont); 1344 *hfont=NULL; 1345 rc = 0; 1346 } 1347 else if (!rc) 1348 rc = -1; 1349 } 1350 else 1351 winetest_trace("Failed to find usable font\n"); 1352 1353 return rc; 1354 } 1355 1356 #define find_font_for_range(a,b,c,d,e,f,g) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _find_font_for_range(a,b,c,d,e,f,g) 1357 1358 static void test_ScriptShapeOpenType(HDC hdc) 1359 { 1360 HRESULT hr; 1361 SCRIPT_CACHE sc = NULL; 1362 WORD glyphs[4], logclust[4]; 1363 SCRIPT_GLYPHPROP glyphProp[4]; 1364 SCRIPT_ITEM items[2]; 1365 ULONG tags[2]; 1366 SCRIPT_CONTROL Control; 1367 SCRIPT_STATE State; 1368 int nb, outnItems; 1369 HFONT hfont, hfont_orig; 1370 int test_valid; 1371 shapeTest_glyph glyph_test[4]; 1372 1373 static const WCHAR test1[] = {'w', 'i', 'n', 'e',0}; 1374 static const shapeTest_char t1_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{0,0}}}; 1375 static const shapeTest_glyph t1_g[] = { 1376 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1377 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1378 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1379 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}} }; 1380 1381 static const WCHAR test2[] = {0x202B, 'i', 'n', 0x202C,0}; 1382 static const shapeTest_char t2_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{0,0}}}; 1383 static const shapeTest_glyph t2_g[] = { 1384 {0,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1385 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1386 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1387 {0,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}} }; 1388 1389 static const WCHAR test3[] = {'t', 't', 'f', 'f', 'f', 'i', 0}; 1390 static const shapeTest_char t3_c[] = {{0, {0, 0}}, {0, {0, 0}}, {0, {0, 0}}, 1391 {1, {0, 0}}, {1, {0, 0}}, {1, {0, 0}}}; 1392 static const shapeTest_glyph t3_g[] = { 1393 {1, {{SCRIPT_JUSTIFY_CHARACTER, 1, 0, 0, 0, 0}, 0}}, 1394 {1, {{SCRIPT_JUSTIFY_CHARACTER, 1, 0, 0, 0, 0}, 0}}}; 1395 1396 /* Hebrew */ 1397 static const WCHAR test_hebrew[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd,0}; 1398 static const shapeTest_char hebrew_c[] = {{3,{0,0}},{2,{0,0}},{1,{0,0}},{0,{0,0}}}; 1399 static const shapeTest_glyph hebrew_g[] = { 1400 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1401 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1402 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1403 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}} }; 1404 1405 /* Arabic */ 1406 static const WCHAR test_arabic[] = {0x0633,0x0644,0x0627,0x0645,0}; 1407 static const shapeTest_char arabic_c[] = {{2,{0,0}},{1,{0,0}},{1,{0,0}},{0,{0,0}}}; 1408 static const shapeTest_glyph arabic_g[] = { 1409 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1410 {1,{{SCRIPT_JUSTIFY_ARABIC_NORMAL,1,0,0,0,0},0}}, 1411 {1,{{SCRIPT_JUSTIFY_ARABIC_SEEN,1,0,0,0,0},0}} }; 1412 1413 /* Thai */ 1414 static const WCHAR test_thai[] = {0x0e2a, 0x0e04, 0x0e23, 0x0e34, 0x0e1b, 0x0e15, 0x0e4c, 0x0e44, 0x0e17, 0x0e22,}; 1415 static const shapeTest_char thai_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{2,{0,0}},{4,{0,0}},{5,{0,0}},{5,{0,0}},{7,{0,0}},{8,{0,0}},{9,{0,0}}}; 1416 static const shapeTest_glyph thai_g[] = { 1417 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1418 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1419 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1420 {1,{{SCRIPT_JUSTIFY_CHARACTER,0,1,1,0,0},0}}, 1421 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1422 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1423 {1,{{SCRIPT_JUSTIFY_CHARACTER,0,1,1,0,0},0}}, 1424 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1425 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1426 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}}; 1427 1428 /* Syriac */ 1429 static const WCHAR test_syriac[] = {0x0710, 0x072c, 0x0728, 0x0742, 0x0718, 0x0723, 0x0720, 0x0710, 0}; 1430 static const shapeTest_char syriac_c[] = {{6, {0, 0}}, {5, {0, 0}}, {4, {0, 0}}, 1431 {4, {0, 0}}, {2, {0, 0}}, {1, {0, 0}}, {0, {0, 0}}, {0, {0, 0}}}; 1432 static const shapeTest_glyph syriac_g[] = { 1433 {1,{{SCRIPT_JUSTIFY_ARABIC_NORMAL,1,0,0,0,0},0}}, 1434 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1435 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1436 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1437 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1438 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1439 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1440 1441 /* Thaana */ 1442 static const WCHAR test_thaana[] = {0x078a, 0x07ae, 0x0792, 0x07b0, 0x0020, 0x0796, 0x07aa, 0x0789, 0x07b0, 0x0795, 0x07ac, 0x0791, 0x07b0}; 1443 static const shapeTest_char thaana_c[] = {{12,{0,0}},{12,{0,0}},{10,{0,0}},{10,{0,0}},{8,{1,0}},{7,{0,0}},{7,{0,0}},{5,{0,0}},{5,{0,0}},{3,{0,0}},{3,{0,0}},{1,{0,0}},{1,{0,0}}}; 1444 static const shapeTest_glyph thaana_g[] = { 1445 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1446 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1447 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1448 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1449 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1450 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1451 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1452 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1453 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1454 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1455 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1456 {1,{{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}}, 1457 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1458 1459 /* Phags-pa */ 1460 static const WCHAR test_phagspa[] = {0xa84f, 0xa861, 0xa843, 0x0020, 0xa863, 0xa861, 0xa859, 0x0020, 0xa850, 0xa85c, 0xa85e}; 1461 static const shapeTest_char phagspa_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{1,0}},{4,{0,0}},{5,{0,0}},{6,{0,0}},{7,{1,0}},{8,{0,0}},{9,{0,0}},{10,{0,0}}}; 1462 static const shapeTest_glyph phagspa_g[] = { 1463 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1464 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1465 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1466 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1467 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1468 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1469 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1470 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1471 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1472 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1473 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1474 static const SCRIPT_GLYPHPROP phagspa_win10_props[] = { 1475 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1476 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1477 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1478 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1479 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1480 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1481 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1482 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1483 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1484 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1485 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0} }; 1486 1487 /* Lao */ 1488 static const WCHAR test_lao[] = {0x0ead, 0x0eb1, 0x0e81, 0x0eaa, 0x0ead, 0x0e99, 0x0ea5, 0x0eb2, 0x0ea7, 0}; 1489 static const shapeTest_char lao_c[] = {{0,{0,0}},{0,{0,0}},{2,{0,0}},{3,{0,0}},{4,{0,0}},{5,{0,0}},{6,{0,0}},{7,{0,0}},{8,{0,0}}}; 1490 static const shapeTest_glyph lao_g[] = { 1491 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1492 {1,{{SCRIPT_JUSTIFY_CHARACTER,0,1,1,0,0},0}}, 1493 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1494 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1495 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1496 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1497 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1498 {1,{{SCRIPT_JUSTIFY_CHARACTER,1,0,0,0,0},0}}, 1499 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1500 1501 /* Tibetan */ 1502 static const WCHAR test_tibetan[] = {0x0f04, 0x0f05, 0x0f0e, 0x0020, 0x0f51, 0x0f7c, 0x0f53, 0x0f0b, 0x0f5a, 0x0f53, 0x0f0b, 0x0f51, 0x0f44, 0x0f0b, 0x0f54, 0x0f7c, 0x0f0d}; 1503 static const shapeTest_char tibetan_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{1,0}},{4,{0,0}},{4,{0,0}},{6,{0,0}},{7,{0,0}},{8,{0,0}},{9,{0,0}},{10,{0,0}},{11,{0,0}},{12,{0,0}},{13,{0,0}},{14,{0,0}},{14,{0,0}},{16,{0,0}}}; 1504 static const shapeTest_glyph tibetan_g[] = { 1505 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1506 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1507 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1508 {1,{{SCRIPT_JUSTIFY_BLANK,1,0,0,0,0},0}}, 1509 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1510 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1511 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1512 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1513 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1514 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1515 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1516 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1517 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1518 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1519 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1520 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1521 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1522 static const SCRIPT_GLYPHPROP tibetan_win10_props[] = { 1523 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1524 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1525 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1526 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1527 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1528 {{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}, 1529 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1530 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1531 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1532 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1533 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1534 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1535 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1536 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1537 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}, 1538 {{SCRIPT_JUSTIFY_NONE,0,1,1,0,0},0}, 1539 {{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0} }; 1540 1541 /* Devanagari */ 1542 static const WCHAR test_devanagari[] = {0x0926, 0x0947, 0x0935, 0x0928, 0x093e, 0x0917, 0x0930, 0x0940}; 1543 static const shapeTest_char devanagari_c[] = {{0,{0,0}},{0,{0,0}},{2,{0,0}},{3,{0,0}},{3,{0,0}},{5,{0,0}},{6,{0,0}},{6,{0,0}}}; 1544 static const shapeTest_glyph devanagari_g[] = { 1545 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1546 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1547 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1548 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1549 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1550 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1551 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1552 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1553 1554 /* Bengali */ 1555 static const WCHAR test_bengali[] = {0x09ac, 0x09be, 0x0982, 0x09b2, 0x09be}; 1556 static const shapeTest_char bengali_c[] = {{0,{0,0}},{0,{0,0}},{0,{0,0}},{3,{0,0}},{3,{0,0}}}; 1557 static const shapeTest_glyph bengali_g[] = { 1558 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1559 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1560 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1561 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1562 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1563 1564 /* Gurmukhi */ 1565 static const WCHAR test_gurmukhi[] = {0x0a17, 0x0a41, 0x0a30, 0x0a2e, 0x0a41, 0x0a16, 0x0a40}; 1566 static const shapeTest_char gurmukhi_c[] = {{0,{0,0}},{0,{0,0}},{2,{0,0}},{3,{0,0}},{3,{0,0}},{5,{0,0}},{5,{0,0}}}; 1567 static const shapeTest_glyph gurmukhi_g[] = { 1568 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1569 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1570 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1571 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1572 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1573 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1574 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1575 1576 /* Gujarati */ 1577 static const WCHAR test_gujarati[] = {0x0a97, 0x0ac1, 0x0a9c, 0x0ab0, 0x0abe, 0x0aa4, 0x0ac0}; 1578 static const shapeTest_char gujarati_c[] = {{0,{0,0}},{0,{0,0}},{2,{0,0}},{3,{0,0}},{3,{0,0}},{5,{0,0}},{5,{0,0}}}; 1579 static const shapeTest_glyph gujarati_g[] = { 1580 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1581 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1582 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1583 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1584 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1585 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1586 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1587 1588 /* Oriya */ 1589 static const WCHAR test_oriya[] = {0x0b13, 0x0b21, 0x0b3c, 0x0b3f, 0x0b06}; 1590 static const shapeTest_char oriya_c[] = {{0,{0,0}},{1,{0,0}},{1,{0,0}},{1,{0,0}},{3,{0,0}}}; 1591 static const shapeTest_glyph oriya_g[] = { 1592 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1593 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1594 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1595 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1596 1597 /* Tamil */ 1598 static const WCHAR test_tamil[] = {0x0ba4, 0x0bae, 0x0bbf, 0x0bb4, 0x0bcd}; 1599 static const shapeTest_char tamil_c[] = {{0,{0,0}},{1,{0,0}},{1,{0,0}},{3,{0,0}},{3,{0,0}}}; 1600 static const shapeTest_glyph tamil_g[] = { 1601 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1602 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1603 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1604 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}} }; 1605 1606 /* Telugu */ 1607 static const WCHAR test_telugu[] = {0x0c24, 0x0c46, 0x0c32, 0x0c41, 0x0c17, 0x0c41}; 1608 static const shapeTest_char telugu_c[] = {{0,{0,0}},{0,{0,0}},{2,{0,0}},{2,{0,0}},{4,{0,0}},{4,{0,0}}}; 1609 static const shapeTest_glyph telugu_g[] = { 1610 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1611 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1612 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1613 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1614 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1615 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1616 1617 /* Malayalam */ 1618 static const WCHAR test_malayalam[] = {0x0d2e, 0x0d32, 0x0d2f, 0x0d3e, 0x0d33, 0x0d02}; 1619 static const shapeTest_char malayalam_c[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{2,{0,0}},{4,{0,0}},{4,{0,0}}}; 1620 static const shapeTest_glyph malayalam_g[] = { 1621 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1622 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1623 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1624 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1625 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1626 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1627 1628 /* Kannada */ 1629 static const WCHAR test_kannada[] = {0x0c95, 0x0ca8, 0x0ccd, 0x0ca8, 0x0ca1}; 1630 static const shapeTest_char kannada_c[] = {{0,{0,0}},{1,{0,0}},{1,{0,0}},{1,{0,0}},{3,{0,0}}}; 1631 static const shapeTest_glyph kannada_g[] = { 1632 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1633 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1634 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}}, 1635 {1,{{SCRIPT_JUSTIFY_NONE,1,0,0,0,0},0}}, 1636 {1,{{SCRIPT_JUSTIFY_NONE,0,0,0,0,0},0}} }; 1637 1638 static const font_fingerprint fingerprint_estrangelo = { 1639 {'A','a','B','b','C','c','D','d',0,0}, 1640 {284,310,285,311,286,312,287,313,0,0}}; 1641 1642 1643 if (!pScriptItemizeOpenType || !pScriptShapeOpenType) 1644 { 1645 win_skip("ScriptShapeOpenType not available on this platform\n"); 1646 return; 1647 } 1648 1649 memset(&Control, 0 , sizeof(Control)); 1650 memset(&State, 0 , sizeof(State)); 1651 1652 hr = pScriptItemizeOpenType(test1, 4, 2, &Control, &State, items, tags, &outnItems); 1653 ok(hr == S_OK, "ScriptItemizeOpenType should return S_OK not %08x\n", hr); 1654 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1655 1656 hr = pScriptShapeOpenType(hdc, &sc, &items[0].a, tags[0], 0x00000000, NULL, NULL, 0, test1, 4, 4, NULL, NULL, glyphs, NULL, &nb); 1657 ok(hr == E_INVALIDARG, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr); 1658 1659 hr = pScriptShapeOpenType(hdc, &sc, &items[0].a, tags[0], 0x00000000, NULL, NULL, 0, test1, 4, 4, NULL, NULL, glyphs, glyphProp, NULL); 1660 ok(hr == E_INVALIDARG, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr); 1661 1662 hr = pScriptShapeOpenType(NULL, &sc, &items[0].a, tags[0], 0x00000000, NULL, NULL, 0, test1, 4, 4, NULL, NULL, glyphs, glyphProp, &nb); 1663 ok(hr == E_INVALIDARG, "ScriptShapeOpenType should return E_PENDING not %08x\n", hr); 1664 1665 hr = pScriptShapeOpenType(hdc, &sc, &items[0].a, tags[0], 0x00000000, NULL, NULL, 0, test1, 4, 4, NULL, NULL, glyphs, glyphProp, &nb); 1666 ok( hr == E_INVALIDARG, 1667 "ScriptShapeOpenType should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 1668 hr = pScriptShapeOpenType(hdc, &sc, &items[0].a, tags[0], 0x00000000, NULL, NULL, 0, test1, 4, 4, logclust, NULL, glyphs, glyphProp, &nb); 1669 ok(hr == E_INVALIDARG, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr); 1670 1671 ScriptFreeCache(&sc); 1672 1673 test_shape_ok(hdc, test1, 4, &Control, &State, 0, 4, t1_c, t1_g); 1674 1675 /* newer Tahoma has zerowidth space glyphs for 0x202b and 0x202c */ 1676 memcpy(glyph_test, t2_g, sizeof(glyph_test)); 1677 GetGlyphIndicesW(hdc, test2, 4, glyphs, 0); 1678 if (glyphs[0] != 0) 1679 glyph_test[0].Glyph = 1; 1680 if (glyphs[3] != 0) 1681 glyph_test[3].Glyph = 1; 1682 1683 test_shape_ok(hdc, test2, 4, &Control, &State, 1, 4, t2_c, glyph_test); 1684 1685 test_valid = find_font_for_range(hdc, "Calibri", 0, test3[0], &hfont, &hfont_orig, NULL); 1686 if (hfont != NULL) 1687 { 1688 test_shape_ok_valid(test_valid, hdc, test3, 6, &Control, &State, 0, 2, t3_c, t3_g); 1689 SelectObject(hdc, hfont_orig); 1690 DeleteObject(hfont); 1691 } 1692 1693 test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 11, test_hebrew[0], &hfont, &hfont_orig, NULL); 1694 if (hfont != NULL) 1695 { 1696 test_shape_ok_valid(test_valid, hdc, test_hebrew, 4, &Control, &State, 0, 4, hebrew_c, hebrew_g); 1697 SelectObject(hdc, hfont_orig); 1698 DeleteObject(hfont); 1699 } 1700 1701 test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 13, test_arabic[0], &hfont, &hfont_orig, NULL); 1702 if (hfont != NULL) 1703 { 1704 test_shape_ok_valid(test_valid, hdc, test_arabic, 4, &Control, &State, 0, 3, arabic_c, arabic_g); 1705 SelectObject(hdc, hfont_orig); 1706 DeleteObject(hfont); 1707 } 1708 1709 test_valid = find_font_for_range(hdc, "Microsoft Sans Serif", 24, test_thai[0], &hfont, &hfont_orig, NULL); 1710 if (hfont != NULL) 1711 { 1712 test_shape_ok_valid(test_valid, hdc, test_thai, 10, &Control, &State, 0, 10, thai_c, thai_g); 1713 SelectObject(hdc, hfont_orig); 1714 DeleteObject(hfont); 1715 } 1716 1717 test_valid = find_font_for_range(hdc, "Estrangelo Edessa", 71, test_syriac[0], &hfont, &hfont_orig, &fingerprint_estrangelo); 1718 if (hfont != NULL) 1719 { 1720 test_shape_ok_valid(test_valid, hdc, test_syriac, 8, &Control, &State, 0, 7, syriac_c, syriac_g); 1721 SelectObject(hdc, hfont_orig); 1722 DeleteObject(hfont); 1723 } 1724 1725 test_valid = find_font_for_range(hdc, "MV Boli", 72, test_thaana[0], &hfont, &hfont_orig, NULL); 1726 if (hfont != NULL) 1727 { 1728 test_shape_ok_valid(test_valid, hdc, test_thaana, 13, &Control, &State, 0, 13, thaana_c, thaana_g); 1729 SelectObject(hdc, hfont_orig); 1730 DeleteObject(hfont); 1731 } 1732 1733 test_valid = find_font_for_range(hdc, "Microsoft PhagsPa", 53, test_phagspa[0], &hfont, &hfont_orig, NULL); 1734 if (hfont != NULL) 1735 { 1736 test_shape_ok_valid_props2(test_valid, hdc, test_phagspa, 11, &Control, &State, 0, 11, 1737 phagspa_c, phagspa_g, phagspa_win10_props); 1738 SelectObject(hdc, hfont_orig); 1739 DeleteObject(hfont); 1740 } 1741 1742 test_valid = find_font_for_range(hdc, "DokChampa", 25, test_lao[0], &hfont, &hfont_orig, NULL); 1743 if (hfont != NULL) 1744 { 1745 test_shape_ok_valid(test_valid, hdc, test_lao, 9, &Control, &State, 0, 9, lao_c, lao_g); 1746 SelectObject(hdc, hfont_orig); 1747 DeleteObject(hfont); 1748 } 1749 1750 test_valid = find_font_for_range(hdc, "Microsoft Himalaya", 70, test_tibetan[0], &hfont, &hfont_orig, NULL); 1751 if (hfont != NULL) 1752 { 1753 test_shape_ok_valid_props2(test_valid, hdc, test_tibetan, 17, &Control, &State, 0, 17, 1754 tibetan_c, tibetan_g, tibetan_win10_props); 1755 SelectObject(hdc, hfont_orig); 1756 DeleteObject(hfont); 1757 } 1758 1759 test_valid = find_font_for_range(hdc, "Mangal", 15, test_devanagari[0], &hfont, &hfont_orig, NULL); 1760 if (hfont != NULL) 1761 { 1762 test_shape_ok_valid(test_valid, hdc, test_devanagari, 8, &Control, &State, 0, 8, devanagari_c, devanagari_g); 1763 SelectObject(hdc, hfont_orig); 1764 DeleteObject(hfont); 1765 } 1766 1767 test_valid = find_font_for_range(hdc, "Vrinda", 16, test_bengali[0], &hfont, &hfont_orig, NULL); 1768 if (hfont != NULL) 1769 { 1770 test_shape_ok_valid(test_valid, hdc, test_bengali, 5, &Control, &State, 0, 5, bengali_c, bengali_g); 1771 SelectObject(hdc, hfont_orig); 1772 DeleteObject(hfont); 1773 } 1774 1775 test_valid = find_font_for_range(hdc, "Raavi", 17, test_gurmukhi[0], &hfont, &hfont_orig, NULL); 1776 if (hfont != NULL) 1777 { 1778 test_shape_ok_valid(test_valid, hdc, test_gurmukhi, 7, &Control, &State, 0, 7, gurmukhi_c, gurmukhi_g); 1779 SelectObject(hdc, hfont_orig); 1780 DeleteObject(hfont); 1781 } 1782 1783 test_valid = find_font_for_range(hdc, "Shruti", 18, test_gujarati[0], &hfont, &hfont_orig, NULL); 1784 if (hfont != NULL) 1785 { 1786 test_shape_ok_valid(test_valid, hdc, test_gujarati, 7, &Control, &State, 0, 7, gujarati_c, gujarati_g); 1787 SelectObject(hdc, hfont_orig); 1788 DeleteObject(hfont); 1789 } 1790 1791 test_valid = find_font_for_range(hdc, "Kalinga", 19, test_oriya[0], &hfont, &hfont_orig, NULL); 1792 if (hfont != NULL) 1793 { 1794 test_shape_ok_valid(test_valid, hdc, test_oriya, 5, &Control, &State, 0, 4, oriya_c, oriya_g); 1795 SelectObject(hdc, hfont_orig); 1796 DeleteObject(hfont); 1797 } 1798 1799 test_valid = find_font_for_range(hdc, "Latha", 20, test_tamil[0], &hfont, &hfont_orig, NULL); 1800 if (hfont != NULL) 1801 { 1802 test_shape_ok_valid(test_valid, hdc, test_tamil, 5, &Control, &State, 0, 4, tamil_c, tamil_g); 1803 SelectObject(hdc, hfont_orig); 1804 DeleteObject(hfont); 1805 } 1806 1807 test_valid = find_font_for_range(hdc, "Gautami", 21, test_telugu[0], &hfont, &hfont_orig, NULL); 1808 if (hfont != NULL) 1809 { 1810 test_shape_ok_valid(test_valid, hdc, test_telugu, 6, &Control, &State, 0, 6, telugu_c, telugu_g); 1811 SelectObject(hdc, hfont_orig); 1812 DeleteObject(hfont); 1813 } 1814 1815 test_valid = find_font_for_range(hdc, "Kartika", 23, test_malayalam[0], &hfont, &hfont_orig, NULL); 1816 if (hfont != NULL) 1817 { 1818 test_shape_ok_valid(test_valid, hdc, test_malayalam, 6, &Control, &State, 0, 6, malayalam_c, malayalam_g); 1819 SelectObject(hdc, hfont_orig); 1820 DeleteObject(hfont); 1821 } 1822 1823 test_valid = find_font_for_range(hdc, "Tunga", 22, test_kannada[0], &hfont, &hfont_orig, NULL); 1824 if (hfont != NULL) 1825 { 1826 test_shape_ok_valid(test_valid, hdc, test_kannada, 5, &Control, &State, 0, 4, kannada_c, kannada_g); 1827 SelectObject(hdc, hfont_orig); 1828 DeleteObject(hfont); 1829 } 1830 } 1831 1832 static void test_ScriptShape(HDC hdc) 1833 { 1834 static const WCHAR test1[] = {'w', 'i', 'n', 'e',0}; 1835 static const WCHAR test2[] = {0x202B, 'i', 'n', 0x202C,0}; 1836 static const WCHAR test3[] = {0x30b7}; 1837 HRESULT hr; 1838 SCRIPT_CACHE sc = NULL; 1839 SCRIPT_CACHE sc2 = NULL; 1840 WORD glyphs[4], glyphs2[4], logclust[4], glyphs3[4]; 1841 SCRIPT_VISATTR attrs[4]; 1842 SCRIPT_ITEM items[4]; 1843 int nb, i, j; 1844 1845 hr = ScriptItemize(test1, 4, 2, NULL, NULL, items, NULL); 1846 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 1847 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1848 1849 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, NULL, &nb); 1850 ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr); 1851 1852 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, NULL); 1853 ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr); 1854 1855 hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb); 1856 ok(hr == E_PENDING, "ScriptShape should return E_PENDING not %08x\n", hr); 1857 1858 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb); 1859 ok(broken(hr == S_OK) || 1860 hr == E_INVALIDARG || /* Vista, W2K8 */ 1861 hr == E_FAIL, /* WIN7 */ 1862 "ScriptShape should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 1863 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1864 1865 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 1866 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1867 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1868 1869 hr = ScriptShape(hdc, &sc2, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 1870 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1871 ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2); 1872 ScriptFreeCache(&sc2); 1873 1874 memset(glyphs,-1,sizeof(glyphs)); 1875 memset(logclust,-1,sizeof(logclust)); 1876 memset(attrs,-1,sizeof(attrs)); 1877 hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 1878 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1879 ok(nb == 4, "Wrong number of items\n"); 1880 ok(logclust[0] == 0, "clusters out of order\n"); 1881 ok(logclust[1] == 1, "clusters out of order\n"); 1882 ok(logclust[2] == 2, "clusters out of order\n"); 1883 ok(logclust[3] == 3, "clusters out of order\n"); 1884 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1885 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1886 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1887 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1888 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1889 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1890 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1891 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1892 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1893 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1894 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1895 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1896 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1897 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1898 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1899 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1900 1901 ScriptFreeCache(&sc); 1902 sc = NULL; 1903 1904 memset(glyphs2,-1,sizeof(glyphs2)); 1905 memset(glyphs3,-1,sizeof(glyphs3)); 1906 memset(logclust,-1,sizeof(logclust)); 1907 memset(attrs,-1,sizeof(attrs)); 1908 1909 GetGlyphIndicesW(hdc, test2, 4, glyphs3, 0); 1910 1911 hr = ScriptShape(hdc, &sc, test2, 4, 4, &items[0].a, glyphs2, logclust, attrs, &nb); 1912 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1913 ok(nb == 4, "Wrong number of items\n"); 1914 ok(glyphs2[0] == glyphs3[0], "Incorrect glyph for 0x202B\n"); 1915 ok(glyphs2[3] == glyphs3[3], "Incorrect glyph for 0x202C\n"); 1916 ok(logclust[0] == 0, "clusters out of order\n"); 1917 ok(logclust[1] == 1, "clusters out of order\n"); 1918 ok(logclust[2] == 2, "clusters out of order\n"); 1919 ok(logclust[3] == 3, "clusters out of order\n"); 1920 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1921 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1922 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1923 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1924 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1925 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1926 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1927 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1928 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1929 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1930 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1931 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1932 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1933 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1934 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1935 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1936 1937 /* modify LTR to RTL */ 1938 items[0].a.fRTL = 1; 1939 memset(glyphs2,-1,sizeof(glyphs2)); 1940 memset(logclust,-1,sizeof(logclust)); 1941 memset(attrs,-1,sizeof(attrs)); 1942 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs2, logclust, attrs, &nb); 1943 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1944 ok(nb == 4, "Wrong number of items\n"); 1945 ok(glyphs2[0] == glyphs[3], "Glyphs not reordered properly\n"); 1946 ok(glyphs2[1] == glyphs[2], "Glyphs not reordered properly\n"); 1947 ok(glyphs2[2] == glyphs[1], "Glyphs not reordered properly\n"); 1948 ok(glyphs2[3] == glyphs[0], "Glyphs not reordered properly\n"); 1949 ok(logclust[0] == 3, "clusters out of order\n"); 1950 ok(logclust[1] == 2, "clusters out of order\n"); 1951 ok(logclust[2] == 1, "clusters out of order\n"); 1952 ok(logclust[3] == 0, "clusters out of order\n"); 1953 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1954 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1955 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1956 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1957 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1958 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1959 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1960 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1961 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1962 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1963 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1964 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1965 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1966 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1967 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1968 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1969 1970 ScriptFreeCache(&sc); 1971 1972 /* some control characters are shown as blank */ 1973 for (i = 0; i < 2; i++) 1974 { 1975 static const WCHAR space[] = {' ', 0}; 1976 static const struct 1977 { 1978 WCHAR c; 1979 unsigned int item_count; 1980 unsigned int item; 1981 } 1982 test_data[] = 1983 { 1984 {0x0009, 3, 1}, /* \t */ 1985 {0x000a, 3, 1}, /* \n */ 1986 {0x000d, 3, 1}, /* \r */ 1987 {0x001c, 3, 1}, /* FS */ 1988 {0x001d, 3, 1}, /* GS */ 1989 {0x001e, 3, 1}, /* RS */ 1990 {0x001f, 3, 1}, /* US */ 1991 {0x200b, 1, 0}, /* ZWSP */ 1992 {0x200c, 1, 0}, /* ZWNJ */ 1993 {0x200d, 1, 0}, /* ZWJ */ 1994 {0x200e, 3, 1}, /* LRM */ 1995 {0x200f, 3, 1}, /* RLM */ 1996 {0x202a, 3, 1}, /* LRE */ 1997 {0x202b, 3, 1}, /* RLE */ 1998 {0x202c, 3, 1}, /* PDF */ 1999 {0x202d, 3, 1}, /* LRO */ 2000 {0x202e, 3, 1}, /* RLO */ 2001 }; 2002 WCHAR chars[3]; 2003 HFONT font, oldfont = NULL; 2004 LOGFONTA lf; 2005 2006 font = GetCurrentObject(hdc, OBJ_FONT); 2007 GetObjectA(font, sizeof(lf), &lf); 2008 if (i == 1) { 2009 lstrcpyA(lf.lfFaceName, "MS Sans Serif"); 2010 font = CreateFontIndirectA(&lf); 2011 oldfont = SelectObject(hdc, font); 2012 } 2013 2014 hr = ScriptItemize(space, 1, 2, NULL, NULL, items, NULL); 2015 ok(hr == S_OK, "%s: expected S_OK, got %08x\n", lf.lfFaceName, hr); 2016 2017 hr = ScriptShape(hdc, &sc, space, 1, 1, &items[0].a, glyphs, logclust, attrs, &nb); 2018 ok(hr == S_OK, "%s: expected S_OK, got %08x\n", lf.lfFaceName, hr); 2019 ok(nb == 1, "%s: expected 1, got %d\n", lf.lfFaceName, nb); 2020 2021 chars[0] = 'A'; 2022 chars[2] = 'A'; 2023 for (j = 0; j < sizeof(test_data) / sizeof(*test_data); ++j) 2024 { 2025 WCHAR c = test_data[j].c; 2026 SCRIPT_ITEM *item; 2027 2028 chars[1] = c; 2029 hr = ScriptItemize(chars, 3, 4, NULL, NULL, items, &nb); 2030 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2031 ok(nb == test_data[j].item_count, "%s: [%02x] Got unexpected item count %d.\n", 2032 lf.lfFaceName, c, nb); 2033 item = &items[test_data[j].item]; 2034 2035 ok(!item->a.fNoGlyphIndex, "%s: [%02x] got unexpected fNoGlyphIndex %#x.\n", 2036 lf.lfFaceName, c, item->a.fNoGlyphIndex); 2037 hr = ScriptShape(hdc, &sc, chars, 3, 3, &item->a, glyphs2, logclust, attrs, &nb); 2038 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2039 ok(nb == 3, "%s: [%02x] expected 3, got %d\n", lf.lfFaceName, c, nb); 2040 ok(!item->a.fNoGlyphIndex, "%s: [%02x] got unexpected fNoGlyphIndex %#x.\n", 2041 lf.lfFaceName, c, item->a.fNoGlyphIndex); 2042 2043 ok(glyphs[0] == glyphs2[1] || 2044 broken(glyphs2[1] == c && (c < 0x10)), 2045 "%s: [%02x] expected %04x, got %04x\n", lf.lfFaceName, c, glyphs[0], glyphs2[1]); 2046 ok(attrs[1].fZeroWidth || broken(!attrs[1].fZeroWidth && (c < 0x10) /* Vista */), 2047 "%s: [%02x] got unexpected fZeroWidth %#x.\n", lf.lfFaceName, c, attrs[1].fZeroWidth); 2048 2049 item->a.fNoGlyphIndex = 1; 2050 hr = ScriptShape(hdc, &sc, chars, 3, 3, &item->a, glyphs2, logclust, attrs, &nb); 2051 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2052 ok(nb == 3, "%s: [%02x] expected 1, got %d\n", lf.lfFaceName, c, nb); 2053 2054 if (c == 0x200b || c == 0x200c || c == 0x200d) 2055 { 2056 ok(glyphs2[1] == 0x0020, 2057 "%s: [%02x] got unexpected %04x.\n", lf.lfFaceName, c, glyphs2[1]); 2058 ok(attrs[1].fZeroWidth, "%s: [%02x] got unexpected fZeroWidth %#x.\n", 2059 lf.lfFaceName, c, attrs[1].fZeroWidth); 2060 } 2061 else 2062 { 2063 ok(glyphs2[1] == c, 2064 "%s: [%02x] got unexpected %04x.\n", lf.lfFaceName, c, glyphs2[1]); 2065 ok(!attrs[1].fZeroWidth, "%s: [%02x] got unexpected fZeroWidth %#x.\n", 2066 lf.lfFaceName, c, attrs[1].fZeroWidth); 2067 } 2068 } 2069 if (oldfont) 2070 DeleteObject(SelectObject(hdc, oldfont)); 2071 ScriptFreeCache(&sc); 2072 } 2073 2074 /* Text does not support this range. */ 2075 memset(items, 0, sizeof(items)); 2076 nb = 0; 2077 hr = ScriptItemize(test3, sizeof(test3)/sizeof(test3[0]), sizeof(items)/sizeof(items[0]), NULL, NULL, items, &nb); 2078 ok(hr == S_OK, "ScriptItemize failed, hr %#x.\n", hr); 2079 ok(items[0].a.eScript > 0, "Expected script id.\n"); 2080 ok(nb == 1, "Unexpected number of items.\n"); 2081 2082 memset(glyphs, 0xff, sizeof(glyphs)); 2083 nb = 0; 2084 hr = ScriptShape(hdc, &sc, test3, sizeof(test3)/sizeof(test3[0]), sizeof(glyphs)/sizeof(glyphs[0]), &items[0].a, 2085 glyphs, logclust, attrs, &nb); 2086 ok(hr == S_OK, "ScriptShape failed, hr %#x.\n", hr); 2087 ok(nb == 1, "Unexpected glyph count %u\n", nb); 2088 ok(glyphs[0] == 0, "Unexpected glyph id\n"); 2089 ScriptFreeCache(&sc); 2090 } 2091 2092 static void test_ScriptPlace(HDC hdc) 2093 { 2094 static const WCHAR test1[] = {'t', 'e', 's', 't',0}; 2095 BOOL ret; 2096 HRESULT hr; 2097 SCRIPT_CACHE sc = NULL; 2098 SCRIPT_CACHE sc2 = NULL; 2099 WORD glyphs[4], logclust[4]; 2100 SCRIPT_VISATTR attrs[4]; 2101 SCRIPT_ITEM items[2]; 2102 int nb, widths[4]; 2103 GOFFSET offset[4]; 2104 ABC abc[4]; 2105 2106 hr = ScriptItemize(test1, 4, 2, NULL, NULL, items, NULL); 2107 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 2108 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2109 2110 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 2111 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 2112 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2113 2114 hr = ScriptPlace(hdc, &sc, glyphs, 4, NULL, &items[0].a, widths, NULL, NULL); 2115 ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr); 2116 2117 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL); 2118 ok(broken(hr == E_PENDING) || 2119 hr == E_INVALIDARG || /* Vista, W2K8 */ 2120 hr == E_FAIL, /* WIN7 */ 2121 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 2122 2123 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2124 ok(hr == E_PENDING, "ScriptPlace should return E_PENDING not %08x\n", hr); 2125 2126 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, abc); 2127 ok(broken(hr == E_PENDING) || 2128 hr == E_INVALIDARG || /* Vista, W2K8 */ 2129 hr == E_FAIL, /* WIN7 */ 2130 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 2131 2132 hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2133 ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); 2134 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2135 2136 hr = ScriptPlace(hdc, &sc2, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2137 ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); 2138 ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2); 2139 ScriptFreeCache(&sc2); 2140 2141 if (widths[0] != 0) 2142 { 2143 int old_width = widths[0]; 2144 attrs[0].fZeroWidth = 1; 2145 2146 hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2147 ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); 2148 ok(widths[0] == 0, "got width %d\n", widths[0]); 2149 widths[0] = old_width; 2150 } 2151 else 2152 skip("Glyph already has zero-width - skipping fZeroWidth test\n"); 2153 2154 ret = ExtTextOutW(hdc, 1, 1, 0, NULL, glyphs, 4, widths); 2155 ok(ret, "ExtTextOutW should return TRUE\n"); 2156 2157 ScriptFreeCache(&sc); 2158 } 2159 2160 static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256]) 2161 { 2162 HRESULT hr; 2163 int iMaxProps; 2164 const SCRIPT_PROPERTIES **ppSp; 2165 2166 int cInChars; 2167 int cMaxItems; 2168 SCRIPT_ITEM pItem[255]; 2169 int pcItems; 2170 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2171 WCHAR TestItem2[] = {'T', 'e', 's', 't', 'b', 0}; 2172 WCHAR TestItem3[] = {'T', 'e', 's', 't', 'c',' ','1','2','3',' ',' ','e','n','d',0}; 2173 WCHAR TestItem4[] = {'T', 'e', 's', 't', 'd',' ',0x0684,0x0694,0x06a4,' ',' ','\r','\n','e','n','d',0}; 2174 WCHAR TestItem5[] = {0x0684,'T','e','s','t','e',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0}; 2175 WCHAR TestItem6[] = {'T', 'e', 's', 't', 'f',' ',' ',' ','\r','\n','e','n','d',0}; 2176 2177 SCRIPT_CACHE psc; 2178 int cChars; 2179 int cMaxGlyphs; 2180 unsigned short pwOutGlyphs1[256]; 2181 unsigned short pwOutGlyphs2[256]; 2182 unsigned short pwLogClust[256]; 2183 SCRIPT_VISATTR psva[256]; 2184 int pcGlyphs; 2185 int piAdvance[256]; 2186 GOFFSET pGoffset[256]; 2187 ABC pABC[256]; 2188 int cnt; 2189 2190 /* Start testing usp10 functions */ 2191 /* This test determines that the pointer returned by ScriptGetProperties is valid 2192 * by checking a known value in the table */ 2193 hr = ScriptGetProperties(&ppSp, &iMaxProps); 2194 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 2195 trace("number of script properties %d\n", iMaxProps); 2196 ok (iMaxProps > 0, "Number of scripts returned should not be 0\n"); 2197 if (iMaxProps > 0) 2198 ok( ppSp[0]->langid == 0, "Langid[0] not = to 0\n"); /* Check a known value to ensure */ 2199 /* ptrs work */ 2200 2201 /* This is a valid test that will cause parsing to take place */ 2202 cInChars = 5; 2203 cMaxItems = 255; 2204 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2205 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2206 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2207 * returned. */ 2208 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2209 if (pcItems > 0) 2210 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2211 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2212 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2213 2214 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2215 * ie. ScriptItemize has succeeded and that pItem has been set */ 2216 cInChars = 5; 2217 if (hr == S_OK) { 2218 psc = NULL; /* must be null on first call */ 2219 cChars = cInChars; 2220 cMaxGlyphs = cInChars; 2221 hr = ScriptShape(NULL, &psc, TestItem1, cChars, 2222 cMaxGlyphs, &pItem[0].a, 2223 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2224 ok (hr == E_PENDING, "If psc is NULL (%08x) the E_PENDING should be returned\n", hr); 2225 cMaxGlyphs = 4; 2226 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2227 cMaxGlyphs, &pItem[0].a, 2228 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2229 ok (hr == E_OUTOFMEMORY, "If not enough output area cChars (%d) is > than CMaxGlyphs " 2230 "(%d) but not E_OUTOFMEMORY\n", 2231 cChars, cMaxGlyphs); 2232 cMaxGlyphs = 256; 2233 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2234 cMaxGlyphs, &pItem[0].a, 2235 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2236 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2237 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2238 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2239 if (hr ==0) { 2240 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2241 pGoffset, pABC); 2242 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2243 hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2244 pGoffset, pABC); 2245 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2246 for (cnt=0; cnt < pcGlyphs; cnt++) 2247 pwOutGlyphs[cnt] = pwOutGlyphs1[cnt]; /* Send to next function */ 2248 } 2249 2250 /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation * 2251 * takes place if fNoGlyphIndex is set. */ 2252 2253 cInChars = 5; 2254 cMaxItems = 255; 2255 hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2256 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2257 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2258 * returned. */ 2259 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2260 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2261 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2262 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue */ 2263 if (hr == S_OK) { 2264 cChars = cInChars; 2265 cMaxGlyphs = 256; 2266 pItem[0].a.fNoGlyphIndex = 1; /* say no translate */ 2267 hr = ScriptShape(NULL, &psc, TestItem2, cChars, 2268 cMaxGlyphs, &pItem[0].a, 2269 pwOutGlyphs2, pwLogClust, psva, &pcGlyphs); 2270 ok (hr != E_PENDING, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n", hr); 2271 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2272 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2273 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2274 for (cnt=0; cnt < cChars && TestItem2[cnt] == pwOutGlyphs2[cnt]; cnt++) {} 2275 ok (cnt == cChars, "Translation to place when told not to. WCHAR %d - %04x != %04x\n", 2276 cnt, TestItem2[cnt], pwOutGlyphs2[cnt]); 2277 if (hr == S_OK) { 2278 hr = ScriptPlace(hdc, &psc, pwOutGlyphs2, pcGlyphs, psva, &pItem[0].a, piAdvance, 2279 pGoffset, pABC); 2280 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2281 } 2282 } 2283 ScriptFreeCache( &psc); 2284 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2285 2286 } 2287 2288 /* This is a valid test that will cause parsing to take place and create 3 script_items */ 2289 cInChars = (sizeof(TestItem3)/2)-1; 2290 cMaxItems = 255; 2291 hr = ScriptItemize(TestItem3, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2292 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2293 if (hr == S_OK) 2294 { 2295 ok (pcItems == 3, "The number of SCRIPT_ITEMS should be 3 not %d\n", pcItems); 2296 if (pcItems > 2) 2297 { 2298 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == 6, 2299 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n", 2300 pItem[0].iCharPos, pItem[1].iCharPos); 2301 ok (pItem[1].iCharPos == 6 && pItem[2].iCharPos == 11, 2302 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n", 2303 pItem[1].iCharPos, pItem[2].iCharPos); 2304 ok (pItem[2].iCharPos == 11 && pItem[3].iCharPos == cInChars, 2305 "Start pos [2] not = 11 (%d) or end [3] pos not = 14 (%d), cInChars = %d\n", 2306 pItem[2].iCharPos, pItem[3].iCharPos, cInChars); 2307 } 2308 } 2309 2310 /* This is a valid test that will cause parsing to take place and create 5 script_items */ 2311 cInChars = (sizeof(TestItem4)/2)-1; 2312 cMaxItems = 255; 2313 hr = ScriptItemize(TestItem4, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2314 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2315 if (hr == S_OK) 2316 { 2317 ok (pcItems == 5, "The number of SCRIPT_ITEMS should be 5 not %d\n", pcItems); 2318 if (pcItems > 4) 2319 { 2320 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == 6, 2321 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n", 2322 pItem[0].iCharPos, pItem[1].iCharPos); 2323 ok (pItem[0].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2324 pItem[0].a.s.uBidiLevel); 2325 ok (pItem[1].iCharPos == 6 && pItem[2].iCharPos == 11, 2326 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n", 2327 pItem[1].iCharPos, pItem[2].iCharPos); 2328 ok (pItem[1].a.s.uBidiLevel == 1, "Should have been bidi=1 not %d\n", 2329 pItem[1].a.s.uBidiLevel); 2330 ok (pItem[2].iCharPos == 11 && pItem[3].iCharPos == 12, 2331 "Start pos [2] not = 11 (%d) or end [3] pos not = 12 (%d)\n", 2332 pItem[2].iCharPos, pItem[3].iCharPos); 2333 ok (pItem[2].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2334 pItem[2].a.s.uBidiLevel); 2335 ok (pItem[3].iCharPos == 12 && pItem[4].iCharPos == 13, 2336 "Start pos [3] not = 12 (%d) or end [4] pos not = 13 (%d)\n", 2337 pItem[3].iCharPos, pItem[4].iCharPos); 2338 ok (pItem[3].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2339 pItem[3].a.s.uBidiLevel); 2340 ok (pItem[4].iCharPos == 13 && pItem[5].iCharPos == cInChars, 2341 "Start pos [4] not = 13 (%d) or end [5] pos not = 16 (%d), cInChars = %d\n", 2342 pItem[4].iCharPos, pItem[5].iCharPos, cInChars); 2343 } 2344 } 2345 2346 /* 2347 * This test is for when the first unicode character requires bidi support 2348 */ 2349 cInChars = (sizeof(TestItem5)-1)/sizeof(WCHAR); 2350 hr = ScriptItemize(TestItem5, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2351 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2352 ok (pcItems == 4, "There should have been 4 items, found %d\n", pcItems); 2353 ok (pItem[0].a.s.uBidiLevel == 1, "The first character should have been bidi=1 not %d\n", 2354 pItem[0].a.s.uBidiLevel); 2355 2356 /* This test checks to make sure that the test to see if there are sufficient buffers to store * 2357 * the pointer to the last char works. Note that windows often needs a greater number of * 2358 * SCRIPT_ITEMS to process a string than is returned in pcItems. */ 2359 cInChars = (sizeof(TestItem6)/2)-1; 2360 cMaxItems = 4; 2361 hr = ScriptItemize(TestItem6, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2362 ok (hr == E_OUTOFMEMORY, "ScriptItemize should return E_OUTOFMEMORY, returned %08x\n", hr); 2363 2364 } 2365 2366 static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256]) 2367 { 2368 HRESULT hr; 2369 SCRIPT_CACHE psc = NULL; 2370 int cInChars; 2371 int cChars; 2372 unsigned short pwOutGlyphs2[256]; 2373 unsigned short pwOutGlyphs3[256]; 2374 DWORD dwFlags; 2375 int cnt; 2376 2377 static const WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2378 static const WCHAR TestItem2[] = {0x202B, 'i', 'n', 0x202C,0}; 2379 static const WCHAR TestItem3[] = {'a','b','c','d','(','<','{','[',0x2039,0}; 2380 static const WCHAR TestItem3b[] = {'a','b','c','d',')','>','}',']',0x203A,0}; 2381 2382 /* Check to make sure that SCRIPT_CACHE gets allocated ok */ 2383 dwFlags = 0; 2384 cInChars = cChars = 5; 2385 /* Some sanity checks for ScriptGetCMap */ 2386 2387 hr = ScriptGetCMap(NULL, NULL, NULL, 0, 0, NULL); 2388 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL,0,0,NULL), " 2389 "expected E_INVALIDARG, got %08x\n", hr); 2390 2391 hr = ScriptGetCMap(NULL, NULL, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2392 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), " 2393 "expected E_INVALIDARG, got %08x\n", hr); 2394 2395 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2396 psc = NULL; 2397 hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, 0, pwOutGlyphs3); 2398 ok( hr == E_PENDING, "(NULL,&psc,NULL,0,0,NULL), expected E_PENDING, " 2399 "got %08x\n", hr); 2400 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2401 2402 /* Set psc to NULL but add hdc, to be able to check if a pointer is returned in psc */ 2403 psc = NULL; 2404 hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, 0, pwOutGlyphs3); 2405 ok( hr == S_OK, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, " 2406 "got %08x\n", hr); 2407 ok( psc != NULL, "ScritpGetCMap expected psc to be not NULL\n"); 2408 ScriptFreeCache( &psc); 2409 2410 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2411 psc = NULL; 2412 hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2413 ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", hr); 2414 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2415 /* Check to see if the results are the same as those returned by ScriptShape */ 2416 hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2417 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2418 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2419 for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {} 2420 ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n", 2421 cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]); 2422 2423 ScriptFreeCache( &psc); 2424 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2425 2426 /* ScriptGetCMap returns whatever font defines, no special treatment for control chars */ 2427 cInChars = cChars = 4; 2428 GetGlyphIndicesW(hdc, TestItem2, cInChars, pwOutGlyphs2, 0); 2429 2430 hr = ScriptGetCMap(hdc, &psc, TestItem2, cInChars, dwFlags, pwOutGlyphs3); 2431 if (pwOutGlyphs3[0] == 0 || pwOutGlyphs3[3] == 0) 2432 ok(hr == S_FALSE, "ScriptGetCMap should return S_FALSE not (%08x)\n", hr); 2433 else 2434 ok(hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2435 2436 ok(psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2437 ok(pwOutGlyphs3[0] == pwOutGlyphs2[0], "expected glyph %d, got %d\n", pwOutGlyphs2[0], pwOutGlyphs3[0]); 2438 ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "expected glyph %d, got %d\n", pwOutGlyphs2[3], pwOutGlyphs3[3]); 2439 2440 cInChars = cChars = 9; 2441 hr = ScriptGetCMap(hdc, &psc, TestItem3b, cInChars, dwFlags, pwOutGlyphs2); 2442 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2443 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2444 2445 cInChars = cChars = 9; 2446 dwFlags = SGCM_RTL; 2447 hr = ScriptGetCMap(hdc, &psc, TestItem3, cInChars, dwFlags, pwOutGlyphs3); 2448 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2449 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2450 ok(pwOutGlyphs3[0] == pwOutGlyphs2[0], "glyph incorrectly altered\n"); 2451 ok(pwOutGlyphs3[1] == pwOutGlyphs2[1], "glyph incorrectly altered\n"); 2452 ok(pwOutGlyphs3[2] == pwOutGlyphs2[2], "glyph incorrectly altered\n"); 2453 ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "glyph incorrectly altered\n"); 2454 ok(pwOutGlyphs3[4] == pwOutGlyphs2[4], "glyph not mirrored correctly\n"); 2455 ok(pwOutGlyphs3[5] == pwOutGlyphs2[5], "glyph not mirrored correctly\n"); 2456 ok(pwOutGlyphs3[6] == pwOutGlyphs2[6], "glyph not mirrored correctly\n"); 2457 ok(pwOutGlyphs3[7] == pwOutGlyphs2[7], "glyph not mirrored correctly\n"); 2458 ok(pwOutGlyphs3[8] == pwOutGlyphs2[8], "glyph not mirrored correctly\n"); 2459 2460 ScriptFreeCache( &psc); 2461 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2462 } 2463 2464 #define MAX_ENUM_FONTS 4096 2465 2466 struct enum_font_data 2467 { 2468 int total; 2469 ENUMLOGFONTA elf[MAX_ENUM_FONTS]; 2470 }; 2471 2472 static INT CALLBACK enum_bitmap_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 2473 { 2474 struct enum_font_data *efnd = (struct enum_font_data *)lParam; 2475 2476 if (type & (TRUETYPE_FONTTYPE | DEVICE_FONTTYPE)) return 1; 2477 2478 if (efnd->total < MAX_ENUM_FONTS) 2479 { 2480 efnd->elf[efnd->total++] = *(ENUMLOGFONTA*)lf; 2481 } 2482 else 2483 trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS); 2484 2485 return 1; 2486 } 2487 2488 static INT CALLBACK enum_truetype_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 2489 { 2490 struct enum_font_data *efnd = (struct enum_font_data *)lParam; 2491 2492 if (!(type & (TRUETYPE_FONTTYPE | DEVICE_FONTTYPE))) return 1; 2493 2494 if (efnd->total < MAX_ENUM_FONTS) 2495 { 2496 efnd->elf[efnd->total++] = *(ENUMLOGFONTA*)lf; 2497 } 2498 else 2499 trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS); 2500 2501 return 1; 2502 } 2503 2504 static void test_ScriptGetFontProperties(HDC hdc) 2505 { 2506 HRESULT hr; 2507 SCRIPT_CACHE psc,old_psc; 2508 SCRIPT_FONTPROPERTIES sfp; 2509 HFONT font, oldfont; 2510 LOGFONTA lf; 2511 struct enum_font_data efnd; 2512 TEXTMETRICA tmA; 2513 WORD gi[3]; 2514 WCHAR str[3]; 2515 DWORD i, ret; 2516 WORD system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID()); 2517 static const WCHAR invalids[] = {0x0020, 0x200B, 0xF71B}; 2518 /* U+0020: numeric space 2519 U+200B: zero width space 2520 U+F71B: unknown, found by black box testing */ 2521 BOOL is_arial, is_times_new_roman, is_arabic = (system_lang_id == LANG_ARABIC); 2522 2523 /* Some sanity checks for ScriptGetFontProperties */ 2524 2525 hr = ScriptGetFontProperties(NULL,NULL,NULL); 2526 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr); 2527 2528 hr = ScriptGetFontProperties(NULL,NULL,&sfp); 2529 ok( hr == E_INVALIDARG, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr); 2530 2531 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2532 psc = NULL; 2533 hr = ScriptGetFontProperties(NULL,&psc,NULL); 2534 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr); 2535 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2536 2537 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2538 psc = NULL; 2539 hr = ScriptGetFontProperties(NULL,&psc,&sfp); 2540 ok( hr == E_PENDING, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", hr); 2541 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2542 2543 hr = ScriptGetFontProperties(hdc,NULL,NULL); 2544 ok( hr == E_INVALIDARG, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr); 2545 2546 hr = ScriptGetFontProperties(hdc,NULL,&sfp); 2547 ok( hr == E_INVALIDARG, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr); 2548 2549 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2550 psc = NULL; 2551 hr = ScriptGetFontProperties(hdc,&psc,NULL); 2552 ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr); 2553 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2554 2555 /* Pass an invalid sfp */ 2556 psc = NULL; 2557 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES) - 1; 2558 hr = ScriptGetFontProperties(hdc,&psc,&sfp); 2559 ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) invalid, expected E_INVALIDARG, got %08x\n", hr); 2560 ok( psc != NULL, "Expected a pointer in psc, got NULL\n"); 2561 ok( sfp.cBytes == sizeof(SCRIPT_FONTPROPERTIES) - 1, "Unexpected cBytes.\n"); 2562 ScriptFreeCache(&psc); 2563 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2564 2565 /* Give it the correct cBytes, we don't care about what's coming back */ 2566 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2567 psc = NULL; 2568 hr = ScriptGetFontProperties(hdc,&psc,&sfp); 2569 ok( hr == S_OK, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", hr); 2570 ok( psc != NULL, "Expected a pointer in psc, got NULL\n"); 2571 2572 /* Save the psc pointer */ 2573 old_psc = psc; 2574 /* Now a NULL hdc again */ 2575 hr = ScriptGetFontProperties(NULL,&psc,&sfp); 2576 ok( hr == S_OK, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", hr); 2577 ok( psc == old_psc, "Expected psc not to be changed, was %p is now %p\n", old_psc, psc); 2578 ScriptFreeCache(&psc); 2579 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2580 2581 memset(&lf, 0, sizeof(lf)); 2582 lf.lfCharSet = DEFAULT_CHARSET; 2583 efnd.total = 0; 2584 EnumFontFamiliesA(hdc, NULL, enum_bitmap_font_proc, (LPARAM)&efnd); 2585 2586 for (i = 0; i < efnd.total; i++) 2587 { 2588 if (strlen((char *)efnd.elf[i].elfFullName) >= LF_FACESIZE) 2589 { 2590 trace("Font name to long to test: %s\n",(char *)efnd.elf[i].elfFullName); 2591 continue; 2592 } 2593 lstrcpyA(lf.lfFaceName, (char *)efnd.elf[i].elfFullName); 2594 font = CreateFontIndirectA(&lf); 2595 oldfont = SelectObject(hdc, font); 2596 2597 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2598 psc = NULL; 2599 hr = ScriptGetFontProperties(hdc, &psc, &sfp); 2600 ok(hr == S_OK, "ScriptGetFontProperties expected S_OK, got %08x\n", hr); 2601 if (winetest_interactive) 2602 { 2603 trace("bitmap font %s\n", lf.lfFaceName); 2604 trace("wgBlank %04x\n", sfp.wgBlank); 2605 trace("wgDefault %04x\n", sfp.wgDefault); 2606 trace("wgInvalid %04x\n", sfp.wgInvalid); 2607 trace("wgKashida %04x\n", sfp.wgKashida); 2608 trace("iKashidaWidth %d\n", sfp.iKashidaWidth); 2609 } 2610 2611 ret = GetTextMetricsA(hdc, &tmA); 2612 ok(ret != 0, "GetTextMetricsA failed!\n"); 2613 2614 ret = GetGlyphIndicesW(hdc, invalids, 1, gi, GGI_MARK_NONEXISTING_GLYPHS); 2615 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2616 2617 ok(sfp.wgBlank == tmA.tmBreakChar || sfp.wgBlank == gi[0], "bitmap font %s wgBlank %04x tmBreakChar %04x Space %04x\n", lf.lfFaceName, sfp.wgBlank, tmA.tmBreakChar, gi[0]); 2618 2619 ok(sfp.wgDefault == 0 || sfp.wgDefault == tmA.tmDefaultChar || broken(sfp.wgDefault == (0x100 | tmA.tmDefaultChar)), "bitmap font %s wgDefault %04x, tmDefaultChar %04x\n", lf.lfFaceName, sfp.wgDefault, tmA.tmDefaultChar); 2620 2621 ok(sfp.wgInvalid == sfp.wgBlank || broken(is_arabic), "bitmap font %s wgInvalid %02x wgBlank %02x\n", lf.lfFaceName, sfp.wgInvalid, sfp.wgBlank); 2622 2623 ok(sfp.wgKashida == 0xFFFF || broken(is_arabic), "bitmap font %s wgKashida %02x\n", lf.lfFaceName, sfp.wgKashida); 2624 2625 ScriptFreeCache(&psc); 2626 2627 SelectObject(hdc, oldfont); 2628 DeleteObject(font); 2629 } 2630 2631 efnd.total = 0; 2632 EnumFontFamiliesA(hdc, NULL, enum_truetype_proc, (LPARAM)&efnd); 2633 2634 for (i = 0; i < efnd.total; i++) 2635 { 2636 if (strlen((char *)efnd.elf[i].elfFullName) >= LF_FACESIZE) 2637 { 2638 trace("Font name to long to test: %s\n",(char *)efnd.elf[i].elfFullName); 2639 continue; 2640 } 2641 lstrcpyA(lf.lfFaceName, (char *)efnd.elf[i].elfFullName); 2642 font = CreateFontIndirectA(&lf); 2643 oldfont = SelectObject(hdc, font); 2644 2645 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2646 psc = NULL; 2647 hr = ScriptGetFontProperties(hdc, &psc, &sfp); 2648 ok(hr == S_OK, "ScriptGetFontProperties expected S_OK, got %08x\n", hr); 2649 if (winetest_interactive) 2650 { 2651 trace("truetype font %s\n", lf.lfFaceName); 2652 trace("wgBlank %04x\n", sfp.wgBlank); 2653 trace("wgDefault %04x\n", sfp.wgDefault); 2654 trace("wgInvalid %04x\n", sfp.wgInvalid); 2655 trace("wgKashida %04x\n", sfp.wgKashida); 2656 trace("iKashidaWidth %d\n", sfp.iKashidaWidth); 2657 } 2658 2659 str[0] = 0x0020; /* U+0020: numeric space */ 2660 ret = GetGlyphIndicesW(hdc, str, 1, gi, 0); 2661 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2662 ok(sfp.wgBlank == gi[0], "truetype font %s wgBlank %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgBlank, gi[0]); 2663 2664 ok(sfp.wgDefault == 0 || broken(is_arabic), "truetype font %s wgDefault %04x\n", lf.lfFaceName, sfp.wgDefault); 2665 2666 ret = GetGlyphIndicesW(hdc, invalids, 3, gi, GGI_MARK_NONEXISTING_GLYPHS); 2667 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2668 if (gi[2] != 0xFFFF) /* index of default non exist char */ 2669 ok(sfp.wgInvalid == gi[2], "truetype font %s wgInvalid %04x gi[2] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[2]); 2670 else if (gi[1] != 0xFFFF) 2671 ok(sfp.wgInvalid == gi[1], "truetype font %s wgInvalid %04x gi[1] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[1]); 2672 else if (gi[0] != 0xFFFF) 2673 ok(sfp.wgInvalid == gi[0], "truetype font %s wgInvalid %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[0]); 2674 else 2675 ok(sfp.wgInvalid == 0, "truetype font %s wgInvalid %04x expect 0\n", lf.lfFaceName, sfp.wgInvalid); 2676 2677 str[0] = 0x0640; /* U+0640: kashida */ 2678 ret = GetGlyphIndicesW(hdc, str, 1, gi, GGI_MARK_NONEXISTING_GLYPHS); 2679 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2680 is_arial = !lstrcmpA(lf.lfFaceName, "Arial"); 2681 is_times_new_roman= !lstrcmpA(lf.lfFaceName, "Times New Roman"); 2682 ok(sfp.wgKashida == gi[0] || broken(is_arial || is_times_new_roman) || broken(is_arabic), "truetype font %s wgKashida %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgKashida, gi[0]); 2683 2684 ScriptFreeCache(&psc); 2685 2686 SelectObject(hdc, oldfont); 2687 DeleteObject(font); 2688 } 2689 } 2690 2691 static void test_ScriptTextOut(HDC hdc) 2692 { 2693 HRESULT hr; 2694 2695 int cInChars; 2696 int cMaxItems; 2697 SCRIPT_ITEM pItem[255]; 2698 int pcItems; 2699 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2700 2701 SCRIPT_CACHE psc; 2702 int cChars; 2703 int cMaxGlyphs; 2704 unsigned short pwOutGlyphs1[256]; 2705 WORD pwLogClust[256]; 2706 SCRIPT_VISATTR psva[256]; 2707 int pcGlyphs; 2708 int piAdvance[256]; 2709 GOFFSET pGoffset[256]; 2710 ABC pABC[256]; 2711 RECT rect; 2712 int piX; 2713 int iCP = 1; 2714 BOOL fTrailing = FALSE; 2715 SCRIPT_LOGATTR *psla; 2716 SCRIPT_LOGATTR sla[256]; 2717 2718 /* This is a valid test that will cause parsing to take place */ 2719 cInChars = 5; 2720 cMaxItems = 255; 2721 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2722 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2723 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2724 * returned. */ 2725 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2726 if (pcItems > 0) 2727 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2728 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2729 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2730 2731 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2732 * ie. ScriptItemize has succeeded and that pItem has been set */ 2733 cInChars = 5; 2734 if (hr == S_OK) { 2735 psc = NULL; /* must be null on first call */ 2736 cChars = cInChars; 2737 cMaxGlyphs = 256; 2738 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2739 cMaxGlyphs, &pItem[0].a, 2740 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2741 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2742 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2743 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2744 if (hr == S_OK) { 2745 /* Note hdc is needed as glyph info is not yet in psc */ 2746 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2747 pGoffset, pABC); 2748 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2749 ScriptFreeCache(&psc); /* Get rid of psc for next test set */ 2750 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2751 2752 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL); 2753 ok (hr == E_INVALIDARG, "Should return 0 not (%08x)\n", hr); 2754 2755 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2756 piAdvance, NULL, pGoffset); 2757 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), " 2758 "expected E_INVALIDARG, got %08x\n", hr); 2759 2760 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2761 psc = NULL; 2762 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, 2763 NULL, NULL, NULL); 2764 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, " 2765 "got %08x\n", hr); 2766 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2767 2768 /* hdc is required for this one rather than the usual optional */ 2769 psc = NULL; 2770 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2771 piAdvance, NULL, pGoffset); 2772 ok( hr == E_INVALIDARG, "(NULL,&psc,), expected E_INVALIDARG, got %08x\n", hr); 2773 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2774 2775 /* Set that it returns 0 status */ 2776 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2777 piAdvance, NULL, pGoffset); 2778 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2779 2780 /* Test Rect Rgn is acceptable */ 2781 SetRect(&rect, 10, 10, 40, 20); 2782 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2783 piAdvance, NULL, pGoffset); 2784 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2785 2786 iCP = 1; 2787 hr = ScriptCPtoX(iCP, fTrailing, cChars, pcGlyphs, (const WORD *) &pwLogClust, 2788 (const SCRIPT_VISATTR *) &psva, (const int *)&piAdvance, &pItem[0].a, &piX); 2789 ok(hr == S_OK, "ScriptCPtoX Stub should return S_OK not %08x\n", hr); 2790 2791 psla = (SCRIPT_LOGATTR *)&sla; 2792 hr = ScriptBreak(TestItem1, cChars, &pItem[0].a, psla); 2793 ok(hr == S_OK, "ScriptBreak Stub should return S_OK not %08x\n", hr); 2794 2795 /* Clean up and go */ 2796 ScriptFreeCache(&psc); 2797 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2798 } 2799 } 2800 } 2801 2802 static void test_ScriptTextOut2(HDC hdc) 2803 { 2804 /* Intent is to validate that the HDC passed into ScriptTextOut is 2805 * used instead of the (possibly) invalid cached one 2806 */ 2807 HRESULT hr; 2808 2809 HDC hdc1, hdc2; 2810 int cInChars; 2811 int cMaxItems; 2812 SCRIPT_ITEM pItem[255]; 2813 int pcItems; 2814 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2815 2816 SCRIPT_CACHE psc; 2817 int cChars; 2818 int cMaxGlyphs; 2819 unsigned short pwOutGlyphs1[256]; 2820 WORD pwLogClust[256]; 2821 SCRIPT_VISATTR psva[256]; 2822 int pcGlyphs; 2823 int piAdvance[256]; 2824 GOFFSET pGoffset[256]; 2825 ABC pABC[256]; 2826 2827 /* Create an extra DC that will be used until the ScriptTextOut */ 2828 hdc1 = CreateCompatibleDC(hdc); 2829 ok (hdc1 != 0, "CreateCompatibleDC failed to create a DC\n"); 2830 hdc2 = CreateCompatibleDC(hdc); 2831 ok (hdc2 != 0, "CreateCompatibleDC failed to create a DC\n"); 2832 2833 /* This is a valid test that will cause parsing to take place */ 2834 cInChars = 5; 2835 cMaxItems = 255; 2836 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2837 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2838 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2839 * returned. */ 2840 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2841 if (pcItems > 0) 2842 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2843 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2844 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2845 2846 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2847 * ie. ScriptItemize has succeeded and that pItem has been set */ 2848 cInChars = 5; 2849 if (hr == S_OK) { 2850 psc = NULL; /* must be null on first call */ 2851 cChars = cInChars; 2852 cMaxGlyphs = 256; 2853 hr = ScriptShape(hdc2, &psc, TestItem1, cChars, 2854 cMaxGlyphs, &pItem[0].a, 2855 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2856 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2857 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2858 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2859 if (hr == S_OK) { 2860 BOOL ret; 2861 2862 /* Note hdc is needed as glyph info is not yet in psc */ 2863 hr = ScriptPlace(hdc2, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2864 pGoffset, pABC); 2865 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2866 2867 /* key part!!! cached dc is being deleted */ 2868 ret = DeleteDC(hdc2); 2869 ok(ret, "DeleteDC should return 1 not %d\n", ret); 2870 2871 /* At this point the cached hdc (hdc2) has been destroyed, 2872 * however, we are passing in a *real* hdc (the original hdc). 2873 * The text should be written to that DC 2874 */ 2875 hr = ScriptTextOut(hdc1, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2876 piAdvance, NULL, pGoffset); 2877 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2878 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2879 2880 DeleteDC(hdc1); 2881 2882 /* Clean up and go */ 2883 ScriptFreeCache(&psc); 2884 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2885 } 2886 } 2887 } 2888 2889 static void test_ScriptTextOut3(HDC hdc) 2890 { 2891 HRESULT hr; 2892 2893 int cInChars; 2894 int cMaxItems; 2895 SCRIPT_ITEM pItem[255]; 2896 int pcItems; 2897 WCHAR TestItem1[] = {' ','\r', 0}; 2898 2899 SCRIPT_CACHE psc; 2900 int cChars; 2901 int cMaxGlyphs; 2902 unsigned short pwOutGlyphs1[256]; 2903 WORD pwLogClust[256]; 2904 SCRIPT_VISATTR psva[256]; 2905 int pcGlyphs; 2906 int piAdvance[256]; 2907 GOFFSET pGoffset[256]; 2908 ABC pABC[256]; 2909 RECT rect; 2910 2911 /* This is to ensure that nonexistent glyphs are translated into a valid glyph number */ 2912 cInChars = 2; 2913 cMaxItems = 255; 2914 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2915 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2916 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2917 * returned. */ 2918 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2919 if (pcItems > 0) 2920 ok (pItem[0].iCharPos == 0 && pItem[2].iCharPos == cInChars, 2921 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2922 pItem[0].iCharPos, cInChars, pItem[2].iCharPos); 2923 2924 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2925 * ie. ScriptItemize has succeeded and that pItem has been set */ 2926 cInChars = 2; 2927 if (hr == S_OK) { 2928 psc = NULL; /* must be null on first call */ 2929 cChars = cInChars; 2930 cMaxGlyphs = 256; 2931 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2932 cMaxGlyphs, &pItem[0].a, 2933 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2934 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2935 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2936 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2937 if (hr ==0) { 2938 /* Note hdc is needed as glyph info is not yet in psc */ 2939 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2940 pGoffset, pABC); 2941 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2942 2943 /* Test Rect Rgn is acceptable */ 2944 SetRect(&rect, 10, 10, 40, 20); 2945 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2946 piAdvance, NULL, pGoffset); 2947 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2948 } 2949 /* Clean up and go */ 2950 ScriptFreeCache(&psc); 2951 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2952 } 2953 } 2954 2955 #define test_item_ScriptXtoX(a,b,c,d,e,f) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_item_ScriptXtoX(a,b,c,d,e,f) 2956 2957 static void _test_item_ScriptXtoX(SCRIPT_ANALYSIS *psa, int cChars, int cGlyphs, const int* offsets, const WORD *pwLogClust, const int* piAdvance ) 2958 { 2959 int iX, iCP; 2960 int icChars, icGlyphs; 2961 int piCP, piX; 2962 HRESULT hr; 2963 SCRIPT_VISATTR psva[10]; 2964 int piTrailing; 2965 BOOL fTrailing; 2966 int direction; 2967 2968 memset(psva,0,sizeof(psva)); 2969 direction = (psa->fRTL)?-1:+1; 2970 2971 for(iCP = 0; iCP < cChars; iCP++) 2972 { 2973 iX = offsets[iCP]; 2974 icChars = cChars; 2975 icGlyphs = cGlyphs; 2976 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 2977 winetest_ok(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 2978 winetest_ok(piCP == iCP, "ScriptXtoCP: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 2979 winetest_ok(piTrailing == 0, "ScriptXtoCP: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 2980 } 2981 2982 for(iCP = 0; iCP < cChars; iCP++) 2983 { 2984 iX = offsets[iCP]+direction; 2985 icChars = cChars; 2986 icGlyphs = cGlyphs; 2987 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 2988 winetest_ok(hr == S_OK, "ScriptXtoCP leading: should return S_OK not %08x\n", hr); 2989 winetest_ok(piCP == iCP, "ScriptXtoCP leading: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 2990 winetest_ok(piTrailing == 0, "ScriptXtoCP leading: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 2991 } 2992 2993 for(iCP = 0; iCP < cChars; iCP++) 2994 { 2995 iX = offsets[iCP+1]-direction; 2996 icChars = cChars; 2997 icGlyphs = cGlyphs; 2998 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 2999 winetest_ok(hr == S_OK, "ScriptXtoCP trailing: should return S_OK not %08x\n", hr); 3000 winetest_ok(piCP == iCP, "ScriptXtoCP trailing: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3001 winetest_ok(piTrailing == 1, "ScriptXtoCP trailing: iX=%d should return piTrailing=1 not %d\n", iX, piTrailing); 3002 } 3003 3004 for(iCP = 0; iCP <= cChars+1; iCP++) 3005 { 3006 fTrailing = FALSE; 3007 icChars = cChars; 3008 icGlyphs = cGlyphs; 3009 hr = ScriptCPtoX(iCP, fTrailing, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piX); 3010 winetest_ok(hr == S_OK, "ScriptCPtoX: should return S_OK not %08x\n", hr); 3011 winetest_ok(piX == offsets[iCP], 3012 "ScriptCPtoX: iCP=%d should return piX=%d not %d\n", iCP, offsets[iCP], piX); 3013 } 3014 3015 for(iCP = 0; iCP <= cChars+1; iCP++) 3016 { 3017 fTrailing = TRUE; 3018 icChars = cChars; 3019 icGlyphs = cGlyphs; 3020 hr = ScriptCPtoX(iCP, fTrailing, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piX); 3021 winetest_ok(hr == S_OK, "ScriptCPtoX trailing: should return S_OK not %08x\n", hr); 3022 winetest_ok(piX == offsets[iCP+1], 3023 "ScriptCPtoX trailing: iCP=%d should return piX=%d not %d\n", iCP, offsets[iCP+1], piX); 3024 } 3025 } 3026 3027 #define test_caret_item_ScriptXtoCP(a,b,c,d,e,f) _test_caret_item_ScriptXtoCP(__LINE__,a,b,c,d,e,f) 3028 3029 static void _test_caret_item_ScriptXtoCP(int line, SCRIPT_ANALYSIS *psa, int cChars, int cGlyphs, const int* offsets, const WORD *pwLogClust, const int* piAdvance ) 3030 { 3031 int iX, iCP, i; 3032 int icChars, icGlyphs; 3033 int piCP; 3034 int clusterSize; 3035 HRESULT hr; 3036 SCRIPT_VISATTR psva[10]; 3037 int piTrailing; 3038 int direction; 3039 3040 memset(psva,0,sizeof(psva)); 3041 direction = (psa->fRTL)?-1:+1; 3042 3043 for(iX = -1, i = iCP = 0; i < cChars; i++) 3044 { 3045 if (offsets[i] != iX) 3046 { 3047 iX = offsets[i]; 3048 iCP = i; 3049 } 3050 icChars = cChars; 3051 icGlyphs = cGlyphs; 3052 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3053 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 3054 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3055 ok_(__FILE__,line)(piTrailing == 0, "ScriptXtoCP: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 3056 } 3057 3058 for(iX = -2, i = 0; i < cChars; i++) 3059 { 3060 if (offsets[i]+direction != iX) 3061 { 3062 iX = offsets[i] + direction; 3063 iCP = i; 3064 } 3065 icChars = cChars; 3066 icGlyphs = cGlyphs; 3067 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3068 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP leading: should return S_OK not %08x\n", hr); 3069 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP leading: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3070 ok_(__FILE__,line)(piTrailing == 0, "ScriptXtoCP leading: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 3071 } 3072 3073 for(clusterSize = 0, iCP = 0, iX = -2, i = 0; i < cChars; i++) 3074 { 3075 clusterSize++; 3076 if (offsets[i] != offsets[i+1]) 3077 { 3078 iX = offsets[i+1]-direction; 3079 icChars = cChars; 3080 icGlyphs = cGlyphs; 3081 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3082 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP trailing: should return S_OK not %08x\n", hr); 3083 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP trailing: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3084 ok_(__FILE__,line)(piTrailing == clusterSize, "ScriptXtoCP trailing: iX=%d should return piTrailing=%d not %d\n", iX, clusterSize, piTrailing); 3085 iCP = i+1; 3086 clusterSize = 0; 3087 } 3088 } 3089 } 3090 3091 static void test_ScriptXtoX(void) 3092 /**************************************************************************************** 3093 * This routine tests the ScriptXtoCP and ScriptCPtoX functions using static variables * 3094 ****************************************************************************************/ 3095 { 3096 WORD pwLogClust[10] = {0, 0, 0, 1, 1, 2, 2, 3, 3, 3}; 3097 WORD pwLogClust_RTL[10] = {3, 3, 3, 2, 2, 1, 1, 0, 0, 0}; 3098 WORD pwLogClust_2[7] = {4, 3, 3, 2, 1, 0 ,0}; 3099 WORD pwLogClust_3[17] = {0, 1, 1, 1, 1, 4, 5, 6, 6, 8, 8, 8, 8, 11, 11, 13, 13}; 3100 WORD pwLogClust_3_RTL[17] = {13, 13, 11, 11, 8, 8, 8, 8, 6, 6, 5, 4, 1, 1, 1, 1, 0}; 3101 int piAdvance[10] = {201, 190, 210, 180, 170, 204, 189, 195, 212, 203}; 3102 int piAdvance_2[5] = {39, 26, 19, 17, 11}; 3103 int piAdvance_3[15] = {6, 6, 0, 0, 10, 5, 10, 0, 12, 0, 0, 9, 0, 10, 0}; 3104 static const int offsets[13] = {0, 67, 134, 201, 296, 391, 496, 601, 1052, 1503, 1954, 1954, 1954}; 3105 static const int offsets_RTL[13] = {781, 721, 661, 601, 496, 391, 296, 201, 134, 67, 0, 0, 0}; 3106 static const int offsets_2[10] = {112, 101, 92, 84, 65, 39, 19, 0, 0, 0}; 3107 3108 static const int offsets_3[19] = {0, 6, 6, 6, 6, 12, 22, 27, 27, 37, 37, 37, 37, 49, 49, 58, 58, 68, 68}; 3109 static const int offsets_3_RTL[19] = {68, 68, 58, 58, 49, 49, 49, 49, 37, 37, 27, 22, 12, 12, 12, 12, 6, 6}; 3110 3111 SCRIPT_VISATTR psva[15]; 3112 SCRIPT_ANALYSIS sa; 3113 SCRIPT_ITEM items[2]; 3114 int iX, i; 3115 int piCP; 3116 int piTrailing; 3117 HRESULT hr; 3118 static const WCHAR hebrW[] = { 0x5be, 0}; 3119 static const WCHAR thaiW[] = { 0xe2a, 0}; 3120 const SCRIPT_PROPERTIES **ppScriptProperties; 3121 3122 memset(&sa, 0 , sizeof(SCRIPT_ANALYSIS)); 3123 memset(psva, 0, sizeof(psva)); 3124 3125 sa.fRTL = FALSE; 3126 hr = ScriptXtoCP(-1, 10, 10, pwLogClust, psva, piAdvance, &sa, &piCP, &piTrailing); 3127 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3128 if (piTrailing) 3129 ok(piCP == -1, "Negative iX should return piCP=-1 not %d\n", piCP); 3130 else /* win2k3 */ 3131 ok(piCP == 10, "Negative iX should return piCP=10 not %d\n", piCP); 3132 3133 for (iX = 0; iX <= 7; iX++) 3134 { 3135 WORD clust = 0; 3136 INT advance = 16; 3137 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3138 ok(piCP==0 && piTrailing==0,"%i should return 0(%i) and 0(%i)\n",iX, piCP,piTrailing); 3139 } 3140 for (iX = 8; iX < 16; iX++) 3141 { 3142 WORD clust = 0; 3143 INT advance = 16; 3144 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3145 ok(piCP==0 && piTrailing==1,"%i should return 0(%i) and 1(%i)\n",iX, piCP,piTrailing); 3146 } 3147 3148 sa.fRTL = TRUE; 3149 hr = ScriptXtoCP(-1, 10, 10, pwLogClust_RTL, psva, piAdvance, &sa, &piCP, &piTrailing); 3150 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3151 if (piTrailing) 3152 ok(piCP == -1, "Negative iX should return piCP=-1 not %d\n", piCP); 3153 else /* win2k3 */ 3154 ok(piCP == 10, "Negative iX should return piCP=10 not %d\n", piCP); 3155 3156 iX = 1954; 3157 hr = ScriptXtoCP(1954, 10, 10, pwLogClust_RTL, psva, piAdvance, &sa, &piCP, &piTrailing); 3158 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3159 ok(piCP == -1, "iX=%d should return piCP=-1 not %d\n", iX, piCP); 3160 ok(piTrailing == 1, "iX=%d should return piTrailing=1 not %d\n", iX, piTrailing); 3161 3162 for (iX = 1; iX <= 8; iX++) 3163 { 3164 WORD clust = 0; 3165 INT advance = 16; 3166 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3167 ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr); 3168 ok(piCP==0 && piTrailing==1,"%i should return 0(%i) and 1(%i)\n",iX,piCP,piTrailing); 3169 } 3170 for (iX = 9; iX < 16; iX++) 3171 { 3172 WORD clust = 0; 3173 INT advance = 16; 3174 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3175 ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr); 3176 ok(piCP==0 && piTrailing==0,"%i should return 0(%i) and 0(%i)\n",iX,piCP,piTrailing); 3177 } 3178 3179 sa.fRTL = FALSE; 3180 test_item_ScriptXtoX(&sa, 10, 10, offsets, pwLogClust, piAdvance); 3181 sa.fRTL = TRUE; 3182 test_item_ScriptXtoX(&sa, 10, 10, offsets_RTL, pwLogClust_RTL, piAdvance); 3183 test_item_ScriptXtoX(&sa, 7, 5, offsets_2, pwLogClust_2, piAdvance_2); 3184 3185 /* Get thai eScript, This will do LTR and fNeedsCaretInfo */ 3186 hr = ScriptItemize(thaiW, 1, 2, NULL, NULL, items, &i); 3187 ok(hr == S_OK, "got %08x\n", hr); 3188 ok(i == 1, "got %d\n", i); 3189 sa = items[0].a; 3190 3191 test_caret_item_ScriptXtoCP(&sa, 17, 15, offsets_3, pwLogClust_3, piAdvance_3); 3192 3193 /* Get hebrew eScript, This will do RTL and fNeedsCaretInfo */ 3194 hr = ScriptItemize(hebrW, 1, 2, NULL, NULL, items, &i); 3195 ok(hr == S_OK, "got %08x\n", hr); 3196 ok(i == 1, "got %d\n", i); 3197 sa = items[0].a; 3198 3199 /* Note: This behavior CHANGED in uniscribe versions... 3200 * so we only want to test if fNeedsCaretInfo is set */ 3201 hr = ScriptGetProperties(&ppScriptProperties, &i); 3202 if (ppScriptProperties[sa.eScript]->fNeedsCaretInfo) 3203 { 3204 test_caret_item_ScriptXtoCP(&sa, 17, 15, offsets_3_RTL, pwLogClust_3_RTL, piAdvance_3); 3205 hr = ScriptXtoCP(0, 17, 15, pwLogClust_3_RTL, psva, piAdvance_3, &sa, &piCP, &piTrailing); 3206 ok(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 3207 ok(piCP == 16, "ScriptXtoCP: iX=0 should return piCP=16 not %d\n", piCP); 3208 ok(piTrailing == 1, "ScriptXtoCP: iX=0 should return piTrailing=1 not %d\n", piTrailing); 3209 } 3210 else 3211 win_skip("Uniscribe version too old to test Hebrew clusters\n"); 3212 } 3213 3214 static void test_ScriptString(HDC hdc) 3215 { 3216 /******************************************************************************************* 3217 * 3218 * This set of tests are for the string functions of uniscribe. The ScriptStringAnalyse 3219 * function allocates memory pointed to by the SCRIPT_STRING_ANALYSIS ssa pointer. This 3220 * memory is freed by ScriptStringFree. There needs to be a valid hdc for this as 3221 * ScriptStringAnalyse calls ScriptItemize, ScriptShape and ScriptPlace which require it. 3222 * 3223 */ 3224 3225 HRESULT hr; 3226 WCHAR teststr[] = {'T','e','s','t','1',' ','a','2','b','3', '\0'}; 3227 int len = (sizeof(teststr) / sizeof(WCHAR)) - 1; 3228 int Glyphs = len * 2 + 16; 3229 int Charset; 3230 DWORD Flags = SSA_GLYPHS; 3231 int ReqWidth = 100; 3232 static const int Dx[(sizeof(teststr) / sizeof(WCHAR)) - 1]; 3233 static const BYTE InClass[(sizeof(teststr) / sizeof(WCHAR)) - 1]; 3234 SCRIPT_STRING_ANALYSIS ssa = NULL; 3235 3236 int X = 10; 3237 int Y = 100; 3238 UINT Options = 0; 3239 const RECT rc = {0, 50, 100, 100}; 3240 int MinSel = 0; 3241 int MaxSel = 0; 3242 BOOL Disabled = FALSE; 3243 const int *clip_len; 3244 int i; 3245 UINT *order; 3246 3247 3248 Charset = -1; /* this flag indicates unicode input */ 3249 /* Test without hdc to get E_PENDING */ 3250 hr = ScriptStringAnalyse( NULL, teststr, len, Glyphs, Charset, Flags, 3251 ReqWidth, NULL, NULL, Dx, NULL, 3252 InClass, &ssa); 3253 ok(hr == E_PENDING, "ScriptStringAnalyse Stub should return E_PENDING not %08x\n", hr); 3254 3255 /* Test that 0 length string returns E_INVALIDARG */ 3256 hr = ScriptStringAnalyse( hdc, teststr, 0, Glyphs, Charset, Flags, 3257 ReqWidth, NULL, NULL, Dx, NULL, 3258 InClass, &ssa); 3259 ok(hr == E_INVALIDARG, "ScriptStringAnalyse should return E_INVALIDARG not %08x\n", hr); 3260 3261 /* test with hdc, this should be a valid test */ 3262 hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags, 3263 ReqWidth, NULL, NULL, Dx, NULL, 3264 InClass, &ssa); 3265 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3266 ScriptStringFree(&ssa); 3267 3268 /* test makes sure that a call with a valid pssa still works */ 3269 hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags, 3270 ReqWidth, NULL, NULL, Dx, NULL, 3271 InClass, &ssa); 3272 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3273 ok(ssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n"); 3274 3275 if (hr == S_OK) 3276 { 3277 hr = ScriptStringOut(ssa, X, Y, Options, &rc, MinSel, MaxSel, Disabled); 3278 ok(hr == S_OK, "ScriptStringOut should return S_OK not %08x\n", hr); 3279 } 3280 3281 clip_len = ScriptString_pcOutChars(ssa); 3282 ok(*clip_len == len, "ScriptString_pcOutChars failed, got %d, expected %d\n", *clip_len, len); 3283 3284 order = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *clip_len * sizeof(UINT)); 3285 hr = ScriptStringGetOrder(ssa, order); 3286 ok(hr == S_OK, "ScriptStringGetOrder failed, got %08x, expected S_OK\n", hr); 3287 3288 for (i = 0; i < *clip_len; i++) ok(order[i] == i, "%d: got %d expected %d\n", i, order[i], i); 3289 HeapFree(GetProcessHeap(), 0, order); 3290 3291 hr = ScriptStringFree(&ssa); 3292 ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); 3293 } 3294 3295 static void test_ScriptStringXtoCP_CPtoX(HDC hdc) 3296 { 3297 /***************************************************************************************** 3298 * 3299 * This test is for the ScriptStringXtoCP and ScriptStringXtoCP functions. Due to the 3300 * nature of the fonts between Windows and Wine, the test is implemented by generating 3301 * values using one one function then checking the output of the second. In this way 3302 * the validity of the functions is established using Windows as a base and confirming 3303 * similar behaviour in wine. 3304 */ 3305 3306 HRESULT hr; 3307 static const WCHAR teststr1[] = {0x05e9, 'i', 0x05dc, 'n', 0x05d5, 'e', 0x05dd, '.',0}; 3308 static const BOOL rtl[] = {1, 0, 1, 0, 1, 0, 1, 0}; 3309 void *String = (WCHAR *) &teststr1; /* ScriptStringAnalysis needs void */ 3310 int String_len = (sizeof(teststr1)/sizeof(WCHAR))-1; 3311 int Glyphs = String_len * 2 + 16; /* size of buffer as recommended */ 3312 int Charset = -1; /* unicode */ 3313 DWORD Flags = SSA_GLYPHS; 3314 int ReqWidth = 100; 3315 static const BYTE InClass[(sizeof(teststr1)/sizeof(WCHAR))-1]; 3316 SCRIPT_STRING_ANALYSIS ssa = NULL; 3317 3318 int Ch; /* Character position in string */ 3319 int iTrailing; 3320 int Cp; /* Character position in string */ 3321 int X; 3322 int trail,lead; 3323 BOOL fTrailing; 3324 3325 /* Test with hdc, this should be a valid test 3326 * Here we generate an SCRIPT_STRING_ANALYSIS that will be used as input to the 3327 * following character positions to X and X to character position functions. 3328 */ 3329 3330 hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, 3331 ReqWidth, NULL, NULL, NULL, NULL, 3332 InClass, &ssa); 3333 ok(hr == S_OK || 3334 hr == E_INVALIDARG, /* NT */ 3335 "ScriptStringAnalyse should return S_OK or E_INVALIDARG not %08x\n", hr); 3336 3337 if (hr == S_OK) 3338 { 3339 ok(ssa != NULL, "ScriptStringAnalyse ssa should not be NULL\n"); 3340 3341 /* 3342 * Loop to generate character positions to provide starting positions for the 3343 * ScriptStringCPtoX and ScriptStringXtoCP functions 3344 */ 3345 for (Cp = 0; Cp < String_len; Cp++) 3346 { 3347 /* The fTrailing flag is used to indicate whether the X being returned is at 3348 * the beginning or the end of the character. What happens here is that if 3349 * fTrailing indicates the end of the character, ie. FALSE, then ScriptStringXtoCP 3350 * returns the beginning of the next character and iTrailing is FALSE. So for this 3351 * loop iTrailing will be FALSE in both cases. 3352 */ 3353 hr = ScriptStringCPtoX(ssa, Cp, TRUE, &trail); 3354 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3355 hr = ScriptStringCPtoX(ssa, Cp, FALSE, &lead); 3356 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3357 if (rtl[Cp]) 3358 ok(lead > trail, "Leading values should be after trailing for rtl characters(%i)\n",Cp); 3359 else 3360 ok(lead < trail, "Trailing values should be after leading for ltr characters(%i)\n",Cp); 3361 3362 /* move by 1 pixel so that we are not between 2 characters. That could result in being the lead of a rtl and 3363 at the same time the trail of an ltr */ 3364 3365 /* inside the leading edge */ 3366 X = lead; 3367 if (rtl[Cp]) X--; else X++; 3368 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3369 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3370 ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, trail); 3371 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3372 iTrailing, X); 3373 3374 /* inside the trailing edge */ 3375 X = trail; 3376 if (rtl[Cp]) X++; else X--; 3377 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3378 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3379 ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, trail); 3380 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3381 iTrailing, X); 3382 3383 /* outside the "trailing" edge */ 3384 if (Cp < String_len-1) 3385 { 3386 if (rtl[Cp]) X = lead; else X = trail; 3387 X++; 3388 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3389 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3390 ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, trail); 3391 if (rtl[Cp+1]) 3392 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3393 iTrailing, X); 3394 else 3395 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3396 iTrailing, X); 3397 } 3398 3399 /* outside the "leading" edge */ 3400 if (Cp != 0) 3401 { 3402 if (rtl[Cp]) X = trail; else X = lead; 3403 X--; 3404 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3405 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3406 ok(Cp - 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp - 1, Ch, trail); 3407 if (Cp != 0 && rtl[Cp-1]) 3408 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3409 iTrailing, X); 3410 else 3411 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3412 iTrailing, X); 3413 } 3414 } 3415 3416 /* Check beyond the leading boundary of the whole string */ 3417 if (rtl[0]) 3418 { 3419 /* having a leading rtl character seems to confuse usp */ 3420 /* this looks to be a windows bug we should emulate */ 3421 hr = ScriptStringCPtoX(ssa, 0, TRUE, &X); 3422 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3423 X--; 3424 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3425 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3426 ok(Ch == 1, "ScriptStringXtoCP should return Ch = 1 not %d for X outside leading edge when rtl\n", Ch); 3427 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside leading edge when rtl\n", 3428 iTrailing); 3429 } 3430 else 3431 { 3432 hr = ScriptStringCPtoX(ssa, 0, FALSE, &X); 3433 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3434 X--; 3435 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3436 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3437 ok(Ch == -1, "ScriptStringXtoCP should return Ch = -1 not %d for X outside leading edge\n", Ch); 3438 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = outside leading edge\n", 3439 iTrailing); 3440 } 3441 3442 /* Check beyond the end boundary of the whole string */ 3443 if (rtl[String_len-1]) 3444 { 3445 hr = ScriptStringCPtoX(ssa, String_len-1, FALSE, &X); 3446 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3447 } 3448 else 3449 { 3450 hr = ScriptStringCPtoX(ssa, String_len-1, TRUE, &X); 3451 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3452 } 3453 X++; 3454 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3455 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3456 ok(Ch == String_len, "ScriptStringXtoCP should return Ch = %i not %d for X outside trailing edge\n", String_len, Ch); 3457 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside trailing edge\n", 3458 iTrailing); 3459 3460 /* 3461 * Cleanup the SSA for the next round of tests 3462 */ 3463 hr = ScriptStringFree(&ssa); 3464 ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); 3465 3466 /* 3467 * Test to see that exceeding the number of chars returns E_INVALIDARG. First 3468 * generate an SSA for the subsequent tests. 3469 */ 3470 hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, 3471 ReqWidth, NULL, NULL, NULL, NULL, 3472 InClass, &ssa); 3473 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3474 3475 /* 3476 * When ScriptStringCPtoX is called with a character position Cp that exceeds the 3477 * string length, return E_INVALIDARG. This also invalidates the ssa so a 3478 * ScriptStringFree should also fail. 3479 */ 3480 fTrailing = FALSE; 3481 Cp = String_len + 1; 3482 hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); 3483 ok(hr == E_INVALIDARG, "ScriptStringCPtoX should return E_INVALIDARG not %08x\n", hr); 3484 3485 ScriptStringFree(&ssa); 3486 } 3487 } 3488 3489 static HWND create_test_window(void) 3490 { 3491 HWND hwnd = CreateWindowExA(0, "Static", "", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL); 3492 ok(hwnd != NULL, "Failed to create test window.\n"); 3493 3494 ShowWindow(hwnd, SW_SHOW); 3495 UpdateWindow(hwnd); 3496 3497 return hwnd; 3498 } 3499 3500 static void test_ScriptCacheGetHeight(HDC hdc) 3501 { 3502 HFONT hfont, prev_hfont; 3503 SCRIPT_CACHE sc = NULL; 3504 LONG height, height2; 3505 TEXTMETRICW tm; 3506 LOGFONTA lf; 3507 HRESULT hr; 3508 HWND hwnd; 3509 HDC hdc2; 3510 3511 hr = ScriptCacheGetHeight(NULL, NULL, NULL); 3512 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3513 3514 hr = ScriptCacheGetHeight(NULL, &sc, NULL); 3515 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3516 3517 hr = ScriptCacheGetHeight(NULL, &sc, &height); 3518 ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr); 3519 3520 height = 123; 3521 hr = ScriptCacheGetHeight(hdc, NULL, &height); 3522 ok(hr == E_INVALIDARG, "Uexpected hr %#x.\n", hr); 3523 ok(height == 123, "Unexpected height.\n"); 3524 3525 memset(&tm, 0, sizeof(tm)); 3526 GetTextMetricsW(hdc, &tm); 3527 ok(tm.tmHeight > 0, "Unexpected tmHeight %u.\n", tm.tmHeight); 3528 3529 height = 0; 3530 hr = ScriptCacheGetHeight(hdc, &sc, &height); 3531 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3532 ok(height == tm.tmHeight, "expected height > 0\n"); 3533 3534 /* Try again with NULL dc. */ 3535 height2 = 0; 3536 hr = ScriptCacheGetHeight(NULL, &sc, &height2); 3537 ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr); 3538 ok(height2 == height, "Unexpected height %u.\n", height2); 3539 3540 hwnd = create_test_window(); 3541 3542 hdc2 = GetDC(hwnd); 3543 ok(hdc2 != NULL, "Failed to get window dc.\n"); 3544 3545 memset(&lf, 0, sizeof(LOGFONTA)); 3546 lstrcpyA(lf.lfFaceName, "Tahoma"); 3547 lf.lfHeight = -32; 3548 3549 hfont = CreateFontIndirectA(&lf); 3550 ok(hfont != NULL, "Failed to create font.\n"); 3551 3552 prev_hfont = SelectObject(hdc2, hfont); 3553 3554 memset(&tm, 0, sizeof(tm)); 3555 GetTextMetricsW(hdc2, &tm); 3556 ok(tm.tmHeight > height, "Unexpected tmHeight %u.\n", tm.tmHeight); 3557 3558 height2 = 0; 3559 hr = ScriptCacheGetHeight(hdc2, &sc, &height2); 3560 ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr); 3561 ok(height2 == height, "Unexpected height.\n"); 3562 3563 SelectObject(hdc2, prev_hfont); 3564 DeleteObject(hfont); 3565 3566 ReleaseDC(hwnd, hdc2); 3567 DestroyWindow(hwnd); 3568 3569 ScriptFreeCache(&sc); 3570 } 3571 3572 static void test_ScriptGetGlyphABCWidth(HDC hdc) 3573 { 3574 HRESULT hr; 3575 SCRIPT_CACHE sc = NULL; 3576 ABC abc; 3577 3578 hr = ScriptGetGlyphABCWidth(NULL, NULL, 'a', NULL); 3579 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3580 3581 hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', NULL); 3582 ok(broken(hr == E_PENDING) || 3583 hr == E_INVALIDARG, /* WIN7 */ 3584 "expected E_INVALIDARG, got 0x%08x\n", hr); 3585 3586 hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', &abc); 3587 ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr); 3588 3589 if (0) { /* crashes on WinXP */ 3590 hr = ScriptGetGlyphABCWidth(hdc, &sc, 'a', NULL); 3591 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3592 } 3593 3594 hr = ScriptGetGlyphABCWidth(hdc, &sc, 'a', &abc); 3595 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3596 3597 ScriptFreeCache(&sc); 3598 } 3599 3600 static void test_ScriptLayout(void) 3601 { 3602 HRESULT hr; 3603 static const BYTE levels[][10] = 3604 { 3605 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 3606 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 3607 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, 3608 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, 3609 3610 { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, 3611 { 1, 1, 1, 2, 2, 2, 1, 1, 1, 1 }, 3612 { 2, 2, 2, 1, 1, 1, 2, 2, 2, 2 }, 3613 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 0 }, 3614 { 1, 1, 2, 2, 3, 3, 2, 2, 1, 1 }, 3615 3616 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 1 }, 3617 { 1, 0, 1, 2, 2, 1, 2, 1, 0, 1 }, 3618 3619 { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, 3620 { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0 }, 3621 { 2, 2, 2, 4, 4, 4, 1, 1, 0, 0 }, 3622 { 1, 2, 3, 0, 3, 2, 1, 0, 0, 0 } 3623 }; 3624 static const int expect_l2v[][10] = 3625 { 3626 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3627 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3628 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3629 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3630 3631 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5}, 3632 /**/ { 9, 8, 7, 4, 5, 6, 3 ,2 ,1, 0}, 3633 /**/ { 7, 8, 9, 6, 5, 4, 0 ,1 ,2, 3}, 3634 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3635 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0}, 3636 3637 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3638 /**/ { 0, 1, 7, 5, 6, 4, 3 ,2 ,8, 9}, 3639 3640 { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, 3641 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3642 { 2, 3, 4, 5, 6, 7, 1, 0, 8, 9}, 3643 { 2, 0, 1, 3, 5, 6, 4, 7, 8, 9} 3644 }; 3645 static const int expect_v2l[][10] = 3646 { 3647 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3648 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3649 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3650 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3651 3652 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5}, 3653 { 9, 8, 7, 6, 3, 4, 5 ,2 ,1, 0}, 3654 { 6, 7, 8, 9, 5, 4, 3 ,0 ,1, 2}, 3655 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3656 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0}, 3657 3658 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3659 { 0, 1, 7, 6, 5, 3, 4 ,2 ,8, 9}, 3660 3661 { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, 3662 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3663 { 7, 6, 0, 1, 2, 3, 4, 5, 8, 9}, 3664 { 1, 2, 0, 3, 6, 4, 5, 7, 8, 9} 3665 }; 3666 3667 int i, j, vistolog[sizeof(levels[0])], logtovis[sizeof(levels[0])]; 3668 3669 hr = ScriptLayout(sizeof(levels[0]), NULL, vistolog, logtovis); 3670 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3671 3672 hr = ScriptLayout(sizeof(levels[0]), levels[0], NULL, NULL); 3673 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3674 3675 for (i = 0; i < sizeof(levels)/sizeof(levels[0]); i++) 3676 { 3677 hr = ScriptLayout(sizeof(levels[0]), levels[i], vistolog, logtovis); 3678 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3679 3680 for (j = 0; j < sizeof(levels[i]); j++) 3681 { 3682 ok(expect_v2l[i][j] == vistolog[j], 3683 "failure: levels[%d][%d] = %d, vistolog[%d] = %d\n", 3684 i, j, levels[i][j], j, vistolog[j] ); 3685 } 3686 3687 for (j = 0; j < sizeof(levels[i]); j++) 3688 { 3689 ok(expect_l2v[i][j] == logtovis[j], 3690 "failure: levels[%d][%d] = %d, logtovis[%d] = %d\n", 3691 i, j, levels[i][j], j, logtovis[j] ); 3692 } 3693 } 3694 } 3695 3696 static BOOL CALLBACK enum_proc(LGRPID group, LCID lcid, LPSTR locale, LONG_PTR lparam) 3697 { 3698 HRESULT hr; 3699 SCRIPT_DIGITSUBSTITUTE sds; 3700 SCRIPT_CONTROL sc; 3701 SCRIPT_STATE ss; 3702 LCID lcid_old; 3703 3704 if (!IsValidLocale(lcid, LCID_INSTALLED)) return TRUE; 3705 3706 memset(&sds, 0, sizeof(sds)); 3707 memset(&sc, 0, sizeof(sc)); 3708 memset(&ss, 0, sizeof(ss)); 3709 3710 lcid_old = GetThreadLocale(); 3711 if (!SetThreadLocale(lcid)) return TRUE; 3712 3713 hr = ScriptRecordDigitSubstitution(lcid, &sds); 3714 ok(hr == S_OK, "ScriptRecordDigitSubstitution failed: 0x%08x\n", hr); 3715 3716 hr = ScriptApplyDigitSubstitution(&sds, &sc, &ss); 3717 ok(hr == S_OK, "ScriptApplyDigitSubstitution failed: 0x%08x\n", hr); 3718 3719 SetThreadLocale(lcid_old); 3720 return TRUE; 3721 } 3722 3723 static void test_digit_substitution(void) 3724 { 3725 BOOL ret; 3726 unsigned int i; 3727 static const LGRPID groups[] = 3728 { 3729 LGRPID_WESTERN_EUROPE, 3730 LGRPID_CENTRAL_EUROPE, 3731 LGRPID_BALTIC, 3732 LGRPID_GREEK, 3733 LGRPID_CYRILLIC, 3734 LGRPID_TURKISH, 3735 LGRPID_JAPANESE, 3736 LGRPID_KOREAN, 3737 LGRPID_TRADITIONAL_CHINESE, 3738 LGRPID_SIMPLIFIED_CHINESE, 3739 LGRPID_THAI, 3740 LGRPID_HEBREW, 3741 LGRPID_ARABIC, 3742 LGRPID_VIETNAMESE, 3743 LGRPID_INDIC, 3744 LGRPID_GEORGIAN, 3745 LGRPID_ARMENIAN 3746 }; 3747 3748 for (i = 0; i < sizeof(groups)/sizeof(groups[0]); i++) 3749 { 3750 ret = EnumLanguageGroupLocalesA(enum_proc, groups[i], 0, 0); 3751 ok(ret, "EnumLanguageGroupLocalesA failed unexpectedly: %u\n", GetLastError()); 3752 } 3753 } 3754 3755 static void test_ScriptGetProperties(void) 3756 { 3757 const SCRIPT_PROPERTIES **props; 3758 HRESULT hr; 3759 int num; 3760 3761 hr = ScriptGetProperties(NULL, NULL); 3762 ok(hr == E_INVALIDARG, "ScriptGetProperties succeeded\n"); 3763 3764 hr = ScriptGetProperties(NULL, &num); 3765 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3766 3767 hr = ScriptGetProperties(&props, NULL); 3768 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3769 3770 hr = ScriptGetProperties(&props, &num); 3771 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3772 } 3773 3774 static void test_ScriptBreak(void) 3775 { 3776 static const WCHAR test[] = {' ','\r','\n',0}; 3777 SCRIPT_ITEM items[4]; 3778 SCRIPT_LOGATTR la; 3779 HRESULT hr; 3780 3781 hr = ScriptItemize(test, 3, 4, NULL, NULL, items, NULL); 3782 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 3783 3784 /* 3785 * This Test crashes pre Vista. 3786 3787 hr = ScriptBreak(test, 1, &items[0].a, NULL); 3788 ok(hr == E_INVALIDARG, "ScriptBreak should return E_INVALIDARG not %08x\n", hr); 3789 */ 3790 3791 hr = ScriptBreak(test, 0, &items[0].a, &la); 3792 ok(hr == E_FAIL || broken(hr == S_OK), "ScriptBreak should return E_FAIL not %08x\n", hr); 3793 3794 hr = ScriptBreak(test, -1, &items[0].a, &la); 3795 ok(hr == E_INVALIDARG || broken(hr == S_OK), "ScriptBreak should return E_INVALIDARG not %08x\n", hr); 3796 3797 memset(&la, 0, sizeof(la)); 3798 hr = ScriptBreak(test, 1, &items[0].a, &la); 3799 ok(hr == S_OK, "ScriptBreak should return S_OK not %08x\n", hr); 3800 3801 ok(!la.fSoftBreak, "fSoftBreak set\n"); 3802 ok(la.fWhiteSpace, "fWhiteSpace not set\n"); 3803 ok(la.fCharStop, "fCharStop not set\n"); 3804 ok(!la.fWordStop, "fWordStop set\n"); 3805 ok(!la.fInvalid, "fInvalid set\n"); 3806 ok(!la.fReserved, "fReserved set\n"); 3807 3808 memset(&la, 0, sizeof(la)); 3809 hr = ScriptBreak(test + 1, 1, &items[1].a, &la); 3810 ok(hr == S_OK, "ScriptBreak should return S_OK not %08x\n", hr); 3811 3812 ok(!la.fSoftBreak, "fSoftBreak set\n"); 3813 ok(!la.fWhiteSpace, "fWhiteSpace set\n"); 3814 ok(la.fCharStop, "fCharStop not set\n"); 3815 ok(!la.fWordStop, "fWordStop set\n"); 3816 ok(!la.fInvalid, "fInvalid set\n"); 3817 ok(!la.fReserved, "fReserved set\n"); 3818 3819 memset(&la, 0, sizeof(la)); 3820 hr = ScriptBreak(test + 2, 1, &items[2].a, &la); 3821 ok(hr == S_OK, "ScriptBreak should return S_OK not %08x\n", hr); 3822 3823 ok(!la.fSoftBreak, "fSoftBreak set\n"); 3824 ok(!la.fWhiteSpace, "fWhiteSpace set\n"); 3825 ok(la.fCharStop, "fCharStop not set\n"); 3826 ok(!la.fWordStop, "fWordStop set\n"); 3827 ok(!la.fInvalid, "fInvalid set\n"); 3828 ok(!la.fReserved, "fReserved set\n"); 3829 } 3830 3831 static void test_newlines(void) 3832 { 3833 static const WCHAR test1[] = {'t','e','x','t','\r','t','e','x','t',0}; 3834 static const WCHAR test2[] = {'t','e','x','t','\n','t','e','x','t',0}; 3835 static const WCHAR test3[] = {'t','e','x','t','\r','\n','t','e','x','t',0}; 3836 static const WCHAR test4[] = {'t','e','x','t','\n','\r','t','e','x','t',0}; 3837 static const WCHAR test5[] = {'1','2','3','4','\n','\r','1','2','3','4',0}; 3838 SCRIPT_ITEM items[5]; 3839 HRESULT hr; 3840 int count; 3841 3842 count = 0; 3843 hr = ScriptItemize(test1, lstrlenW(test1), 5, NULL, NULL, items, &count); 3844 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3845 ok(count == 3, "got %d expected 3\n", count); 3846 3847 count = 0; 3848 hr = ScriptItemize(test2, lstrlenW(test2), 5, NULL, NULL, items, &count); 3849 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3850 ok(count == 3, "got %d expected 3\n", count); 3851 3852 count = 0; 3853 hr = ScriptItemize(test3, lstrlenW(test3), 5, NULL, NULL, items, &count); 3854 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3855 ok(count == 4, "got %d expected 4\n", count); 3856 3857 count = 0; 3858 hr = ScriptItemize(test4, lstrlenW(test4), 5, NULL, NULL, items, &count); 3859 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3860 ok(count == 4, "got %d expected 4\n", count); 3861 3862 count = 0; 3863 hr = ScriptItemize(test5, lstrlenW(test5), 5, NULL, NULL, items, &count); 3864 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3865 ok(count == 4, "got %d expected 4\n", count); 3866 } 3867 3868 static void test_ScriptGetFontFunctions(HDC hdc) 3869 { 3870 HRESULT hr; 3871 if (!pScriptGetFontScriptTags || !pScriptGetFontLanguageTags || !pScriptGetFontFeatureTags) 3872 { 3873 win_skip("ScriptGetFontScriptTags,ScriptGetFontLanguageTags or ScriptGetFontFeatureTags not available on this platform\n"); 3874 } 3875 else 3876 { 3877 SCRIPT_CACHE sc = NULL; 3878 OPENTYPE_TAG tags[5]; 3879 int count = 0; 3880 int outnItems=0; 3881 SCRIPT_ITEM outpItems[15]; 3882 SCRIPT_CONTROL Control; 3883 SCRIPT_STATE State; 3884 static const WCHAR test_phagspa[] = {0xa84f, 0xa861, 0xa843, 0x0020, 0xa863, 0xa861, 0xa859, 0x0020, 0xa850, 0xa85c, 0xa85e}; 3885 3886 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, NULL); 3887 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3888 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3889 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, &count); 3890 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3891 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3892 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, NULL); 3893 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3894 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3895 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, tags, &count); 3896 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3897 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3898 hr = pScriptGetFontScriptTags(NULL, &sc, NULL, 5, tags, &count); 3899 ok(hr == E_PENDING,"Incorrect return code\n"); 3900 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3901 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, &count); 3902 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3903 if (hr == S_OK) 3904 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3905 else if (hr == E_OUTOFMEMORY) 3906 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3907 ok(sc != NULL, "ScriptCache should be initialized\n"); 3908 3909 ScriptFreeCache(&sc); 3910 sc = NULL; 3911 3912 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, NULL, NULL); 3913 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3914 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3915 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, NULL, &count); 3916 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3917 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3918 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 5, tags, NULL); 3919 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3920 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3921 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, tags, &count); 3922 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3923 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3924 hr = pScriptGetFontLanguageTags(NULL, &sc, NULL, latn_tag, 5, tags, &count); 3925 ok(hr == E_PENDING,"Incorrect return code\n"); 3926 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3927 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 5, tags, &count); 3928 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3929 if (hr == S_OK) 3930 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3931 else if (hr == E_OUTOFMEMORY) 3932 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3933 3934 ScriptFreeCache(&sc); 3935 sc = NULL; 3936 3937 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, NULL); 3938 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3939 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3940 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, &count); 3941 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3942 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3943 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 5, tags, NULL); 3944 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3945 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3946 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, tags, &count); 3947 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3948 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3949 hr = pScriptGetFontFeatureTags(NULL, &sc, NULL, latn_tag, 0x0, 5, tags, &count); 3950 ok(hr == E_PENDING,"Incorrect return code\n"); 3951 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3952 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 5, tags, &count); 3953 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3954 if (hr == S_OK) 3955 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3956 else if (hr == E_OUTOFMEMORY) 3957 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3958 3959 memset(&Control, 0, sizeof(Control)); 3960 memset(&State, 0, sizeof(State)); 3961 3962 hr = ScriptItemize(test_phagspa, 10, 15, &Control, &State, outpItems, &outnItems); 3963 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3964 memset(tags,0,sizeof(tags)); 3965 hr = pScriptGetFontScriptTags(hdc, &sc, &outpItems[0].a, 5, tags, &count); 3966 ok( hr == USP_E_SCRIPT_NOT_IN_FONT || broken(hr == S_OK), "wrong return code\n"); 3967 3968 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, dsrt_tag, 5, tags, &count); 3969 ok( hr == S_OK, "wrong return code\n"); 3970 hr = pScriptGetFontLanguageTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 5, tags, &count); 3971 ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n"); 3972 3973 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, dsrt_tag, 0x0, 5, tags, &count); 3974 ok( hr == S_OK, "wrong return code\n"); 3975 hr = pScriptGetFontFeatureTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 0x0, 5, tags, &count); 3976 ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n"); 3977 3978 ScriptFreeCache(&sc); 3979 } 3980 } 3981 3982 struct logical_width_test 3983 { 3984 int char_count; 3985 int glyph_count; 3986 int advances[3]; 3987 WORD map[3]; 3988 int widths[3]; 3989 BOOL clusterstart[3]; 3990 BOOL diacritic[3]; 3991 BOOL zerowidth[3]; 3992 BOOL todo; 3993 }; 3994 3995 static const struct logical_width_test logical_width_tests[] = 3996 { 3997 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 } }, 3998 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 }, { 1, 0, 0 } }, 3999 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 }, { 0 }, { 1, 1, 1 } }, 4000 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 27, 21, 12 }, { 0, 0, 0 }, { 0 }, { 0 }, TRUE }, 4001 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 21, 12 }, { 0, 1, 0 }, { 0 }, { 0 }, TRUE }, 4002 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 21, 12 }, { 1, 1, 0 }, { 0 }, { 0 }, TRUE }, 4003 { 3, 3, { 6, 9, 12 }, { 0, 2, 2 }, { 15, 6, 6 }, { 1, 0, 1 } }, 4004 }; 4005 4006 static void test_ScriptGetLogicalWidths(void) 4007 { 4008 SCRIPT_ANALYSIS sa = { 0 }; 4009 unsigned int i, j; 4010 4011 for (i = 0; i < sizeof(logical_width_tests)/sizeof(logical_width_tests[0]); i++) 4012 { 4013 const struct logical_width_test *ptr = logical_width_tests + i; 4014 SCRIPT_VISATTR attrs[3]; 4015 int widths[3]; 4016 HRESULT hr; 4017 4018 memset(attrs, 0, sizeof(attrs)); 4019 for (j = 0; j < ptr->glyph_count; j++) 4020 { 4021 attrs[j].fClusterStart = ptr->clusterstart[j]; 4022 attrs[j].fDiacritic = ptr->diacritic[j]; 4023 attrs[j].fZeroWidth = ptr->zerowidth[j]; 4024 } 4025 4026 hr = ScriptGetLogicalWidths(&sa, ptr->char_count, ptr->glyph_count, ptr->advances, ptr->map, attrs, widths); 4027 ok(hr == S_OK, "got 0x%08x\n", hr); 4028 4029 todo_wine_if(ptr->todo) 4030 ok(!memcmp(ptr->widths, widths, sizeof(widths)), "test %u: got wrong widths\n", i); 4031 } 4032 } 4033 4034 static void test_ScriptIsComplex(void) 4035 { 4036 static const WCHAR testW[] = {0x202a,'1',0x202c,0}; 4037 static const WCHAR test2W[] = {'1',0}; 4038 static const struct complex_test 4039 { 4040 const WCHAR *text; 4041 DWORD flags; 4042 HRESULT hr; 4043 BOOL todo; 4044 } complex_tests[] = 4045 { 4046 { test2W, SIC_ASCIIDIGIT, S_OK }, 4047 { test2W, SIC_COMPLEX, S_FALSE }, 4048 { test2W, SIC_COMPLEX | SIC_ASCIIDIGIT, S_OK }, 4049 { testW, SIC_NEUTRAL | SIC_COMPLEX, S_OK }, 4050 { testW, SIC_NEUTRAL, S_FALSE, TRUE }, 4051 { testW, SIC_COMPLEX, S_OK }, 4052 { testW, 0, S_FALSE }, 4053 }; 4054 unsigned int i; 4055 HRESULT hr; 4056 4057 hr = ScriptIsComplex(NULL, 0, 0); 4058 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* winxp/vista */, "got 0x%08x\n", hr); 4059 4060 if (hr == E_INVALIDARG) 4061 { 4062 hr = ScriptIsComplex(NULL, 1, 0); 4063 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 4064 } 4065 4066 hr = ScriptIsComplex(test2W, -1, SIC_ASCIIDIGIT); 4067 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* winxp/vista */, "got 0x%08x\n", hr); 4068 4069 hr = ScriptIsComplex(test2W, 0, SIC_ASCIIDIGIT); 4070 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4071 4072 for (i = 0; i < sizeof(complex_tests)/sizeof(complex_tests[0]); i++) 4073 { 4074 hr = ScriptIsComplex(complex_tests[i].text, lstrlenW(complex_tests[i].text), complex_tests[i].flags); 4075 todo_wine_if(complex_tests[i].todo) 4076 ok(hr == complex_tests[i].hr, "%u: got %#x, expected %#x, flags %#x\n", i, hr, complex_tests[i].hr, 4077 complex_tests[i].flags); 4078 } 4079 4080 hr = ScriptIsComplex(test2W, 1, ~0u); 4081 ok(hr == S_OK, "got 0x%08x\n", hr); 4082 4083 hr = ScriptIsComplex(testW, 3, 0); 4084 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4085 4086 hr = ScriptIsComplex(testW, 3, SIC_NEUTRAL | SIC_COMPLEX); 4087 ok(hr == S_OK, "got 0x%08x\n", hr); 4088 4089 hr = ScriptIsComplex(testW, 3, SIC_COMPLEX); 4090 ok(hr == S_OK, "got 0x%08x\n", hr); 4091 4092 hr = ScriptIsComplex(test2W, 1, SIC_COMPLEX); 4093 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4094 } 4095 4096 static void test_ScriptString_pSize(HDC hdc) 4097 { 4098 static const WCHAR textW[] = {'A',0}; 4099 SCRIPT_STRING_ANALYSIS ssa; 4100 const SIZE *size; 4101 TEXTMETRICW tm; 4102 HRESULT hr; 4103 ABC abc; 4104 4105 hr = ScriptStringAnalyse(hdc, textW, 1, 16, -1, SSA_GLYPHS, 0, NULL, NULL, NULL, NULL, NULL, &ssa); 4106 ok(hr == S_OK, "ScriptStringAnalyse failed, hr %#x.\n", hr); 4107 4108 size = ScriptString_pSize(NULL); 4109 ok(size == NULL || broken(size != NULL) /* <win7 */, "Unexpected size pointer.\n"); 4110 4111 GetCharABCWidthsW(hdc, textW[0], textW[0], &abc); 4112 4113 memset(&tm, 0, sizeof(tm)); 4114 GetTextMetricsW(hdc, &tm); 4115 ok(tm.tmHeight > 0, "Unexpected tmHeight.\n"); 4116 4117 size = ScriptString_pSize(ssa); 4118 ok(size != NULL, "Unexpected size pointer.\n"); 4119 ok(size->cx == abc.abcA + abc.abcB + abc.abcC, "Unexpected cx size %d.\n", size->cx); 4120 ok(size->cy == tm.tmHeight, "Unexpected cy size %d.\n", size->cy); 4121 4122 hr = ScriptStringFree(&ssa); 4123 ok(hr == S_OK, "Failed to free ssa, hr %#x.\n", hr); 4124 } 4125 4126 static void test_script_cache_reuse(void) 4127 { 4128 HRESULT hr; 4129 HWND hwnd1, hwnd2; 4130 HDC hdc1, hdc2; 4131 LOGFONTA lf; 4132 HFONT hfont1, hfont2; 4133 HFONT prev_hfont1, prev_hfont2; 4134 SCRIPT_CACHE sc = NULL; 4135 SCRIPT_CACHE sc2; 4136 LONG height; 4137 4138 hwnd1 = create_test_window(); 4139 hwnd2 = create_test_window(); 4140 4141 hdc1 = GetDC(hwnd1); 4142 hdc2 = GetDC(hwnd2); 4143 ok(hdc1 != NULL && hdc2 != NULL, "Failed to get window dc.\n"); 4144 4145 memset(&lf, 0, sizeof(LOGFONTA)); 4146 lstrcpyA(lf.lfFaceName, "Tahoma"); 4147 4148 lf.lfHeight = 10; 4149 hfont1 = CreateFontIndirectA(&lf); 4150 ok(hfont1 != NULL, "CreateFontIndirectA failed\n"); 4151 hfont2 = CreateFontIndirectA(&lf); 4152 ok(hfont2 != NULL, "CreateFontIndirectA failed\n"); 4153 ok(hfont1 != hfont2, "Expected fonts %p and %p to differ\n", hfont1, hfont2); 4154 4155 prev_hfont1 = SelectObject(hdc1, hfont1); 4156 ok(prev_hfont1 != NULL, "SelectObject failed: %p\n", prev_hfont1); 4157 prev_hfont2 = SelectObject(hdc2, hfont1); 4158 ok(prev_hfont2 != NULL, "SelectObject failed: %p\n", prev_hfont2); 4159 4160 /* Get a script cache */ 4161 hr = ScriptCacheGetHeight(hdc1, &sc, &height); 4162 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4163 ok(sc != NULL, "Script cache is NULL\n"); 4164 4165 /* Same font, same DC -> same SCRIPT_CACHE */ 4166 sc2 = NULL; 4167 hr = ScriptCacheGetHeight(hdc1, &sc2, &height); 4168 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4169 ok(sc2 != NULL, "Script cache is NULL\n"); 4170 ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); 4171 ScriptFreeCache(&sc2); 4172 4173 /* Same font in different DC -> same SCRIPT_CACHE */ 4174 sc2 = NULL; 4175 hr = ScriptCacheGetHeight(hdc2, &sc2, &height); 4176 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4177 ok(sc2 != NULL, "Script cache is NULL\n"); 4178 ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); 4179 ScriptFreeCache(&sc2); 4180 4181 /* Same font face & size, but different font handle */ 4182 ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n"); 4183 ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n"); 4184 4185 sc2 = NULL; 4186 hr = ScriptCacheGetHeight(hdc1, &sc2, &height); 4187 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4188 ok(sc2 != NULL, "Script cache is NULL\n"); 4189 ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); 4190 ScriptFreeCache(&sc2); 4191 4192 sc2 = NULL; 4193 hr = ScriptCacheGetHeight(hdc2, &sc2, &height); 4194 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4195 ok(sc2 != NULL, "Script cache is NULL\n"); 4196 ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); 4197 ScriptFreeCache(&sc2); 4198 4199 /* Different font size -- now we get a different SCRIPT_CACHE */ 4200 SelectObject(hdc1, prev_hfont1); 4201 SelectObject(hdc2, prev_hfont2); 4202 DeleteObject(hfont2); 4203 lf.lfHeight = 20; 4204 hfont2 = CreateFontIndirectA(&lf); 4205 ok(hfont2 != NULL, "CreateFontIndirectA failed\n"); 4206 ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n"); 4207 ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n"); 4208 4209 sc2 = NULL; 4210 hr = ScriptCacheGetHeight(hdc1, &sc2, &height); 4211 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4212 ok(sc2 != NULL, "Script cache is NULL\n"); 4213 ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2); 4214 ScriptFreeCache(&sc2); 4215 4216 sc2 = NULL; 4217 hr = ScriptCacheGetHeight(hdc2, &sc2, &height); 4218 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 4219 ok(sc2 != NULL, "Script cache is NULL\n"); 4220 ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2); 4221 ScriptFreeCache(&sc2); 4222 4223 ScriptFreeCache(&sc); 4224 SelectObject(hdc1, prev_hfont1); 4225 SelectObject(hdc2, prev_hfont2); 4226 DeleteObject(hfont1); 4227 DeleteObject(hfont2); 4228 DestroyWindow(hwnd1); 4229 DestroyWindow(hwnd2); 4230 } 4231 4232 static void init_tests(void) 4233 { 4234 HMODULE module = GetModuleHandleA("usp10.dll"); 4235 4236 ok(module != 0, "Expected usp10.dll to be loaded.\n"); 4237 4238 pScriptItemizeOpenType = (void *)GetProcAddress(module, "ScriptItemizeOpenType"); 4239 pScriptShapeOpenType = (void *)GetProcAddress(module, "ScriptShapeOpenType"); 4240 pScriptGetFontScriptTags = (void *)GetProcAddress(module, "ScriptGetFontScriptTags"); 4241 pScriptGetFontLanguageTags = (void *)GetProcAddress(module, "ScriptGetFontLanguageTags"); 4242 pScriptGetFontFeatureTags = (void *)GetProcAddress(module, "ScriptGetFontFeatureTags"); 4243 } 4244 4245 START_TEST(usp10) 4246 { 4247 HWND hwnd; 4248 HDC hdc; 4249 LOGFONTA lf; 4250 HFONT hfont; 4251 4252 unsigned short pwOutGlyphs[256]; 4253 4254 /* We need a valid HDC to drive a lot of Script functions which requires the following * 4255 * to set up for the tests. */ 4256 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100, 4257 0, 0, 0, NULL); 4258 assert(hwnd != 0); 4259 ShowWindow(hwnd, SW_SHOW); 4260 UpdateWindow(hwnd); 4261 4262 hdc = GetDC(hwnd); /* We now have a hdc */ 4263 ok( hdc != NULL, "HDC failed to be created %p\n", hdc); 4264 4265 memset(&lf, 0, sizeof(LOGFONTA)); 4266 lstrcpyA(lf.lfFaceName, "Tahoma"); 4267 lf.lfHeight = 10; 4268 lf.lfWeight = 3; 4269 lf.lfWidth = 10; 4270 4271 hfont = SelectObject(hdc, CreateFontIndirectA(&lf)); 4272 ok(hfont != NULL, "SelectObject failed: %p\n", hfont); 4273 4274 init_tests(); 4275 4276 test_ScriptItemize(); 4277 test_ScriptItemize_surrogates(); 4278 test_ScriptItemIzeShapePlace(hdc,pwOutGlyphs); 4279 test_ScriptGetCMap(hdc, pwOutGlyphs); 4280 test_ScriptCacheGetHeight(hdc); 4281 test_ScriptGetGlyphABCWidth(hdc); 4282 test_ScriptShape(hdc); 4283 test_ScriptShapeOpenType(hdc); 4284 test_ScriptPlace(hdc); 4285 4286 test_ScriptGetFontProperties(hdc); 4287 test_ScriptTextOut(hdc); 4288 test_ScriptTextOut2(hdc); 4289 test_ScriptTextOut3(hdc); 4290 test_ScriptXtoX(); 4291 test_ScriptString(hdc); 4292 test_ScriptStringXtoCP_CPtoX(hdc); 4293 test_ScriptString_pSize(hdc); 4294 4295 test_ScriptLayout(); 4296 test_digit_substitution(); 4297 test_ScriptGetProperties(); 4298 test_ScriptBreak(); 4299 test_newlines(); 4300 4301 test_ScriptGetFontFunctions(hdc); 4302 test_ScriptGetLogicalWidths(); 4303 4304 test_ScriptIsComplex(); 4305 test_script_cache_reuse(); 4306 4307 ReleaseDC(hwnd, hdc); 4308 DestroyWindow(hwnd); 4309 } 4310