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