]> granicus.if.org Git - icu/commitdiff
ICU-10234 check in layout engine perf test
authorSteven R. Loomis <srl@icu-project.org>
Thu, 27 Jun 2013 17:37:58 +0000 (17:37 +0000)
committerSteven R. Loomis <srl@icu-project.org>
Thu, 27 Jun 2013 17:37:58 +0000 (17:37 +0000)
X-SVN-Rev: 33861

20 files changed:
icu4c/source/configure
icu4c/source/configure.in
icu4c/source/test/perf/leperf/FontObject.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/FontObject.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/FontTableCache.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/FontTableCache.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/Makefile.in [new file with mode: 0644]
icu4c/source/test/perf/leperf/PortableFontInstance.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/PortableFontInstance.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/SimpleFontInstance.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/SimpleFontInstance.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/cfonts.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/cfonts.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/cmaps.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/cmaps.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/leperf.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/letrperf.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/sfnt.h [new file with mode: 0644]
icu4c/source/test/perf/leperf/xmlreader.cpp [new file with mode: 0644]
icu4c/source/test/perf/leperf/xmlreader.h [new file with mode: 0644]

index 1a20f41d78a4f285285d9b8c6ed8e850024f3406..a37b772e006409244bc489db880a605d029912e0 100755 (executable)
@@ -1,13 +1,11 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68.
+# Generated by GNU Autoconf 2.69.
 #
 #  Copyright (c) 1999-2012, International Business Machines Corporation and others. All Rights Reserved.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -136,6 +134,31 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -169,7 +192,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -214,21 +238,25 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-       # neutralization value for shells without unset; and this also
-       # works around shells that cannot unset nonexistent variables.
-       # Preserve -v and -x to the replacement shell.
-       BASH_ENV=/dev/null
-       ENV=/dev/null
-       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-       export CONFIG_SHELL
-       case $- in # ((((
-         *v*x* | *x*v* ) as_opts=-vx ;;
-         *v* ) as_opts=-v ;;
-         *x* ) as_opts=-x ;;
-         * ) as_opts= ;;
-       esac
-       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -330,6 +358,14 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -451,6 +487,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -485,16 +525,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -506,28 +546,8 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -1223,8 +1243,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1490,9 +1508,9 @@ test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
 configure
-generated by GNU Autoconf 2.68
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 
@@ -1645,7 +1663,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -1723,7 +1741,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) >= 0)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -1739,7 +1758,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -1765,7 +1785,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) < 0)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -1781,7 +1802,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) >= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -1815,7 +1837,8 @@ int
 main ()
 {
 static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0
+test_array [0] = 0;
+return test_array [0];
 
   ;
   return 0;
@@ -1942,7 +1965,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2173,7 +2196,7 @@ This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -2764,7 +2787,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2808,7 +2831,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3252,8 +3275,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -3368,7 +3390,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3412,7 +3434,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3794,7 +3816,7 @@ case $as_dir/ in #((
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
          if test $ac_prog = install &&
            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
@@ -3915,7 +3937,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_U_MAKE="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3991,7 +4013,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4110,7 +4132,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -4176,7 +4198,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -5200,7 +5222,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5240,7 +5262,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5294,7 +5316,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="${ac_tool_prefix}ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5334,7 +5356,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7325,7 +7347,7 @@ echo "CXXFLAGS=$CXXFLAGS"
 
 
 # output the Makefiles
-ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layout/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile"
+ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layout/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile test/perf/leperf/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -7771,16 +7793,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -7840,28 +7862,16 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -7883,7 +7893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # values after options handling.
 ac_log="
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -7936,10 +7946,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.68,
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -8017,7 +8027,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
@@ -8107,6 +8117,7 @@ do
     "test/perf/ustrperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/ustrperf/Makefile" ;;
     "test/perf/utfperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utfperf/Makefile" ;;
     "test/perf/utrie2perf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utrie2perf/Makefile" ;;
+    "test/perf/leperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/leperf/Makefile" ;;
     "samples/Makefile") CONFIG_FILES="$CONFIG_FILES samples/Makefile" ;;
     "samples/date/Makefile") CONFIG_FILES="$CONFIG_FILES samples/date/Makefile" ;;
     "samples/cal/Makefile") CONFIG_FILES="$CONFIG_FILES samples/cal/Makefile" ;;
index 2e33779997d8cfadcf064f1d1b67ed2f2e1e06b9..fb1eda92c7d743594430cc9034828e3690ec5008 100644 (file)
@@ -1265,6 +1265,7 @@ AC_CONFIG_FILES([icudefs.mk \
                test/perf/ustrperf/Makefile \
                test/perf/utfperf/Makefile \
                test/perf/utrie2perf/Makefile \
+                test/perf/leperf/Makefile \
                samples/Makefile samples/date/Makefile \
                samples/cal/Makefile samples/layout/Makefile])
 AC_OUTPUT
