4 * Copyright 2006 Jeff Latimer
5 * Copyright 2006 Hans Leidekker
6 * Copyright 2010 CodeWeavers, Aric Stewart
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.
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.
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
23 * Uniscribe allows for processing of complex scripts such as joining
24 * and filtering characters and bi-directional text with custom line breaks.
30 #include <wine/test.h>
34 typedef struct _itemTest
{
43 typedef struct _shapeTest_char
{
45 SCRIPT_CHARPROP CharProp
;
48 typedef struct _shapeTest_glyph
{
50 SCRIPT_GLYPHPROP GlyphProp
;
53 /* Uniscribe 1.6 calls */
54 static HRESULT (WINAPI
*pScriptItemizeOpenType
)( const WCHAR
*pwcInChars
, int cInChars
, int cMaxItems
, const SCRIPT_CONTROL
*psControl
, const SCRIPT_STATE
*psState
, SCRIPT_ITEM
*pItems
, ULONG
*pScriptTags
, int *pcItems
);
56 static HRESULT (WINAPI
*pScriptShapeOpenType
)( HDC hdc
, SCRIPT_CACHE
*psc
, SCRIPT_ANALYSIS
*psa
, OPENTYPE_TAG tagScript
, OPENTYPE_TAG tagLangSys
, int *rcRangeChars
, TEXTRANGE_PROPERTIES
**rpRangeProperties
, int cRanges
, const WCHAR
*pwcChars
, int cChars
, int cMaxGlyphs
, WORD
*pwLogClust
, SCRIPT_CHARPROP
*pCharProps
, WORD
*pwOutGlyphs
, SCRIPT_GLYPHPROP
*pOutGlyphProps
, int *pcGlyphs
);
58 static DWORD (WINAPI
*pGetGlyphIndicesW
)(HDC hdc
, LPCWSTR lpstr
, INT count
, LPWORD pgi
, DWORD flags
);
60 static inline void _test_items_ok(LPCWSTR string
, DWORD cchString
,
61 SCRIPT_CONTROL
*Control
, SCRIPT_STATE
*State
,
62 DWORD nItems
, const itemTest
* items
, BOOL nItemsToDo
,
67 SCRIPT_ITEM outpItems
[15];
68 ULONG tags
[15] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
70 if (pScriptItemizeOpenType
)
71 hr
= pScriptItemizeOpenType(string
, cchString
, 15, Control
, State
, outpItems
, tags
, &outnItems
);
73 hr
= ScriptItemize(string
, cchString
, 15, Control
, State
, outpItems
, &outnItems
);
75 winetest_ok(!hr
, "ScriptItemize should return S_OK not %08x\n", hr
);
76 if (nItemsBroken
&& broken(nItemsBroken
== outnItems
))
78 winetest_win_skip("This test broken on this platform\n");
82 todo_wine
winetest_ok(outnItems
== nItems
, "Wrong number of items\n");
84 winetest_ok(outnItems
== nItems
, "Wrong number of items\n");
85 for (x
= 0; x
<= outnItems
; x
++)
87 if (items
[x
].todo_flag
[0])
88 todo_wine
winetest_ok(outpItems
[x
].iCharPos
== items
[x
].iCharPos
, "%i:Wrong CharPos\n",x
);
90 winetest_ok(outpItems
[x
].iCharPos
== items
[x
].iCharPos
, "%i:Wrong CharPos (%i)\n",x
,outpItems
[x
].iCharPos
);
92 if (items
[x
].todo_flag
[1])
93 todo_wine
winetest_ok(outpItems
[x
].a
.fRTL
== items
[x
].fRTL
, "%i:Wrong fRTL\n",x
);
95 winetest_ok(outpItems
[x
].a
.fRTL
== items
[x
].fRTL
, "%i:Wrong fRTL(%i)\n",x
,outpItems
[x
].a
.fRTL
);
96 if (items
[x
].todo_flag
[2])
97 todo_wine
winetest_ok(outpItems
[x
].a
.fLayoutRTL
== items
[x
].fLayoutRTL
, "%i:Wrong fLayoutRTL\n",x
);
99 winetest_ok(outpItems
[x
].a
.fLayoutRTL
== items
[x
].fLayoutRTL
, "%i:Wrong fLayoutRTL(%i)\n",x
,outpItems
[x
].a
.fLayoutRTL
);
100 if (items
[x
].todo_flag
[3])
101 todo_wine
winetest_ok(outpItems
[x
].a
.s
.uBidiLevel
== items
[x
].uBidiLevel
, "%i:Wrong BidiLevel\n",x
);
103 winetest_ok(outpItems
[x
].a
.s
.uBidiLevel
== items
[x
].uBidiLevel
, "%i:Wrong BidiLevel(%i)\n",x
,outpItems
[x
].a
.s
.uBidiLevel
);
105 winetest_ok(outpItems
[x
].a
.eScript
!= SCRIPT_UNDEFINED
, "%i: Undefined script\n",x
);
106 if (pScriptItemizeOpenType
)
108 if (items
[x
].todo_flag
[4])
109 todo_wine
winetest_ok(tags
[x
] == items
[x
].scriptTag
,"%i:Incorrect Script Tag %x != %x\n",x
,tags
[x
],items
[x
].scriptTag
);
111 winetest_ok(tags
[x
] == items
[x
].scriptTag
,"%i:Incorrect Script Tag %x != %x\n",x
,tags
[x
],items
[x
].scriptTag
);
116 #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 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
119 ( ( (ULONG)_x4 << 24 ) | \
120 ( (ULONG)_x3 << 16 ) | \
121 ( (ULONG)_x2 << 8 ) | \
124 #define latn_tag MS_MAKE_TAG('l','a','t','n')
125 #define arab_tag MS_MAKE_TAG('a','r','a','b')
126 #define thai_tag MS_MAKE_TAG('t','h','a','i')
127 #define hebr_tag MS_MAKE_TAG('h','e','b','r')
128 #define syrc_tag MS_MAKE_TAG('s','y','r','c')
129 #define deva_tag MS_MAKE_TAG('d','e','v','a')
130 #define beng_tag MS_MAKE_TAG('b','e','n','g')
131 #define guru_tag MS_MAKE_TAG('g','u','r','u')
132 #define gujr_tag MS_MAKE_TAG('g','u','j','r')
133 #define orya_tag MS_MAKE_TAG('o','r','y','a')
134 #define taml_tag MS_MAKE_TAG('t','a','m','l')
135 #define telu_tag MS_MAKE_TAG('t','e','l','u')
136 #define knda_tag MS_MAKE_TAG('k','n','d','a')
138 static void test_ScriptItemize( void )
140 static const WCHAR test1
[] = {'t', 'e', 's', 't',0};
141 static const itemTest t11
[2] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},4,0,0,0,-1}};
142 static const itemTest t12
[2] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},4,0,0,0,-1}};
144 static const WCHAR test1b
[] = {' ', ' ', ' ', ' ',0};
145 static const itemTest t1b1
[2] = {{{0,0,0,0,0},0,0,0,0,0},{{0,0,0,0,0},4,0,0,0,-1}};
146 static const itemTest t1b2
[2] = {{{0,0,0,0,0},0,1,1,1,0},{{0,0,0,0,0},4,0,0,0,-1}};
149 static const WCHAR test2
[] = {'1','2','3','-','5','2',0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,'7','1','.',0};
150 static const itemTest t21
[7] = {{{0,0,0,0,0},0,0,0,0,0},{{0,0,0,0,0},3,0,0,0,0},{{0,0,0,0,0},4,0,0,0,0},{{0,0,0,0,0},6,1,1,1,arab_tag
},{{0,0,0,0,0},13,0,0,0,0},{{0,0,0,0,0},15,0,0,0,0},{{0,0,0,0,0},16,0,0,0,-1}};
151 static const itemTest t22
[5] = {{{0,0,0,1,0},0,0,0,2,0},{{0,0,0,0,0},6,1,1,1,arab_tag
},{{0,0,1,0,0},13,0,1,2,0},{{0,0,0,0,0},15,0,0,0,0},{{0,0,0,0,0},16,0,0,0,-1}};
152 static const itemTest t23
[5] = {{{0,0,1,0,0},0,0,1,2,0},{{0,0,0,0,0},6,1,1,1,arab_tag
},{{0,0,1,0,0},13,0,1,2,0},{{0,0,0,0,0},15,1,1,1,0},{{0,0,0,0,0},16,0,0,0,-1}};
154 static const WCHAR test2b
[] = {'A','B','C','-','D','E','F',' ',0x0621,0x0623,0x0624,0};
155 static const itemTest t2b1
[5] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},3,0,0,0,0},{{0,0,0,0,0},4,0,0,0,latn_tag
},{{0,0,0,0,0},8,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
156 static const itemTest t2b2
[5] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},3,0,0,2,0},{{0,0,0,0,0},4,0,0,2,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
157 static const itemTest t2b3
[3] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
160 static const WCHAR test2c
[] = {' ',0x0621,0x0623,0x0624,'A','B','C','-','D','E','F',0};
161 static const itemTest t2c1
[5] = {{{0,0,0,0,0},0,1,1,1,arab_tag
},{{0,0,0,0,0},4,0,0,0,latn_tag
},{{0,0,0,0,0},7,0,0,0,0},{{0,0,0,0,0},8,0,0,0,latn_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
162 static const itemTest t2c2
[6] = {{{0,0,0,0,1},0,0,0,0,0},{{0,0,0,0,0},1,1,1,1,arab_tag
},{{0,0,0,0,0},4,0,0,0,latn_tag
},{{0,0,0,0,0},7,0,0,0,0},{{0,0,0,0,0},8,0,0,0,latn_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
163 static const itemTest t2c3
[5] = {{{0,0,0,0,0},0,1,1,1,arab_tag
},{{0,0,0,0,0},4,0,0,2,latn_tag
},{{0,0,0,0,0},7,0,0,2,0},{{0,0,0,0,0},8,0,0,2,latn_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
164 static const itemTest t2c4
[3] = {{{0,0,0,0,0},0,1,1,1,arab_tag
},{{0,0,0,0,0},4,0,0,2,latn_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
167 static const WCHAR test2d
[] = {'A','B','C','-','D','E','F',0x0621,0x0623,0x0624,' ',0};
168 static const itemTest t2d1
[5] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},3,0,0,0,0},{{0,0,0,0,0},4,0,0,0,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
169 static const itemTest t2d2
[6] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},3,0,0,0,0},{{0,0,0,0,0},4,0,0,0,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},10,0,0,0,0},{{0,0,0,0,0},11,0,0,0,-1}};
170 static const itemTest t2d3
[5] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},3,0,0,2,0},{{0,0,0,0,0},4,0,0,2,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
171 static const itemTest t2d4
[3] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},7,1,1,1,arab_tag
},{{0,0,0,0,0},11,0,0,0,-1}};
174 static const WCHAR test3
[] =
175 {0x0e04,0x0e27,0x0e32,0x0e21,0x0e1e,0x0e22,0x0e32,0x0e22,0x0e32, 0x0e21
176 ,0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e44,0x0e2b,0x0e19
177 ,0x0e04,0x0e27,0x0e32,0x0e21,0x0e2a, 0x0e33,0x0e40,0x0e23,0x0e47,0x0e08,
178 0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e19,0x0e31,0x0e48,0x0e19,0};
180 static const itemTest t31
[2] = {{{0,0,0,0,0},0,0,0,0,thai_tag
},{{0,0,0,0,0},41,0,0,0,-1}};
181 static const itemTest t32
[2] = {{{0,0,0,0,0},0,0,0,2,thai_tag
},{{0,0,0,0,0},41,0,0,0,-1}};
183 static const WCHAR test4
[] = {'1','2','3','-','5','2',' ','i','s',' ','7','1','.',0};
185 static const itemTest t41
[6] = {{{0,0,0,0,0},0,0,0,0,0},{{0,0,0,0,0},3,0,0,0,0},{{0,0,0,0,0},4,0,0,0,0},{{0,0,0,0,0},7,0,0,0,latn_tag
},{{0,0,0,0,0},10,0,0,0,0},{{0,0,0,0,0},12,0,0,0,-1}};
186 static const itemTest t42
[5] = {{{0,0,1,0,0},0,0,1,2,0},{{0,0,0,0,1},6,1,1,1,0},{{0,0,0,0,0},7,0,0,2,latn_tag
},{{0,0,0,0,0},10,0,0,2,0},{{0,0,0,0,0},12,0,0,0,-1}};
187 static const itemTest t43
[4] = {{{0,0,1,0,0},0,0,1,2,0},{{0,0,0,0,1},6,1,1,1,0},{{0,0,0,0,0},7,0,0,2,latn_tag
},{{0,0,0,0,0},12,0,0,0,-1}};
190 static const WCHAR test5
[] =
191 {0x0627,0x0644,0x0635,0x0651,0x0650,0x062d,0x0629,0x064f,' ',0x062a,0x064e,
192 0x0627,0x062c,0x064c,' ',0x0639,0x064e,0x0644,0x0649,' ',
193 0x0631,0x064f,0x0624,0x0648,0x0633,0x0650,' ',0x0627,0x0644
194 ,0x0623,0x0635,0x0650,0x062d,0x0651,0x064e,0x0627,0x0621,0x0650,0};
195 static const itemTest t51
[2] = {{{0,0,0,0,0},0,1,1,1,arab_tag
},{{0,0,0,0,0},38,0,0,0,-1}};
198 static const WCHAR test6
[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd, '.',0};
199 static const itemTest t61
[3] = {{{0,0,0,0,0},0,1,1,1,hebr_tag
},{{0,0,0,0,0},4,0,0,0,0},{{0,0,0,0,0},5,0,0,0,-1}};
200 static const itemTest t62
[3] = {{{0,0,0,0,0},0,1,1,1,hebr_tag
},{{0,0,0,0,0},4,1,1,1,0},{{0,0,0,0,0},5,0,0,0,-1}};
201 static const itemTest t63
[2] = {{{0,0,0,0,0},0,1,1,1,hebr_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
202 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};
203 static const itemTest t71
[4] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},9,1,1,1,hebr_tag
},{{0,0,0,0,0},19,0,0,0,latn_tag
},{{0,0,0,0,0},29,0,0,0,-1}};
204 static const itemTest t72
[4] = {{{0,0,0,0,0},0,0,0,0,latn_tag
},{{0,0,0,0,0},9,1,1,1,hebr_tag
},{{0,0,0,0,0},18,0,0,0,latn_tag
},{{0,0,0,0,0},29,0,0,0,-1}};
205 static const itemTest t73
[4] = {{{0,0,0,0,0},0,0,0,2,latn_tag
},{{0,0,0,0,0},8,1,1,1,hebr_tag
},{{0,0,0,0,0},19,0,0,2,latn_tag
},{{0,0,0,0,0},29,0,0,0,-1}};
206 static const WCHAR test8
[] = {0x0633, 0x0644, 0x0627, 0x0645,0};
207 static const itemTest t81
[2] = {{{0,0,0,0,0},0,1,1,1,arab_tag
},{{0,0,0,0,0},4,0,0,0,-1}};
209 /* Syriac (Like Arabic )*/
210 static const WCHAR test9
[] = {0x0710, 0x0712, 0x0712, 0x0714, '.',0};
211 static const itemTest t91
[3] = {{{0,0,0,0,0},0,1,1,1,syrc_tag
},{{0,0,0,0,0},4,0,0,0,0},{{0,0,0,0,0},5,0,0,0,-1}};
212 static const itemTest t92
[3] = {{{0,0,0,0,0},0,1,1,1,syrc_tag
},{{0,0,0,0,0},4,1,1,1,0},{{0,0,0,0,0},5,0,0,0,-1}};
213 static const itemTest t93
[2] = {{{0,0,0,0,0},0,1,1,1,syrc_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
215 static const WCHAR test10
[] = {0x0717, 0x0718, 0x071a, 0x071b,0};
216 static const itemTest t101
[2] = {{{0,0,0,0,0},0,1,1,1,syrc_tag
},{{0,0,0,0,0},4,0,0,0,-1}};
219 static const WCHAR test11
[] = {0x0926, 0x0947, 0x0935, 0x0928, 0x093e, 0x0917, 0x0930, 0x0940};
220 static const itemTest t111
[2] = {{{0,0,0,0,0},0,0,0,0,deva_tag
},{{0,0,0,0,0},8,0,0,0,-1}};
221 static const itemTest t112
[2] = {{{0,0,0,0,0},0,0,0,2,deva_tag
},{{0,0,0,0,0},8,0,0,0,-1}};
224 static const WCHAR test12
[] = {0x09ac, 0x09be, 0x0982, 0x09b2, 0x09be};
225 static const itemTest t121
[2] = {{{0,0,0,0,0},0,0,0,0,beng_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
226 static const itemTest t122
[2] = {{{0,0,0,0,0},0,0,0,2,beng_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
229 static const WCHAR test13
[] = {0x0a17, 0x0a41, 0x0a30, 0x0a2e, 0x0a41, 0x0a16, 0x0a40};
230 static const itemTest t131
[2] = {{{0,0,0,0,0},0,0,0,0,guru_tag
},{{0,0,0,0,0},7,0,0,0,-1}};
231 static const itemTest t132
[2] = {{{0,0,0,0,0},0,0,0,2,guru_tag
},{{0,0,0,0,0},7,0,0,0,-1}};
234 static const WCHAR test14
[] = {0x0a97, 0x0ac1, 0x0a9c, 0x0ab0, 0x0abe, 0x0aa4, 0x0ac0};
235 static const itemTest t141
[2] = {{{0,0,0,0,0},0,0,0,0,gujr_tag
},{{0,0,0,0,0},7,0,0,0,-1}};
236 static const itemTest t142
[2] = {{{0,0,0,0,0},0,0,0,2,gujr_tag
},{{0,0,0,0,0},7,0,0,0,-1}};
239 static const WCHAR test15
[] = {0x0b13, 0x0b21, 0x0b3c, 0x0b3f, 0x0b06};
240 static const itemTest t151
[2] = {{{0,0,0,0,0},0,0,0,0,orya_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
241 static const itemTest t152
[2] = {{{0,0,0,0,0},0,0,0,2,orya_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
244 static const WCHAR test16
[] = {0x0ba4, 0x0bae, 0x0bbf, 0x0bb4, 0x0bcd};
245 static const itemTest t161
[2] = {{{0,0,0,0,0},0,0,0,0,taml_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
246 static const itemTest t162
[2] = {{{0,0,0,0,0},0,0,0,2,taml_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
249 static const WCHAR test17
[] = {0x0c24, 0x0c46, 0x0c32, 0x0c41, 0x0c17, 0x0c41};
250 static const itemTest t171
[2] = {{{0,0,0,0,0},0,0,0,0,telu_tag
},{{0,0,0,0,0},6,0,0,0,-1}};
251 static const itemTest t172
[2] = {{{0,0,0,0,0},0,0,0,2,telu_tag
},{{0,0,0,0,0},6,0,0,0,-1}};
254 static const WCHAR test18
[] = {0x0c95, 0x0ca8, 0x0ccd, 0x0ca8, 0x0ca1};
255 static const itemTest t181
[2] = {{{0,0,0,0,0},0,0,0,0,knda_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
256 static const itemTest t182
[2] = {{{0,0,0,0,0},0,0,0,2,knda_tag
},{{0,0,0,0,0},5,0,0,0,-1}};
258 SCRIPT_ITEM items
[15];
259 SCRIPT_CONTROL Control
;
265 usp10
= LoadLibraryA("usp10.dll");
266 ok (usp10
!= 0,"Unable to LoadLibrary on usp10.dll\n");
267 pScriptItemizeOpenType
= (void*)GetProcAddress(usp10
, "ScriptItemizeOpenType");
268 pScriptShapeOpenType
= (void*)GetProcAddress(usp10
, "ScriptShapeOpenType");
269 pGetGlyphIndicesW
= (void*)GetProcAddress(GetModuleHandleA("gdi32.dll"), "GetGlyphIndicesW");
271 memset(&Control
, 0, sizeof(Control
));
272 memset(&State
, 0, sizeof(State
));
274 hr
= ScriptItemize(NULL
, 4, 10, &Control
, &State
, items
, NULL
);
275 ok (hr
== E_INVALIDARG
, "ScriptItemize should return E_INVALIDARG if pwcInChars is NULL\n");
277 hr
= ScriptItemize(test1
, 4, 10, &Control
, &State
, NULL
, NULL
);
278 ok (hr
== E_INVALIDARG
, "ScriptItemize should return E_INVALIDARG if pItems is NULL\n");
280 hr
= ScriptItemize(test1
, 4, 1, &Control
, &State
, items
, NULL
);
281 ok (hr
== E_INVALIDARG
, "ScriptItemize should return E_INVALIDARG if cMaxItems < 2.\n");
283 hr
= ScriptItemize(test1
, 0, 10, NULL
, NULL
, items
, &nItems
);
284 ok (hr
== E_INVALIDARG
, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n");
286 test_items_ok(test1
,4,NULL
,NULL
,1,t11
,FALSE
,0);
287 test_items_ok(test1b
,4,NULL
,NULL
,1,t1b1
,FALSE
,0);
288 test_items_ok(test2
,16,NULL
,NULL
,6,t21
,FALSE
,0);
289 test_items_ok(test2b
,11,NULL
,NULL
,4,t2b1
,FALSE
,0);
290 test_items_ok(test2c
,11,NULL
,NULL
,4,t2c1
,FALSE
,0);
291 test_items_ok(test2d
,11,NULL
,NULL
,4,t2d1
,FALSE
,0);
292 test_items_ok(test3
,41,NULL
,NULL
,1,t31
,FALSE
,0);
293 test_items_ok(test4
,12,NULL
,NULL
,5,t41
,FALSE
,0);
294 test_items_ok(test5
,38,NULL
,NULL
,1,t51
,FALSE
,0);
295 test_items_ok(test6
,5,NULL
,NULL
,2,t61
,FALSE
,0);
296 test_items_ok(test7
,29,NULL
,NULL
,3,t71
,FALSE
,0);
297 test_items_ok(test8
,4,NULL
,NULL
,1,t81
,FALSE
,0);
298 test_items_ok(test9
,5,NULL
,NULL
,2,t91
,FALSE
,0);
299 test_items_ok(test10
,4,NULL
,NULL
,1,t101
,FALSE
,0);
300 test_items_ok(test11
,8,NULL
,NULL
,1,t111
,FALSE
,0);
301 test_items_ok(test12
,5,NULL
,NULL
,1,t121
,FALSE
,0);
302 test_items_ok(test13
,7,NULL
,NULL
,1,t131
,FALSE
,0);
303 test_items_ok(test14
,7,NULL
,NULL
,1,t141
,FALSE
,0);
304 test_items_ok(test15
,5,NULL
,NULL
,1,t151
,FALSE
,0);
305 test_items_ok(test16
,5,NULL
,NULL
,1,t161
,FALSE
,0);
306 test_items_ok(test17
,6,NULL
,NULL
,1,t171
,FALSE
,0);
307 test_items_ok(test18
,5,NULL
,NULL
,1,t181
,FALSE
,0);
309 State
.uBidiLevel
= 0;
310 test_items_ok(test1
,4,&Control
,&State
,1,t11
,FALSE
,0);
311 test_items_ok(test1b
,4,&Control
,&State
,1,t1b1
,FALSE
,0);
312 test_items_ok(test2
,16,&Control
,&State
,4,t22
,FALSE
,0);
313 test_items_ok(test2b
,11,&Control
,&State
,4,t2b1
,FALSE
,0);
314 test_items_ok(test2c
,11,&Control
,&State
,5,t2c2
,FALSE
,0);
315 test_items_ok(test2d
,11,&Control
,&State
,5,t2d2
,FALSE
,0);
316 test_items_ok(test3
,41,&Control
,&State
,1,t31
,FALSE
,0);
317 test_items_ok(test4
,12,&Control
,&State
,5,t41
,FALSE
,0);
318 test_items_ok(test5
,38,&Control
,&State
,1,t51
,FALSE
,0);
319 test_items_ok(test6
,5,&Control
,&State
,2,t61
,FALSE
,0);
320 test_items_ok(test7
,29,&Control
,&State
,3,t72
,FALSE
,0);
321 test_items_ok(test8
,4,&Control
,&State
,1,t81
,FALSE
,0);
322 test_items_ok(test9
,5,&Control
,&State
,2,t91
,FALSE
,0);
323 test_items_ok(test10
,4,&Control
,&State
,1,t101
,FALSE
,0);
324 test_items_ok(test11
,8,&Control
,&State
,1,t111
,FALSE
,0);
325 test_items_ok(test12
,5,&Control
,&State
,1,t121
,FALSE
,0);
326 test_items_ok(test13
,7,&Control
,&State
,1,t131
,FALSE
,0);
327 test_items_ok(test14
,7,&Control
,&State
,1,t141
,FALSE
,0);
328 test_items_ok(test15
,5,&Control
,&State
,1,t151
,FALSE
,0);
329 test_items_ok(test16
,5,&Control
,&State
,1,t161
,FALSE
,0);
330 test_items_ok(test17
,6,&Control
,&State
,1,t171
,FALSE
,0);
331 test_items_ok(test18
,5,&Control
,&State
,1,t181
,FALSE
,0);
333 State
.uBidiLevel
= 1;
334 test_items_ok(test1
,4,&Control
,&State
,1,t12
,FALSE
,0);
335 test_items_ok(test1b
,4,&Control
,&State
,1,t1b2
,FALSE
,0);
336 test_items_ok(test2
,16,&Control
,&State
,4,t23
,FALSE
,0);
337 test_items_ok(test2b
,11,&Control
,&State
,4,t2b2
,FALSE
,0);
338 test_items_ok(test2c
,11,&Control
,&State
,4,t2c3
,FALSE
,0);
339 test_items_ok(test2d
,11,&Control
,&State
,4,t2d3
,FALSE
,0);
340 test_items_ok(test3
,41,&Control
,&State
,1,t32
,FALSE
,0);
341 test_items_ok(test4
,12,&Control
,&State
,4,t42
,FALSE
,0);
342 test_items_ok(test5
,38,&Control
,&State
,1,t51
,FALSE
,0);
343 test_items_ok(test6
,5,&Control
,&State
,2,t62
,FALSE
,0);
344 test_items_ok(test7
,29,&Control
,&State
,3,t73
,FALSE
,0);
345 test_items_ok(test8
,4,&Control
,&State
,1,t81
,FALSE
,0);
346 test_items_ok(test9
,5,&Control
,&State
,2,t92
,FALSE
,0);
347 test_items_ok(test10
,4,&Control
,&State
,1,t101
,FALSE
,0);
348 test_items_ok(test11
,8,&Control
,&State
,1,t112
,FALSE
,0);
349 test_items_ok(test12
,5,&Control
,&State
,1,t122
,FALSE
,0);
350 test_items_ok(test13
,7,&Control
,&State
,1,t132
,FALSE
,0);
351 test_items_ok(test14
,7,&Control
,&State
,1,t142
,FALSE
,0);
352 test_items_ok(test15
,5,&Control
,&State
,1,t152
,FALSE
,0);
353 test_items_ok(test16
,5,&Control
,&State
,1,t162
,FALSE
,0);
354 test_items_ok(test17
,6,&Control
,&State
,1,t172
,FALSE
,0);
355 test_items_ok(test18
,5,&Control
,&State
,1,t182
,FALSE
,0);
357 State
.uBidiLevel
= 1;
358 Control
.fMergeNeutralItems
= TRUE
;
359 test_items_ok(test1
,4,&Control
,&State
,1,t12
,FALSE
,0);
360 test_items_ok(test1b
,4,&Control
,&State
,1,t1b2
,FALSE
,0);
361 test_items_ok(test2
,16,&Control
,&State
,4,t23
,FALSE
,0);
362 test_items_ok(test2b
,11,&Control
,&State
,2,t2b3
,FALSE
,4);
363 test_items_ok(test2c
,11,&Control
,&State
,2,t2c4
,FALSE
,4);
364 test_items_ok(test2d
,11,&Control
,&State
,2,t2d4
,FALSE
,4);
365 test_items_ok(test3
,41,&Control
,&State
,1,t32
,FALSE
,0);
366 test_items_ok(test4
,12,&Control
,&State
,3,t43
,FALSE
,4);
367 test_items_ok(test5
,38,&Control
,&State
,1,t51
,FALSE
,0);
368 test_items_ok(test6
,5,&Control
,&State
,1,t63
,FALSE
,2);
369 test_items_ok(test7
,29,&Control
,&State
,3,t73
,FALSE
,0);
370 test_items_ok(test8
,4,&Control
,&State
,1,t81
,FALSE
,0);
371 test_items_ok(test9
,5,&Control
,&State
,1,t93
,FALSE
,2);
372 test_items_ok(test10
,4,&Control
,&State
,1,t101
,FALSE
,0);
373 test_items_ok(test11
,8,&Control
,&State
,1,t112
,FALSE
,0);
374 test_items_ok(test12
,5,&Control
,&State
,1,t122
,FALSE
,0);
375 test_items_ok(test13
,7,&Control
,&State
,1,t132
,FALSE
,0);
376 test_items_ok(test14
,7,&Control
,&State
,1,t142
,FALSE
,0);
377 test_items_ok(test15
,5,&Control
,&State
,1,t152
,FALSE
,0);
378 test_items_ok(test16
,5,&Control
,&State
,1,t162
,FALSE
,0);
379 test_items_ok(test17
,6,&Control
,&State
,1,t172
,FALSE
,0);
380 test_items_ok(test18
,5,&Control
,&State
,1,t182
,FALSE
,0);
383 static inline void _test_shape_ok(int valid
, HDC hdc
, LPCWSTR string
,
384 DWORD cchString
, SCRIPT_CONTROL
*Control
,
385 SCRIPT_STATE
*State
, DWORD item
, DWORD nGlyphs
,
386 const shapeTest_char
* charItems
,
387 const shapeTest_glyph
* glyphItems
)
390 int x
, outnItems
=0, outnGlyphs
=0;
391 SCRIPT_ITEM outpItems
[15];
392 SCRIPT_CACHE sc
= NULL
;
395 int maxGlyphs
= cchString
* 1.5;
396 SCRIPT_GLYPHPROP
*glyphProp
;
397 SCRIPT_CHARPROP
*charProp
;
400 hr
= pScriptItemizeOpenType(string
, cchString
, 15, Control
, State
, outpItems
, tags
, &outnItems
);
401 if (hr
== USP_E_SCRIPT_NOT_IN_FONT
)
404 winetest_win_skip("Select font does not support script\n");
406 winetest_trace("Select font does not support script\n");
410 winetest_ok(!hr
, "ScriptItemizeOpenType should return S_OK not %08x\n", hr
);
412 winetest_trace("ScriptItemizeOpenType should return S_OK not %08x\n", hr
);
415 if (outnItems
<= item
)
418 winetest_win_skip("Did not get enough items\n");
420 winetest_trace("Did not get enough items\n");
424 logclust
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORD
) * cchString
);
425 memset(logclust
,'a',sizeof(WORD
) * cchString
);
426 charProp
= HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_CHARPROP
) * cchString
);
427 memset(charProp
,'a',sizeof(SCRIPT_CHARPROP
) * cchString
);
428 glyphs
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORD
) * maxGlyphs
);
429 memset(glyphs
,'a',sizeof(WORD
) * cchString
);
430 glyphProp
= HeapAlloc(GetProcessHeap(), 0, sizeof(SCRIPT_GLYPHPROP
) * maxGlyphs
);
431 memset(glyphProp
,'a',sizeof(SCRIPT_GLYPHPROP
) * cchString
);
433 hr
= pScriptShapeOpenType(hdc
, &sc
, &outpItems
[item
].a
, tags
[item
], 0x00000000, NULL
, NULL
, 0, string
, cchString
, maxGlyphs
, logclust
, charProp
, glyphs
, glyphProp
, &outnGlyphs
);
435 winetest_ok(hr
== S_OK
, "ScriptShapeOpenType failed (%x)\n",hr
);
437 winetest_trace("ScriptShapeOpenType failed (%x)\n",hr
);
441 for (x
= 0; x
< cchString
; x
++)
444 winetest_ok(logclust
[x
] == charItems
[x
].wLogClust
, "%i: invalid LogClust(%i)\n",x
,logclust
[x
]);
445 else if (logclust
[x
] != charItems
[x
].wLogClust
)
446 winetest_trace("%i: invalid LogClust(%i)\n",x
,logclust
[x
]);
448 winetest_ok(charProp
[x
].fCanGlyphAlone
== charItems
[x
].CharProp
.fCanGlyphAlone
, "%i: invalid fCanGlyphAlone\n",x
);
449 else if (charProp
[x
].fCanGlyphAlone
!= charItems
[x
].CharProp
.fCanGlyphAlone
)
450 winetest_trace("%i: invalid fCanGlyphAlone\n",x
);
454 winetest_ok(nGlyphs
== outnGlyphs
, "got incorrect number of glyphs (%i)\n",outnGlyphs
);
455 else if (nGlyphs
!= outnGlyphs
)
456 winetest_trace("got incorrect number of glyphs (%i)\n",outnGlyphs
);
457 for (x
= 0; x
< outnGlyphs
; x
++)
459 if (glyphItems
[x
].Glyph
)
462 winetest_ok(glyphs
[x
]!=0, "%i: Glyph not present when it should be\n",x
);
463 else if (glyphs
[x
]==0)
464 winetest_trace("%i: Glyph not present when it should be\n",x
);
469 winetest_ok(glyphs
[x
]==0, "%i: Glyph present when it should not be\n",x
);
470 else if (glyphs
[x
]!=0)
471 winetest_trace("%i: Glyph present when it should not be\n",x
);
474 winetest_ok(glyphProp
[x
].sva
.uJustification
== glyphItems
[x
].GlyphProp
.sva
.uJustification
, "%i: uJustification incorrect (%i)\n",x
,glyphProp
[x
].sva
.uJustification
);
475 else if (glyphProp
[x
].sva
.uJustification
!= glyphItems
[x
].GlyphProp
.sva
.uJustification
)
476 winetest_trace("%i: uJustification incorrect (%i)\n",x
,glyphProp
[x
].sva
.uJustification
);
478 winetest_ok(glyphProp
[x
].sva
.fClusterStart
== glyphItems
[x
].GlyphProp
.sva
.fClusterStart
, "%i: fClusterStart incorrect (%i)\n",x
,glyphProp
[x
].sva
.fClusterStart
);
479 else if (glyphProp
[x
].sva
.fClusterStart
!= glyphItems
[x
].GlyphProp
.sva
.fClusterStart
)
480 winetest_trace("%i: fClusterStart incorrect (%i)\n",x
,glyphProp
[x
].sva
.fClusterStart
);
482 winetest_ok(glyphProp
[x
].sva
.fDiacritic
== glyphItems
[x
].GlyphProp
.sva
.fDiacritic
, "%i: fDiacritic incorrect (%i)\n",x
,glyphProp
[x
].sva
.fDiacritic
);
483 else if (glyphProp
[x
].sva
.fDiacritic
!= glyphItems
[x
].GlyphProp
.sva
.fDiacritic
)
484 winetest_trace("%i: fDiacritic incorrect (%i)\n",x
,glyphProp
[x
].sva
.fDiacritic
);
486 winetest_ok(glyphProp
[x
].sva
.fZeroWidth
== glyphItems
[x
].GlyphProp
.sva
.fZeroWidth
, "%i: fZeroWidth incorrect (%i)\n",x
,glyphProp
[x
].sva
.fZeroWidth
);
487 else if (glyphProp
[x
].sva
.fZeroWidth
!= glyphItems
[x
].GlyphProp
.sva
.fZeroWidth
)
488 winetest_trace("%i: fZeroWidth incorrect (%i)\n",x
,glyphProp
[x
].sva
.fZeroWidth
);
491 HeapFree(GetProcessHeap(),0,logclust
);
492 HeapFree(GetProcessHeap(),0,charProp
);
493 HeapFree(GetProcessHeap(),0,glyphs
);
494 HeapFree(GetProcessHeap(),0,glyphProp
);
495 ScriptFreeCache(&sc
);
498 #define test_shape_ok(a,b,c,d,e,f,g,h,i) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_shape_ok(1,a,b,c,d,e,f,g,h,i)
500 #define test_shape_ok_valid(v,a,b,c,d,e,f,g,h,i) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _test_shape_ok(v,a,b,c,d,e,f,g,h,i)
502 typedef struct tagRangeP
{
507 static int CALLBACK
enumFontProc( const LOGFONT
*lpelfe
, const TEXTMETRIC
*lpntme
,
508 DWORD FontType
, LPARAM lParam
)
510 NEWTEXTMETRICEX
*ntme
= (NEWTEXTMETRICEX
*)lpntme
;
511 fontEnumParam
*rp
= (fontEnumParam
*) lParam
;
516 if (FontType
!= TRUETYPE_FONTTYPE
)
520 while (i
> sizeof(DWORD
)*8)
523 i
-= (sizeof(DWORD
)*8);
530 if (ntme
->ntmFontSig
.fsUsb
[idx
] & mask
)
532 memcpy(&(rp
->lf
),lpelfe
,sizeof(LOGFONT
));
538 static int _find_font_for_range(HDC hdc
, const CHAR
*recommended
, BYTE range
, const WCHAR check
, HFONT
*hfont
, HFONT
*origFont
)
541 fontEnumParam lParam
;
543 lParam
.range
= range
;
544 memset(&lParam
.lf
,0,sizeof(LOGFONT
));
549 lstrcpyA(lParam
.lf
.lfFaceName
, recommended
);
550 if (!EnumFontFamiliesExA(hdc
, &lParam
.lf
, enumFontProc
, (LPARAM
)&lParam
, 0))
552 *hfont
= CreateFontIndirectA(&lParam
.lf
);
555 winetest_trace("using font %s\n",lParam
.lf
.lfFaceName
);
563 memset(&lParam
.lf
,0,sizeof(LOGFONT
));
564 lParam
.lf
.lfCharSet
= DEFAULT_CHARSET
;
566 if (!EnumFontFamiliesExA(hdc
, &lParam
.lf
, enumFontProc
, (LPARAM
)&lParam
, 0) && lParam
.lf
.lfFaceName
[0])
568 *hfont
= CreateFontIndirectA(&lParam
.lf
);
570 winetest_trace("trying font %s: failures will only be warnings\n",lParam
.lf
.lfFaceName
);
578 *origFont
= SelectObject(hdc
,*hfont
);
579 if (pGetGlyphIndicesW
&& (pGetGlyphIndicesW(hdc
, &check
, 1, &glyph
, 0) == GDI_ERROR
|| glyph
==0))
581 winetest_trace(" Font fails to contain required glyphs\n");
582 SelectObject(hdc
,*origFont
);
583 DeleteObject(*hfont
);
591 winetest_trace("Failed to find usable font\n");
596 #define find_font_for_range(a,b,c,d,e,f) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _find_font_for_range(a,b,c,d,e,f)
598 static void test_ScriptShapeOpenType(HDC hdc
)
601 SCRIPT_CACHE sc
= NULL
;
602 WORD glyphs
[4], logclust
[4];
603 SCRIPT_GLYPHPROP glyphProp
[4];
604 SCRIPT_ITEM items
[2];
606 SCRIPT_CONTROL Control
;
609 HFONT hfont
, hfont_orig
;
612 static const WCHAR test1
[] = {'w', 'i', 'n', 'e',0};
613 static const shapeTest_char t1_c
[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{0,0}}};
614 static const shapeTest_glyph t1_g
[] = {
615 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
616 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
617 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
618 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}} };
620 static const WCHAR test2
[] = {0x202B, 'i', 'n', 0x202C,0};
621 static const shapeTest_char t2_c
[] = {{0,{0,0}},{1,{0,0}},{2,{0,0}},{3,{0,0}}};
622 static const shapeTest_glyph t2_g
[] = {
623 {0,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
624 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
625 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
626 {0,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}} };
629 static const WCHAR test_hebrew
[] = {0x05e9, 0x05dc, 0x05d5, 0x05dd,0};
630 static const shapeTest_char hebrew_c
[] = {{3,{0,0}},{2,{0,0}},{1,{0,0}},{0,{0,0}}};
631 static const shapeTest_glyph hebrew_g
[] = {
632 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
633 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
634 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
635 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}} };
638 static const WCHAR test_arabic
[] = {0x0633,0x0644,0x0627,0x0645,0};
639 static const shapeTest_char arabic_c
[] = {{2,{0,0}},{1,{0,0}},{1,{0,0}},{0,{0,0}}};
640 static const shapeTest_glyph arabic_g
[] = {
641 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
642 {1,{{SCRIPT_JUSTIFY_ARABIC_NORMAL
,1,0,0,0,0},0}},
643 {1,{{SCRIPT_JUSTIFY_ARABIC_SEEN
,1,0,0,0,0},0}} };
646 static const WCHAR test_thai
[] = {0x0e2a, 0x0e04, 0x0e23, 0x0e34, 0x0e1b, 0x0e15, 0x0e4c, 0x0e44, 0x0e17, 0x0e22,};
647 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}}};
648 static const shapeTest_glyph thai_g
[] = {
649 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
650 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
651 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
652 {1,{{SCRIPT_JUSTIFY_CHARACTER
,0,1,1,0,0},0}},
653 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
654 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
655 {1,{{SCRIPT_JUSTIFY_CHARACTER
,0,1,1,0,0},0}},
656 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
657 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
658 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}}};
661 static const WCHAR test_syriac
[] = {0x0710, 0x0710, 0x0710, 0x0728, 0x0718, 0x0723,0};
662 static const shapeTest_char syriac_c
[] = {{5,{0,0}},{4,{0,0}},{3,{0,0}},{2,{0,0}},{1,{0,0}},{0,{0,0}}};
663 static const shapeTest_glyph syriac_g
[] = {
664 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
665 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
666 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
667 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
668 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
669 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}} };
672 static const WCHAR test_thaana
[] = {0x078a, 0x07ae, 0x0792, 0x07b0, 0x0020, 0x0796, 0x07aa, 0x0789, 0x07b0, 0x0795, 0x07ac, 0x0791, 0x07b0};
673 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}}};
674 static const shapeTest_glyph thaana_g
[] = {
675 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
676 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
677 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
678 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
679 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
680 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
681 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
682 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
683 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
684 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
685 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
686 {1,{{SCRIPT_JUSTIFY_NONE
,0,1,1,0,0},0}},
687 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}} };
690 static const WCHAR test_phagspa
[] = {0xa84f, 0xa861, 0xa843, 0x0020, 0xa863, 0xa861, 0xa859, 0x0020, 0xa850, 0xa85c, 0xa85e};
691 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}}};
692 static const shapeTest_glyph phagspa_g
[] = {
693 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
694 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
695 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
696 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
697 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
698 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
699 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
700 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
701 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
702 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
703 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}} };
706 static const WCHAR test_lao
[] = {0x0ead, 0x0eb1, 0x0e81, 0x0eaa, 0x0ead, 0x0e99, 0x0ea5, 0x0eb2, 0x0ea7, 0};
707 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}}};
708 static const shapeTest_glyph lao_g
[] = {
709 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
710 {1,{{SCRIPT_JUSTIFY_CHARACTER
,0,1,1,0,0},0}},
711 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
712 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
713 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
714 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
715 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
716 {1,{{SCRIPT_JUSTIFY_CHARACTER
,1,0,0,0,0},0}},
717 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}} };
720 static const WCHAR test_tibetan
[] = {0x0f04, 0x0f05, 0x0f0e, 0x0020, 0x0f51, 0x0f7c, 0x0f53, 0x0f0b, 0x0f5a, 0x0f53, 0x0f0b, 0x0f51, 0x0f44, 0x0f0b, 0x0f54, 0x0f7c, 0x0f0d};
721 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}}};
722 static const shapeTest_glyph tibetan_g
[] = {
723 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
724 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
725 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
726 {1,{{SCRIPT_JUSTIFY_BLANK
,1,0,0,0,0},0}},
727 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
728 {1,{{SCRIPT_JUSTIFY_NONE
,0,0,0,0,0},0}},
729 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
730 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
731 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
732 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
733 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
734 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
735 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
736 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
737 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}},
738 {1,{{SCRIPT_JUSTIFY_NONE
,0,0,0,0,0},0}},
739 {1,{{SCRIPT_JUSTIFY_NONE
,1,0,0,0,0},0}} };
741 if (!pScriptItemizeOpenType
|| !pScriptShapeOpenType
)
743 win_skip("ScriptShapeOpenType not available on this platform\n");
747 memset(&Control
, 0 , sizeof(Control
));
748 memset(&State
, 0 , sizeof(State
));
750 hr
= pScriptItemizeOpenType(test1
, 4, 2, &Control
, &State
, items
, tags
, &outnItems
);
751 ok(!hr
, "ScriptItemizeOpenType should return S_OK not %08x\n", hr
);
752 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
754 hr
= pScriptShapeOpenType(hdc
, &sc
, &items
[0].a
, tags
[0], 0x00000000, NULL
, NULL
, 0, test1
, 4, 4, NULL
, NULL
, glyphs
, NULL
, &nb
);
755 ok(hr
== E_INVALIDARG
, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr
);
757 hr
= pScriptShapeOpenType(hdc
, &sc
, &items
[0].a
, tags
[0], 0x00000000, NULL
, NULL
, 0, test1
, 4, 4, NULL
, NULL
, glyphs
, glyphProp
, NULL
);
758 ok(hr
== E_INVALIDARG
, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr
);
760 hr
= pScriptShapeOpenType(NULL
, &sc
, &items
[0].a
, tags
[0], 0x00000000, NULL
, NULL
, 0, test1
, 4, 4, NULL
, NULL
, glyphs
, glyphProp
, &nb
);
761 ok(hr
== E_INVALIDARG
, "ScriptShapeOpenType should return E_PENDING not %08x\n", hr
);
763 hr
= pScriptShapeOpenType(hdc
, &sc
, &items
[0].a
, tags
[0], 0x00000000, NULL
, NULL
, 0, test1
, 4, 4, NULL
, NULL
, glyphs
, glyphProp
, &nb
);
764 ok( hr
== E_INVALIDARG
,
765 "ScriptShapeOpenType should return E_FAIL or E_INVALIDARG, not %08x\n", hr
);
766 hr
= pScriptShapeOpenType(hdc
, &sc
, &items
[0].a
, tags
[0], 0x00000000, NULL
, NULL
, 0, test1
, 4, 4, logclust
, NULL
, glyphs
, glyphProp
, &nb
);
767 ok(hr
== E_INVALIDARG
, "ScriptShapeOpenType should return E_INVALIDARG not %08x\n", hr
);
769 ScriptFreeCache(&sc
);
771 test_shape_ok(hdc
, test1
, 4, &Control
, &State
, 0, 4, t1_c
, t1_g
);
772 test_shape_ok(hdc
, test2
, 4, &Control
, &State
, 1, 4, t2_c
, t2_g
);
774 test_valid
= find_font_for_range(hdc
, "Microsoft Sans Serif", 11, test_hebrew
[0], &hfont
, &hfont_orig
);
777 test_shape_ok_valid(test_valid
, hdc
, test_hebrew
, 4, &Control
, &State
, 0, 4, hebrew_c
, hebrew_g
);
778 SelectObject(hdc
, hfont_orig
);
782 test_valid
= find_font_for_range(hdc
, "Microsoft Sans Serif", 13, test_arabic
[0], &hfont
, &hfont_orig
);
785 test_shape_ok_valid(test_valid
, hdc
, test_arabic
, 4, &Control
, &State
, 0, 3, arabic_c
, arabic_g
);
786 SelectObject(hdc
, hfont_orig
);
790 test_valid
= find_font_for_range(hdc
, "Microsoft Sans Serif", 24, test_thai
[0], &hfont
, &hfont_orig
);
793 test_shape_ok_valid(test_valid
, hdc
, test_thai
, 10, &Control
, &State
, 0, 10, thai_c
, thai_g
);
794 SelectObject(hdc
, hfont_orig
);
798 test_valid
= find_font_for_range(hdc
, "Estrangelo Edessa", 71, test_syriac
[0], &hfont
, &hfont_orig
);
801 test_shape_ok_valid(test_valid
, hdc
, test_syriac
, 6, &Control
, &State
, 0, 6, syriac_c
, syriac_g
);
802 SelectObject(hdc
, hfont_orig
);
806 test_valid
= find_font_for_range(hdc
, "MV Boli", 72, test_thaana
[0], &hfont
, &hfont_orig
);
809 test_shape_ok_valid(test_valid
, hdc
, test_thaana
, 13, &Control
, &State
, 0, 13, thaana_c
, thaana_g
);
810 SelectObject(hdc
, hfont_orig
);
814 test_valid
= find_font_for_range(hdc
, "Microsoft PhagsPa", 53, test_phagspa
[0], &hfont
, &hfont_orig
);
817 test_shape_ok_valid(test_valid
, hdc
, test_phagspa
, 11, &Control
, &State
, 0, 11, phagspa_c
, phagspa_g
);
818 SelectObject(hdc
, hfont_orig
);
822 test_valid
= find_font_for_range(hdc
, "DokChampa", 25, test_lao
[0], &hfont
, &hfont_orig
);
825 test_shape_ok_valid(test_valid
, hdc
, test_lao
, 9, &Control
, &State
, 0, 9, lao_c
, lao_g
);
826 SelectObject(hdc
, hfont_orig
);
830 test_valid
= find_font_for_range(hdc
, "Microsoft Himalaya", 70, test_tibetan
[0], &hfont
, &hfont_orig
);
833 test_shape_ok_valid(test_valid
, hdc
, test_tibetan
, 17, &Control
, &State
, 0, 17, tibetan_c
, tibetan_g
);
834 SelectObject(hdc
, hfont_orig
);
839 static void test_ScriptShape(HDC hdc
)
841 static const WCHAR test1
[] = {'w', 'i', 'n', 'e',0};
842 static const WCHAR test2
[] = {0x202B, 'i', 'n', 0x202C,0};
844 SCRIPT_CACHE sc
= NULL
;
845 WORD glyphs
[4], glyphs2
[4], logclust
[4];
846 SCRIPT_VISATTR attrs
[4];
847 SCRIPT_ITEM items
[2];
850 hr
= ScriptItemize(test1
, 4, 2, NULL
, NULL
, items
, NULL
);
851 ok(!hr
, "ScriptItemize should return S_OK not %08x\n", hr
);
852 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
854 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, NULL
, NULL
, &nb
);
855 ok(hr
== E_INVALIDARG
, "ScriptShape should return E_INVALIDARG not %08x\n", hr
);
857 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, NULL
, attrs
, NULL
);
858 ok(hr
== E_INVALIDARG
, "ScriptShape should return E_INVALIDARG not %08x\n", hr
);
860 hr
= ScriptShape(NULL
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, NULL
, attrs
, &nb
);
861 ok(hr
== E_PENDING
, "ScriptShape should return E_PENDING not %08x\n", hr
);
863 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, NULL
, attrs
, &nb
);
864 ok(broken(hr
== S_OK
) ||
865 hr
== E_INVALIDARG
|| /* Vista, W2K8 */
866 hr
== E_FAIL
, /* WIN7 */
867 "ScriptShape should return E_FAIL or E_INVALIDARG, not %08x\n", hr
);
868 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
870 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, logclust
, attrs
, &nb
);
871 ok(!hr
, "ScriptShape should return S_OK not %08x\n", hr
);
872 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
875 memset(glyphs
,-1,sizeof(glyphs
));
876 memset(logclust
,-1,sizeof(logclust
));
877 memset(attrs
,-1,sizeof(attrs
));
878 hr
= ScriptShape(NULL
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, logclust
, attrs
, &nb
);
879 ok(!hr
, "ScriptShape should return S_OK not %08x\n", hr
);
880 ok(nb
== 4, "Wrong number of items\n");
881 ok(logclust
[0] == 0, "clusters out of order\n");
882 ok(logclust
[1] == 1, "clusters out of order\n");
883 ok(logclust
[2] == 2, "clusters out of order\n");
884 ok(logclust
[3] == 3, "clusters out of order\n");
885 ok(attrs
[0].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
886 ok(attrs
[1].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
887 ok(attrs
[2].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
888 ok(attrs
[3].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
889 ok(attrs
[0].fClusterStart
== 1, "fClusterStart incorrect\n");
890 ok(attrs
[1].fClusterStart
== 1, "fClusterStart incorrect\n");
891 ok(attrs
[2].fClusterStart
== 1, "fClusterStart incorrect\n");
892 ok(attrs
[3].fClusterStart
== 1, "fClusterStart incorrect\n");
893 ok(attrs
[0].fDiacritic
== 0, "fDiacritic incorrect\n");
894 ok(attrs
[1].fDiacritic
== 0, "fDiacritic incorrect\n");
895 ok(attrs
[2].fDiacritic
== 0, "fDiacritic incorrect\n");
896 ok(attrs
[3].fDiacritic
== 0, "fDiacritic incorrect\n");
897 ok(attrs
[0].fZeroWidth
== 0, "fZeroWidth incorrect\n");
898 ok(attrs
[1].fZeroWidth
== 0, "fZeroWidth incorrect\n");
899 ok(attrs
[2].fZeroWidth
== 0, "fZeroWidth incorrect\n");
900 ok(attrs
[3].fZeroWidth
== 0, "fZeroWidth incorrect\n");
902 ScriptFreeCache(&sc
);
905 memset(glyphs2
,-1,sizeof(glyphs2
));
906 memset(logclust
,-1,sizeof(logclust
));
907 memset(attrs
,-1,sizeof(attrs
));
908 hr
= ScriptShape(hdc
, &sc
, test2
, 4, 4, &items
[0].a
, glyphs2
, logclust
, attrs
, &nb
);
909 ok(hr
== S_OK
, "ScriptShape should return S_OK not %08x\n", hr
);
910 ok(nb
== 4, "Wrong number of items\n");
911 ok(glyphs2
[0] == 0 || broken(glyphs2
[0] == 0x80), "Incorrect glyph for 0x202B\n");
912 ok(glyphs2
[3] == 0 || broken(glyphs2
[3] == 0x80), "Incorrect glyph for 0x202C\n");
913 ok(logclust
[0] == 0, "clusters out of order\n");
914 ok(logclust
[1] == 1, "clusters out of order\n");
915 ok(logclust
[2] == 2, "clusters out of order\n");
916 ok(logclust
[3] == 3, "clusters out of order\n");
917 ok(attrs
[0].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
918 ok(attrs
[1].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
919 ok(attrs
[2].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
920 ok(attrs
[3].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
921 ok(attrs
[0].fClusterStart
== 1, "fClusterStart incorrect\n");
922 ok(attrs
[1].fClusterStart
== 1, "fClusterStart incorrect\n");
923 ok(attrs
[2].fClusterStart
== 1, "fClusterStart incorrect\n");
924 ok(attrs
[3].fClusterStart
== 1, "fClusterStart incorrect\n");
925 ok(attrs
[0].fDiacritic
== 0, "fDiacritic incorrect\n");
926 ok(attrs
[1].fDiacritic
== 0, "fDiacritic incorrect\n");
927 ok(attrs
[2].fDiacritic
== 0, "fDiacritic incorrect\n");
928 ok(attrs
[3].fDiacritic
== 0, "fDiacritic incorrect\n");
929 ok(attrs
[0].fZeroWidth
== 0, "fZeroWidth incorrect\n");
930 ok(attrs
[1].fZeroWidth
== 0, "fZeroWidth incorrect\n");
931 ok(attrs
[2].fZeroWidth
== 0, "fZeroWidth incorrect\n");
932 ok(attrs
[3].fZeroWidth
== 0, "fZeroWidth incorrect\n");
934 /* modify LTR to RTL */
936 memset(glyphs2
,-1,sizeof(glyphs2
));
937 memset(logclust
,-1,sizeof(logclust
));
938 memset(attrs
,-1,sizeof(attrs
));
939 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs2
, logclust
, attrs
, &nb
);
940 ok(!hr
, "ScriptShape should return S_OK not %08x\n", hr
);
941 ok(nb
== 4, "Wrong number of items\n");
942 ok(glyphs2
[0] == glyphs
[3], "Glyphs not reordered properly\n");
943 ok(glyphs2
[1] == glyphs
[2], "Glyphs not reordered properly\n");
944 ok(glyphs2
[2] == glyphs
[1], "Glyphs not reordered properly\n");
945 ok(glyphs2
[3] == glyphs
[0], "Glyphs not reordered properly\n");
946 ok(logclust
[0] == 3, "clusters out of order\n");
947 ok(logclust
[1] == 2, "clusters out of order\n");
948 ok(logclust
[2] == 1, "clusters out of order\n");
949 ok(logclust
[3] == 0, "clusters out of order\n");
950 ok(attrs
[0].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
951 ok(attrs
[1].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
952 ok(attrs
[2].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
953 ok(attrs
[3].uJustification
== SCRIPT_JUSTIFY_CHARACTER
, "uJustification incorrect\n");
954 ok(attrs
[0].fClusterStart
== 1, "fClusterStart incorrect\n");
955 ok(attrs
[1].fClusterStart
== 1, "fClusterStart incorrect\n");
956 ok(attrs
[2].fClusterStart
== 1, "fClusterStart incorrect\n");
957 ok(attrs
[3].fClusterStart
== 1, "fClusterStart incorrect\n");
958 ok(attrs
[0].fDiacritic
== 0, "fDiacritic incorrect\n");
959 ok(attrs
[1].fDiacritic
== 0, "fDiacritic incorrect\n");
960 ok(attrs
[2].fDiacritic
== 0, "fDiacritic incorrect\n");
961 ok(attrs
[3].fDiacritic
== 0, "fDiacritic incorrect\n");
962 ok(attrs
[0].fZeroWidth
== 0, "fZeroWidth incorrect\n");
963 ok(attrs
[1].fZeroWidth
== 0, "fZeroWidth incorrect\n");
964 ok(attrs
[2].fZeroWidth
== 0, "fZeroWidth incorrect\n");
965 ok(attrs
[3].fZeroWidth
== 0, "fZeroWidth incorrect\n");
967 ScriptFreeCache(&sc
);
970 static void test_ScriptPlace(HDC hdc
)
972 static const WCHAR test1
[] = {'t', 'e', 's', 't',0};
975 SCRIPT_CACHE sc
= NULL
;
976 WORD glyphs
[4], logclust
[4];
977 SCRIPT_VISATTR attrs
[4];
978 SCRIPT_ITEM items
[2];
983 hr
= ScriptItemize(test1
, 4, 2, NULL
, NULL
, items
, NULL
);
984 ok(!hr
, "ScriptItemize should return S_OK not %08x\n", hr
);
985 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
987 hr
= ScriptShape(hdc
, &sc
, test1
, 4, 4, &items
[0].a
, glyphs
, logclust
, attrs
, &nb
);
988 ok(!hr
, "ScriptShape should return S_OK not %08x\n", hr
);
989 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
991 hr
= ScriptPlace(hdc
, &sc
, glyphs
, 4, NULL
, &items
[0].a
, widths
, NULL
, NULL
);
992 ok(hr
== E_INVALIDARG
, "ScriptPlace should return E_INVALIDARG not %08x\n", hr
);
994 hr
= ScriptPlace(NULL
, &sc
, glyphs
, 4, attrs
, &items
[0].a
, widths
, NULL
, NULL
);
995 ok(broken(hr
== E_PENDING
) ||
996 hr
== E_INVALIDARG
|| /* Vista, W2K8 */
997 hr
== E_FAIL
, /* WIN7 */
998 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr
);
1000 hr
= ScriptPlace(NULL
, &sc
, glyphs
, 4, attrs
, &items
[0].a
, widths
, offset
, NULL
);
1001 ok(hr
== E_PENDING
, "ScriptPlace should return E_PENDING not %08x\n", hr
);
1003 hr
= ScriptPlace(NULL
, &sc
, glyphs
, 4, attrs
, &items
[0].a
, widths
, NULL
, abc
);
1004 ok(broken(hr
== E_PENDING
) ||
1005 hr
== E_INVALIDARG
|| /* Vista, W2K8 */
1006 hr
== E_FAIL
, /* WIN7 */
1007 "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr
);
1009 hr
= ScriptPlace(hdc
, &sc
, glyphs
, 4, attrs
, &items
[0].a
, widths
, offset
, NULL
);
1010 ok(!hr
, "ScriptPlace should return S_OK not %08x\n", hr
);
1011 ok(items
[0].a
.fNoGlyphIndex
== FALSE
, "fNoGlyphIndex TRUE\n");
1013 ret
= ExtTextOutW(hdc
, 1, 1, 0, NULL
, glyphs
, 4, widths
);
1014 ok(ret
, "ExtTextOutW should return TRUE\n");
1016 ScriptFreeCache(&sc
);
1019 static void test_ScriptItemIzeShapePlace(HDC hdc
, unsigned short pwOutGlyphs
[256])
1023 const SCRIPT_PROPERTIES
**ppSp
;
1027 SCRIPT_ITEM pItem
[255];
1029 WCHAR TestItem1
[] = {'T', 'e', 's', 't', 'a', 0};
1030 WCHAR TestItem2
[] = {'T', 'e', 's', 't', 'b', 0};
1031 WCHAR TestItem3
[] = {'T', 'e', 's', 't', 'c',' ','1','2','3',' ',' ','e','n','d',0};
1032 WCHAR TestItem4
[] = {'T', 'e', 's', 't', 'd',' ',0x0684,0x0694,0x06a4,' ',' ','\r','\n','e','n','d',0};
1033 WCHAR TestItem5
[] = {0x0684,'T','e','s','t','e',' ',0x0684,0x0694,0x06a4,' ',' ','e','n','d',0};
1034 WCHAR TestItem6
[] = {'T', 'e', 's', 't', 'f',' ',' ',' ','\r','\n','e','n','d',0};
1039 unsigned short pwOutGlyphs1
[256];
1040 unsigned short pwOutGlyphs2
[256];
1041 unsigned short pwLogClust
[256];
1042 SCRIPT_VISATTR psva
[256];
1045 GOFFSET pGoffset
[256];
1049 /* Start testing usp10 functions */
1050 /* This test determines that the pointer returned by ScriptGetProperties is valid
1051 * by checking a known value in the table */
1052 hr
= ScriptGetProperties(&ppSp
, &iMaxProps
);
1053 ok(hr
== S_OK
, "ScriptGetProperties failed: 0x%08x\n", hr
);
1054 trace("number of script properties %d\n", iMaxProps
);
1055 ok (iMaxProps
> 0, "Number of scripts returned should not be 0\n");
1057 ok( ppSp
[0]->langid
== 0, "Langid[0] not = to 0\n"); /* Check a known value to ensure */
1060 /* This is a valid test that will cause parsing to take place */
1063 hr
= ScriptItemize(TestItem1
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1064 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1065 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
1067 ok (pcItems
> 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
1069 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== cInChars
,
1070 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
1071 pItem
[0].iCharPos
, cInChars
, pItem
[1].iCharPos
);
1073 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
1074 * ie. ScriptItemize has succeeded and that pItem has been set */
1077 psc
= NULL
; /* must be null on first call */
1079 cMaxGlyphs
= cInChars
;
1080 hr
= ScriptShape(NULL
, &psc
, TestItem1
, cChars
,
1081 cMaxGlyphs
, &pItem
[0].a
,
1082 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1083 ok (hr
== E_PENDING
, "If psc is NULL (%08x) the E_PENDING should be returned\n", hr
);
1085 hr
= ScriptShape(hdc
, &psc
, TestItem1
, cChars
,
1086 cMaxGlyphs
, &pItem
[0].a
,
1087 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1088 ok (hr
== E_OUTOFMEMORY
, "If not enough output area cChars (%d) is > than CMaxGlyphs "
1089 "(%d) but not E_OUTOFMEMORY\n",
1090 cChars
, cMaxGlyphs
);
1092 hr
= ScriptShape(hdc
, &psc
, TestItem1
, cChars
,
1093 cMaxGlyphs
, &pItem
[0].a
,
1094 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1095 ok (hr
== 0, "ScriptShape should return 0 not (%08x)\n", hr
);
1096 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1097 ok (pcGlyphs
== cChars
, "Chars in (%d) should equal Glyphs out (%d)\n", cChars
, pcGlyphs
);
1099 hr
= ScriptPlace(hdc
, &psc
, pwOutGlyphs1
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1101 ok (hr
== 0, "ScriptPlace should return 0 not (%08x)\n", hr
);
1102 hr
= ScriptPlace(NULL
, &psc
, pwOutGlyphs1
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1104 ok (hr
== 0, "ScriptPlace should return 0 not (%08x)\n", hr
);
1105 for (cnt
=0; cnt
< pcGlyphs
; cnt
++)
1106 pwOutGlyphs
[cnt
] = pwOutGlyphs1
[cnt
]; /* Send to next function */
1109 /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation *
1110 * takes place if fNoGlyphIndex is set. */
1114 hr
= ScriptItemize(TestItem2
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1115 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1116 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
1118 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== cInChars
,
1119 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
1120 pItem
[0].iCharPos
, cInChars
, pItem
[1].iCharPos
);
1121 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue */
1125 pItem
[0].a
.fNoGlyphIndex
= 1; /* say no translate */
1126 hr
= ScriptShape(NULL
, &psc
, TestItem2
, cChars
,
1127 cMaxGlyphs
, &pItem
[0].a
,
1128 pwOutGlyphs2
, pwLogClust
, psva
, &pcGlyphs
);
1129 ok (hr
!= E_PENDING
, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n", hr
);
1130 ok (hr
== 0, "ScriptShape should return 0 not (%08x)\n", hr
);
1131 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1132 ok (pcGlyphs
== cChars
, "Chars in (%d) should equal Glyphs out (%d)\n", cChars
, pcGlyphs
);
1133 for (cnt
=0; cnt
< cChars
&& TestItem2
[cnt
] == pwOutGlyphs2
[cnt
]; cnt
++) {}
1134 ok (cnt
== cChars
, "Translation to place when told not to. WCHAR %d - %04x != %04x\n",
1135 cnt
, TestItem2
[cnt
], pwOutGlyphs2
[cnt
]);
1137 hr
= ScriptPlace(hdc
, &psc
, pwOutGlyphs2
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1139 ok (hr
== 0, "ScriptPlace should return 0 not (%08x)\n", hr
);
1142 ScriptFreeCache( &psc
);
1143 ok (!psc
, "psc is not null after ScriptFreeCache\n");
1147 /* This is a valid test that will cause parsing to take place and create 3 script_items */
1148 cInChars
= (sizeof(TestItem3
)/2)-1;
1150 hr
= ScriptItemize(TestItem3
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1151 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1154 ok (pcItems
== 3, "The number of SCRIPT_ITEMS should be 3 not %d\n", pcItems
);
1157 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== 6,
1158 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n",
1159 pItem
[0].iCharPos
, pItem
[1].iCharPos
);
1160 ok (pItem
[1].iCharPos
== 6 && pItem
[2].iCharPos
== 11,
1161 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n",
1162 pItem
[1].iCharPos
, pItem
[2].iCharPos
);
1163 ok (pItem
[2].iCharPos
== 11 && pItem
[3].iCharPos
== cInChars
,
1164 "Start pos [2] not = 11 (%d) or end [3] pos not = 14 (%d), cInChars = %d\n",
1165 pItem
[2].iCharPos
, pItem
[3].iCharPos
, cInChars
);
1169 /* This is a valid test that will cause parsing to take place and create 5 script_items */
1170 cInChars
= (sizeof(TestItem4
)/2)-1;
1172 hr
= ScriptItemize(TestItem4
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1173 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1176 ok (pcItems
== 5, "The number of SCRIPT_ITEMS should be 5 not %d\n", pcItems
);
1179 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== 6,
1180 "Start pos [0] not = 0 (%d) or end pos [1] not = %d\n",
1181 pItem
[0].iCharPos
, pItem
[1].iCharPos
);
1182 ok (pItem
[0].a
.s
.uBidiLevel
== 0, "Should have been bidi=0 not %d\n",
1183 pItem
[0].a
.s
.uBidiLevel
);
1184 ok (pItem
[1].iCharPos
== 6 && pItem
[2].iCharPos
== 11,
1185 "Start pos [1] not = 6 (%d) or end pos [2] not = 11 (%d)\n",
1186 pItem
[1].iCharPos
, pItem
[2].iCharPos
);
1187 ok (pItem
[1].a
.s
.uBidiLevel
== 1, "Should have been bidi=1 not %d\n",
1188 pItem
[1].a
.s
.uBidiLevel
);
1189 ok (pItem
[2].iCharPos
== 11 && pItem
[3].iCharPos
== 12,
1190 "Start pos [2] not = 11 (%d) or end [3] pos not = 12 (%d)\n",
1191 pItem
[2].iCharPos
, pItem
[3].iCharPos
);
1192 ok (pItem
[2].a
.s
.uBidiLevel
== 0, "Should have been bidi=0 not %d\n",
1193 pItem
[2].a
.s
.uBidiLevel
);
1194 ok (pItem
[3].iCharPos
== 12 && pItem
[4].iCharPos
== 13,
1195 "Start pos [3] not = 12 (%d) or end [4] pos not = 13 (%d)\n",
1196 pItem
[3].iCharPos
, pItem
[4].iCharPos
);
1197 ok (pItem
[3].a
.s
.uBidiLevel
== 0, "Should have been bidi=0 not %d\n",
1198 pItem
[3].a
.s
.uBidiLevel
);
1199 ok (pItem
[4].iCharPos
== 13 && pItem
[5].iCharPos
== cInChars
,
1200 "Start pos [4] not = 13 (%d) or end [5] pos not = 16 (%d), cInChars = %d\n",
1201 pItem
[4].iCharPos
, pItem
[5].iCharPos
, cInChars
);
1206 * This test is for when the first unicode character requires bidi support
1208 cInChars
= (sizeof(TestItem5
)-1)/sizeof(WCHAR
);
1209 hr
= ScriptItemize(TestItem5
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1210 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1211 ok (pcItems
== 4, "There should have been 4 items, found %d\n", pcItems
);
1212 ok (pItem
[0].a
.s
.uBidiLevel
== 1, "The first character should have been bidi=1 not %d\n",
1213 pItem
[0].a
.s
.uBidiLevel
);
1215 /* This test checks to make sure that the test to see if there are sufficient buffers to store *
1216 * the pointer to the last char works. Note that windows often needs a greater number of *
1217 * SCRIPT_ITEMS to process a string than is returned in pcItems. */
1218 cInChars
= (sizeof(TestItem6
)/2)-1;
1220 hr
= ScriptItemize(TestItem6
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1221 ok (hr
== E_OUTOFMEMORY
, "ScriptItemize should return E_OUTOFMEMORY, returned %08x\n", hr
);
1225 static void test_ScriptGetCMap(HDC hdc
, unsigned short pwOutGlyphs
[256])
1228 SCRIPT_CACHE psc
= NULL
;
1231 unsigned short pwOutGlyphs2
[256];
1232 unsigned short pwOutGlyphs3
[256];
1236 static const WCHAR TestItem1
[] = {'T', 'e', 's', 't', 'a', 0};
1237 static const WCHAR TestItem2
[] = {0x202B, 'i', 'n', 0x202C,0};
1238 static const WCHAR TestItem3
[] = {'a','b','c','d','(','<','{','[',0x2039,0};
1239 static const WCHAR TestItem3b
[] = {'a','b','c','d',')','>','}',']',0x203A,0};
1241 /* Check to make sure that SCRIPT_CACHE gets allocated ok */
1243 cInChars
= cChars
= 5;
1244 /* Some sanity checks for ScriptGetCMap */
1246 hr
= ScriptGetCMap(NULL
, NULL
, NULL
, 0, 0, NULL
);
1247 ok( hr
== E_INVALIDARG
, "(NULL,NULL,NULL,0,0,NULL), "
1248 "expected E_INVALIDARG, got %08x\n", hr
);
1250 hr
= ScriptGetCMap(NULL
, NULL
, TestItem1
, cInChars
, dwFlags
, pwOutGlyphs3
);
1251 ok( hr
== E_INVALIDARG
, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
1252 "expected E_INVALIDARG, got %08x\n", hr
);
1254 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1256 hr
= ScriptGetCMap(NULL
, &psc
, TestItem1
, cInChars
, 0, pwOutGlyphs3
);
1257 ok( hr
== E_PENDING
, "(NULL,&psc,NULL,0,0,NULL), expected E_PENDING, "
1259 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1261 /* Set psc to NULL but add hdc, to be able to check if a pointer is returned in psc */
1263 hr
= ScriptGetCMap(hdc
, &psc
, TestItem1
, cInChars
, 0, pwOutGlyphs3
);
1264 ok( hr
== S_OK
, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, "
1266 ok( psc
!= NULL
, "ScritpGetCMap expected psc to be not NULL\n");
1267 ScriptFreeCache( &psc
);
1269 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1271 hr
= ScriptGetCMap(NULL
, &psc
, TestItem1
, cInChars
, dwFlags
, pwOutGlyphs3
);
1272 ok( hr
== E_PENDING
, "(NULL,&psc,), expected E_PENDING, got %08x\n", hr
);
1273 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1274 /* Check to see if the results are the same as those returned by ScriptShape */
1275 hr
= ScriptGetCMap(hdc
, &psc
, TestItem1
, cInChars
, dwFlags
, pwOutGlyphs3
);
1276 ok (hr
== 0, "ScriptGetCMap should return 0 not (%08x)\n", hr
);
1277 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1278 for (cnt
=0; cnt
< cChars
&& pwOutGlyphs
[cnt
] == pwOutGlyphs3
[cnt
]; cnt
++) {}
1279 ok (cnt
== cInChars
, "Translation not correct. WCHAR %d - %04x != %04x\n",
1280 cnt
, pwOutGlyphs
[cnt
], pwOutGlyphs3
[cnt
]);
1282 ScriptFreeCache( &psc
);
1283 ok (!psc
, "psc is not null after ScriptFreeCache\n");
1285 cInChars
= cChars
= 4;
1286 hr
= ScriptGetCMap(hdc
, &psc
, TestItem2
, cInChars
, dwFlags
, pwOutGlyphs3
);
1287 ok (hr
== S_FALSE
, "ScriptGetCMap should return S_FALSE not (%08x)\n", hr
);
1288 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1289 ok(pwOutGlyphs3
[0] == 0 || broken(pwOutGlyphs3
[0] == 0x80), "Glyph 0 should be default glyph\n");
1290 ok(pwOutGlyphs3
[3] == 0 || broken(pwOutGlyphs3
[0] == 0x80), "Glyph 0 should be default glyph\n");
1293 cInChars
= cChars
= 9;
1294 hr
= ScriptGetCMap(hdc
, &psc
, TestItem3b
, cInChars
, dwFlags
, pwOutGlyphs2
);
1295 ok (hr
== S_OK
, "ScriptGetCMap should return S_OK not (%08x)\n", hr
);
1296 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1298 cInChars
= cChars
= 9;
1300 hr
= ScriptGetCMap(hdc
, &psc
, TestItem3
, cInChars
, dwFlags
, pwOutGlyphs3
);
1301 ok (hr
== S_OK
, "ScriptGetCMap should return S_OK not (%08x)\n", hr
);
1302 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1303 ok(pwOutGlyphs3
[0] == pwOutGlyphs2
[0], "glyph incorrectly altered\n");
1304 ok(pwOutGlyphs3
[1] == pwOutGlyphs2
[1], "glyph incorreclty altered\n");
1305 ok(pwOutGlyphs3
[2] == pwOutGlyphs2
[2], "glyph incorreclty altered\n");
1306 ok(pwOutGlyphs3
[3] == pwOutGlyphs2
[3], "glyph incorreclty altered\n");
1307 ok(pwOutGlyphs3
[4] == pwOutGlyphs2
[4], "glyph not mirrored correctly\n");
1308 ok(pwOutGlyphs3
[5] == pwOutGlyphs2
[5], "glyph not mirrored correctly\n");
1309 ok(pwOutGlyphs3
[6] == pwOutGlyphs2
[6], "glyph not mirrored correctly\n");
1310 ok(pwOutGlyphs3
[7] == pwOutGlyphs2
[7], "glyph not mirrored correctly\n");
1311 ok(pwOutGlyphs3
[8] == pwOutGlyphs2
[8], "glyph not mirrored correctly\n");
1313 ScriptFreeCache( &psc
);
1314 ok (!psc
, "psc is not null after ScriptFreeCache\n");
1317 static void test_ScriptGetFontProperties(HDC hdc
)
1320 SCRIPT_CACHE psc
,old_psc
;
1321 SCRIPT_FONTPROPERTIES sfp
;
1323 /* Some sanity checks for ScriptGetFontProperties */
1325 hr
= ScriptGetFontProperties(NULL
,NULL
,NULL
);
1326 ok( hr
== E_INVALIDARG
, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr
);
1328 hr
= ScriptGetFontProperties(NULL
,NULL
,&sfp
);
1329 ok( hr
== E_INVALIDARG
, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr
);
1331 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1333 hr
= ScriptGetFontProperties(NULL
,&psc
,NULL
);
1334 ok( hr
== E_INVALIDARG
, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr
);
1335 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1337 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1339 hr
= ScriptGetFontProperties(NULL
,&psc
,&sfp
);
1340 ok( hr
== E_PENDING
, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", hr
);
1341 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1343 hr
= ScriptGetFontProperties(hdc
,NULL
,NULL
);
1344 ok( hr
== E_INVALIDARG
, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", hr
);
1346 hr
= ScriptGetFontProperties(hdc
,NULL
,&sfp
);
1347 ok( hr
== E_INVALIDARG
, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", hr
);
1349 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1351 hr
= ScriptGetFontProperties(hdc
,&psc
,NULL
);
1352 ok( hr
== E_INVALIDARG
, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", hr
);
1353 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1355 /* Pass an invalid sfp */
1357 sfp
.cBytes
= sizeof(SCRIPT_FONTPROPERTIES
) - 1;
1358 hr
= ScriptGetFontProperties(hdc
,&psc
,&sfp
);
1359 ok( hr
== E_INVALIDARG
, "(hdc,&psc,&sfp) invalid, expected E_INVALIDARG, got %08x\n", hr
);
1360 ok( psc
!= NULL
, "Expected a pointer in psc, got NULL\n");
1361 ScriptFreeCache(&psc
);
1362 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1364 /* Give it the correct cBytes, we don't care about what's coming back */
1365 sfp
.cBytes
= sizeof(SCRIPT_FONTPROPERTIES
);
1367 hr
= ScriptGetFontProperties(hdc
,&psc
,&sfp
);
1368 ok( hr
== S_OK
, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", hr
);
1369 ok( psc
!= NULL
, "Expected a pointer in psc, got NULL\n");
1371 /* Save the psc pointer */
1373 /* Now a NULL hdc again */
1374 hr
= ScriptGetFontProperties(NULL
,&psc
,&sfp
);
1375 ok( hr
== S_OK
, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", hr
);
1376 ok( psc
== old_psc
, "Expected psc not to be changed, was %p is now %p\n", old_psc
, psc
);
1377 ScriptFreeCache(&psc
);
1378 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1381 static void test_ScriptTextOut(HDC hdc
)
1387 SCRIPT_ITEM pItem
[255];
1389 WCHAR TestItem1
[] = {'T', 'e', 's', 't', 'a', 0};
1394 unsigned short pwOutGlyphs1
[256];
1395 WORD pwLogClust
[256];
1396 SCRIPT_VISATTR psva
[256];
1399 GOFFSET pGoffset
[256];
1404 BOOL fTrailing
= FALSE
;
1405 SCRIPT_LOGATTR
*psla
;
1406 SCRIPT_LOGATTR sla
[256];
1408 /* This is a valid test that will cause parsing to take place */
1411 hr
= ScriptItemize(TestItem1
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1412 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1413 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
1415 ok (pcItems
> 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
1417 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== cInChars
,
1418 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
1419 pItem
[0].iCharPos
, cInChars
, pItem
[1].iCharPos
);
1421 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
1422 * ie. ScriptItemize has succeeded and that pItem has been set */
1425 psc
= NULL
; /* must be null on first call */
1428 hr
= ScriptShape(hdc
, &psc
, TestItem1
, cChars
,
1429 cMaxGlyphs
, &pItem
[0].a
,
1430 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1431 ok (hr
== 0, "ScriptShape should return 0 not (%08x)\n", hr
);
1432 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1433 ok (pcGlyphs
== cChars
, "Chars in (%d) should equal Glyphs out (%d)\n", cChars
, pcGlyphs
);
1435 /* Note hdc is needed as glyph info is not yet in psc */
1436 hr
= ScriptPlace(hdc
, &psc
, pwOutGlyphs1
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1438 ok (hr
== 0, "Should return 0 not (%08x)\n", hr
);
1439 ScriptFreeCache(&psc
); /* Get rid of psc for next test set */
1440 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1442 hr
= ScriptTextOut(NULL
, NULL
, 0, 0, 0, NULL
, NULL
, NULL
, 0, NULL
, 0, NULL
, NULL
, NULL
);
1443 ok (hr
== E_INVALIDARG
, "Should return 0 not (%08x)\n", hr
);
1445 hr
= ScriptTextOut(NULL
, NULL
, 0, 0, 0, NULL
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1446 piAdvance
, NULL
, pGoffset
);
1447 ok( hr
== E_INVALIDARG
, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
1448 "expected E_INVALIDARG, got %08x\n", hr
);
1450 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
1452 hr
= ScriptTextOut(NULL
, &psc
, 0, 0, 0, NULL
, NULL
, NULL
, 0, NULL
, 0,
1454 ok( hr
== E_INVALIDARG
, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, "
1456 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1458 /* hdc is required for this one rather than the usual optional */
1460 hr
= ScriptTextOut(NULL
, &psc
, 0, 0, 0, NULL
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1461 piAdvance
, NULL
, pGoffset
);
1462 ok( hr
== E_INVALIDARG
, "(NULL,&psc,), expected E_INVALIDARG, got %08x\n", hr
);
1463 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1465 /* Set that it returns 0 status */
1466 hr
= ScriptTextOut(hdc
, &psc
, 0, 0, 0, NULL
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1467 piAdvance
, NULL
, pGoffset
);
1468 ok (hr
== 0, "ScriptTextOut should return 0 not (%08x)\n", hr
);
1470 /* Test Rect Rgn is acceptable */
1475 hr
= ScriptTextOut(hdc
, &psc
, 0, 0, 0, &rect
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1476 piAdvance
, NULL
, pGoffset
);
1477 ok (hr
== 0, "ScriptTextOut should return 0 not (%08x)\n", hr
);
1480 hr
= ScriptCPtoX(iCP
, fTrailing
, cChars
, pcGlyphs
, (const WORD
*) &pwLogClust
,
1481 (const SCRIPT_VISATTR
*) &psva
, (const int *)&piAdvance
, &pItem
[0].a
, &piX
);
1482 ok(hr
== S_OK
, "ScriptCPtoX Stub should return S_OK not %08x\n", hr
);
1484 psla
= (SCRIPT_LOGATTR
*)&sla
;
1485 hr
= ScriptBreak(TestItem1
, cChars
, &pItem
[0].a
, psla
);
1486 ok(hr
== S_OK
, "ScriptBreak Stub should return S_OK not %08x\n", hr
);
1488 /* Clean up and go */
1489 ScriptFreeCache(&psc
);
1490 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1495 static void test_ScriptTextOut2(HDC hdc
)
1497 /* Intent is to validate that the HDC passed into ScriptTextOut is
1498 * used instead of the (possibly) invalid cached one
1505 SCRIPT_ITEM pItem
[255];
1507 WCHAR TestItem1
[] = {'T', 'e', 's', 't', 'a', 0};
1512 unsigned short pwOutGlyphs1
[256];
1513 WORD pwLogClust
[256];
1514 SCRIPT_VISATTR psva
[256];
1517 GOFFSET pGoffset
[256];
1520 /* Create an extra DC that will be used until the ScriptTextOut */
1521 hdc1
= CreateCompatibleDC(hdc
);
1522 ok (hdc1
!= 0, "CreateCompatibleDC failed to create a DC\n");
1523 hdc2
= CreateCompatibleDC(hdc
);
1524 ok (hdc2
!= 0, "CreateCompatibleDC failed to create a DC\n");
1526 /* This is a valid test that will cause parsing to take place */
1529 hr
= ScriptItemize(TestItem1
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1530 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1531 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
1533 ok (pcItems
> 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
1535 ok (pItem
[0].iCharPos
== 0 && pItem
[1].iCharPos
== cInChars
,
1536 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
1537 pItem
[0].iCharPos
, cInChars
, pItem
[1].iCharPos
);
1539 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
1540 * ie. ScriptItemize has succeeded and that pItem has been set */
1543 psc
= NULL
; /* must be null on first call */
1546 hr
= ScriptShape(hdc2
, &psc
, TestItem1
, cChars
,
1547 cMaxGlyphs
, &pItem
[0].a
,
1548 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1549 ok (hr
== 0, "ScriptShape should return 0 not (%08x)\n", hr
);
1550 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1551 ok (pcGlyphs
== cChars
, "Chars in (%d) should equal Glyphs out (%d)\n", cChars
, pcGlyphs
);
1553 /* Note hdc is needed as glyph info is not yet in psc */
1554 hr
= ScriptPlace(hdc2
, &psc
, pwOutGlyphs1
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1556 ok (hr
== 0, "Should return 0 not (%08x)\n", hr
);
1558 /* key part!!! cached dc is being deleted */
1559 hr
= DeleteDC(hdc2
);
1560 ok(hr
== 1, "DeleteDC should return 1 not %08x\n", hr
);
1562 /* At this point the cached hdc (hdc2) has been destroyed,
1563 * however, we are passing in a *real* hdc (the original hdc).
1564 * The text should be written to that DC
1566 hr
= ScriptTextOut(hdc1
, &psc
, 0, 0, 0, NULL
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1567 piAdvance
, NULL
, pGoffset
);
1568 ok (hr
== 0, "ScriptTextOut should return 0 not (%08x)\n", hr
);
1569 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1573 /* Clean up and go */
1574 ScriptFreeCache(&psc
);
1575 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1580 static void test_ScriptTextOut3(HDC hdc
)
1586 SCRIPT_ITEM pItem
[255];
1588 WCHAR TestItem1
[] = {' ','\r', 0};
1593 unsigned short pwOutGlyphs1
[256];
1594 WORD pwLogClust
[256];
1595 SCRIPT_VISATTR psva
[256];
1598 GOFFSET pGoffset
[256];
1602 /* This is to ensure that non exisiting glyphs are translated into a valid glyph number */
1605 hr
= ScriptItemize(TestItem1
, cInChars
, cMaxItems
, NULL
, NULL
, pItem
, &pcItems
);
1606 ok (hr
== 0, "ScriptItemize should return 0, returned %08x\n", hr
);
1607 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
1609 ok (pcItems
> 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
1611 ok (pItem
[0].iCharPos
== 0 && pItem
[2].iCharPos
== cInChars
,
1612 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
1613 pItem
[0].iCharPos
, cInChars
, pItem
[2].iCharPos
);
1615 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
1616 * ie. ScriptItemize has succeeded and that pItem has been set */
1619 psc
= NULL
; /* must be null on first call */
1622 hr
= ScriptShape(hdc
, &psc
, TestItem1
, cChars
,
1623 cMaxGlyphs
, &pItem
[0].a
,
1624 pwOutGlyphs1
, pwLogClust
, psva
, &pcGlyphs
);
1625 ok (hr
== 0, "ScriptShape should return 0 not (%08x)\n", hr
);
1626 ok (psc
!= NULL
, "psc should not be null and have SCRIPT_CACHE buffer address\n");
1627 ok (pcGlyphs
== cChars
, "Chars in (%d) should equal Glyphs out (%d)\n", cChars
, pcGlyphs
);
1629 /* Note hdc is needed as glyph info is not yet in psc */
1630 hr
= ScriptPlace(hdc
, &psc
, pwOutGlyphs1
, pcGlyphs
, psva
, &pItem
[0].a
, piAdvance
,
1632 ok (hr
== 0, "Should return 0 not (%08x)\n", hr
);
1634 /* Test Rect Rgn is acceptable */
1639 hr
= ScriptTextOut(hdc
, &psc
, 0, 0, 0, &rect
, &pItem
[0].a
, NULL
, 0, pwOutGlyphs1
, pcGlyphs
,
1640 piAdvance
, NULL
, pGoffset
);
1641 ok (hr
== 0, "ScriptTextOut should return 0 not (%08x)\n", hr
);
1644 /* Clean up and go */
1645 ScriptFreeCache(&psc
);
1646 ok( psc
== NULL
, "Expected psc to be NULL, got %p\n", psc
);
1650 static void test_ScriptXtoX(void)
1651 /****************************************************************************************
1652 * This routine tests the ScriptXtoCP and ScriptCPtoX functions using static variables *
1653 ****************************************************************************************/
1655 static const WCHAR test
[] = {'t', 'e', 's', 't',0};
1656 SCRIPT_ITEM items
[2];
1660 WORD pwLogClust
[10] = {0, 0, 0, 1, 1, 2, 2, 3, 3, 3};
1661 WORD pwLogClust_RTL
[10] = {3, 3, 3, 2, 2, 1, 1, 0, 0, 0};
1662 SCRIPT_VISATTR psva
[10];
1663 int piAdvance
[10] = {200, 190, 210, 180, 170, 204, 189, 195, 212, 203};
1668 static const int offsets
[13] = {0, 66, 133, 200, 295, 390, 495, 600, 1051, 1502, 1953, 1953, 1953};
1669 static const int offsets_RTL
[13] = {780, 720, 660, 600, 495, 390, 295, 200, 133, 66, 0, 0, 0};
1671 hr
= ScriptItemize(test
, lstrlenW(test
), sizeof(items
)/sizeof(items
[0]), NULL
, NULL
, items
, NULL
);
1672 ok(!hr
, "ScriptItemize should return S_OK not %08x\n", hr
);
1677 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1678 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1680 ok(piCP
== -1, "Negative iX should return piCP=-1 not %d\n", piCP
);
1682 ok(piCP
== 10, "Negative iX should return piCP=10 not %d\n", piCP
);
1684 for(iCP
= 0; iCP
< 10; iCP
++)
1686 iX
= offsets
[iCP
]+1;
1689 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1690 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1691 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1692 ok(piTrailing
== 0, "iX=%d should return piTrailing=0 not %d\n", iX
, piTrailing
);
1695 for(iCP
= 0; iCP
< 10; iCP
++)
1697 iX
= offsets
[iCP
+1]-1;
1700 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1701 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1702 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1703 ok(piTrailing
== 1, "iX=%d should return piTrailing=1 not %d\n", iX
, piTrailing
);
1706 /* 0,1,2 are actually fractional offsets meaning that they will not be reporting the same iCP as comes in so don't test those */
1707 for(iCP
= 3; iCP
< 10; iCP
++)
1712 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1713 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1714 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1715 ok(piTrailing
== 0, "iX=%d should return piTrailing=0 not %d\n", iX
, piTrailing
);
1718 items
[0].a
.fRTL
= TRUE
;
1723 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1724 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1726 ok(piCP
== -1, "Negative iX should return piCP=-1 not %d\n", piCP
);
1728 ok(piCP
== 10, "Negative iX should return piCP=10 not %d\n", piCP
);
1733 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1734 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1735 ok(piCP
== -1, "iX=%d should return piCP=-1 not %d\n", iX
, piCP
);
1736 ok(piTrailing
== 1, "iX=%d should return piTrailing=1 not %d\n", iX
, piTrailing
);
1738 for(iCP
= 0; iCP
< 10; iCP
++)
1740 iX
= offsets_RTL
[iCP
]-1;
1743 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1744 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1745 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1746 ok(piTrailing
== 0, "iX=%d should return piTrailing=0 not %d\n", iX
, piTrailing
);
1749 for(iCP
= 0; iCP
< 10; iCP
++)
1751 iX
= offsets_RTL
[iCP
+1]+1;
1754 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1755 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1756 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1757 ok(piTrailing
== 1, "iX=%d should return piTrailing=1 not %d\n", iX
, piTrailing
);
1760 for(iCP
= 0; iCP
< 10; iCP
++)
1762 iX
= offsets_RTL
[iCP
];
1765 hr
= ScriptXtoCP(iX
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piCP
, &piTrailing
);
1766 ok(hr
== S_OK
, "ScriptXtoCP should return S_OK not %08x\n", hr
);
1767 ok(piCP
== iCP
, "iX=%d should return piCP=%d not %d\n", iX
, iCP
, piCP
);
1768 ok(piTrailing
== 0, "iX=%d should return piTrailing=0 not %d\n", iX
, piTrailing
);
1771 items
[0].a
.fRTL
= FALSE
;
1773 for(iCP
= 0; iCP
<= 11; iCP
++)
1778 hr
= ScriptCPtoX(iCP
, fTrailing
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piX
);
1779 ok(hr
== S_OK
, "ScriptCPtoX should return S_OK not %08x\n", hr
);
1780 ok(piX
== offsets
[iCP
],
1781 "iCP=%d should return piX=%d not %d\n", iCP
, offsets
[iCP
], piX
);
1784 for(iCP
= 0; iCP
<= 11; iCP
++)
1789 hr
= ScriptCPtoX(iCP
, fTrailing
, cChars
, cGlyphs
, pwLogClust
, psva
, piAdvance
, &items
[0].a
, &piX
);
1790 ok(hr
== S_OK
, "ScriptCPtoX should return S_OK not %08x\n", hr
);
1791 ok(piX
== offsets
[iCP
+1],
1792 "iCP=%d should return piX=%d not %d\n", iCP
, offsets
[iCP
+1], piX
);
1795 items
[0].a
.fRTL
= TRUE
;
1797 for(iCP
= 0; iCP
<= 11; iCP
++)
1802 hr
= ScriptCPtoX(iCP
, fTrailing
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piX
);
1803 ok(hr
== S_OK
, "ScriptCPtoX should return S_OK not %08x\n", hr
);
1804 ok(piX
== offsets_RTL
[iCP
],
1805 "iCP=%d should return piX=%d not %d\n", iCP
, offsets_RTL
[iCP
], piX
);
1808 for(iCP
= 0; iCP
<= 11; iCP
++)
1813 hr
= ScriptCPtoX(iCP
, fTrailing
, cChars
, cGlyphs
, pwLogClust_RTL
, psva
, piAdvance
, &items
[0].a
, &piX
);
1814 ok(hr
== S_OK
, "ScriptCPtoX should return S_OK not %08x\n", hr
);
1815 ok(piX
== offsets_RTL
[iCP
+1],
1816 "iCP=%d should return piX=%d not %d\n", iCP
, offsets_RTL
[iCP
+1], piX
);
1820 static void test_ScriptString(HDC hdc
)
1822 /*******************************************************************************************
1824 * This set of tests are for the string functions of uniscribe. The ScriptStringAnalyse
1825 * function allocates memory pointed to by the SCRIPT_STRING_ANALYSIS ssa pointer. This
1826 * memory is freed by ScriptStringFree. There needs to be a valid hdc for this as
1827 * ScriptStringAnalyse calls ScriptSItemize, ScriptShape and ScriptPlace which require it.
1832 WCHAR teststr
[] = {'T','e','s','t','1',' ','a','2','b','3', '\0'};
1833 int len
= (sizeof(teststr
) / sizeof(WCHAR
)) - 1;
1834 int Glyphs
= len
* 2 + 16;
1836 DWORD Flags
= SSA_GLYPHS
;
1838 const int Dx
[5] = {10, 10, 10, 10, 10};
1839 const BYTE InClass
= 0;
1840 SCRIPT_STRING_ANALYSIS ssa
= NULL
;
1845 const RECT rc
= {0, 50, 100, 100};
1848 BOOL Disabled
= FALSE
;
1849 const int *clip_len
;
1854 Charset
= -1; /* this flag indicates unicode input */
1855 /* Test without hdc to get E_PENDING */
1856 hr
= ScriptStringAnalyse( NULL
, teststr
, len
, Glyphs
, Charset
, Flags
,
1857 ReqWidth
, NULL
, NULL
, Dx
, NULL
,
1859 ok(hr
== E_PENDING
, "ScriptStringAnalyse Stub should return E_PENDING not %08x\n", hr
);
1861 /* test with hdc, this should be a valid test */
1862 hr
= ScriptStringAnalyse( hdc
, teststr
, len
, Glyphs
, Charset
, Flags
,
1863 ReqWidth
, NULL
, NULL
, Dx
, NULL
,
1865 ok(hr
== S_OK
, "ScriptStringAnalyse should return S_OK not %08x\n", hr
);
1866 ScriptStringFree(&ssa
);
1868 /* test makes sure that a call with a valid pssa still works */
1869 hr
= ScriptStringAnalyse( hdc
, teststr
, len
, Glyphs
, Charset
, Flags
,
1870 ReqWidth
, NULL
, NULL
, Dx
, NULL
,
1872 ok(hr
== S_OK
, "ScriptStringAnalyse should return S_OK not %08x\n", hr
);
1873 ok(ssa
!= NULL
, "ScriptStringAnalyse pssa should not be NULL\n");
1877 hr
= ScriptStringOut(ssa
, X
, Y
, Options
, &rc
, MinSel
, MaxSel
, Disabled
);
1878 ok(hr
== S_OK
, "ScriptStringOut should return S_OK not %08x\n", hr
);
1881 clip_len
= ScriptString_pcOutChars(ssa
);
1882 ok(*clip_len
== len
, "ScriptString_pcOutChars failed, got %d, expected %d\n", *clip_len
, len
);
1884 order
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *clip_len
* sizeof(UINT
));
1885 hr
= ScriptStringGetOrder(ssa
, order
);
1886 ok(hr
== S_OK
, "ScriptStringGetOrder failed, got %08x, expected S_OK\n", hr
);
1888 for (i
= 0; i
< *clip_len
; i
++) ok(order
[i
] == i
, "%d: got %d expected %d\n", i
, order
[i
], i
);
1889 HeapFree(GetProcessHeap(), 0, order
);
1891 hr
= ScriptStringFree(&ssa
);
1892 ok(hr
== S_OK
, "ScriptStringFree should return S_OK not %08x\n", hr
);
1895 static void test_ScriptStringXtoCP_CPtoX(HDC hdc
)
1897 /*****************************************************************************************
1899 * This test is for the ScriptStringXtoCP and ScriptStringXtoCP functions. Due to the
1900 * nature of the fonts between Windows and Wine, the test is implemented by generating
1901 * values using one one function then checking the output of the second. In this way
1902 * the validity of the functions is established using Windows as a base and confirming
1903 * similar behaviour in wine.
1907 static const WCHAR teststr1
[] = {0x05e9, 'i', 0x05dc, 'n', 0x05d5, 'e', 0x05dd, '.',0};
1908 static const BOOL rtl
[] = {1, 0, 1, 0, 1, 0, 1, 0};
1909 void *String
= (WCHAR
*) &teststr1
; /* ScriptStringAnalysis needs void */
1910 int String_len
= (sizeof(teststr1
)/sizeof(WCHAR
))-1;
1911 int Glyphs
= String_len
* 2 + 16; /* size of buffer as recommended */
1912 int Charset
= -1; /* unicode */
1913 DWORD Flags
= SSA_GLYPHS
;
1915 const BYTE InClass
= 0;
1916 SCRIPT_STRING_ANALYSIS ssa
= NULL
;
1918 int Ch
; /* Character position in string */
1920 int Cp
; /* Character position in string */
1925 /* Test with hdc, this should be a valid test
1926 * Here we generate an SCRIPT_STRING_ANALYSIS that will be used as input to the
1927 * following character positions to X and X to character position functions.
1930 hr
= ScriptStringAnalyse( hdc
, String
, String_len
, Glyphs
, Charset
, Flags
,
1931 ReqWidth
, NULL
, NULL
, NULL
, NULL
,
1934 hr
== E_INVALIDARG
, /* NT */
1935 "ScriptStringAnalyse should return S_OK or E_INVALIDARG not %08x\n", hr
);
1939 ok(ssa
!= NULL
, "ScriptStringAnalyse ssa should not be NULL\n");
1942 * Loop to generate character positions to provide starting positions for the
1943 * ScriptStringCPtoX and ScriptStringXtoCP functions
1945 for (Cp
= 0; Cp
< String_len
; Cp
++)
1947 /* The fTrailing flag is used to indicate whether the X being returned is at
1948 * the beginning or the end of the character. What happens here is that if
1949 * fTrailing indicates the end of the character, ie. FALSE, then ScriptStringXtoCP
1950 * returns the beginning of the next character and iTrailing is FALSE. So for this
1951 * loop iTrailing will be FALSE in both cases.
1953 hr
= ScriptStringCPtoX(ssa
, Cp
, TRUE
, &trail
);
1954 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
1955 hr
= ScriptStringCPtoX(ssa
, Cp
, FALSE
, &lead
);
1956 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
1958 ok(lead
> trail
, "Leading values should be after trialing for rtl chracters(%i)\n",Cp
);
1960 ok(lead
< trail
, "Trailing values should be after leading for ltr chracters(%i)\n",Cp
);
1962 /* move by 1 pixel so that we are not inbetween 2 characters. That could result in being the lead of a rtl and
1963 at the same time the trail of an ltr */
1965 /* inside the leading edge */
1967 if (rtl
[Cp
]) X
--; else X
++;
1968 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
1969 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
1970 ok(Cp
== Ch
, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp
, Ch
, trail
);
1971 ok(iTrailing
== FALSE
, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
1974 /* inside the trailing edge */
1976 if (rtl
[Cp
]) X
++; else X
--;
1977 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
1978 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
1979 ok(Cp
== Ch
, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp
, Ch
, trail
);
1980 ok(iTrailing
== TRUE
, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
1983 /* outside the "trailing" edge */
1984 if (Cp
< String_len
-1)
1986 if (rtl
[Cp
]) X
= lead
; else X
= trail
;
1988 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
1989 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
1990 ok(Cp
+ 1 == Ch
, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp
+ 1, Ch
, trail
);
1992 ok(iTrailing
== TRUE
, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
1995 ok(iTrailing
== FALSE
, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
1999 /* outside the "leading" edge */
2002 if (rtl
[Cp
]) X
= trail
; else X
= lead
;
2004 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
2005 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
2006 ok(Cp
- 1 == Ch
, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp
- 1, Ch
, trail
);
2007 if (Cp
!= 0 && rtl
[Cp
-1])
2008 ok(iTrailing
== FALSE
, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
2011 ok(iTrailing
== TRUE
, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
2016 /* Check beyond the leading boundary of the whole string */
2019 /* having a leading rtl character seems to confuse usp */
2020 /* this looks to be a windows bug we should emulate */
2021 hr
= ScriptStringCPtoX(ssa
, 0, TRUE
, &X
);
2022 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
2024 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
2025 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
2026 ok(Ch
== 1, "ScriptStringXtoCP should return Ch = 1 not %d for X outside leading edge when rtl\n", Ch
);
2027 ok(iTrailing
== FALSE
, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside leading edge when rtl\n",
2032 hr
= ScriptStringCPtoX(ssa
, 0, FALSE
, &X
);
2033 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
2035 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
2036 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
2037 ok(Ch
== -1, "ScriptStringXtoCP should return Ch = -1 not %d for X outside leading edge\n", Ch
);
2038 ok(iTrailing
== TRUE
, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = outside leading edge\n",
2042 /* Check beyond the end boundary of the whole string */
2043 if (rtl
[String_len
-1])
2045 hr
= ScriptStringCPtoX(ssa
, String_len
-1, FALSE
, &X
);
2046 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
2050 hr
= ScriptStringCPtoX(ssa
, String_len
-1, TRUE
, &X
);
2051 ok(hr
== S_OK
, "ScriptStringCPtoX should return S_OK not %08x\n", hr
);
2054 hr
= ScriptStringXtoCP(ssa
, X
, &Ch
, &iTrailing
);
2055 ok(hr
== S_OK
, "ScriptStringXtoCP should return S_OK not %08x\n", hr
);
2056 ok(Ch
== String_len
, "ScriptStringXtoCP should return Ch = %i not %d for X outside trailing edge\n", String_len
, Ch
);
2057 ok(iTrailing
== FALSE
, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = outside traling edge\n",
2061 * Cleanup the SSA for the next round of tests
2063 hr
= ScriptStringFree(&ssa
);
2064 ok(hr
== S_OK
, "ScriptStringFree should return S_OK not %08x\n", hr
);
2067 * Test to see that exceeding the number of chars returns E_INVALIDARG. First
2068 * generate an SSA for the subsequent tests.
2070 hr
= ScriptStringAnalyse( hdc
, String
, String_len
, Glyphs
, Charset
, Flags
,
2071 ReqWidth
, NULL
, NULL
, NULL
, NULL
,
2073 ok(hr
== S_OK
, "ScriptStringAnalyse should return S_OK not %08x\n", hr
);
2076 * When ScriptStringCPtoX is called with a character position Cp that exceeds the
2077 * string length, return E_INVALIDARG. This also invalidates the ssa so a
2078 * ScriptStringFree should also fail.
2081 Cp
= String_len
+ 1;
2082 hr
= ScriptStringCPtoX(ssa
, Cp
, fTrailing
, &X
);
2083 ok(hr
== E_INVALIDARG
, "ScriptStringCPtoX should return E_INVALIDARG not %08x\n", hr
);
2085 ScriptStringFree(&ssa
);
2089 static void test_ScriptCacheGetHeight(HDC hdc
)
2092 SCRIPT_CACHE sc
= NULL
;
2095 hr
= ScriptCacheGetHeight(NULL
, NULL
, NULL
);
2096 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2098 hr
= ScriptCacheGetHeight(NULL
, &sc
, NULL
);
2099 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2101 hr
= ScriptCacheGetHeight(NULL
, &sc
, &height
);
2102 ok(hr
== E_PENDING
, "expected E_PENDING, got 0x%08x\n", hr
);
2106 hr
= ScriptCacheGetHeight(hdc
, &sc
, &height
);
2107 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2108 ok(height
> 0, "expected height > 0\n");
2110 ScriptFreeCache(&sc
);
2113 static void test_ScriptGetGlyphABCWidth(HDC hdc
)
2116 SCRIPT_CACHE sc
= NULL
;
2119 hr
= ScriptGetGlyphABCWidth(NULL
, NULL
, 'a', NULL
);
2120 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2122 hr
= ScriptGetGlyphABCWidth(NULL
, &sc
, 'a', NULL
);
2123 ok(broken(hr
== E_PENDING
) ||
2124 hr
== E_INVALIDARG
, /* WIN7 */
2125 "expected E_INVALIDARG, got 0x%08x\n", hr
);
2127 hr
= ScriptGetGlyphABCWidth(NULL
, &sc
, 'a', &abc
);
2128 ok(hr
== E_PENDING
, "expected E_PENDING, got 0x%08x\n", hr
);
2130 if (0) { /* crashes on WinXP */
2131 hr
= ScriptGetGlyphABCWidth(hdc
, &sc
, 'a', NULL
);
2132 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2135 hr
= ScriptGetGlyphABCWidth(hdc
, &sc
, 'a', &abc
);
2136 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2138 ScriptFreeCache(&sc
);
2141 static void test_ScriptLayout(void)
2144 static const BYTE levels
[][10] =
2146 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2147 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
2148 { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
2149 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
2151 { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
2152 { 1, 1, 1, 2, 2, 2, 1, 1, 1, 1 },
2153 { 2, 2, 2, 1, 1, 1, 2, 2, 2, 2 },
2154 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 0 },
2155 { 1, 1, 2, 2, 3, 3, 2, 2, 1, 1 },
2157 { 0, 0, 1, 1, 2, 2, 1, 1, 0, 1 },
2158 { 1, 0, 1, 2, 2, 1, 2, 1, 0, 1 },
2160 static const int expect_l2v
[][10] =
2162 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
2163 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
2164 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
2165 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
2167 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5},
2168 /**/ { 9, 8, 7, 4, 5, 6, 3 ,2 ,1, 0},
2169 /**/ { 7, 8, 9, 6, 5, 4, 0 ,1 ,2, 3},
2170 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9},
2171 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0},
2173 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9},
2174 /**/ { 0, 1, 7, 5, 6, 4, 3 ,2 ,8, 9},
2176 static const int expect_v2l
[][10] =
2178 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
2179 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
2180 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
2181 { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
2183 { 0, 1, 2, 3, 4, 9, 8 ,7 ,6, 5},
2184 { 9, 8, 7, 6, 3, 4, 5 ,2 ,1, 0},
2185 { 6, 7, 8, 9, 5, 4, 3 ,0 ,1, 2},
2186 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9},
2187 { 9, 8, 2, 3, 5, 4, 6 ,7 ,1, 0},
2189 { 0, 1, 7, 6, 4, 5, 3 ,2 ,8, 9},
2190 { 0, 1, 7, 6, 5, 3, 4 ,2 ,8, 9},
2193 int i
, j
, vistolog
[sizeof(levels
[0])], logtovis
[sizeof(levels
[0])];
2195 hr
= ScriptLayout(sizeof(levels
[0]), NULL
, vistolog
, logtovis
);
2196 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2198 hr
= ScriptLayout(sizeof(levels
[0]), levels
[0], NULL
, NULL
);
2199 ok(hr
== E_INVALIDARG
, "expected E_INVALIDARG, got 0x%08x\n", hr
);
2201 for (i
= 0; i
< sizeof(levels
)/sizeof(levels
[0]); i
++)
2203 hr
= ScriptLayout(sizeof(levels
[0]), levels
[i
], vistolog
, logtovis
);
2204 ok(hr
== S_OK
, "expected S_OK, got 0x%08x\n", hr
);
2206 for (j
= 0; j
< sizeof(levels
[i
]); j
++)
2208 ok(expect_v2l
[i
][j
] == vistolog
[j
],
2209 "failure: levels[%d][%d] = %d, vistolog[%d] = %d\n",
2210 i
, j
, levels
[i
][j
], j
, vistolog
[j
] );
2213 for (j
= 0; j
< sizeof(levels
[i
]); j
++)
2215 ok(expect_l2v
[i
][j
] == logtovis
[j
],
2216 "failure: levels[%d][%d] = %d, logtovis[%d] = %d\n",
2217 i
, j
, levels
[i
][j
], j
, logtovis
[j
] );
2222 static BOOL CALLBACK
enum_proc(LGRPID group
, LCID lcid
, LPSTR locale
, LONG_PTR lparam
)
2225 SCRIPT_DIGITSUBSTITUTE sds
;
2230 if (!IsValidLocale(lcid
, LCID_INSTALLED
)) return TRUE
;
2232 memset(&sds
, 0, sizeof(sds
));
2233 memset(&sc
, 0, sizeof(sc
));
2234 memset(&ss
, 0, sizeof(ss
));
2236 lcid_old
= GetThreadLocale();
2237 if (!SetThreadLocale(lcid
)) return TRUE
;
2239 hr
= ScriptRecordDigitSubstitution(lcid
, &sds
);
2240 ok(hr
== S_OK
, "ScriptRecordDigitSubstitution failed: 0x%08x\n", hr
);
2242 hr
= ScriptApplyDigitSubstitution(&sds
, &sc
, &ss
);
2243 ok(hr
== S_OK
, "ScriptApplyDigitSubstitution failed: 0x%08x\n", hr
);
2245 SetThreadLocale(lcid_old
);
2249 static void test_digit_substitution(void)
2253 static const LGRPID groups
[] =
2255 LGRPID_WESTERN_EUROPE
,
2256 LGRPID_CENTRAL_EUROPE
,
2263 LGRPID_TRADITIONAL_CHINESE
,
2264 LGRPID_SIMPLIFIED_CHINESE
,
2274 static BOOL (WINAPI
* pEnumLanguageGroupLocalesA
)(LANGGROUPLOCALE_ENUMPROCA
,LGRPID
,DWORD
,LONG_PTR
);
2276 hKernel32
= GetModuleHandleA("kernel32.dll");
2277 pEnumLanguageGroupLocalesA
= (void*)GetProcAddress(hKernel32
, "EnumLanguageGroupLocalesA");
2279 if (!pEnumLanguageGroupLocalesA
)
2281 win_skip("EnumLanguageGroupLocalesA not available on this platform\n");
2285 for (i
= 0; i
< sizeof(groups
)/sizeof(groups
[0]); i
++)
2287 ret
= pEnumLanguageGroupLocalesA(enum_proc
, groups
[i
], 0, 0);
2288 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
2290 win_skip("EnumLanguageGroupLocalesA not implemented on this platform\n");
2294 ok(ret
, "EnumLanguageGroupLocalesA failed unexpectedly: %u\n", GetLastError());
2298 static void test_ScriptGetProperties(void)
2300 const SCRIPT_PROPERTIES
**props
;
2304 hr
= ScriptGetProperties(NULL
, NULL
);
2305 ok(hr
== E_INVALIDARG
, "ScriptGetProperties succeeded\n");
2307 hr
= ScriptGetProperties(NULL
, &num
);
2308 ok(hr
== S_OK
, "ScriptGetProperties failed: 0x%08x\n", hr
);
2310 hr
= ScriptGetProperties(&props
, NULL
);
2311 ok(hr
== S_OK
, "ScriptGetProperties failed: 0x%08x\n", hr
);
2313 hr
= ScriptGetProperties(&props
, &num
);
2314 ok(hr
== S_OK
, "ScriptGetProperties failed: 0x%08x\n", hr
);
2317 static void test_ScriptBreak(void)
2319 static const WCHAR test
[] = {' ','\r','\n',0};
2320 SCRIPT_ITEM items
[4];
2324 hr
= ScriptItemize(test
, 3, 4, NULL
, NULL
, items
, NULL
);
2325 ok(!hr
, "ScriptItemize should return S_OK not %08x\n", hr
);
2327 memset(&la
, 0, sizeof(la
));
2328 hr
= ScriptBreak(test
, 1, &items
[0].a
, &la
);
2329 ok(!hr
, "ScriptBreak should return S_OK not %08x\n", hr
);
2331 ok(!la
.fSoftBreak
, "fSoftBreak set\n");
2332 ok(la
.fWhiteSpace
, "fWhiteSpace not set\n");
2333 ok(la
.fCharStop
, "fCharStop not set\n");
2334 ok(!la
.fWordStop
, "fWordStop set\n");
2335 ok(!la
.fInvalid
, "fInvalid set\n");
2336 ok(!la
.fReserved
, "fReserved set\n");
2338 memset(&la
, 0, sizeof(la
));
2339 hr
= ScriptBreak(test
+ 1, 1, &items
[1].a
, &la
);
2340 ok(!hr
, "ScriptBreak should return S_OK not %08x\n", hr
);
2342 ok(!la
.fSoftBreak
, "fSoftBreak set\n");
2343 ok(!la
.fWhiteSpace
, "fWhiteSpace set\n");
2344 ok(la
.fCharStop
, "fCharStop not set\n");
2345 ok(!la
.fWordStop
, "fWordStop set\n");
2346 ok(!la
.fInvalid
, "fInvalid set\n");
2347 ok(!la
.fReserved
, "fReserved set\n");
2349 memset(&la
, 0, sizeof(la
));
2350 hr
= ScriptBreak(test
+ 2, 1, &items
[2].a
, &la
);
2351 ok(!hr
, "ScriptBreak should return S_OK not %08x\n", hr
);
2353 ok(!la
.fSoftBreak
, "fSoftBreak set\n");
2354 ok(!la
.fWhiteSpace
, "fWhiteSpace set\n");
2355 ok(la
.fCharStop
, "fCharStop not set\n");
2356 ok(!la
.fWordStop
, "fWordStop set\n");
2357 ok(!la
.fInvalid
, "fInvalid set\n");
2358 ok(!la
.fReserved
, "fReserved set\n");
2361 static void test_newlines(void)
2363 static const WCHAR test1
[] = {'t','e','x','t','\r','t','e','x','t',0};
2364 static const WCHAR test2
[] = {'t','e','x','t','\n','t','e','x','t',0};
2365 static const WCHAR test3
[] = {'t','e','x','t','\r','\n','t','e','x','t',0};
2366 static const WCHAR test4
[] = {'t','e','x','t','\n','\r','t','e','x','t',0};
2367 static const WCHAR test5
[] = {'1','2','3','4','\n','\r','1','2','3','4',0};
2368 SCRIPT_ITEM items
[5];
2373 hr
= ScriptItemize(test1
, lstrlenW(test1
), 5, NULL
, NULL
, items
, &count
);
2374 ok(hr
== S_OK
, "ScriptItemize failed: 0x%08x\n", hr
);
2375 ok(count
== 3, "got %d expected 3\n", count
);
2378 hr
= ScriptItemize(test2
, lstrlenW(test2
), 5, NULL
, NULL
, items
, &count
);
2379 ok(hr
== S_OK
, "ScriptItemize failed: 0x%08x\n", hr
);
2380 ok(count
== 3, "got %d expected 3\n", count
);
2383 hr
= ScriptItemize(test3
, lstrlenW(test3
), 5, NULL
, NULL
, items
, &count
);
2384 ok(hr
== S_OK
, "ScriptItemize failed: 0x%08x\n", hr
);
2385 ok(count
== 4, "got %d expected 4\n", count
);
2388 hr
= ScriptItemize(test4
, lstrlenW(test4
), 5, NULL
, NULL
, items
, &count
);
2389 ok(hr
== S_OK
, "ScriptItemize failed: 0x%08x\n", hr
);
2390 ok(count
== 4, "got %d expected 4\n", count
);
2393 hr
= ScriptItemize(test5
, lstrlenW(test5
), 5, NULL
, NULL
, items
, &count
);
2394 ok(hr
== S_OK
, "ScriptItemize failed: 0x%08x\n", hr
);
2395 ok(count
== 4, "got %d expected 4\n", count
);
2405 unsigned short pwOutGlyphs
[256];
2407 /* We need a valid HDC to drive a lot of Script functions which requires the following *
2408 * to set up for the tests. */
2409 hwnd
= CreateWindowExA(0, "static", "", WS_POPUP
, 0,0,100,100,
2412 ShowWindow(hwnd
, SW_SHOW
);
2415 hdc
= GetDC(hwnd
); /* We now have a hdc */
2416 ok( hdc
!= NULL
, "HDC failed to be created %p\n", hdc
);
2418 memset(&lf
, 0, sizeof(LOGFONTA
));
2419 lstrcpyA(lf
.lfFaceName
, "Tahoma");
2424 hfont
= SelectObject(hdc
, CreateFontIndirectA(&lf
));
2425 ok(hfont
!= NULL
, "SelectObject failed: %p\n", hfont
);
2427 test_ScriptItemize();
2428 test_ScriptItemIzeShapePlace(hdc
,pwOutGlyphs
);
2429 test_ScriptGetCMap(hdc
, pwOutGlyphs
);
2430 test_ScriptCacheGetHeight(hdc
);
2431 test_ScriptGetGlyphABCWidth(hdc
);
2432 test_ScriptShape(hdc
);
2433 test_ScriptShapeOpenType(hdc
);
2434 test_ScriptPlace(hdc
);
2436 test_ScriptGetFontProperties(hdc
);
2437 test_ScriptTextOut(hdc
);
2438 test_ScriptTextOut2(hdc
);
2439 test_ScriptTextOut3(hdc
);
2441 test_ScriptString(hdc
);
2442 test_ScriptStringXtoCP_CPtoX(hdc
);
2444 test_ScriptLayout();
2445 test_digit_substitution();
2446 test_ScriptGetProperties();
2450 ReleaseDC(hwnd
, hdc
);
2451 DestroyWindow(hwnd
);