blob: d9daa033fc43f319f0bae937eab8093ac34fe251 [file] [log] [blame]
/*
* Text analyzing tests
*
* Copyright 2012 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <assert.h>
#include "initguid.h"
#include "windows.h"
#include "dwrite.h"
#include "wine/test.h"
static IDWriteFactory *factory;
enum analysis_kind {
ScriptAnalysis,
LastKind
};
static const char *get_analysis_kind_name(enum analysis_kind kind)
{
switch (kind)
{
case ScriptAnalysis:
return "ScriptAnalysis";
default:
return "unknown";
}
}
struct script_analysis {
UINT32 pos;
UINT32 len;
DWRITE_SCRIPT_SHAPES shapes;
};
struct call_entry {
enum analysis_kind kind;
struct script_analysis sa;
};
struct testcontext {
enum analysis_kind kind;
int todo;
int *failcount;
const char *file;
int line;
};
struct call_sequence
{
int count;
int size;
struct call_entry *sequence;
};
#define NUM_CALL_SEQUENCES 1
#define ANALYZER_ID 0
static struct call_sequence *sequences[NUM_CALL_SEQUENCES];
static struct call_sequence *expected_seq[1];
static void add_call(struct call_sequence **seq, int sequence_index, const struct call_entry *call)
{
struct call_sequence *call_seq = seq[sequence_index];
if (!call_seq->sequence)
{
call_seq->size = 10;
call_seq->sequence = HeapAlloc(GetProcessHeap(), 0,
call_seq->size * sizeof (struct call_entry));
}
if (call_seq->count == call_seq->size)
{
call_seq->size *= 2;
call_seq->sequence = HeapReAlloc(GetProcessHeap(), 0,
call_seq->sequence,
call_seq->size * sizeof (struct call_entry));
}
assert(call_seq->sequence);
call_seq->sequence[call_seq->count++] = *call;
}
static inline void flush_sequence(struct call_sequence **seg, int sequence_index)
{
struct call_sequence *call_seq = seg[sequence_index];
HeapFree(GetProcessHeap(), 0, call_seq->sequence);
call_seq->sequence = NULL;
call_seq->count = call_seq->size = 0;
}
static inline void flush_sequences(struct call_sequence **seq, int n)
{
int i;
for (i = 0; i < n; i++)
flush_sequence(seq, i);
}
static void init_call_sequences(struct call_sequence **seq, int n)
{
int i;
for (i = 0; i < n; i++)
seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct call_sequence));
}
static void test_uint(UINT32 actual, UINT32 expected, const char *name, const struct testcontext *ctxt)
{
if (expected != actual && ctxt->todo)
{
(*ctxt->failcount)++;
ok_(ctxt->file, ctxt->line) (0, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name, expected, actual);
}
else
ok_(ctxt->file, ctxt->line) (expected == actual, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name,
expected, actual);
}
static void ok_sequence_(struct call_sequence **seq, int sequence_index,
const struct call_entry *expected, const char *context, int todo,
const char *file, int line)
{
struct call_sequence *call_seq = seq[sequence_index];
static const struct call_entry end_of_sequence = { LastKind };
const struct call_entry *actual, *sequence;
int failcount = 0;
struct testcontext ctxt;
add_call(seq, sequence_index, &end_of_sequence);
sequence = call_seq->sequence;
actual = sequence;
ctxt.failcount = &failcount;
ctxt.todo = todo;
ctxt.file = file;
ctxt.line = line;
while (expected->kind != LastKind && actual->kind != LastKind)
{
if (expected->kind == actual->kind)
{
ctxt.kind = expected->kind;
switch (actual->kind)
{
case ScriptAnalysis:
{
const struct script_analysis *sa_act = &actual->sa;
const struct script_analysis *sa_exp = &expected->sa;
test_uint(sa_act->pos, sa_exp->pos, "position", &ctxt);
test_uint(sa_act->len, sa_exp->len, "length", &ctxt);
test_uint(sa_act->shapes, sa_exp->shapes, "shapes", &ctxt);
break;
}
default:
ok(0, "%s: callback not handled, %s\n", context, get_analysis_kind_name(actual->kind));
}
expected++;
actual++;
}
else if (todo)
{
failcount++;
todo_wine
{
ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
}
flush_sequence(seq, sequence_index);
return;
}
else
{
ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
expected++;
actual++;
}
}
if (todo)
{
todo_wine
{
if (expected->kind != LastKind || actual->kind != LastKind)
{
failcount++;
ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
}
}
}
else if (expected->kind != LastKind || actual->kind != LastKind)
{
ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
}
if (todo && !failcount) /* succeeded yet marked todo */
{
todo_wine
{
ok_(file, line)(1, "%s: marked \"todo_wine\" but succeeds\n", context);
}
}
flush_sequence(seq, sequence_index);
}
#define ok_sequence(seq, index, exp, contx, todo) \
ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
static HRESULT WINAPI analysissink_QueryInterface(IDWriteTextAnalysisSink *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
return S_OK;
}
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI analysissink_AddRef(IDWriteTextAnalysisSink *iface)
{
return 2;
}
static ULONG WINAPI analysissink_Release(IDWriteTextAnalysisSink *iface)
{
return 1;
}
static HRESULT WINAPI analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface,
UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
{
struct call_entry entry;
entry.kind = ScriptAnalysis;
entry.sa.pos = position;
entry.sa.len = length;
entry.sa.shapes = sa->shapes;
add_call(sequences, ANALYZER_ID, &entry);
return S_OK;
}
static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface,
UINT32 position,
UINT32 length,
DWRITE_LINE_BREAKPOINT const* breakpoints)
{
ok(0, "unexpected\n");
return E_NOTIMPL;
}
static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface,
UINT32 position,
UINT32 length,
UINT8 explicitLevel,
UINT8 resolvedLevel)
{
ok(0, "unexpected\n");
return E_NOTIMPL;
}
static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
UINT32 position,
UINT32 length,
IDWriteNumberSubstitution* substitution)
{
ok(0, "unexpected\n");
return E_NOTIMPL;
}
static IDWriteTextAnalysisSinkVtbl analysissinkvtbl = {
analysissink_QueryInterface,
analysissink_AddRef,
analysissink_Release,
analysissink_SetScriptAnalysis,
analysissink_SetLineBreakpoints,
analysissink_SetBidiLevel,
analysissink_SetNumberSubstitution
};
static IDWriteTextAnalysisSink analysissink = { &analysissinkvtbl };
static HRESULT WINAPI analysissource_QueryInterface(IDWriteTextAnalysisSource *iface,
REFIID riid, void **obj)
{
ok(0, "QueryInterface not expected\n");
return E_NOTIMPL;
}
static ULONG WINAPI analysissource_AddRef(IDWriteTextAnalysisSource *iface)
{
ok(0, "AddRef not expected\n");
return 2;
}
static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
{
ok(0, "Release not expected\n");
return 1;
}
static const WCHAR *g_source;
static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
UINT32 position, WCHAR const** text, UINT32* text_len)
{
if (position >= lstrlenW(g_source))
{
*text = NULL;
*text_len = 0;
}
else
{
*text = &g_source[position];
*text_len = lstrlenW(g_source) - position;
}
return S_OK;
}
static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource *iface,
UINT32 position, WCHAR const** text, UINT32* text_len)
{
ok(0, "unexpected\n");
return E_NOTIMPL;
}
static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(
IDWriteTextAnalysisSource *iface)
{
ok(0, "unexpected\n");
return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
}
static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface,
UINT32 position, UINT32* text_len, WCHAR const** locale)
{
*locale = NULL;
*text_len = 0;
return S_OK;
}
static HRESULT WINAPI analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource *iface,
UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
{
ok(0, "unexpected\n");
return E_NOTIMPL;
}
static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
analysissource_QueryInterface,
analysissource_AddRef,
analysissource_Release,
analysissource_GetTextAtPosition,
analysissource_GetTextBeforePosition,
analysissource_GetParagraphReadingDirection,
analysissource_GetLocaleName,
analysissource_GetNumberSubstitution
};
static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl };
struct sa_test {
const WCHAR string[50];
int item_count;
struct script_analysis sa[10];
};
static struct sa_test sa_tests[] = {
{
/* just 1 char string */
{'t',0}, 1,
{ { 0, 1, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
{'t','e','s','t',0}, 1,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
{' ',' ',' ',' ','!','$','[','^','{','~',0}, 1,
{ { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
{' ',' ',' ','1','2',' ',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* digits only */
{'1','2',0}, 1,
{ { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Arabic */
{0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,0}, 1,
{ { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Arabic */
{0x0627,0x0644,0x0635,0x0651,0x0650,0x062d,0x0629,0x064f,' ',0x062a,0x064e,
0x0627,0x062c,0x064c,' ',0x0639,0x064e,0x0644,0x0649,' ',
0x0631,0x064f,0x0624,0x0648,0x0633,0x0650,' ',0x0627,0x0644,
0x0623,0x0635,0x0650,0x062d,0x0651,0x064e,0x0627,0x0621,0x0650,0x06f0,0x06f5,0}, 1,
{ { 0, 40, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Arabic, Latin */
{'1','2','3','-','5','2',0x064a,0x064f,0x0633,0x0627,0x0648,0x0650,0x064a,'7','1','.',0}, 1,
{ { 0, 16, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Arabic, English */
{'A','B','C','-','D','E','F',' ',0x0621,0x0623,0x0624,0}, 2,
{ { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 8, 3, DWRITE_SCRIPT_SHAPES_DEFAULT },
}
},
{
/* leading space, Arabic, English */
{' ',0x0621,0x0623,0x0624,'A','B','C','-','D','E','F',0}, 2,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 4, 7, DWRITE_SCRIPT_SHAPES_DEFAULT },
}
},
{
/* English, Arabic, trailing space */
{'A','B','C','-','D','E','F',0x0621,0x0623,0x0624,' ',0}, 2,
{ { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 7, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
}
},
{
/* C1 Controls, Latin-1 Supplement */
{0x80,0x90,0x9f,0xa0,0xc0,0xb8,0xbf,0xc0,0xff,0}, 2,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_NO_VISUAL },
{ 3, 6, DWRITE_SCRIPT_SHAPES_DEFAULT },
}
},
{
/* Latin Extended-A */
{0x100,0x120,0x130,0x140,0x150,0x160,0x170,0x17f,0}, 1,
{ { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Latin Extended-B */
{0x180,0x190,0x1bf,0x1c0,0x1c3,0x1c4,0x1cc,0x1dc,0x1ff,0x217,0x21b,0x24f,0}, 1,
{ { 0, 12, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* IPA Extensions */
{0x250,0x260,0x270,0x290,0x2af,0}, 1,
{ { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Spacing Modifier Letters */
{0x2b0,0x2ba,0x2d7,0x2dd,0x2ef,0x2ff,0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Combining Diacritical Marks */
{0x300,0x320,0x340,0x345,0x350,0x36f,0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Greek and Coptic */
{0x370,0x388,0x3d8,0x3e1,0x3e2,0x3fa,0x3ff,0}, 3,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 4, 1, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 5, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }
}
},
{
/* Cyrillic and Cyrillic Supplement */
{0x400,0x40f,0x410,0x44f,0x450,0x45f,0x460,0x481,0x48a,0x4f0,0x4fa,0x4ff,0x500,0x510,0x520,0}, 1,
{ { 0, 15, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Armenian */
{0x531,0x540,0x559,0x55f,0x570,0x589,0x58a,0}, 1,
{ { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Hebrew */
{0x5e9,0x5dc,0x5d5,0x5dd,0}, 1,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Latin, Hebrew, Latin */
{'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,
{ { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 9, 10, DWRITE_SCRIPT_SHAPES_DEFAULT },
{ 19, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Syriac */
{0x710,0x712,0x712,0x714,'.',0}, 1,
{ { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Arabic Supplement */
{0x750,0x760,0x76d,'.',0}, 1,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Thaana */
{0x780,0x78e,0x798,0x7a6,0x7b0,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* N'Ko */
{0x7c0,0x7ca,0x7e8,0x7eb,0x7f6,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Thaana */
{0x780,0x798,0x7a5,0x7a6,0x7b0,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Devanagari */
{0x926,0x947,0x935,0x928,0x93e,0x917,0x930,0x940,'.',0}, 1,
{ { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Bengali */
{0x9ac,0x9be,0x982,0x9b2,0x9be,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Gurmukhi */
{0xa17,0xa41,0xa30,0xa2e,0xa41,0xa16,0xa40,'.',0}, 1,
{ { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Gujarati */
{0xa97,0xac1,0xa9c,0xab0,0xabe,0xaa4,0xac0,'.',0}, 1,
{ { 0, 8, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Oriya */
{0xb13,0xb21,0xb3c,0xb3f,0xb06,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Tamil */
{0xba4,0xbae,0xbbf,0xbb4,0xbcd,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Telugu */
{0xc24,0xc46,0xc32,0xc41,0xc17,0xc41,'.',0}, 1,
{ { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Kannada */
{0xc95,0xca8,0xccd,0xca8,0xca1,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Malayalam */
{0xd2e,0xd32,0xd2f,0xd3e,0xd33,0xd02,'.',0}, 1,
{ { 0, 7, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Sinhala */
{0xd82,0xd85,0xd9a,0xdcf,'.',0}, 1,
{ { 0, 5, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Thai */
{0x0e04,0x0e27,0x0e32,0x0e21,0x0e1e,0x0e22,0x0e32,0x0e22,0x0e32,0x0e21,
0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e44,0x0e2b,0x0e19,
0x0e04,0x0e27,0x0e32,0x0e21,0x0e2a, 0x0e33,0x0e40,0x0e23,0x0e47,0x0e08,
0x0e2d,0x0e22,0x0e39,0x0e48,0x0e17,0x0e35,0x0e48,0x0e19,0x0e31,0x0e48,0x0e19,'.',0}, 1,
{ { 0, 42, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Lao */
{0xead,0xeb1,0xe81,0xeaa,0xead,0xe99,0xea5,0xeb2,0xea7,'.',0}, 1,
{ { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Tibetan */
{0xf04,0xf05,0xf0e,0x020,0xf51,0xf7c,0xf53,0xf0b,0xf5a,0xf53,0xf0b,
0xf51,0xf44,0xf0b,0xf54,0xf7c,0xf0d,'.',0}, 1,
{ { 0, 18, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Myanmar */
{0x1019,0x103c,0x1014,0x103a,0x1019,0x102c,0x1021,0x1000,0x1039,0x1001,0x101b,0x102c,'.',0}, 1,
{ { 0, 13, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Georgian */
{0x10a0,0x10d0,0x10da,0x10f1,0x10fb,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Hangul */
{0x1100,0x1110,0x1160,0x1170,0x11a8,'.',0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Ethiopic */
{0x130d,0x12d5,0x12dd,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Cherokee */
{0x13e3,0x13b3,0x13a9,0x0020,0x13a6,0x13ec,0x13c2,0x13af,0x13cd,0x13d7,0}, 1,
{ { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Canadian */
{0x1403,0x14c4,0x1483,0x144e,0x1450,0x1466,0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Ogham */
{0x169b,0x1691,0x168c,0x1690,0x168b,0x169c,0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Runic */
{0x16a0,0x16a1,0x16a2,0x16a3,0x16a4,0x16a5,0}, 1,
{ { 0, 6, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Khmer */
{0x1781,0x17c1,0x1798,0x179a,0x1797,0x17b6,0x179f,0x17b6,0x19e0,0}, 1,
{ { 0, 9, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Mongolian */
{0x182e,0x1823,0x1829,0x182d,0x1823,0x182f,0x0020,0x182a,0x1822,0x1834,0x1822,0x182d,0x180c,0}, 1,
{ { 0, 13, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Limbu */
{0x1900,0x1910,0x1920,0x1930,0}, 1,
{ { 0, 4, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Tai Le */
{0x1956,0x196d,0x1970,0x1956,0x196c,0x1973,0x1951,0x1968,0x1952,0x1970,0}, 1,
{ { 0, 10, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* New Tai Lue */
{0x1992,0x19c4,0}, 1,
{ { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Buginese */
{0x1a00,0x1a10,0}, 1,
{ { 0, 2, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Tai Tham */
{0x1a20,0x1a40,0x1a50,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Balinese */
{0x1b00,0x1b05,0x1b20,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Sundanese */
{0x1b80,0x1b85,0x1ba0,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Batak */
{0x1bc0,0x1be5,0x1bfc,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Lepcha */
{0x1c00,0x1c20,0x1c40,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Ol Chiki */
{0x1c50,0x1c5a,0x1c77,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Sundanese Supplement */
{0x1cc0,0x1cc5,0x1cc8,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
{
/* Phonetic Extensions */
{0x1d00,0x1d40,0x1d70,0}, 1,
{ { 0, 3, DWRITE_SCRIPT_SHAPES_DEFAULT }}
},
/* keep this as end marker */
{ {0} }
};
static void init_expected_sa(struct call_sequence **seq, const struct sa_test *test)
{
static const struct call_entry end_of_sequence = { LastKind };
int i;
flush_sequence(seq, 0);
/* add expected calls */
for (i = 0; i < test->item_count; i++)
{
struct call_entry call;
call.kind = ScriptAnalysis;
call.sa = test->sa[i];
add_call(seq, 0, &call);
}
/* and stop marker */
add_call(seq, 0, &end_of_sequence);
}
static void test_AnalyzeScript(void)
{
const struct sa_test *ptr = sa_tests;
IDWriteTextAnalyzer *analyzer;
HRESULT hr;
hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
ok(hr == S_OK, "got 0x%08x\n", hr);
while (*ptr->string)
{
g_source = ptr->string;
init_expected_sa(expected_seq, ptr);
hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, lstrlenW(g_source), &analysissink);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, "AnalyzeScript", FALSE);
ptr++;
}
IDWriteTextAnalyzer_Release(analyzer);
}
START_TEST(analyzer)
{
HRESULT hr;
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr != S_OK)
{
win_skip("failed to create factory\n");
return;
}
init_call_sequences(sequences, NUM_CALL_SEQUENCES);
init_call_sequences(expected_seq, 1);
test_AnalyzeScript();
IDWriteFactory_Release(factory);
}