diff --git a/icu4c/source/test/perf/leperf/FontObject.cpp b/icu4c/source/test/perf/leperf/FontObject.cpp
new file mode 100644 (file)
index 0000000..1d6f6ec
--- /dev/null
@@ -0,0 +1,240 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#include <stdio.h>
+
+#include "LETypes.h"
+#include "FontObject.h"
+#include "LESwaps.h"
+
+FontObject::FontObject(char *fileName)
+  : directory(NULL), numTables(0), searchRange(0),entrySelector(0),
+    cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0),
+    cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0),
+    headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL)
+{
+    file = fopen(fileName, "rb");
+
+    if (file == NULL) {
+        printf("?? Couldn't open %s", fileName);
+        return;
+    }
+
+    SFNTDirectory tempDir;
+
+    fread(&tempDir, sizeof tempDir, 1, file);
+
+    numTables       = SWAPW(tempDir.numTables);
+    searchRange     = SWAPW(tempDir.searchRange) >> 4;
+    entrySelector   = SWAPW(tempDir.entrySelector);
+    rangeShift      = SWAPW(tempDir.rangeShift) >> 4;
+
+    int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry));
+
+    directory = (SFNTDirectory *) new char[dirSize];
+
+    fseek(file, 0L, SEEK_SET);
+    fread(directory, sizeof(char), dirSize, file);
+
+    initUnicodeCMAP();
+}
+
+FontObject::~FontObject()
+{
+    fclose(file);
+    delete[] directory;
+    delete[] cmapTable;
+    delete[] headTable;
+    delete[] hmtxTable;
+}
+
+void FontObject::deleteTable(void *table)
+{
+    delete[] (char *) table;
+}
+
+DirectoryEntry *FontObject::findTable(LETag tag)
+{
+    le_uint16 table = 0;
+    le_uint16 probe = 1 << entrySelector;
+
+    if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) {
+        table = rangeShift;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) {
+            table += probe;
+        }
+    }
+
+    if (SWAPL(directory->tableDirectory[table].tag) == tag) {
+        return &directory->tableDirectory[table];
+    }
+
+    return NULL;
+}
+
+void *FontObject::readTable(LETag tag, le_uint32 *length)
+{
+    DirectoryEntry *entry = findTable(tag);
+
+    if (entry == NULL) {
+        *length = 0;
+        return NULL;
+    }
+
+    *length = SWAPL(entry->length);
+
+    void *table = new char[*length];
+
+    fseek(file, SWAPL(entry->offset), SEEK_SET);
+    fread(table, sizeof(char), *length, file);
+
+    return table;
+}
+
+CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID)
+{
+    LETag cmapTag = 0x636D6170; // 'cmap'
+
+    if (cmapTable == NULL) {
+        le_uint32 length;
+
+        cmapTable = (CMAPTable *) readTable(cmapTag, &length);
+    }
+
+    if (cmapTable != NULL) {
+        le_uint16 i;
+        le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables);
+
+
+        for (i = 0; i < nSubtables; i += 1) {
+            CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i];
+
+            if (SWAPW(esh->platformID) == platformID &&
+                SWAPW(esh->platformSpecificID) == platformSpecificID) {
+                return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset));
+            }
+        }
+    }
+
+    return NULL;
+}
+
+void FontObject::initUnicodeCMAP()
+{
+    CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1);
+
+    if (encodingSubtable == 0 ||
+        SWAPW(encodingSubtable->format) != 4) {
+        printf("Can't find unicode 'cmap'");
+        return;
+    }
+
+    CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable;
+
+    cmSegCount = SWAPW(header->segCountX2) / 2;
+    cmSearchRange = SWAPW(header->searchRange);
+    cmEntrySelector = SWAPW(header->entrySelector);
+    cmRangeShift = SWAPW(header->rangeShift) / 2;
+    cmEndCodes = &header->endCodes[0];
+    cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad...
+    cmIdDelta = &cmStartCodes[cmSegCount];
+    cmIdRangeOffset = &cmIdDelta[cmSegCount];
+}
+
+LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32)
+{
+    if (unicode32 >= 0x10000) {
+        return 0;
+    }
+
+    LEUnicode16 unicode = (LEUnicode16) unicode32;
+    le_uint16 index = 0;
+    le_uint16 probe = 1 << cmEntrySelector;
+    LEGlyphID result = 0;
+
+    if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) {
+        index = cmRangeShift;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPW(cmStartCodes[index + probe]) <= unicode) {
+            index += probe;
+        }
+    }
+
+    if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) {
+        if (cmIdRangeOffset[index] == 0) {
+            result = (LEGlyphID) unicode;
+        } else {
+            le_uint16 offset = unicode - SWAPW(cmStartCodes[index]);
+            le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]);
+            le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset);
+
+            result = SWAPW(glyphIndexTable[offset]);
+        }
+
+        result += SWAPW(cmIdDelta[index]);
+    } else {
+        result = 0;
+    }
+
+    return result;
+}
+
+le_uint16 FontObject::getUnitsPerEM()
+{
+    if (headTable == NULL) {
+        LETag headTag = 0x68656164; // 'head'
+        le_uint32 length;
+
+        headTable = (HEADTable *) readTable(headTag, &length);
+    }
+
+    return SWAPW(headTable->unitsPerEm);
+}
+
+le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph)
+{
+    if (hmtxTable == NULL) {
+        LETag maxpTag = 0x6D617870; // 'maxp'
+        LETag hheaTag = 0x68686561; // 'hhea'
+        LETag hmtxTag = 0x686D7478; // 'hmtx'
+        le_uint32 length;
+        HHEATable *hheaTable;
+        MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length);
+
+        numGlyphs = SWAPW(maxpTable->numGlyphs);
+        deleteTable(maxpTable);
+
+        hheaTable = (HHEATable *) readTable(hheaTag, &length);
+        numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
+        deleteTable(hheaTable);
+
+        hmtxTable = (HMTXTable *) readTable(hmtxTag, &length);
+    }
+
+    le_uint16 index = glyph;
+
+    if (glyph >= numGlyphs) {
+        return 0;
+    }
+
+    if (glyph >= numOfLongHorMetrics) {
+        index = numOfLongHorMetrics - 1;
+    }
+
+    return SWAPW(hmtxTable->hMetrics[index].advanceWidth);
+}
+
+
diff --git a/icu4c/source/test/perf/leperf/FontObject.h b/icu4c/source/test/perf/leperf/FontObject.h
new file mode 100644 (file)
index 0000000..c7961f5
--- /dev/null
@@ -0,0 +1,235 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+
+#ifndef __FONTOBJECT_H
+#define __FONTOBJECT_H
+
+#include <stdio.h>
+
+#include "LETypes.h"
+
+
+#ifndef ANY_NUMBER
+#define ANY_NUMBER 1
+#endif
+
+struct DirectoryEntry
+{
+    le_uint32   tag;
+    le_uint32   checksum;
+    le_uint32   offset;
+    le_uint32   length;
+};
+
+struct SFNTDirectory
+{
+    le_uint32       scalerType;
+    le_uint16       numTables;
+    le_uint16       searchRange;
+    le_uint16       entrySelector;
+    le_uint16       rangeShift;
+    DirectoryEntry  tableDirectory[ANY_NUMBER];
+};
+
+
+struct CMAPEncodingSubtableHeader
+{
+    le_uint16   platformID;
+    le_uint16   platformSpecificID;
+    le_uint32   encodingOffset;
+};
+
+struct CMAPTable
+{
+    le_uint16   version;
+    le_uint16   numberSubtables;
+    CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
+};
+
+struct CMAPEncodingSubtable
+{
+    le_uint16   format;
+    le_uint16   length;
+    le_uint16   language;
+};
+
+struct CMAPFormat0Encoding : CMAPEncodingSubtable
+{
+    le_uint8    glyphIndexArray[256];
+};
+
+struct CMAPFormat2Subheader
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_int16    idDelta;
+    le_uint16   idRangeOffset;
+};
+
+struct CMAPFormat2Encoding : CMAPEncodingSubtable
+{
+    le_uint16  subHeadKeys[256];
+    CMAPFormat2Subheader subheaders[ANY_NUMBER];
+};
+
+struct CMAPFormat4Encoding : CMAPEncodingSubtable
+{
+    le_uint16   segCountX2;
+    le_uint16   searchRange;
+    le_uint16   entrySelector;
+    le_uint16   rangeShift;
+    le_uint16   endCodes[ANY_NUMBER];
+//  le_uint16   reservedPad;
+//  le_uint16   startCodes[ANY_NUMBER];
+//  le_uint16   idDelta[ANY_NUMBER];
+//  le_uint16   idRangeOffset[ANY_NUMBER];
+//  le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+
+struct CMAPFormat6Encoding : CMAPEncodingSubtable
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+
+typedef le_int32 fixed;
+
+struct BigDate
+{
+    le_uint32 bc;
+    le_uint32 ad;
+};
+
+struct HEADTable
+{
+    fixed       version;
+    fixed       fontRevision;
+    le_uint32   checksumAdjustment;
+    le_uint32   magicNumber;
+    le_uint16   flags;
+    le_uint16   unitsPerEm;
+    BigDate     created;
+    BigDate     modified;
+    le_int16    xMin;
+    le_int16    yMin;
+    le_int16    xMax;
+    le_int16    yMax;
+    le_int16    lowestRecPPEM;
+    le_int16    fontDirectionHint;
+    le_int16    indexToLocFormat;
+    le_int16    glyphDataFormat;
+};
+
+struct MAXPTable
+{
+    fixed       version;
+    le_uint16   numGlyphs;
+    le_uint16   maxPoints;
+    le_uint16   maxContours;
+    le_uint16   maxComponentPoints;
+    le_uint16   maxComponentContours;
+    le_uint16   maxZones;
+    le_uint16   maxTwilightPoints;
+    le_uint16   maxStorage;
+    le_uint16   maxFunctionDefs;
+    le_uint16   maxInstructionDefs;
+    le_uint16   maxStackElements;
+    le_uint16   maxSizeOfInstructions;
+    le_uint16   maxComponentElements;
+    le_uint16   maxComponentDepth;
+};
+
+struct HHEATable
+{
+    fixed       version;
+    le_int16    ascent;
+    le_int16    descent;
+    le_int16    lineGap;
+    le_uint16   advanceWidthMax;
+    le_int16    minLeftSideBearing;
+    le_int16    minRightSideBearing;
+    le_int16    xMaxExtent;
+    le_int16    caretSlopeRise;
+    le_int16    caretSlopeRun;
+    le_int16    caretOffset;
+    le_int16    reserved1;
+    le_int16    reserved2;
+    le_int16    reserved3;
+    le_int16    reserved4;
+    le_int16    metricDataFormat;
+    le_uint16   numOfLongHorMetrics;
+};
+
+struct LongHorMetric
+{
+    le_uint16   advanceWidth;
+    le_int16    leftSideBearing;
+};
+
+struct HMTXTable
+{
+    LongHorMetric hMetrics[ANY_NUMBER];        // ANY_NUMBER = numOfLongHorMetrics from hhea table
+//  le_int16      leftSideBearing[ANY_NUMBER]; // ANY_NUMBER = numGlyphs - numOfLongHorMetrics
+};
+
+class FontObject
+{
+public:
+    FontObject(char *fontName);
+    ~FontObject();
+
+    void *readTable(LETag tag, le_uint32 *length);
+    void deleteTable(void *table);
+
+    LEGlyphID unicodeToGlyph(LEUnicode32 unicode);
+
+#if 0
+    le_uint32 unicodesToGlyphs(LEUnicode *chars, le_uint32 nChars, LEGlyphID *glyphs,
+        le_uint32 *charIndices, le_bool rightToLeft);
+#endif
+
+    le_uint16 getUnitsPerEM();
+
+    le_uint16 getGlyphAdvance(LEGlyphID glyph);
+
+private:
+    FontObject();
+
+    DirectoryEntry *findTable(LETag tag);
+    CMAPEncodingSubtable *findCMAP(le_uint16 platformID, le_uint16 platformSpecificID);
+    void initUnicodeCMAP();
+
+    SFNTDirectory *directory;
+    le_uint16 numTables;
+    le_uint16 searchRange;
+    le_uint16 entrySelector;
+    le_uint16 rangeShift;
+
+    CMAPTable *cmapTable;
+    le_uint16 cmSegCount;
+    le_uint16 cmSearchRange;
+    le_uint16 cmEntrySelector;
+    le_uint16 cmRangeShift;
+    le_uint16 *cmEndCodes;
+    le_uint16 *cmStartCodes;
+    le_uint16 *cmIdDelta;
+    le_uint16 *cmIdRangeOffset;
+
+    HEADTable *headTable;
+
+    HMTXTable *hmtxTable;
+    le_uint16 numGlyphs;
+    le_uint16 numOfLongHorMetrics;
+
+    FILE *file;
+
+};
+
+#endif
+
diff --git a/icu4c/source/test/perf/leperf/FontTableCache.cpp b/icu4c/source/test/perf/leperf/FontTableCache.cpp
new file mode 100644 (file)
index 0000000..a2c0727
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ **********************************************************************
+ *   Copyright (C) 2003-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ **********************************************************************
+ */
+
+#include "layout/LETypes.h"
+
+//#include "letest.h"
+#include "FontTableCache.h"
+
+#define TABLE_CACHE_INIT 5
+#define TABLE_CACHE_GROW 5
+
+struct FontTableCacheEntry
+{
+  LETag tag;
+  const void *table;
+  size_t length;
+};
+
+FontTableCache::FontTableCache()
+    : fTableCacheCurr(0), fTableCacheSize(TABLE_CACHE_INIT)
+{
+    fTableCache = LE_NEW_ARRAY(FontTableCacheEntry, fTableCacheSize);
+
+    if (fTableCache == NULL) {
+        fTableCacheSize = 0;
+        return;
+    }
+
+    for (int i = 0; i < fTableCacheSize; i += 1) {
+        fTableCache[i].tag   = 0;
+        fTableCache[i].table = NULL;
+        fTableCache[i].length = 0;
+    }
+}
+
+FontTableCache::~FontTableCache()
+{
+    for (int i = fTableCacheCurr - 1; i >= 0; i -= 1) {
+      LE_DELETE_ARRAY(fTableCache[i].table);
+
+        fTableCache[i].tag   = 0;
+        fTableCache[i].table = NULL;
+        fTableCache[i].length = 0;
+    }
+
+    fTableCacheCurr = 0;
+
+    LE_DELETE_ARRAY(fTableCache);
+}
+
+void FontTableCache::freeFontTable(const void *table) const
+{
+  LE_DELETE_ARRAY(table);
+}
+
+const void *FontTableCache::find(LETag tableTag, size_t &length) const
+{
+    for (int i = 0; i < fTableCacheCurr; i += 1) {
+        if (fTableCache[i].tag == tableTag) {
+          length = fTableCache[i].length;
+          return fTableCache[i].table;
+        }
+    }
+
+    const void *table = readFontTable(tableTag, length);
+
+    ((FontTableCache *) this)->add(tableTag, table, length);
+
+    return table;
+}
+
+void FontTableCache::add(LETag tableTag, const void *table, size_t length)
+{
+    if (fTableCacheCurr >= fTableCacheSize) {
+        le_int32 newSize = fTableCacheSize + TABLE_CACHE_GROW;
+
+        fTableCache = (FontTableCacheEntry *) LE_GROW_ARRAY(fTableCache, newSize);
+
+        for (le_int32 i = fTableCacheSize; i < newSize; i += 1) {
+            fTableCache[i].tag   = 0;
+            fTableCache[i].table = NULL;
+            fTableCache[i].length = 0;
+        }
+
+        fTableCacheSize = newSize;
+    }
+
+    fTableCache[fTableCacheCurr].tag   = tableTag;
+    fTableCache[fTableCacheCurr].table = table;
+    fTableCache[fTableCacheCurr].length = length;
+
+    fTableCacheCurr += 1;
+}
diff --git a/icu4c/source/test/perf/leperf/FontTableCache.h b/icu4c/source/test/perf/leperf/FontTableCache.h
new file mode 100644 (file)
index 0000000..d0e1c54
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ **********************************************************************
+ *   Copyright (C) 2003-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ **********************************************************************
+ */
+
+#ifndef __FONTTABLECACHE_H
+
+#define __FONTTABLECACHE_H
+
+#include "layout/LETypes.h"
+
+U_NAMESPACE_USE
+
+struct FontTableCacheEntry;
+
+class FontTableCache
+{
+public:
+    FontTableCache();
+
+    virtual ~FontTableCache();
+
+    const void *find(LETag tableTag, size_t &length) const;
+
+protected:
+    virtual const void *readFontTable(LETag tableTag, size_t &length) const = 0;
+    virtual void freeFontTable(const void *table) const;
+
+private:
+
+    void add(LETag tableTag, const void *table, size_t length);
+
+    FontTableCacheEntry *fTableCache;
+    le_int32 fTableCacheCurr;
+    le_int32 fTableCacheSize;
+};
+
+#endif
+
diff --git a/icu4c/source/test/perf/leperf/Makefile.in b/icu4c/source/test/perf/leperf/Makefile.in
new file mode 100644 (file)
index 0000000..d943a57
--- /dev/null
@@ -0,0 +1,83 @@
+## Makefile.in for ICU - test/perf/collperf
+## Copyright (c) 2001-2013, International Business Machines Corporation and
+## others. All Rights Reserved.
+
+## Source directory information
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+top_builddir = ../../..
+
+include $(top_builddir)/icudefs.mk
+
+-include Makefile.local
+
+## Build directory information
+subdir = test/perf/leperf
+
+## Extra files to remove for 'make clean'
+CLEANFILES = *~ $(DEPS)
+
+## Target information
+TARGET = leperf
+
+CPPFLAGS += -I$(top_srcdir)/common -I$(top_srcdir)/layout/.. -I$(top_srcdir)/tools/toolutil -I$(top_srcdir)/tools/ctestfw -I$(top_srcdir)/io -I$(top_srcdir)/i18n
+LIBS = $(LIBCTESTFW) $(LIBICUIO) $(LIBICULE) $(LIBICUUC) $(LIBICUI18N) $(LIBICUTOOLUTIL) $(DEFAULT_LIBS) $(LIB_M)
+
+OBJECTS = $(TARGET).o
+
+DEPS = $(OBJECTS:.o=.d)
+
+## List of phony targets
+.PHONY : all all-local install install-local clean clean-local \
+distclean distclean-local dist dist-local check check-local
+
+## Clear suffix list
+.SUFFIXES :
+
+## List of standard targets
+all: all-local
+install: install-local
+clean: clean-local
+distclean : distclean-local
+dist: dist-local
+check: all check-local
+
+all-local: $(TARGET)
+
+install-local:
+
+dist-local:
+
+clean-local:
+       test -z "$(CLEANFILES)" || $(RMV) $(CLEANFILES)
+       $(RMV) $(OBJECTS) $(TARGET)
+
+distclean-local: clean-local
+       $(RMV) Makefile
+
+check-local: all-local
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+        && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(TARGET) : $(OBJECTS)
+       $(LINK.cc) -o $@ $^ $(LIBS)
+       $(POST_BUILD_STEP)
+
+invoke:
+       @$(RMV) current.out
+# following is bash specific
+       set -o pipefail && ( ICU_DATA=$${ICU_DATA:-$(top_builddir)/data/} TZ=PST8PDT $(INVOKE) ./$(TARGET) $(INVOCATION) | tee current.out )
+
+ifeq (,$(MAKECMDGOALS))
+-include $(DEPS)
+else
+ifneq ($(patsubst %clean,,$(MAKECMDGOALS)),)
+ifneq ($(patsubst %install,,$(MAKECMDGOALS)),)
+-include $(DEPS)
+endif
+endif
+endif
+
diff --git a/icu4c/source/test/perf/leperf/PortableFontInstance.cpp b/icu4c/source/test/perf/leperf/PortableFontInstance.cpp
new file mode 100644 (file)
index 0000000..abbd8ee
--- /dev/null
@@ -0,0 +1,481 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  PortableFontInstance.cpp
+ *
+ *   created on: 11/22/1999
+ *   created by: Eric R. Mader
+ */
+
+#include <stdio.h>
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+#include "layout/LESwaps.h"
+
+#include "PortableFontInstance.h"
+
+//#include "letest.h"
+#include "sfnt.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#if 0
+static const char *letagToStr(LETag tag, char *str) {
+  str[0]= 0xFF & (tag>>24);
+  str[1]= 0xFF & (tag>>16);
+  str[2]= 0xFF & (tag>>8);
+  str[3]= 0xFF & (tag>>0);
+  str[4]= 0;
+  return str;
+}
+#endif
+
+//
+// Finds the high bit by binary searching
+// through the bits in n.
+//
+le_int8 PortableFontInstance::highBit(le_int32 value)
+{
+    if (value <= 0) {
+        return -32;
+    }
+
+    le_uint8 bit = 0;
+
+    if (value >= 1 << 16) {
+        value >>= 16;
+        bit += 16;
+    }
+
+    if (value >= 1 << 8) {
+        value >>= 8;
+        bit += 8;
+    }
+
+    if (value >= 1 << 4) {
+        value >>= 4;
+        bit += 4;
+    }
+
+    if (value >= 1 << 2) {
+        value >>= 2;
+        bit += 2;
+    }
+
+    if (value >= 1 << 1) {
+        value >>= 1;
+        bit += 1;
+    }
+
+    return bit;
+}
+
+PortableFontInstance::PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status)
+    : fFile(NULL), fPointSize(pointSize), fUnitsPerEM(0), fFontChecksum(0), fAscent(0), fDescent(0), fLeading(0),
+      fDirectory(NULL), fNAMETable(NULL), fNameCount(0), fNameStringOffset(0), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
+{
+    if (LE_FAILURE(status)) {
+        return;
+    }
+
+    // open the font file
+    fFile = fopen(fileName, "rb");
+    //printf("Open Font: %s\n", fileName);
+
+    if (fFile == NULL) {
+        printf("%s:%d: %s: FNF\n", __FILE__, __LINE__, fileName);
+        status = LE_FONT_FILE_NOT_FOUND_ERROR;
+        return;
+    }
+
+    // read in the directory
+    SFNTDirectory tempDir;
+
+    fread(&tempDir, sizeof tempDir, 1, fFile);
+
+    le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry));
+    const LETag headTag = LE_HEAD_TABLE_TAG;
+    const LETag hheaTag = LE_HHEA_TABLE_TAG;
+    const HEADTable *headTable = NULL;
+    const HHEATable *hheaTable = NULL;
+//  const NAMETable *nameTable = NULL;
+    le_uint16 numTables = 0;
+
+    fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize);
+
+    if (fDirectory == NULL) {
+        printf("%s:%d: %s: malloc err\n", __FILE__, __LINE__, fileName);
+        status = LE_MEMORY_ALLOCATION_ERROR;
+        goto error_exit;
+    }
+
+    fseek(fFile, 0L, SEEK_SET);
+    fread((void *) fDirectory, sizeof(char), dirSize, fFile);
+
+    //
+    // We calculate these numbers 'cause some fonts
+    // have bogus values for them in the directory header.
+    //
+    numTables = SWAPW(fDirectory->numTables);
+    fDirPower = 1 << highBit(numTables);
+    fDirExtra = numTables - fDirPower;
+
+    // read unitsPerEm from 'head' table
+    headTable = (const HEADTable *) readFontTable(headTag);
+
+    if (headTable == NULL) {
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        printf("%s:%d: %s: missing head table\n", __FILE__, __LINE__, fileName);
+        goto error_exit;
+    }
+
+    fUnitsPerEM   = SWAPW(headTable->unitsPerEm);
+    fFontChecksum = SWAPL(headTable->checksumAdjustment);
+    freeFontTable(headTable);
+
+    //nameTable = (NAMETable *) readFontTable(nameTag);
+
+    //if (nameTable == NULL) {
+    //    status = LE_MISSING_FONT_TABLE_ERROR;
+    //    goto error_exit;
+    //}
+
+    //fFontVersionString = findName(nameTable, NAME_VERSION_STRING, PLATFORM_MACINTOSH, MACINTOSH_ROMAN, MACINTOSH_ENGLISH);
+
+    //if (fFontVersionString == NULL) {
+    //    status = LE_MISSING_FONT_TABLE_ERROR;
+    //    goto error_exit;
+    //}
+
+    //freeFontTable(nameTable);
+
+    hheaTable = (HHEATable *) readFontTable(hheaTag);
+
+    if (hheaTable == NULL) {
+        printf("%s:%d: %s: missing hhea table\n", __FILE__, __LINE__, fileName);
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        goto error_exit;
+    }
+
+    fAscent  = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
+    fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
+    fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
+
+    fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
+
+    freeFontTable((void *) hheaTable);
+
+    fCMAPMapper = findUnicodeMapper();
+
+    if (fCMAPMapper == NULL) {
+        printf("%s:%d: %s: can't load cmap\n", __FILE__, __LINE__, fileName);
+        status = LE_MISSING_FONT_TABLE_ERROR;
+        goto error_exit;
+    }
+
+    return;
+
+error_exit:
+    fclose(fFile);
+    fFile = NULL;
+    return;
+}
+
+PortableFontInstance::~PortableFontInstance()
+{
+    if (fFile != NULL) {
+        fclose(fFile);
+
+        freeFontTable(fHMTXTable);
+        freeFontTable(fNAMETable);
+
+        delete fCMAPMapper;
+
+        LE_DELETE_ARRAY(fDirectory);
+    }
+}
+
+const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
+{
+    if (fDirectory != NULL) {
+        le_uint16 table = 0;
+        le_uint16 probe = fDirPower;
+
+        if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
+            table = fDirExtra;
+        }
+
+        while (probe > (1 << 0)) {
+            probe >>= 1;
+
+            if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
+                table += probe;
+            }
+        }
+
+        if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
+            return &fDirectory->tableDirectory[table];
+        }
+    }
+
+    return NULL;
+}
+
+const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
+{
+    const DirectoryEntry *entry = findTable(tag);
+
+    if (entry == NULL) {
+        *length = 0;
+        return NULL;
+    }
+
+    *length = SWAPL(entry->length);
+
+    void *table = LE_NEW_ARRAY(char, *length);
+
+    if (table != NULL) {
+        fseek(fFile, SWAPL(entry->offset), SEEK_SET);
+        fread(table, sizeof(char), *length, fFile);
+    }
+
+    return table;
+}
+
+const void *PortableFontInstance::getFontTable(LETag tableTag) const
+{
+  size_t ignored;
+  return getFontTable(tableTag, ignored);
+}
+
+const void *PortableFontInstance::getFontTable(LETag tableTag, size_t &length) const
+{
+  return FontTableCache::find(tableTag, length);
+}
+
+const void *PortableFontInstance::readFontTable(LETag tableTag, size_t &length) const
+{
+    le_uint32 len;
+
+    const void *data= readTable(tableTag, &len);
+    length = len;
+    //char tag5[5];
+    //printf("Read %s, result %p #%d\n", letagToStr(tableTag,tag5), data,len);
+    return data;
+}
+
+CMAPMapper *PortableFontInstance::findUnicodeMapper()
+{
+    LETag cmapTag = LE_CMAP_TABLE_TAG;
+    const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
+
+    if (cmap == NULL) {
+        return NULL;
+    }
+
+    return CMAPMapper::createUnicodeMapper(cmap);
+}
+
+const char *PortableFontInstance::getNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
+{
+    if (fNAMETable == NULL) {
+        LETag nameTag = LE_NAME_TABLE_TAG;
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+
+        if (realThis->fNAMETable != NULL) {
+            realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
+            realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
+        }
+    }
+
+    for(le_int32 i = 0; i < fNameCount; i += 1) {
+        const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
+        
+        if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
+            SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
+            char *name = ((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset);
+            le_uint16 length = SWAPW(nameRecord->length);
+            char *result = LE_NEW_ARRAY(char, length + 2);
+
+            LE_ARRAY_COPY(result, name, length);
+            result[length] = result[length + 1] = 0;
+
+            return result;
+        }
+    }
+
+    return NULL;
+}
+
+const LEUnicode16 *PortableFontInstance::getUnicodeNameString(le_uint16 nameID, le_uint16 platformID, le_uint16 encodingID, le_uint16 languageID) const
+{
+    if (fNAMETable == NULL) {
+        LETag nameTag = LE_NAME_TABLE_TAG;
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        realThis->fNAMETable = (const NAMETable *) readFontTable(nameTag);
+
+        if (realThis->fNAMETable != NULL) {
+            realThis->fNameCount        = SWAPW(realThis->fNAMETable->count);
+            realThis->fNameStringOffset = SWAPW(realThis->fNAMETable->stringOffset);
+        }
+    }
+
+    for(le_int32 i = 0; i < fNameCount; i += 1) {
+        const NameRecord *nameRecord = &fNAMETable->nameRecords[i];
+        
+        if (SWAPW(nameRecord->platformID) == platformID && SWAPW(nameRecord->encodingID) == encodingID &&
+            SWAPW(nameRecord->languageID) == languageID && SWAPW(nameRecord->nameID) == nameID) {
+            LEUnicode16 *name = (LEUnicode16 *) (((char *) fNAMETable) + fNameStringOffset + SWAPW(nameRecord->offset));
+            le_uint16 length = SWAPW(nameRecord->length) / 2;
+            LEUnicode16 *result = LE_NEW_ARRAY(LEUnicode16, length + 2);
+
+            for (le_int32 c = 0; c < length; c += 1) {
+                result[c] = SWAPW(name[c]);
+            }
+
+            result[length] = 0;
+
+            return result;
+        }
+    }
+
+    return NULL;
+}
+
+void PortableFontInstance::deleteNameString(const char *name) const
+{
+    LE_DELETE_ARRAY(name);
+}
+
+void PortableFontInstance::deleteNameString(const LEUnicode16 *name) const
+{
+    LE_DELETE_ARRAY(name);
+}
+
+void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
+{
+    TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
+
+    if (fHMTXTable == NULL) {
+        LETag maxpTag = LE_MAXP_TABLE_TAG;
+        LETag hmtxTag = LE_HMTX_TABLE_TAG;
+        const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
+        PortableFontInstance *realThis = (PortableFontInstance *) this;
+
+        if (maxpTable != NULL) {
+            realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
+            freeFontTable(maxpTable);
+        }
+
+        realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
+    }
+
+    le_uint16 index = ttGlyph;
+
+    if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
+        advance.fX = advance.fY = 0;
+        return;
+    }
+
+    if (ttGlyph >= fNumLongHorMetrics) {
+        index = fNumLongHorMetrics - 1;
+    }
+
+    advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
+    advance.fY = 0;
+}
+
+le_bool PortableFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
+{
+    return FALSE;
+}
+
+le_int32 PortableFontInstance::getUnitsPerEM() const
+{
+    return fUnitsPerEM;
+}
+
+le_uint32 PortableFontInstance::getFontChecksum() const
+{
+    return fFontChecksum;
+}
+
+le_uint32 PortableFontInstance::getRawChecksum() const
+{
+  // how big is it?
+  //  fseek(fFile, 0L, SEEK_END);
+  //  long size = ftell(fFile);
+  le_int32 chksum = 0;
+  // now, calculate
+  fseek(fFile, 0L, SEEK_SET);
+  int r;
+  int count =0;
+  while((r = fgetc(fFile)) != EOF) {
+    chksum += r;
+    count ++;
+  }
+  return (le_uint32) chksum; // cast to signed
+}
+
+le_int32 PortableFontInstance::getAscent() const
+{
+    return fAscent;
+}
+
+le_int32 PortableFontInstance::getDescent() const
+{
+    return fDescent;
+}
+
+le_int32 PortableFontInstance::getLeading() const
+{
+    return fLeading;
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth);
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper);
+}
+
+LEGlyphID PortableFontInstance::mapCharToGlyph(LEUnicode32 ch) const
+{
+    return fCMAPMapper->unicodeToGlyph(ch);
+}
+
+float PortableFontInstance::getXPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float PortableFontInstance::getYPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float PortableFontInstance::getScaleFactorX() const
+{
+    return 1.0;
+}
+
+float PortableFontInstance::getScaleFactorY() const
+{
+    return 1.0;
+}
diff --git a/icu4c/source/test/perf/leperf/PortableFontInstance.h b/icu4c/source/test/perf/leperf/PortableFontInstance.h
new file mode 100644 (file)
index 0000000..ed366e9
--- /dev/null
@@ -0,0 +1,121 @@
+
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  PortableFontInstance.h
+ *
+ *   created on: 11/12/1999
+ *   created by: Eric R. Mader
+ */
+
+#ifndef __PORTABLEFONTINSTANCE_H
+#define __PORTABLEFONTINSTANCE_H
+
+#include <stdio.h>
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+
+#include "FontTableCache.h"
+
+#include "sfnt.h"
+#include "cmaps.h"
+
+class PortableFontInstance : public LEFontInstance, protected FontTableCache
+{
+private:
+    FILE *fFile;
+
+    float     fPointSize;
+    le_int32  fUnitsPerEM;
+    le_uint32 fFontChecksum;
+    le_int32  fAscent;
+    le_int32  fDescent;
+    le_int32  fLeading;
+
+    const SFNTDirectory *fDirectory;
+    le_uint16 fDirPower;
+    le_uint16 fDirExtra;
+
+    float fDeviceScaleX;
+    float fDeviceScaleY;
+
+    const NAMETable *fNAMETable;
+    le_uint16 fNameCount;
+    le_uint16 fNameStringOffset;
+
+    CMAPMapper *fCMAPMapper;
+
+    const HMTXTable *fHMTXTable;
+    le_uint16 fNumGlyphs;
+    le_uint16 fNumLongHorMetrics;
+
+    static le_int8 highBit(le_int32 value);
+
+    const DirectoryEntry *findTable(LETag tag) const;
+    const void *readTable(LETag tag, le_uint32 *length) const;
+    void getMetrics();
+
+    CMAPMapper *findUnicodeMapper();
+
+protected:
+    const void *readFontTable(LETag tableTag) const { size_t ignored; return readFontTable(tableTag, ignored); }
+    const void *readFontTable(LETag tableTag, size_t &length) const;
+
+public:
+    PortableFontInstance(const char *fileName, float pointSize, LEErrorCode &status);
+
+    virtual ~PortableFontInstance();
+
+    virtual const void *getFontTable(LETag tableTag) const;
+    virtual const void *getFontTable(LETag tableTag, size_t &length) const;
+
+    virtual const char *getNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
+
+    virtual const LEUnicode16 *getUnicodeNameString(le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language) const;
+
+    virtual void deleteNameString(const char *name) const;
+
+    virtual void deleteNameString(const LEUnicode16 *name) const;
+
+    virtual le_int32 getUnitsPerEM() const;
+
+    virtual le_uint32 getFontChecksum() const;
+
+    virtual le_uint32 getRawChecksum() const;
+
+    virtual le_int32 getAscent() const;
+
+    virtual le_int32 getDescent() const;
+
+    virtual le_int32 getLeading() const;
+
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const;
+    
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;
+
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;
+
+    virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
+
+    virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
+
+    float getXPixelsPerEm() const;
+
+    float getYPixelsPerEm() const;
+
+    float getScaleFactorX() const;
+
+    float getScaleFactorY() const;
+
+};
+
+#endif
diff --git a/icu4c/source/test/perf/leperf/SimpleFontInstance.cpp b/icu4c/source/test/perf/leperf/SimpleFontInstance.cpp
new file mode 100644 (file)
index 0000000..d240a6a
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  SimpleFontInstance.cpp
+ *
+ *   created on: 03/30/2006
+ *   created by: Eric R. Mader
+ */
+
+#include "unicode/utypes.h"
+#include "unicode/uchar.h"
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+
+#include "layout/CanonShaping.h"
+#include "SimpleFontInstance.h"
+
+SimpleFontInstance::SimpleFontInstance(float pointSize, LEErrorCode &status)
+    : fPointSize(pointSize), fAscent(0), fDescent(0)
+{
+    if (LE_FAILURE(status)) {
+        return;
+    }
+
+    fAscent  = (le_int32) yUnitsToPoints(2000.0);
+    fDescent = (le_int32) yUnitsToPoints(600.0);
+
+    return;
+}
+
+SimpleFontInstance::~SimpleFontInstance()
+{
+    // nothing to do...
+}
+
+const void *SimpleFontInstance::getFontTable(LETag tableTag) const
+{
+    if (tableTag == LE_GSUB_TABLE_TAG) {
+        return CanonShaping::glyphSubstitutionTable;
+    }
+    
+    if (tableTag == LE_GDEF_TABLE_TAG) {
+        return CanonShaping::glyphDefinitionTable;
+    }
+
+    return NULL;
+}
+
+void SimpleFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
+{
+#if 0
+    if (u_getCombiningClass((UChar32) glyph) == 0) {
+        advance.fX = xUnitsToPoints(2048);
+    } else {
+        advance.fX = 0;
+    }
+#else
+    advance.fX = xUnitsToPoints(2048);
+#endif
+
+    advance.fY = 0;
+}
+
+le_int32 SimpleFontInstance::getUnitsPerEM() const
+{
+    return 2048;
+}
+
+le_int32 SimpleFontInstance::getAscent() const
+{
+    return fAscent;
+}
+
+le_int32 SimpleFontInstance::getDescent() const
+{
+    return fDescent;
+}
+
+le_int32 SimpleFontInstance::getLeading() const
+{
+    return 0;
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID SimpleFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper, filterZeroWidth);
+}
+
+// We really want to inherit this method from the superclass, but some compilers
+// issue a warning if we don't implement it...
+LEGlyphID SimpleFontInstance::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
+{
+    return LEFontInstance::mapCharToGlyph(ch, mapper);
+}
+
+LEGlyphID SimpleFontInstance::mapCharToGlyph(LEUnicode32 ch) const
+{
+    return (LEGlyphID) ch;
+}
+
+float SimpleFontInstance::getXPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float SimpleFontInstance::getYPixelsPerEm() const
+{
+    return fPointSize;
+}
+
+float SimpleFontInstance::getScaleFactorX() const
+{
+    return 1.0;
+}
+
+float SimpleFontInstance::getScaleFactorY() const
+{
+    return 1.0;
+}
+
+le_bool SimpleFontInstance::getGlyphPoint(LEGlyphID /*glyph*/, le_int32 /*pointNumber*/, LEPoint &/*point*/) const
+{
+    return FALSE;
+}
+
diff --git a/icu4c/source/test/perf/leperf/SimpleFontInstance.h b/icu4c/source/test/perf/leperf/SimpleFontInstance.h
new file mode 100644 (file)
index 0000000..1e28a82
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ *   file name:  SimpleFontInstance.h
+ *
+ *   created on: 03/30/2006
+ *   created by: Eric R. Mader
+ */
+
+#ifndef __SIMPLEFONTINSTANCE_H
+#define __SIMPLEFONTINSTANCE_H
+
+#include "layout/LETypes.h"
+#include "layout/LEFontInstance.h"
+
+U_NAMESPACE_USE
+
+class SimpleFontInstance : public LEFontInstance
+{
+private:
+    float     fPointSize;
+    le_int32  fAscent;
+    le_int32  fDescent;
+
+protected:
+    const void *readFontTable(LETag tableTag) const;
+
+public:
+    SimpleFontInstance(float pointSize, LEErrorCode &status);
+
+    virtual ~SimpleFontInstance();
+
+    virtual const void *getFontTable(LETag tableTag) const;
+
+    virtual le_int32 getUnitsPerEM() const;
+
+    virtual le_int32 getAscent() const;
+
+    virtual le_int32 getDescent() const;
+
+    virtual le_int32 getLeading() const;
+
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth) const;
+    
+    // We really want to inherit this method from the superclass, but some compilers
+    // issue a warning if we don't implement it...
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const;
+
+    virtual LEGlyphID mapCharToGlyph(LEUnicode32 ch) const;
+
+    virtual void getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const;
+
+    virtual le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const;
+
+    float getXPixelsPerEm() const;
+
+    float getYPixelsPerEm() const;
+
+    float getScaleFactorX() const;
+
+    float getScaleFactorY() const;
+
+};
+
+#endif
diff --git a/icu4c/source/test/perf/leperf/cfonts.cpp b/icu4c/source/test/perf/leperf/cfonts.cpp
new file mode 100644 (file)
index 0000000..a2e5d30
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
+ *
+ */
+
+#include "LETypes.h"
+#include "loengine.h"
+#include "PortableFontInstance.h"
+#include "SimpleFontInstance.h"
+
+U_CDECL_BEGIN
+
+le_font *le_portableFontOpen(const char *fileName,
+                                       float pointSize,
+                                       LEErrorCode *status)
+{
+       return (le_font *) new PortableFontInstance(fileName, pointSize, *status);
+}
+
+le_font *le_simpleFontOpen(float pointSize,
+                                 LEErrorCode *status)
+{
+       return (le_font *) new SimpleFontInstance(pointSize, *status);
+}
+
+void le_fontClose(le_font *font)
+{
+       LEFontInstance *fontInstance = (LEFontInstance *) font;
+
+       delete fontInstance;
+}
+
+const char *le_getNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language)
+{
+       PortableFontInstance *pfi = (PortableFontInstance *) font;
+
+       return pfi->getNameString(nameID, platform, encoding, language);
+}
+
+const LEUnicode16 *le_getUnicodeNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language)
+{
+       PortableFontInstance *pfi = (PortableFontInstance *) font;
+
+       return pfi->getUnicodeNameString(nameID, platform, encoding, language);
+}
+
+void le_deleteNameString(le_font *font, const char *name)
+{
+       PortableFontInstance *pfi = (PortableFontInstance *) font;
+
+       pfi->deleteNameString(name);
+}
+
+void le_deleteUnicodeNameString(le_font *font, const LEUnicode16 *name)
+{
+       PortableFontInstance *pfi = (PortableFontInstance *) font;
+
+       pfi->deleteNameString(name);
+}
+
+le_uint32 le_getFontChecksum(le_font *font)
+{
+       PortableFontInstance *pfi = (PortableFontInstance *) font;
+
+       return pfi->getFontChecksum();
+}
+
+U_CDECL_END
diff --git a/icu4c/source/test/perf/leperf/cfonts.h b/icu4c/source/test/perf/leperf/cfonts.h
new file mode 100644 (file)
index 0000000..b5cbf28
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __CFONTS_H
+#define __CFONTS_H
+
+#include "LETypes.h"
+#include "loengine.h"
+
+le_font *le_portableFontOpen(const char *fileName,
+                                                       float pointSize,
+                                                       LEErrorCode *status);
+
+le_font *le_simpleFontOpen(float pointSize,
+                                                  LEErrorCode *status);
+
+void le_fontClose(le_font *font);
+
+const char *le_getNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language);
+
+const LEUnicode16 *le_getUnicodeNameString(le_font *font, le_uint16 nameID, le_uint16 platform, le_uint16 encoding, le_uint16 language);
+
+void le_deleteNameString(le_font *font, const char *name);
+
+void le_deleteUnicodeNameString(le_font *font, const LEUnicode16 *name);
+
+le_uint32 le_getFontChecksum(le_font *font);
+
+#endif
diff --git a/icu4c/source/test/perf/leperf/cmaps.cpp b/icu4c/source/test/perf/leperf/cmaps.cpp
new file mode 100644 (file)
index 0000000..7eedb00
--- /dev/null
@@ -0,0 +1,247 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#include "layout/LETypes.h"
+#include "layout/LESwaps.h"
+
+#include "sfnt.h"
+#include "cmaps.h"
+#include <stdio.h>
+
+#define SWAPU16(code) ((LEUnicode16) SWAPW(code))
+#define SWAPU32(code) ((LEUnicode32) SWAPL(code))
+
+//
+// Finds the high bit by binary searching
+// through the bits in value.
+//
+le_int8 highBit(le_uint32 value)
+{
+    le_uint8 bit = 0;
+
+    if (value >= 1 << 16) {
+        value >>= 16;
+        bit += 16;
+    }
+
+    if (value >= 1 << 8) {
+        value >>= 8;
+        bit += 8;
+    }
+
+    if (value >= 1 << 4) {
+        value >>= 4;
+        bit += 4;
+    }
+
+    if (value >= 1 << 2) {
+        value >>= 2;
+        bit += 2;
+    }
+
+    if (value >= 1 << 1) {
+        value >>= 1;
+        bit += 1;
+    }
+
+    return bit;
+}
+
+CMAPMapper *CMAPMapper::createUnicodeMapper(const CMAPTable *cmap)
+{
+    le_uint16 i;
+    le_uint16 nSubtables = SWAPW(cmap->numberSubtables);
+    const CMAPEncodingSubtable *subtable = NULL;
+    le_bool found = FALSE;
+    le_uint16 foundPlatformID = 0xFFFF;
+    le_uint16 foundPlatformSpecificID = 0xFFFF;
+    le_uint32 foundOffset = 0;
+    le_uint16 foundTable = 0xFFFF;
+    // first pass, look for MS table. (preferred?)
+    for (i = 0; i < nSubtables && !found; i += 1) {
+        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
+
+        le_uint16 platformID = SWAPW(esh->platformID);
+        le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID);
+        if (platformID == 3) { // microsoft
+          switch (platformSpecificID) {
+            case 1: // Unicode BMP (UCS-2)
+            case 10: // Unicode UCS-4
+                foundOffset = SWAPL(esh->encodingOffset);
+                foundPlatformID = platformID;
+                foundPlatformSpecificID = platformSpecificID;
+                found = TRUE;
+                foundTable = i;
+                break;
+
+                //default:
+              //              printf("%s:%d: microsoft (3) platform specific ID %d (wanted 1 or 10) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformSpecificID)), i, nSubtables);
+            }
+        } else {
+          //printf("%s:%d: platform  ID %d (wanted 3, microsoft) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformID)), i, nSubtables);
+        }
+    }
+
+    // second pass, allow non MS table
+    // first pass, look for MS table. (preferred?)
+      for (i = 0; i < nSubtables && !found; i += 1) {
+        const CMAPEncodingSubtableHeader *esh = &cmap->encodingSubtableHeaders[i];
+        le_uint16 platformID = SWAPW(esh->platformID);
+        le_uint16 platformSpecificID = SWAPW(esh->platformSpecificID);
+        //printf("%s:%d: table %d/%d has platform:specific %d:%d\n", __FILE__, __LINE__, i, nSubtables, platformID, platformSpecificID);
+        switch(platformID) {
+        case 0: // Unicode platform
+          switch(platformSpecificID) {
+          case 0:
+          case 1:
+          case 2:
+          case 3:
+            foundOffset = SWAPL(esh->encodingOffset);
+            foundPlatformID = platformID;
+            foundPlatformSpecificID = platformSpecificID;
+            foundTable = i;
+            found = TRUE;
+            break;
+
+          default: printf("Error: table %d (psid %d) is unknown. Skipping.\n", i, platformSpecificID); break;
+          }
+          break;
+        
+          //default:
+          //printf("Skipping platform id %d\n", platformID);
+        }
+    }
+
+
+    if (found)
+    {
+      subtable = (const CMAPEncodingSubtable *) ((const char *) cmap + foundOffset);
+      //printf("%s:%d: using subtable #%d/%d type %d:%d\n", __FILE__, __LINE__, foundTable, nSubtables, foundPlatformID, foundPlatformSpecificID);
+    } else {
+      printf("%s:%d: could not find subtable.\n", __FILE__, __LINE__);
+      return NULL;
+    }
+
+    le_uint16 tableFormat = SWAPW(subtable->format);
+    //printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat);
+
+    switch (tableFormat) {
+    case 4:
+        return new CMAPFormat4Mapper(cmap, (const CMAPFormat4Encoding *) subtable);
+
+    case 12:
+    {
+        const CMAPFormat12Encoding *encoding = (const CMAPFormat12Encoding *) subtable;
+
+        return new CMAPGroupMapper(cmap, encoding->groups, SWAPL(encoding->nGroups));
+    }
+
+    default:
+        break;
+    }
+
+    printf("%s:%d: Unknown format %x.\n", __FILE__, __LINE__, (SWAPW(subtable->format)));
+    return NULL;
+}
+
+CMAPFormat4Mapper::CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header)
+    : CMAPMapper(cmap)
+{
+    le_uint16 segCount = SWAPW(header->segCountX2) / 2;
+
+    fEntrySelector = SWAPW(header->entrySelector);
+    fRangeShift = SWAPW(header->rangeShift) / 2;
+    fEndCodes = &header->endCodes[0];
+    fStartCodes = &header->endCodes[segCount + 1]; // + 1 for reservedPad...
+    fIdDelta = &fStartCodes[segCount];
+    fIdRangeOffset = &fIdDelta[segCount];
+}
+
+LEGlyphID CMAPFormat4Mapper::unicodeToGlyph(LEUnicode32 unicode32) const
+{
+    if (unicode32 >= 0x10000) {
+        return 0;
+    }
+
+    LEUnicode16 unicode = (LEUnicode16) unicode32;
+    le_uint16 index = 0;
+    le_uint16 probe = 1 << fEntrySelector;
+    TTGlyphID result = 0;
+
+    if (SWAPU16(fStartCodes[fRangeShift]) <= unicode) {
+        index = fRangeShift;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPU16(fStartCodes[index + probe]) <= unicode) {
+            index += probe;
+        }
+    }
+
+    if (unicode >= SWAPU16(fStartCodes[index]) && unicode <= SWAPU16(fEndCodes[index])) {
+        if (fIdRangeOffset[index] == 0) {
+            result = (TTGlyphID) unicode;
+        } else {
+            le_uint16 offset = unicode - SWAPU16(fStartCodes[index]);
+            le_uint16 rangeOffset = SWAPW(fIdRangeOffset[index]);
+            le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &fIdRangeOffset[index] + rangeOffset);
+
+            result = SWAPW(glyphIndexTable[offset]);
+        }
+
+        result += SWAPW(fIdDelta[index]);
+    } else {
+        result = 0;
+    }
+
+    return LE_SET_GLYPH(0, result);
+}
+
+CMAPFormat4Mapper::~CMAPFormat4Mapper()
+{
+    // parent destructor does it all
+}
+
+CMAPGroupMapper::CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups)
+    : CMAPMapper(cmap), fGroups(groups)
+{
+    le_uint8 bit = highBit(nGroups);
+    fPower = 1 << bit;
+    fRangeOffset = nGroups - fPower;
+}
+
+LEGlyphID CMAPGroupMapper::unicodeToGlyph(LEUnicode32 unicode32) const
+{
+    le_int32 probe = fPower;
+    le_int32 range = 0;
+
+    if (SWAPU32(fGroups[fRangeOffset].startCharCode) <= unicode32) {
+        range = fRangeOffset;
+    }
+
+    while (probe > (1 << 0)) {
+        probe >>= 1;
+
+        if (SWAPU32(fGroups[range + probe].startCharCode) <= unicode32) {
+            range += probe;
+        }
+    }
+
+    if (SWAPU32(fGroups[range].startCharCode) <= unicode32 && SWAPU32(fGroups[range].endCharCode) >= unicode32) {
+        return (LEGlyphID) (SWAPU32(fGroups[range].startGlyphCode) + unicode32 - SWAPU32(fGroups[range].startCharCode));
+    }
+
+    return 0;
+}
+
+CMAPGroupMapper::~CMAPGroupMapper()
+{
+    // parent destructor does it all
+}
+
diff --git a/icu4c/source/test/perf/leperf/cmaps.h b/icu4c/source/test/perf/leperf/cmaps.h
new file mode 100644 (file)
index 0000000..7a733ad
--- /dev/null
@@ -0,0 +1,85 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+
+#ifndef __CMAPS_H
+#define __CMAPS_H
+
+#include "layout/LETypes.h"
+//#include "letest.h"
+#include "sfnt.h"
+
+class CMAPMapper
+{
+public:
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const = 0;
+
+    virtual ~CMAPMapper();
+
+    static CMAPMapper *createUnicodeMapper(const CMAPTable *cmap);
+
+protected:
+    CMAPMapper(const CMAPTable *cmap);
+
+    CMAPMapper() {};
+
+private:
+    const CMAPTable *fcmap;
+};
+
+class CMAPFormat4Mapper : public CMAPMapper
+{
+public:
+    CMAPFormat4Mapper(const CMAPTable *cmap, const CMAPFormat4Encoding *header);
+
+    virtual ~CMAPFormat4Mapper();
+
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
+
+protected:
+    CMAPFormat4Mapper() {};
+
+private:
+    le_uint16       fEntrySelector;
+    le_uint16       fRangeShift;
+    const le_uint16 *fEndCodes;
+    const le_uint16 *fStartCodes;
+    const le_uint16 *fIdDelta;
+    const le_uint16 *fIdRangeOffset;
+};
+
+class CMAPGroupMapper : public CMAPMapper
+{
+public:
+    CMAPGroupMapper(const CMAPTable *cmap, const CMAPGroup *groups, le_uint32 nGroups);
+
+    virtual ~CMAPGroupMapper();
+
+    virtual LEGlyphID unicodeToGlyph(LEUnicode32 unicode32) const;
+
+protected:
+    CMAPGroupMapper() {};
+
+private:
+    le_int32 fPower;
+    le_int32 fRangeOffset;
+    const CMAPGroup *fGroups;
+};
+
+inline CMAPMapper::CMAPMapper(const CMAPTable *cmap)
+    : fcmap(cmap)
+{
+    // nothing else to do
+}
+
+inline CMAPMapper::~CMAPMapper()
+{
+    LE_DELETE_ARRAY(fcmap);
+}
+
+#endif
+
diff --git a/icu4c/source/test/perf/leperf/leperf.cpp b/icu4c/source/test/perf/leperf/leperf.cpp
new file mode 100644 (file)
index 0000000..3881904
--- /dev/null
@@ -0,0 +1,120 @@
+/***************************************************************************
+*
+*   Copyright (C) 2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#include "unicode/utimer.h"
+#include "unicode/ustdio.h"
+#include "layout/LETypes.h"
+#include "layout/LayoutEngine.h"
+#include "layout/LEScripts.h"
+#include "SimpleFontInstance.h"
+#include "PortableFontInstance.h"
+
+class Params {
+public:
+  LEFontInstance *font;
+  LEUnicode *chars;
+  le_int32 charLen;
+  ScriptCodes script;
+  le_int32 glyphCount;
+};
+
+LEUnicode     ArabChars[] = {
+        0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068, 0x0020, // "English "
+        0x0645, 0x0627, 0x0646, 0x062A, 0x0648, 0x0634,                 // MEM ALIF KAF NOON TEH WAW SHEEN
+        0x0020, 0x0074, 0x0065, 0x0078, 0x0074, 0x02E, 0                   // " text."
+    };
+
+void iterate(void * p) {
+  Params* params = (Params*) p;
+
+    LEErrorCode status = LE_NO_ERROR;
+    LEFontInstance *font = params->font;
+    LayoutEngine *engine = LayoutEngine::layoutEngineFactory(font, params->script, -1, status);
+    LEGlyphID *glyphs    = NULL;
+    le_int32  *indices   = NULL;
+    float     *positions = NULL;
+    le_int32   glyphCount = 0;
+    LEUnicode *chars = params->chars;
+    glyphCount = engine->layoutChars(chars, 0, params->charLen, params->charLen, TRUE, 0.0, 0.0, status);
+    glyphs    = LE_NEW_ARRAY(LEGlyphID, glyphCount + 10);
+    indices   = LE_NEW_ARRAY(le_int32, glyphCount + 10);
+    positions = LE_NEW_ARRAY(float, glyphCount + 10);
+    engine->getGlyphs(glyphs, status);
+    params->glyphCount = glyphCount;
+    
+    
+    delete glyphs;
+    delete indices;
+    delete positions;
+    delete engine;
+    //delete font;
+}
+
+int main(int argc, const char *argv[]) {
+  double len=10.0;
+  for(int i=1;i<argc;i++) {
+    puts("arg:");
+    puts(argv[i]);
+    if(argv[i][0]=='p') {
+      printf("hit enter-pid=%d", getpid());
+      getchar();
+    } else if(argv[i][0]>='0' && argv[i][0]<='9') {
+      len = (1.0)*(argv[i][0]-'0');
+    }
+  }
+  u_printf("leperf: Testing %s for %.fs...\n", U_ICU_VERSION, len);
+  LEErrorCode status = LE_NO_ERROR;
+  //uloc_setDefault("en_US", &status);
+  Params p;
+
+#if 0  
+  p.script = arabScriptCode;
+  p.chars = ArabChars;
+  p.charLen = sizeof(ArabChars)/sizeof(ArabChars[0]);
+#else
+  p.script = latnScriptCode;
+  p.chars = new LEUnicode[257];
+  for(int i=0;i<256;i++) {
+    p.chars[i] = i+1;
+  }
+  p.chars[256] = 0;
+  p.charLen = 256;
+#endif
+  
+  int32_t loopCount;
+  double timeTaken;
+  double timeNs;
+#if 0
+  p.font = new SimpleFontInstance(12, status);
+  u_printf("leperf: Running SFI...\r");
+  timeTaken = utimer_loopUntilDone(len, &loopCount, iterate, &p);
+  u_printf("leperf: SFI .. took %.fs %.2fns/ea\nleperf: .. iter= %d\n", timeTaken, 1000000000.0*(timeTaken/(double)loopCount), (int32_t)loopCount);
+  delete p.font;
+#endif
+    PortableFontInstance *font;
+    LEErrorCode fontStatus = LE_NO_ERROR;
+    const char *fontPath = "myfont.ttf";
+
+    font = new PortableFontInstance(fontPath, 12, fontStatus);
+
+    p.font = font;
+    loopCount=0;
+    u_printf("leperf: testing %s\n", fontPath);
+    u_printf("leperf: Running ...\r");
+  timeTaken = utimer_loopUntilDone(len, &loopCount, iterate, &p);
+  timeNs = 1000000000.0*(timeTaken/(double)loopCount);
+  u_printf("leperf: PFI .. took %.fs %.2fns/ea\nleperf: .. iter= %d\n", timeTaken, timeNs, (int32_t)loopCount);
+  u_printf("leperf: DATA|\"%s\"|%.2f|\n", U_ICU_VERSION, timeNs);
+  u_printf("leperf: glyphs=%d\n", p.glyphCount);
+  return 0;
+}
+
+// hack - #include these for easier build.
+#include "SimpleFontInstance.cpp"
+#include "PortableFontInstance.cpp"
+#include "cmaps.cpp"
+#include "FontTableCache.cpp"
diff --git a/icu4c/source/test/perf/leperf/letrperf.cpp b/icu4c/source/test/perf/leperf/letrperf.cpp
new file mode 100644 (file)
index 0000000..75cfe1b
--- /dev/null
@@ -0,0 +1,177 @@
+/***************************************************************************
+*
+*   Copyright (C) 2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+/**
+ * Usage:
+ * build against a configured (but not built) ICU.
+ * example: cc -O2 test_LETableReference.cpp -I. -I/xsrl/II/include -I/xsrl/E/icu/source/tools/ctestfw
+ */
+#include "unicode/utimer.h"
+#include "LETableReference.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ITEM_COUNT 10000
+
+long *items = 0;
+
+struct OneObject {
+  long items[ITEM_COUNT];
+};
+
+struct Long {
+  long v;
+};
+
+struct CompObject {
+  Long items[ITEM_COUNT];
+};
+
+
+void time_null(void * /*ref*/) {
+  for(int i=0;i<ITEM_COUNT;i++) {
+    if(items[i]==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+
+void time_obj(void * ref) {
+  OneObject &obj = *((OneObject*)ref);
+  for(int i=0;i<ITEM_COUNT;i++) {
+    if(obj.items[i]==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+void time_obj2(void * ref) {
+  long *items2 = ((OneObject*)ref)->items;
+  for(int i=0;i<ITEM_COUNT;i++) {
+    if(items2[i]==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+
+void time_letr1(void * ref) {
+  OneObject &obj = *((OneObject*)ref);
+  LETableReference data((const le_uint8*)ref, sizeof(OneObject));
+  LEErrorCode success = LE_NO_ERROR;
+
+  LEReferenceTo<OneObject> stuff(data, success);
+  if(LE_FAILURE(success)) {
+    puts("failure");
+    abort();
+  }
+  long *items2 = ((OneObject*)ref)->items;
+  for(int i=0;i<ITEM_COUNT;i++) {
+    if(items[i]==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+
+
+void time_letr2(void * ref) {
+  OneObject &obj = *((OneObject*)ref);
+  LETableReference data((const le_uint8*)ref, sizeof(OneObject));
+  LEErrorCode success = LE_NO_ERROR;
+
+  long *items2 = ((OneObject*)ref)->items;
+  for(int i=0;i<ITEM_COUNT;i++) {
+    LEReferenceTo<OneObject> stuff(data, success);
+    if(LE_FAILURE(success)) {
+      puts("failure");
+      abort();
+    }
+    if(items[i]==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+
+static void time_letr3(void * ref) {
+  LETableReference data((const le_uint8*)ref, sizeof(OneObject));
+  LEErrorCode success = LE_NO_ERROR;
+  LEReferenceTo<CompObject> comp(data, success);  
+  LEReferenceToArrayOf<Long> longs(comp, success, (size_t)0, ITEM_COUNT);
+  if(LE_FAILURE(success)) {
+    puts("failure");
+    abort();
+  }
+
+  for(int i=0;i<ITEM_COUNT;i++) {
+    const Long &item = longs.getObject(i, success);
+    if(LE_FAILURE(success)) {
+      puts("failure");
+      abort();
+    }
+    if(item.v==2) {
+      return;
+    }
+  }
+  puts("error");
+  abort();
+}
+
+
+int main() {
+  double runTime = 2.0;
+  printf("Test of LETableReference<> timing. %.1fs per run.\n", runTime);
+  items = new long[ITEM_COUNT];
+  OneObject *oo = new OneObject();
+  CompObject *oo2 = new CompObject();
+  for(int i=0;i<ITEM_COUNT-1;i++) {
+    items[i] = oo->items[i] = oo2->items[i].v = (i%1024)+3;
+  }
+  items[ITEM_COUNT-1] = oo->items[ITEM_COUNT-1] = oo2->items[ITEM_COUNT-1].v = 2; // last one
+
+  puts("will call once..");
+  time_letr3((void*)oo2);
+  puts("testing all..");
+  int32_t loopCount;
+  double time_taken;
+
+#define showTime(x,y)  printf("%s:\ttesting...\r",  #x);   fflush(stdout); \
+  time_taken = utimer_loopUntilDone(runTime, &loopCount, x, y); \
+  printf("%s:\t%.1fs\t#%d\t%.1f/s\n", #x, time_taken, loopCount, loopCount/(double)time_taken);
+
+  // clear out cache
+  {
+    double oldTime = runTime;
+    runTime = 0.25;
+    showTime(time_null, NULL); 
+    showTime(time_null, NULL); 
+    showTime(time_null, NULL); 
+    showTime(time_null, NULL); 
+    runTime = oldTime;
+  }
+  puts("-- ready to start --");
+
+
+  showTime(time_null, NULL); 
+  showTime(time_obj, (void*)oo);
+  showTime(time_obj2, (void*)oo);
+  showTime(time_letr1, (void*)oo2);
+  showTime(time_letr2, (void*)oo2);
+  showTime(time_letr3, (void*)oo2);
+  showTime(time_null, NULL);
+  
+  delete [] items;
+  delete oo;
+  delete oo2;
+}
diff --git a/icu4c/source/test/perf/leperf/sfnt.h b/icu4c/source/test/perf/leperf/sfnt.h
new file mode 100644 (file)
index 0000000..f39d64a
--- /dev/null
@@ -0,0 +1,449 @@
+/***************************************************************************
+*
+*   Copyright (C) 1998-2013, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+************************************************************************/
+
+#ifndef __SFNT_H
+#define __SFNT_H
+
+#include "layout/LETypes.h"
+
+U_NAMESPACE_USE
+
+#ifndef ANY_NUMBER
+#define ANY_NUMBER 1
+#endif
+
+struct DirectoryEntry
+{
+    le_uint32   tag;
+    le_uint32   checksum;
+    le_uint32   offset;
+    le_uint32   length;
+};
+
+#ifndef __cplusplus
+typedef struct DirectoryEntry DirectoryEntry;
+#endif
+
+struct SFNTDirectory
+{
+    le_uint32       scalerType;
+    le_uint16       numTables;
+    le_uint16       searchRange;
+    le_uint16       entrySelector;
+    le_uint16       rangeShift;
+    DirectoryEntry  tableDirectory[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct SFNTDirectory SFNTDirectory;
+#endif
+
+
+struct CMAPEncodingSubtableHeader
+{
+    le_uint16   platformID;
+    le_uint16   platformSpecificID;
+    le_uint32   encodingOffset;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtableHeader CMAPEncodingSubtableHeader;
+#endif
+
+struct CMAPTable
+{
+    le_uint16   version;
+    le_uint16   numberSubtables;
+    CMAPEncodingSubtableHeader encodingSubtableHeaders[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct CMAPTable CMAPTable;
+#endif
+
+struct CMAPEncodingSubtable
+{
+    le_uint16   format;
+    le_uint16   length;
+    le_uint16   language;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtable CMAPEncodingSubtable;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat0Encoding : CMAPEncodingSubtable
+{
+    le_uint8    glyphIndexArray[256];
+};
+#else
+struct CMAPFormat0Encoding
+{
+       CMAPEncodingSubtable base;
+
+       le_uint8 glyphIndexArray[256];
+};
+
+typedef struct CMAPFormat0Encoding CMAPFormat0Encoding;
+#endif
+
+struct CMAPFormat2Subheader
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_int16    idDelta;
+    le_uint16   idRangeOffset;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPFormat2Subheader CMAPFormat2Subheader;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat2Encoding : CMAPEncodingSubtable
+{
+    le_uint16  subHeadKeys[256];
+    CMAPFormat2Subheader subheaders[ANY_NUMBER];
+};
+#else
+struct CMAPFormat2Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16  subHeadKeys[256];
+    CMAPFormat2Subheader subheaders[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat2Encoding CMAPFormat2Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat4Encoding : CMAPEncodingSubtable
+{
+    le_uint16   segCountX2;
+    le_uint16   searchRange;
+    le_uint16   entrySelector;
+    le_uint16   rangeShift;
+    le_uint16   endCodes[ANY_NUMBER];
+/*
+    le_uint16   reservedPad;
+    le_uint16   startCodes[ANY_NUMBER];
+    le_uint16   idDelta[ANY_NUMBER];
+    le_uint16   idRangeOffset[ANY_NUMBER];
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+*/
+};
+#else
+struct CMAPFormat4Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16   segCountX2;
+    le_uint16   searchRange;
+    le_uint16   entrySelector;
+    le_uint16   rangeShift;
+    le_uint16   endCodes[ANY_NUMBER];
+/*
+//  le_uint16   reservedPad;
+//  le_uint16   startCodes[ANY_NUMBER];
+//  le_uint16   idDelta[ANY_NUMBER];
+//  le_uint16   idRangeOffset[ANY_NUMBER];
+//  le_uint16   glyphIndexArray[ANY_NUMBER];
+*/
+};
+
+typedef struct CMAPFormat4Encoding CMAPFormat4Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat6Encoding : CMAPEncodingSubtable
+{
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+#else
+struct CMAPFormat6Encoding
+{
+       CMAPEncodingSubtable base;
+
+    le_uint16   firstCode;
+    le_uint16   entryCount;
+    le_uint16   glyphIndexArray[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat6Encoding CMAPFormat6Encoding;
+#endif
+
+struct CMAPEncodingSubtable32
+{
+    le_uint32   format;
+    le_uint32   length;
+    le_uint32   language;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPEncodingSubtable32 CMAPEncodingSubtable32;
+#endif
+
+struct CMAPGroup
+{
+    le_uint32   startCharCode;
+    le_uint32   endCharCode;
+    le_uint32   startGlyphCode;
+};
+
+#ifndef __cplusplus
+typedef struct CMAPGroup CMAPGroup;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat8Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   is32[65536/32];
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+#else
+struct CMAPFormat8Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   is32[65536/32];
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat8Encoding CMAPFormat8Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat10Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   startCharCode;
+    le_uint32   numCharCodes;
+    le_uint16   glyphs[ANY_NUMBER];
+};
+#else
+struct CMAPFormat10Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   startCharCode;
+    le_uint32   numCharCodes;
+    le_uint16   glyphs[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat10Encoding CMAPFormat10Encoding;
+#endif
+
+#ifdef __cplusplus
+struct CMAPFormat12Encoding : CMAPEncodingSubtable32
+{
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+#else
+struct CMAPFormat12Encoding
+{
+       CMAPEncodingSubtable32 base;
+
+    le_uint32   nGroups;
+    CMAPGroup   groups[ANY_NUMBER];
+};
+
+typedef struct CMAPFormat12Encoding CMAPFormat12Encoding;
+#endif
+
+typedef le_int32 fixed;
+
+struct BigDate
+{
+    le_uint32   bc;
+    le_uint32   ad;
+};
+
+#ifndef __cplusplus
+typedef struct BigDate BigDate;
+#endif
+
+struct HEADTable
+{
+    fixed       version;
+    fixed       fontRevision;
+    le_uint32   checksumAdjustment;
+    le_uint32   magicNumber;
+    le_uint16   flags;
+    le_uint16   unitsPerEm;
+    BigDate     created;
+    BigDate     modified;
+    le_int16    xMin;
+    le_int16    yMin;
+    le_int16    xMax;
+    le_int16    yMax;
+    le_int16    lowestRecPPEM;
+    le_int16    fontDirectionHint;
+    le_int16    indexToLocFormat;
+    le_int16    glyphDataFormat;
+};
+
+#ifndef __cplusplus
+typedef struct HEADTable HEADTable;
+#endif
+
+struct MAXPTable
+{
+    fixed       version;
+    le_uint16   numGlyphs;
+    le_uint16   maxPoints;
+    le_uint16   maxContours;
+    le_uint16   maxComponentPoints;
+    le_uint16   maxComponentContours;
+    le_uint16   maxZones;
+    le_uint16   maxTwilightPoints;
+    le_uint16   maxStorage;
+    le_uint16   maxFunctionDefs;
+    le_uint16   maxInstructionDefs;
+    le_uint16   maxStackElements;
+    le_uint16   maxSizeOfInstructions;
+    le_uint16   maxComponentElements;
+    le_uint16   maxComponentDepth;
+};
+
+#ifndef __cplusplus
+typedef struct MAXPTable MAXPTable;
+#endif
+
+struct HHEATable
+{
+    fixed       version;
+    le_int16    ascent;
+    le_int16    descent;
+    le_int16    lineGap;
+    le_uint16   advanceWidthMax;
+    le_int16    minLeftSideBearing;
+    le_int16    minRightSideBearing;
+    le_int16    xMaxExtent;
+    le_int16    caretSlopeRise;
+    le_int16    caretSlopeRun;
+    le_int16    caretOffset;
+    le_int16    reserved1;
+    le_int16    reserved2;
+    le_int16    reserved3;
+    le_int16    reserved4;
+    le_int16    metricDataFormat;
+    le_uint16   numOfLongHorMetrics;
+};
+
+#ifndef __cplusplus
+typedef struct HHEATable HHEATable;
+#endif
+
+struct LongHorMetric
+{
+    le_uint16   advanceWidth;
+    le_int16    leftSideBearing;
+};
+
+#ifndef __cplusplus
+typedef struct LongHorMetric LongHorMetric;
+#endif
+
+struct HMTXTable
+{
+    LongHorMetric hMetrics[ANY_NUMBER];       /* ANY_NUMBER = numOfLongHorMetrics from hhea table */
+/* le_int16        leftSideBearing[ANY_NUMBER];  ANY_NUMBER = numGlyphs - numOfLongHorMetrics     */
+};
+
+#ifndef __cplusplus
+typedef struct HMTXTable HMTXTable;
+#endif
+
+enum PlatformID
+{
+    PLATFORM_UNICODE = 0,
+    PLATFORM_MACINTOSH = 1,
+    PLATFORM_ISO       = 2,
+    PLATFORM_MICROSOFT = 3,
+    PLATFORM_CUSTOM    = 4
+};
+
+enum MacintoshEncodingID
+{
+    MACINTOSH_ROMAN = 0
+};
+
+enum MacintoshLanguageID
+{
+    MACINTOSH_ENGLISH = 0
+};
+
+enum MicrosoftEncodingID
+{
+    MICROSOFT_UNICODE_BMP  =  1,
+    MICROSOFT_UNICODE_FULL = 10
+};
+
+enum MicrosoftLanguageID
+{
+    MICROSOFT_ENGLISH = 0x409
+};
+
+enum NameID
+{
+    NAME_COPYRIGHT_NOTICE     = 0,
+    NAME_FONT_FAMILY          = 1,
+    NAME_FONT_SUB_FAMILY      = 2,
+    NAME_UNIQUE_FONT_ID       = 3,
+    NAME_FULL_FONT_NAME       = 4,
+    NAME_VERSION_STRING       = 5,
+    NAME_POSTSCRIPT_NAME      = 6,
+    NAME_TRADEMARK            = 7,
+    NAME_MANUFACTURER         = 8,
+    NAME_DESIGNER             = 9,
+    NAME_DESCRIPTION          = 10,
+    NAME_VENDOR_URL           = 11,
+    NAME_DESIGNER_URL         = 12,
+    NAME_LICENSE_DESCRIPTION  = 13,
+    NAME_LICENSE_URL          = 14,
+    NAME_RESERVED             = 15,
+    NAME_PREFERRED_FAMILY     = 16,
+    NAME_PREFERRED_SUB_FAMILY = 17,
+    NAME_COMPATIBLE_FULL      = 18,
+    NAME_SAMPLE_TEXT          = 19,
+    NAME_POSTSCRIPT_CID       = 20
+};
+
+struct NameRecord
+{
+    le_uint16 platformID;
+    le_uint16 encodingID;
+    le_uint16 languageID;
+    le_uint16 nameID;
+    le_uint16 length;
+    le_uint16 offset;
+};
+
+#ifndef __cplusplus
+typedef struct NameRecord NameRecord;
+#endif
+
+struct NAMETable
+{
+    le_uint16 version;
+    le_uint16 count;
+    le_uint16 stringOffset;
+    NameRecord nameRecords[ANY_NUMBER];
+};
+
+#ifndef __cplusplus
+typedef struct NAMETable NAMETable;
+#endif
+
+#endif
+
diff --git a/icu4c/source/test/perf/leperf/xmlreader.cpp b/icu4c/source/test/perf/leperf/xmlreader.cpp
new file mode 100644 (file)
index 0000000..3115f18
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *******************************************************************************
+ *
+ *   Copyright (C) 1999-2013, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ *******************************************************************************
+ */
+
+#include "unicode/utypes.h"
+#include "unicode/uclean.h"
+#include "unicode/uchar.h"
+#include "unicode/unistr.h"
+#include "unicode/uscript.h"
+#include "unicode/putil.h"
+#include "unicode/ctest.h"
+
+#include "layout/LETypes.h"
+#include "layout/LEScripts.h"
+
+#include "letsutil.h"
+#include "letest.h"
+
+#include "xmlreader.h"
+
+#include "xmlparser.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+//U_NAMESPACE_USE
+
+#define CH_COMMA 0x002C
+
+static le_uint32 *getHexArray(const UnicodeString &numbers, int32_t &arraySize)
+{
+    int32_t offset = -1;
+
+    arraySize = 1;
+    while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
+        arraySize += 1;
+    }
+
+    le_uint32 *array = NEW_ARRAY(le_uint32, arraySize);
+    char number[16];
+    le_int32 count = 0;
+    le_int32 start = 0, end = 0;
+    le_int32 len = 0;
+
+    // trim leading whitespace
+    while(u_isUWhiteSpace(numbers[start])) {
+        start += 1;
+    }
+
+    while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
+        len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
+        number[len] = '\0';
+        start = end + 1;
+
+        sscanf(number, "%x", &array[count++]);
+
+        // trim whitespace following the comma
+        while(u_isUWhiteSpace(numbers[start])) {
+            start += 1;
+        }
+    }
+
+    // trim trailing whitespace
+    end = numbers.length();
+    while(u_isUWhiteSpace(numbers[end - 1])) {
+        end -= 1;
+    }
+
+    len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
+    number[len] = '\0';
+    sscanf(number, "%x", &array[count]);
+
+    return array;
+}
+
+static float *getFloatArray(const UnicodeString &numbers, int32_t &arraySize)
+{
+    int32_t offset = -1;
+
+    arraySize = 1;
+    while((offset = numbers.indexOf(CH_COMMA, offset + 1)) >= 0) {
+        arraySize += 1;
+    }
+
+    float *array = NEW_ARRAY(float, arraySize);
+    char number[32];
+    le_int32 count = 0;
+    le_int32 start = 0, end = 0;
+    le_int32 len = 0;
+
+    // trim leading whitespace
+    while(u_isUWhiteSpace(numbers[start])) {
+        start += 1;
+    }
+
+    while((end = numbers.indexOf(CH_COMMA, start)) >= 0) {
+        len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
+        number[len] = '\0';
+        start = end + 1;
+
+        sscanf(number, "%f", &array[count++]);
+
+        // trim whiteapce following the comma
+        while(u_isUWhiteSpace(numbers[start])) {
+            start += 1;
+        }
+    }
+
+    while(u_isUWhiteSpace(numbers[start])) {
+        start += 1;
+    }
+
+    // trim trailing whitespace
+    end = numbers.length();
+    while(u_isUWhiteSpace(numbers[end - 1])) {
+        end -= 1;
+    }
+
+    len = numbers.extract(start, end - start, number, ARRAY_SIZE(number), US_INV);
+    number[len] = '\0';
+    sscanf(number, "%f", &array[count]);
+
+    return array;
+}
+
+U_CDECL_BEGIN
+void readTestFile(const char *testFilePath, TestCaseCallback callback)
+{
+#if !UCONFIG_NO_REGULAR_EXPRESSIONS
+    UErrorCode status = U_ZERO_ERROR;
+    UXMLParser  *parser = UXMLParser::createParser(status);
+    UXMLElement *root   = parser->parseFile(testFilePath, status);
+
+    if (root == NULL) {
+        log_err("Could not open the test data file: %s\n", testFilePath);
+        delete parser;
+        return;
+    }
+
+    UnicodeString test_case        = UNICODE_STRING_SIMPLE("test-case");
+    UnicodeString test_text        = UNICODE_STRING_SIMPLE("test-text");
+    UnicodeString test_font        = UNICODE_STRING_SIMPLE("test-font");
+    UnicodeString result_glyphs    = UNICODE_STRING_SIMPLE("result-glyphs");
+    UnicodeString result_indices   = UNICODE_STRING_SIMPLE("result-indices");
+    UnicodeString result_positions = UNICODE_STRING_SIMPLE("result-positions");
+
+    // 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");
+    UnicodeString ver_attr    = UNICODE_STRING_SIMPLE("version");
+    UnicodeString cksum_attr  = UNICODE_STRING_SIMPLE("checksum");
+
+    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));
+            char *fontName  = NULL;
+                       char *fontVer   = NULL;
+                       char *fontCksum = NULL;
+            const UXMLElement *element;
+            int32_t ec = 0;
+            int32_t charCount = 0;
+            int32_t typoFlags = 3; // kerning + ligatures...
+            UScriptCode scriptCode;
+            le_int32 languageCode = -1;
+            UnicodeString text, glyphs, indices, positions;
+            int32_t glyphCount = 0, indexCount = 0, positionCount = 0;
+            TestResult expected = {0, NULL, NULL, NULL};
+
+            uscript_getCode(script, &scriptCode, 1, &status);
+            if (LE_FAILURE(status)) {
+                log_err("invalid script name: %s.\n", script);
+                goto free_c_strings;
+            }
+
+            if (lang != NULL) {
+                languageCode = getLanguageCode(lang);
+
+                if (languageCode < 0) {
+                    log_err("invalid language name: %s.\n", lang);
+                    goto free_c_strings;
+                }
+            }
+
+            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) {
+                    fontName  = getCString(element->getAttribute(name_attr));
+                    fontVer   = getCString(element->getAttribute(ver_attr));
+                    fontCksum = getCString(element->getAttribute(cksum_attr));
+
+                } else if (tag.compare(test_text) == 0) {
+                    text = element->getText(TRUE);
+                    charCount = text.length();
+                } else if (tag.compare(result_glyphs) == 0) {
+                    glyphs = element->getText(TRUE);
+                } else if (tag.compare(result_indices) == 0) {
+                    indices = element->getText(TRUE);
+                } else if (tag.compare(result_positions) == 0) {
+                    positions = element->getText(TRUE);
+                } else {
+                    // an unknown tag...
+                    char *cTag = getCString(&tag);
+
+                    log_info("Test %s: unknown element with tag \"%s\"\n", id, cTag);
+                    freeCString(cTag);
+                }
+            }
+
+            expected.glyphs    = (LEGlyphID *) getHexArray(glyphs, glyphCount);
+            expected.indices   = (le_int32 *)  getHexArray(indices, indexCount);
+            expected.positions = getFloatArray(positions, positionCount);
+
+            expected.glyphCount = glyphCount;
+
+            if (glyphCount < charCount || indexCount != glyphCount || positionCount < glyphCount * 2 + 2) {
+                log_err("Test %s: inconsistent input data: charCount = %d, glyphCount = %d, indexCount = %d, positionCount = %d\n",
+                    id, charCount, glyphCount, indexCount, positionCount);
+                goto free_expected;
+            };
+
+                       (*callback)(id, fontName, fontVer, fontCksum, scriptCode, languageCode, text.getBuffer(), charCount, &expected);
+
+free_expected:
+            DELETE_ARRAY(expected.positions);
+            DELETE_ARRAY(expected.indices);
+            DELETE_ARRAY(expected.glyphs);
+
+free_c_strings:
+                       freeCString(fontCksum);
+                       freeCString(fontVer);
+                       freeCString(fontName);
+            freeCString(lang);
+            freeCString(script);
+            freeCString(id);
+        }
+    }
+
+    delete root;
+    delete parser;
+#endif
+}
+U_CDECL_END
diff --git a/icu4c/source/test/perf/leperf/xmlreader.h b/icu4c/source/test/perf/leperf/xmlreader.h
new file mode 100644 (file)
index 0000000..386a097
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *
+ * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
+ *
+ */
+
+#ifndef __XMLREADER_H
+#define __XMLREADER_H
+
+#include "LETypes.h"
+#include "letest.h"
+
+typedef void (*TestCaseCallback) (const char *testID,
+                                                                 const char *fontName,
+                                                                 const char *fontVersion,
+                                                                 const char *fontChecksum,
+                                                                 le_int32 scriptCode,
+                                                                 le_int32 languageCode,
+                                                                 const LEUnicode *text,
+                                                                 le_int32 charCount,
+                                                                 TestResult *expected);
+
+U_CAPI void readTestFile(const char *testFilePath, TestCaseCallback callback);
+
+#endif