]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/letest/gendata.cpp
ICU-59117.0.1.tar.gz
[apple/icu.git] / icuSources / test / letest / gendata.cpp
index 24aa3384899eea596803ac91688cd791322612ad..a9c5da56a1dfd708504f896bfad07d5bbf36d9da 100644 (file)
@@ -1,7 +1,9 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
  *******************************************************************************
  *
- *   Copyright (C) 1999-2003, International Business Machines
+ *   Copyright (C) 1999-2013, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *
  *******************************************************************************
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include <string.h>
+#include <time.h>
 
-#include "LETypes.h"
-#include "LEScripts.h"
-#include "LayoutEngine.h"
+#include "unicode/utypes.h"
+#include "unicode/unistr.h"
+#include "unicode/uscript.h"
+#include "unicode/ubidi.h"
+#include "unicode/ustring.h"
+
+#include "layout/LETypes.h"
+#include "layout/LEScripts.h"
+#include "layout/LayoutEngine.h"
 
 #include "PortableFontInstance.h"
+#include "SimpleFontInstance.h"
 
-#include "unicode/uscript.h"
+#include "xmlparser.h"
 
-U_NAMESPACE_USE
+#include "letsutil.h"
+#include "letest.h"
 
-#define ARRAY_LENGTH(array) (sizeof array / sizeof array[0])
+U_NAMESPACE_USE
 
+static LEErrorCode overallStatus = LE_NO_ERROR;
 struct TestInput
 {
-    char      *fontName;
-    LEUnicode *text;
-    le_int32   textLength;
-    le_int32   scriptCode;
-    le_bool    rightToLeft;
+    const char *fontName;
+    LEUnicode  *text;
+    le_int32    textLength;
+    le_int32    scriptCode;
+    le_bool     rightToLeft;
 };
 
