xref: /aosp_15_r20/external/icu/icu4c/source/test/letest/cletest.c (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker  *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker  *
6*0e209d39SAndroid Build Coastguard Worker  *   Copyright (C) 1999-2014, International Business Machines
7*0e209d39SAndroid Build Coastguard Worker  *   Corporation and others.  All Rights Reserved.
8*0e209d39SAndroid Build Coastguard Worker  *
9*0e209d39SAndroid Build Coastguard Worker  *******************************************************************************
10*0e209d39SAndroid Build Coastguard Worker  */
11*0e209d39SAndroid Build Coastguard Worker 
12*0e209d39SAndroid Build Coastguard Worker #ifndef USING_ICULEHB /* C API not available under HB */
13*0e209d39SAndroid Build Coastguard Worker 
14*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
15*0e209d39SAndroid Build Coastguard Worker #include "unicode/ubidi.h"
16*0e209d39SAndroid Build Coastguard Worker #include "unicode/uscript.h"
17*0e209d39SAndroid Build Coastguard Worker #include "unicode/ctest.h"
18*0e209d39SAndroid Build Coastguard Worker 
19*0e209d39SAndroid Build Coastguard Worker #include "layout/LETypes.h"
20*0e209d39SAndroid Build Coastguard Worker #include "layout/LEScripts.h"
21*0e209d39SAndroid Build Coastguard Worker #include "layout/loengine.h"
22*0e209d39SAndroid Build Coastguard Worker 
23*0e209d39SAndroid Build Coastguard Worker #include "layout/playout.h"
24*0e209d39SAndroid Build Coastguard Worker #include "layout/plruns.h"
25*0e209d39SAndroid Build Coastguard Worker 
26*0e209d39SAndroid Build Coastguard Worker #include "cfonts.h"
27*0e209d39SAndroid Build Coastguard Worker 
28*0e209d39SAndroid Build Coastguard Worker #include "letest.h"
29*0e209d39SAndroid Build Coastguard Worker 
30*0e209d39SAndroid Build Coastguard Worker #include "sfnt.h"
31*0e209d39SAndroid Build Coastguard Worker #include "xmlreader.h"
32*0e209d39SAndroid Build Coastguard Worker #include "putilimp.h" /* for U_FILE_SEP_STRING */
33*0e209d39SAndroid Build Coastguard Worker 
34*0e209d39SAndroid Build Coastguard Worker #include <stdlib.h>
35*0e209d39SAndroid Build Coastguard Worker #include <stdio.h>
36*0e209d39SAndroid Build Coastguard Worker #include <string.h>
37*0e209d39SAndroid Build Coastguard Worker 
38*0e209d39SAndroid Build Coastguard Worker #define CH_COMMA 0x002C
39*0e209d39SAndroid Build Coastguard Worker 
40*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
ParamTest(void)41*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV ParamTest(void)
42*0e209d39SAndroid Build Coastguard Worker {
43*0e209d39SAndroid Build Coastguard Worker     LEErrorCode status = LE_NO_ERROR;
44*0e209d39SAndroid Build Coastguard Worker     le_font *font = le_simpleFontOpen(12, &status);
45*0e209d39SAndroid Build Coastguard Worker     le_engine *engine = le_create(font, arabScriptCode, -1, 0, &status);
46*0e209d39SAndroid Build Coastguard Worker     LEGlyphID *glyphs    = NULL;
47*0e209d39SAndroid Build Coastguard Worker     le_int32  *indices   = NULL;
48*0e209d39SAndroid Build Coastguard Worker     float     *positions = NULL;
49*0e209d39SAndroid Build Coastguard Worker     le_int32   glyphCount = 0;
50*0e209d39SAndroid Build Coastguard Worker 
51*0e209d39SAndroid Build Coastguard Worker     float x = 0.0, y = 0.0;
52*0e209d39SAndroid Build Coastguard Worker 	LEUnicode chars[] = {
53*0e209d39SAndroid Build Coastguard Worker 	  0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, /* "English "                      */
54*0e209d39SAndroid Build Coastguard Worker 	  0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634,                 /* MEM ALIF KAF NOON TEH WAW SHEEN */
55*0e209d39SAndroid Build Coastguard Worker 	  0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E                   /* " text."                        */
56*0e209d39SAndroid Build Coastguard Worker     };
57*0e209d39SAndroid Build Coastguard Worker 
58*0e209d39SAndroid Build Coastguard Worker 
59*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_getGlyphCount(engine, &status);
60*0e209d39SAndroid Build Coastguard Worker     if (glyphCount != 0) {
61*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphCount() on an empty layout returned %d.\n", glyphCount);
62*0e209d39SAndroid Build Coastguard Worker     }
63*0e209d39SAndroid Build Coastguard Worker 
64*0e209d39SAndroid Build Coastguard Worker     glyphs    = NEW_ARRAY(LEGlyphID, glyphCount + 10);
65*0e209d39SAndroid Build Coastguard Worker     indices   = NEW_ARRAY(le_int32, glyphCount + 10);
66*0e209d39SAndroid Build Coastguard Worker     positions = NEW_ARRAY(float, glyphCount + 10);
67*0e209d39SAndroid Build Coastguard Worker 
68*0e209d39SAndroid Build Coastguard Worker     le_getGlyphs(engine, NULL, &status);
69*0e209d39SAndroid Build Coastguard Worker 
70*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
71*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphs(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
72*0e209d39SAndroid Build Coastguard Worker     }
73*0e209d39SAndroid Build Coastguard Worker 
74*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
75*0e209d39SAndroid Build Coastguard Worker     le_getGlyphs(engine, glyphs, &status);
76*0e209d39SAndroid Build Coastguard Worker 
77*0e209d39SAndroid Build Coastguard Worker     if (status != LE_NO_LAYOUT_ERROR) {
78*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphs(glyphs, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
79*0e209d39SAndroid Build Coastguard Worker     }
80*0e209d39SAndroid Build Coastguard Worker 
81*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
82*0e209d39SAndroid Build Coastguard Worker     le_getCharIndices(engine, NULL, &status);
83*0e209d39SAndroid Build Coastguard Worker 
84*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
85*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getCharIndices(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
86*0e209d39SAndroid Build Coastguard Worker     }
87*0e209d39SAndroid Build Coastguard Worker 
88*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
89*0e209d39SAndroid Build Coastguard Worker     le_getCharIndices(engine, indices, &status);
90*0e209d39SAndroid Build Coastguard Worker 
91*0e209d39SAndroid Build Coastguard Worker     if (status != LE_NO_LAYOUT_ERROR) {
92*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getCharIndices(indices, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
93*0e209d39SAndroid Build Coastguard Worker     }
94*0e209d39SAndroid Build Coastguard Worker 
95*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
96*0e209d39SAndroid Build Coastguard Worker     le_getCharIndicesWithBase(engine, NULL, 1024, &status);
97*0e209d39SAndroid Build Coastguard Worker 
98*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
99*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getCharIndices(NULL, 1024, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
100*0e209d39SAndroid Build Coastguard Worker     }
101*0e209d39SAndroid Build Coastguard Worker 
102*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
103*0e209d39SAndroid Build Coastguard Worker     le_getCharIndicesWithBase(engine, indices, 1024, &status);
104*0e209d39SAndroid Build Coastguard Worker 
105*0e209d39SAndroid Build Coastguard Worker     if (status != LE_NO_LAYOUT_ERROR) {
106*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getCharIndices(indices, 1024, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
107*0e209d39SAndroid Build Coastguard Worker     }
108*0e209d39SAndroid Build Coastguard Worker 
109*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
110*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPositions(engine, NULL, &status);
111*0e209d39SAndroid Build Coastguard Worker 
112*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
113*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphPositions(NULL, status) did not return LE_ILLEGAL_ARGUMENT_ERROR.\n");
114*0e209d39SAndroid Build Coastguard Worker     }
115*0e209d39SAndroid Build Coastguard Worker 
116*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
117*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPositions(engine, positions, &status);
118*0e209d39SAndroid Build Coastguard Worker 
119*0e209d39SAndroid Build Coastguard Worker     if (status != LE_NO_LAYOUT_ERROR) {
120*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphPositions(positions, status) on an empty layout did not return LE_NO_LAYOUT_ERROR.\n");
121*0e209d39SAndroid Build Coastguard Worker     }
122*0e209d39SAndroid Build Coastguard Worker 
123*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(positions);
124*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(indices);
125*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(glyphs);
126*0e209d39SAndroid Build Coastguard Worker 
127*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
128*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, NULL, 0, 0, 0, false, 0.0, 0.0, &status);
129*0e209d39SAndroid Build Coastguard Worker 
130*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
131*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars(NULL, 0, 0, 0, false, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
132*0e209d39SAndroid Build Coastguard Worker     }
133*0e209d39SAndroid Build Coastguard Worker 
134*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
135*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, -1, 6, 20, true, 0.0, 0.0, &status);
136*0e209d39SAndroid Build Coastguard Worker 
137*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
138*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars(chars, -1, 6, 20, true, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
139*0e209d39SAndroid Build Coastguard Worker     }
140*0e209d39SAndroid Build Coastguard Worker 
141*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
142*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, 8, -1, 20, true, 0.0, 0.0, &status);
143*0e209d39SAndroid Build Coastguard Worker 
144*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
145*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars(chars, 8, -1, 20, true, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
146*0e209d39SAndroid Build Coastguard Worker     }
147*0e209d39SAndroid Build Coastguard Worker 
148*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
149*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, 8, 6, -1, true, 0.0, 0.0, &status);
150*0e209d39SAndroid Build Coastguard Worker 
151*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
152*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars((chars, 8, 6, -1, true, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
153*0e209d39SAndroid Build Coastguard Worker     }
154*0e209d39SAndroid Build Coastguard Worker 
155*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
156*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, 8, 6, 10, true, 0.0, 0.0, &status);
157*0e209d39SAndroid Build Coastguard Worker 
158*0e209d39SAndroid Build Coastguard Worker     if (status != LE_ILLEGAL_ARGUMENT_ERROR) {
159*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars(chars, 8, 6, 10, true, 0.0, 0.0, status) did not fail w/ LE_ILLEGAL_ARGUMENT_ERROR.\n");
160*0e209d39SAndroid Build Coastguard Worker     }
161*0e209d39SAndroid Build Coastguard Worker 
162*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
163*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, 8, 6, 20, true, 0.0, 0.0, &status);
164*0e209d39SAndroid Build Coastguard Worker 
165*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
166*0e209d39SAndroid Build Coastguard Worker         log_err("Calling layoutChars(chars, 8, 6, 20, true, 0.0, 0.0, status) failed.\n");
167*0e209d39SAndroid Build Coastguard Worker         goto bail;
168*0e209d39SAndroid Build Coastguard Worker     }
169*0e209d39SAndroid Build Coastguard Worker 
170*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPosition(engine, -1, &x, &y, &status);
171*0e209d39SAndroid Build Coastguard Worker 
172*0e209d39SAndroid Build Coastguard Worker     if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
173*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphPosition(-1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
174*0e209d39SAndroid Build Coastguard Worker     }
175*0e209d39SAndroid Build Coastguard Worker 
176*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
177*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPosition(engine, glyphCount + 1, &x, &y, &status);
178*0e209d39SAndroid Build Coastguard Worker 
179*0e209d39SAndroid Build Coastguard Worker     if (status != LE_INDEX_OUT_OF_BOUNDS_ERROR) {
180*0e209d39SAndroid Build Coastguard Worker         log_err("Calling getGlyphPosition(glyphCount + 1, x, y, status) did not fail w/ LE_INDEX_OUT_OF_BOUNDS_ERROR.\n");
181*0e209d39SAndroid Build Coastguard Worker     }
182*0e209d39SAndroid Build Coastguard Worker 
183*0e209d39SAndroid Build Coastguard Worker bail:
184*0e209d39SAndroid Build Coastguard Worker     le_close(engine);
185*0e209d39SAndroid Build Coastguard Worker     le_fontClose(font);
186*0e209d39SAndroid Build Coastguard Worker }
187*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
188*0e209d39SAndroid Build Coastguard Worker 
189*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
FactoryTest(void)190*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV FactoryTest(void)
191*0e209d39SAndroid Build Coastguard Worker {
192*0e209d39SAndroid Build Coastguard Worker     LEErrorCode status = LE_NO_ERROR;
193*0e209d39SAndroid Build Coastguard Worker     le_font *font = le_simpleFontOpen(12, &status);
194*0e209d39SAndroid Build Coastguard Worker     le_engine *engine = NULL;
195*0e209d39SAndroid Build Coastguard Worker 	le_int32 scriptCode;
196*0e209d39SAndroid Build Coastguard Worker 
197*0e209d39SAndroid Build Coastguard Worker     for(scriptCode = 0; scriptCode < scriptCodeCount; scriptCode += 1) {
198*0e209d39SAndroid Build Coastguard Worker         status = LE_NO_ERROR;
199*0e209d39SAndroid Build Coastguard Worker         engine = le_create(font, scriptCode, -1, 0, &status);
200*0e209d39SAndroid Build Coastguard Worker 
201*0e209d39SAndroid Build Coastguard Worker         if (LE_FAILURE(status)) {
202*0e209d39SAndroid Build Coastguard Worker             log_err("Could not create a LayoutEngine for script \'%s\'.\n", uscript_getShortName((UScriptCode)scriptCode));
203*0e209d39SAndroid Build Coastguard Worker         }
204*0e209d39SAndroid Build Coastguard Worker 
205*0e209d39SAndroid Build Coastguard Worker         le_close(engine);
206*0e209d39SAndroid Build Coastguard Worker     }
207*0e209d39SAndroid Build Coastguard Worker 
208*0e209d39SAndroid Build Coastguard Worker     le_fontClose(font);
209*0e209d39SAndroid Build Coastguard Worker }
210*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
211*0e209d39SAndroid Build Coastguard Worker 
212*0e209d39SAndroid Build Coastguard Worker U_CDECL_BEGIN
AccessTest(void)213*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV AccessTest(void)
214*0e209d39SAndroid Build Coastguard Worker {
215*0e209d39SAndroid Build Coastguard Worker     LEErrorCode status = LE_NO_ERROR;
216*0e209d39SAndroid Build Coastguard Worker     le_font *font = le_simpleFontOpen(12, &status);
217*0e209d39SAndroid Build Coastguard Worker     le_engine *engine =le_create(font, arabScriptCode, -1, 0, &status);
218*0e209d39SAndroid Build Coastguard Worker     le_int32 glyphCount;
219*0e209d39SAndroid Build Coastguard Worker     LEGlyphID glyphs[6];
220*0e209d39SAndroid Build Coastguard Worker     le_int32 biasedIndices[6], indices[6], glyph;
221*0e209d39SAndroid Build Coastguard Worker     float positions[6 * 2 + 2];
222*0e209d39SAndroid Build Coastguard Worker     LEUnicode chars[] = {
223*0e209d39SAndroid Build Coastguard Worker       0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, /* "English "                      */
224*0e209d39SAndroid Build Coastguard Worker       0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634,                 /* MEM ALIF KAF NOON TEH WAW SHEEN */
225*0e209d39SAndroid Build Coastguard Worker       0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E                   /* " text."                        */
226*0e209d39SAndroid Build Coastguard Worker     };
227*0e209d39SAndroid Build Coastguard Worker 
228*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
229*0e209d39SAndroid Build Coastguard Worker         log_err("Could not create LayoutEngine.\n");
230*0e209d39SAndroid Build Coastguard Worker         goto bail;
231*0e209d39SAndroid Build Coastguard Worker     }
232*0e209d39SAndroid Build Coastguard Worker 
233*0e209d39SAndroid Build Coastguard Worker     glyphCount = le_layoutChars(engine, chars, 8, 6, 20, true, 0.0, 0.0, &status);
234*0e209d39SAndroid Build Coastguard Worker 
235*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status) || glyphCount != 6) {
236*0e209d39SAndroid Build Coastguard Worker         log_err("layoutChars(chars, 8, 6, 20, true, 0.0, 0.0, status) failed.\n");
237*0e209d39SAndroid Build Coastguard Worker         goto bail;
238*0e209d39SAndroid Build Coastguard Worker     }
239*0e209d39SAndroid Build Coastguard Worker 
240*0e209d39SAndroid Build Coastguard Worker     le_getGlyphs(engine, glyphs, &status);
241*0e209d39SAndroid Build Coastguard Worker     le_getCharIndices(engine, indices, &status);
242*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPositions(engine, positions, &status);
243*0e209d39SAndroid Build Coastguard Worker 
244*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
245*0e209d39SAndroid Build Coastguard Worker         log_err("Could not get glyph, indices and position arrays.\n");
246*0e209d39SAndroid Build Coastguard Worker         goto bail;
247*0e209d39SAndroid Build Coastguard Worker     }
248*0e209d39SAndroid Build Coastguard Worker 
249*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
250*0e209d39SAndroid Build Coastguard Worker     le_getCharIndicesWithBase(engine, biasedIndices, 1024, &status);
251*0e209d39SAndroid Build Coastguard Worker 
252*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
253*0e209d39SAndroid Build Coastguard Worker         log_err("getCharIndices(biasedIndices, 1024, status) failed.\n");
254*0e209d39SAndroid Build Coastguard Worker     } else {
255*0e209d39SAndroid Build Coastguard Worker         for (glyph = 0; glyph < glyphCount; glyph += 1) {
256*0e209d39SAndroid Build Coastguard Worker             if (biasedIndices[glyph] != (indices[glyph] + 1024)) {
257*0e209d39SAndroid Build Coastguard Worker                 log_err("biasedIndices[%d] != indices[%d] + 1024: %8X, %8X\n",
258*0e209d39SAndroid Build Coastguard Worker                     glyph, glyph, biasedIndices[glyph], indices[glyph]);
259*0e209d39SAndroid Build Coastguard Worker                 break;
260*0e209d39SAndroid Build Coastguard Worker             }
261*0e209d39SAndroid Build Coastguard Worker         }
262*0e209d39SAndroid Build Coastguard Worker     }
263*0e209d39SAndroid Build Coastguard Worker 
264*0e209d39SAndroid Build Coastguard Worker     status = LE_NO_ERROR;
265*0e209d39SAndroid Build Coastguard Worker     for (glyph = 0; glyph <= glyphCount; glyph += 1) {
266*0e209d39SAndroid Build Coastguard Worker         float x = 0.0, y = 0.0;
267*0e209d39SAndroid Build Coastguard Worker 
268*0e209d39SAndroid Build Coastguard Worker         le_getGlyphPosition(engine, glyph, &x, &y, &status);
269*0e209d39SAndroid Build Coastguard Worker 
270*0e209d39SAndroid Build Coastguard Worker         if (LE_FAILURE(status)) {
271*0e209d39SAndroid Build Coastguard Worker             log_err("getGlyphPosition(%d, x, y, status) failed.\n", glyph);
272*0e209d39SAndroid Build Coastguard Worker             break;
273*0e209d39SAndroid Build Coastguard Worker         }
274*0e209d39SAndroid Build Coastguard Worker 
275*0e209d39SAndroid Build Coastguard Worker         if (x != positions[glyph*2] || y != positions[glyph*2 + 1]) {
276*0e209d39SAndroid Build Coastguard Worker             log_err("getGlyphPosition(%d, x, y, status) returned bad position: (%f, %f) != (%f, %f)\n",
277*0e209d39SAndroid Build Coastguard Worker                 glyph, x, y, positions[glyph*2], positions[glyph*2 + 1]);
278*0e209d39SAndroid Build Coastguard Worker             break;
279*0e209d39SAndroid Build Coastguard Worker         }
280*0e209d39SAndroid Build Coastguard Worker     }
281*0e209d39SAndroid Build Coastguard Worker 
282*0e209d39SAndroid Build Coastguard Worker bail:
283*0e209d39SAndroid Build Coastguard Worker     le_close(engine);
284*0e209d39SAndroid Build Coastguard Worker     le_fontClose(font);
285*0e209d39SAndroid Build Coastguard Worker }
286*0e209d39SAndroid Build Coastguard Worker U_CDECL_END
287*0e209d39SAndroid Build Coastguard Worker 
compareResults(const char * testID,TestResult * expected,TestResult * actual)288*0e209d39SAndroid Build Coastguard Worker static le_bool compareResults(const char *testID, TestResult *expected, TestResult *actual)
289*0e209d39SAndroid Build Coastguard Worker {
290*0e209d39SAndroid Build Coastguard Worker     le_int32 i;
291*0e209d39SAndroid Build Coastguard Worker 
292*0e209d39SAndroid Build Coastguard Worker     /* NOTE: we'll stop on the first failure 'cause once there's one error, it may cascade... */
293*0e209d39SAndroid Build Coastguard Worker     if (actual->glyphCount != expected->glyphCount) {
294*0e209d39SAndroid Build Coastguard Worker         log_err("Test %s: incorrect glyph count: expected %d, got %d\n",
295*0e209d39SAndroid Build Coastguard Worker             testID, expected->glyphCount, actual->glyphCount);
296*0e209d39SAndroid Build Coastguard Worker         return false;
297*0e209d39SAndroid Build Coastguard Worker     }
298*0e209d39SAndroid Build Coastguard Worker 
299*0e209d39SAndroid Build Coastguard Worker     for (i = 0; i < actual->glyphCount; i += 1) {
300*0e209d39SAndroid Build Coastguard Worker         if (actual->glyphs[i] != expected->glyphs[i]) {
301*0e209d39SAndroid Build Coastguard Worker             log_err("Test %s: incorrect id for glyph %d: expected %4X, got %4X\n",
302*0e209d39SAndroid Build Coastguard Worker                 testID, i, expected->glyphs[i], actual->glyphs[i]);
303*0e209d39SAndroid Build Coastguard Worker             return false;
304*0e209d39SAndroid Build Coastguard Worker         }
305*0e209d39SAndroid Build Coastguard Worker     }
306*0e209d39SAndroid Build Coastguard Worker 
307*0e209d39SAndroid Build Coastguard Worker     for (i = 0; i < actual->glyphCount; i += 1) {
308*0e209d39SAndroid Build Coastguard Worker         if (actual->indices[i] != expected->indices[i]) {
309*0e209d39SAndroid Build Coastguard Worker             log_err("Test %s: incorrect index for glyph %d: expected %8X, got %8X\n",
310*0e209d39SAndroid Build Coastguard Worker                 testID, i, expected->indices[i], actual->indices[i]);
311*0e209d39SAndroid Build Coastguard Worker             return false;
312*0e209d39SAndroid Build Coastguard Worker         }
313*0e209d39SAndroid Build Coastguard Worker     }
314*0e209d39SAndroid Build Coastguard Worker 
315*0e209d39SAndroid Build Coastguard Worker     for (i = 0; i <= actual->glyphCount; i += 1) {
316*0e209d39SAndroid Build Coastguard Worker         double xError = uprv_fabs(actual->positions[i * 2] - expected->positions[i * 2]);
317*0e209d39SAndroid Build Coastguard Worker         double yError = uprv_fabs(actual->positions[i * 2 + 1] - expected->positions[i * 2 + 1]);
318*0e209d39SAndroid Build Coastguard Worker 
319*0e209d39SAndroid Build Coastguard Worker         if (xError > 0.0001) {
320*0e209d39SAndroid Build Coastguard Worker             log_err("Test %s: incorrect x position for glyph %d: expected %f, got %f\n",
321*0e209d39SAndroid Build Coastguard Worker                 testID, i, expected->positions[i * 2], actual->positions[i * 2]);
322*0e209d39SAndroid Build Coastguard Worker             return false;
323*0e209d39SAndroid Build Coastguard Worker         }
324*0e209d39SAndroid Build Coastguard Worker 
325*0e209d39SAndroid Build Coastguard Worker         if (yError < 0) {
326*0e209d39SAndroid Build Coastguard Worker             yError = -yError;
327*0e209d39SAndroid Build Coastguard Worker         }
328*0e209d39SAndroid Build Coastguard Worker 
329*0e209d39SAndroid Build Coastguard Worker         if (yError > 0.0001) {
330*0e209d39SAndroid Build Coastguard Worker             log_err("Test %s: incorrect y position for glyph %d: expected %f, got %f\n",
331*0e209d39SAndroid Build Coastguard Worker                 testID, i, expected->positions[i * 2 + 1], actual->positions[i * 2 + 1]);
332*0e209d39SAndroid Build Coastguard Worker             return false;
333*0e209d39SAndroid Build Coastguard Worker         }
334*0e209d39SAndroid Build Coastguard Worker     }
335*0e209d39SAndroid Build Coastguard Worker 
336*0e209d39SAndroid Build Coastguard Worker     return true;
337*0e209d39SAndroid Build Coastguard Worker }
338*0e209d39SAndroid Build Coastguard Worker 
checkFontVersion(le_font * font,const char * testVersionString,le_uint32 testChecksum,const char * testID)339*0e209d39SAndroid Build Coastguard Worker static void checkFontVersion(le_font *font, const char *testVersionString,
340*0e209d39SAndroid Build Coastguard Worker                              le_uint32 testChecksum, const char *testID)
341*0e209d39SAndroid Build Coastguard Worker {
342*0e209d39SAndroid Build Coastguard Worker     le_uint32 fontChecksum = le_getFontChecksum(font);
343*0e209d39SAndroid Build Coastguard Worker 
344*0e209d39SAndroid Build Coastguard Worker     if (fontChecksum != testChecksum) {
345*0e209d39SAndroid Build Coastguard Worker         const char *fontVersionString = le_getNameString(font, NAME_VERSION_STRING,
346*0e209d39SAndroid Build Coastguard Worker             PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
347*0e209d39SAndroid Build Coastguard Worker         const LEUnicode16 *uFontVersionString = NULL;
348*0e209d39SAndroid Build Coastguard Worker 
349*0e209d39SAndroid Build Coastguard Worker         if (fontVersionString == NULL) {
350*0e209d39SAndroid Build Coastguard Worker             uFontVersionString = le_getUnicodeNameString(font, NAME_VERSION_STRING,
351*0e209d39SAndroid Build Coastguard Worker                 PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
352*0e209d39SAndroid Build Coastguard Worker         }
353*0e209d39SAndroid Build Coastguard Worker 
354*0e209d39SAndroid Build Coastguard Worker         log_info("Test %s: this may not be the same font used to generate the test data.\n", testID);
355*0e209d39SAndroid Build Coastguard Worker 
356*0e209d39SAndroid Build Coastguard Worker         if (uFontVersionString != NULL) {
357*0e209d39SAndroid Build Coastguard Worker             log_info("Your font's version string is \"%S\"\n", uFontVersionString);
358*0e209d39SAndroid Build Coastguard Worker             le_deleteUnicodeNameString(font, uFontVersionString);
359*0e209d39SAndroid Build Coastguard Worker         } else {
360*0e209d39SAndroid Build Coastguard Worker             log_info("Your font's version string is \"%s\"\n", fontVersionString);
361*0e209d39SAndroid Build Coastguard Worker             le_deleteNameString(font, fontVersionString);
362*0e209d39SAndroid Build Coastguard Worker         }
363*0e209d39SAndroid Build Coastguard Worker 
364*0e209d39SAndroid Build Coastguard Worker         log_info("The expected version string is \"%s\"\n", testVersionString);
365*0e209d39SAndroid Build Coastguard Worker         log_info("If you see errors, they may be due to the version of the font you're using.\n");
366*0e209d39SAndroid Build Coastguard Worker     }
367*0e209d39SAndroid Build Coastguard Worker }
368*0e209d39SAndroid Build Coastguard Worker 
369*0e209d39SAndroid Build Coastguard Worker /* Returns the path to icu/source/test/testdata/ */
getSourceTestData()370*0e209d39SAndroid Build Coastguard Worker static const char *getSourceTestData() {
371*0e209d39SAndroid Build Coastguard Worker #ifdef U_TOPSRCDIR
372*0e209d39SAndroid Build Coastguard Worker     const char *srcDataDir = U_TOPSRCDIR U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
373*0e209d39SAndroid Build Coastguard Worker #else
374*0e209d39SAndroid Build Coastguard Worker     const char *srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
375*0e209d39SAndroid Build Coastguard Worker     FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
376*0e209d39SAndroid Build Coastguard Worker 
377*0e209d39SAndroid Build Coastguard Worker     if (f != NULL) {
378*0e209d39SAndroid Build Coastguard Worker         /* We're in icu/source/test/letest/ */
379*0e209d39SAndroid Build Coastguard Worker         fclose(f);
380*0e209d39SAndroid Build Coastguard Worker     } else {
381*0e209d39SAndroid Build Coastguard Worker         /* We're in icu/source/test/letest/(Debug|Release) */
382*0e209d39SAndroid Build Coastguard Worker         srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
383*0e209d39SAndroid Build Coastguard Worker     }
384*0e209d39SAndroid Build Coastguard Worker #endif
385*0e209d39SAndroid Build Coastguard Worker 
386*0e209d39SAndroid Build Coastguard Worker     return srcDataDir;
387*0e209d39SAndroid Build Coastguard Worker }
388*0e209d39SAndroid Build Coastguard Worker 
getPath(char buffer[2048],const char * filename)389*0e209d39SAndroid Build Coastguard Worker static const char *getPath(char buffer[2048], const char *filename) {
390*0e209d39SAndroid Build Coastguard Worker     const char *testDataDirectory = getSourceTestData();
391*0e209d39SAndroid Build Coastguard Worker 
392*0e209d39SAndroid Build Coastguard Worker     strcpy(buffer, testDataDirectory);
393*0e209d39SAndroid Build Coastguard Worker     strcat(buffer, filename);
394*0e209d39SAndroid Build Coastguard Worker 
395*0e209d39SAndroid Build Coastguard Worker     return buffer;
396*0e209d39SAndroid Build Coastguard Worker }
397*0e209d39SAndroid Build Coastguard Worker 
openFont(const char * fontName,const char * checksum,const char * version,const char * testID)398*0e209d39SAndroid Build Coastguard Worker static le_font *openFont(const char *fontName, const char *checksum, const char *version, const char *testID)
399*0e209d39SAndroid Build Coastguard Worker {
400*0e209d39SAndroid Build Coastguard Worker     char path[2048];
401*0e209d39SAndroid Build Coastguard Worker     le_font *font;
402*0e209d39SAndroid Build Coastguard Worker     LEErrorCode fontStatus = LE_NO_ERROR;
403*0e209d39SAndroid Build Coastguard Worker 
404*0e209d39SAndroid Build Coastguard Worker 	if (fontName != NULL) {
405*0e209d39SAndroid Build Coastguard Worker 		font = le_portableFontOpen(getPath(path, fontName), 12, &fontStatus);
406*0e209d39SAndroid Build Coastguard Worker 
407*0e209d39SAndroid Build Coastguard Worker 		if (LE_FAILURE(fontStatus)) {
408*0e209d39SAndroid Build Coastguard Worker 			log_info("Test %s: can't open font %s - test skipped.\n", testID, fontName);
409*0e209d39SAndroid Build Coastguard Worker 			le_fontClose(font);
410*0e209d39SAndroid Build Coastguard Worker 			return NULL;
411*0e209d39SAndroid Build Coastguard Worker 		} else {
412*0e209d39SAndroid Build Coastguard Worker 			le_uint32 cksum = 0;
413*0e209d39SAndroid Build Coastguard Worker 
414*0e209d39SAndroid Build Coastguard Worker 			sscanf(checksum, "%x", &cksum);
415*0e209d39SAndroid Build Coastguard Worker 
416*0e209d39SAndroid Build Coastguard Worker 			checkFontVersion(font, version, cksum, testID);
417*0e209d39SAndroid Build Coastguard Worker 		}
418*0e209d39SAndroid Build Coastguard Worker 	} else {
419*0e209d39SAndroid Build Coastguard Worker 		font = le_simpleFontOpen(12, &fontStatus);
420*0e209d39SAndroid Build Coastguard Worker 	}
421*0e209d39SAndroid Build Coastguard Worker 
422*0e209d39SAndroid Build Coastguard Worker     return font;
423*0e209d39SAndroid Build Coastguard Worker }
424*0e209d39SAndroid Build Coastguard Worker 
getRTL(const LEUnicode * text,le_int32 charCount)425*0e209d39SAndroid Build Coastguard Worker static le_bool getRTL(const LEUnicode *text, le_int32 charCount)
426*0e209d39SAndroid Build Coastguard Worker {
427*0e209d39SAndroid Build Coastguard Worker     UBiDiLevel level;
428*0e209d39SAndroid Build Coastguard Worker     le_int32 limit = -1;
429*0e209d39SAndroid Build Coastguard Worker     UErrorCode status = U_ZERO_ERROR;
430*0e209d39SAndroid Build Coastguard Worker     UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
431*0e209d39SAndroid Build Coastguard Worker 
432*0e209d39SAndroid Build Coastguard Worker     ubidi_setPara(ubidi, text, charCount, UBIDI_DEFAULT_LTR, NULL, &status);
433*0e209d39SAndroid Build Coastguard Worker 
434*0e209d39SAndroid Build Coastguard Worker     /* TODO: Should check that there's only a single logical run... */
435*0e209d39SAndroid Build Coastguard Worker     ubidi_getLogicalRun(ubidi, 0, &limit, &level);
436*0e209d39SAndroid Build Coastguard Worker 
437*0e209d39SAndroid Build Coastguard Worker     ubidi_close(ubidi);
438*0e209d39SAndroid Build Coastguard Worker 
439*0e209d39SAndroid Build Coastguard Worker     return level & 1;
440*0e209d39SAndroid Build Coastguard Worker }
441*0e209d39SAndroid Build Coastguard Worker 
doTestCase(const char * testID,const char * fontName,const char * fontVersion,const char * fontChecksum,le_int32 scriptCode,le_int32 languageCode,const LEUnicode * text,le_int32 charCount,TestResult * expected)442*0e209d39SAndroid Build Coastguard Worker static void doTestCase (const char *testID,
443*0e209d39SAndroid Build Coastguard Worker 				 const char *fontName,
444*0e209d39SAndroid Build Coastguard Worker 				 const char *fontVersion,
445*0e209d39SAndroid Build Coastguard Worker 				 const char *fontChecksum,
446*0e209d39SAndroid Build Coastguard Worker 				 le_int32 scriptCode,
447*0e209d39SAndroid Build Coastguard Worker 				 le_int32 languageCode,
448*0e209d39SAndroid Build Coastguard Worker 				 const LEUnicode *text,
449*0e209d39SAndroid Build Coastguard Worker 				 le_int32 charCount,
450*0e209d39SAndroid Build Coastguard Worker 				 TestResult *expected)
451*0e209d39SAndroid Build Coastguard Worker {
452*0e209d39SAndroid Build Coastguard Worker 	LEErrorCode status = LE_NO_ERROR;
453*0e209d39SAndroid Build Coastguard Worker 	le_engine *engine;
454*0e209d39SAndroid Build Coastguard Worker 	le_font *font = openFont(fontName, fontChecksum, fontVersion, testID);
455*0e209d39SAndroid Build Coastguard Worker 	le_int32 typoFlags = 3; /* kerning + ligatures */
456*0e209d39SAndroid Build Coastguard Worker 	TestResult actual;
457*0e209d39SAndroid Build Coastguard Worker 
458*0e209d39SAndroid Build Coastguard Worker 	if (font == NULL) {
459*0e209d39SAndroid Build Coastguard Worker 		/* error message already printed. */
460*0e209d39SAndroid Build Coastguard Worker 		return;
461*0e209d39SAndroid Build Coastguard Worker 	}
462*0e209d39SAndroid Build Coastguard Worker 
463*0e209d39SAndroid Build Coastguard Worker 	if (fontName == NULL) {
464*0e209d39SAndroid Build Coastguard Worker 		typoFlags |= 0x80000000L;  /* use CharSubstitutionFilter... */
465*0e209d39SAndroid Build Coastguard Worker 	}
466*0e209d39SAndroid Build Coastguard Worker 
467*0e209d39SAndroid Build Coastguard Worker     engine = le_create(font, scriptCode, languageCode, typoFlags, &status);
468*0e209d39SAndroid Build Coastguard Worker 
469*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
470*0e209d39SAndroid Build Coastguard Worker         log_err("Test %s: could not create a LayoutEngine.\n", testID);
471*0e209d39SAndroid Build Coastguard Worker         goto free_expected;
472*0e209d39SAndroid Build Coastguard Worker     }
473*0e209d39SAndroid Build Coastguard Worker 
474*0e209d39SAndroid Build Coastguard Worker     actual.glyphCount = le_layoutChars(engine, text, 0, charCount, charCount, getRTL(text, charCount), 0, 0, &status);
475*0e209d39SAndroid Build Coastguard Worker 
476*0e209d39SAndroid Build Coastguard Worker     actual.glyphs    = NEW_ARRAY(LEGlyphID, actual.glyphCount);
477*0e209d39SAndroid Build Coastguard Worker     actual.indices   = NEW_ARRAY(le_int32, actual.glyphCount);
478*0e209d39SAndroid Build Coastguard Worker     actual.positions = NEW_ARRAY(float, actual.glyphCount * 2 + 2);
479*0e209d39SAndroid Build Coastguard Worker 
480*0e209d39SAndroid Build Coastguard Worker     le_getGlyphs(engine, actual.glyphs, &status);
481*0e209d39SAndroid Build Coastguard Worker     le_getCharIndices(engine, actual.indices, &status);
482*0e209d39SAndroid Build Coastguard Worker     le_getGlyphPositions(engine, actual.positions, &status);
483*0e209d39SAndroid Build Coastguard Worker 
484*0e209d39SAndroid Build Coastguard Worker     compareResults(testID, expected, &actual);
485*0e209d39SAndroid Build Coastguard Worker 
486*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(actual.positions);
487*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(actual.indices);
488*0e209d39SAndroid Build Coastguard Worker     DELETE_ARRAY(actual.glyphs);
489*0e209d39SAndroid Build Coastguard Worker 
490*0e209d39SAndroid Build Coastguard Worker     le_close(engine);
491*0e209d39SAndroid Build Coastguard Worker 
492*0e209d39SAndroid Build Coastguard Worker free_expected:
493*0e209d39SAndroid Build Coastguard Worker     le_fontClose(font);
494*0e209d39SAndroid Build Coastguard Worker }
495*0e209d39SAndroid Build Coastguard Worker 
DataDrivenTest(void)496*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV DataDrivenTest(void)
497*0e209d39SAndroid Build Coastguard Worker {
498*0e209d39SAndroid Build Coastguard Worker     char path[2048];
499*0e209d39SAndroid Build Coastguard Worker     const char *testFilePath = getPath(path, "letest.xml");
500*0e209d39SAndroid Build Coastguard Worker 
501*0e209d39SAndroid Build Coastguard Worker 	readTestFile(testFilePath, doTestCase);
502*0e209d39SAndroid Build Coastguard Worker }
503*0e209d39SAndroid Build Coastguard Worker 
504*0e209d39SAndroid Build Coastguard Worker /*
505*0e209d39SAndroid Build Coastguard Worker  * From ticket:5923:
506*0e209d39SAndroid Build Coastguard Worker  *
507*0e209d39SAndroid Build Coastguard Worker  * Build a paragraph that contains a mixture of left to right and right to left text.
508*0e209d39SAndroid Build Coastguard Worker  * Break it into multiple lines and make sure that the glyphToCharMap for run in each
509*0e209d39SAndroid Build Coastguard Worker  * line is correct.
510*0e209d39SAndroid Build Coastguard Worker  *
511*0e209d39SAndroid Build Coastguard Worker  * Note: it might be a good idea to also check the glyphs and positions for each run,
512*0e209d39SAndroid Build Coastguard Worker  * that we get the expected number of runs per line and that the line breaks are where
513*0e209d39SAndroid Build Coastguard Worker  * we expect them to be. Really, it would be a good idea to make a whole test suite
514*0e209d39SAndroid Build Coastguard Worker  * for pl_paragraph.
515*0e209d39SAndroid Build Coastguard Worker  */
GlyphToCharTest(void)516*0e209d39SAndroid Build Coastguard Worker static void U_CALLCONV GlyphToCharTest(void)
517*0e209d39SAndroid Build Coastguard Worker {
518*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_BREAK_ITERATION
519*0e209d39SAndroid Build Coastguard Worker     LEErrorCode status = LE_NO_ERROR;
520*0e209d39SAndroid Build Coastguard Worker     le_font *font;
521*0e209d39SAndroid Build Coastguard Worker     pl_fontRuns *fontRuns;
522*0e209d39SAndroid Build Coastguard Worker     pl_paragraph *paragraph;
523*0e209d39SAndroid Build Coastguard Worker     const pl_line *line;
524*0e209d39SAndroid Build Coastguard Worker     /*
525*0e209d39SAndroid Build Coastguard Worker      * This is the same text that's in <icu>/source/samples/layout/Sample.txt
526*0e209d39SAndroid Build Coastguard Worker      */
527*0e209d39SAndroid Build Coastguard Worker     LEUnicode chars[] = {
528*0e209d39SAndroid Build Coastguard Worker         /*BOM*/ 0x0054, 0x0068, 0x0065, 0x0020, 0x004c, 0x0061, 0x0079,
529*0e209d39SAndroid Build Coastguard Worker         0x006f, 0x0075, 0x0074, 0x0045, 0x006e, 0x0067, 0x0069, 0x006e,
530*0e209d39SAndroid Build Coastguard Worker         0x0065, 0x0020, 0x0064, 0x006f, 0x0065, 0x0073, 0x0020, 0x0061,
531*0e209d39SAndroid Build Coastguard Worker         0x006c, 0x006c, 0x0020, 0x0074, 0x0068, 0x0065, 0x0020, 0x0077,
532*0e209d39SAndroid Build Coastguard Worker         0x006f, 0x0072, 0x006b, 0x0020, 0x006e, 0x0065, 0x0063, 0x0065,
533*0e209d39SAndroid Build Coastguard Worker         0x0073, 0x0073, 0x0061, 0x0072, 0x0079, 0x0020, 0x0074, 0x006f,
534*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0064, 0x0069, 0x0073, 0x0070, 0x006c, 0x0061, 0x0079,
535*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0055, 0x006e, 0x0069, 0x0063, 0x006f, 0x0064, 0x0065,
536*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x0020, 0x0077, 0x0072,
537*0e209d39SAndroid Build Coastguard Worker         0x0069, 0x0074, 0x0074, 0x0065, 0x006e, 0x0020, 0x0069, 0x006e,
538*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x006c, 0x0061, 0x006e, 0x0067, 0x0075, 0x0061, 0x0067,
539*0e209d39SAndroid Build Coastguard Worker         0x0065, 0x0073, 0x0020, 0x0077, 0x0069, 0x0074, 0x0068, 0x0020,
540*0e209d39SAndroid Build Coastguard Worker         0x0063, 0x006f, 0x006d, 0x0070, 0x006c, 0x0065, 0x0078, 0x0020,
541*0e209d39SAndroid Build Coastguard Worker         0x0077, 0x0072, 0x0069, 0x0074, 0x0069, 0x006e, 0x0067, 0x0020,
542*0e209d39SAndroid Build Coastguard Worker         0x0073, 0x0079, 0x0073, 0x0074, 0x0065, 0x006d, 0x0073, 0x0020,
543*0e209d39SAndroid Build Coastguard Worker         0x0073, 0x0075, 0x0063, 0x0068, 0x0020, 0x0061, 0x0073, 0x0020,
544*0e209d39SAndroid Build Coastguard Worker         0x0048, 0x0069, 0x006e, 0x0064, 0x0069, 0x0020, 0x0028, 0x0939,
545*0e209d39SAndroid Build Coastguard Worker         0x093f, 0x0928, 0x094d, 0x0926, 0x0940, 0x0029, 0x0020, 0x0054,
546*0e209d39SAndroid Build Coastguard Worker         0x0068, 0x0061, 0x0069, 0x0020, 0x0028, 0x0e44, 0x0e17, 0x0e22,
547*0e209d39SAndroid Build Coastguard Worker         0x0029, 0x0020, 0x0061, 0x006e, 0x0064, 0x0020, 0x0041, 0x0072,
548*0e209d39SAndroid Build Coastguard Worker         0x0061, 0x0062, 0x0069, 0x0063, 0x0020, 0x0028, 0x0627, 0x0644,
549*0e209d39SAndroid Build Coastguard Worker         0x0639, 0x0631, 0x0628, 0x064a, 0x0629, 0x0029, 0x002e, 0x0020,
550*0e209d39SAndroid Build Coastguard Worker         0x0048, 0x0065, 0x0072, 0x0065, 0x0027, 0x0073, 0x0020, 0x0061,
551*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0073, 0x0061, 0x006d, 0x0070, 0x006c, 0x0065, 0x0020,
552*0e209d39SAndroid Build Coastguard Worker         0x006f, 0x0066, 0x0020, 0x0073, 0x006f, 0x006d, 0x0065, 0x0020,
553*0e209d39SAndroid Build Coastguard Worker         0x0074, 0x0065, 0x0078, 0x0074, 0x0020, 0x0077, 0x0072, 0x0069,
554*0e209d39SAndroid Build Coastguard Worker         0x0074, 0x0074, 0x0065, 0x006e, 0x0020, 0x0069, 0x006e, 0x0020,
555*0e209d39SAndroid Build Coastguard Worker         0x0053, 0x0061, 0x006e, 0x0073, 0x006b, 0x0072, 0x0069, 0x0074,
556*0e209d39SAndroid Build Coastguard Worker         0x003a, 0x0020, 0x0936, 0x094d, 0x0930, 0x0940, 0x092e, 0x0926,
557*0e209d39SAndroid Build Coastguard Worker         0x094d, 0x0020, 0x092d, 0x0917, 0x0935, 0x0926, 0x094d, 0x0917,
558*0e209d39SAndroid Build Coastguard Worker         0x0940, 0x0924, 0x093e, 0x0020, 0x0905, 0x0927, 0x094d, 0x092f,
559*0e209d39SAndroid Build Coastguard Worker         0x093e, 0x092f, 0x0020, 0x0905, 0x0930, 0x094d, 0x091c, 0x0941,
560*0e209d39SAndroid Build Coastguard Worker         0x0928, 0x0020, 0x0935, 0x093f, 0x0937, 0x093e, 0x0926, 0x0020,
561*0e209d39SAndroid Build Coastguard Worker         0x092f, 0x094b, 0x0917, 0x0020, 0x0927, 0x0943, 0x0924, 0x0930,
562*0e209d39SAndroid Build Coastguard Worker         0x093e, 0x0937, 0x094d, 0x091f, 0x094d, 0x0930, 0x0020, 0x0909,
563*0e209d39SAndroid Build Coastguard Worker         0x0935, 0x093e, 0x091a, 0x0964, 0x0020, 0x0927, 0x0930, 0x094d,
564*0e209d39SAndroid Build Coastguard Worker         0x092e, 0x0915, 0x094d, 0x0937, 0x0947, 0x0924, 0x094d, 0x0930,
565*0e209d39SAndroid Build Coastguard Worker         0x0947, 0x0020, 0x0915, 0x0941, 0x0930, 0x0941, 0x0915, 0x094d,
566*0e209d39SAndroid Build Coastguard Worker         0x0937, 0x0947, 0x0924, 0x094d, 0x0930, 0x0947, 0x0020, 0x0938,
567*0e209d39SAndroid Build Coastguard Worker         0x092e, 0x0935, 0x0947, 0x0924, 0x093e, 0x0020, 0x092f, 0x0941,
568*0e209d39SAndroid Build Coastguard Worker         0x092f, 0x0941, 0x0924, 0x094d, 0x0938, 0x0935, 0x0903, 0x0020,
569*0e209d39SAndroid Build Coastguard Worker         0x092e, 0x093e, 0x092e, 0x0915, 0x093e, 0x0903, 0x0020, 0x092a,
570*0e209d39SAndroid Build Coastguard Worker         0x093e, 0x0923, 0x094d, 0x0921, 0x0935, 0x093e, 0x0936, 0x094d,
571*0e209d39SAndroid Build Coastguard Worker         0x091a, 0x0948, 0x0935, 0x0020, 0x0915, 0x093f, 0x092e, 0x0915,
572*0e209d39SAndroid Build Coastguard Worker         0x0941, 0x0930, 0x094d, 0x0935, 0x0924, 0x0020, 0x0938, 0x0902,
573*0e209d39SAndroid Build Coastguard Worker         0x091c, 0x092f, 0x0020, 0x0048, 0x0065, 0x0072, 0x0065, 0x0027,
574*0e209d39SAndroid Build Coastguard Worker         0x0073, 0x0020, 0x0061, 0x0020, 0x0073, 0x0061, 0x006d, 0x0070,
575*0e209d39SAndroid Build Coastguard Worker         0x006c, 0x0065, 0x0020, 0x006f, 0x0066, 0x0020, 0x0073, 0x006f,
576*0e209d39SAndroid Build Coastguard Worker         0x006d, 0x0065, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x0020,
577*0e209d39SAndroid Build Coastguard Worker         0x0077, 0x0072, 0x0069, 0x0074, 0x0074, 0x0065, 0x006e, 0x0020,
578*0e209d39SAndroid Build Coastguard Worker         0x0069, 0x006e, 0x0020, 0x0041, 0x0072, 0x0061, 0x0062, 0x0069,
579*0e209d39SAndroid Build Coastguard Worker         0x0063, 0x003a, 0x0020, 0x0623, 0x0633, 0x0627, 0x0633, 0x064b,
580*0e209d39SAndroid Build Coastguard Worker         0x0627, 0x060c, 0x0020, 0x062a, 0x062a, 0x0639, 0x0627, 0x0645,
581*0e209d39SAndroid Build Coastguard Worker         0x0644, 0x0020, 0x0627, 0x0644, 0x062d, 0x0648, 0x0627, 0x0633,
582*0e209d39SAndroid Build Coastguard Worker         0x064a, 0x0628, 0x0020, 0x0641, 0x0642, 0x0637, 0x0020, 0x0645,
583*0e209d39SAndroid Build Coastguard Worker         0x0639, 0x0020, 0x0627, 0x0644, 0x0623, 0x0631, 0x0642, 0x0627,
584*0e209d39SAndroid Build Coastguard Worker         0x0645, 0x060c, 0x0020, 0x0648, 0x062a, 0x0642, 0x0648, 0x0645,
585*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0628, 0x062a, 0x062e, 0x0632, 0x064a, 0x0646, 0x0020,
586*0e209d39SAndroid Build Coastguard Worker         0x0627, 0x0644, 0x0623, 0x062d, 0x0631, 0x0641, 0x0020, 0x0648,
587*0e209d39SAndroid Build Coastguard Worker         0x0627, 0x0644, 0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x0020,
588*0e209d39SAndroid Build Coastguard Worker         0x0627, 0x0644, 0x0623, 0x062e, 0x0631, 0x0649, 0x0020, 0x0628,
589*0e209d39SAndroid Build Coastguard Worker         0x0639, 0x062f, 0x0020, 0x0623, 0x0646, 0x0020, 0x062a, 0x064f,
590*0e209d39SAndroid Build Coastguard Worker         0x0639, 0x0637, 0x064a, 0x0020, 0x0631, 0x0642, 0x0645, 0x0627,
591*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0645, 0x0639, 0x064a, 0x0646, 0x0627, 0x0020, 0x0644,
592*0e209d39SAndroid Build Coastguard Worker         0x0643, 0x0644, 0x0020, 0x0648, 0x0627, 0x062d, 0x062f, 0x0020,
593*0e209d39SAndroid Build Coastguard Worker         0x0645, 0x0646, 0x0647, 0x0627, 0x002e, 0x0020, 0x0648, 0x0642,
594*0e209d39SAndroid Build Coastguard Worker         0x0628, 0x0644, 0x0020, 0x0627, 0x062e, 0x062a, 0x0631, 0x0627,
595*0e209d39SAndroid Build Coastguard Worker         0x0639, 0x0020, 0x0022, 0x064a, 0x0648, 0x0646, 0x0650, 0x0643,
596*0e209d39SAndroid Build Coastguard Worker         0x0648, 0x062f, 0x0022, 0x060c, 0x0020, 0x0643, 0x0627, 0x0646,
597*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0647, 0x0646, 0x0627, 0x0643, 0x0020, 0x0645, 0x0626,
598*0e209d39SAndroid Build Coastguard Worker         0x0627, 0x062a, 0x0020, 0x0627, 0x0644, 0x0623, 0x0646, 0x0638,
599*0e209d39SAndroid Build Coastguard Worker         0x0645, 0x0629, 0x0020, 0x0644, 0x0644, 0x062a, 0x0634, 0x0641,
600*0e209d39SAndroid Build Coastguard Worker         0x064a, 0x0631, 0x0020, 0x0648, 0x062a, 0x062e, 0x0635, 0x064a,
601*0e209d39SAndroid Build Coastguard Worker         0x0635, 0x0020, 0x0647, 0x0630, 0x0647, 0x0020, 0x0627, 0x0644,
602*0e209d39SAndroid Build Coastguard Worker         0x0623, 0x0631, 0x0642, 0x0627, 0x0645, 0x0020, 0x0644, 0x0644,
603*0e209d39SAndroid Build Coastguard Worker         0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x060c, 0x0020, 0x0648,
604*0e209d39SAndroid Build Coastguard Worker         0x0644, 0x0645, 0x0020, 0x064a, 0x0648, 0x062c, 0x062f, 0x0020,
605*0e209d39SAndroid Build Coastguard Worker         0x0646, 0x0638, 0x0627, 0x0645, 0x0020, 0x062a, 0x0634, 0x0641,
606*0e209d39SAndroid Build Coastguard Worker         0x064a, 0x0631, 0x0020, 0x0648, 0x0627, 0x062d, 0x062f, 0x0020,
607*0e209d39SAndroid Build Coastguard Worker         0x064a, 0x062d, 0x062a, 0x0648, 0x064a, 0x0020, 0x0639, 0x0644,
608*0e209d39SAndroid Build Coastguard Worker         0x0649, 0x0020, 0x062c, 0x0645, 0x064a, 0x0639, 0x0020, 0x0627,
609*0e209d39SAndroid Build Coastguard Worker         0x0644, 0x0645, 0x062d, 0x0627, 0x0631, 0x0641, 0x0020, 0x0627,
610*0e209d39SAndroid Build Coastguard Worker         0x0644, 0x0636, 0x0631, 0x0648, 0x0631, 0x064a, 0x0629, 0x0020,
611*0e209d39SAndroid Build Coastguard Worker         0x0061, 0x006e, 0x0064, 0x0020, 0x0068, 0x0065, 0x0072, 0x0065,
612*0e209d39SAndroid Build Coastguard Worker         0x0027, 0x0073, 0x0020, 0x0061, 0x0020, 0x0073, 0x0061, 0x006d,
613*0e209d39SAndroid Build Coastguard Worker         0x0070, 0x006c, 0x0065, 0x0020, 0x006f, 0x0066, 0x0020, 0x0073,
614*0e209d39SAndroid Build Coastguard Worker         0x006f, 0x006d, 0x0065, 0x0020, 0x0074, 0x0065, 0x0078, 0x0074,
615*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0077, 0x0072, 0x0069, 0x0074, 0x0074, 0x0065, 0x006e,
616*0e209d39SAndroid Build Coastguard Worker         0x0020, 0x0069, 0x006e, 0x0020, 0x0054, 0x0068, 0x0061, 0x0069,
617*0e209d39SAndroid Build Coastguard Worker         0x003a, 0x0020, 0x0e1a, 0x0e17, 0x0e17, 0x0e35, 0x0e48, 0x0e51,
618*0e209d39SAndroid Build Coastguard Worker         0x0e1e, 0x0e32, 0x0e22, 0x0e38, 0x0e44, 0x0e0b, 0x0e42, 0x0e04,
619*0e209d39SAndroid Build Coastguard Worker         0x0e25, 0x0e19, 0x0e42, 0x0e14, 0x0e42, 0x0e23, 0x0e18, 0x0e35,
620*0e209d39SAndroid Build Coastguard Worker         0x0e2d, 0x0e32, 0x0e28, 0x0e31, 0x0e22, 0x0e2d, 0x0e22, 0x0e39,
621*0e209d39SAndroid Build Coastguard Worker         0x0e48, 0x0e17, 0x0e48, 0x0e32, 0x0e21, 0x0e01, 0x0e25, 0x0e32,
622*0e209d39SAndroid Build Coastguard Worker         0x0e07, 0x0e17, 0x0e38, 0x0e48, 0x0e07, 0x0e43, 0x0e2b, 0x0e0d,
623*0e209d39SAndroid Build Coastguard Worker         0x0e48, 0x0e43, 0x0e19, 0x0e41, 0x0e04, 0x0e19, 0x0e0b, 0x0e31,
624*0e209d39SAndroid Build Coastguard Worker         0x0e2a, 0x0e01, 0x0e31, 0x0e1a, 0x0e25, 0x0e38, 0x0e07, 0x0e40,
625*0e209d39SAndroid Build Coastguard Worker         0x0e2e, 0x0e19, 0x0e23, 0x0e35, 0x0e0a, 0x0e32, 0x0e27, 0x0e44,
626*0e209d39SAndroid Build Coastguard Worker         0x0e23, 0x0e48, 0x0e41, 0x0e25, 0x0e30, 0x0e1b, 0x0e49, 0x0e32,
627*0e209d39SAndroid Build Coastguard Worker         0x0e40, 0x0e2d, 0x0e47, 0x0e21, 0x0e20, 0x0e23, 0x0e23, 0x0e22,
628*0e209d39SAndroid Build Coastguard Worker         0x0e32, 0x0e0a, 0x0e32, 0x0e27, 0x0e44, 0x0e23, 0x0e48, 0x0e1a,
629*0e209d39SAndroid Build Coastguard Worker         0x0e49, 0x0e32, 0x0e19, 0x0e02, 0x0e2d, 0x0e07, 0x0e1e, 0x0e27,
630*0e209d39SAndroid Build Coastguard Worker         0x0e01, 0x0e40, 0x0e02, 0x0e32, 0x0e2b, 0x0e25, 0x0e31, 0x0e07,
631*0e209d39SAndroid Build Coastguard Worker         0x0e40, 0x0e25, 0x0e47, 0x0e01, 0x0e40, 0x0e1e, 0x0e23, 0x0e32,
632*0e209d39SAndroid Build Coastguard Worker         0x0e30, 0x0e44, 0x0e21, 0x0e49, 0x0e2a, 0x0e23, 0x0e49, 0x0e32,
633*0e209d39SAndroid Build Coastguard Worker         0x0e07, 0x0e1a, 0x0e49, 0x0e32, 0x0e19, 0x0e15, 0x0e49, 0x0e2d,
634*0e209d39SAndroid Build Coastguard Worker         0x0e07, 0x0e02, 0x0e19, 0x0e21, 0x0e32, 0x0e14, 0x0e49, 0x0e27,
635*0e209d39SAndroid Build Coastguard Worker         0x0e22, 0x0e40, 0x0e01, 0x0e27, 0x0e35, 0x0e22, 0x0e19, 0x0e40,
636*0e209d39SAndroid Build Coastguard Worker         0x0e1b, 0x0e47, 0x0e19, 0x0e23, 0x0e30, 0x0e22, 0x0e30, 0x0e17,
637*0e209d39SAndroid Build Coastguard Worker         0x0e32, 0x0e07, 0x0e2b, 0x0e25, 0x0e32, 0x0e22, 0x0e44, 0x0e21,
638*0e209d39SAndroid Build Coastguard Worker         0x0e25, 0x0e4c
639*0e209d39SAndroid Build Coastguard Worker     };
640*0e209d39SAndroid Build Coastguard Worker     le_int32 charCount = LE_ARRAY_SIZE(chars);
641*0e209d39SAndroid Build Coastguard Worker     le_int32 charIndex = 0, lineNumber = 1;
642*0e209d39SAndroid Build Coastguard Worker     le_int32 run, i;
643*0e209d39SAndroid Build Coastguard Worker     const float lineWidth = 600;
644*0e209d39SAndroid Build Coastguard Worker 
645*0e209d39SAndroid Build Coastguard Worker     font = le_simpleFontOpen(12, &status);
646*0e209d39SAndroid Build Coastguard Worker 
647*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
648*0e209d39SAndroid Build Coastguard Worker         log_err("le_simpleFontOpen(12, &status) failed");
649*0e209d39SAndroid Build Coastguard Worker         goto finish;
650*0e209d39SAndroid Build Coastguard Worker     }
651*0e209d39SAndroid Build Coastguard Worker 
652*0e209d39SAndroid Build Coastguard Worker     fontRuns = pl_openEmptyFontRuns(0);
653*0e209d39SAndroid Build Coastguard Worker     pl_addFontRun(fontRuns, font, charCount);
654*0e209d39SAndroid Build Coastguard Worker 
655*0e209d39SAndroid Build Coastguard Worker     paragraph = pl_create(chars, charCount, fontRuns, NULL, NULL, NULL, 0, false, &status);
656*0e209d39SAndroid Build Coastguard Worker 
657*0e209d39SAndroid Build Coastguard Worker     pl_closeFontRuns(fontRuns);
658*0e209d39SAndroid Build Coastguard Worker 
659*0e209d39SAndroid Build Coastguard Worker     if (LE_FAILURE(status)) {
660*0e209d39SAndroid Build Coastguard Worker         log_err("pl_create failed.");
661*0e209d39SAndroid Build Coastguard Worker         goto close_font;
662*0e209d39SAndroid Build Coastguard Worker     }
663*0e209d39SAndroid Build Coastguard Worker 
664*0e209d39SAndroid Build Coastguard Worker     pl_reflow(paragraph);
665*0e209d39SAndroid Build Coastguard Worker     while ((line = pl_nextLine(paragraph, lineWidth)) != NULL) {
666*0e209d39SAndroid Build Coastguard Worker         le_int32 runCount = pl_countLineRuns(line);
667*0e209d39SAndroid Build Coastguard Worker 
668*0e209d39SAndroid Build Coastguard Worker         for(run = 0; run < runCount; run += 1) {
669*0e209d39SAndroid Build Coastguard Worker             const pl_visualRun *visualRun = pl_getLineVisualRun(line, run);
670*0e209d39SAndroid Build Coastguard Worker             const le_int32 glyphCount = pl_getVisualRunGlyphCount(visualRun);
671*0e209d39SAndroid Build Coastguard Worker             const le_int32 *glyphToCharMap = pl_getVisualRunGlyphToCharMap(visualRun);
672*0e209d39SAndroid Build Coastguard Worker 
673*0e209d39SAndroid Build Coastguard Worker             if (pl_getVisualRunDirection(visualRun) == UBIDI_RTL) {
674*0e209d39SAndroid Build Coastguard Worker                 /*
675*0e209d39SAndroid Build Coastguard Worker                  * For a right to left run, make sure that the character indices
676*0e209d39SAndroid Build Coastguard Worker                  * increase from the right most glyph to the left most glyph. If
677*0e209d39SAndroid Build Coastguard Worker                  * there are any one to many glyph substitutions, we might get several
678*0e209d39SAndroid Build Coastguard Worker                  * glyphs in a row with the same character index.
679*0e209d39SAndroid Build Coastguard Worker                  */
680*0e209d39SAndroid Build Coastguard Worker                 for(i = glyphCount - 1; i >= 0; i -= 1) {
681*0e209d39SAndroid Build Coastguard Worker                     le_int32 ix = glyphToCharMap[i];
682*0e209d39SAndroid Build Coastguard Worker 
683*0e209d39SAndroid Build Coastguard Worker                     if (ix != charIndex) {
684*0e209d39SAndroid Build Coastguard Worker                         if (ix != charIndex - 1) {
685*0e209d39SAndroid Build Coastguard Worker                             log_err("Bad glyph to char index for glyph %d on line %d: expected %d, got %d\n",
686*0e209d39SAndroid Build Coastguard Worker                                 i, lineNumber, charIndex, ix);
687*0e209d39SAndroid Build Coastguard Worker                             goto close_paragraph; /* once there's one error, we can't count on anything else... */
688*0e209d39SAndroid Build Coastguard Worker                         }
689*0e209d39SAndroid Build Coastguard Worker                     } else {
690*0e209d39SAndroid Build Coastguard Worker                         charIndex += 1;
691*0e209d39SAndroid Build Coastguard Worker                     }
692*0e209d39SAndroid Build Coastguard Worker                 }
693*0e209d39SAndroid Build Coastguard Worker             } else {
694*0e209d39SAndroid Build Coastguard Worker                 /*
695*0e209d39SAndroid Build Coastguard Worker                  * We can't just check the order of the character indices
696*0e209d39SAndroid Build Coastguard Worker                  * for left to right runs because Indic text might have been
697*0e209d39SAndroid Build Coastguard Worker                  * reordered. What we can do is find the minimum and maximum
698*0e209d39SAndroid Build Coastguard Worker                  * character indices in the run and make sure that the minimum
699*0e209d39SAndroid Build Coastguard Worker                  * is equal to charIndex and then advance charIndex to the maximum.
700*0e209d39SAndroid Build Coastguard Worker                  */
701*0e209d39SAndroid Build Coastguard Worker                 le_int32 minIndex = 0x7FFFFFFF, maxIndex = -1;
702*0e209d39SAndroid Build Coastguard Worker 
703*0e209d39SAndroid Build Coastguard Worker                 for(i = 0; i < glyphCount; i += 1) {
704*0e209d39SAndroid Build Coastguard Worker                     le_int32 ix = glyphToCharMap[i];
705*0e209d39SAndroid Build Coastguard Worker 
706*0e209d39SAndroid Build Coastguard Worker                     if (ix > maxIndex) {
707*0e209d39SAndroid Build Coastguard Worker                         maxIndex = ix;
708*0e209d39SAndroid Build Coastguard Worker                     }
709*0e209d39SAndroid Build Coastguard Worker 
710*0e209d39SAndroid Build Coastguard Worker                     if (ix < minIndex) {
711*0e209d39SAndroid Build Coastguard Worker                         minIndex = ix;
712*0e209d39SAndroid Build Coastguard Worker                     }
713*0e209d39SAndroid Build Coastguard Worker                 }
714*0e209d39SAndroid Build Coastguard Worker 
715*0e209d39SAndroid Build Coastguard Worker                 if (minIndex != charIndex) {
716*0e209d39SAndroid Build Coastguard Worker                     log_err("Bad minIndex for run %d on line %d: expected %d, got %d\n",
717*0e209d39SAndroid Build Coastguard Worker                         run, lineNumber, charIndex, minIndex);
718*0e209d39SAndroid Build Coastguard Worker                     goto close_paragraph; /* once there's one error, we can't count on anything else... */
719*0e209d39SAndroid Build Coastguard Worker                 }
720*0e209d39SAndroid Build Coastguard Worker 
721*0e209d39SAndroid Build Coastguard Worker                 charIndex = maxIndex + 1;
722*0e209d39SAndroid Build Coastguard Worker             }
723*0e209d39SAndroid Build Coastguard Worker         }
724*0e209d39SAndroid Build Coastguard Worker 
725*0e209d39SAndroid Build Coastguard Worker         lineNumber += 1;
726*0e209d39SAndroid Build Coastguard Worker     }
727*0e209d39SAndroid Build Coastguard Worker 
728*0e209d39SAndroid Build Coastguard Worker close_paragraph:
729*0e209d39SAndroid Build Coastguard Worker     pl_close(paragraph);
730*0e209d39SAndroid Build Coastguard Worker 
731*0e209d39SAndroid Build Coastguard Worker close_font:
732*0e209d39SAndroid Build Coastguard Worker     le_fontClose(font);
733*0e209d39SAndroid Build Coastguard Worker 
734*0e209d39SAndroid Build Coastguard Worker finish:
735*0e209d39SAndroid Build Coastguard Worker     return;
736*0e209d39SAndroid Build Coastguard Worker #endif
737*0e209d39SAndroid Build Coastguard Worker }
738*0e209d39SAndroid Build Coastguard Worker 
addCTests(TestNode ** root)739*0e209d39SAndroid Build Coastguard Worker U_CFUNC void addCTests(TestNode **root)
740*0e209d39SAndroid Build Coastguard Worker {
741*0e209d39SAndroid Build Coastguard Worker     addTest(root, &ParamTest,       "c_api/ParameterTest");
742*0e209d39SAndroid Build Coastguard Worker     addTest(root, &FactoryTest,     "c_api/FactoryTest");
743*0e209d39SAndroid Build Coastguard Worker     addTest(root, &AccessTest,      "c_layout/AccessTest");
744*0e209d39SAndroid Build Coastguard Worker     addTest(root, &DataDrivenTest,  "c_layout/DataDrivenTest");
745*0e209d39SAndroid Build Coastguard Worker     addTest(root, &GlyphToCharTest, "c_paragraph/GlyphToCharTest");
746*0e209d39SAndroid Build Coastguard Worker }
747*0e209d39SAndroid Build Coastguard Worker 
748*0e209d39SAndroid Build Coastguard Worker 
749*0e209d39SAndroid Build Coastguard Worker #endif
750