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 WORD glyphs[4], glyphs2[4], logclust[4], glyphs3[4]; 1840 SCRIPT_VISATTR attrs[4]; 1841 SCRIPT_ITEM items[4]; 1842 int nb, i, j; 1843 1844 hr = ScriptItemize(test1, 4, 2, NULL, NULL, items, NULL); 1845 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 1846 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1847 1848 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, NULL, &nb); 1849 ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr); 1850 1851 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, NULL); 1852 ok(hr == E_INVALIDARG, "ScriptShape should return E_INVALIDARG not %08x\n", hr); 1853 1854 hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb); 1855 ok(hr == E_PENDING, "ScriptShape should return E_PENDING not %08x\n", hr); 1856 1857 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb); 1858 ok(broken(hr == S_OK) || 1859 hr == E_INVALIDARG || /* Vista, W2K8 */ 1860 hr == E_FAIL, /* WIN7 */ 1861 "ScriptShape should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 1862 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1863 1864 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 1865 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1866 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 1867 1868 1869 memset(glyphs,-1,sizeof(glyphs)); 1870 memset(logclust,-1,sizeof(logclust)); 1871 memset(attrs,-1,sizeof(attrs)); 1872 hr = ScriptShape(NULL, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 1873 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1874 ok(nb == 4, "Wrong number of items\n"); 1875 ok(logclust[0] == 0, "clusters out of order\n"); 1876 ok(logclust[1] == 1, "clusters out of order\n"); 1877 ok(logclust[2] == 2, "clusters out of order\n"); 1878 ok(logclust[3] == 3, "clusters out of order\n"); 1879 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1880 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1881 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1882 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1883 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1884 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1885 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1886 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1887 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1888 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1889 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1890 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1891 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1892 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1893 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1894 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1895 1896 ScriptFreeCache(&sc); 1897 sc = NULL; 1898 1899 memset(glyphs2,-1,sizeof(glyphs2)); 1900 memset(glyphs3,-1,sizeof(glyphs3)); 1901 memset(logclust,-1,sizeof(logclust)); 1902 memset(attrs,-1,sizeof(attrs)); 1903 1904 GetGlyphIndicesW(hdc, test2, 4, glyphs3, 0); 1905 1906 hr = ScriptShape(hdc, &sc, test2, 4, 4, &items[0].a, glyphs2, logclust, attrs, &nb); 1907 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1908 ok(nb == 4, "Wrong number of items\n"); 1909 ok(glyphs2[0] == glyphs3[0], "Incorrect glyph for 0x202B\n"); 1910 ok(glyphs2[3] == glyphs3[3], "Incorrect glyph for 0x202C\n"); 1911 ok(logclust[0] == 0, "clusters out of order\n"); 1912 ok(logclust[1] == 1, "clusters out of order\n"); 1913 ok(logclust[2] == 2, "clusters out of order\n"); 1914 ok(logclust[3] == 3, "clusters out of order\n"); 1915 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1916 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1917 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1918 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1919 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1920 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1921 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1922 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1923 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1924 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1925 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1926 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1927 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1928 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1929 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1930 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1931 1932 /* modify LTR to RTL */ 1933 items[0].a.fRTL = 1; 1934 memset(glyphs2,-1,sizeof(glyphs2)); 1935 memset(logclust,-1,sizeof(logclust)); 1936 memset(attrs,-1,sizeof(attrs)); 1937 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs2, logclust, attrs, &nb); 1938 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 1939 ok(nb == 4, "Wrong number of items\n"); 1940 ok(glyphs2[0] == glyphs[3], "Glyphs not reordered properly\n"); 1941 ok(glyphs2[1] == glyphs[2], "Glyphs not reordered properly\n"); 1942 ok(glyphs2[2] == glyphs[1], "Glyphs not reordered properly\n"); 1943 ok(glyphs2[3] == glyphs[0], "Glyphs not reordered properly\n"); 1944 ok(logclust[0] == 3, "clusters out of order\n"); 1945 ok(logclust[1] == 2, "clusters out of order\n"); 1946 ok(logclust[2] == 1, "clusters out of order\n"); 1947 ok(logclust[3] == 0, "clusters out of order\n"); 1948 ok(attrs[0].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1949 ok(attrs[1].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1950 ok(attrs[2].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1951 ok(attrs[3].uJustification == SCRIPT_JUSTIFY_CHARACTER, "uJustification incorrect\n"); 1952 ok(attrs[0].fClusterStart == 1, "fClusterStart incorrect\n"); 1953 ok(attrs[1].fClusterStart == 1, "fClusterStart incorrect\n"); 1954 ok(attrs[2].fClusterStart == 1, "fClusterStart incorrect\n"); 1955 ok(attrs[3].fClusterStart == 1, "fClusterStart incorrect\n"); 1956 ok(attrs[0].fDiacritic == 0, "fDiacritic incorrect\n"); 1957 ok(attrs[1].fDiacritic == 0, "fDiacritic incorrect\n"); 1958 ok(attrs[2].fDiacritic == 0, "fDiacritic incorrect\n"); 1959 ok(attrs[3].fDiacritic == 0, "fDiacritic incorrect\n"); 1960 ok(attrs[0].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1961 ok(attrs[1].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1962 ok(attrs[2].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1963 ok(attrs[3].fZeroWidth == 0, "fZeroWidth incorrect\n"); 1964 1965 ScriptFreeCache(&sc); 1966 1967 /* some control characters are shown as blank */ 1968 for (i = 0; i < 2; i++) 1969 { 1970 static const WCHAR space[] = {' ', 0}; 1971 static const struct 1972 { 1973 WCHAR c; 1974 unsigned int item_count; 1975 unsigned int item; 1976 } 1977 test_data[] = 1978 { 1979 {0x0009, 3, 1}, /* \t */ 1980 {0x000a, 3, 1}, /* \n */ 1981 {0x000d, 3, 1}, /* \r */ 1982 {0x001c, 3, 1}, /* FS */ 1983 {0x001d, 3, 1}, /* GS */ 1984 {0x001e, 3, 1}, /* RS */ 1985 {0x001f, 3, 1}, /* US */ 1986 {0x200b, 1, 0}, /* ZWSP */ 1987 {0x200c, 1, 0}, /* ZWNJ */ 1988 {0x200d, 1, 0}, /* ZWJ */ 1989 {0x200e, 3, 1}, /* LRM */ 1990 {0x200f, 3, 1}, /* RLM */ 1991 {0x202a, 3, 1}, /* LRE */ 1992 {0x202b, 3, 1}, /* RLE */ 1993 {0x202c, 3, 1}, /* PDF */ 1994 {0x202d, 3, 1}, /* LRO */ 1995 {0x202e, 3, 1}, /* RLO */ 1996 }; 1997 WCHAR chars[3]; 1998 HFONT font, oldfont = NULL; 1999 LOGFONTA lf; 2000 2001 font = GetCurrentObject(hdc, OBJ_FONT); 2002 GetObjectA(font, sizeof(lf), &lf); 2003 if (i == 1) { 2004 lstrcpyA(lf.lfFaceName, "MS Sans Serif"); 2005 font = CreateFontIndirectA(&lf); 2006 oldfont = SelectObject(hdc, font); 2007 } 2008 2009 hr = ScriptItemize(space, 1, 2, NULL, NULL, items, NULL); 2010 ok(hr == S_OK, "%s: expected S_OK, got %08x\n", lf.lfFaceName, hr); 2011 2012 hr = ScriptShape(hdc, &sc, space, 1, 1, &items[0].a, glyphs, logclust, attrs, &nb); 2013 ok(hr == S_OK, "%s: expected S_OK, got %08x\n", lf.lfFaceName, hr); 2014 ok(nb == 1, "%s: expected 1, got %d\n", lf.lfFaceName, nb); 2015 2016 chars[0] = 'A'; 2017 chars[2] = 'A'; 2018 for (j = 0; j < sizeof(test_data) / sizeof(*test_data); ++j) 2019 { 2020 WCHAR c = test_data[j].c; 2021 SCRIPT_ITEM *item; 2022 2023 chars[1] = c; 2024 hr = ScriptItemize(chars, 3, 4, NULL, NULL, items, &nb); 2025 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2026 ok(nb == test_data[j].item_count, "%s: [%02x] Got unexpected item count %d.\n", 2027 lf.lfFaceName, c, nb); 2028 item = &items[test_data[j].item]; 2029 2030 ok(!item->a.fNoGlyphIndex, "%s: [%02x] got unexpected fNoGlyphIndex %#x.\n", 2031 lf.lfFaceName, c, item->a.fNoGlyphIndex); 2032 hr = ScriptShape(hdc, &sc, chars, 3, 3, &item->a, glyphs2, logclust, attrs, &nb); 2033 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2034 ok(nb == 3, "%s: [%02x] expected 3, got %d\n", lf.lfFaceName, c, nb); 2035 ok(!item->a.fNoGlyphIndex, "%s: [%02x] got unexpected fNoGlyphIndex %#x.\n", 2036 lf.lfFaceName, c, item->a.fNoGlyphIndex); 2037 2038 ok(glyphs[0] == glyphs2[1] || 2039 broken(glyphs2[1] == c && (c < 0x10)), 2040 "%s: [%02x] expected %04x, got %04x\n", lf.lfFaceName, c, glyphs[0], glyphs2[1]); 2041 ok(attrs[1].fZeroWidth || broken(!attrs[1].fZeroWidth && (c < 0x10) /* Vista */), 2042 "%s: [%02x] got unexpected fZeroWidth %#x.\n", lf.lfFaceName, c, attrs[1].fZeroWidth); 2043 2044 item->a.fNoGlyphIndex = 1; 2045 hr = ScriptShape(hdc, &sc, chars, 3, 3, &item->a, glyphs2, logclust, attrs, &nb); 2046 ok(hr == S_OK, "%s: [%02x] expected S_OK, got %08x\n", lf.lfFaceName, c, hr); 2047 ok(nb == 3, "%s: [%02x] expected 1, got %d\n", lf.lfFaceName, c, nb); 2048 2049 if (c == 0x200b || c == 0x200c || c == 0x200d) 2050 { 2051 ok(glyphs2[1] == 0x0020, 2052 "%s: [%02x] got unexpected %04x.\n", lf.lfFaceName, c, glyphs2[1]); 2053 ok(attrs[1].fZeroWidth, "%s: [%02x] got unexpected fZeroWidth %#x.\n", 2054 lf.lfFaceName, c, attrs[1].fZeroWidth); 2055 } 2056 else 2057 { 2058 ok(glyphs2[1] == c, 2059 "%s: [%02x] got unexpected %04x.\n", lf.lfFaceName, c, glyphs2[1]); 2060 ok(!attrs[1].fZeroWidth, "%s: [%02x] got unexpected fZeroWidth %#x.\n", 2061 lf.lfFaceName, c, attrs[1].fZeroWidth); 2062 } 2063 } 2064 if (oldfont) 2065 DeleteObject(SelectObject(hdc, oldfont)); 2066 ScriptFreeCache(&sc); 2067 } 2068 2069 /* Text does not support this range. */ 2070 memset(items, 0, sizeof(items)); 2071 nb = 0; 2072 hr = ScriptItemize(test3, sizeof(test3)/sizeof(test3[0]), sizeof(items)/sizeof(items[0]), NULL, NULL, items, &nb); 2073 ok(hr == S_OK, "ScriptItemize failed, hr %#x.\n", hr); 2074 ok(items[0].a.eScript > 0, "Expected script id.\n"); 2075 ok(nb == 1, "Unexpected number of items.\n"); 2076 2077 memset(glyphs, 0xff, sizeof(glyphs)); 2078 nb = 0; 2079 hr = ScriptShape(hdc, &sc, test3, sizeof(test3)/sizeof(test3[0]), sizeof(glyphs)/sizeof(glyphs[0]), &items[0].a, 2080 glyphs, logclust, attrs, &nb); 2081 ok(hr == S_OK, "ScriptShape failed, hr %#x.\n", hr); 2082 ok(nb == 1, "Unexpected glyph count %u\n", nb); 2083 ok(glyphs[0] == 0, "Unexpected glyph id\n"); 2084 ScriptFreeCache(&sc); 2085 } 2086 2087 static void test_ScriptPlace(HDC hdc) 2088 { 2089 static const WCHAR test1[] = {'t', 'e', 's', 't',0}; 2090 BOOL ret; 2091 HRESULT hr; 2092 SCRIPT_CACHE sc = NULL; 2093 WORD glyphs[4], logclust[4]; 2094 SCRIPT_VISATTR attrs[4]; 2095 SCRIPT_ITEM items[2]; 2096 int nb, widths[4]; 2097 GOFFSET offset[4]; 2098 ABC abc[4]; 2099 2100 hr = ScriptItemize(test1, 4, 2, NULL, NULL, items, NULL); 2101 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 2102 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2103 2104 hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); 2105 ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); 2106 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2107 2108 hr = ScriptPlace(hdc, &sc, glyphs, 4, NULL, &items[0].a, widths, NULL, NULL); 2109 ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr); 2110 2111 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL); 2112 ok(broken(hr == E_PENDING) || 2113 hr == E_INVALIDARG || /* Vista, W2K8 */ 2114 hr == E_FAIL, /* WIN7 */ 2115 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 2116 2117 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2118 ok(hr == E_PENDING, "ScriptPlace should return E_PENDING not %08x\n", hr); 2119 2120 hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, abc); 2121 ok(broken(hr == E_PENDING) || 2122 hr == E_INVALIDARG || /* Vista, W2K8 */ 2123 hr == E_FAIL, /* WIN7 */ 2124 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr); 2125 2126 hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2127 ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); 2128 ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); 2129 2130 if (widths[0] != 0) 2131 { 2132 int old_width = widths[0]; 2133 attrs[0].fZeroWidth = 1; 2134 2135 hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); 2136 ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); 2137 ok(widths[0] == 0, "got width %d\n", widths[0]); 2138 widths[0] = old_width; 2139 } 2140 else 2141 skip("Glyph already has zero-width - skipping fZeroWidth test\n"); 2142 2143 ret = ExtTextOutW(hdc, 1, 1, 0, NULL, glyphs, 4, widths); 2144 ok(ret, "ExtTextOutW should return TRUE\n"); 2145 2146 ScriptFreeCache(&sc); 2147 } 2148 2149 static void test_ScriptItemIzeShapePlace(HDC hdc, unsigned short pwOutGlyphs[256]) 2150 { 2151 HRESULT hr; 2152 int iMaxProps; 2153 const SCRIPT_PROPERTIES **ppSp; 2154 2155 int cInChars; 2156 int cMaxItems; 2157 SCRIPT_ITEM pItem[255]; 2158 int pcItems; 2159 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2160 WCHAR TestItem2[] = {'T', 'e', 's', 't', 'b', 0}; 2161 WCHAR TestItem3[] = {'T', 'e', 's', 't', 'c',' ','1','2','3',' ',' ','e','n','d',0}; 2162 WCHAR TestItem4[] = {'T', 'e', 's', 't', 'd',' ',0x0684,0x0694,0x06a4,' ',' ','\r','\n','e','n','d',0}; 2163 WCHAR TestItem5[] = {0x0684,'T','e','s','t','e',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0}; 2164 WCHAR TestItem6[] = {'T', 'e', 's', 't', 'f',' ',' ',' ','\r','\n','e','n','d',0}; 2165 2166 SCRIPT_CACHE psc; 2167 int cChars; 2168 int cMaxGlyphs; 2169 unsigned short pwOutGlyphs1[256]; 2170 unsigned short pwOutGlyphs2[256]; 2171 unsigned short pwLogClust[256]; 2172 SCRIPT_VISATTR psva[256]; 2173 int pcGlyphs; 2174 int piAdvance[256]; 2175 GOFFSET pGoffset[256]; 2176 ABC pABC[256]; 2177 int cnt; 2178 2179 /* Start testing usp10 functions */ 2180 /* This test determines that the pointer returned by ScriptGetProperties is valid 2181 * by checking a known value in the table */ 2182 hr = ScriptGetProperties(&ppSp, &iMaxProps); 2183 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 2184 trace("number of script properties %d\n", iMaxProps); 2185 ok (iMaxProps > 0, "Number of scripts returned should not be 0\n"); 2186 if (iMaxProps > 0) 2187 ok( ppSp[0]->langid == 0, "Langid[0] not = to 0\n"); /* Check a known value to ensure */ 2188 /* ptrs work */ 2189 2190 /* This is a valid test that will cause parsing to take place */ 2191 cInChars = 5; 2192 cMaxItems = 255; 2193 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2194 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2195 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2196 * returned. */ 2197 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2198 if (pcItems > 0) 2199 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2200 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2201 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2202 2203 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2204 * ie. ScriptItemize has succeeded and that pItem has been set */ 2205 cInChars = 5; 2206 if (hr == S_OK) { 2207 psc = NULL; /* must be null on first call */ 2208 cChars = cInChars; 2209 cMaxGlyphs = cInChars; 2210 hr = ScriptShape(NULL, &psc, TestItem1, cChars, 2211 cMaxGlyphs, &pItem[0].a, 2212 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2213 ok (hr == E_PENDING, "If psc is NULL (%08x) the E_PENDING should be returned\n", hr); 2214 cMaxGlyphs = 4; 2215 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2216 cMaxGlyphs, &pItem[0].a, 2217 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2218 ok (hr == E_OUTOFMEMORY, "If not enough output area cChars (%d) is > than CMaxGlyphs " 2219 "(%d) but not E_OUTOFMEMORY\n", 2220 cChars, cMaxGlyphs); 2221 cMaxGlyphs = 256; 2222 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2223 cMaxGlyphs, &pItem[0].a, 2224 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2225 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2226 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2227 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2228 if (hr ==0) { 2229 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2230 pGoffset, pABC); 2231 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2232 hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2233 pGoffset, pABC); 2234 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2235 for (cnt=0; cnt < pcGlyphs; cnt++) 2236 pwOutGlyphs[cnt] = pwOutGlyphs1[cnt]; /* Send to next function */ 2237 } 2238 2239 /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation * 2240 * takes place if fNoGlyphIndex is set. */ 2241 2242 cInChars = 5; 2243 cMaxItems = 255; 2244 hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2245 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2246 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2247 * returned. */ 2248 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2249 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2250 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2251 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue */ 2252 if (hr == S_OK) { 2253 cChars = cInChars; 2254 cMaxGlyphs = 256; 2255 pItem[0].a.fNoGlyphIndex = 1; /* say no translate */ 2256 hr = ScriptShape(NULL, &psc, TestItem2, cChars, 2257 cMaxGlyphs, &pItem[0].a, 2258 pwOutGlyphs2, pwLogClust, psva, &pcGlyphs); 2259 ok (hr != E_PENDING, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n", hr); 2260 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2261 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2262 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2263 for (cnt=0; cnt < cChars && TestItem2[cnt] == pwOutGlyphs2[cnt]; cnt++) {} 2264 ok (cnt == cChars, "Translation to place when told not to. WCHAR %d - %04x != %04x\n", 2265 cnt, TestItem2[cnt], pwOutGlyphs2[cnt]); 2266 if (hr == S_OK) { 2267 hr = ScriptPlace(hdc, &psc, pwOutGlyphs2, pcGlyphs, psva, &pItem[0].a, piAdvance, 2268 pGoffset, pABC); 2269 ok (hr == S_OK, "ScriptPlace should return S_OK not (%08x)\n", hr); 2270 } 2271 } 2272 ScriptFreeCache( &psc); 2273 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2274 2275 } 2276 2277 /* This is a valid test that will cause parsing to take place and create 3 script_items */ 2278 cInChars = (sizeof(TestItem3)/2)-1; 2279 cMaxItems = 255; 2280 hr = ScriptItemize(TestItem3, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2281 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2282 if (hr == S_OK) 2283 { 2284 ok (pcItems == 3, "The number of SCRIPT_ITEMS should be 3 not %d\n", pcItems); 2285 if (pcItems > 2) 2286 { 2287 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == 6, 2288 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n", 2289 pItem[0].iCharPos, pItem[1].iCharPos); 2290 ok (pItem[1].iCharPos == 6 && pItem[2].iCharPos == 11, 2291 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n", 2292 pItem[1].iCharPos, pItem[2].iCharPos); 2293 ok (pItem[2].iCharPos == 11 && pItem[3].iCharPos == cInChars, 2294 "Start pos [2] not = 11 (%d) or end [3] pos not = 14 (%d), cInChars = %d\n", 2295 pItem[2].iCharPos, pItem[3].iCharPos, cInChars); 2296 } 2297 } 2298 2299 /* This is a valid test that will cause parsing to take place and create 5 script_items */ 2300 cInChars = (sizeof(TestItem4)/2)-1; 2301 cMaxItems = 255; 2302 hr = ScriptItemize(TestItem4, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2303 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2304 if (hr == S_OK) 2305 { 2306 ok (pcItems == 5, "The number of SCRIPT_ITEMS should be 5 not %d\n", pcItems); 2307 if (pcItems > 4) 2308 { 2309 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == 6, 2310 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n", 2311 pItem[0].iCharPos, pItem[1].iCharPos); 2312 ok (pItem[0].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2313 pItem[0].a.s.uBidiLevel); 2314 ok (pItem[1].iCharPos == 6 && pItem[2].iCharPos == 11, 2315 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n", 2316 pItem[1].iCharPos, pItem[2].iCharPos); 2317 ok (pItem[1].a.s.uBidiLevel == 1, "Should have been bidi=1 not %d\n", 2318 pItem[1].a.s.uBidiLevel); 2319 ok (pItem[2].iCharPos == 11 && pItem[3].iCharPos == 12, 2320 "Start pos [2] not = 11 (%d) or end [3] pos not = 12 (%d)\n", 2321 pItem[2].iCharPos, pItem[3].iCharPos); 2322 ok (pItem[2].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2323 pItem[2].a.s.uBidiLevel); 2324 ok (pItem[3].iCharPos == 12 && pItem[4].iCharPos == 13, 2325 "Start pos [3] not = 12 (%d) or end [4] pos not = 13 (%d)\n", 2326 pItem[3].iCharPos, pItem[4].iCharPos); 2327 ok (pItem[3].a.s.uBidiLevel == 0, "Should have been bidi=0 not %d\n", 2328 pItem[3].a.s.uBidiLevel); 2329 ok (pItem[4].iCharPos == 13 && pItem[5].iCharPos == cInChars, 2330 "Start pos [4] not = 13 (%d) or end [5] pos not = 16 (%d), cInChars = %d\n", 2331 pItem[4].iCharPos, pItem[5].iCharPos, cInChars); 2332 } 2333 } 2334 2335 /* 2336 * This test is for when the first unicode character requires bidi support 2337 */ 2338 cInChars = (sizeof(TestItem5)-1)/sizeof(WCHAR); 2339 hr = ScriptItemize(TestItem5, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2340 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2341 ok (pcItems == 4, "There should have been 4 items, found %d\n", pcItems); 2342 ok (pItem[0].a.s.uBidiLevel == 1, "The first character should have been bidi=1 not %d\n", 2343 pItem[0].a.s.uBidiLevel); 2344 2345 /* This test checks to make sure that the test to see if there are sufficient buffers to store * 2346 * the pointer to the last char works. Note that windows often needs a greater number of * 2347 * SCRIPT_ITEMS to process a string than is returned in pcItems. */ 2348 cInChars = (sizeof(TestItem6)/2)-1; 2349 cMaxItems = 4; 2350 hr = ScriptItemize(TestItem6, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2351 ok (hr == E_OUTOFMEMORY, "ScriptItemize should return E_OUTOFMEMORY, returned %08x\n", hr); 2352 2353 } 2354 2355 static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256]) 2356 { 2357 HRESULT hr; 2358 SCRIPT_CACHE psc = NULL; 2359 int cInChars; 2360 int cChars; 2361 unsigned short pwOutGlyphs2[256]; 2362 unsigned short pwOutGlyphs3[256]; 2363 DWORD dwFlags; 2364 int cnt; 2365 2366 static const WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2367 static const WCHAR TestItem2[] = {0x202B, 'i', 'n', 0x202C,0}; 2368 static const WCHAR TestItem3[] = {'a','b','c','d','(','<','{','[',0x2039,0}; 2369 static const WCHAR TestItem3b[] = {'a','b','c','d',')','>','}',']',0x203A,0}; 2370 2371 /* Check to make sure that SCRIPT_CACHE gets allocated ok */ 2372 dwFlags = 0; 2373 cInChars = cChars = 5; 2374 /* Some sanity checks for ScriptGetCMap */ 2375 2376 hr = ScriptGetCMap(NULL, NULL, NULL, 0, 0, NULL); 2377 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL,0,0,NULL), " 2378 "expected E_INVALIDARG, got %08x\n", hr); 2379 2380 hr = ScriptGetCMap(NULL, NULL, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2381 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), " 2382 "expected E_INVALIDARG, got %08x\n", hr); 2383 2384 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2385 psc = NULL; 2386 hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, 0, pwOutGlyphs3); 2387 ok( hr == E_PENDING, "(NULL,&psc,NULL,0,0,NULL), expected E_PENDING, " 2388 "got %08x\n", hr); 2389 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2390 2391 /* Set psc to NULL but add hdc, to be able to check if a pointer is returned in psc */ 2392 psc = NULL; 2393 hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, 0, pwOutGlyphs3); 2394 ok( hr == S_OK, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, " 2395 "got %08x\n", hr); 2396 ok( psc != NULL, "ScritpGetCMap expected psc to be not NULL\n"); 2397 ScriptFreeCache( &psc); 2398 2399 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2400 psc = NULL; 2401 hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2402 ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", hr); 2403 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2404 /* Check to see if the results are the same as those returned by ScriptShape */ 2405 hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3); 2406 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2407 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2408 for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {} 2409 ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n", 2410 cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]); 2411 2412 ScriptFreeCache( &psc); 2413 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2414 2415 /* ScriptGetCMap returns whatever font defines, no special treatment for control chars */ 2416 cInChars = cChars = 4; 2417 GetGlyphIndicesW(hdc, TestItem2, cInChars, pwOutGlyphs2, 0); 2418 2419 hr = ScriptGetCMap(hdc, &psc, TestItem2, cInChars, dwFlags, pwOutGlyphs3); 2420 if (pwOutGlyphs3[0] == 0 || pwOutGlyphs3[3] == 0) 2421 ok(hr == S_FALSE, "ScriptGetCMap should return S_FALSE not (%08x)\n", hr); 2422 else 2423 ok(hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2424 2425 ok(psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2426 ok(pwOutGlyphs3[0] == pwOutGlyphs2[0], "expected glyph %d, got %d\n", pwOutGlyphs2[0], pwOutGlyphs3[0]); 2427 ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "expected glyph %d, got %d\n", pwOutGlyphs2[3], pwOutGlyphs3[3]); 2428 2429 cInChars = cChars = 9; 2430 hr = ScriptGetCMap(hdc, &psc, TestItem3b, cInChars, dwFlags, pwOutGlyphs2); 2431 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2432 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2433 2434 cInChars = cChars = 9; 2435 dwFlags = SGCM_RTL; 2436 hr = ScriptGetCMap(hdc, &psc, TestItem3, cInChars, dwFlags, pwOutGlyphs3); 2437 ok (hr == S_OK, "ScriptGetCMap should return S_OK not (%08x)\n", hr); 2438 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2439 ok(pwOutGlyphs3[0] == pwOutGlyphs2[0], "glyph incorrectly altered\n"); 2440 ok(pwOutGlyphs3[1] == pwOutGlyphs2[1], "glyph incorrectly altered\n"); 2441 ok(pwOutGlyphs3[2] == pwOutGlyphs2[2], "glyph incorrectly altered\n"); 2442 ok(pwOutGlyphs3[3] == pwOutGlyphs2[3], "glyph incorrectly altered\n"); 2443 ok(pwOutGlyphs3[4] == pwOutGlyphs2[4], "glyph not mirrored correctly\n"); 2444 ok(pwOutGlyphs3[5] == pwOutGlyphs2[5], "glyph not mirrored correctly\n"); 2445 ok(pwOutGlyphs3[6] == pwOutGlyphs2[6], "glyph not mirrored correctly\n"); 2446 ok(pwOutGlyphs3[7] == pwOutGlyphs2[7], "glyph not mirrored correctly\n"); 2447 ok(pwOutGlyphs3[8] == pwOutGlyphs2[8], "glyph not mirrored correctly\n"); 2448 2449 ScriptFreeCache( &psc); 2450 ok (!psc, "psc is not null after ScriptFreeCache\n"); 2451 } 2452 2453 #define MAX_ENUM_FONTS 4096 2454 2455 struct enum_font_data 2456 { 2457 int total; 2458 ENUMLOGFONTA elf[MAX_ENUM_FONTS]; 2459 }; 2460 2461 static INT CALLBACK enum_bitmap_font_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 2462 { 2463 struct enum_font_data *efnd = (struct enum_font_data *)lParam; 2464 2465 if (type & (TRUETYPE_FONTTYPE | DEVICE_FONTTYPE)) return 1; 2466 2467 if (efnd->total < MAX_ENUM_FONTS) 2468 { 2469 efnd->elf[efnd->total++] = *(ENUMLOGFONTA*)lf; 2470 } 2471 else 2472 trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS); 2473 2474 return 1; 2475 } 2476 2477 static INT CALLBACK enum_truetype_proc(const LOGFONTA *lf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam) 2478 { 2479 struct enum_font_data *efnd = (struct enum_font_data *)lParam; 2480 2481 if (!(type & (TRUETYPE_FONTTYPE | DEVICE_FONTTYPE))) return 1; 2482 2483 if (efnd->total < MAX_ENUM_FONTS) 2484 { 2485 efnd->elf[efnd->total++] = *(ENUMLOGFONTA*)lf; 2486 } 2487 else 2488 trace("enum tests invalid; you have more than %d fonts\n", MAX_ENUM_FONTS); 2489 2490 return 1; 2491 } 2492 2493 static void test_ScriptGetFontProperties(HDC hdc) 2494 { 2495 HRESULT hr; 2496 SCRIPT_CACHE psc,old_psc; 2497 SCRIPT_FONTPROPERTIES sfp; 2498 HFONT font, oldfont; 2499 LOGFONTA lf; 2500 struct enum_font_data efnd; 2501 TEXTMETRICA tmA; 2502 WORD gi[3]; 2503 WCHAR str[3]; 2504 DWORD i, ret; 2505 WORD system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID()); 2506 static const WCHAR invalids[] = {0x0020, 0x200B, 0xF71B}; 2507 /* U+0020: numeric space 2508 U+200B: zero width space 2509 U+F71B: unknown, found by black box testing */ 2510 BOOL is_arial, is_times_new_roman, is_arabic = (system_lang_id == LANG_ARABIC); 2511 2512 /* Some sanity checks for ScriptGetFontProperties */ 2513 2514 hr = ScriptGetFontProperties(NULL,NULL,NULL); 2515 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr); 2516 2517 hr = ScriptGetFontProperties(NULL,NULL,&sfp); 2518 ok( hr == E_INVALIDARG, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr); 2519 2520 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2521 psc = NULL; 2522 hr = ScriptGetFontProperties(NULL,&psc,NULL); 2523 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr); 2524 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2525 2526 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2527 psc = NULL; 2528 hr = ScriptGetFontProperties(NULL,&psc,&sfp); 2529 ok( hr == E_PENDING, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", hr); 2530 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2531 2532 hr = ScriptGetFontProperties(hdc,NULL,NULL); 2533 ok( hr == E_INVALIDARG, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr); 2534 2535 hr = ScriptGetFontProperties(hdc,NULL,&sfp); 2536 ok( hr == E_INVALIDARG, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr); 2537 2538 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2539 psc = NULL; 2540 hr = ScriptGetFontProperties(hdc,&psc,NULL); 2541 ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr); 2542 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2543 2544 /* Pass an invalid sfp */ 2545 psc = NULL; 2546 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES) - 1; 2547 hr = ScriptGetFontProperties(hdc,&psc,&sfp); 2548 ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) invalid, expected E_INVALIDARG, got %08x\n", hr); 2549 ok( psc != NULL, "Expected a pointer in psc, got NULL\n"); 2550 ok( sfp.cBytes == sizeof(SCRIPT_FONTPROPERTIES) - 1, "Unexpected cBytes.\n"); 2551 ScriptFreeCache(&psc); 2552 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2553 2554 /* Give it the correct cBytes, we don't care about what's coming back */ 2555 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2556 psc = NULL; 2557 hr = ScriptGetFontProperties(hdc,&psc,&sfp); 2558 ok( hr == S_OK, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", hr); 2559 ok( psc != NULL, "Expected a pointer in psc, got NULL\n"); 2560 2561 /* Save the psc pointer */ 2562 old_psc = psc; 2563 /* Now a NULL hdc again */ 2564 hr = ScriptGetFontProperties(NULL,&psc,&sfp); 2565 ok( hr == S_OK, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", hr); 2566 ok( psc == old_psc, "Expected psc not to be changed, was %p is now %p\n", old_psc, psc); 2567 ScriptFreeCache(&psc); 2568 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2569 2570 memset(&lf, 0, sizeof(lf)); 2571 lf.lfCharSet = DEFAULT_CHARSET; 2572 efnd.total = 0; 2573 EnumFontFamiliesA(hdc, NULL, enum_bitmap_font_proc, (LPARAM)&efnd); 2574 2575 for (i = 0; i < efnd.total; i++) 2576 { 2577 if (strlen((char *)efnd.elf[i].elfFullName) >= LF_FACESIZE) 2578 { 2579 trace("Font name to long to test: %s\n",(char *)efnd.elf[i].elfFullName); 2580 continue; 2581 } 2582 lstrcpyA(lf.lfFaceName, (char *)efnd.elf[i].elfFullName); 2583 font = CreateFontIndirectA(&lf); 2584 oldfont = SelectObject(hdc, font); 2585 2586 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2587 psc = NULL; 2588 hr = ScriptGetFontProperties(hdc, &psc, &sfp); 2589 ok(hr == S_OK, "ScriptGetFontProperties expected S_OK, got %08x\n", hr); 2590 if (winetest_interactive) 2591 { 2592 trace("bitmap font %s\n", lf.lfFaceName); 2593 trace("wgBlank %04x\n", sfp.wgBlank); 2594 trace("wgDefault %04x\n", sfp.wgDefault); 2595 trace("wgInvalid %04x\n", sfp.wgInvalid); 2596 trace("wgKashida %04x\n", sfp.wgKashida); 2597 trace("iKashidaWidth %d\n", sfp.iKashidaWidth); 2598 } 2599 2600 ret = GetTextMetricsA(hdc, &tmA); 2601 ok(ret != 0, "GetTextMetricsA failed!\n"); 2602 2603 ret = GetGlyphIndicesW(hdc, invalids, 1, gi, GGI_MARK_NONEXISTING_GLYPHS); 2604 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2605 2606 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]); 2607 2608 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); 2609 2610 ok(sfp.wgInvalid == sfp.wgBlank || broken(is_arabic), "bitmap font %s wgInvalid %02x wgBlank %02x\n", lf.lfFaceName, sfp.wgInvalid, sfp.wgBlank); 2611 2612 ok(sfp.wgKashida == 0xFFFF || broken(is_arabic), "bitmap font %s wgKashida %02x\n", lf.lfFaceName, sfp.wgKashida); 2613 2614 ScriptFreeCache(&psc); 2615 2616 SelectObject(hdc, oldfont); 2617 DeleteObject(font); 2618 } 2619 2620 efnd.total = 0; 2621 EnumFontFamiliesA(hdc, NULL, enum_truetype_proc, (LPARAM)&efnd); 2622 2623 for (i = 0; i < efnd.total; i++) 2624 { 2625 if (strlen((char *)efnd.elf[i].elfFullName) >= LF_FACESIZE) 2626 { 2627 trace("Font name to long to test: %s\n",(char *)efnd.elf[i].elfFullName); 2628 continue; 2629 } 2630 lstrcpyA(lf.lfFaceName, (char *)efnd.elf[i].elfFullName); 2631 font = CreateFontIndirectA(&lf); 2632 oldfont = SelectObject(hdc, font); 2633 2634 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES); 2635 psc = NULL; 2636 hr = ScriptGetFontProperties(hdc, &psc, &sfp); 2637 ok(hr == S_OK, "ScriptGetFontProperties expected S_OK, got %08x\n", hr); 2638 if (winetest_interactive) 2639 { 2640 trace("truetype font %s\n", lf.lfFaceName); 2641 trace("wgBlank %04x\n", sfp.wgBlank); 2642 trace("wgDefault %04x\n", sfp.wgDefault); 2643 trace("wgInvalid %04x\n", sfp.wgInvalid); 2644 trace("wgKashida %04x\n", sfp.wgKashida); 2645 trace("iKashidaWidth %d\n", sfp.iKashidaWidth); 2646 } 2647 2648 str[0] = 0x0020; /* U+0020: numeric space */ 2649 ret = GetGlyphIndicesW(hdc, str, 1, gi, 0); 2650 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2651 ok(sfp.wgBlank == gi[0], "truetype font %s wgBlank %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgBlank, gi[0]); 2652 2653 ok(sfp.wgDefault == 0 || broken(is_arabic), "truetype font %s wgDefault %04x\n", lf.lfFaceName, sfp.wgDefault); 2654 2655 ret = GetGlyphIndicesW(hdc, invalids, 3, gi, GGI_MARK_NONEXISTING_GLYPHS); 2656 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2657 if (gi[2] != 0xFFFF) /* index of default non exist char */ 2658 ok(sfp.wgInvalid == gi[2], "truetype font %s wgInvalid %04x gi[2] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[2]); 2659 else if (gi[1] != 0xFFFF) 2660 ok(sfp.wgInvalid == gi[1], "truetype font %s wgInvalid %04x gi[1] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[1]); 2661 else if (gi[0] != 0xFFFF) 2662 ok(sfp.wgInvalid == gi[0], "truetype font %s wgInvalid %04x gi[0] %04x\n", lf.lfFaceName, sfp.wgInvalid, gi[0]); 2663 else 2664 ok(sfp.wgInvalid == 0, "truetype font %s wgInvalid %04x expect 0\n", lf.lfFaceName, sfp.wgInvalid); 2665 2666 str[0] = 0x0640; /* U+0640: kashida */ 2667 ret = GetGlyphIndicesW(hdc, str, 1, gi, GGI_MARK_NONEXISTING_GLYPHS); 2668 ok(ret != GDI_ERROR, "GetGlyphIndicesW failed!\n"); 2669 is_arial = !lstrcmpA(lf.lfFaceName, "Arial"); 2670 is_times_new_roman= !lstrcmpA(lf.lfFaceName, "Times New Roman"); 2671 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]); 2672 2673 ScriptFreeCache(&psc); 2674 2675 SelectObject(hdc, oldfont); 2676 DeleteObject(font); 2677 } 2678 } 2679 2680 static void test_ScriptTextOut(HDC hdc) 2681 { 2682 HRESULT hr; 2683 2684 int cInChars; 2685 int cMaxItems; 2686 SCRIPT_ITEM pItem[255]; 2687 int pcItems; 2688 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2689 2690 SCRIPT_CACHE psc; 2691 int cChars; 2692 int cMaxGlyphs; 2693 unsigned short pwOutGlyphs1[256]; 2694 WORD pwLogClust[256]; 2695 SCRIPT_VISATTR psva[256]; 2696 int pcGlyphs; 2697 int piAdvance[256]; 2698 GOFFSET pGoffset[256]; 2699 ABC pABC[256]; 2700 RECT rect; 2701 int piX; 2702 int iCP = 1; 2703 BOOL fTrailing = FALSE; 2704 SCRIPT_LOGATTR *psla; 2705 SCRIPT_LOGATTR sla[256]; 2706 2707 /* This is a valid test that will cause parsing to take place */ 2708 cInChars = 5; 2709 cMaxItems = 255; 2710 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2711 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2712 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2713 * returned. */ 2714 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2715 if (pcItems > 0) 2716 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2717 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2718 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2719 2720 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2721 * ie. ScriptItemize has succeeded and that pItem has been set */ 2722 cInChars = 5; 2723 if (hr == S_OK) { 2724 psc = NULL; /* must be null on first call */ 2725 cChars = cInChars; 2726 cMaxGlyphs = 256; 2727 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2728 cMaxGlyphs, &pItem[0].a, 2729 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2730 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2731 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2732 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2733 if (hr == S_OK) { 2734 /* Note hdc is needed as glyph info is not yet in psc */ 2735 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2736 pGoffset, pABC); 2737 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2738 ScriptFreeCache(&psc); /* Get rid of psc for next test set */ 2739 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2740 2741 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL); 2742 ok (hr == E_INVALIDARG, "Should return 0 not (%08x)\n", hr); 2743 2744 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2745 piAdvance, NULL, pGoffset); 2746 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), " 2747 "expected E_INVALIDARG, got %08x\n", hr); 2748 2749 /* Set psc to NULL, to be able to check if a pointer is returned in psc */ 2750 psc = NULL; 2751 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, 2752 NULL, NULL, NULL); 2753 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, " 2754 "got %08x\n", hr); 2755 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2756 2757 /* hdc is required for this one rather than the usual optional */ 2758 psc = NULL; 2759 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2760 piAdvance, NULL, pGoffset); 2761 ok( hr == E_INVALIDARG, "(NULL,&psc,), expected E_INVALIDARG, got %08x\n", hr); 2762 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2763 2764 /* Set that it returns 0 status */ 2765 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2766 piAdvance, NULL, pGoffset); 2767 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2768 2769 /* Test Rect Rgn is acceptable */ 2770 SetRect(&rect, 10, 10, 40, 20); 2771 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2772 piAdvance, NULL, pGoffset); 2773 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2774 2775 iCP = 1; 2776 hr = ScriptCPtoX(iCP, fTrailing, cChars, pcGlyphs, (const WORD *) &pwLogClust, 2777 (const SCRIPT_VISATTR *) &psva, (const int *)&piAdvance, &pItem[0].a, &piX); 2778 ok(hr == S_OK, "ScriptCPtoX Stub should return S_OK not %08x\n", hr); 2779 2780 psla = (SCRIPT_LOGATTR *)&sla; 2781 hr = ScriptBreak(TestItem1, cChars, &pItem[0].a, psla); 2782 ok(hr == S_OK, "ScriptBreak Stub should return S_OK not %08x\n", hr); 2783 2784 /* Clean up and go */ 2785 ScriptFreeCache(&psc); 2786 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2787 } 2788 } 2789 } 2790 2791 static void test_ScriptTextOut2(HDC hdc) 2792 { 2793 /* Intent is to validate that the HDC passed into ScriptTextOut is 2794 * used instead of the (possibly) invalid cached one 2795 */ 2796 HRESULT hr; 2797 2798 HDC hdc1, hdc2; 2799 int cInChars; 2800 int cMaxItems; 2801 SCRIPT_ITEM pItem[255]; 2802 int pcItems; 2803 WCHAR TestItem1[] = {'T', 'e', 's', 't', 'a', 0}; 2804 2805 SCRIPT_CACHE psc; 2806 int cChars; 2807 int cMaxGlyphs; 2808 unsigned short pwOutGlyphs1[256]; 2809 WORD pwLogClust[256]; 2810 SCRIPT_VISATTR psva[256]; 2811 int pcGlyphs; 2812 int piAdvance[256]; 2813 GOFFSET pGoffset[256]; 2814 ABC pABC[256]; 2815 2816 /* Create an extra DC that will be used until the ScriptTextOut */ 2817 hdc1 = CreateCompatibleDC(hdc); 2818 ok (hdc1 != 0, "CreateCompatibleDC failed to create a DC\n"); 2819 hdc2 = CreateCompatibleDC(hdc); 2820 ok (hdc2 != 0, "CreateCompatibleDC failed to create a DC\n"); 2821 2822 /* This is a valid test that will cause parsing to take place */ 2823 cInChars = 5; 2824 cMaxItems = 255; 2825 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2826 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2827 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2828 * returned. */ 2829 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2830 if (pcItems > 0) 2831 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars, 2832 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2833 pItem[0].iCharPos, cInChars, pItem[1].iCharPos); 2834 2835 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2836 * ie. ScriptItemize has succeeded and that pItem has been set */ 2837 cInChars = 5; 2838 if (hr == S_OK) { 2839 psc = NULL; /* must be null on first call */ 2840 cChars = cInChars; 2841 cMaxGlyphs = 256; 2842 hr = ScriptShape(hdc2, &psc, TestItem1, cChars, 2843 cMaxGlyphs, &pItem[0].a, 2844 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2845 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2846 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2847 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2848 if (hr == S_OK) { 2849 BOOL ret; 2850 2851 /* Note hdc is needed as glyph info is not yet in psc */ 2852 hr = ScriptPlace(hdc2, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2853 pGoffset, pABC); 2854 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2855 2856 /* key part!!! cached dc is being deleted */ 2857 ret = DeleteDC(hdc2); 2858 ok(ret, "DeleteDC should return 1 not %d\n", ret); 2859 2860 /* At this point the cached hdc (hdc2) has been destroyed, 2861 * however, we are passing in a *real* hdc (the original hdc). 2862 * The text should be written to that DC 2863 */ 2864 hr = ScriptTextOut(hdc1, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2865 piAdvance, NULL, pGoffset); 2866 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2867 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2868 2869 DeleteDC(hdc1); 2870 2871 /* Clean up and go */ 2872 ScriptFreeCache(&psc); 2873 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2874 } 2875 } 2876 } 2877 2878 static void test_ScriptTextOut3(HDC hdc) 2879 { 2880 HRESULT hr; 2881 2882 int cInChars; 2883 int cMaxItems; 2884 SCRIPT_ITEM pItem[255]; 2885 int pcItems; 2886 WCHAR TestItem1[] = {' ','\r', 0}; 2887 2888 SCRIPT_CACHE psc; 2889 int cChars; 2890 int cMaxGlyphs; 2891 unsigned short pwOutGlyphs1[256]; 2892 WORD pwLogClust[256]; 2893 SCRIPT_VISATTR psva[256]; 2894 int pcGlyphs; 2895 int piAdvance[256]; 2896 GOFFSET pGoffset[256]; 2897 ABC pABC[256]; 2898 RECT rect; 2899 2900 /* This is to ensure that nonexistent glyphs are translated into a valid glyph number */ 2901 cInChars = 2; 2902 cMaxItems = 255; 2903 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems); 2904 ok (hr == S_OK, "ScriptItemize should return S_OK, returned %08x\n", hr); 2905 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is * 2906 * returned. */ 2907 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n"); 2908 if (pcItems > 0) 2909 ok (pItem[0].iCharPos == 0 && pItem[2].iCharPos == cInChars, 2910 "Start pos not = 0 (%d) or end pos not = %d (%d)\n", 2911 pItem[0].iCharPos, cInChars, pItem[2].iCharPos); 2912 2913 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue 2914 * ie. ScriptItemize has succeeded and that pItem has been set */ 2915 cInChars = 2; 2916 if (hr == S_OK) { 2917 psc = NULL; /* must be null on first call */ 2918 cChars = cInChars; 2919 cMaxGlyphs = 256; 2920 hr = ScriptShape(hdc, &psc, TestItem1, cChars, 2921 cMaxGlyphs, &pItem[0].a, 2922 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs); 2923 ok (hr == S_OK, "ScriptShape should return S_OK not (%08x)\n", hr); 2924 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n"); 2925 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs); 2926 if (hr ==0) { 2927 /* Note hdc is needed as glyph info is not yet in psc */ 2928 hr = ScriptPlace(hdc, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance, 2929 pGoffset, pABC); 2930 ok (hr == S_OK, "Should return S_OK not (%08x)\n", hr); 2931 2932 /* Test Rect Rgn is acceptable */ 2933 SetRect(&rect, 10, 10, 40, 20); 2934 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs, 2935 piAdvance, NULL, pGoffset); 2936 ok (hr == S_OK, "ScriptTextOut should return S_OK not (%08x)\n", hr); 2937 } 2938 /* Clean up and go */ 2939 ScriptFreeCache(&psc); 2940 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc); 2941 } 2942 } 2943 2944 #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) 2945 2946 static void _test_item_ScriptXtoX(SCRIPT_ANALYSIS *psa, int cChars, int cGlyphs, const int* offsets, const WORD *pwLogClust, const int* piAdvance ) 2947 { 2948 int iX, iCP; 2949 int icChars, icGlyphs; 2950 int piCP, piX; 2951 HRESULT hr; 2952 SCRIPT_VISATTR psva[10]; 2953 int piTrailing; 2954 BOOL fTrailing; 2955 int direction; 2956 2957 memset(psva,0,sizeof(psva)); 2958 direction = (psa->fRTL)?-1:+1; 2959 2960 for(iCP = 0; iCP < cChars; iCP++) 2961 { 2962 iX = offsets[iCP]; 2963 icChars = cChars; 2964 icGlyphs = cGlyphs; 2965 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 2966 winetest_ok(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 2967 winetest_ok(piCP == iCP, "ScriptXtoCP: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 2968 winetest_ok(piTrailing == 0, "ScriptXtoCP: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 2969 } 2970 2971 for(iCP = 0; iCP < cChars; iCP++) 2972 { 2973 iX = offsets[iCP]+direction; 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 leading: should return S_OK not %08x\n", hr); 2978 winetest_ok(piCP == iCP, "ScriptXtoCP leading: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 2979 winetest_ok(piTrailing == 0, "ScriptXtoCP leading: 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+1]-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 trailing: should return S_OK not %08x\n", hr); 2989 winetest_ok(piCP == iCP, "ScriptXtoCP trailing: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 2990 winetest_ok(piTrailing == 1, "ScriptXtoCP trailing: iX=%d should return piTrailing=1 not %d\n", iX, piTrailing); 2991 } 2992 2993 for(iCP = 0; iCP <= cChars+1; iCP++) 2994 { 2995 fTrailing = FALSE; 2996 icChars = cChars; 2997 icGlyphs = cGlyphs; 2998 hr = ScriptCPtoX(iCP, fTrailing, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piX); 2999 winetest_ok(hr == S_OK, "ScriptCPtoX: should return S_OK not %08x\n", hr); 3000 winetest_ok(piX == offsets[iCP], 3001 "ScriptCPtoX: iCP=%d should return piX=%d not %d\n", iCP, offsets[iCP], piX); 3002 } 3003 3004 for(iCP = 0; iCP <= cChars+1; iCP++) 3005 { 3006 fTrailing = TRUE; 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 trailing: should return S_OK not %08x\n", hr); 3011 winetest_ok(piX == offsets[iCP+1], 3012 "ScriptCPtoX trailing: iCP=%d should return piX=%d not %d\n", iCP, offsets[iCP+1], piX); 3013 } 3014 } 3015 3016 #define test_caret_item_ScriptXtoCP(a,b,c,d,e,f) _test_caret_item_ScriptXtoCP(__LINE__,a,b,c,d,e,f) 3017 3018 static void _test_caret_item_ScriptXtoCP(int line, SCRIPT_ANALYSIS *psa, int cChars, int cGlyphs, const int* offsets, const WORD *pwLogClust, const int* piAdvance ) 3019 { 3020 int iX, iCP, i; 3021 int icChars, icGlyphs; 3022 int piCP; 3023 int clusterSize; 3024 HRESULT hr; 3025 SCRIPT_VISATTR psva[10]; 3026 int piTrailing; 3027 int direction; 3028 3029 memset(psva,0,sizeof(psva)); 3030 direction = (psa->fRTL)?-1:+1; 3031 3032 for(iX = -1, i = iCP = 0; i < cChars; i++) 3033 { 3034 if (offsets[i] != iX) 3035 { 3036 iX = offsets[i]; 3037 iCP = i; 3038 } 3039 icChars = cChars; 3040 icGlyphs = cGlyphs; 3041 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3042 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 3043 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3044 ok_(__FILE__,line)(piTrailing == 0, "ScriptXtoCP: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 3045 } 3046 3047 for(iX = -2, i = 0; i < cChars; i++) 3048 { 3049 if (offsets[i]+direction != iX) 3050 { 3051 iX = offsets[i] + direction; 3052 iCP = i; 3053 } 3054 icChars = cChars; 3055 icGlyphs = cGlyphs; 3056 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3057 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP leading: should return S_OK not %08x\n", hr); 3058 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP leading: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3059 ok_(__FILE__,line)(piTrailing == 0, "ScriptXtoCP leading: iX=%d should return piTrailing=0 not %d\n", iX, piTrailing); 3060 } 3061 3062 for(clusterSize = 0, iCP = 0, iX = -2, i = 0; i < cChars; i++) 3063 { 3064 clusterSize++; 3065 if (offsets[i] != offsets[i+1]) 3066 { 3067 iX = offsets[i+1]-direction; 3068 icChars = cChars; 3069 icGlyphs = cGlyphs; 3070 hr = ScriptXtoCP(iX, icChars, icGlyphs, pwLogClust, psva, piAdvance, psa, &piCP, &piTrailing); 3071 ok_(__FILE__,line)(hr == S_OK, "ScriptXtoCP trailing: should return S_OK not %08x\n", hr); 3072 ok_(__FILE__,line)(piCP == iCP, "ScriptXtoCP trailing: iX=%d should return piCP=%d not %d\n", iX, iCP, piCP); 3073 ok_(__FILE__,line)(piTrailing == clusterSize, "ScriptXtoCP trailing: iX=%d should return piTrailing=%d not %d\n", iX, clusterSize, piTrailing); 3074 iCP = i+1; 3075 clusterSize = 0; 3076 } 3077 } 3078 } 3079 3080 static void test_ScriptXtoX(void) 3081 /**************************************************************************************** 3082 * This routine tests the ScriptXtoCP and ScriptCPtoX functions using static variables * 3083 ****************************************************************************************/ 3084 { 3085 WORD pwLogClust[10] = {0, 0, 0, 1, 1, 2, 2, 3, 3, 3}; 3086 WORD pwLogClust_RTL[10] = {3, 3, 3, 2, 2, 1, 1, 0, 0, 0}; 3087 WORD pwLogClust_2[7] = {4, 3, 3, 2, 1, 0 ,0}; 3088 WORD pwLogClust_3[17] = {0, 1, 1, 1, 1, 4, 5, 6, 6, 8, 8, 8, 8, 11, 11, 13, 13}; 3089 WORD pwLogClust_3_RTL[17] = {13, 13, 11, 11, 8, 8, 8, 8, 6, 6, 5, 4, 1, 1, 1, 1, 0}; 3090 int piAdvance[10] = {201, 190, 210, 180, 170, 204, 189, 195, 212, 203}; 3091 int piAdvance_2[5] = {39, 26, 19, 17, 11}; 3092 int piAdvance_3[15] = {6, 6, 0, 0, 10, 5, 10, 0, 12, 0, 0, 9, 0, 10, 0}; 3093 static const int offsets[13] = {0, 67, 134, 201, 296, 391, 496, 601, 1052, 1503, 1954, 1954, 1954}; 3094 static const int offsets_RTL[13] = {781, 721, 661, 601, 496, 391, 296, 201, 134, 67, 0, 0, 0}; 3095 static const int offsets_2[10] = {112, 101, 92, 84, 65, 39, 19, 0, 0, 0}; 3096 3097 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}; 3098 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}; 3099 3100 SCRIPT_VISATTR psva[15]; 3101 SCRIPT_ANALYSIS sa; 3102 SCRIPT_ITEM items[2]; 3103 int iX, i; 3104 int piCP; 3105 int piTrailing; 3106 HRESULT hr; 3107 static const WCHAR hebrW[] = { 0x5be, 0}; 3108 static const WCHAR thaiW[] = { 0xe2a, 0}; 3109 const SCRIPT_PROPERTIES **ppScriptProperties; 3110 3111 memset(&sa, 0 , sizeof(SCRIPT_ANALYSIS)); 3112 memset(psva, 0, sizeof(psva)); 3113 3114 sa.fRTL = FALSE; 3115 hr = ScriptXtoCP(-1, 10, 10, pwLogClust, psva, piAdvance, &sa, &piCP, &piTrailing); 3116 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3117 if (piTrailing) 3118 ok(piCP == -1, "Negative iX should return piCP=-1 not %d\n", piCP); 3119 else /* win2k3 */ 3120 ok(piCP == 10, "Negative iX should return piCP=10 not %d\n", piCP); 3121 3122 for (iX = 0; iX <= 7; iX++) 3123 { 3124 WORD clust = 0; 3125 INT advance = 16; 3126 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3127 ok(piCP==0 && piTrailing==0,"%i should return 0(%i) and 0(%i)\n",iX, piCP,piTrailing); 3128 } 3129 for (iX = 8; iX < 16; iX++) 3130 { 3131 WORD clust = 0; 3132 INT advance = 16; 3133 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3134 ok(piCP==0 && piTrailing==1,"%i should return 0(%i) and 1(%i)\n",iX, piCP,piTrailing); 3135 } 3136 3137 sa.fRTL = TRUE; 3138 hr = ScriptXtoCP(-1, 10, 10, pwLogClust_RTL, psva, piAdvance, &sa, &piCP, &piTrailing); 3139 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3140 if (piTrailing) 3141 ok(piCP == -1, "Negative iX should return piCP=-1 not %d\n", piCP); 3142 else /* win2k3 */ 3143 ok(piCP == 10, "Negative iX should return piCP=10 not %d\n", piCP); 3144 3145 iX = 1954; 3146 hr = ScriptXtoCP(1954, 10, 10, pwLogClust_RTL, psva, piAdvance, &sa, &piCP, &piTrailing); 3147 ok(hr == S_OK, "ScriptXtoCP should return S_OK not %08x\n", hr); 3148 ok(piCP == -1, "iX=%d should return piCP=-1 not %d\n", iX, piCP); 3149 ok(piTrailing == 1, "iX=%d should return piTrailing=1 not %d\n", iX, piTrailing); 3150 3151 for (iX = 1; iX <= 8; iX++) 3152 { 3153 WORD clust = 0; 3154 INT advance = 16; 3155 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3156 ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr); 3157 ok(piCP==0 && piTrailing==1,"%i should return 0(%i) and 1(%i)\n",iX,piCP,piTrailing); 3158 } 3159 for (iX = 9; iX < 16; iX++) 3160 { 3161 WORD clust = 0; 3162 INT advance = 16; 3163 hr = ScriptXtoCP(iX, 1, 1, &clust, psva, &advance, &sa, &piCP, &piTrailing); 3164 ok(hr == S_OK, "ScriptXtoCP() failed, hr %#x.\n", hr); 3165 ok(piCP==0 && piTrailing==0,"%i should return 0(%i) and 0(%i)\n",iX,piCP,piTrailing); 3166 } 3167 3168 sa.fRTL = FALSE; 3169 test_item_ScriptXtoX(&sa, 10, 10, offsets, pwLogClust, piAdvance); 3170 sa.fRTL = TRUE; 3171 test_item_ScriptXtoX(&sa, 10, 10, offsets_RTL, pwLogClust_RTL, piAdvance); 3172 test_item_ScriptXtoX(&sa, 7, 5, offsets_2, pwLogClust_2, piAdvance_2); 3173 3174 /* Get thai eScript, This will do LTR and fNeedsCaretInfo */ 3175 hr = ScriptItemize(thaiW, 1, 2, NULL, NULL, items, &i); 3176 ok(hr == S_OK, "got %08x\n", hr); 3177 ok(i == 1, "got %d\n", i); 3178 sa = items[0].a; 3179 3180 test_caret_item_ScriptXtoCP(&sa, 17, 15, offsets_3, pwLogClust_3, piAdvance_3); 3181 3182 /* Get hebrew eScript, This will do RTL and fNeedsCaretInfo */ 3183 hr = ScriptItemize(hebrW, 1, 2, NULL, NULL, items, &i); 3184 ok(hr == S_OK, "got %08x\n", hr); 3185 ok(i == 1, "got %d\n", i); 3186 sa = items[0].a; 3187 3188 /* Note: This behavior CHANGED in uniscribe versions... 3189 * so we only want to test if fNeedsCaretInfo is set */ 3190 hr = ScriptGetProperties(&ppScriptProperties, &i); 3191 if (ppScriptProperties[sa.eScript]->fNeedsCaretInfo) 3192 { 3193 test_caret_item_ScriptXtoCP(&sa, 17, 15, offsets_3_RTL, pwLogClust_3_RTL, piAdvance_3); 3194 hr = ScriptXtoCP(0, 17, 15, pwLogClust_3_RTL, psva, piAdvance_3, &sa, &piCP, &piTrailing); 3195 ok(hr == S_OK, "ScriptXtoCP: should return S_OK not %08x\n", hr); 3196 ok(piCP == 16, "ScriptXtoCP: iX=0 should return piCP=16 not %d\n", piCP); 3197 ok(piTrailing == 1, "ScriptXtoCP: iX=0 should return piTrailing=1 not %d\n", piTrailing); 3198 } 3199 else 3200 win_skip("Uniscribe version too old to test Hebrew clusters\n"); 3201 } 3202 3203 static void test_ScriptString(HDC hdc) 3204 { 3205 /******************************************************************************************* 3206 * 3207 * This set of tests are for the string functions of uniscribe. The ScriptStringAnalyse 3208 * function allocates memory pointed to by the SCRIPT_STRING_ANALYSIS ssa pointer. This 3209 * memory is freed by ScriptStringFree. There needs to be a valid hdc for this as 3210 * ScriptStringAnalyse calls ScriptItemize, ScriptShape and ScriptPlace which require it. 3211 * 3212 */ 3213 3214 HRESULT hr; 3215 WCHAR teststr[] = {'T','e','s','t','1',' ','a','2','b','3', '\0'}; 3216 int len = (sizeof(teststr) / sizeof(WCHAR)) - 1; 3217 int Glyphs = len * 2 + 16; 3218 int Charset; 3219 DWORD Flags = SSA_GLYPHS; 3220 int ReqWidth = 100; 3221 static const int Dx[(sizeof(teststr) / sizeof(WCHAR)) - 1]; 3222 static const BYTE InClass[(sizeof(teststr) / sizeof(WCHAR)) - 1]; 3223 SCRIPT_STRING_ANALYSIS ssa = NULL; 3224 3225 int X = 10; 3226 int Y = 100; 3227 UINT Options = 0; 3228 const RECT rc = {0, 50, 100, 100}; 3229 int MinSel = 0; 3230 int MaxSel = 0; 3231 BOOL Disabled = FALSE; 3232 const int *clip_len; 3233 int i; 3234 UINT *order; 3235 3236 3237 Charset = -1; /* this flag indicates unicode input */ 3238 /* Test without hdc to get E_PENDING */ 3239 hr = ScriptStringAnalyse( NULL, teststr, len, Glyphs, Charset, Flags, 3240 ReqWidth, NULL, NULL, Dx, NULL, 3241 InClass, &ssa); 3242 ok(hr == E_PENDING, "ScriptStringAnalyse Stub should return E_PENDING not %08x\n", hr); 3243 3244 /* Test that 0 length string returns E_INVALIDARG */ 3245 hr = ScriptStringAnalyse( hdc, teststr, 0, Glyphs, Charset, Flags, 3246 ReqWidth, NULL, NULL, Dx, NULL, 3247 InClass, &ssa); 3248 ok(hr == E_INVALIDARG, "ScriptStringAnalyse should return E_INVALIDARG not %08x\n", hr); 3249 3250 /* test with hdc, this should be a valid test */ 3251 hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags, 3252 ReqWidth, NULL, NULL, Dx, NULL, 3253 InClass, &ssa); 3254 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3255 ScriptStringFree(&ssa); 3256 3257 /* test makes sure that a call with a valid pssa still works */ 3258 hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags, 3259 ReqWidth, NULL, NULL, Dx, NULL, 3260 InClass, &ssa); 3261 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3262 ok(ssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n"); 3263 3264 if (hr == S_OK) 3265 { 3266 hr = ScriptStringOut(ssa, X, Y, Options, &rc, MinSel, MaxSel, Disabled); 3267 ok(hr == S_OK, "ScriptStringOut should return S_OK not %08x\n", hr); 3268 } 3269 3270 clip_len = ScriptString_pcOutChars(ssa); 3271 ok(*clip_len == len, "ScriptString_pcOutChars failed, got %d, expected %d\n", *clip_len, len); 3272 3273 order = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *clip_len * sizeof(UINT)); 3274 hr = ScriptStringGetOrder(ssa, order); 3275 ok(hr == S_OK, "ScriptStringGetOrder failed, got %08x, expected S_OK\n", hr); 3276 3277 for (i = 0; i < *clip_len; i++) ok(order[i] == i, "%d: got %d expected %d\n", i, order[i], i); 3278 HeapFree(GetProcessHeap(), 0, order); 3279 3280 hr = ScriptStringFree(&ssa); 3281 ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); 3282 } 3283 3284 static void test_ScriptStringXtoCP_CPtoX(HDC hdc) 3285 { 3286 /***************************************************************************************** 3287 * 3288 * This test is for the ScriptStringXtoCP and ScriptStringXtoCP functions. Due to the 3289 * nature of the fonts between Windows and Wine, the test is implemented by generating 3290 * values using one one function then checking the output of the second. In this way 3291 * the validity of the functions is established using Windows as a base and confirming 3292 * similar behaviour in wine. 3293 */ 3294 3295 HRESULT hr; 3296 static const WCHAR teststr1[] = {0x05e9, 'i', 0x05dc, 'n', 0x05d5, 'e', 0x05dd, '.',0}; 3297 static const BOOL rtl[] = {1, 0, 1, 0, 1, 0, 1, 0}; 3298 void *String = (WCHAR *) &teststr1; /* ScriptStringAnalysis needs void */ 3299 int String_len = (sizeof(teststr1)/sizeof(WCHAR))-1; 3300 int Glyphs = String_len * 2 + 16; /* size of buffer as recommended */ 3301 int Charset = -1; /* unicode */ 3302 DWORD Flags = SSA_GLYPHS; 3303 int ReqWidth = 100; 3304 static const BYTE InClass[(sizeof(teststr1)/sizeof(WCHAR))-1]; 3305 SCRIPT_STRING_ANALYSIS ssa = NULL; 3306 3307 int Ch; /* Character position in string */ 3308 int iTrailing; 3309 int Cp; /* Character position in string */ 3310 int X; 3311 int trail,lead; 3312 BOOL fTrailing; 3313 3314 /* Test with hdc, this should be a valid test 3315 * Here we generate an SCRIPT_STRING_ANALYSIS that will be used as input to the 3316 * following character positions to X and X to character position functions. 3317 */ 3318 3319 hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, 3320 ReqWidth, NULL, NULL, NULL, NULL, 3321 InClass, &ssa); 3322 ok(hr == S_OK || 3323 hr == E_INVALIDARG, /* NT */ 3324 "ScriptStringAnalyse should return S_OK or E_INVALIDARG not %08x\n", hr); 3325 3326 if (hr == S_OK) 3327 { 3328 ok(ssa != NULL, "ScriptStringAnalyse ssa should not be NULL\n"); 3329 3330 /* 3331 * Loop to generate character positions to provide starting positions for the 3332 * ScriptStringCPtoX and ScriptStringXtoCP functions 3333 */ 3334 for (Cp = 0; Cp < String_len; Cp++) 3335 { 3336 /* The fTrailing flag is used to indicate whether the X being returned is at 3337 * the beginning or the end of the character. What happens here is that if 3338 * fTrailing indicates the end of the character, ie. FALSE, then ScriptStringXtoCP 3339 * returns the beginning of the next character and iTrailing is FALSE. So for this 3340 * loop iTrailing will be FALSE in both cases. 3341 */ 3342 hr = ScriptStringCPtoX(ssa, Cp, TRUE, &trail); 3343 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3344 hr = ScriptStringCPtoX(ssa, Cp, FALSE, &lead); 3345 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3346 if (rtl[Cp]) 3347 ok(lead > trail, "Leading values should be after trailing for rtl characters(%i)\n",Cp); 3348 else 3349 ok(lead < trail, "Trailing values should be after leading for ltr characters(%i)\n",Cp); 3350 3351 /* move by 1 pixel so that we are not between 2 characters. That could result in being the lead of a rtl and 3352 at the same time the trail of an ltr */ 3353 3354 /* inside the leading edge */ 3355 X = lead; 3356 if (rtl[Cp]) X--; else X++; 3357 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3358 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3359 ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, trail); 3360 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3361 iTrailing, X); 3362 3363 /* inside the trailing edge */ 3364 X = trail; 3365 if (rtl[Cp]) X++; else X--; 3366 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3367 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3368 ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, trail); 3369 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3370 iTrailing, X); 3371 3372 /* outside the "trailing" edge */ 3373 if (Cp < String_len-1) 3374 { 3375 if (rtl[Cp]) X = lead; else X = trail; 3376 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 + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, trail); 3380 if (rtl[Cp+1]) 3381 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3382 iTrailing, X); 3383 else 3384 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3385 iTrailing, X); 3386 } 3387 3388 /* outside the "leading" edge */ 3389 if (Cp != 0) 3390 { 3391 if (rtl[Cp]) X = trail; else X = lead; 3392 X--; 3393 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3394 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3395 ok(Cp - 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp - 1, Ch, trail); 3396 if (Cp != 0 && rtl[Cp-1]) 3397 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", 3398 iTrailing, X); 3399 else 3400 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", 3401 iTrailing, X); 3402 } 3403 } 3404 3405 /* Check beyond the leading boundary of the whole string */ 3406 if (rtl[0]) 3407 { 3408 /* having a leading rtl character seems to confuse usp */ 3409 /* this looks to be a windows bug we should emulate */ 3410 hr = ScriptStringCPtoX(ssa, 0, TRUE, &X); 3411 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3412 X--; 3413 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3414 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3415 ok(Ch == 1, "ScriptStringXtoCP should return Ch = 1 not %d for X outside leading edge when rtl\n", Ch); 3416 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside leading edge when rtl\n", 3417 iTrailing); 3418 } 3419 else 3420 { 3421 hr = ScriptStringCPtoX(ssa, 0, FALSE, &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\n", Ch); 3427 ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = outside leading edge\n", 3428 iTrailing); 3429 } 3430 3431 /* Check beyond the end boundary of the whole string */ 3432 if (rtl[String_len-1]) 3433 { 3434 hr = ScriptStringCPtoX(ssa, String_len-1, FALSE, &X); 3435 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3436 } 3437 else 3438 { 3439 hr = ScriptStringCPtoX(ssa, String_len-1, TRUE, &X); 3440 ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); 3441 } 3442 X++; 3443 hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); 3444 ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); 3445 ok(Ch == String_len, "ScriptStringXtoCP should return Ch = %i not %d for X outside trailing edge\n", String_len, Ch); 3446 ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside trailing edge\n", 3447 iTrailing); 3448 3449 /* 3450 * Cleanup the SSA for the next round of tests 3451 */ 3452 hr = ScriptStringFree(&ssa); 3453 ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); 3454 3455 /* 3456 * Test to see that exceeding the number of chars returns E_INVALIDARG. First 3457 * generate an SSA for the subsequent tests. 3458 */ 3459 hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, 3460 ReqWidth, NULL, NULL, NULL, NULL, 3461 InClass, &ssa); 3462 ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); 3463 3464 /* 3465 * When ScriptStringCPtoX is called with a character position Cp that exceeds the 3466 * string length, return E_INVALIDARG. This also invalidates the ssa so a 3467 * ScriptStringFree should also fail. 3468 */ 3469 fTrailing = FALSE; 3470 Cp = String_len + 1; 3471 hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); 3472 ok(hr == E_INVALIDARG, "ScriptStringCPtoX should return E_INVALIDARG not %08x\n", hr); 3473 3474 ScriptStringFree(&ssa); 3475 } 3476 } 3477 3478 static HWND create_test_window(void) 3479 { 3480 HWND hwnd = CreateWindowExA(0, "Static", "", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL); 3481 ok(hwnd != NULL, "Failed to create test window.\n"); 3482 3483 ShowWindow(hwnd, SW_SHOW); 3484 UpdateWindow(hwnd); 3485 3486 return hwnd; 3487 } 3488 3489 static void test_ScriptCacheGetHeight(HDC hdc) 3490 { 3491 HFONT hfont, prev_hfont; 3492 SCRIPT_CACHE sc = NULL; 3493 LONG height, height2; 3494 TEXTMETRICW tm; 3495 LOGFONTA lf; 3496 HRESULT hr; 3497 HWND hwnd; 3498 HDC hdc2; 3499 3500 hr = ScriptCacheGetHeight(NULL, NULL, NULL); 3501 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3502 3503 hr = ScriptCacheGetHeight(NULL, &sc, NULL); 3504 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3505 3506 hr = ScriptCacheGetHeight(NULL, &sc, &height); 3507 ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr); 3508 3509 height = 123; 3510 hr = ScriptCacheGetHeight(hdc, NULL, &height); 3511 ok(hr == E_INVALIDARG, "Uexpected hr %#x.\n", hr); 3512 ok(height == 123, "Unexpected height.\n"); 3513 3514 memset(&tm, 0, sizeof(tm)); 3515 GetTextMetricsW(hdc, &tm); 3516 ok(tm.tmHeight > 0, "Unexpected tmHeight %u.\n", tm.tmHeight); 3517 3518 height = 0; 3519 hr = ScriptCacheGetHeight(hdc, &sc, &height); 3520 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3521 ok(height == tm.tmHeight, "expected height > 0\n"); 3522 3523 /* Try again with NULL dc. */ 3524 height2 = 0; 3525 hr = ScriptCacheGetHeight(NULL, &sc, &height2); 3526 ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr); 3527 ok(height2 == height, "Unexpected height %u.\n", height2); 3528 3529 hwnd = create_test_window(); 3530 3531 hdc2 = GetDC(hwnd); 3532 ok(hdc2 != NULL, "Failed to get window dc.\n"); 3533 3534 memset(&lf, 0, sizeof(LOGFONTA)); 3535 lstrcpyA(lf.lfFaceName, "Tahoma"); 3536 lf.lfHeight = -32; 3537 3538 hfont = CreateFontIndirectA(&lf); 3539 ok(hfont != NULL, "Failed to create font.\n"); 3540 3541 prev_hfont = SelectObject(hdc2, hfont); 3542 3543 memset(&tm, 0, sizeof(tm)); 3544 GetTextMetricsW(hdc2, &tm); 3545 ok(tm.tmHeight > height, "Unexpected tmHeight %u.\n", tm.tmHeight); 3546 3547 height2 = 0; 3548 hr = ScriptCacheGetHeight(hdc2, &sc, &height2); 3549 ok(hr == S_OK, "Failed to get cached height, hr %#x.\n", hr); 3550 ok(height2 == height, "Unexpected height.\n"); 3551 3552 SelectObject(hdc2, prev_hfont); 3553 DeleteObject(hfont); 3554 3555 ReleaseDC(hwnd, hdc2); 3556 DestroyWindow(hwnd); 3557 3558 ScriptFreeCache(&sc); 3559 } 3560 3561 static void test_ScriptGetGlyphABCWidth(HDC hdc) 3562 { 3563 HRESULT hr; 3564 SCRIPT_CACHE sc = NULL; 3565 ABC abc; 3566 3567 hr = ScriptGetGlyphABCWidth(NULL, NULL, 'a', NULL); 3568 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3569 3570 hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', NULL); 3571 ok(broken(hr == E_PENDING) || 3572 hr == E_INVALIDARG, /* WIN7 */ 3573 "expected E_INVALIDARG, got 0x%08x\n", hr); 3574 3575 hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', &abc); 3576 ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr); 3577 3578 if (0) { /* crashes on WinXP */ 3579 hr = ScriptGetGlyphABCWidth(hdc, &sc, 'a', NULL); 3580 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3581 } 3582 3583 hr = ScriptGetGlyphABCWidth(hdc, &sc, 'a', &abc); 3584 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3585 3586 ScriptFreeCache(&sc); 3587 } 3588 3589 static void test_ScriptLayout(void) 3590 { 3591 HRESULT hr; 3592 static const BYTE levels[][10] = 3593 { 3594 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 3595 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 3596 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, 3597 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, 3598 3599 { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, 3600 { 1, 1, 1, 2, 2, 2, 1, 1, 1, 1 }, 3601 { 2, 2, 2, 1, 1, 1, 2, 2, 2, 2 }, 3602 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 0 }, 3603 { 1, 1, 2, 2, 3, 3, 2, 2, 1, 1 }, 3604 3605 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 1 }, 3606 { 1, 0, 1, 2, 2, 1, 2, 1, 0, 1 }, 3607 3608 { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, 3609 { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0 }, 3610 { 2, 2, 2, 4, 4, 4, 1, 1, 0, 0 }, 3611 { 1, 2, 3, 0, 3, 2, 1, 0, 0, 0 } 3612 }; 3613 static const int expect_l2v[][10] = 3614 { 3615 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3616 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3617 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3618 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3619 3620 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5}, 3621 /**/ { 9, 8, 7, 4, 5, 6, 3 ,2 ,1, 0}, 3622 /**/ { 7, 8, 9, 6, 5, 4, 0 ,1 ,2, 3}, 3623 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3624 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0}, 3625 3626 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3627 /**/ { 0, 1, 7, 5, 6, 4, 3 ,2 ,8, 9}, 3628 3629 { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, 3630 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3631 { 2, 3, 4, 5, 6, 7, 1, 0, 8, 9}, 3632 { 2, 0, 1, 3, 5, 6, 4, 7, 8, 9} 3633 }; 3634 static const int expect_v2l[][10] = 3635 { 3636 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3637 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3638 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 3639 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, 3640 3641 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5}, 3642 { 9, 8, 7, 6, 3, 4, 5 ,2 ,1, 0}, 3643 { 6, 7, 8, 9, 5, 4, 3 ,0 ,1, 2}, 3644 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3645 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0}, 3646 3647 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9}, 3648 { 0, 1, 7, 6, 5, 3, 4 ,2 ,8, 9}, 3649 3650 { 1, 0, 2, 3, 4, 5, 6, 7, 8, 9}, 3651 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3652 { 7, 6, 0, 1, 2, 3, 4, 5, 8, 9}, 3653 { 1, 2, 0, 3, 6, 4, 5, 7, 8, 9} 3654 }; 3655 3656 int i, j, vistolog[sizeof(levels[0])], logtovis[sizeof(levels[0])]; 3657 3658 hr = ScriptLayout(sizeof(levels[0]), NULL, vistolog, logtovis); 3659 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3660 3661 hr = ScriptLayout(sizeof(levels[0]), levels[0], NULL, NULL); 3662 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 3663 3664 for (i = 0; i < sizeof(levels)/sizeof(levels[0]); i++) 3665 { 3666 hr = ScriptLayout(sizeof(levels[0]), levels[i], vistolog, logtovis); 3667 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 3668 3669 for (j = 0; j < sizeof(levels[i]); j++) 3670 { 3671 ok(expect_v2l[i][j] == vistolog[j], 3672 "failure: levels[%d][%d] = %d, vistolog[%d] = %d\n", 3673 i, j, levels[i][j], j, vistolog[j] ); 3674 } 3675 3676 for (j = 0; j < sizeof(levels[i]); j++) 3677 { 3678 ok(expect_l2v[i][j] == logtovis[j], 3679 "failure: levels[%d][%d] = %d, logtovis[%d] = %d\n", 3680 i, j, levels[i][j], j, logtovis[j] ); 3681 } 3682 } 3683 } 3684 3685 static BOOL CALLBACK enum_proc(LGRPID group, LCID lcid, LPSTR locale, LONG_PTR lparam) 3686 { 3687 HRESULT hr; 3688 SCRIPT_DIGITSUBSTITUTE sds; 3689 SCRIPT_CONTROL sc; 3690 SCRIPT_STATE ss; 3691 LCID lcid_old; 3692 3693 if (!IsValidLocale(lcid, LCID_INSTALLED)) return TRUE; 3694 3695 memset(&sds, 0, sizeof(sds)); 3696 memset(&sc, 0, sizeof(sc)); 3697 memset(&ss, 0, sizeof(ss)); 3698 3699 lcid_old = GetThreadLocale(); 3700 if (!SetThreadLocale(lcid)) return TRUE; 3701 3702 hr = ScriptRecordDigitSubstitution(lcid, &sds); 3703 ok(hr == S_OK, "ScriptRecordDigitSubstitution failed: 0x%08x\n", hr); 3704 3705 hr = ScriptApplyDigitSubstitution(&sds, &sc, &ss); 3706 ok(hr == S_OK, "ScriptApplyDigitSubstitution failed: 0x%08x\n", hr); 3707 3708 SetThreadLocale(lcid_old); 3709 return TRUE; 3710 } 3711 3712 static void test_digit_substitution(void) 3713 { 3714 BOOL ret; 3715 unsigned int i; 3716 static const LGRPID groups[] = 3717 { 3718 LGRPID_WESTERN_EUROPE, 3719 LGRPID_CENTRAL_EUROPE, 3720 LGRPID_BALTIC, 3721 LGRPID_GREEK, 3722 LGRPID_CYRILLIC, 3723 LGRPID_TURKISH, 3724 LGRPID_JAPANESE, 3725 LGRPID_KOREAN, 3726 LGRPID_TRADITIONAL_CHINESE, 3727 LGRPID_SIMPLIFIED_CHINESE, 3728 LGRPID_THAI, 3729 LGRPID_HEBREW, 3730 LGRPID_ARABIC, 3731 LGRPID_VIETNAMESE, 3732 LGRPID_INDIC, 3733 LGRPID_GEORGIAN, 3734 LGRPID_ARMENIAN 3735 }; 3736 3737 for (i = 0; i < sizeof(groups)/sizeof(groups[0]); i++) 3738 { 3739 ret = EnumLanguageGroupLocalesA(enum_proc, groups[i], 0, 0); 3740 ok(ret, "EnumLanguageGroupLocalesA failed unexpectedly: %u\n", GetLastError()); 3741 } 3742 } 3743 3744 static void test_ScriptGetProperties(void) 3745 { 3746 const SCRIPT_PROPERTIES **props; 3747 HRESULT hr; 3748 int num; 3749 3750 hr = ScriptGetProperties(NULL, NULL); 3751 ok(hr == E_INVALIDARG, "ScriptGetProperties succeeded\n"); 3752 3753 hr = ScriptGetProperties(NULL, &num); 3754 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3755 3756 hr = ScriptGetProperties(&props, NULL); 3757 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3758 3759 hr = ScriptGetProperties(&props, &num); 3760 ok(hr == S_OK, "ScriptGetProperties failed: 0x%08x\n", hr); 3761 } 3762 3763 static void test_ScriptBreak(void) 3764 { 3765 static const WCHAR test[] = {' ','\r','\n',0}; 3766 SCRIPT_ITEM items[4]; 3767 SCRIPT_LOGATTR la; 3768 HRESULT hr; 3769 3770 hr = ScriptItemize(test, 3, 4, NULL, NULL, items, NULL); 3771 ok(hr == S_OK, "ScriptItemize should return S_OK not %08x\n", hr); 3772 3773 /* 3774 * This Test crashes pre Vista. 3775 3776 hr = ScriptBreak(test, 1, &items[0].a, NULL); 3777 ok(hr == E_INVALIDARG, "ScriptBreak should return E_INVALIDARG not %08x\n", hr); 3778 */ 3779 3780 hr = ScriptBreak(test, 0, &items[0].a, &la); 3781 ok(hr == E_FAIL || broken(hr == S_OK), "ScriptBreak should return E_FAIL not %08x\n", hr); 3782 3783 hr = ScriptBreak(test, -1, &items[0].a, &la); 3784 ok(hr == E_INVALIDARG || broken(hr == S_OK), "ScriptBreak should return E_INVALIDARG not %08x\n", hr); 3785 3786 memset(&la, 0, sizeof(la)); 3787 hr = ScriptBreak(test, 1, &items[0].a, &la); 3788 ok(hr == S_OK, "ScriptBreak should return S_OK not %08x\n", hr); 3789 3790 ok(!la.fSoftBreak, "fSoftBreak set\n"); 3791 ok(la.fWhiteSpace, "fWhiteSpace not set\n"); 3792 ok(la.fCharStop, "fCharStop not set\n"); 3793 ok(!la.fWordStop, "fWordStop set\n"); 3794 ok(!la.fInvalid, "fInvalid set\n"); 3795 ok(!la.fReserved, "fReserved set\n"); 3796 3797 memset(&la, 0, sizeof(la)); 3798 hr = ScriptBreak(test + 1, 1, &items[1].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 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 + 2, 1, &items[2].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 3820 static void test_newlines(void) 3821 { 3822 static const WCHAR test1[] = {'t','e','x','t','\r','t','e','x','t',0}; 3823 static const WCHAR test2[] = {'t','e','x','t','\n','t','e','x','t',0}; 3824 static const WCHAR test3[] = {'t','e','x','t','\r','\n','t','e','x','t',0}; 3825 static const WCHAR test4[] = {'t','e','x','t','\n','\r','t','e','x','t',0}; 3826 static const WCHAR test5[] = {'1','2','3','4','\n','\r','1','2','3','4',0}; 3827 SCRIPT_ITEM items[5]; 3828 HRESULT hr; 3829 int count; 3830 3831 count = 0; 3832 hr = ScriptItemize(test1, lstrlenW(test1), 5, NULL, NULL, items, &count); 3833 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3834 ok(count == 3, "got %d expected 3\n", count); 3835 3836 count = 0; 3837 hr = ScriptItemize(test2, lstrlenW(test2), 5, NULL, NULL, items, &count); 3838 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3839 ok(count == 3, "got %d expected 3\n", count); 3840 3841 count = 0; 3842 hr = ScriptItemize(test3, lstrlenW(test3), 5, NULL, NULL, items, &count); 3843 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3844 ok(count == 4, "got %d expected 4\n", count); 3845 3846 count = 0; 3847 hr = ScriptItemize(test4, lstrlenW(test4), 5, NULL, NULL, items, &count); 3848 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3849 ok(count == 4, "got %d expected 4\n", count); 3850 3851 count = 0; 3852 hr = ScriptItemize(test5, lstrlenW(test5), 5, NULL, NULL, items, &count); 3853 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3854 ok(count == 4, "got %d expected 4\n", count); 3855 } 3856 3857 static void test_ScriptGetFontFunctions(HDC hdc) 3858 { 3859 HRESULT hr; 3860 if (!pScriptGetFontScriptTags || !pScriptGetFontLanguageTags || !pScriptGetFontFeatureTags) 3861 { 3862 win_skip("ScriptGetFontScriptTags,ScriptGetFontLanguageTags or ScriptGetFontFeatureTags not available on this platform\n"); 3863 } 3864 else 3865 { 3866 SCRIPT_CACHE sc = NULL; 3867 OPENTYPE_TAG tags[5]; 3868 int count = 0; 3869 int outnItems=0; 3870 SCRIPT_ITEM outpItems[15]; 3871 SCRIPT_CONTROL Control; 3872 SCRIPT_STATE State; 3873 static const WCHAR test_phagspa[] = {0xa84f, 0xa861, 0xa843, 0x0020, 0xa863, 0xa861, 0xa859, 0x0020, 0xa850, 0xa85c, 0xa85e}; 3874 3875 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, NULL); 3876 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3877 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3878 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, NULL, &count); 3879 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3880 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3881 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, NULL); 3882 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3883 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3884 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 0, tags, &count); 3885 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3886 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3887 hr = pScriptGetFontScriptTags(NULL, &sc, NULL, 5, tags, &count); 3888 ok(hr == E_PENDING,"Incorrect return code\n"); 3889 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3890 hr = pScriptGetFontScriptTags(hdc, &sc, NULL, 5, tags, &count); 3891 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3892 if (hr == S_OK) 3893 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3894 else if (hr == E_OUTOFMEMORY) 3895 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3896 ok(sc != NULL, "ScriptCache should be initialized\n"); 3897 3898 ScriptFreeCache(&sc); 3899 sc = NULL; 3900 3901 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, NULL, NULL); 3902 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3903 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3904 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, NULL, &count); 3905 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3906 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3907 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 5, tags, NULL); 3908 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3909 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3910 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 0, tags, &count); 3911 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3912 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3913 hr = pScriptGetFontLanguageTags(NULL, &sc, NULL, latn_tag, 5, tags, &count); 3914 ok(hr == E_PENDING,"Incorrect return code\n"); 3915 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3916 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, latn_tag, 5, tags, &count); 3917 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3918 if (hr == S_OK) 3919 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3920 else if (hr == E_OUTOFMEMORY) 3921 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3922 3923 ScriptFreeCache(&sc); 3924 sc = NULL; 3925 3926 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, NULL); 3927 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3928 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3929 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, NULL, &count); 3930 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3931 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3932 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 5, tags, NULL); 3933 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3934 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3935 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 0, tags, &count); 3936 ok(hr == E_INVALIDARG,"Incorrect return code\n"); 3937 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3938 hr = pScriptGetFontFeatureTags(NULL, &sc, NULL, latn_tag, 0x0, 5, tags, &count); 3939 ok(hr == E_PENDING,"Incorrect return code\n"); 3940 ok(sc == NULL, "ScriptCache should remain uninitialized\n"); 3941 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, latn_tag, 0x0, 5, tags, &count); 3942 ok((hr == S_OK || hr == E_OUTOFMEMORY),"Incorrect return code\n"); 3943 if (hr == S_OK) 3944 ok(count <= 5, "Count should be less or equal to 5 with S_OK return\n"); 3945 else if (hr == E_OUTOFMEMORY) 3946 ok(count == 0, "Count should be 0 with E_OUTOFMEMORY return\n"); 3947 3948 memset(&Control, 0, sizeof(Control)); 3949 memset(&State, 0, sizeof(State)); 3950 3951 hr = ScriptItemize(test_phagspa, 10, 15, &Control, &State, outpItems, &outnItems); 3952 ok(hr == S_OK, "ScriptItemize failed: 0x%08x\n", hr); 3953 memset(tags,0,sizeof(tags)); 3954 hr = pScriptGetFontScriptTags(hdc, &sc, &outpItems[0].a, 5, tags, &count); 3955 ok( hr == USP_E_SCRIPT_NOT_IN_FONT || broken(hr == S_OK), "wrong return code\n"); 3956 3957 hr = pScriptGetFontLanguageTags(hdc, &sc, NULL, dsrt_tag, 5, tags, &count); 3958 ok( hr == S_OK, "wrong return code\n"); 3959 hr = pScriptGetFontLanguageTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 5, tags, &count); 3960 ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n"); 3961 3962 hr = pScriptGetFontFeatureTags(hdc, &sc, NULL, dsrt_tag, 0x0, 5, tags, &count); 3963 ok( hr == S_OK, "wrong return code\n"); 3964 hr = pScriptGetFontFeatureTags(hdc, &sc, &outpItems[0].a, dsrt_tag, 0x0, 5, tags, &count); 3965 ok( hr == E_INVALIDARG || broken(hr == S_OK), "wrong return code\n"); 3966 3967 ScriptFreeCache(&sc); 3968 } 3969 } 3970 3971 struct logical_width_test 3972 { 3973 int char_count; 3974 int glyph_count; 3975 int advances[3]; 3976 WORD map[3]; 3977 int widths[3]; 3978 BOOL clusterstart[3]; 3979 BOOL diacritic[3]; 3980 BOOL zerowidth[3]; 3981 BOOL todo; 3982 }; 3983 3984 static const struct logical_width_test logical_width_tests[] = 3985 { 3986 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 } }, 3987 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 }, { 1, 0, 0 } }, 3988 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 9, 12 }, { 1, 1, 1 }, { 0 }, { 1, 1, 1 } }, 3989 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 27, 21, 12 }, { 0, 0, 0 }, { 0 }, { 0 }, TRUE }, 3990 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 21, 12 }, { 0, 1, 0 }, { 0 }, { 0 }, TRUE }, 3991 { 3, 3, { 6, 9, 12 }, { 0, 1, 2 }, { 6, 21, 12 }, { 1, 1, 0 }, { 0 }, { 0 }, TRUE }, 3992 { 3, 3, { 6, 9, 12 }, { 0, 2, 2 }, { 15, 6, 6 }, { 1, 0, 1 } }, 3993 }; 3994 3995 static void test_ScriptGetLogicalWidths(void) 3996 { 3997 SCRIPT_ANALYSIS sa = { 0 }; 3998 unsigned int i, j; 3999 4000 for (i = 0; i < sizeof(logical_width_tests)/sizeof(logical_width_tests[0]); i++) 4001 { 4002 const struct logical_width_test *ptr = logical_width_tests + i; 4003 SCRIPT_VISATTR attrs[3]; 4004 int widths[3]; 4005 HRESULT hr; 4006 4007 memset(attrs, 0, sizeof(attrs)); 4008 for (j = 0; j < ptr->glyph_count; j++) 4009 { 4010 attrs[j].fClusterStart = ptr->clusterstart[j]; 4011 attrs[j].fDiacritic = ptr->diacritic[j]; 4012 attrs[j].fZeroWidth = ptr->zerowidth[j]; 4013 } 4014 4015 hr = ScriptGetLogicalWidths(&sa, ptr->char_count, ptr->glyph_count, ptr->advances, ptr->map, attrs, widths); 4016 ok(hr == S_OK, "got 0x%08x\n", hr); 4017 4018 todo_wine_if(ptr->todo) 4019 ok(!memcmp(ptr->widths, widths, sizeof(widths)), "test %u: got wrong widths\n", i); 4020 } 4021 } 4022 4023 static void test_ScriptIsComplex(void) 4024 { 4025 static const WCHAR testW[] = {0x202a,'1',0x202c,0}; 4026 static const WCHAR test2W[] = {'1',0}; 4027 static const struct complex_test 4028 { 4029 const WCHAR *text; 4030 DWORD flags; 4031 HRESULT hr; 4032 BOOL todo; 4033 } complex_tests[] = 4034 { 4035 { test2W, SIC_ASCIIDIGIT, S_OK }, 4036 { test2W, SIC_COMPLEX, S_FALSE }, 4037 { test2W, SIC_COMPLEX | SIC_ASCIIDIGIT, S_OK }, 4038 { testW, SIC_NEUTRAL | SIC_COMPLEX, S_OK }, 4039 { testW, SIC_NEUTRAL, S_FALSE, TRUE }, 4040 { testW, SIC_COMPLEX, S_OK }, 4041 { testW, 0, S_FALSE }, 4042 }; 4043 unsigned int i; 4044 HRESULT hr; 4045 4046 hr = ScriptIsComplex(NULL, 0, 0); 4047 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* winxp/vista */, "got 0x%08x\n", hr); 4048 4049 if (hr == E_INVALIDARG) 4050 { 4051 hr = ScriptIsComplex(NULL, 1, 0); 4052 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 4053 } 4054 4055 hr = ScriptIsComplex(test2W, -1, SIC_ASCIIDIGIT); 4056 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* winxp/vista */, "got 0x%08x\n", hr); 4057 4058 hr = ScriptIsComplex(test2W, 0, SIC_ASCIIDIGIT); 4059 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4060 4061 for (i = 0; i < sizeof(complex_tests)/sizeof(complex_tests[0]); i++) 4062 { 4063 hr = ScriptIsComplex(complex_tests[i].text, lstrlenW(complex_tests[i].text), complex_tests[i].flags); 4064 todo_wine_if(complex_tests[i].todo) 4065 ok(hr == complex_tests[i].hr, "%u: got %#x, expected %#x, flags %#x\n", i, hr, complex_tests[i].hr, 4066 complex_tests[i].flags); 4067 } 4068 4069 hr = ScriptIsComplex(test2W, 1, ~0u); 4070 ok(hr == S_OK, "got 0x%08x\n", hr); 4071 4072 hr = ScriptIsComplex(testW, 3, 0); 4073 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4074 4075 hr = ScriptIsComplex(testW, 3, SIC_NEUTRAL | SIC_COMPLEX); 4076 ok(hr == S_OK, "got 0x%08x\n", hr); 4077 4078 hr = ScriptIsComplex(testW, 3, SIC_COMPLEX); 4079 ok(hr == S_OK, "got 0x%08x\n", hr); 4080 4081 hr = ScriptIsComplex(test2W, 1, SIC_COMPLEX); 4082 ok(hr == S_FALSE, "got 0x%08x\n", hr); 4083 } 4084 4085 static void test_ScriptString_pSize(HDC hdc) 4086 { 4087 static const WCHAR textW[] = {'A',0}; 4088 SCRIPT_STRING_ANALYSIS ssa; 4089 const SIZE *size; 4090 TEXTMETRICW tm; 4091 HRESULT hr; 4092 ABC abc; 4093 4094 hr = ScriptStringAnalyse(hdc, textW, 1, 16, -1, SSA_GLYPHS, 0, NULL, NULL, NULL, NULL, NULL, &ssa); 4095 ok(hr == S_OK, "ScriptStringAnalyse failed, hr %#x.\n", hr); 4096 4097 size = ScriptString_pSize(NULL); 4098 ok(size == NULL || broken(size != NULL) /* <win7 */, "Unexpected size pointer.\n"); 4099 4100 GetCharABCWidthsW(hdc, textW[0], textW[0], &abc); 4101 4102 memset(&tm, 0, sizeof(tm)); 4103 GetTextMetricsW(hdc, &tm); 4104 ok(tm.tmHeight > 0, "Unexpected tmHeight.\n"); 4105 4106 size = ScriptString_pSize(ssa); 4107 ok(size != NULL, "Unexpected size pointer.\n"); 4108 ok(size->cx == abc.abcA + abc.abcB + abc.abcC, "Unexpected cx size %d.\n", size->cx); 4109 ok(size->cy == tm.tmHeight, "Unexpected cy size %d.\n", size->cy); 4110 4111 hr = ScriptStringFree(&ssa); 4112 ok(hr == S_OK, "Failed to free ssa, hr %#x.\n", hr); 4113 } 4114 4115 static void init_tests(void) 4116 { 4117 HMODULE module = GetModuleHandleA("usp10.dll"); 4118 4119 ok(module != 0, "Expected usp10.dll to be loaded.\n"); 4120 4121 pScriptItemizeOpenType = (void *)GetProcAddress(module, "ScriptItemizeOpenType"); 4122 pScriptShapeOpenType = (void *)GetProcAddress(module, "ScriptShapeOpenType"); 4123 pScriptGetFontScriptTags = (void *)GetProcAddress(module, "ScriptGetFontScriptTags"); 4124 pScriptGetFontLanguageTags = (void *)GetProcAddress(module, "ScriptGetFontLanguageTags"); 4125 pScriptGetFontFeatureTags = (void *)GetProcAddress(module, "ScriptGetFontFeatureTags"); 4126 } 4127 4128 START_TEST(usp10) 4129 { 4130 HWND hwnd; 4131 HDC hdc; 4132 LOGFONTA lf; 4133 HFONT hfont; 4134 4135 unsigned short pwOutGlyphs[256]; 4136 4137 /* We need a valid HDC to drive a lot of Script functions which requires the following * 4138 * to set up for the tests. */ 4139 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100, 4140 0, 0, 0, NULL); 4141 assert(hwnd != 0); 4142 ShowWindow(hwnd, SW_SHOW); 4143 UpdateWindow(hwnd); 4144 4145 hdc = GetDC(hwnd); /* We now have a hdc */ 4146 ok( hdc != NULL, "HDC failed to be created %p\n", hdc); 4147 4148 memset(&lf, 0, sizeof(LOGFONTA)); 4149 lstrcpyA(lf.lfFaceName, "Tahoma"); 4150 lf.lfHeight = 10; 4151 lf.lfWeight = 3; 4152 lf.lfWidth = 10; 4153 4154 hfont = SelectObject(hdc, CreateFontIndirectA(&lf)); 4155 ok(hfont != NULL, "SelectObject failed: %p\n", hfont); 4156 4157 init_tests(); 4158 4159 test_ScriptItemize(); 4160 test_ScriptItemize_surrogates(); 4161 test_ScriptItemIzeShapePlace(hdc,pwOutGlyphs); 4162 test_ScriptGetCMap(hdc, pwOutGlyphs); 4163 test_ScriptCacheGetHeight(hdc); 4164 test_ScriptGetGlyphABCWidth(hdc); 4165 test_ScriptShape(hdc); 4166 test_ScriptShapeOpenType(hdc); 4167 test_ScriptPlace(hdc); 4168 4169 test_ScriptGetFontProperties(hdc); 4170 test_ScriptTextOut(hdc); 4171 test_ScriptTextOut2(hdc); 4172 test_ScriptTextOut3(hdc); 4173 test_ScriptXtoX(); 4174 test_ScriptString(hdc); 4175 test_ScriptStringXtoCP_CPtoX(hdc); 4176 test_ScriptString_pSize(hdc); 4177 4178 test_ScriptLayout(); 4179 test_digit_substitution(); 4180 test_ScriptGetProperties(); 4181 test_ScriptBreak(); 4182 test_newlines(); 4183 4184 test_ScriptGetFontFunctions(hdc); 4185 test_ScriptGetLogicalWidths(); 4186 4187 test_ScriptIsComplex(); 4188 4189 ReleaseDC(hwnd, hdc); 4190 DestroyWindow(hwnd); 4191 } 4192