]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
3 | * | |
73c04bcf | 4 | * Copyright (C) 1999-2006, International Business Machines |
b75a7d8f A |
5 | * Corporation and others. All Rights Reserved. |
6 | * | |
7 | ******************************************************************************* | |
8 | * file name: gendata.cpp | |
9 | * | |
10 | * created on: 11/03/2000 | |
11 | * created by: Eric R. Mader | |
12 | */ | |
13 | ||
14 | #include <stdio.h> | |
73c04bcf A |
15 | #include <string.h> |
16 | #include <time.h> | |
b75a7d8f | 17 | |
73c04bcf A |
18 | #include "unicode/utypes.h" |
19 | #include "unicode/unistr.h" | |
20 | #include "unicode/uscript.h" | |
21 | #include "unicode/ubidi.h" | |
22 | ||
23 | #include "layout/LETypes.h" | |
24 | #include "layout/LEScripts.h" | |
25 | #include "layout/LayoutEngine.h" | |
b75a7d8f A |
26 | |
27 | #include "PortableFontInstance.h" | |
73c04bcf | 28 | #include "SimpleFontInstance.h" |
b75a7d8f | 29 | |
73c04bcf | 30 | #include "xmlparser.h" |
b75a7d8f | 31 | |
73c04bcf A |
32 | #include "letsutil.h" |
33 | #include "letest.h" | |
b75a7d8f | 34 | |
73c04bcf | 35 | U_NAMESPACE_USE |
b75a7d8f A |
36 | |
37 | struct TestInput | |
38 | { | |
73c04bcf A |
39 | const char *fontName; |
40 | LEUnicode *text; | |
41 | le_int32 textLength; | |
42 | le_int32 scriptCode; | |
43 | le_bool rightToLeft; | |
b75a7d8f A |
44 | }; |
45 | ||
46 | /* | |
47 | * FIXME: should use the output file name and the current date. | |
48 | */ | |
73c04bcf A |
49 | const char *header = |
50 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | |
b75a7d8f | 51 | "\n" |
73c04bcf A |
52 | "<!--\n" |
53 | " Copyright (c) 1999-%4.4d International Business Machines\n" | |
54 | " Corporation and others. All rights reserved.\n" | |
55 | "\n" | |
56 | " WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT\n" | |
57 | " UNLESS YOU REALLY KNOW WHAT YOU'RE DOING.\n" | |
58 | "\n" | |
59 | " file name: letest.xml\n" | |
60 | " generated on: %s\n" | |
61 | " generated by: gendata.cpp\n" | |
62 | "-->\n" | |
63 | "\n" | |
64 | "<layout-tests>\n"; | |
b75a7d8f | 65 | |
73c04bcf | 66 | void dumpLongs(FILE *file, const char *tag, le_int32 *longs, le_int32 count) { |
b75a7d8f A |
67 | char lineBuffer[8 * 12 + 2]; |
68 | le_int32 bufp = 0; | |
69 | ||
73c04bcf | 70 | fprintf(file, " <%s>\n", tag); |
b75a7d8f A |
71 | |
72 | for (int i = 0; i < count; i += 1) { | |
73 | if (i % 8 == 0 && bufp != 0) { | |
73c04bcf | 74 | fprintf(file, " %s\n", lineBuffer); |
b75a7d8f A |
75 | bufp = 0; |
76 | } | |
77 | ||
78 | bufp += sprintf(&lineBuffer[bufp], "0x%8.8X, ", longs[i]); | |
79 | } | |
80 | ||
81 | if (bufp != 0) { | |
82 | lineBuffer[bufp - 2] = '\0'; | |
73c04bcf | 83 | fprintf(file, " %s\n", lineBuffer); |
b75a7d8f A |
84 | } |
85 | ||
73c04bcf | 86 | fprintf(file, " </%s>\n\n", tag); |
b75a7d8f A |
87 | } |
88 | ||
73c04bcf | 89 | void dumpFloats(FILE *file, const char *tag, float *floats, le_int32 count) { |
b75a7d8f A |
90 | char lineBuffer[8 * 16 + 2]; |
91 | le_int32 bufp = 0; | |
92 | ||
73c04bcf | 93 | fprintf(file, " <%s>\n", tag); |
b75a7d8f A |
94 | |
95 | for (int i = 0; i < count; i += 1) { | |
96 | if (i % 8 == 0 && bufp != 0) { | |
73c04bcf | 97 | fprintf(file, " %s\n", lineBuffer); |
b75a7d8f A |
98 | bufp = 0; |
99 | } | |
100 | ||
73c04bcf | 101 | bufp += sprintf(&lineBuffer[bufp], "%f, ", floats[i]); |
b75a7d8f A |
102 | } |
103 | ||
104 | if (bufp != 0) { | |
105 | lineBuffer[bufp - 2] = '\0'; | |
73c04bcf | 106 | fprintf(file, " %s\n", lineBuffer); |
b75a7d8f A |
107 | } |
108 | ||
73c04bcf | 109 | fprintf(file, " </%s>\n", tag); |
b75a7d8f A |
110 | } |
111 | ||
73c04bcf | 112 | int main(int /*argc*/, char *argv[]) |
b75a7d8f | 113 | { |
73c04bcf | 114 | UErrorCode status = U_ZERO_ERROR; |
b75a7d8f | 115 | FILE *outputFile = fopen(argv[1], "w"); |
73c04bcf A |
116 | time_t now = time(NULL); |
117 | struct tm *local = localtime(&now); | |
118 | const char *tmFormat = "%m/%d/%Y %I:%M:%S %p %Z"; | |
119 | char tmString[64]; | |
b75a7d8f | 120 | |
73c04bcf A |
121 | strftime(tmString, 64, tmFormat, local); |
122 | fprintf(outputFile, header, local->tm_year + 1900, tmString); | |
b75a7d8f | 123 | |
73c04bcf A |
124 | UXMLParser *parser = UXMLParser::createParser(status); |
125 | UXMLElement *root = parser->parseFile("gendata.xml", status); | |
b75a7d8f | 126 | |
73c04bcf A |
127 | if (root == NULL) { |
128 | printf("Error: Could not open gendata.xml\n"); | |
129 | delete parser; | |
130 | return -1; | |
b75a7d8f A |
131 | } |
132 | ||
73c04bcf A |
133 | UnicodeString test_case = UNICODE_STRING_SIMPLE("test-case"); |
134 | UnicodeString test_text = UNICODE_STRING_SIMPLE("test-text"); | |
135 | UnicodeString test_font = UNICODE_STRING_SIMPLE("test-font"); | |
136 | ||
137 | // test-case attributes | |
138 | UnicodeString id_attr = UNICODE_STRING_SIMPLE("id"); | |
139 | UnicodeString script_attr = UNICODE_STRING_SIMPLE("script"); | |
140 | UnicodeString lang_attr = UNICODE_STRING_SIMPLE("lang"); | |
141 | ||
142 | // test-font attributes | |
143 | UnicodeString name_attr = UNICODE_STRING_SIMPLE("name"); | |
144 | ||
145 | const UXMLElement *testCase; | |
146 | int32_t tc = 0; | |
147 | ||
148 | while((testCase = root->nextChildElement(tc)) != NULL) { | |
149 | if (testCase->getTagName().compare(test_case) == 0) { | |
150 | char *id = getCString(testCase->getAttribute(id_attr)); | |
151 | char *script = getCString(testCase->getAttribute(script_attr)); | |
152 | char *lang = getCString(testCase->getAttribute(lang_attr)); | |
153 | LEFontInstance *font = NULL; | |
154 | const UXMLElement *element; | |
155 | int32_t ec = 0; | |
156 | int32_t charCount = 0; | |
157 | int32_t typoFlags = 3; // kerning + ligatures... | |
158 | UScriptCode scriptCode; | |
159 | le_int32 languageCode = -1; | |
160 | UnicodeString text; | |
161 | int32_t glyphCount = 0; | |
162 | LEErrorCode leStatus = LE_NO_ERROR; | |
163 | LayoutEngine *engine = NULL; | |
164 | LEGlyphID *glyphs = NULL; | |
165 | le_int32 *indices = NULL; | |
166 | float *positions = NULL; | |
167 | ||
168 | uscript_getCode(script, &scriptCode, 1, &status); | |
169 | if (LE_FAILURE(status)) { | |
170 | printf("Error: invalid script name: %s.\n", script); | |
171 | goto free_c_strings; | |
172 | } | |
173 | ||
174 | if (lang != NULL) { | |
175 | languageCode = getLanguageCode(lang); | |
176 | ||
177 | if (languageCode < 0) { | |
178 | printf("Error: invalid language name: %s.\n", lang); | |
179 | goto free_c_strings; | |
180 | } | |
181 | ||
182 | fprintf(outputFile, " <test-case id=\"%s\" script=\"%s\" lang=\"%s\">\n", id, script, lang); | |
183 | } else { | |
184 | fprintf(outputFile, " <test-case id=\"%s\" script=\"%s\">\n", id, script); | |
185 | } | |
186 | ||
187 | while((element = testCase->nextChildElement(ec)) != NULL) { | |
188 | UnicodeString tag = element->getTagName(); | |
189 | ||
190 | // TODO: make sure that each element is only used once. | |
191 | if (tag.compare(test_font) == 0) { | |
192 | char *fontName = getCString(element->getAttribute(name_attr)); | |
193 | const char *version = NULL; | |
194 | PortableFontInstance *pfi = new PortableFontInstance(fontName, 12, leStatus); | |
195 | ||
196 | if (LE_FAILURE(leStatus)) { | |
197 | printf("Error: could not open font: %s\n", fontName); | |
198 | freeCString(fontName); | |
199 | goto free_c_strings; | |
200 | } | |
201 | ||
202 | version = pfi->getNameString(NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH); | |
203 | ||
204 | fprintf(outputFile, " <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\"/>\n\n", | |
205 | fontName, version, pfi->getFontChecksum()); | |
206 | ||
207 | pfi->deleteNameString(version); | |
208 | freeCString(fontName); | |
209 | font = pfi; | |
210 | } else if (tag.compare(test_text) == 0) { | |
211 | char *utf8 = NULL; | |
212 | ||
213 | text = element->getText(TRUE); | |
214 | charCount = text.length(); | |
215 | ||
216 | utf8 = getUTF8String(&text); | |
217 | fprintf(outputFile, " <test-text>%s</test-text>\n\n", utf8); | |
218 | freeCString(utf8); | |
219 | } else { | |
220 | // an unknown tag... | |
221 | char *cTag = getCString(&tag); | |
222 | ||
223 | printf("Test %s: unknown element with tag \"%s\"\n", id, cTag); | |
224 | freeCString(cTag); | |
225 | } | |
226 | } | |
227 | ||
228 | if (font == NULL) { | |
229 | LEErrorCode fontStatus = LE_NO_ERROR; | |
230 | ||
231 | font = new SimpleFontInstance(12, fontStatus); | |
232 | typoFlags |= 0x80000000L; // use CharSubstitutionFilter... | |
233 | } | |
234 | ||
235 | engine = LayoutEngine::layoutEngineFactory(font, scriptCode, languageCode, typoFlags, leStatus); | |
236 | ||
237 | if (LE_FAILURE(leStatus)) { | |
238 | printf("Error for test %s: could not create a LayoutEngine.\n", id); | |
239 | goto delete_font; | |
240 | } | |
241 | ||
242 | glyphCount = engine->layoutChars(text.getBuffer(), 0, charCount, charCount, getRTL(text), 0, 0, leStatus); | |
243 | ||
244 | glyphs = NEW_ARRAY(LEGlyphID, glyphCount); | |
245 | indices = NEW_ARRAY(le_int32, glyphCount); | |
246 | positions = NEW_ARRAY(float, glyphCount * 2 + 2); | |
247 | ||
248 | engine->getGlyphs(glyphs, leStatus); | |
249 | engine->getCharIndices(indices, leStatus); | |
250 | engine->getGlyphPositions(positions, leStatus); | |
251 | ||
252 | dumpLongs(outputFile, "result-glyphs", (le_int32 *) glyphs, glyphCount); | |
253 | ||
254 | dumpLongs(outputFile, "result-indices", indices, glyphCount); | |
255 | ||
256 | dumpFloats(outputFile, "result-positions", positions, glyphCount * 2 + 2); | |
257 | ||
258 | fprintf(outputFile, " </test-case>\n\n"); | |
259 | ||
260 | DELETE_ARRAY(positions); | |
261 | DELETE_ARRAY(indices); | |
262 | DELETE_ARRAY(glyphs); | |
b75a7d8f | 263 | |
73c04bcf | 264 | delete engine; |
b75a7d8f | 265 | |
73c04bcf A |
266 | delete_font: |
267 | delete font; | |
b75a7d8f | 268 | |
73c04bcf A |
269 | free_c_strings: |
270 | freeCString(lang); | |
271 | freeCString(script); | |
272 | freeCString(id); | |
273 | } | |
b75a7d8f A |
274 | } |
275 | ||
73c04bcf A |
276 | delete root; |
277 | delete parser; | |
278 | ||
279 | fprintf(outputFile, "</layout-tests>\n"); | |
b75a7d8f A |
280 | |
281 | fclose(outputFile); | |
b75a7d8f | 282 | } |