1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1999-2008, International Business Machines 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> 15 #include <string.h> 16 #include <time.h> 17 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" 26 27 #include "PortableFontInstance.h" 28 #include "SimpleFontInstance.h" 29 30 #include "xmlparser.h" 31 32 #include "letsutil.h" 33 #include "letest.h" 34 35 U_NAMESPACE_USE 36 37 struct TestInput 38 { 39 const char *fontName; 40 LEUnicode *text; 41 le_int32 textLength; 42 le_int32 scriptCode; 43 le_bool rightToLeft; 44 }; 45 46 /* 47 * FIXME: should use the output file name and the current date. 48 */ 49 const char *header = 50 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 51 "\n" 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"; 65 66 void dumpLongs(FILE *file, const char *tag, le_int32 *longs, le_int32 count) { 67 char lineBuffer[8 * 12 + 2]; 68 le_int32 bufp = 0; 69 70 fprintf(file, " <%s>\n", tag); 71 72 for (int i = 0; i < count; i += 1) { 73 if (i % 8 == 0 && bufp != 0) { 74 fprintf(file, " %s\n", lineBuffer); 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'; 83 fprintf(file, " %s\n", lineBuffer); 84 } 85 86 fprintf(file, " </%s>\n\n", tag); 87 } 88 89 void dumpFloats(FILE *file, const char *tag, float *floats, le_int32 count) { 90 char lineBuffer[8 * 16 + 2]; 91 le_int32 bufp = 0; 92 93 fprintf(file, " <%s>\n", tag); 94 95 for (int i = 0; i < count; i += 1) { 96 if (i % 8 == 0 && bufp != 0) { 97 fprintf(file, " %s\n", lineBuffer); 98 bufp = 0; 99 } 100 101 bufp += sprintf(&lineBuffer[bufp], "%f, ", floats[i]); 102 } 103 104 if (bufp != 0) { 105 lineBuffer[bufp - 2] = '\0'; 106 fprintf(file, " %s\n", lineBuffer); 107 } 108 109 fprintf(file, " </%s>\n", tag); 110 } 111 112 int main(int /*argc*/, char *argv[]) 113 { 114 UErrorCode status = U_ZERO_ERROR; 115 FILE *outputFile = fopen(argv[1], "w"); 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]; 120 121 strftime(tmString, 64, tmFormat, local); 122 fprintf(outputFile, header, local->tm_year + 1900, tmString); 123 124 UXMLParser *parser = UXMLParser::createParser(status); 125 UXMLElement *root = parser->parseFile("gendata.xml", status); 126 127 if (root == NULL) { 128 printf("Error: Could not open gendata.xml\n"); 129 delete parser; 130 return -1; 131 } 132 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 // The standard recommends that the Macintosh Roman/English name string be present, but 205 // if it's not, try the Microsoft Unicode/English string. 206 if (version == NULL) { 207 const LEUnicode16 *uversion = pfi->getUnicodeNameString(NAME_VERSION_STRING, PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH); 208 209 if (uversion != NULL) { 210 fprintf(outputFile, " <test-font name=\"%s\" version=\"%S\" checksum=\"0x%8.8X\"/>\n\n", 211 fontName, uversion, pfi->getFontChecksum()); 212 213 pfi->deleteNameString(uversion); 214 } 215 } else { 216 fprintf(outputFile, " <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\"/>\n\n", 217 fontName, version, pfi->getFontChecksum()); 218 219 pfi->deleteNameString(version); 220 } 221 222 freeCString(fontName); 223 224 font = pfi; 225 } else if (tag.compare(test_text) == 0) { 226 char *utf8 = NULL; 227 228 text = element->getText(TRUE); 229 charCount = text.length(); 230 231 utf8 = getUTF8String(&text); 232 fprintf(outputFile, " <test-text>%s</test-text>\n\n", utf8); 233 freeCString(utf8); 234 } else { 235 // an unknown tag... 236 char *cTag = getCString(&tag); 237 238 printf("Test %s: unknown element with tag \"%s\"\n", id, cTag); 239 freeCString(cTag); 240 } 241 } 242 243 if (font == NULL) { 244 LEErrorCode fontStatus = LE_NO_ERROR; 245 246 font = new SimpleFontInstance(12, fontStatus); 247 typoFlags |= 0x80000000L; // use CharSubstitutionFilter... 248 } 249 250 engine = LayoutEngine::layoutEngineFactory(font, scriptCode, languageCode, typoFlags, leStatus); 251 252 if (LE_FAILURE(leStatus)) { 253 printf("Error for test %s: could not create a LayoutEngine.\n", id); 254 goto delete_font; 255 } 256 257 glyphCount = engine->layoutChars(text.getBuffer(), 0, charCount, charCount, getRTL(text), 0, 0, leStatus); 258 259 glyphs = NEW_ARRAY(LEGlyphID, glyphCount); 260 indices = NEW_ARRAY(le_int32, glyphCount); 261 positions = NEW_ARRAY(float, glyphCount * 2 + 2); 262 263 engine->getGlyphs(glyphs, leStatus); 264 engine->getCharIndices(indices, leStatus); 265 engine->getGlyphPositions(positions, leStatus); 266 267 dumpLongs(outputFile, "result-glyphs", (le_int32 *) glyphs, glyphCount); 268 269 dumpLongs(outputFile, "result-indices", indices, glyphCount); 270 271 dumpFloats(outputFile, "result-positions", positions, glyphCount * 2 + 2); 272 273 fprintf(outputFile, " </test-case>\n\n"); 274 275 DELETE_ARRAY(positions); 276 DELETE_ARRAY(indices); 277 DELETE_ARRAY(glyphs); 278 279 delete engine; 280 281 delete_font: 282 delete font; 283 284 free_c_strings: 285 freeCString(lang); 286 freeCString(script); 287 freeCString(id); 288 } 289 } 290 291 delete root; 292 delete parser; 293 294 fprintf(outputFile, "</layout-tests>\n"); 295 296 fclose(outputFile); 297 } 298