From: Steven R. Loomis Date: Thu, 27 Jun 2013 17:37:58 +0000 (+0000) Subject: ICU-10234 check in layout engine perf test X-Git-Tag: milestone-59-0-1~2806 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f4d12ea18303c01bc2aa0cc0226f9b5167bc2bb1;p=icu ICU-10234 check in layout engine perf test X-SVN-Rev: 33861 --- diff --git a/icu4c/source/configure b/icu4c/source/configure index 1a20f41d78a..a37b772e006 100755 --- a/icu4c/source/configure +++ b/icu4c/source/configure @@ -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 #include -#include -#include +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" ;; diff --git a/icu4c/source/configure.in b/icu4c/source/configure.in index 2e33779997d..fb1eda92c7d 100644 --- a/icu4c/source/configure.in +++ b/icu4c/source/configure.in @@ -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 index 00000000000..1d6f6ec88d0 --- /dev/null +++ b/icu4c/source/test/perf/leperf/FontObject.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** +* +* Copyright (C) 1998-2013, International Business Machines +* Corporation and others. All Rights Reserved. +* +************************************************************************/ + +#include + +#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 index 00000000000..c7961f5c3db --- /dev/null +++ b/icu4c/source/test/perf/leperf/FontObject.h @@ -0,0 +1,235 @@ +/*************************************************************************** +* +* Copyright (C) 1998-2013, International Business Machines +* Corporation and others. All Rights Reserved. +* +************************************************************************/ + + +#ifndef __FONTOBJECT_H +#define __FONTOBJECT_H + +#include + +#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 index 00000000000..a2c0727a212 --- /dev/null +++ b/icu4c/source/test/perf/leperf/FontTableCache.cpp @@ -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 index 00000000000..d0e1c54b078 --- /dev/null +++ b/icu4c/source/test/perf/leperf/FontTableCache.h @@ -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 index 00000000000..d943a57dfa6 --- /dev/null +++ b/icu4c/source/test/perf/leperf/Makefile.in @@ -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 index 00000000000..abbd8ee6077 --- /dev/null +++ b/icu4c/source/test/perf/leperf/PortableFontInstance.cpp @@ -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 + +#include "layout/LETypes.h" +#include "layout/LEFontInstance.h" +#include "layout/LESwaps.h" + +#include "PortableFontInstance.h" + +//#include "letest.h" +#include "sfnt.h" + +#include +#include + +#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 index 00000000000..ed366e9f7a0 --- /dev/null +++ b/icu4c/source/test/perf/leperf/PortableFontInstance.h @@ -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 + +#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 index 00000000000..d240a6aac88 --- /dev/null +++ b/icu4c/source/test/perf/leperf/SimpleFontInstance.cpp @@ -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 index 00000000000..1e28a82e0d4 --- /dev/null +++ b/icu4c/source/test/perf/leperf/SimpleFontInstance.h @@ -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 index 00000000000..a2e5d309754 --- /dev/null +++ b/icu4c/source/test/perf/leperf/cfonts.cpp @@ -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 index 00000000000..b5cbf285d11 --- /dev/null +++ b/icu4c/source/test/perf/leperf/cfonts.h @@ -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 index 00000000000..7eedb000e31 --- /dev/null +++ b/icu4c/source/test/perf/leperf/cmaps.cpp @@ -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 + +#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 index 00000000000..7a733adb8f8 --- /dev/null +++ b/icu4c/source/test/perf/leperf/cmaps.h @@ -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 index 00000000000..3881904f918 --- /dev/null +++ b/icu4c/source/test/perf/leperf/leperf.cpp @@ -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='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 index 00000000000..75cfe1bbdf5 --- /dev/null +++ b/icu4c/source/test/perf/leperf/letrperf.cpp @@ -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 +#include + +#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;iitems; + for(int i=0;i stuff(data, success); + if(LE_FAILURE(success)) { + puts("failure"); + abort(); + } + long *items2 = ((OneObject*)ref)->items; + for(int i=0;iitems; + for(int i=0;i 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 comp(data, success); + LEReferenceToArrayOf longs(comp, success, (size_t)0, ITEM_COUNT); + if(LE_FAILURE(success)) { + puts("failure"); + abort(); + } + + for(int i=0;i timing. %.1fs per run.\n", runTime); + items = new long[ITEM_COUNT]; + OneObject *oo = new OneObject(); + CompObject *oo2 = new CompObject(); + for(int i=0;iitems[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 index 00000000000..f39d64a9c7b --- /dev/null +++ b/icu4c/source/test/perf/leperf/sfnt.h @@ -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 index 00000000000..3115f183af7 --- /dev/null +++ b/icu4c/source/test/perf/leperf/xmlreader.cpp @@ -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 +#include +#include + +//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 index 00000000000..386a097133a --- /dev/null +++ b/icu4c/source/test/perf/leperf/xmlreader.h @@ -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