dwrite: Recognize more Unicode ranges in script analyzer.
[wine/multimedia.git] / dlls / dwrite / tests / analyzer.c
blobe504a22b4fc815f3405e9b5c2bc7fe9afdec5456
1 /*
2 * Text analyzing tests
4 * Copyright 2012 Nikolay Sivov for CodeWeavers
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 #define COBJMACROS
23 #include <assert.h>
25 #include "initguid.h"
26 #include "windows.h"
27 #include "dwrite.h"
29 #include "wine/test.h"
31 static IDWriteFactory *factory;
33 enum analysis_kind {
34 ScriptAnalysis,
35 LastKind
38 static const char *get_analysis_kind_name(enum analysis_kind kind)
40 switch (kind)
42 case ScriptAnalysis:
43 return "ScriptAnalysis";
44 default:
45 return "unknown";
49 struct script_analysis {
50 UINT32 pos;
51 UINT32 len;
52 DWRITE_SCRIPT_SHAPES shapes;
55 struct call_entry {
56 enum analysis_kind kind;
57 struct script_analysis sa;
60 struct testcontext {
61 enum analysis_kind kind;
62 BOOL todo;
63 int *failcount;
64 const char *file;
65 int line;
68 struct call_sequence
70 int count;
71 int size;
72 struct call_entry *sequence;
75 #define NUM_CALL_SEQUENCES 1
76 #define ANALYZER_ID 0
77 static struct call_sequence *sequences[NUM_CALL_SEQUENCES];
78 static struct call_sequence *expected_seq[1];
80 static void add_call(struct call_sequence **seq, int sequence_index, const struct call_entry *call)
82 struct call_sequence *call_seq = seq[sequence_index];
84 if (!call_seq->sequence)
86 call_seq->size = 10;
87 call_seq->sequence = HeapAlloc(GetProcessHeap(), 0,
88 call_seq->size * sizeof (struct call_entry));
91 if (call_seq->count == call_seq->size)
93 call_seq->size *= 2;
94 call_seq->sequence = HeapReAlloc(GetProcessHeap(), 0,
95 call_seq->sequence,
96 call_seq->size * sizeof (struct call_entry));
99 assert(call_seq->sequence);
101 call_seq->sequence[call_seq->count++] = *call;
104 static inline void flush_sequence(struct call_sequence **seg, int sequence_index)
106 struct call_sequence *call_seq = seg[sequence_index];
108 HeapFree(GetProcessHeap(), 0, call_seq->sequence);
109 call_seq->sequence = NULL;
110 call_seq->count = call_seq->size = 0;
113 static inline void flush_sequences(struct call_sequence **seq, int n)
115 int i;
116 for (i = 0; i < n; i++)
117 flush_sequence(seq, i);
120 static void init_call_sequences(struct call_sequence **seq, int n)
122 int i;
124 for (i = 0; i < n; i++)
125 seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct call_sequence));
128 static void test_uint(UINT32 actual, UINT32 expected, const char *name, const struct testcontext *ctxt)
130 if (expected != actual && ctxt->todo)
132 (*ctxt->failcount)++;
133 ok_(ctxt->file, ctxt->line) (0, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name, expected, actual);
135 else
136 ok_(ctxt->file, ctxt->line) (expected == actual, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name,
137 expected, actual);
140 static void ok_sequence_(struct call_sequence **seq, int sequence_index,
141 const struct call_entry *expected, const char *context, BOOL todo,
142 const char *file, int line)
144 struct call_sequence *call_seq = seq[sequence_index];
145 static const struct call_entry end_of_sequence = { LastKind };
146 const struct call_entry *actual, *sequence;
147 int failcount = 0;
148 struct testcontext ctxt;
150 add_call(seq, sequence_index, &end_of_sequence);
152 sequence = call_seq->sequence;
153 actual = sequence;
155 ctxt.failcount = &failcount;
156 ctxt.todo = todo;
157 ctxt.file = file;
158 ctxt.line = line;
160 while (expected->kind != LastKind && actual->kind != LastKind)
162 if (expected->kind == actual->kind)
164 ctxt.kind = expected->kind;
166 switch (actual->kind)
168 case ScriptAnalysis:
170 const struct script_analysis *sa_act = &actual->sa;
171 const struct script_analysis *sa_exp = &expected->sa;
173 test_uint(sa_act->pos, sa_exp->pos, "position", &ctxt);
174 test_uint(sa_act->len, sa_exp->len, "length", &ctxt);
175 test_uint(sa_act->shapes, sa_exp->shapes, "shapes", &ctxt);
177 break;
179 default:
180 ok(0, "%s: callback not handled, %s\n", context, get_analysis_kind_name(actual->kind));
182 expected++;
183 actual++;
185 else if (todo)
187 failcount++;
188 todo_wine
190 ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
191 context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
194 flush_sequence(seq, sequence_index);
195 return;
197 else
199 ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
200 context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
201 expected++;
202 actual++;
206 if (todo)
208 todo_wine
210 if (expected->kind != LastKind || actual->kind != LastKind)
212 failcount++;
213 ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
214 context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
218 else if (expected->kind != LastKind || actual->kind != LastKind)
220 ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
221 context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
224 if (todo && !failcount) /* succeeded yet marked todo */
226 todo_wine
228 ok_(file, line)(1, "%s: marked \"todo_wine\" but succeeds\n", context);
232 flush_sequence(seq, sequence_index);
235 #define ok_sequence(seq, index, exp, contx, todo) \
236 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
238 static HRESULT WINAPI analysissink_QueryInterface(IDWriteTextAnalysisSink *iface, REFIID riid, void **obj)
240 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown))
242 *obj = iface;
243 return S_OK;
246 *obj = NULL;
247 return E_NOINTERFACE;
250 static ULONG WINAPI analysissink_AddRef(IDWriteTextAnalysisSink *iface)
252 return 2;
255 static ULONG WINAPI analysissink_Release(IDWriteTextAnalysisSink *iface)
257 return 1;
260 static HRESULT WINAPI analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface,
261 UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
263 struct call_entry entry;
265 entry.kind = ScriptAnalysis;
266 entry.sa.pos = position;
267 entry.sa.len = length;
268 entry.sa.shapes = sa->shapes;
269 add_call(sequences, ANALYZER_ID, &entry);
270 return S_OK;
273 static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface,
274 UINT32 position,
275 UINT32 length,
276 DWRITE_LINE_BREAKPOINT const* breakpoints)
278 ok(0, "unexpected\n");
279 return E_NOTIMPL;
282 static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface,
283 UINT32 position,
284 UINT32 length,
285 UINT8 explicitLevel,
286 UINT8 resolvedLevel)
288 ok(0, "unexpected\n");
289 return E_NOTIMPL;
292 static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
293 UINT32 position,
294 UINT32 length,
295 IDWriteNumberSubstitution* substitution)
297 ok(0, "unexpected\n");
298 return E_NOTIMPL;
301 static IDWriteTextAnalysisSinkVtbl analysissinkvtbl = {
302 analysissink_QueryInterface,
303 analysissink_AddRef,
304 analysissink_Release,
305 analysissink_SetScriptAnalysis,
306 analysissink_SetLineBreakpoints,
307 analysissink_SetBidiLevel,
308 analysissink_SetNumberSubstitution
311 static IDWriteTextAnalysisSink analysissink = { &analysissinkvtbl };
313 static HRESULT WINAPI analysissource_QueryInterface(IDWriteTextAnalysisSource *iface,
314 REFIID riid, void **obj)
316 ok(0, "QueryInterface not expected\n");
317 return E_NOTIMPL;
320 static ULONG WINAPI analysissource_AddRef(IDWriteTextAnalysisSource *iface)
322 ok(0, "AddRef not expected\n");
323 return 2;
326 static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
328 ok(0, "Release not expected\n");
329 return 1;
332 static const WCHAR *g_source;
334 static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
335 UINT32 position, WCHAR const** text, UINT32* text_len)
337 if (position >= lstrlenW(g_source))
339 *text = NULL;
340 *text_len = 0;
342 else
344 *text = &g_source[position];
345 *text_len = lstrlenW(g_source) - position;
348 return S_OK;
351 static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource *iface,
352 UINT32 position, WCHAR const** text, UINT32* text_len)
354 ok(0, "unexpected\n");
355 return E_NOTIMPL;
358 static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(
359 IDWriteTextAnalysisSource *iface)
361 ok(0, "unexpected\n");
362 return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
365 static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface,
366 UINT32 position, UINT32* text_len, WCHAR const** locale)
368 *locale = NULL;
369 *text_len = 0;
370 return S_OK;
373 static HRESULT WINAPI analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource *iface,
374 UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
376 ok(0, "unexpected\n");
377 return E_NOTIMPL;
380 static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
381 analysissource_QueryInterface,
382 analysissource_AddRef,
383 analysissource_Release,
384 analysissource_GetTextAtPosition,
385 analysissource_GetTextBeforePosition,
386 analysissource_GetParagraphReadingDirection,
387 analysissource_GetLocaleName,
388 analysissource_GetNumberSubstitution
391 static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl };
393 struct sa_test {
394 const WCHAR string[50];
395 int item_count;
396 struct script_analysis sa[10];
399 static struct sa_test sa_tests[] = {
401 /* just 1 char string */
402 {'t',0}, 1,
403 { { 0, 1, DWRITE_SCRIPT_SHAPES_DEFAULT }}
406 {'t','e','s','t',0}, 1,
407 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
410 {' ',' ',' ',' ','!','$','[','^','{','~',0}, 1,
411 { { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
414 {' ',' ',' ','1','2',' ',0}, 1,
415 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
418 /* digits only */
419 {'1','2',0}, 1,
420 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
423 /* Arabic */
424 {0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,0}, 1,
425 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
428 /* Arabic */
429 {0x0627,0x0644,0x0635,0x0651,0x0650,0x062d,0x0629,0x064f,' ',0x062a,0x064e,
430 0x0627,0x062c,0x064c,' ',0x0639,0x064e,0x0644,0x0649,' ',
431 0x0631,0x064f,0x0624,0x0648,0x0633,0x0650,' ',0x0627,0x0644,
432 0x0623,0x0635,0x0650,0x062d,0x0651,0x064e,0x0627,0x0621,0x0650,0x06f0,0x06f5,0}, 1,
433 { { 0, 40, DWRITE_SCRIPT_SHAPES_DEFAULT }}
436 /* Arabic, Latin */
437 {'1','2','3','-','5','2',0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,'7','1','.',0}, 1,
438 { { 0, 16, DWRITE_SCRIPT_SHAPES_DEFAULT }}
441 /* Arabic, English */
442 {'A','B','C','-','D','E','F',' ',0x0621,0x0623,0x0624,0}, 2,
443 { { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT },
444 { 8, 3, DWRITE_SCRIPT_SHAPES_DEFAULT },
448 /* leading space, Arabic, English */
449 {' ',0x0621,0x0623,0x0624,'A','B','C','-','D','E','F',0}, 2,
450 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
451 { 4, 7, DWRITE_SCRIPT_SHAPES_DEFAULT },
455 /* English, Arabic, trailing space */
456 {'A','B','C','-','D','E','F',0x0621,0x0623,0x0624,' ',0}, 2,
457 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT },
458 { 7, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
462 /* C1 Controls, Latin-1 Supplement */
463 {0x80,0x90,0x9f,0xa0,0xc0,0xb8,0xbf,0xc0,0xff,0}, 2,
464 { { 0, 3, DWRITE_SCRIPT_SHAPES_NO_VISUAL },
465 { 3, 6, DWRITE_SCRIPT_SHAPES_DEFAULT },
469 /* Latin Extended-A */
470 {0x100,0x120,0x130,0x140,0x150,0x160,0x170,0x17f,0}, 1,
471 { { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
474 /* Latin Extended-B */
475 {0x180,0x190,0x1bf,0x1c0,0x1c3,0x1c4,0x1cc,0x1dc,0x1ff,0x217,0x21b,0x24f,0}, 1,
476 { { 0, 12, DWRITE_SCRIPT_SHAPES_DEFAULT }}
479 /* IPA Extensions */
480 {0x250,0x260,0x270,0x290,0x2af,0}, 1,
481 { { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
484 /* Spacing Modifier Letters */
485 {0x2b0,0x2ba,0x2d7,0x2dd,0x2ef,0x2ff,0}, 1,
486 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
489 /* Combining Diacritical Marks */
490 {0x300,0x320,0x340,0x345,0x350,0x36f,0}, 1,
491 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
494 /* Greek and Coptic */
495 {0x370,0x388,0x3d8,0x3e1,0x3e2,0x3fa,0x3ff,0}, 3,
496 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
497 { 4, 1, DWRITE_SCRIPT_SHAPES_DEFAULT },
498 { 5, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }
502 /* Cyrillic and Cyrillic Supplement */
503 {0x400,0x40f,0x410,0x44f,0x450,0x45f,0x460,0x481,0x48a,0x4f0,0x4fa,0x4ff,0x500,0x510,0x520,0}, 1,
504 { { 0, 15, DWRITE_SCRIPT_SHAPES_DEFAULT }}
507 /* Armenian */
508 {0x531,0x540,0x559,0x55f,0x570,0x589,0x58a,0}, 1,
509 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
512 /* Hebrew */
513 {0x5e9,0x5dc,0x5d5,0x5dd,0}, 1,
514 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
517 /* Latin, Hebrew, Latin */
518 {'p','a','r','t',' ','o','n','e',' ',0x5d7,0x5dc,0x5e7,' ',0x5e9,0x5ea,0x5d9,0x5d9,0x5dd,' ','p','a','r','t',' ','t','h','r','e','e',0}, 3,
519 { { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT },
520 { 9, 10, DWRITE_SCRIPT_SHAPES_DEFAULT },
521 { 19, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
524 /* Syriac */
525 {0x710,0x712,0x712,0x714,'.',0}, 1,
526 { { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
529 /* Arabic Supplement */
530 {0x750,0x760,0x76d,'.',0}, 1,
531 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
534 /* Thaana */
535 {0x780,0x78e,0x798,0x7a6,0x7b0,'.',0}, 1,
536 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
539 /* N'Ko */
540 {0x7c0,0x7ca,0x7e8,0x7eb,0x7f6,'.',0}, 1,
541 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
544 /* Thaana */
545 {0x780,0x798,0x7a5,0x7a6,0x7b0,'.',0}, 1,
546 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
549 /* Devanagari */
550 {0x926,0x947,0x935,0x928,0x93e,0x917,0x930,0x940,'.',0}, 1,
551 { { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT }}
554 /* Bengali */
555 {0x9ac,0x9be,0x982,0x9b2,0x9be,'.',0}, 1,
556 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
559 /* Gurmukhi */
560 {0xa17,0xa41,0xa30,0xa2e,0xa41,0xa16,0xa40,'.',0}, 1,
561 { { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
564 /* Gujarati */
565 {0xa97,0xac1,0xa9c,0xab0,0xabe,0xaa4,0xac0,'.',0}, 1,
566 { { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
569 /* Oriya */
570 {0xb13,0xb21,0xb3c,0xb3f,0xb06,'.',0}, 1,
571 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
574 /* Tamil */
575 {0xba4,0xbae,0xbbf,0xbb4,0xbcd,'.',0}, 1,
576 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
579 /* Telugu */
580 {0xc24,0xc46,0xc32,0xc41,0xc17,0xc41,'.',0}, 1,
581 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
584 /* Kannada */
585 {0xc95,0xca8,0xccd,0xca8,0xca1,'.',0}, 1,
586 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
589 /* Malayalam */
590 {0xd2e,0xd32,0xd2f,0xd3e,0xd33,0xd02,'.',0}, 1,
591 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
594 /* Sinhala */
595 {0xd82,0xd85,0xd9a,0xdcf,'.',0}, 1,
596 { { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
599 /* Thai */
600 {0x0e04,0x0e27,0x0e32,0x0e21,0x0e1e,0x0e22,0x0e32,0x0e22,0x0e32,0x0e21,
601 0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e44,0x0e2b,0x0e19,
602 0x0e04,0x0e27,0x0e32,0x0e21,0x0e2a, 0x0e33,0x0e40,0x0e23,0x0e47,0x0e08,
603 0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e19,0x0e31,0x0e48,0x0e19,'.',0}, 1,
604 { { 0, 42, DWRITE_SCRIPT_SHAPES_DEFAULT }}
607 /* Lao */
608 {0xead,0xeb1,0xe81,0xeaa,0xead,0xe99,0xea5,0xeb2,0xea7,'.',0}, 1,
609 { { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
612 /* Tibetan */
613 {0xf04,0xf05,0xf0e,0x020,0xf51,0xf7c,0xf53,0xf0b,0xf5a,0xf53,0xf0b,
614 0xf51,0xf44,0xf0b,0xf54,0xf7c,0xf0d,'.',0}, 1,
615 { { 0, 18, DWRITE_SCRIPT_SHAPES_DEFAULT }}
618 /* Myanmar */
619 {0x1019,0x103c,0x1014,0x103a,0x1019,0x102c,0x1021,0x1000,0x1039,0x1001,0x101b,0x102c,'.',0}, 1,
620 { { 0, 13, DWRITE_SCRIPT_SHAPES_DEFAULT }}
623 /* Georgian */
624 {0x10a0,0x10d0,0x10da,0x10f1,0x10fb,0x2d00,'.',0}, 1,
625 { { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
628 /* Hangul */
629 {0x1100,0x1110,0x1160,0x1170,0x11a8,'.',0}, 1,
630 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
633 /* Ethiopic */
634 {0x130d,0x12d5,0x12dd,0}, 1,
635 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
638 /* Cherokee */
639 {0x13e3,0x13b3,0x13a9,0x0020,0x13a6,0x13ec,0x13c2,0x13af,0x13cd,0x13d7,0}, 1,
640 { { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
643 /* Canadian */
644 {0x1403,0x14c4,0x1483,0x144e,0x1450,0x1466,0}, 1,
645 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
648 /* Ogham */
649 {0x169b,0x1691,0x168c,0x1690,0x168b,0x169c,0}, 1,
650 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
653 /* Runic */
654 {0x16a0,0x16a1,0x16a2,0x16a3,0x16a4,0x16a5,0}, 1,
655 { { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
658 /* Khmer */
659 {0x1781,0x17c1,0x1798,0x179a,0x1797,0x17b6,0x179f,0x17b6,0x19e0,0}, 1,
660 { { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT }}
663 /* Mongolian */
664 {0x182e,0x1823,0x1829,0x182d,0x1823,0x182f,0x0020,0x182a,0x1822,0x1834,0x1822,0x182d,0x180c,0}, 1,
665 { { 0, 13, DWRITE_SCRIPT_SHAPES_DEFAULT }}
668 /* Limbu */
669 {0x1900,0x1910,0x1920,0x1930,0}, 1,
670 { { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
673 /* Tai Le */
674 {0x1956,0x196d,0x1970,0x1956,0x196c,0x1973,0x1951,0x1968,0x1952,0x1970,0}, 1,
675 { { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
678 /* New Tai Lue */
679 {0x1992,0x19c4,0}, 1,
680 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
683 /* Buginese */
684 {0x1a00,0x1a10,0}, 1,
685 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
688 /* Tai Tham */
689 {0x1a20,0x1a40,0x1a50,0}, 1,
690 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
693 /* Balinese */
694 {0x1b00,0x1b05,0x1b20,0}, 1,
695 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
698 /* Sundanese */
699 {0x1b80,0x1b85,0x1ba0,0}, 1,
700 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
703 /* Batak */
704 {0x1bc0,0x1be5,0x1bfc,0}, 1,
705 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
708 /* Lepcha */
709 {0x1c00,0x1c20,0x1c40,0}, 1,
710 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
713 /* Ol Chiki */
714 {0x1c50,0x1c5a,0x1c77,0}, 1,
715 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
718 /* Sundanese Supplement */
719 {0x1cc0,0x1cc5,0x1cc7,0}, 1,
720 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
723 /* Phonetic Extensions */
724 {0x1d00,0x1d40,0x1d70,0}, 1,
725 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
728 /* Combining diacritical marks */
729 {0x1dc0,0x300,0x1ddf,0}, 1,
730 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
733 /* Latin Extended Additional, Extended-C */
734 {0x1e00,0x1d00,0x2c60,0}, 1,
735 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
738 /* Greek Extended */
739 {0x3f0,0x1f00,0}, 1,
740 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
743 /* General Punctuation */
744 {0x1dc0,0x2000,0}, 1,
745 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
748 /* Superscripts and Subscripts */
749 {0x2070,0x2086,0x2000,0}, 1,
750 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
753 /* Currency, Combining Diacritical Marks for Symbols. Letterlike Symbols.. */
754 {0x20a0,0x20b8,0x2000,0x20d0,0x2100,0x2150,0x2190,0x2200,0x2300,0x2400,0x2440,0x2460,0x2500,0x2580,0x25a0,0x2600,
755 0x2700,0x27c0,0x27f0,0x2900,0x2980,0x2a00,0x2b00,0}, 1,
756 { { 0, 23, DWRITE_SCRIPT_SHAPES_DEFAULT }}
759 /* Braille */
760 {0x2800,0x2070,0x2000,0}, 1,
761 { { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
764 /* Glagolitic */
765 {0x2c00,0x2c12,0}, 1,
766 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
769 /* Coptic */
770 {0x2c80,0x3e2,0x1f00,0}, 2,
771 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT },
772 { 2, 1, DWRITE_SCRIPT_SHAPES_DEFAULT } }
775 /* Tifinagh */
776 {0x2d30,0x2d4a,0}, 1,
777 { { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
779 /* keep this as end marker */
780 { {0} }
783 static void init_expected_sa(struct call_sequence **seq, const struct sa_test *test)
785 static const struct call_entry end_of_sequence = { LastKind };
786 int i;
788 flush_sequence(seq, 0);
790 /* add expected calls */
791 for (i = 0; i < test->item_count; i++)
793 struct call_entry call;
795 call.kind = ScriptAnalysis;
796 call.sa = test->sa[i];
797 add_call(seq, 0, &call);
800 /* and stop marker */
801 add_call(seq, 0, &end_of_sequence);
804 static void test_AnalyzeScript(void)
806 const struct sa_test *ptr = sa_tests;
807 IDWriteTextAnalyzer *analyzer;
808 HRESULT hr;
810 hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
811 ok(hr == S_OK, "got 0x%08x\n", hr);
813 while (*ptr->string)
815 g_source = ptr->string;
817 init_expected_sa(expected_seq, ptr);
818 hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, lstrlenW(g_source), &analysissink);
819 ok(hr == S_OK, "got 0x%08x\n", hr);
820 ok_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, wine_dbgstr_w(ptr->string), FALSE);
821 ptr++;
824 IDWriteTextAnalyzer_Release(analyzer);
827 START_TEST(analyzer)
829 HRESULT hr;
831 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
832 ok(hr == S_OK, "got 0x%08x\n", hr);
833 if (hr != S_OK)
835 win_skip("failed to create factory\n");
836 return;
839 init_call_sequences(sequences, NUM_CALL_SEQUENCES);
840 init_call_sequences(expected_seq, 1);
842 test_AnalyzeScript();
844 IDWriteFactory_Release(factory);