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