1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *******************************************************************************
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
459d709d503bab6e2b61931737e662dd293b40578ccornelius *   Copyright (C) 1999-2013, International Business Machines
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   Corporation and others.  All Rights Reserved.
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   file name:  gendata.cpp
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   created on: 11/03/2000
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *   created by: Eric R. Mader
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <string.h>
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <time.h>
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unistr.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uscript.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ubidi.h"
2259d709d503bab6e2b61931737e662dd293b40578ccornelius#include "unicode/ustring.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LETypes.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LEScripts.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LayoutEngine.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "PortableFontInstance.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "SimpleFontInstance.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "xmlparser.h"
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "letsutil.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "letest.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_USE
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
3859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic LEErrorCode overallStatus = LE_NO_ERROR;
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct TestInput
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *fontName;
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEUnicode  *text;
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32    textLength;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32    scriptCode;
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_bool     rightToLeft;
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
4859d709d503bab6e2b61931737e662dd293b40578ccornelius/* Returns the path to icu/source/test/testdata/ */
4959d709d503bab6e2b61931737e662dd293b40578ccorneliusconst char *getSourceTestData() {
5059d709d503bab6e2b61931737e662dd293b40578ccornelius    const char *srcDataDir = NULL;
5159d709d503bab6e2b61931737e662dd293b40578ccornelius#ifdef U_TOPSRCDIR
5259d709d503bab6e2b61931737e662dd293b40578ccornelius    srcDataDir =  U_TOPSRCDIR  U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
5359d709d503bab6e2b61931737e662dd293b40578ccornelius#else
5459d709d503bab6e2b61931737e662dd293b40578ccornelius    srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
5559d709d503bab6e2b61931737e662dd293b40578ccornelius    FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
5659d709d503bab6e2b61931737e662dd293b40578ccornelius
5759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (f != NULL) {
5859d709d503bab6e2b61931737e662dd293b40578ccornelius        /* We're in icu/source/test/letest/ */
5959d709d503bab6e2b61931737e662dd293b40578ccornelius        fclose(f);
6059d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
6159d709d503bab6e2b61931737e662dd293b40578ccornelius        /* We're in icu/source/test/letest/(Debug|Release) */
6259d709d503bab6e2b61931737e662dd293b40578ccornelius        srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
6359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
6459d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
6559d709d503bab6e2b61931737e662dd293b40578ccornelius
6659d709d503bab6e2b61931737e662dd293b40578ccornelius    return srcDataDir;
6759d709d503bab6e2b61931737e662dd293b40578ccornelius}
6859d709d503bab6e2b61931737e662dd293b40578ccornelius
6959d709d503bab6e2b61931737e662dd293b40578ccorneliusconst char *getPath(char buffer[2048], const char *filename) {
7059d709d503bab6e2b61931737e662dd293b40578ccornelius    const char *testDataDirectory = getSourceTestData();
7159d709d503bab6e2b61931737e662dd293b40578ccornelius
7259d709d503bab6e2b61931737e662dd293b40578ccornelius    strcpy(buffer, testDataDirectory);
7359d709d503bab6e2b61931737e662dd293b40578ccornelius    strcat(buffer, filename);
7459d709d503bab6e2b61931737e662dd293b40578ccornelius
7559d709d503bab6e2b61931737e662dd293b40578ccornelius    return buffer;
7659d709d503bab6e2b61931737e662dd293b40578ccornelius}
7759d709d503bab6e2b61931737e662dd293b40578ccornelius
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * FIXME: should use the output file name and the current date.
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char *header =
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "\n"
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "<!--\n"
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  Copyright (c) 1999-%4.4d International Business Machines\n"
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  Corporation and others. All rights reserved.\n"
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "\n"
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT\n"
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  UNLESS YOU REALLY KNOW WHAT YOU'RE DOING.\n"
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "\n"
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  file name:    letest.xml\n"
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  generated on: %s\n"
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "  generated by: gendata.cpp\n"
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "-->\n"
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "\n"
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "<layout-tests>\n";
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid dumpLongs(FILE *file, const char *tag, le_int32 *longs, le_int32 count) {
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char lineBuffer[8 * 12 + 2];
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 bufp = 0;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(file, "        <%s>\n", tag);
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i < count; i += 1) {
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (i % 8 == 0 && bufp != 0) {
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fprintf(file, "            %s\n", lineBuffer);
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bufp = 0;
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bufp += sprintf(&lineBuffer[bufp], "0x%8.8X, ", longs[i]);
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bufp != 0) {
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lineBuffer[bufp - 2] = '\0';
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(file, "            %s\n", lineBuffer);
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(file, "        </%s>\n\n", tag);
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid dumpFloats(FILE *file, const char *tag, float *floats, le_int32 count) {
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char lineBuffer[8 * 16 + 2];
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 bufp = 0;
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(file, "        <%s>\n", tag);
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i < count; i += 1) {
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (i % 8 == 0 && bufp != 0) {
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fprintf(file, "            %s\n", lineBuffer);
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bufp = 0;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        bufp += sprintf(&lineBuffer[bufp], "%f, ", floats[i]);
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (bufp != 0) {
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        lineBuffer[bufp - 2] = '\0';
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fprintf(file, "            %s\n", lineBuffer);
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(file, "        </%s>\n", tag);
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14459d709d503bab6e2b61931737e662dd293b40578ccorneliusint main(int argc, char *argv[])
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
14759d709d503bab6e2b61931737e662dd293b40578ccornelius    const char *gendataFile = "gendata.xml";
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FILE *outputFile = fopen(argv[1], "w");
14959d709d503bab6e2b61931737e662dd293b40578ccornelius    if(argc>2) {
15059d709d503bab6e2b61931737e662dd293b40578ccornelius      gendataFile = argv[2];
15159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    time_t now = time(NULL);
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    struct tm *local = localtime(&now);
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *tmFormat = "%m/%d/%Y %I:%M:%S %p %Z";
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char  tmString[64];
15659d709d503bab6e2b61931737e662dd293b40578ccornelius    le_uint32 count = 0;
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    strftime(tmString, 64, tmFormat, local);
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(outputFile, header, local->tm_year + 1900, tmString);
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UXMLParser  *parser = UXMLParser::createParser(status);
16159d709d503bab6e2b61931737e662dd293b40578ccornelius    UXMLElement *root   = parser->parseFile(gendataFile, status);
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (root == NULL) {
16459d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("Error: Could not open %s\n", gendataFile);
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete parser;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return -1;
16759d709d503bab6e2b61931737e662dd293b40578ccornelius    } else if(U_FAILURE(status)) {
16859d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("Error reading %s: %s\n", gendataFile, u_errorName(status));
16959d709d503bab6e2b61931737e662dd293b40578ccornelius      return -2;
17059d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
17159d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("Reading %s\n", gendataFile);
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // test-case attributes
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString id_attr     = UNICODE_STRING_SIMPLE("id");
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString lang_attr   = UNICODE_STRING_SIMPLE("lang");
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // test-font attributes
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString name_attr   = UNICODE_STRING_SIMPLE("name");
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UXMLElement *testCase;
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t tc = 0;
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while((testCase = root->nextChildElement(tc)) != NULL) {
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (testCase->getTagName().compare(test_case) == 0) {
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            char *id = getCString(testCase->getAttribute(id_attr));
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            char *script = getCString(testCase->getAttribute(script_attr));
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            char *lang   = getCString(testCase->getAttribute(lang_attr));
19459d709d503bab6e2b61931737e662dd293b40578ccornelius            ++count;
19559d709d503bab6e2b61931737e662dd293b40578ccornelius            printf("\n ID %s\n", id);
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            LEFontInstance *font = NULL;
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            const UXMLElement *element;
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ec = 0;
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t charCount = 0;
20059d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t typoFlags = LayoutEngine::kTypoFlagKern | LayoutEngine::kTypoFlagLiga; // kerning + ligatures...
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UScriptCode scriptCode;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32 languageCode = -1;
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UnicodeString text;
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t glyphCount = 0;
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            LEErrorCode leStatus = LE_NO_ERROR;
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            LayoutEngine *engine = NULL;
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            LEGlyphID *glyphs    = NULL;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            le_int32  *indices   = NULL;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            float     *positions = NULL;
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uscript_getCode(script, &scriptCode, 1, &status);
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (LE_FAILURE(status)) {
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                printf("Error: invalid script name: %s.\n", script);
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                goto free_c_strings;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lang != NULL) {
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                languageCode = getLanguageCode(lang);
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (languageCode < 0) {
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    printf("Error: invalid language name: %s.\n", lang);
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    goto free_c_strings;
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fprintf(outputFile, "    <test-case id=\"%s\" script=\"%s\" lang=\"%s\">\n", id, script, lang);
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                fprintf(outputFile, "    <test-case id=\"%s\" script=\"%s\">\n", id, script);
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while((element = testCase->nextChildElement(ec)) != NULL) {
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString tag = element->getTagName();
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // TODO: make sure that each element is only used once.
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (tag.compare(test_font) == 0) {
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    char *fontName  = getCString(element->getAttribute(name_attr));
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    const char *version = NULL;
23759d709d503bab6e2b61931737e662dd293b40578ccornelius                    char buf[2048];
23859d709d503bab6e2b61931737e662dd293b40578ccornelius                    PortableFontInstance *pfi = new PortableFontInstance(getPath(buf,fontName), 12, leStatus);
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (LE_FAILURE(leStatus)) {
24159d709d503bab6e2b61931737e662dd293b40578ccornelius                      printf("Error: could not open font: %s (path: %s)\n", fontName, buf);
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        freeCString(fontName);
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        goto free_c_strings;
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24659d709d503bab6e2b61931737e662dd293b40578ccornelius                    printf(" Generating: %s, %s, %s, %s\n", id, script, lang, fontName);
24759d709d503bab6e2b61931737e662dd293b40578ccornelius
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    version = pfi->getNameString(NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    // The standard recommends that the Macintosh Roman/English name string be present, but
25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    // if it's not, try the Microsoft Unicode/English string.
25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    if (version == NULL) {
25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        const LEUnicode16 *uversion = pfi->getUnicodeNameString(NAME_VERSION_STRING, PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        if (uversion != NULL) {
25659d709d503bab6e2b61931737e662dd293b40578ccornelius                          char uversion_utf8[300];
25759d709d503bab6e2b61931737e662dd293b40578ccornelius                          UErrorCode status2 = U_ZERO_ERROR;
25859d709d503bab6e2b61931737e662dd293b40578ccornelius                          u_strToUTF8(uversion_utf8, 300, NULL, uversion, -1, &status2);
25959d709d503bab6e2b61931737e662dd293b40578ccornelius                          if(U_FAILURE(status2)) {
26059d709d503bab6e2b61931737e662dd293b40578ccornelius                            uversion_utf8[0]=0;
26159d709d503bab6e2b61931737e662dd293b40578ccornelius                          }
26259d709d503bab6e2b61931737e662dd293b40578ccornelius                            fprintf(outputFile, "        <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
26359d709d503bab6e2b61931737e662dd293b40578ccornelius                                    fontName, uversion_utf8, pfi->getFontChecksum(), pfi->getRawChecksum());
26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                            pfi->deleteNameString(uversion);
26659d709d503bab6e2b61931737e662dd293b40578ccornelius                        } else {
26759d709d503bab6e2b61931737e662dd293b40578ccornelius                          fprintf(outputFile, "        <test-font name=\"%s\" version=\"unknown-0x%8.8X\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
26859d709d503bab6e2b61931737e662dd293b40578ccornelius                                  fontName, pfi->getFontChecksum(), pfi->getFontChecksum(), pfi->getRawChecksum());
26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        }
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    } else {
27159d709d503bab6e2b61931737e662dd293b40578ccornelius                        fprintf(outputFile, "        <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
27259d709d503bab6e2b61931737e662dd293b40578ccornelius                                fontName, version, pfi->getFontChecksum(), pfi->getRawChecksum());
27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                        pfi->deleteNameString(version);
27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    }
27659d709d503bab6e2b61931737e662dd293b40578ccornelius                    fflush(outputFile);
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    freeCString(fontName);
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    font = pfi;
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if (tag.compare(test_text) == 0) {
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    char *utf8 = NULL;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    text = element->getText(TRUE);
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    charCount = text.length();
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    utf8 = getUTF8String(&text);
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    fprintf(outputFile, "        <test-text>%s</test-text>\n\n", utf8);
28959d709d503bab6e2b61931737e662dd293b40578ccornelius                    fflush(outputFile);
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    freeCString(utf8);
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // an unknown tag...
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    char *cTag = getCString(&tag);
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    printf("Test %s: unknown element with tag \"%s\"\n", id, cTag);
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    freeCString(cTag);
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (font == NULL) {
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                LEErrorCode fontStatus = LE_NO_ERROR;
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                font = new SimpleFontInstance(12, fontStatus);
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                typoFlags |= 0x80000000L;  // use CharSubstitutionFilter...
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            engine = LayoutEngine::layoutEngineFactory(font, scriptCode, languageCode, typoFlags, leStatus);
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (LE_FAILURE(leStatus)) {
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                printf("Error for test %s: could not create a LayoutEngine.\n", id);
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                goto delete_font;
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            glyphCount = engine->layoutChars(text.getBuffer(), 0, charCount, charCount, getRTL(text), 0, 0, leStatus);
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            glyphs    = NEW_ARRAY(LEGlyphID, glyphCount);
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            indices   = NEW_ARRAY(le_int32, glyphCount);
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            positions = NEW_ARRAY(float, glyphCount * 2 + 2);
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            engine->getGlyphs(glyphs, leStatus);
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            engine->getCharIndices(indices, leStatus);
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            engine->getGlyphPositions(positions, leStatus);
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32459d709d503bab6e2b61931737e662dd293b40578ccornelius            if(LE_FAILURE(leStatus)) {
32559d709d503bab6e2b61931737e662dd293b40578ccornelius              fprintf(stderr,"ERROR: LO returned error: %s\n", u_errorName((UErrorCode)leStatus));
32659d709d503bab6e2b61931737e662dd293b40578ccornelius              overallStatus = leStatus;
32759d709d503bab6e2b61931737e662dd293b40578ccornelius              fprintf(outputFile, "<!-- ERROR: %d -->\n", leStatus);
32859d709d503bab6e2b61931737e662dd293b40578ccornelius              fflush(outputFile);
32959d709d503bab6e2b61931737e662dd293b40578ccornelius              leStatus = LE_NO_ERROR;
33059d709d503bab6e2b61931737e662dd293b40578ccornelius            } else {
33159d709d503bab6e2b61931737e662dd293b40578ccornelius              dumpLongs(outputFile, "result-glyphs", (le_int32 *) glyphs, glyphCount);
33259d709d503bab6e2b61931737e662dd293b40578ccornelius
33359d709d503bab6e2b61931737e662dd293b40578ccornelius              dumpLongs(outputFile, "result-indices", indices, glyphCount);
33459d709d503bab6e2b61931737e662dd293b40578ccornelius
33559d709d503bab6e2b61931737e662dd293b40578ccornelius              dumpFloats(outputFile, "result-positions", positions, glyphCount * 2 + 2);
33659d709d503bab6e2b61931737e662dd293b40578ccornelius              fflush(outputFile);
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
33859d709d503bab6e2b61931737e662dd293b40578ccornelius            }
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            DELETE_ARRAY(positions);
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            DELETE_ARRAY(indices);
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            DELETE_ARRAY(glyphs);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete engine;
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querudelete_font:
34759d709d503bab6e2b61931737e662dd293b40578ccornelius            fprintf(outputFile, "    </test-case>\n\n");
34859d709d503bab6e2b61931737e662dd293b40578ccornelius            fflush(outputFile);
34959d709d503bab6e2b61931737e662dd293b40578ccornelius
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete font;
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufree_c_strings:
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            freeCString(lang);
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            freeCString(script);
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            freeCString(id);
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete root;
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete parser;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(outputFile, "</layout-tests>\n");
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36459d709d503bab6e2b61931737e662dd293b40578ccornelius    if(count==0) {
36559d709d503bab6e2b61931737e662dd293b40578ccornelius      fprintf(stderr, "No cases processed!\n");
36659d709d503bab6e2b61931737e662dd293b40578ccornelius      return 1;
36759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
36859d709d503bab6e2b61931737e662dd293b40578ccornelius
36959d709d503bab6e2b61931737e662dd293b40578ccornelius
37059d709d503bab6e2b61931737e662dd293b40578ccornelius    if(LE_FAILURE(overallStatus)) {
37159d709d503bab6e2b61931737e662dd293b40578ccornelius      fprintf(outputFile, "<!-- !!! FAILED. %d -->\n", overallStatus);
37259d709d503bab6e2b61931737e662dd293b40578ccornelius      fprintf(stderr, "!!! FAILED. %d\n", overallStatus);
37359d709d503bab6e2b61931737e662dd293b40578ccornelius      fclose(outputFile);
37459d709d503bab6e2b61931737e662dd293b40578ccornelius      return 0;
37559d709d503bab6e2b61931737e662dd293b40578ccornelius      //      return 1;
37659d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
37759d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("Generated.\n");
37859d709d503bab6e2b61931737e662dd293b40578ccornelius      fclose(outputFile);
37959d709d503bab6e2b61931737e662dd293b40578ccornelius      return 0;
38059d709d503bab6e2b61931737e662dd293b40578ccornelius    }
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
382