4 * Copyright 2006 Jeff Latimer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Uniscribe allows for processing of complex scripts such as joining
22 * and filtering characters and bi-directional text with custom line breaks.
28 #include <wine/test.h>
35 static void test_ScriptItemIzeShapePlace(unsigned short pwOutGlyphs[256])
39 const SCRIPT_PROPERTIES **ppSp;
45 SCRIPT_ITEM pItem[255];
47 WCHAR TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0};
48 WCHAR TestItem2[6] = {'T', 'e', 's', 't', 0x0166, 0};
53 unsigned short pwOutGlyphs1[256];
54 unsigned short pwOutGlyphs2[256];
55 unsigned short pwLogClust[256];
56 SCRIPT_VISATTR psva[256];
59 GOFFSET pGoffset[256];
63 /* We need a valid HDC to drive a lot of Script functions which requires the following *
64 * to set up for the tests. */
65 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
68 ShowWindow(hwnd, SW_SHOW);
71 hdc = GetDC(hwnd); /* We now have a hdc */
72 ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
74 /* Start testing usp10 functions */
75 /* This test determines that the pointer returned by ScriptGetProperties is valid
76 * by checking a known value in the table */
77 hr = ScriptGetProperties(&ppSp, &iMaxProps);
78 trace("number of script properties %d\n", iMaxProps);
79 ok (iMaxProps > 0, "Number of scripts returned should not be 0\n");
81 ok( ppSp[5]->langid == 9, "Langid[5] not = to 9\n"); /* Check a known value to ensure */
85 /* This set of tests are to check that the various edits in ScriptIemize work */
86 cInChars = 5; /* Length of test without NULL */
87 cMaxItems = 1; /* Check threshold value */
88 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
89 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cMaxItems < 2. Was %d\n",
93 hr = ScriptItemize(NULL, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
94 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pwcInChars is NULL\n");
98 hr = ScriptItemize(TestItem1, 0, cMaxItems, NULL, NULL, pItem, &pcItems);
99 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if cInChars is 0\n");
103 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, NULL, &pcItems);
104 ok (hr == E_INVALIDARG, "ScriptItemize should return E_INVALIDARG if pItems is NULL\n");
106 /* This is a valid test that will cause parsing to take place */
109 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
110 ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
111 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
113 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
115 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
116 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
117 pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
119 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
120 * ie. ScriptItemize has succeeded and that pItem has been set */
124 psc = NULL; /* must be null on first call */
126 cMaxGlyphs = cInChars;
127 hr = ScriptShape(NULL, &psc, TestItem1, cChars,
128 cMaxGlyphs, &pItem[0].a,
129 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
130 ok (hr == E_PENDING, "If psc is NULL (%08x) the E_PENDING should be returned\n",
133 hr = ScriptShape(hdc, &psc, TestItem1, cChars,
134 cMaxGlyphs, &pItem[0].a,
135 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
136 ok (hr == E_OUTOFMEMORY, "If not enough output area cChars (%d) is > than CMaxGlyphs "
137 "(%d) but not E_OUTOFMEMORY\n",
140 hr = ScriptShape(hdc, &psc, TestItem1, cChars,
141 cMaxGlyphs, &pItem[0].a,
142 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
143 ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
144 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
145 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
147 hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
149 ok (hr == 0, "Should return 0 not (%08x)\n", (unsigned int) hr);
150 for (cnt=0; cnt < pcGlyphs; cnt++)
151 pwOutGlyphs[cnt] = pwOutGlyphs1[cnt]; /* Send to next function */
154 /* This test will check to make sure that SCRIPT_CACHE is reused and that not translation *
155 * takes place if fNoGlyphIndex is set. */
159 hr = ScriptItemize(TestItem2, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
160 ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
161 /* This test is for the intertrim operation of ScriptItemize where only one SCRIPT_ITEM is *
163 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
164 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
165 pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
166 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue */
170 pItem[0].a.fNoGlyphIndex = 1; /* say no translate */
171 hr = ScriptShape(NULL, &psc, TestItem2, cChars,
172 cMaxGlyphs, &pItem[0].a,
173 pwOutGlyphs2, pwLogClust, psva, &pcGlyphs);
174 ok (hr != E_PENDING, "If psc should not be NULL (%08x) and the E_PENDING should be returned\n",
176 ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
177 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
178 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
179 for (cnt=0; cnt < cChars && TestItem2[cnt] == pwOutGlyphs2[cnt]; cnt++) {}
180 ok (cnt == cChars, "Translation to place when told not to. WCHAR %d - %04x != %04x\n",
181 cnt, TestItem2[cnt], pwOutGlyphs2[cnt]);
183 hr = ScriptPlace(NULL, &psc, pwOutGlyphs2, pcGlyphs, psva, &pItem[0].a, piAdvance,
185 ok (hr == 0, "ScriptPlace should return 0 not (%08x)\n", (unsigned int) hr);
188 hr = ScriptFreeCache( &psc);
189 ok (!psc, "psc is not null after ScriptFreeCache\n");
193 ReleaseDC(hwnd, hdc);
197 void test_ScriptGetCMap(unsigned short pwOutGlyphs[256])
202 SCRIPT_CACHE psc = NULL;
205 unsigned short pwOutGlyphs3[256];
206 WCHAR TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0};
210 /* We need a valid HDC to drive a lot of Script functions which requires the following *
211 * to set up for the tests. */
212 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
217 ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
219 /* Check to make sure that SCRIPT_CACHE gets allocated ok */
221 cInChars = cChars = 5;
222 /* Some sanity checks for ScriptGetCMap */
224 hr = ScriptGetCMap(NULL, NULL, NULL, 0, 0, NULL);
225 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL,0,0,NULL), "
226 "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
228 hr = ScriptGetCMap(NULL, NULL, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
229 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
230 "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
232 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
234 hr = ScriptGetCMap(NULL, &psc, NULL, 0, 0, NULL);
235 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0NULL), expected E_INVALIDARG, "
236 "got %08x\n", (unsigned int)hr);
237 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
239 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
241 hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
242 ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", (unsigned int)hr);
243 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
244 /* Check to see if the results are the same as those returned by ScriptShape */
245 hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, dwFlags, pwOutGlyphs3);
246 ok (hr == 0, "ScriptGetCMap should return 0 not (%08x)\n", (unsigned int) hr);
247 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
248 for (cnt=0; cnt < cChars && pwOutGlyphs[cnt] == pwOutGlyphs3[cnt]; cnt++) {}
249 ok (cnt == cInChars, "Translation not correct. WCHAR %d - %04x != %04x\n",
250 cnt, pwOutGlyphs[cnt], pwOutGlyphs3[cnt]);
252 hr = ScriptFreeCache( &psc);
253 ok (!psc, "psc is not null after ScriptFreeCache\n");
256 void test_ScriptGetFontProperties(void)
261 SCRIPT_CACHE psc,old_psc;
262 SCRIPT_FONTPROPERTIES sfp;
264 /* Only do the bare minumum to get a valid hdc */
265 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
269 ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
271 /* Some sanity checks for ScriptGetFontProperties */
273 hr = ScriptGetFontProperties(NULL,NULL,NULL);
274 ok( hr == E_INVALIDARG, "(NULL,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
276 hr = ScriptGetFontProperties(NULL,NULL,&sfp);
277 ok( hr == E_INVALIDARG, "(NULL,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
279 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
281 hr = ScriptGetFontProperties(NULL,&psc,NULL);
282 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
283 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
285 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
287 hr = ScriptGetFontProperties(NULL,&psc,&sfp);
288 ok( hr == E_PENDING, "(NULL,&psc,&sfp), expected E_PENDING, got %08x\n", (unsigned int)hr);
289 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
291 hr = ScriptGetFontProperties(hdc,NULL,NULL);
292 ok( hr == E_INVALIDARG, "(hdc,NULL,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
294 hr = ScriptGetFontProperties(hdc,NULL,&sfp);
295 ok( hr == E_INVALIDARG, "(hdc,NULL,&sfp), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
297 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
299 hr = ScriptGetFontProperties(hdc,&psc,NULL);
300 ok( hr == E_INVALIDARG, "(hdc,&psc,NULL), expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
301 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
303 /* Pass an uninitialized sfp */
305 hr = ScriptGetFontProperties(hdc,&psc,&sfp);
306 ok( hr == E_INVALIDARG, "(hdc,&psc,&sfp) partly uninitialized, expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
307 ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
308 ScriptFreeCache(&psc);
309 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
311 /* Give it the correct cBytes, we don't care about what's coming back */
312 sfp.cBytes = sizeof(SCRIPT_FONTPROPERTIES);
314 hr = ScriptGetFontProperties(hdc,&psc,&sfp);
315 ok( hr == S_OK, "(hdc,&psc,&sfp) partly initialized, expected S_OK, got %08x\n", (unsigned int)hr);
316 ok( psc != NULL, "Expected a pointer in psc, got NULL\n");
318 /* Save the psc pointer */
320 /* Now a NULL hdc again */
321 hr = ScriptGetFontProperties(NULL,&psc,&sfp);
322 ok( hr == S_OK, "(NULL,&psc,&sfp), expected S_OK, got %08x\n", (unsigned int)hr);
323 ok( psc == old_psc, "Expected psc not to be changed, was %p is now %p\n", old_psc, psc);
324 ScriptFreeCache(&psc);
325 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
328 ReleaseDC(hwnd, hdc);
332 void test_ScriptTextOut(void)
340 SCRIPT_ITEM pItem[255];
342 WCHAR TestItem1[6] = {'T', 'e', 's', 't', 0x0166, 0};
347 unsigned short pwOutGlyphs1[256];
348 unsigned short pwLogClust[256];
349 SCRIPT_VISATTR psva[256];
352 GOFFSET pGoffset[256];
356 /* We need a valid HDC to drive a lot of Script functions which requires the following *
357 * to set up for the tests. */
358 hwnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,
361 ShowWindow(hwnd, SW_SHOW);
364 hdc = GetDC(hwnd); /* We now have a hdc */
365 ok( hdc != NULL, "HDC failed to be created %p\n", hdc);
367 /* This is a valid test that will cause parsing to take place */
370 hr = ScriptItemize(TestItem1, cInChars, cMaxItems, NULL, NULL, pItem, &pcItems);
371 ok (hr == 0, "ScriptItemize should return 0, returned %08x\n", (unsigned int) hr);
372 /* This test is for the interim operation of ScriptItemize where only one SCRIPT_ITEM is *
374 ok (pcItems > 0, "The number of SCRIPT_ITEMS should be greater than 0\n");
376 ok (pItem[0].iCharPos == 0 && pItem[1].iCharPos == cInChars,
377 "Start pos not = 0 (%d) or end pos not = %d (%d)\n",
378 pItem[0].iCharPos, cInChars, pItem[1].iCharPos);
380 /* It would appear that we have a valid SCRIPT_ANALYSIS and can continue
381 * ie. ScriptItemize has succeeded and that pItem has been set */
385 psc = NULL; /* must be null on first call */
387 cMaxGlyphs = cInChars;
389 hr = ScriptShape(hdc, &psc, TestItem1, cChars,
390 cMaxGlyphs, &pItem[0].a,
391 pwOutGlyphs1, pwLogClust, psva, &pcGlyphs);
392 ok (hr == 0, "ScriptShape should return 0 not (%08x)\n", (unsigned int) hr);
393 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
394 ok (pcGlyphs == cChars, "Chars in (%d) should equal Glyphs out (%d)\n", cChars, pcGlyphs);
396 hr = ScriptPlace(NULL, &psc, pwOutGlyphs1, pcGlyphs, psva, &pItem[0].a, piAdvance,
398 ok (hr == 0, "Should return 0 not (%08x)\n", (unsigned int) hr);
399 ScriptFreeCache(&psc); /* Get rid of psc for next test set */
400 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
402 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL);
403 ok (hr == E_INVALIDARG, "Should return 0 not (%08x)\n", (unsigned int) hr);
405 hr = ScriptTextOut(NULL, NULL, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
406 piAdvance, NULL, pGoffset);
407 ok( hr == E_INVALIDARG, "(NULL,NULL,TestItem1, cInChars, dwFlags, pwOutGlyphs3), "
408 "expected E_INVALIDARG, got %08x\n", (unsigned int)hr);
410 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
412 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0,
414 ok( hr == E_INVALIDARG, "(NULL,&psc,NULL,0,0,0,NULL,), expected E_INVALIDARG, "
415 "got %08x\n", (unsigned int)hr);
416 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
418 /* Set psc to NULL, to be able to check if a pointer is returned in psc */
420 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
421 piAdvance, NULL, pGoffset);
422 ok( hr == E_PENDING, "(NULL,&psc,), expected E_PENDING, got %08x\n", (unsigned int)hr);
423 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
425 /* Se that is gets a psc and that returns 0 status */
426 hr = ScriptTextOut(hdc, &psc, 0, 0, 0, NULL, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
427 piAdvance, NULL, pGoffset);
428 ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
429 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
431 /* Test Rect Rgn is acceptable and that it works without hdc */
436 hr = ScriptTextOut(NULL, &psc, 0, 0, 0, &rect, &pItem[0].a, NULL, 0, pwOutGlyphs1, pcGlyphs,
437 piAdvance, NULL, pGoffset);
438 ok (hr == 0, "ScriptTextOut should return 0 not (%08x)\n", (unsigned int) hr);
439 ok (psc != NULL, "psc should not be null and have SCRIPT_CACHE buffer address\n");
441 /* Clean up and go */
442 ScriptFreeCache(&psc);
443 ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
446 ReleaseDC(hwnd, hdc);
450 static void test_ScriptString(void)
454 WCHAR teststr[6] = {'T', 'e', 's', 't', '1', '\0'};
455 void *pString = (WCHAR *) &teststr;
457 int cGlyphs = cString * 2 + 16;
459 DWORD dwFlags = SSA_GLYPHS;
461 SCRIPT_CONTROL psControl;
462 SCRIPT_STATE psState;
463 const int piDx[5] = {10, 10, 10, 10, 10};
464 SCRIPT_TABDEF pTabdef;
465 const BYTE pbInClass = 0;
466 SCRIPT_STRING_ANALYSIS pssa;
471 const RECT prc = {0, 50, 100, 100};
474 BOOL fDisabled = FALSE;
475 hr = ScriptStringAnalyse( hdc, pString, cString, cGlyphs, iCharset, dwFlags,
476 iReqWidth, &psControl, &psState, piDx, &pTabdef,
478 ok(hr == E_INVALIDARG, "ScriptStringAnalyse Stub should return E_INVALIDARG not %08x\n", (unsigned int) hr);
479 hr = ScriptStringOut(pssa, iX, iY, uOptions, &prc, iMinSel, iMaxSel,fDisabled);
480 ok(hr == E_NOTIMPL, "ScriptStringOut Stub should return E_NOTIMPL not %08x\n", (unsigned int) hr);
481 hr = ScriptStringFree(&pssa);
482 ok(hr == S_OK, "ScriptStringFree Stub should return S_OK not %08x\n", (unsigned int) hr);
487 unsigned short pwOutGlyphs[256];
489 test_ScriptItemIzeShapePlace(pwOutGlyphs);
490 test_ScriptGetCMap(pwOutGlyphs);
491 test_ScriptGetFontProperties();
492 test_ScriptTextOut();