1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *******************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   Copyright (C) 1999-2008, International Business Machines
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   Corporation and others.  All Rights Reserved.
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *******************************************************************************
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   file name:  letest.cpp
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   created on: 11/06/2000
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *   created by: Eric R. Mader
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uclean.h"
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uchar.h"
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/unistr.h"
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uscript.h"
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/putil.h"
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ctest.h"
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "layout/LETypes.h"
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "layout/LEScripts.h"
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "layout/LayoutEngine.h"
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "layout/ParagraphLayout.h"
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "layout/RunArrays.h"
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "PortableFontInstance.h"
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "SimpleFontInstance.h"
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "letsutil.h"
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "letest.h"
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "xmlparser.h"
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "putilimp.h" // for uprv_getUTCtime()
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <stdlib.h>
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <string.h>
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_USE
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define CH_COMMA 0x002C
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV ScriptTest(void)
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if ((int)scriptCodeCount != (int)USCRIPT_CODE_LIMIT) {
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("ScriptCodes::scriptCodeCount = %d, but UScriptCode::USCRIPT_CODE_LIMIT = %d\n", scriptCodeCount, USCRIPT_CODE_LIMIT);
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV ParamTest(void)
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEErrorCode status = LE_NO_ERROR;
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    SimpleFontInstance *font = new SimpleFontInstance(12, status);
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LayoutEngine *engine = LayoutEngine::layoutEngineFactory(font, arabScriptCode, -1, status);
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEGlyphID *glyphs    = NULL;
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32  *indices   = NULL;
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    float     *positions = NULL;
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32   glyphCount = 0;
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->getGlyphCount();
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (glyphCount != 0) {
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphCount() on an empty layout returned %d.\n", glyphCount);
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphs    = NEW_ARRAY(LEGlyphID, glyphCount + 10);
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    indices   = NEW_ARRAY(le_int32, glyphCount + 10);
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    positions = NEW_ARRAY(float, glyphCount + 10);
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(NULL, status);
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphs(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(glyphs, status);
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_NO_LAYOUT_ERROR) {
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphs(glyphs, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(NULL, 0xFF000000L, status);
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphs(NULL, 0xFF000000L, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(glyphs, 0xFF000000L, status);
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_NO_LAYOUT_ERROR) {
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphs(glyphs, 0xFF000000L, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(NULL, status);
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getCharIndices(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(indices, status);
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_NO_LAYOUT_ERROR) {
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getCharIndices(indices, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(NULL, 1024, status);
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getCharIndices(NULL, 1024, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(indices, 1024, status);
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_NO_LAYOUT_ERROR) {
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getCharIndices(indices, 1024, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphPositions(NULL, status);
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphPositions(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphPositions(positions, status);
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_NO_LAYOUT_ERROR) {
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphPositions(positions, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    DELETE_ARRAY(positions);
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    DELETE_ARRAY(indices);
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    DELETE_ARRAY(glyphs);
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(NULL, 0, 0, 0, FALSE, 0.0, 0.0, status);
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars(NULL, 0, 0, 0, FALSE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEUnicode chars[] = {
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, // "English "
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634,                 // MEM ALIF KAF NOON TEH WAW SHEEN
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E                   // " text."
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    };
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, -1, 6, 20, TRUE, 0.0, 0.0, status);
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars(chars, -1, 6, 20, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, 8, -1, 20, TRUE, 0.0, 0.0, status);
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars(chars, 8, -1, 20, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, 8, 6, -1, TRUE, 0.0, 0.0, status);
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars((chars, 8, 6, -1, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, 8, 6, 10, TRUE, 0.0, 0.0, status);
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars(chars, 8, 6, 10, TRUE, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    float x = 0.0, y = 0.0;
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status);
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status) failed.\n");
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto bail;
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphPosition(-1, x, y, status);
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphPosition(-1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphPosition(glyphCount + 1, x, y, status);
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Calling getGlyphPosition(glyphCount + 1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)bail:
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete engine;
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete font;
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV FactoryTest(void)
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEErrorCode status = LE_NO_ERROR;
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    SimpleFontInstance *font = new SimpleFontInstance(12, status);
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LayoutEngine *engine = NULL;
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(le_int32 scriptCode = 0; scriptCode < scriptCodeCount; scriptCode += 1) {
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = LE_NO_ERROR;
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        engine = LayoutEngine::layoutEngineFactory(font, scriptCode, -1, status);
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (LE_FAILURE(status)) {
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("Could not create a LayoutEngine for script \'%s\'.\n", uscript_getShortName((UScriptCode)scriptCode));
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete engine;
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete font;
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV AccessTest(void)
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEErrorCode status = LE_NO_ERROR;
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    SimpleFontInstance *font = new SimpleFontInstance(12, status);
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LayoutEngine *engine = LayoutEngine::layoutEngineFactory(font, arabScriptCode, -1, status);
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 glyphCount;
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEGlyphID glyphs[6], extraBitGlyphs[6];;
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 biasedIndices[6], indices[6], glyph;
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    float positions[6 * 2 + 2];
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEUnicode chars[] = {
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, // "English "
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634,                 // MEM ALIF KAF NOON TEH WAW SHEEN
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E                   // " text."
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    };
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Could not create LayoutEngine.\n");
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto bail;
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    glyphCount = engine->layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status);
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status) || glyphCount != 6) {
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("layoutChars(chars, 8, 6, 20, TRUE, 0.0, 0.0, status) failed.\n");
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto bail;
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(glyphs, status);
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(indices, status);
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphPositions(positions, status);
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Could not get glyph, indices and position arrays.\n");
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto bail;
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getGlyphs(extraBitGlyphs, 0xFF000000L, status);
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("getGlyphs(extraBitGlyphs, 0xFF000000L, status); failed.\n");
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(glyph = 0; glyph < glyphCount; glyph += 1) {
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (extraBitGlyphs[glyph] != (glyphs[glyph] | 0xFF000000L)) {
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                log_err("extraBigGlyphs[%d] != glyphs[%d] | 0xFF000000L: %8X, %8X\n",
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    glyph, glyph, extraBitGlyphs[glyph], glyphs[glyph]);
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    engine->getCharIndices(biasedIndices, 1024, status);
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("getCharIndices(biasedIndices, 1024, status) failed.\n");
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (glyph = 0; glyph < glyphCount; glyph += 1) {
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (biasedIndices[glyph] != (indices[glyph] + 1024)) {
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                log_err("biasedIndices[%d] != indices[%d] + 1024: %8X, %8X\n",
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    glyph, glyph, biasedIndices[glyph], indices[glyph]);
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    status = LE_NO_ERROR;
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (glyph = 0; glyph <= glyphCount; glyph += 1) {
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        float x = 0.0, y = 0.0;
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        engine->getGlyphPosition(glyph, x, y, status);
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (LE_FAILURE(status)) {
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("getGlyphPosition(%d, x, y, status) failed.\n", glyph);
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (x != positions[glyph*2] || y != positions[glyph*2 + 1]) {
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("getGlyphPosition(%d, x, y, status) returned bad position: (%f, %f) != (%f, %f)\n",
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                glyph, x, y, positions[glyph*2], positions[glyph*2 + 1]);
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)bail:
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete engine;
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete font;
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)le_bool compareResults(const char *testID, TestResult *expected, TestResult *actual)
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* NOTE: we'll stop on the first failure 'cause once there's one error, it may cascade... */
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (actual->glyphCount != expected->glyphCount) {
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Test %s: incorrect glyph count: exptected %d, got %d\n",
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            testID, expected->glyphCount, actual->glyphCount);
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 i;
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (i = 0; i < actual->glyphCount; i += 1) {
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (actual->glyphs[i] != expected->glyphs[i]) {
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("Test %s: incorrect id for glyph %d: expected %4X, got %4X\n",
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                testID, i, expected->glyphs[i], actual->glyphs[i]);
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return FALSE;
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (i = 0; i < actual->glyphCount; i += 1) {
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (actual->indices[i] != expected->indices[i]) {
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("Test %s: incorrect index for glyph %d: expected %8X, got %8X\n",
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                testID, i, expected->indices[i], actual->indices[i]);
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return FALSE;
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (i = 0; i <= actual->glyphCount; i += 1) {
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        double xError = uprv_fabs(actual->positions[i * 2] - expected->positions[i * 2]);
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (xError > 0.0001) {
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("Test %s: incorrect x position for glyph %d: expected %f, got %f\n",
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                testID, i, expected->positions[i * 2], actual->positions[i * 2]);
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return FALSE;
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        double yError = uprv_fabs(actual->positions[i * 2 + 1] - expected->positions[i * 2 + 1]);
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (yError < 0) {
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            yError = -yError;
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (yError > 0.0001) {
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_err("Test %s: incorrect y position for glyph %d: expected %f, got %f\n",
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                testID, i, expected->positions[i * 2 + 1], actual->positions[i * 2 + 1]);
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return FALSE;
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return TRUE;
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void checkFontVersion(PortableFontInstance *fontInstance, const char *testVersionString,
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                             le_uint32 testChecksum, const char *testID)
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_uint32 fontChecksum = fontInstance->getFontChecksum();
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fontChecksum != testChecksum) {
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        const char *fontVersionString = fontInstance->getNameString(NAME_VERSION_STRING,
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        const LEUnicode *uFontVersionString = NULL;
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // The standard recommends that the Macintosh Roman/English name string be present, but
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // if it's not, try the Microsoft Unicode/English string.
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (fontVersionString == NULL) {
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uFontVersionString = fontInstance->getUnicodeNameString(NAME_VERSION_STRING,
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_info("Test %s: this may not be the same font used to generate the test data.\n", testID);
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (uFontVersionString != NULL) {
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_info("Your font's version string is \"%S\"\n", uFontVersionString);
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fontInstance->deleteNameString(uFontVersionString);
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            log_info("Your font's version string is \"%s\"\n", fontVersionString);
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fontInstance->deleteNameString(fontVersionString);
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_info("The expected version string is \"%s\"\n", testVersionString);
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_info("If you see errors, they may be due to the version of the font you're using.\n");
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Returns the path to icu/source/test/testdata/ */
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const char *getSourceTestData() {
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char *srcDataDir = NULL;
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef U_TOPSRCDIR
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (f != NULL) {
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* We're in icu/source/test/letest/ */
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fclose(f);
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* We're in icu/source/test/letest/(Debug|Release) */
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return srcDataDir;
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const char *getPath(char buffer[2048], const char *filename) {
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char *testDataDirectory = getSourceTestData();
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    strcpy(buffer, testDataDirectory);
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    strcat(buffer, filename);
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return buffer;
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize)
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t offset = -1;
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    arraySize = 1;
447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        arraySize += 1;
449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_uint32 *array = NEW_ARRAY(le_uint32, arraySize);
452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    char number[16];
453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 count = 0;
454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 start = 0, end = 0;
455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 len = 0;
456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // trim leading whitespace
458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(u_isUWhiteSpace(numbers[start])) {
459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        start += 1;
460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        number[len] = '\0';
465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        start = end + 1;
466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        sscanf(number, "%x", &array[count++]);
468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // trim whitespace following the comma
470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(u_isUWhiteSpace(numbers[start])) {
471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            start += 1;
472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // trim trailing whitespace
476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    end = numbers.length();
477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(u_isUWhiteSpace(numbers[end - 1])) {
478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        end -= 1;
479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    number[len] = '\0';
483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    sscanf(number, "%x", &array[count]);
484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return array;
486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize)
489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t offset = -1;
491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    arraySize = 1;
493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        arraySize += 1;
495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    float *array = NEW_ARRAY(float, arraySize);
498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    char number[32];
499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 count = 0;
500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 start = 0, end = 0;
501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 len = 0;
502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // trim leading whitespace
504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(u_isUWhiteSpace(numbers[start])) {
505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        start += 1;
506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        number[len] = '\0';
511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        start = end + 1;
512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        sscanf(number, "%f", &array[count++]);
514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // trim whiteapce following the comma
516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(u_isUWhiteSpace(numbers[start])) {
517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            start += 1;
518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(u_isUWhiteSpace(numbers[start])) {
522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        start += 1;
523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // trim trailing whitespace
526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    end = numbers.length();
527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(u_isUWhiteSpace(numbers[end - 1])) {
528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        end -= 1;
529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    number[len] = '\0';
533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    sscanf(number, "%f", &array[count]);
534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return array;
536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)LEFontInstance *openFont(const char *fontName, const char *checksum, const char *version, const char *testID)
539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    char path[2048];
541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    PortableFontInstance *font;
542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEErrorCode fontStatus = LE_NO_ERROR;
543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    font = new PortableFontInstance(getPath(path, fontName), 12, fontStatus);
546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(fontStatus)) {
548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_info("Test %s: can't open font %s - test skipped.\n", testID, fontName);
549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete font;
550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        le_uint32 cksum = 0;
553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        sscanf(checksum, "%x", &cksum);
555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        checkFontVersion(font, version, cksum, testID);
557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return font;
560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV DataDrivenTest(void)
564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_REGULAR_EXPRESSIONS
566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    char path[2048];
568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char *testFilePath = getPath(path, "letest.xml");
569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UXMLParser  *parser = UXMLParser::createParser(status);
571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UXMLElement *root   = parser->parseFile(testFilePath, status);
572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (root == NULL) {
574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        log_err("Could not open the test data file: %s\n", testFilePath);
575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete parser;
576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString result_glyphs    = UNICODE_STRING_SIMPLE("result-glyphs");
583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString result_indices   = UNICODE_STRING_SIMPLE("result-indices");
584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions");
585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // test-case attributes
587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString id_attr     = UNICODE_STRING_SIMPLE("id");
588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString lang_attr   = UNICODE_STRING_SIMPLE("lang");
590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // test-font attributes
592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString name_attr   = UNICODE_STRING_SIMPLE("name");
593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString ver_attr    = UNICODE_STRING_SIMPLE("version");
594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString cksum_attr  = UNICODE_STRING_SIMPLE("checksum");
595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UXMLElement *testCase;
597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t tc = 0;
598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while((testCase = root->nextChildElement(tc)) != NULL) {
600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (testCase->getTagName().compare(test_case) == 0) {
601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            char *id = getCString(testCase->getAttribute(id_attr));
602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            char *script = getCString(testCase->getAttribute(script_attr));
603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            char *lang   = getCString(testCase->getAttribute(lang_attr));
604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            LEFontInstance *font = NULL;
605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const UXMLElement *element;
606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t ec = 0;
607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t charCount = 0;
608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t typoFlags = 3; // kerning + ligatures...
609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UScriptCode scriptCode;
610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            le_int32 languageCode = -1;
611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UnicodeString text, glyphs, indices, positions;
612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t glyphCount = 0, indexCount = 0, positionCount = 0;
613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            TestResult expected = {0, NULL, NULL, NULL};
614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            TestResult actual   = {0, NULL, NULL, NULL};
615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            LEErrorCode success = LE_NO_ERROR;
616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            LayoutEngine *engine = NULL;
617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uscript_getCode(script, &scriptCode, 1, &status);
619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (LE_FAILURE(status)) {
620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                log_err("invalid script name: %s.\n", script);
621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto free_c_strings;
622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (lang != NULL) {
625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                languageCode = getLanguageCode(lang);
626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (languageCode < 0) {
628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    log_err("invalid language name: %s.\n", lang);
629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    goto free_c_strings;
630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            while((element = testCase->nextChildElement(ec)) != NULL) {
634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UnicodeString tag = element->getTagName();
635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // TODO: make sure that each element is only used once.
637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (tag.compare(test_font) == 0) {
638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    char *fontName  = getCString(element->getAttribute(name_attr));
639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    char *fontVer   = getCString(element->getAttribute(ver_attr));
640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    char *fontCksum = getCString(element->getAttribute(cksum_attr));
641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    font = openFont(fontName, fontCksum, fontVer, id);
643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    freeCString(fontCksum);
644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    freeCString(fontVer);
645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    freeCString(fontName);
646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (font == NULL) {
648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // warning message already displayed...
649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        goto free_c_strings;
650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (tag.compare(test_text) == 0) {
652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    text = element->getText(TRUE);
653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    charCount = text.length();
654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (tag.compare(result_glyphs) == 0) {
655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    glyphs = element->getText(TRUE);
656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (tag.compare(result_indices) == 0) {
657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    indices = element->getText(TRUE);
658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (tag.compare(result_positions) == 0) {
659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    positions = element->getText(TRUE);
660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else {
661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // an unknown tag...
662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    char *cTag = getCString(&tag);
663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag);
665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    freeCString(cTag);
666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // TODO: make sure that the font, test-text, result-glyphs, result-indices and result-positions
670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // have all been provided
671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (font == NULL) {
672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                LEErrorCode fontStatus = LE_NO_ERROR;
673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                font = new SimpleFontInstance(12, fontStatus);
675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                typoFlags |= 0x80000000L;  // use CharSubstitutionFilter...
676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            expected.glyphs    = (LEGlyphID *) getHexArray(glyphs, glyphCount);
679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            expected.indices   = (le_int32 *)  getHexArray(indices, indexCount);
680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            expected.positions = getFloatArray(positions, positionCount);
681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            expected.glyphCount = glyphCount;
683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    id, charCount, glyphCount, indexCount, positionCount);
687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto free_expected;
688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            };
689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            engine = LayoutEngine::layoutEngineFactory(font, scriptCode, languageCode, typoFlags, success);
691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (LE_FAILURE(success)) {
693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                log_err("Test %s: could not create a LayoutEngine.\n", id);
694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                goto free_expected;
695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            actual.glyphCount = engine->layoutChars(text.getBuffer(), 0, charCount, charCount, getRTL(text), 0, 0, success);
698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            actual.glyphs    = NEW_ARRAY(LEGlyphID, actual.glyphCount);
700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            actual.indices   = NEW_ARRAY(le_int32, actual.glyphCount);
701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            actual.positions = NEW_ARRAY(float, actual.glyphCount * 2 + 2);
702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            engine->getGlyphs(actual.glyphs, success);
704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            engine->getCharIndices(actual.indices, success);
705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            engine->getGlyphPositions(actual.positions, success);
706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            compareResults(id, &expected, &actual);
708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(actual.positions);
710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(actual.indices);
711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(actual.glyphs);
712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete engine;
714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)free_expected:
716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(expected.positions);
717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(expected.indices);
718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            DELETE_ARRAY(expected.glyphs);
719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete font;
721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)free_c_strings:
723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            freeCString(lang);
724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            freeCString(script);
725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            freeCString(id);
726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete root;
730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete parser;
731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * From ticket:5923:
738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Build a paragraph that contains a mixture of left to right and right to left text.
740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Break it into multiple lines and make sure that the glyphToCharMap for run in each
741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * line is correct.
742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Note: it might be a good idea to also check the glyphs and positions for each run,
744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * that we get the expected number of runs per line and that the line breaks are where
745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * we expect them to be. Really, it would be a good idea to make a whole test suite
746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * for ParagraphLayout.
747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV GlyphToCharTest(void)
749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEErrorCode status = LE_NO_ERROR;
751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEFontInstance *font;
752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    FontRuns fontRuns(0);
753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ParagraphLayout *paragraphLayout;
754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ParagraphLayout::Line *line;
755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*
756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * This is the same text that's in <icu>/source/samples/layout/Sample.txt
757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     */
758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    LEUnicode chars[] = {
759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*BOM*/ 0x0054, 0x0068, 0x0065, 0x0020, 0x004c, 0x0061, 0x0079,
760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006f, 0x0075, 0x0074, 0x0045, 0x006e, 0x0067, 0x0069, 0x006e,
761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0065, 0x0020, 0x0064, 0x006f, 0x0065, 0x0073, 0x0020, 0x0061,
762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006c, 0x006c, 0x0020, 0x0074, 0x0068, 0x0065, 0x0020, 0x0077,
763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006f, 0x0072, 0x006b, 0x0020, 0x006e, 0x0065, 0x0063, 0x0065,
764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0073, 0x0073, 0x0061, 0x0072, 0x0079, 0x0020, 0x0074, 0x006f,
765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0064, 0x0069, 0x0073, 0x0070, 0x006c, 0x0061, 0x0079,
766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0055, 0x006e, 0x0069, 0x0063, 0x006f, 0x0064, 0x0065,
767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x0020, 0x0077, 0x0072,
768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0069, 0x0074, 0x0074, 0x0065, 0x006e, 0x0020, 0x0069, 0x006e,
769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x006c, 0x0061, 0x006e, 0x0067, 0x0075, 0x0061, 0x0067,
770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0065, 0x0073, 0x0020, 0x0077, 0x0069, 0x0074, 0x0068, 0x0020,
771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0063, 0x006f, 0x006d, 0x0070, 0x006c, 0x0065, 0x0078, 0x0020,
772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0077, 0x0072, 0x0069, 0x0074, 0x0069, 0x006e, 0x0067, 0x0020,
773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0073, 0x0079, 0x0073, 0x0074, 0x0065, 0x006d, 0x0073, 0x0020,
774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0073, 0x0075, 0x0063, 0x0068, 0x0020, 0x0061, 0x0073, 0x0020,
775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0048, 0x0069, 0x006e, 0x0064, 0x0069, 0x0020, 0x0028, 0x0939,
776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x093f, 0x0928, 0x094d, 0x0926, 0x0940, 0x0029, 0x0020, 0x0054,
777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0068, 0x0061, 0x0069, 0x0020, 0x0028, 0x0e44, 0x0e17, 0x0e22,
778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0029, 0x0020, 0x0061, 0x006e, 0x0064, 0x0020, 0x0041, 0x0072,
779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0061, 0x0062, 0x0069, 0x0063, 0x0020, 0x0028, 0x0627, 0x0644,
780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0639, 0x0631, 0x0628, 0x064a, 0x0629, 0x0029, 0x002e, 0x0020,
781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0048, 0x0065, 0x0072, 0x0065, 0x0027, 0x0073, 0x0020, 0x0061,
782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0073, 0x0061, 0x006d, 0x0070, 0x006c, 0x0065, 0x0020,
783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006f, 0x0066, 0x0020, 0x0073, 0x006f, 0x006d, 0x0065, 0x0020,
784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0074, 0x0065, 0x0078, 0x0074, 0x0020, 0x0077, 0x0072, 0x0069,
785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0074, 0x0074, 0x0065, 0x006e, 0x0020, 0x0069, 0x006e, 0x0020,
786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0053, 0x0061, 0x006e, 0x0073, 0x006b, 0x0072, 0x0069, 0x0074,
787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x003a, 0x0020, 0x0936, 0x094d, 0x0930, 0x0940, 0x092e, 0x0926,
788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x094d, 0x0020, 0x092d, 0x0917, 0x0935, 0x0926, 0x094d, 0x0917,
789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0940, 0x0924, 0x093e, 0x0020, 0x0905, 0x0927, 0x094d, 0x092f,
790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x093e, 0x092f, 0x0020, 0x0905, 0x0930, 0x094d, 0x091c, 0x0941,
791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0928, 0x0020, 0x0935, 0x093f, 0x0937, 0x093e, 0x0926, 0x0020,
792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x092f, 0x094b, 0x0917, 0x0020, 0x0927, 0x0943, 0x0924, 0x0930,
793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x093e, 0x0937, 0x094d, 0x091f, 0x094d, 0x0930, 0x0020, 0x0909,
794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0935, 0x093e, 0x091a, 0x0964, 0x0020, 0x0927, 0x0930, 0x094d,
795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x092e, 0x0915, 0x094d, 0x0937, 0x0947, 0x0924, 0x094d, 0x0930,
796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0947, 0x0020, 0x0915, 0x0941, 0x0930, 0x0941, 0x0915, 0x094d,
797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0937, 0x0947, 0x0924, 0x094d, 0x0930, 0x0947, 0x0020, 0x0938,
798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x092e, 0x0935, 0x0947, 0x0924, 0x093e, 0x0020, 0x092f, 0x0941,
799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x092f, 0x0941, 0x0924, 0x094d, 0x0938, 0x0935, 0x0903, 0x0020,
800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x092e, 0x093e, 0x092e, 0x0915, 0x093e, 0x0903, 0x0020, 0x092a,
801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x093e, 0x0923, 0x094d, 0x0921, 0x0935, 0x093e, 0x0936, 0x094d,
802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x091a, 0x0948, 0x0935, 0x0020, 0x0915, 0x093f, 0x092e, 0x0915,
803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0941, 0x0930, 0x094d, 0x0935, 0x0924, 0x0020, 0x0938, 0x0902,
804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x091c, 0x092f, 0x0020, 0x0048, 0x0065, 0x0072, 0x0065, 0x0027,
805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0073, 0x0020, 0x0061, 0x0020, 0x0073, 0x0061, 0x006d, 0x0070,
806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006c, 0x0065, 0x0020, 0x006f, 0x0066, 0x0020, 0x0073, 0x006f,
807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006d, 0x0065, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x0020,
808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0077, 0x0072, 0x0069, 0x0074, 0x0074, 0x0065, 0x006e, 0x0020,
809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0069, 0x006e, 0x0020, 0x0041, 0x0072, 0x0061, 0x0062, 0x0069,
810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0063, 0x003a, 0x0020, 0x0623, 0x0633, 0x0627, 0x0633, 0x064b,
811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0627, 0x060c, 0x0020, 0x062a, 0x062a, 0x0639, 0x0627, 0x0645,
812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0644, 0x0020, 0x0627, 0x0644, 0x062d, 0x0648, 0x0627, 0x0633,
813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x064a, 0x0628, 0x0020, 0x0641, 0x0642, 0x0637, 0x0020, 0x0645,
814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0639, 0x0020, 0x0627, 0x0644, 0x0623, 0x0631, 0x0642, 0x0627,
815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x060c, 0x0020, 0x0648, 0x062a, 0x0642, 0x0648, 0x0645,
816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0628, 0x062a, 0x062e, 0x0632, 0x064a, 0x0646, 0x0020,
817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0627, 0x0644, 0x0623, 0x062d, 0x0631, 0x0641, 0x0020, 0x0648,
818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0627, 0x0644, 0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x0020,
819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0627, 0x0644, 0x0623, 0x062e, 0x0631, 0x0649, 0x0020, 0x0628,
820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0639, 0x062f, 0x0020, 0x0623, 0x0646, 0x0020, 0x062a, 0x064f,
821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0639, 0x0637, 0x064a, 0x0020, 0x0631, 0x0642, 0x0645, 0x0627,
822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0645, 0x0639, 0x064a, 0x0646, 0x0627, 0x0020, 0x0644,
823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0643, 0x0644, 0x0020, 0x0648, 0x0627, 0x062d, 0x062f, 0x0020,
824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x0646, 0x0647, 0x0627, 0x002e, 0x0020, 0x0648, 0x0642,
825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0628, 0x0644, 0x0020, 0x0627, 0x062e, 0x062a, 0x0631, 0x0627,
826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0639, 0x0020, 0x0022, 0x064a, 0x0648, 0x0646, 0x0650, 0x0643,
827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0648, 0x062f, 0x0022, 0x060c, 0x0020, 0x0643, 0x0627, 0x0646,
828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0647, 0x0646, 0x0627, 0x0643, 0x0020, 0x0645, 0x0626,
829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0627, 0x062a, 0x0020, 0x0627, 0x0644, 0x0623, 0x0646, 0x0638,
830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x0629, 0x0020, 0x0644, 0x0644, 0x062a, 0x0634, 0x0641,
831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x064a, 0x0631, 0x0020, 0x0648, 0x062a, 0x062e, 0x0635, 0x064a,
832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0635, 0x0020, 0x0647, 0x0630, 0x0647, 0x0020, 0x0627, 0x0644,
833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0623, 0x0631, 0x0642, 0x0627, 0x0645, 0x0020, 0x0644, 0x0644,
834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x060c, 0x0020, 0x0648,
835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0644, 0x0645, 0x0020, 0x064a, 0x0648, 0x062c, 0x062f, 0x0020,
836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0646, 0x0638, 0x0627, 0x0645, 0x0020, 0x062a, 0x0634, 0x0641,
837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x064a, 0x0631, 0x0020, 0x0648, 0x0627, 0x062d, 0x062f, 0x0020,
838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x064a, 0x062d, 0x062a, 0x0648, 0x064a, 0x0020, 0x0639, 0x0644,
839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0649, 0x0020, 0x062c, 0x0645, 0x064a, 0x0639, 0x0020, 0x0627,
840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0644, 0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x0020, 0x0627,
841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0644, 0x0636, 0x0631, 0x0648, 0x0631, 0x064a, 0x0629, 0x0020,
842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0061, 0x006e, 0x0064, 0x0020, 0x0068, 0x0065, 0x0072, 0x0065,
843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0027, 0x0073, 0x0020, 0x0061, 0x0020, 0x0073, 0x0061, 0x006d,
844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0070, 0x006c, 0x0065, 0x0020, 0x006f, 0x0066, 0x0020, 0x0073,
845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x006f, 0x006d, 0x0065, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074,
846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0077, 0x0072, 0x0069, 0x0074, 0x0074, 0x0065, 0x006e,
847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0020, 0x0069, 0x006e, 0x0020, 0x0054, 0x0068, 0x0061, 0x0069,
848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x003a, 0x0020, 0x0e1a, 0x0e17, 0x0e17, 0x0e35, 0x0e48, 0x0e51,
849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e1e, 0x0e32, 0x0e22, 0x0e38, 0x0e44, 0x0e0b, 0x0e42, 0x0e04,
850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e25, 0x0e19, 0x0e42, 0x0e14, 0x0e42, 0x0e23, 0x0e18, 0x0e35,
851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e2d, 0x0e32, 0x0e28, 0x0e31, 0x0e22, 0x0e2d, 0x0e22, 0x0e39,
852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e48, 0x0e17, 0x0e48, 0x0e32, 0x0e21, 0x0e01, 0x0e25, 0x0e32,
853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e07, 0x0e17, 0x0e38, 0x0e48, 0x0e07, 0x0e43, 0x0e2b, 0x0e0d,
854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e48, 0x0e43, 0x0e19, 0x0e41, 0x0e04, 0x0e19, 0x0e0b, 0x0e31,
855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e2a, 0x0e01, 0x0e31, 0x0e1a, 0x0e25, 0x0e38, 0x0e07, 0x0e40,
856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e2e, 0x0e19, 0x0e23, 0x0e35, 0x0e0a, 0x0e32, 0x0e27, 0x0e44,
857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e23, 0x0e48, 0x0e41, 0x0e25, 0x0e30, 0x0e1b, 0x0e49, 0x0e32,
858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e40, 0x0e2d, 0x0e47, 0x0e21, 0x0e20, 0x0e23, 0x0e23, 0x0e22,
859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e32, 0x0e0a, 0x0e32, 0x0e27, 0x0e44, 0x0e23, 0x0e48, 0x0e1a,
860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e49, 0x0e32, 0x0e19, 0x0e02, 0x0e2d, 0x0e07, 0x0e1e, 0x0e27,
861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e01, 0x0e40, 0x0e02, 0x0e32, 0x0e2b, 0x0e25, 0x0e31, 0x0e07,
862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e40, 0x0e25, 0x0e47, 0x0e01, 0x0e40, 0x0e1e, 0x0e23, 0x0e32,
863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e30, 0x0e44, 0x0e21, 0x0e49, 0x0e2a, 0x0e23, 0x0e49, 0x0e32,
864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e07, 0x0e1a, 0x0e49, 0x0e32, 0x0e19, 0x0e15, 0x0e49, 0x0e2d,
865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e07, 0x0e02, 0x0e19, 0x0e21, 0x0e32, 0x0e14, 0x0e49, 0x0e27,
866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e22, 0x0e40, 0x0e01, 0x0e27, 0x0e35, 0x0e22, 0x0e19, 0x0e40,
867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e1b, 0x0e47, 0x0e19, 0x0e23, 0x0e30, 0x0e22, 0x0e30, 0x0e17,
868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e32, 0x0e07, 0x0e2b, 0x0e25, 0x0e32, 0x0e22, 0x0e44, 0x0e21,
869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        0x0e25, 0x0e4c
870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    };
871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 charCount = LE_ARRAY_SIZE(chars);
872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    le_int32 charIndex = 0, lineNumber = 1;
873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const float lineWidth = 600;
874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    font = new SimpleFontInstance(12, status);
876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto finish;
879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fontRuns.add(font, charCount);
882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    paragraphLayout = new ParagraphLayout(chars, charCount, &fontRuns, NULL, NULL, NULL, 0, FALSE, status);
884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (LE_FAILURE(status)) {
886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto close_font;
887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    paragraphLayout->reflow();
890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while ((line = paragraphLayout->nextLine(lineWidth)) != NULL) {
891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        le_int32 runCount = line->countRuns();
892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for(le_int32 run = 0; run < runCount; run += 1) {
894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const ParagraphLayout::VisualRun *visualRun = line->getVisualRun(run);
895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            le_int32 glyphCount = visualRun->getGlyphCount();
896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const le_int32 *glyphToCharMap = visualRun->getGlyphToCharMap();
897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (visualRun->getDirection() == UBIDI_RTL) {
899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /*
900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * For a right to left run, make sure that the character indices
901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * increase from the right most glyph to the left most glyph. If
902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * there are any one to many glyph substitutions, we might get several
903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * glyphs in a row with the same character index.
904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 */
905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                for(le_int32 i = glyphCount - 1; i >= 0; i -= 1) {
906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    le_int32 ix = glyphToCharMap[i];
907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (ix != charIndex) {
909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (ix != charIndex - 1) {
910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            log_err("Bad glyph to char index for glyph %d on line %d: expected %d, got %d\n",
911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                i, lineNumber, charIndex, ix);
912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            goto close_paragraph; // once there's one error, we can't count on anything else...
913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    } else {
915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        charIndex += 1;
916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /*
920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * We can't just check the order of the character indices
921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * for left to right runs because Indic text might have been
922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * reordered. What we can do is find the minimum and maximum
923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * character indices in the run and make sure that the minimum
924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 * is equal to charIndex and then advance charIndex to the maximum.
925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 */
926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                le_int32 minIndex = 0x7FFFFFFF, maxIndex = -1;
927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                for(le_int32 i = 0; i < glyphCount; i += 1) {
929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    le_int32 ix = glyphToCharMap[i];
930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (ix > maxIndex) {
932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        maxIndex = ix;
933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (ix < minIndex) {
936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        minIndex = ix;
937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (minIndex != charIndex) {
941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    log_err("Bad minIndex for run %d on line %d: expected %d, got %d\n",
942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        run, lineNumber, charIndex, minIndex);
943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    goto close_paragraph; // once there's one error, we can't count on anything else...
944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                charIndex = maxIndex + 1;
947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        lineNumber += 1;
951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)close_paragraph:
953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete paragraphLayout;
954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)close_font:
956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete font;
957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)finish:
959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void addAllTests(TestNode **root)
964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &ScriptTest,      "api/ScriptTest");
966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &ParamTest,       "api/ParameterTest");
967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &FactoryTest,     "api/FactoryTest");
968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &AccessTest,      "layout/AccessTest");
969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &DataDrivenTest,  "layout/DataDrivenTest");
970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addTest(root, &GlyphToCharTest, "paragraph/GlyphToCharTest");
971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addCTests(root);
973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* returns the path to icu/source/data/out */
976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char *ctest_dataOutDir()
977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    static const char *dataOutDir = NULL;
979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(dataOutDir) {
981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return dataOutDir;
982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* U_TOPBUILDDIR is set by the makefiles on UNIXes when building cintltst and intltst
985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              to point to the top of the build hierarchy, which may or
986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              may not be the same as the source directory, depending on
987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              the configure options used.  At any rate,
988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              set the data path to the built data from this directory.
989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              The value is complete with quotes, so it can be used
990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //              as-is as a string constant.
991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    */
992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if defined (U_TOPBUILDDIR)
993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    {
994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        dataOutDir = U_TOPBUILDDIR "data"U_FILE_SEP_STRING"out"U_FILE_SEP_STRING;
995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else
997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* On Windows, the file name obtained from __FILE__ includes a full path.
999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     *             This file is "wherever\icu\source\test\cintltst\cintltst.c"
1000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     *             Change to    "wherever\icu\source\data"
1001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     */
1002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    {
1003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        static char p[sizeof(__FILE__) + 20];
1004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        char *pBackSlash;
1005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int i;
1006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        strcpy(p, __FILE__);
1008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* We want to back over three '\' chars.                            */
1009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*   Only Windows should end up here, so looking for '\' is safe.   */
1010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (i=1; i<=3; i++) {
1011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            pBackSlash = strrchr(p, U_FILE_SEP_CHAR);
1012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (pBackSlash != NULL) {
1013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *pBackSlash = 0;        /* Truncate the string at the '\'   */
1014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (pBackSlash != NULL) {
1018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* We found and truncated three names from the path.
1019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             *  Now append "source\data" and set the environment
1020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             */
1021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            strcpy(pBackSlash, U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING);
1022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            dataOutDir = p;
1023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else {
1025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* __FILE__ on MSVC7 does not contain the directory */
1026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            FILE *file = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "Makefile.in", "r");
1027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (file) {
1028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fclose(file);
1029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else {
1032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                dataOutDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING "data" U_FILE_SEP_STRING "out" U_FILE_SEP_STRING;
1033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
1037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return dataOutDir;
1039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*  ctest_setICU_DATA  - if the ICU_DATA environment variable is not already
1042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       set, try to deduce the directory in which ICU was built,
1043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       and set ICU_DATA to "icu/source/data" in that location.
1044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       The intent is to allow the tests to have a good chance
1045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       of running without requiring that the user manually set
1046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       ICU_DATA.  Common data isn't a problem, since it is
1047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       picked up via a static (build time) reference, but the
1048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *                       tests dynamically load some data.
1049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
1050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void ctest_setICU_DATA() {
1051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* No location for the data dir was identifiable.
1053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     *   Add other fallbacks for the test data location here if the need arises
1054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     */
1055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (getenv("ICU_DATA") == NULL) {
1056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* If ICU_DATA isn't set, set it to the usual location */
1057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_setDataDirectory(ctest_dataOutDir());
1058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int main(int argc, char* argv[])
1062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
1063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t nerrors = 0;
1064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    TestNode *root = NULL;
1065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode errorCode = U_ZERO_ERROR;
1066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UDate startTime, endTime;
1067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t diffTime;
1068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    startTime = uprv_getUTCtime();
1070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!initArgs(argc, argv, NULL, NULL)) {
1072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Error already displayed. */
1073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return -1;
1074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* Check whether ICU will initialize without forcing the build data directory into
1077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *  the ICU_DATA path.  Success here means either the data dll contains data, or that
1078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *  this test program was run with ICU_DATA set externally.  Failure of this check
1079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *  is normal when ICU data is not packaged into a shared library.
1080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *
1081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *  Whether or not this test succeeds, we want to cleanup and reinitialize
1082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *  with a data path so that data loading from individual files can be tested.
1083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    */
1084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_init(&errorCode);
1085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(errorCode)) {
1087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fprintf(stderr,
1088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            "#### Note:  ICU Init without build-specific setDataDirectory() failed.\n");
1089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_cleanup();
1092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    errorCode = U_ZERO_ERROR;
1093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!initArgs(argc, argv, NULL, NULL)) {
1095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Error already displayed. */
1096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return -1;
1097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Initialize ICU */
1099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ctest_setICU_DATA();    /* u_setDataDirectory() must happen Before u_init() */
1100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_init(&errorCode);
1101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(errorCode)) {
1103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fprintf(stderr,
1104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            "#### ERROR! %s: u_init() failed with status = \"%s\".\n"
1105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            "*** Check the ICU_DATA environment variable and \n"
1106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            "*** check that the data files are present.\n", argv[0], u_errorName(errorCode));
1107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 1;
1108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    addAllTests(&root);
1111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    nerrors = runTestRequest(root, argc, argv);
1112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    cleanUpTestTree(root);
1114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_cleanup();
1115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    endTime = uprv_getUTCtime();
1117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    diffTime = (int32_t)(endTime - startTime);
1118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    printf("Elapsed Time: %02d:%02d:%02d.%03d\n",
1119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (int)((diffTime%U_MILLIS_PER_DAY)/U_MILLIS_PER_HOUR),
1120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (int)((diffTime%U_MILLIS_PER_HOUR)/U_MILLIS_PER_MINUTE),
1121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (int)((diffTime%U_MILLIS_PER_MINUTE)/U_MILLIS_PER_SECOND),
1122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (int)(diffTime%U_MILLIS_PER_SECOND));
1123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return nerrors;
1125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1127