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