-/* 
- * FIXME: should use the output file name and the current date.
- */
-char *header =
-    "/*\n"
-    " *******************************************************************************\n"
-    " *\n"
-    " *   Copyright (C) 1999-2003, International Business Machines\n"
-    " *   Corporation and others.  All Rights Reserved.\n"
-    " *\n"
-    " *   WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT\n"
-    " *   UNLESS YOU REALLY KNOW WHAT YOU'RE DOING.\n"
-    " *\n"
-    " *******************************************************************************\n"
-    " *\n"
-    " *   file name:  testdata.cpp\n"
-    " *   created on: 12/14/2000\n"
-    " *   created by: gendata.cpp\n"
-    " */\n"
-    "\n"
-    "#include \"LETypes.h\"\n"
-    "#include \"LEScripts.h\"\n"
-    "#include \"letest.h\"\n"
-    "\n";
-
-#if 0
-char *scriptNames[] =
-{
-      "USCRIPT_COMMON",      /* Zyyy */
-      "USCRIPT_INHERITED",   /* Qaai */
-      "USCRIPT_ARABIC",      /* Arab */
-      "USCRIPT_ARMENIAN",    /* Armn */
-      "USCRIPT_BENGALI",     /* Beng */
-      "USCRIPT_BOPOMOFO",    /* Bopo */
-      "USCRIPT_CHEROKEE",    /* Cher */
-      "USCRIPT_COPTIC",      /* Qaac */
-      "USCRIPT_CYRILLIC",    /* Cyrl (Cyrs) */
-      "USCRIPT_DESERET",     /* Dsrt */
-      "USCRIPT_DEVANAGARI",  /* Deva */
-      "USCRIPT_ETHIOPIC",    /* Ethi */
-      "USCRIPT_GEORGIAN",    /* Geor (Geon, Geoa) */
-      "USCRIPT_GOTHIC",      /* Goth */
-      "USCRIPT_GREEK",       /* Grek */
-      "USCRIPT_GUJARATI",    /* Gujr */
-      "USCRIPT_GURMUKHI",    /* Guru */
-      "USCRIPT_HAN",         /* Hani */
-      "USCRIPT_HANGUL",      /* Hang */
-      "USCRIPT_HEBREW",      /* Hebr */
-      "USCRIPT_HIRAGANA",    /* Hira */
-      "USCRIPT_KANNADA",     /* Knda */
-      "USCRIPT_KATAKANA",    /* Kana */
-      "USCRIPT_KHMER",       /* Khmr */
-      "USCRIPT_LAO",         /* Laoo */
-      "USCRIPT_LATIN",       /* Latn (Latf, Latg) */
-      "USCRIPT_MALAYALAM",   /* Mlym */
-      "USCRIPT_MONGOLIAN",   /* Mong */
-      "USCRIPT_MYANMAR",     /* Mymr */
-      "USCRIPT_OGHAM",       /* Ogam */
-      "USCRIPT_OLD_ITALIC",  /* Ital */
-      "USCRIPT_ORIYA",       /* Orya */
-      "USCRIPT_RUNIC",       /* Runr */
-      "USCRIPT_SINHALA",     /* Sinh */
-      "USCRIPT_SYRIAC",      /* Syrc (Syrj, Syrn, Syre) */
-      "USCRIPT_TAMIL",       /* Taml */
-      "USCRIPT_TELUGU",      /* Telu */
-      "USCRIPT_THAANA",      /* Thaa */
-      "USCRIPT_THAI",        /* Thai */
-      "USCRIPT_TIBETAN",     /* Tibt */
-      "USCRIPT_UCAS",        /* Cans */
-      "USCRIPT_YI",          /* Yiii */
-      "USCRIPT_TAGALOG",     /* Tglg */
-      "USCRIPT_HANUNOO",     /* Hano */
-      "USCRIPT_BUHID",       /* Buhd */
-      "USCRIPT_TAGBANWA"     /* Tagb */
-};
+/* Returns the path to icu/source/test/testdata/ */
+const char *getSourceTestData() {
+    const char *srcDataDir = NULL;
+#ifdef U_TOPSRCDIR
+    srcDataDir =  U_TOPSRCDIR  U_FILE_SEP_STRING "test" U_FILE_SEP_STRING "testdata" U_FILE_SEP_STRING;
+#else
+    srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
+    FILE *f = fopen(".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING"rbbitst.txt", "r");
+
+    if (f != NULL) {
+        /* We're in icu/source/test/letest/ */
+        fclose(f);
+    } else {
+        /* We're in icu/source/test/letest/(Debug|Release) */
+        srcDataDir = ".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING".."U_FILE_SEP_STRING"test"U_FILE_SEP_STRING"testdata"U_FILE_SEP_STRING;
+    }
 #endif
 
-LEUnicode devaText[] =
-{
-    0x0936, 0x094d, 0x0930, 0x0940, 0x092e, 0x0926, 0x094d, 0x0020,
-    0x092d, 0x0917, 0x0935, 0x0926, 0x094d, 0x0917, 0x0940, 0x0924,
-    0x093e, 0x0020, 0x0905, 0x0927, 0x094d, 0x092f, 0x093e, 0x092f,
-    0x0020, 0x0905, 0x0930, 0x094d, 0x091c, 0x0941, 0x0928, 0x0020,
-    0x0935, 0x093f, 0x0937, 0x093e, 0x0926, 0x0020, 0x092f, 0x094b,
-    0x0917, 0x0020, 0x0927, 0x0943, 0x0924, 0x0930, 0x093e, 0x0937,
-    0x094d, 0x091f, 0x094d, 0x0930, 0x0020, 0x0909, 0x0935, 0x093E,
-    0x091A, 0x0943, 0x0020, 0x0927, 0x0930, 0x094d, 0x092e, 0x0915,
-    0x094d, 0x0937, 0x0947, 0x0924, 0x094d, 0x0930, 0x0947, 0x0020,
-    0x0915, 0x0941, 0x0930, 0x0941, 0x0915, 0x094d, 0x0937, 0x0947,
-    0x0924, 0x094d, 0x0930, 0x0947, 0x0020, 0x0938, 0x092e, 0x0935,
-    0x0947, 0x0924, 0x093e, 0x0020, 0x092f, 0x0941, 0x092f, 0x0941,
-    0x0924, 0x094d, 0x0938, 0x0935, 0x0903, 0x0020, 0x092e, 0x093e,
-    0x092e, 0x0915, 0x093e, 0x0903, 0x0020, 0x092a, 0x093e, 0x0923,
-    0x094d, 0x0921, 0x0935, 0x093e, 0x0936, 0x094d, 0x091a, 0x0948,
-    0x0935, 0x0020, 0x0915, 0x093f, 0x092e, 0x0915, 0x0941, 0x0930,
-    0x094d, 0x0935, 0x0924, 0x0020, 0x0938, 0x0902, 0x091c, 0x0935
-};
-
-le_int32 devaTextLength = ARRAY_LENGTH(devaText);
-
-LEUnicode arabText[] =
-{
-    0x0623, 0x0633, 0x0627, 0x0633, 0x064B, 0x0627, 0x060C, 0x0020, 
-    0x062A, 0x062A, 0x0639, 0x0627, 0x0645, 0x0644, 0x0020, 
-    0x0627, 0x0644, 0x062D, 0x0648, 0x0627, 0x0633, 0x064A, 0x0628, 
-    0x0020, 0x0641, 0x0642, 0x0637, 0x0020, 0x0645, 0x0639, 0x0020, 
-    0x0627, 0x0644, 0x0623, 0x0631, 0x0642, 0x0627, 0x0645, 0x060C, 
-    0x0020, 0x0648, 0x062A, 0x0642, 0x0648, 0x0645, 0x0020, 0x0628, 
-    0x062A, 0x062E, 0x0632, 0x064A, 0x0646, 0x0020, 0x0627, 0x0644, 
-    0x0623, 0x062D, 0x0631, 0x0641, 0x0020, 0x0648, 0x0627, 0x0644, 
-    0x0645, 0x062D, 0x0627, 0x0631, 0x0641, 0x0020, 0x0627, 0x0644, 
-    0x0623, 0x062E, 0x0631, 0x0649, 0x0020, 0x0628, 0x0639, 0x062F, 
-    0x0020, 0x0623, 0x0646, 0x0020, 0x062A, 0x064F, 0x0639, 0x0637, 
-    0x064A, 0x0020, 0x0631, 0x0642, 0x0645, 0x0627, 0x0020, 0x0645, 
-    0x0639, 0x064A, 0x0646, 0x0627, 0x0020, 0x0644, 0x0643, 0x0644, 
-    0x0020, 0x0648, 0x0627, 0x062D, 0x062F, 0x0020, 0x0645, 0x0646, 
-    0x0647, 0x0627, 0x002E, 0x0020, 0x0648, 0x0642, 0x0628, 0x0644, 
-    0x0020, 0x0627, 0x062E, 0x062A, 0x0631, 0x0627, 0x0639, 0x0020, 
-    0x0022, 0x064A, 0x0648, 0x0646, 0x0650, 0x0643, 0x0648, 0x062F, 
-    0x0022, 0x060C, 0x0020, 0x0643, 0x0627, 0x0646, 0x0020, 0x0647, 
-    0x0646, 0x0627, 0x0643, 0x0020, 0x0645, 0x0626, 0x0627, 0x062A, 
-    0x0020, 0x0627, 0x0644, 0x0623, 0x0646, 0x0638, 0x0645, 0x0629, 
-    0x0020, 0x0644, 0x0644, 0x062A, 0x0634, 0x0641, 0x064A, 0x0631, 
-    0x0020, 0x0648, 0x062A, 0x062E, 0x0635, 0x064A, 0x0635, 0x0020, 
-    0x0647, 0x0630, 0x0647, 0x0020, 0x0627, 0x0644, 0x0623, 0x0631, 
-    0x0642, 0x0627, 0x0645, 0x0020, 0x0644, 0x0644, 0x0645, 0x062D, 
-    0x0627, 0x0631, 0x0641, 0x060C, 0x0020, 0x0648, 0x0644, 0x0645, 
-    0x0020, 0x064A, 0x0648, 0x062C, 0x062F, 0x0020, 0x0646, 0x0638, 
-    0x0627, 0x0645, 0x0020, 0x062A, 0x0634, 0x0641, 0x064A, 0x0631, 
-    0x0020, 0x0648, 0x0627, 0x062D, 0x062F, 0x0020, 0x064A, 0x062D, 
-    0x062A, 0x0648, 0x064A, 0x0020, 0x0639, 0x0644, 0x0649, 0x0020, 
-    0x062C, 0x0645, 0x064A, 0x0639, 0x0020, 0x0627, 0x0644, 0x0645, 
-    0x062D, 0x0627, 0x0631, 0x0641, 0x0020, 0x0627, 0x0644, 0x0636, 
-    0x0631, 0x0648, 0x0631, 0x064A, 0x0629
-    
-    /* The next few sentences...
-    0x002E, 0x0020, 0x0648, 
-    0x0639, 0x0644, 0x0649, 0x0020, 0x0633, 0x0628, 0x064A, 0x0644, 
-    0x0020, 0x0627, 0x0644, 0x0645, 0x062B, 0x0627, 0x0644, 0x060C, 
-    0x0020, 0x0641, 0x0625, 0x0646, 0x0020, 0x0627, 0x0644, 0x0627, 
-    0x062A, 0x062D, 0x0627, 0x062F, 0x0020, 0x0627, 0x0644, 0x0623, 
-    0x0648, 0x0631, 0x0648, 0x0628, 0x064A, 0x0020, 0x0644, 0x0648, 
-    0x062D, 0x062F, 0x0647, 0x060C, 0x0020, 0x0627, 0x062D, 0x062A, 
-    0x0648, 0x0649, 0x0020, 0x0627, 0x0644, 0x0639, 0x062F, 0x064A, 
-    0x062F, 0x0020, 0x0645, 0x0646, 0x0020, 0x0627, 0x0644, 0x0634, 
-    0x0641, 0x0631, 0x0627, 0x062A, 0x0020, 0x0627, 0x0644, 0x0645, 
-    0x062E, 0x062A, 0x0644, 0x0641, 0x0629, 0x0020, 0x0644, 0x064A, 
-    0x063A, 0x0637, 0x064A, 0x0020, 0x062C, 0x0645, 0x064A, 0x0639, 
-    0x0020, 0x0627, 0x0644, 0x0644, 0x063A, 0x0627, 0x062A, 0x0020, 
-    0x0627, 0x0644, 0x0645, 0x0633, 0x062A, 0x062E, 0x062F, 0x0645, 
-    0x0629, 0x0020, 0x0641, 0x064A, 0x0020, 0x0627, 0x0644, 0x0627, 
-    0x062A, 0x062D, 0x0627, 0x062F, 0x002E, 0x0020, 0x0648, 0x062D, 
-    0x062A, 0x0649, 0x0020, 0x0644, 0x0648, 0x0020, 0x0627, 0x0639, 
-    0x062A, 0x0628, 0x0631, 0x0646, 0x0627, 0x0020, 0x0644, 0x063A, 
-    0x0629, 0x0020, 0x0648, 0x0627, 0x062D, 0x062F, 0x0629, 0x060C, 
-    0x0020, 0x0643, 0x0627, 0x0644, 0x0644, 0x063A, 0x0629, 0x0020, 
-    0x0627, 0x0644, 0x0625, 0x0646, 0x062C, 0x0644, 0x064A, 0x0632, 
-    0x064A, 0x0629, 0x060C, 0x0020, 0x0641, 0x0625, 0x0646, 0x0020, 
-    0x062C, 0x062F, 0x0648, 0x0644, 0x0020, 0x0634, 0x0641, 0x0631, 
-    0x0629, 0x0020, 0x0648, 0x0627, 0x062D, 0x062F, 0x0020, 0x0644, 
-    0x0645, 0x0020, 0x064A, 0x0643, 0x0641, 0x0020, 0x0644, 0x0627, 
-    0x0633, 0x062A, 0x064A, 0x0639, 0x0627, 0x0628, 0x0020, 0x062C, 
-    0x0645, 0x064A, 0x0639, 0x0020, 0x0627, 0x0644, 0x0623, 0x062D, 
-    0x0631, 0x0641, 0x0020, 0x0648, 0x0639, 0x0644, 0x0627, 0x0645, 
-    0x0627, 0x062A, 0x0020, 0x0627, 0x0644, 0x062A, 0x0631, 0x0642, 
-    0x064A, 0x0645, 0x0020, 0x0648, 0x0627, 0x0644, 0x0631, 0x0645, 
-    0x0648, 0x0632, 0x0020, 0x0627, 0x0644, 0x0641, 0x0646, 0x064A, 
-    0x0629, 0x0020, 0x0648, 0x0627, 0x0644, 0x0639, 0x0644, 0x0645, 
-    0x064A, 0x0629, 0x0020, 0x0627, 0x0644, 0x0634, 0x0627, 0x0626, 
-    0x0639, 0x0629, 0x0020, 0x0627, 0x0644, 0x0627, 0x0633, 0x062A, 
-    0x0639, 0x0645, 0x0627, 0x0644, 0x002E */
-};
-le_int32 arabTextLength = ARRAY_LENGTH(arabText);
-
-
-LEUnicode thaiSample[] =
-{
-    0x0E1A, 0x0E17, 0x0E17, 0x0E35, 0x0E48, 0x0E51, 0x0E1E, 0x0E32,
-    0x0E22, 0x0E38, 0x0E44, 0x0E0B, 0x0E42, 0x0E04, 0x0E25, 0x0E19,
-    0x0E42, 0x0E14, 0x0E42, 0x0E23, 0x0E18, 0x0E35, 0x0E2D, 0x0E32, 
-    0x0E28, 0x0E31, 0x0E22, 0x0E2D, 0x0E22, 0x0E39, 0x0E48, 0x0E17,
-    0x0E48, 0x0E32, 0x0E21, 0x0E01, 0x0E25, 0x0E32, 0x0E07, 0x0E17,
-    0x0E38, 0x0E48, 0x0E07, 0x0E43, 0x0E2B, 0x0E0D, 0x0E48, 0x0E43,
-    0x0E19, 0x0E41, 0x0E04, 0x0E19, 0x0E0B, 0x0E31, 0x0E2A, 0x0E01, 
-    0x0E31, 0x0E1A, 0x0E25, 0x0E38, 0x0E07, 0x0E40, 0x0E2E, 0x0E19,
-    0x0E23, 0x0E35, 0x0E0A, 0x0E32, 0x0E27, 0x0E44, 0x0E23, 0x0E48,
-    0x0E41, 0x0E25, 0x0E30, 0x0E1B, 0x0E49, 0x0E32, 0x0E40, 0x0E2D,
-    0x0E47, 0x0E21, 0x0E20, 0x0E23, 0x0E23, 0x0E22, 0x0E32, 0x0E0A,
-    0x0E32, 0x0E27, 0x0E44, 0x0E23, 0x0E48, 0x0E1A, 0x0E49, 0x0E32,
-    0x0E19, 0x0E02, 0x0E2D, 0x0E07, 0x0E1E, 0x0E27, 0x0E01, 0x0E40, 
-    0x0E02, 0x0E32, 0x0E2B, 0x0E25, 0x0E31, 0x0E07, 0x0E40, 0x0E25,
-    0x0E47, 0x0E01, 0x0E40, 0x0E1E, 0x0E23, 0x0E32, 0x0E30, 0x0E44,
-    0x0E21, 0x0E49, 0x0E2A, 0x0E23, 0x0E49, 0x0E32, 0x0E07, 0x0E1A,
-    0x0E49, 0x0E32, 0x0E19, 0x0E15, 0x0E49, 0x0E2D, 0x0E07, 0x0E02, 
-    0x0E19, 0x0E21, 0x0E32, 0x0E14, 0x0E49, 0x0E27, 0x0E22, 0x0E40,
-    0x0E01, 0x0E27, 0x0E35, 0x0E22, 0x0E19, 0x0E40, 0x0E1B, 0x0E47,
-    0x0E19, 0x0E23, 0x0E30, 0x0E22, 0x0E30, 0x0E17, 0x0E32, 0x0E07,
-    0x0E2B, 0x0E25, 0x0E32, 0x0E22, 0x0E44, 0x0E21, 0x0E25, 0x0E4C
-    /* A few more lines...
-    0x0E1A, 0x0E49, 0x0E32, 0x0E19, 0x0E21, 0x0E35, 0x0E2A, 0x0E35,
-    0x0E48, 0x0E1D, 0x0E32, 0x0E21, 0x0E35, 0x0E1E, 0x0E37, 0x0E49,
-    0x0E19, 0x0E01, 0x0E31, 0x0E1A, 0x0E2B, 0x0E25, 0x0E31, 0x0E07,
-    0x0E04, 0x0E32, 0x0E23, 0x0E27, 0x0E21, 0x0E17, 0x0E33, 0x0E40,
-    0x0E1B, 0x0E47, 0x0E19, 0x0E2B, 0x0E49, 0x0E2D, 0x0E07, 0x0E40,
-    0x0E14, 0x0E35, 0x0E22, 0x0E27, 0x0E43, 0x0E19, 0x0E2B, 0x0E49, 
-    0x0E2D, 0x0E07, 0x0E21, 0x0E35, 0x0E17, 0x0E31, 0x0E49, 0x0E07,
-    0x0E40, 0x0E15, 0x0E32, 0x0E2B, 0x0E38, 0x0E07, 0x0E15, 0x0E49,
-    0x0E21, 0x0E17, 0x0E35, 0x0E48, 0x0E2A, 0x0E19, 0x0E34, 0x0E21,
-    0x0E14, 0x0E39, 0x0E02, 0x0E36, 0x0E49, 0x0E19, 0x0E40, 0x0E25,
-    0x0E2D, 0x0E30, 0x0E21, 0x0E35, 0x0E15, 0x0E39, 0x0E49, 0x0E43, 
-    0x0E2A, 0x0E48, 0x0E16, 0x0E49, 0x0E27, 0x0E22, 0x0E0A, 0x0E32,
-    0x0E21, 0x0E42, 0x0E15, 0x0E4A, 0x0E30, 0x0E40, 0x0E01, 0x0E49,
-    0x0E32, 0x0E2D, 0x0E35, 0x0E49, 0x0E2A, 0x0E32, 0x0E21, 0x0E2B,
-    0x0E23
-    */
-};
-
-le_int32 thaiSampleLength = ARRAY_LENGTH(thaiSample);
-
-TestInput testInputs[] = {
-    {"raghu.ttf",             devaText,   devaTextLength,   devaScriptCode, false},
-    {"CODE2000.TTF",             arabText,   arabTextLength,   arabScriptCode, true},
-    {"LucidaSansRegular.ttf", arabText,   arabTextLength,   arabScriptCode, true},
-    {"Thonburi.ttf",          thaiSample, thaiSampleLength, thaiScriptCode, false}
-};
-
-#define TEST_COUNT ARRAY_LENGTH(testInputs)
-
-le_int32 testCount = TEST_COUNT;
-
-void dumpShorts(FILE *file, char *label, le_int32 id, le_uint16 *shorts, le_int32 count) {
-    char lineBuffer[8 * 8 + 2];
-    le_int32 bufp = 0;
-
-    fprintf(file, label, id);
-
-    for (int i = 0; i < count; i += 1) {
-        if (i % 8 == 0 && bufp != 0) {
-            fprintf(file, "    %s\n", lineBuffer);
-            bufp = 0;
-        }
+    return srcDataDir;
+}
 
-        bufp += sprintf(&lineBuffer[bufp], "0x%4.4X, ", shorts[i]);
-    }
+const char *getPath(char buffer[2048], const char *filename) {
+    const char *testDataDirectory = getSourceTestData();
 
-    if (bufp != 0) {
-        lineBuffer[bufp - 2] = '\0';
-        fprintf(file, "    %s\n", lineBuffer);
-    }
+    strcpy(buffer, testDataDirectory);
+    strcat(buffer, filename);
 
-    fprintf(file, "};\n\n");
+    return buffer;
 }
 
-void dumpLongs(FILE *file, char *label, le_int32 id, le_int32 *longs, le_int32 count) {
+/* 
+ * FIXME: should use the output file name and the current date.
+ */
+const char *header =
+    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+    "\n"
+    "<!--\n"
+    "  Copyright (c) 1999-%4.4d International Business Machines\n"
+    "  Corporation and others. All rights reserved.\n"
+    "\n"
+    "  WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT\n"
+    "  UNLESS YOU REALLY KNOW WHAT YOU'RE DOING.\n"
+    "\n"
+    "  file name:    letest.xml\n"
+    "  generated on: %s\n"
+    "  generated by: gendata.cpp\n"
+    "-->\n"
+    "\n"
+    "<layout-tests>\n";
+
+void dumpLongs(FILE *file, const char *tag, le_int32 *longs, le_int32 count) {
     char lineBuffer[8 * 12 + 2];
     le_int32 bufp = 0;
 
-    fprintf(file, label, id);
+    fprintf(file, "        <%s>\n", tag);
 
     for (int i = 0; i < count; i += 1) {
         if (i % 8 == 0 && bufp != 0) {
-            fprintf(file, "    %s\n", lineBuffer);
+            fprintf(file, "            %s\n", lineBuffer);
             bufp = 0;
         }
 
@@ -305,124 +114,270 @@ void dumpLongs(FILE *file, char *label, le_int32 id, le_int32 *longs, le_int32 c
 
     if (bufp != 0) {
         lineBuffer[bufp - 2] = '\0';
-        fprintf(file, "    %s\n", lineBuffer);
+        fprintf(file, "            %s\n", lineBuffer);
     }
 
-    fprintf(file, "};\n\n");
+    fprintf(file, "        </%s>\n\n", tag);
 }
 
-void dumpFloats(FILE *file, char *label, le_int32 id, float *floats, le_int32 count) {
+void dumpFloats(FILE *file, const char *tag, float *floats, le_int32 count) {
     char lineBuffer[8 * 16 + 2];
     le_int32 bufp = 0;
 
-    fprintf(file, label, id);
+    fprintf(file, "        <%s>\n", tag);
 
     for (int i = 0; i < count; i += 1) {
         if (i % 8 == 0 && bufp != 0) {
-            fprintf(file, "    %s\n", lineBuffer);
+            fprintf(file, "            %s\n", lineBuffer);
             bufp = 0;
         }
 
-        bufp += sprintf(&lineBuffer[bufp], "%fF, ", floats[i]);
+        bufp += sprintf(&lineBuffer[bufp], "%f, ", floats[i]);
     }
 
     if (bufp != 0) {
         lineBuffer[bufp - 2] = '\0';
-        fprintf(file, "    %s\n", lineBuffer);
+        fprintf(file, "            %s\n", lineBuffer);
     }
 
-    fprintf(file, "};\n\n");
-}
-
-const char *getShortName(le_int32 scriptCode)
-{
-    static char shortName[5];
-    const char *name = uscript_getShortName((UScriptCode) scriptCode);
-
-    shortName[0] = tolower(name[0]);
-    shortName[1] = tolower(name[1]);
-    shortName[2] = tolower(name[2]);
-    shortName[3] = tolower(name[3]);
-    shortName[4] = '\0';
-
-    return shortName;
+    fprintf(file, "        </%s>\n", tag);
 }
 
 int main(int argc, char *argv[])
 {
-    le_int32 test;
+    UErrorCode status = U_ZERO_ERROR;
+    const char *gendataFile = "gendata.xml";
     FILE *outputFile = fopen(argv[1], "w");
-
-    fprintf(outputFile, header);
-
-    for (test = 0; test < testCount; test += 1) {
-        LEErrorCode fontStatus = LE_NO_ERROR;
-        PortableFontInstance fontInstance(testInputs[test].fontName, 12, fontStatus);
-
-        if (LE_FAILURE(fontStatus)) {
-            printf("ERROR: test case %d, could not get a font instance for %s\n", test, testInputs[test].fontName);
-            continue;
-        }
-
-        LEErrorCode success = LE_NO_ERROR;
-        LayoutEngine *engine = LayoutEngine::layoutEngineFactory(&fontInstance, testInputs[test].scriptCode, -1, success);
-        le_uint32  glyphCount;
-        LEGlyphID *glyphs;
-        le_int32  *indices;
-        float     *positions;
-
-        if (LE_FAILURE(success)) {
-            printf("ERROR: test case %d, could not create a LayoutEngine for script %s.\n", test, uscript_getName((UScriptCode) testInputs[test].scriptCode));
-            continue;
-        }
-
-        glyphCount = engine->layoutChars(testInputs[test].text, 0, testInputs[test].textLength, testInputs[test].textLength, testInputs[test].rightToLeft, 0, 0, success);
-
-        glyphs    = new LEGlyphID[glyphCount];
-        indices   = new le_int32[glyphCount];
-        positions = new float[glyphCount * 2 + 2];
-
-        engine->getGlyphs(glyphs, success);
-        engine->getCharIndices(indices, success);
-        engine->getGlyphPositions(positions, success);
-
-        //fprintf(outputFile, "font: %s\n", testInputs[test].fontName);
-        dumpShorts(outputFile, "LEUnicode inputText%d[] =\n{\n", test, testInputs[test].text, testInputs[test].textLength);
-
-        dumpLongs(outputFile, "LEGlyphID resultGlyphs%d[] =\n{\n", test, (le_int32 *) glyphs, glyphCount);
-        fprintf(outputFile, "le_int32 resultGlyphCount%d = %d;\n\n", test, glyphCount);
-
-        dumpLongs(outputFile, "le_int32 resultIndices%d[] =\n{\n", test, indices, glyphCount);
-
-        dumpFloats(outputFile, "float resultPositions%d[] =\n{\n", test, positions, glyphCount * 2 + 2);
-
-        fprintf(outputFile, "\n");
-
-        delete[] positions;
-        delete[] indices;
-        delete[] glyphs;
-        delete   engine;
+    if(argc>2) {
+      gendataFile = argv[2];
+    }
+    time_t now = time(NULL);
+    struct tm *local = localtime(&now);
+    const char *tmFormat = "%m/%d/%Y %I:%M:%S %p %Z";
+    char  tmString[64];
+    le_uint32 count = 0;
+    strftime(tmString, 64, tmFormat, local);
+    fprintf(outputFile, header, local->tm_year + 1900, tmString);
+
+    UXMLParser  *parser = UXMLParser::createParser(status);
+    UXMLElement *root   = parser->parseFile(gendataFile, status);
+
+    if (root == NULL) {
+      printf("Error: Could not open %s\n", gendataFile);
+        delete parser;
+        return -1;
+    } else if(U_FAILURE(status)) {
+      printf("Error reading %s: %s\n", gendataFile, u_errorName(status));
+      return -2;
+    } else {
+      printf("Reading %s\n", gendataFile);
     }
 
-    fprintf(outputFile, "TestInput testInputs[] = \n{\n");
-
-    for (test = 0; test < testCount; test += 1) {
-        fprintf(outputFile, "    {\"%s\", inputText%d, %d, %sScriptCode, %s},\n",
-            testInputs[test].fontName, test, testInputs[test].textLength, getShortName(testInputs[test].scriptCode),
-            testInputs[test].rightToLeft? "true" : "false");
+    UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
+    UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
+    UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
+
+    // test-case attributes
+    UnicodeString id_attr     = UNICODE_STRING_SIMPLE("id");
+    UnicodeString script_attr = UNICODE_STRING_SIMPLE("script");
+    UnicodeString lang_attr   = UNICODE_STRING_SIMPLE("lang");
+
+    // test-font attributes
+    UnicodeString name_attr   = UNICODE_STRING_SIMPLE("name");
+
+    const UXMLElement *testCase;
+    int32_t tc = 0;
+
+    while((testCase = root->nextChildElement(tc)) != NULL) {
+        if (testCase->getTagName().compare(test_case) == 0) {
+            char *id = getCString(testCase->getAttribute(id_attr));
+            char *script = getCString(testCase->getAttribute(script_attr));
+            char *lang   = getCString(testCase->getAttribute(lang_attr));
+            ++count;
+            printf("\n ID %s\n", id);
+            LEFontInstance *font = NULL;
+            const UXMLElement *element;
+            int32_t ec = 0;
+            int32_t charCount = 0;
+            int32_t typoFlags = LayoutEngine::kTypoFlagKern | LayoutEngine::kTypoFlagLiga; // kerning + ligatures...
+            UScriptCode scriptCode;
+            le_int32 languageCode = -1;
+            UnicodeString text;
+            int32_t glyphCount = 0;
+            LEErrorCode leStatus = LE_NO_ERROR;
+            LayoutEngine *engine = NULL;
+            LEGlyphID *glyphs    = NULL;
+            le_int32  *indices   = NULL;
+            float     *positions = NULL;
+
+            uscript_getCode(script, &scriptCode, 1, &status);
+            if (LE_FAILURE(status)) {
+                printf("Error: invalid script name: %s.\n", script);
+                goto free_c_strings;
+            }
+
+            if (lang != NULL) {
+                languageCode = getLanguageCode(lang);
+
+                if (languageCode < 0) {
+                    printf("Error: invalid language name: %s.\n", lang);
+                    goto free_c_strings;
+                }
+
+                fprintf(outputFile, "    <test-case id=\"%s\" script=\"%s\" lang=\"%s\">\n", id, script, lang);
+            } else {
+                fprintf(outputFile, "    <test-case id=\"%s\" script=\"%s\">\n", id, script);
+            }
+
+            while((element = testCase->nextChildElement(ec)) != NULL) {
+                UnicodeString tag = element->getTagName();
+
+                // TODO: make sure that each element is only used once.
+                if (tag.compare(test_font) == 0) {
+                    char *fontName  = getCString(element->getAttribute(name_attr));
+                    const char *version = NULL;
+                    char buf[2048];
+                    PortableFontInstance *pfi = new PortableFontInstance(getPath(buf,fontName), 12, leStatus);
+                    
+                    if (LE_FAILURE(leStatus)) {
+                      printf("Error: could not open font: %s (path: %s)\n", fontName, buf);
+                        freeCString(fontName);
+                        goto free_c_strings;
+                    }
+
+                    printf(" Generating: %s, %s, %s, %s\n", id, script, lang, fontName);
+
+                    version = pfi->getNameString(NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
+
+                    // The standard recommends that the Macintosh Roman/English name string be present, but
+                    // if it's not, try the Microsoft Unicode/English string.
+                    if (version == NULL) {
+                        const LEUnicode16 *uversion = pfi->getUnicodeNameString(NAME_VERSION_STRING, PLATFORM_MICROSOFT, MICROSOFT_UNICODE_BMP, MICROSOFT_ENGLISH);
+
+                        if (uversion != NULL) {
+                          char uversion_utf8[300];
+                          UErrorCode status2 = U_ZERO_ERROR;
+                          u_strToUTF8(uversion_utf8, 300, NULL, uversion, -1, &status2);
+                          if(U_FAILURE(status2)) {
+                            uversion_utf8[0]=0;
+                          }
+                            fprintf(outputFile, "        <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
+                                    fontName, uversion_utf8, pfi->getFontChecksum(), pfi->getRawChecksum());
+
+                            pfi->deleteNameString(uversion);
+                        } else {
+                          fprintf(outputFile, "        <test-font name=\"%s\" version=\"unknown-0x%8.8X\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
+                                  fontName, pfi->getFontChecksum(), pfi->getFontChecksum(), pfi->getRawChecksum());
+                        }
+                    } else {
+                        fprintf(outputFile, "        <test-font name=\"%s\" version=\"%s\" checksum=\"0x%8.8X\" rchecksum=\"0x%8.8X\"/>\n\n",
+                                fontName, version, pfi->getFontChecksum(), pfi->getRawChecksum());
+
+                        pfi->deleteNameString(version);
+                    }
+                    fflush(outputFile);
+
+                    freeCString(fontName);
+
+                    font = pfi;
+                } else if (tag.compare(test_text) == 0) {
+                    char *utf8 = NULL;
+
+                    text = element->getText(TRUE);
+                    charCount = text.length();
+
+                    utf8 = getUTF8String(&text);
+                    fprintf(outputFile, "        <test-text>%s</test-text>\n\n", utf8);
+                    fflush(outputFile);
+                    freeCString(utf8);
+                } else {
+                    // an unknown tag...
+                    char *cTag = getCString(&tag);
+
+                    printf("Test %s: unknown element with tag \"%s\"\n", id, cTag);
+                    freeCString(cTag);
+                }
+            }
+
+            if (font == NULL) {
+                LEErrorCode fontStatus = LE_NO_ERROR;
+
+                font = new SimpleFontInstance(12, fontStatus);
+                typoFlags |= 0x80000000L;  // use CharSubstitutionFilter...
+            }
+
+            engine = LayoutEngine::layoutEngineFactory(font, scriptCode, languageCode, typoFlags, leStatus);
+
+            if (LE_FAILURE(leStatus)) {
+                printf("Error for test %s: could not create a LayoutEngine.\n", id);
+                goto delete_font;
+            }
+
+            glyphCount = engine->layoutChars(text.getBuffer(), 0, charCount, charCount, getRTL(text), 0, 0, leStatus);
+
+            glyphs    = NEW_ARRAY(LEGlyphID, glyphCount);
+            indices   = NEW_ARRAY(le_int32, glyphCount);
+            positions = NEW_ARRAY(float, glyphCount * 2 + 2);
+
+            engine->getGlyphs(glyphs, leStatus);
+            engine->getCharIndices(indices, leStatus);
+            engine->getGlyphPositions(positions, leStatus);
+
+            if(LE_FAILURE(leStatus)) {
+              fprintf(stderr,"ERROR: LO returned error: %s\n", u_errorName((UErrorCode)leStatus));
+              overallStatus = leStatus;
+              fprintf(outputFile, "<!-- ERROR: %d -->\n", leStatus);
+              fflush(outputFile);
+              leStatus = LE_NO_ERROR;
+            } else {
+              dumpLongs(outputFile, "result-glyphs", (le_int32 *) glyphs, glyphCount);
+              
+              dumpLongs(outputFile, "result-indices", indices, glyphCount);
+              
+              dumpFloats(outputFile, "result-positions", positions, glyphCount * 2 + 2);
+              fflush(outputFile);
+
+            }
+
+            DELETE_ARRAY(positions);
+            DELETE_ARRAY(indices);
+            DELETE_ARRAY(glyphs);
+
+            delete engine;
+
+delete_font:
+            fprintf(outputFile, "    </test-case>\n\n");
+            fflush(outputFile);
+
+            delete font;
+
+free_c_strings:
+            freeCString(lang);
+            freeCString(script);
+            freeCString(id);
+        }
     }
 
-    fprintf(outputFile, "};\n\nle_int32 testCount = ARRAY_LENGTH(testInputs);\n\n");
+    delete root;
+    delete parser;
 
-    fprintf(outputFile, "TestResult testResults[] = \n{\n");
+    fprintf(outputFile, "</layout-tests>\n");
 
-    for (test = 0; test < testCount; test += 1) {
-        fprintf(outputFile, "    {resultGlyphCount%d, resultGlyphs%d, resultIndices%d, resultPositions%d},\n",
-            test, test, test, test);
+    if(count==0) {
+      fprintf(stderr, "No cases processed!\n");
+      return 1;
     }
 
-    fprintf(outputFile, "};\n\n");
 
-    fclose(outputFile);
-    return 0;
+    if(LE_FAILURE(overallStatus)) {
+      fprintf(outputFile, "<!-- !!! FAILED. %d -->\n", overallStatus);
+      fprintf(stderr, "!!! FAILED. %d\n", overallStatus);
+      fclose(outputFile);
+      return 0;
+      //      return 1;
+    } else {
+      printf("Generated.\n");
+      fclose(outputFile);
+      return 0;
+    }
 }