From 18d7573c5e6a900f8313213e0aeb24561f55e764 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 29 Jan 2002 03:02:50 +0000 Subject: [PATCH] Authors: Huw D M Davies , Charles Loep Various fixes for gdi font handling code including: - Using TTs VDMX table to ensure that we get exactly that same size font that Windows uses. - Fixes to many members of the metrics structures. - Font cache. - Rotated text support. - Support for GGO_GRAY?_BITMAP (ready for anti-aliased text). - Support for GGO_NATIVE. --- configure | 287 +++++++------- configure.in | 4 + dlls/gdi/freetype.c | 940 ++++++++++++++++++++++++++++++++++++++------ include/config.h.in | 3 + include/font.h | 3 +- include/gdi.h | 2 + objects/dc.c | 2 - objects/font.c | 68 +++- objects/gdiobj.c | 23 +- 9 files changed, 1043 insertions(+), 289 deletions(-) diff --git a/configure b/configure index b1eacceb1ad..159333aa218 100755 --- a/configure +++ b/configure @@ -4651,6 +4651,27 @@ else fi done + cat > conftest.$ac_ext < + #include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4662: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_FREETYPE_FTTRIGON_H 1 +EOF + +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* CPPFLAGS="$ac_save_CPPFLAGS" wine_cv_msg_freetype=no fi @@ -4659,19 +4680,19 @@ fi echo $ac_n "checking for parport header/ppdev.h""... $ac_c" 1>&6 -echo "configure:4663: checking for parport header/ppdev.h" >&5 +echo "configure:4684: checking for parport header/ppdev.h" >&5 if eval "test \"`echo '$''{'ac_cv_c_ppdev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { ioctl (1,PPCLAIM,0) ; return 0; } EOF -if { (eval echo configure:4675: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4696: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ppdev="yes" else @@ -4694,12 +4715,12 @@ EOF fi echo $ac_n "checking for GNU style IPX support""... $ac_c" 1>&6 -echo "configure:4698: checking for GNU style IPX support" >&5 +echo "configure:4719: checking for GNU style IPX support" >&5 if eval "test \"`echo '$''{'ac_cv_c_ipx_gnu'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -4707,7 +4728,7 @@ int main() { ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX ; return 0; } EOF -if { (eval echo configure:4711: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4732: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ipx_gnu="yes" else @@ -4732,12 +4753,12 @@ fi if test "$ac_cv_c_ipx_gnu" = "no" then echo $ac_n "checking for linux style IPX support""... $ac_c" 1>&6 -echo "configure:4736: checking for linux style IPX support" >&5 +echo "configure:4757: checking for linux style IPX support" >&5 if eval "test \"`echo '$''{'ac_cv_c_ipx_linux'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -4746,7 +4767,7 @@ int main() { ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX ; return 0; } EOF -if { (eval echo configure:4750: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4771: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ipx_linux="yes" else @@ -4773,17 +4794,17 @@ for ac_hdr in sys/soundcard.h machine/soundcard.h soundcard.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4777: checking for $ac_hdr" >&5 +echo "configure:4798: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4787: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4808: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4811,12 +4832,12 @@ done echo $ac_n "checking for Open Sound System""... $ac_c" 1>&6 -echo "configure:4815: checking for Open Sound System" >&5 +echo "configure:4836: checking for Open Sound System" >&5 if eval "test \"`echo '$''{'ac_cv_c_opensoundsystem'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4862: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_opensoundsystem="yes" else @@ -4860,12 +4881,12 @@ EOF fi echo $ac_n "checking for Open Sound System/MIDI interface""... $ac_c" 1>&6 -echo "configure:4864: checking for Open Sound System/MIDI interface" >&5 +echo "configure:4885: checking for Open Sound System/MIDI interface" >&5 if eval "test \"`echo '$''{'ac_cv_c_opensoundsystem_midi'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4911: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_opensoundsystem_midi="yes" else @@ -4912,7 +4933,7 @@ if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi echo $ac_n "checking whether mmap64 works defined as mmap""... $ac_c" 1>&6 -echo "configure:4916: checking whether mmap64 works defined as mmap" >&5 +echo "configure:4937: checking whether mmap64 works defined as mmap" >&5 if eval "test \"`echo '$''{'ac_cv_mmap64_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4920,7 +4941,7 @@ else ac_cv_mmap64_works="no" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4975: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_mmap64_works="yes" else @@ -4979,7 +5000,7 @@ if test "x${GCC}" = "xyes" then CFLAGS="$CFLAGS -Wall" echo $ac_n "checking for gcc strength-reduce bug""... $ac_c" 1>&6 -echo "configure:4983: checking for gcc strength-reduce bug" >&5 +echo "configure:5004: checking for gcc strength-reduce bug" >&5 if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4987,7 +5008,7 @@ else ac_cv_c_gcc_strength_bug="yes" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5027: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_gcc_strength_bug="no" else @@ -5023,21 +5044,21 @@ echo "$ac_t""$ac_cv_c_gcc_strength_bug" 1>&6 fi echo $ac_n "checking for gcc -mpreferred-stack-boundary=2 support""... $ac_c" 1>&6 -echo "configure:5027: checking for gcc -mpreferred-stack-boundary=2 support" >&5 +echo "configure:5048: checking for gcc -mpreferred-stack-boundary=2 support" >&5 if eval "test \"`echo '$''{'ac_cv_c_gcc_stack_boundary'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -mpreferred-stack-boundary=2" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_gcc_stack_boundary="yes" else @@ -5060,7 +5081,7 @@ fi echo $ac_n "checking whether .type must sit inside a .def directive""... $ac_c" 1>&6 -echo "configure:5064: checking whether .type must sit inside a .def directive" >&5 +echo "configure:5085: checking whether .type must sit inside a .def directive" >&5 if eval "test \"`echo '$''{'ac_cv_c_type_in_def'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5073,14 +5094,14 @@ _ac_test: .long 0 EOF cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5105: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_type_in_def="yes" else @@ -5104,7 +5125,7 @@ fi echo $ac_n "checking whether external symbols need an underscore prefix""... $ac_c" 1>&6 -echo "configure:5108: checking whether external symbols need an underscore prefix" >&5 +echo "configure:5129: checking whether external symbols need an underscore prefix" >&5 if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5116,14 +5137,14 @@ _ac_test: .long 0 EOF cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5148: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_extern_prefix="yes" else @@ -5147,7 +5168,7 @@ fi echo $ac_n "checking whether assembler accepts .string""... $ac_c" 1>&6 -echo "configure:5151: checking whether assembler accepts .string" >&5 +echo "configure:5172: checking whether assembler accepts .string" >&5 if eval "test \"`echo '$''{'ac_cv_c_asm_string'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5157,14 +5178,14 @@ cat > conftest_asm.s < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5189: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_asm_string="yes" else @@ -5192,21 +5213,21 @@ LDDLLFLAGS="" if test "$LIBEXT" = "so" then echo $ac_n "checking whether we can build a GNU style ELF dll""... $ac_c" 1>&6 -echo "configure:5196: checking whether we can build a GNU style ELF dll" >&5 +echo "configure:5217: checking whether we can build a GNU style ELF dll" >&5 if eval "test \"`echo '$''{'ac_cv_c_dll_gnuelf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0,-Bsymbolic" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_dll_gnuelf="yes" else @@ -5227,21 +5248,21 @@ echo "$ac_t""$ac_cv_c_dll_gnuelf" 1>&6 LDDLLFLAGS="-Wl,-Bsymbolic" else echo $ac_n "checking whether we can build a UnixWare (Solaris) dll""... $ac_c" 1>&6 -echo "configure:5231: checking whether we can build a UnixWare (Solaris) dll" >&5 +echo "configure:5252: checking whether we can build a UnixWare (Solaris) dll" >&5 if eval "test \"`echo '$''{'ac_cv_c_dll_unixware'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -fPIC -Wl,-G,-h,conftest.so.1.0,-B,symbolic" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5266: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_dll_unixware="yes" else @@ -5305,7 +5326,7 @@ fi wine_cv_libc_reentrant=no echo $ac_n "checking for reentrant libc: __errno_location""... $ac_c" 1>&6 -echo "configure:5309: checking for reentrant libc: __errno_location" >&5 +echo "configure:5330: checking for reentrant libc: __errno_location" >&5 if eval "test \"`echo '$''{'wine_cv_libc_r___errno_location'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5313,14 +5334,14 @@ else wine_cv_libc_r___errno_location=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then wine_cv_libc_r___errno_location=yes else @@ -5343,7 +5364,7 @@ fi echo $ac_n "checking for reentrant libc: __error""... $ac_c" 1>&6 -echo "configure:5347: checking for reentrant libc: __error" >&5 +echo "configure:5368: checking for reentrant libc: __error" >&5 if eval "test \"`echo '$''{'wine_cv_libc_r___error'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5351,14 +5372,14 @@ else wine_cv_libc_r___error=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5383: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then wine_cv_libc_r___error=yes else @@ -5381,7 +5402,7 @@ fi echo $ac_n "checking for reentrant libc: ___errno""... $ac_c" 1>&6 -echo "configure:5385: checking for reentrant libc: ___errno" >&5 +echo "configure:5406: checking for reentrant libc: ___errno" >&5 if eval "test \"`echo '$''{'wine_cv_libc_r____errno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5389,14 +5410,14 @@ else wine_cv_libc_r____errno=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5421: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then wine_cv_libc_r____errno=yes else @@ -5419,7 +5440,7 @@ fi echo $ac_n "checking for reentrant libc: __thr_errno""... $ac_c" 1>&6 -echo "configure:5423: checking for reentrant libc: __thr_errno" >&5 +echo "configure:5444: checking for reentrant libc: __thr_errno" >&5 if eval "test \"`echo '$''{'wine_cv_libc_r___thr_errno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5427,14 +5448,14 @@ else wine_cv_libc_r___thr_errno=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then wine_cv_libc_r___thr_errno=yes else @@ -5457,7 +5478,7 @@ fi echo $ac_n "checking for reentrant libc: __errno""... $ac_c" 1>&6 -echo "configure:5461: checking for reentrant libc: __errno" >&5 +echo "configure:5482: checking for reentrant libc: __errno" >&5 if eval "test \"`echo '$''{'wine_cv_libc_r___errno'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5465,14 +5486,14 @@ else wine_cv_libc_r___errno=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then wine_cv_libc_r___errno=yes else @@ -5506,7 +5527,7 @@ fi if test "$have_x" = "yes" -a "$wine_cv_libc_reentrant" != "no" then echo $ac_n "checking for reentrant X libraries""... $ac_c" 1>&6 -echo "configure:5510: checking for reentrant X libraries" >&5 +echo "configure:5531: checking for reentrant X libraries" >&5 if eval "test \"`echo '$''{'wine_cv_x_reentrant'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5555,19 +5576,19 @@ fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:5559: checking for working alloca.h" >&5 +echo "configure:5580: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:5571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -5588,12 +5609,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:5592: checking for alloca" >&5 +echo "configure:5613: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -5653,12 +5674,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:5657: checking whether alloca needs Cray hooks" >&5 +echo "configure:5678: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5687: checking for $ac_func" >&5 +echo "configure:5708: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5736: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5738,7 +5759,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:5742: checking stack direction for C alloca" >&5 +echo "configure:5763: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5746,7 +5767,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -5827,12 +5848,12 @@ for ac_func in \ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5831: checking for $ac_func" >&5 +echo "configure:5852: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5880: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5939,17 +5960,17 @@ for ac_hdr in \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5943: checking for $ac_hdr" >&5 +echo "configure:5964: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5953: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5974: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5976,12 +5997,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:5980: checking whether stat file-mode macros are broken" >&5 +echo "configure:6001: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6034,12 +6055,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:6038: checking for working const" >&5 +echo "configure:6059: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6113: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -6109,21 +6130,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:6113: checking for inline" >&5 +echo "configure:6134: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6148: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -6149,12 +6170,12 @@ EOF esac echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:6153: checking for ANSI C header files" >&5 +echo "configure:6174: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6162,7 +6183,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6187: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -6179,7 +6200,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -6197,7 +6218,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -6218,7 +6239,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -6229,7 +6250,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:6233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -6253,12 +6274,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:6257: checking for size_t" >&5 +echo "configure:6278: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6286,7 +6307,7 @@ EOF fi echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:6290: checking size of long long" >&5 +echo "configure:6311: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6294,7 +6315,7 @@ else ac_cv_sizeof_long_long=0 else cat > conftest.$ac_ext < #include @@ -6306,7 +6327,7 @@ main() exit(0); } EOF -if { (eval echo configure:6310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long=`cat conftestval` else @@ -6327,12 +6348,12 @@ EOF echo $ac_n "checking whether linux/input.h is for real""... $ac_c" 1>&6 -echo "configure:6331: checking whether linux/input.h is for real" >&5 +echo "configure:6352: checking whether linux/input.h is for real" >&5 if eval "test \"`echo '$''{'wine_cv_linux_input_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6345,7 +6366,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_input_h=yes else @@ -6369,12 +6390,12 @@ EOF echo $ac_n "checking whether we can use re-entrant gethostbyname_r Linux style""... $ac_c" 1>&6 -echo "configure:6373: checking whether we can use re-entrant gethostbyname_r Linux style" >&5 +echo "configure:6394: checking whether we can use re-entrant gethostbyname_r Linux style" >&5 if eval "test \"`echo '$''{'wine_cv_linux_gethostbyname_r_6'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6395,7 +6416,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6399: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6420: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_gethostbyname_r_6=yes else @@ -6421,12 +6442,12 @@ EOF if test "$ac_cv_header_linux_joystick_h" = "yes" then echo $ac_n "checking whether linux/joystick.h uses the Linux 2.2+ API""... $ac_c" 1>&6 -echo "configure:6425: checking whether linux/joystick.h uses the Linux 2.2+ API" >&5 +echo "configure:6446: checking whether linux/joystick.h uses the Linux 2.2+ API" >&5 if eval "test \"`echo '$''{'wine_cv_linux_joystick_22_api'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6441,7 +6462,7 @@ int main() { /*empty*/ ; return 0; } EOF -if { (eval echo configure:6445: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6466: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_joystick_22_api=yes else @@ -6468,12 +6489,12 @@ fi if test "$ac_cv_header_sys_vfs_h" = "yes" then echo $ac_n "checking whether sys/vfs.h defines statfs""... $ac_c" 1>&6 -echo "configure:6472: checking whether sys/vfs.h defines statfs" >&5 +echo "configure:6493: checking whether sys/vfs.h defines statfs" >&5 if eval "test \"`echo '$''{'wine_cv_sys_vfs_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6490,7 +6511,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6494: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6515: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_vfs_has_statfs=yes else @@ -6517,12 +6538,12 @@ fi if test "$ac_cv_header_sys_statfs_h" = "yes" then echo $ac_n "checking whether sys/statfs.h defines statfs""... $ac_c" 1>&6 -echo "configure:6521: checking whether sys/statfs.h defines statfs" >&5 +echo "configure:6542: checking whether sys/statfs.h defines statfs" >&5 if eval "test \"`echo '$''{'wine_cv_sys_statfs_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6537,7 +6558,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6541: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_statfs_has_statfs=yes else @@ -6564,12 +6585,12 @@ fi if test "$ac_cv_header_sys_mount_h" = "yes" then echo $ac_n "checking whether sys/mount.h defines statfs""... $ac_c" 1>&6 -echo "configure:6568: checking whether sys/mount.h defines statfs" >&5 +echo "configure:6589: checking whether sys/mount.h defines statfs" >&5 if eval "test \"`echo '$''{'wine_cv_sys_mount_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -6584,7 +6605,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6588: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6609: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_mount_has_statfs=yes else @@ -6610,7 +6631,7 @@ fi echo $ac_n "checking for statfs.f_bfree""... $ac_c" 1>&6 -echo "configure:6614: checking for statfs.f_bfree" >&5 +echo "configure:6635: checking for statfs.f_bfree" >&5 if eval "test \"`echo '$''{'wine_cv_statfs_bfree'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6619,7 +6640,7 @@ else wine_cv_statfs_bfree=no else cat > conftest.$ac_ext < @@ -6646,7 +6667,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6650: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6671: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bfree=yes else @@ -6670,7 +6691,7 @@ EOF fi echo $ac_n "checking for statfs.f_bavail""... $ac_c" 1>&6 -echo "configure:6674: checking for statfs.f_bavail" >&5 +echo "configure:6695: checking for statfs.f_bavail" >&5 if eval "test \"`echo '$''{'wine_cv_statfs_bavail'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6679,7 +6700,7 @@ else wine_cv_statfs_bavail=no else cat > conftest.$ac_ext < @@ -6706,7 +6727,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6710: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6731: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bavail=yes else @@ -6731,12 +6752,12 @@ fi echo $ac_n "checking for msg_accrights in struct msghdr""... $ac_c" 1>&6 -echo "configure:6735: checking for msg_accrights in struct msghdr" >&5 +echo "configure:6756: checking for msg_accrights in struct msghdr" >&5 if eval "test \"`echo '$''{'ac_cv_c_msg_accrights'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6744,7 +6765,7 @@ int main() { struct msghdr hdr; hdr.msg_accrights=0 ; return 0; } EOF -if { (eval echo configure:6748: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6769: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_msg_accrights="yes" else @@ -6767,12 +6788,12 @@ fi echo $ac_n "checking for sa_len in struct sockaddr""... $ac_c" 1>&6 -echo "configure:6771: checking for sa_len in struct sockaddr" >&5 +echo "configure:6792: checking for sa_len in struct sockaddr" >&5 if eval "test \"`echo '$''{'ac_cv_c_sockaddr_sa_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6781,7 +6802,7 @@ int main() { static struct sockaddr addr; addr.sa_len = 1 ; return 0; } EOF -if { (eval echo configure:6785: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6806: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sockaddr_sa_len="yes" else @@ -6804,12 +6825,12 @@ fi echo $ac_n "checking for sun_len in struct sockaddr_un""... $ac_c" 1>&6 -echo "configure:6808: checking for sun_len in struct sockaddr_un" >&5 +echo "configure:6829: checking for sun_len in struct sockaddr_un" >&5 if eval "test \"`echo '$''{'ac_cv_c_sockaddr_sun_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6818,7 +6839,7 @@ int main() { static struct sockaddr_un addr; addr.sun_len = 1 ; return 0; } EOF -if { (eval echo configure:6822: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6843: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sockaddr_sun_len="yes" else @@ -6841,12 +6862,12 @@ fi echo $ac_n "checking whether we need to define __i386__""... $ac_c" 1>&6 -echo "configure:6845: checking whether we need to define __i386__" >&5 +echo "configure:6866: checking whether we need to define __i386__" >&5 if eval "test \"`echo '$''{'ac_cv_cpp_def_i386'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < + #include ], + AC_DEFINE(HAVE_FREETYPE_FTTRIGON_H, 1, + [Define if you have the header file.])) CPPFLAGS="$ac_save_CPPFLAGS" wine_cv_msg_freetype=no fi diff --git a/dlls/gdi/freetype.c b/dlls/gdi/freetype.c index 5d1fd91c45b..f45469eb0a5 100644 --- a/dlls/gdi/freetype.c +++ b/dlls/gdi/freetype.c @@ -14,10 +14,12 @@ #include "winreg.h" #include "wingdi.h" #include "wine/unicode.h" +#include "wine/port.h" #include "gdi.h" #include "font.h" #include "debugtools.h" +#include #include #include #include @@ -52,6 +54,9 @@ DEFAULT_DEBUG_CHANNEL(font); #ifdef HAVE_FREETYPE_INTERNAL_SFNT_H #include #endif +#ifdef HAVE_FREETYPE_FTTRIGON_H +#include +#endif static FT_Library library = 0; @@ -60,6 +65,7 @@ typedef struct tagFace { char *file; BOOL Italic; BOOL Bold; + DWORD fsCsb[2]; /* codepage bitfield from FONTSIGNATURE */ struct tagFace *next; } Face; @@ -69,25 +75,90 @@ typedef struct tagFamily { struct tagFamily *next; } Family; +typedef struct { + GLYPHMETRICS gm; + INT adv; /* These three hold to widths of the unrotated chars */ + INT lsb; + INT bbx; + BOOL init; +} GM; + struct tagGdiFont { - DWORD ref; FT_Face ft_face; + int charset; + BOOL fake_italic; + BOOL fake_bold; + INT orientation; + GM *gm; + DWORD gmsize; + HFONT hfont; + SHORT yMax; + SHORT yMin; + struct tagGdiFont *next; }; +#define INIT_GM_SIZE 128 + +static GdiFont GdiFontList = NULL; + static Family *FontList = NULL; +static WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ', + 'R','o','m','a','n','\0'}; +static WCHAR defSans[] = {'A','r','i','a','l','\0'}; +static WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'}; + +static WCHAR defSystem[] = {'A','r','i','a','l','\0'}; +static WCHAR SystemW[] = {'S','y','s','t','e','m','\0'}; +static WCHAR MSSansSerifW[] = {'M','S',' ','S','a','n','s',' ', + 'S','e','r','i','f','\0'}; +static WCHAR HelvW[] = {'H','e','l','v','\0'}; + +static WCHAR ArabicW[] = {'A','r','a','b','i','c','\0'}; +static WCHAR BalticW[] = {'B','a','l','t','i','c','\0'}; +static WCHAR Central_EuropeanW[] = {'C','e','n','t','r','a','l',' ', + 'E','u','r','o','p','e','a','n','\0'}; +static WCHAR CyrillicW[] = {'C','y','r','i','l','l','i','c','\0'}; +static WCHAR GreekW[] = {'G','r','e','e','k','\0'}; +static WCHAR HebrewW[] = {'H','e','b','r','e','w','\0'}; +static WCHAR SymbolW[] = {'S','y','m','b','o','l','\0'}; +static WCHAR ThaiW[] = {'T','h','a','i','\0'}; +static WCHAR TurkishW[] = {'T','u','r','k','i','s','h','\0'}; +static WCHAR VietnameseW[] = {'V','i','e','t','n','a','m','e','s','e','\0'}; +static WCHAR WesternW[] = {'W','e','s','t','e','r','n','\0'}; + +static WCHAR *ElfScriptsW[32] = { /* these are in the order of the fsCsb[0] bits */ + WesternW, /*00*/ + Central_EuropeanW, + CyrillicW, + GreekW, + TurkishW, + HebrewW, + ArabicW, + BalticW, + VietnameseW, /*08*/ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/ + ThaiW, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*23*/ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + SymbolW /*31*/ +}; + static BOOL AddFontFileToList(char *file) { FT_Face ft_face; + TT_OS2 *pOS2; WCHAR *FamilyW, *StyleW; DWORD len; Family *family = FontList; Family **insert = &FontList; Face **insertface; + FT_Error err; + int i; TRACE("Loading font file %s\n", debugstr_a(file)); - if(FT_New_Face(library, file, 0, &ft_face)) { - ERR("Unable to load font file %s\n", debugstr_a(file)); + if((err = FT_New_Face(library, file, 0, &ft_face)) != 0) { + ERR("Unable to load font file %s err = %x\n", debugstr_a(file), err); return FALSE; } @@ -137,6 +208,31 @@ static BOOL AddFontFileToList(char *file) (*insertface)->next = NULL; (*insertface)->Italic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0; (*insertface)->Bold = (ft_face->style_flags & FT_STYLE_FLAG_BOLD) ? 1 : 0; + + pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); + if(pOS2) { + (*insertface)->fsCsb[0] = pOS2->ulCodePageRange1; + (*insertface)->fsCsb[1] = pOS2->ulCodePageRange2; + } else { + (*insertface)->fsCsb[0] = (*insertface)->fsCsb[1] = 0; + } + + if((*insertface)->fsCsb[0] == 0) { /* let's see if we can find any interesting cmaps */ + for(i = 0; i < ft_face->num_charmaps && + !(*insertface)->fsCsb[0]; i++) { + switch(ft_face->charmaps[i]->encoding) { + case ft_encoding_unicode: + (*insertface)->fsCsb[0] = 1; + break; + case ft_encoding_symbol: + (*insertface)->fsCsb[0] = 1L << 31; + break; + default: + break; + } + } + } + FT_Done_Face(ft_face); TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), @@ -164,20 +260,38 @@ static BOOL ReadFontDir(char *dirname) struct dirent *dent; char path[MAX_PATH]; + TRACE("Loading fonts from %s\n", debugstr_a(dirname)); + dir = opendir(dirname); if(!dir) { ERR("Can't open directory %s\n", debugstr_a(dirname)); return FALSE; } while((dent = readdir(dir)) != NULL) { + struct stat statbuf; + if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; + + TRACE("Found %s in %s\n", debugstr_a(dent->d_name), debugstr_a(dirname)); + sprintf(path, "%s/%s", dirname, dent->d_name); - AddFontFileToList(path); + + if(stat(path, &statbuf) == -1) + { + WARN("Can't stat %s\n", debugstr_a(path)); + continue; + } + if(S_ISDIR(statbuf.st_mode)) + ReadFontDir(path); + else + AddFontFileToList(path); } return TRUE; } + + /************************************************************* * WineEngInit * @@ -189,57 +303,59 @@ BOOL WineEngInit(void) DWORD valuelen, datalen, i = 0, type, dlen, vlen; LPSTR value; LPVOID data; + char windowsdir[MAX_PATH]; + char unixname[MAX_PATH]; + + TRACE("\n"); if(FT_Init_FreeType(&library) != 0) { ERR("Can't init FreeType library\n"); return FALSE; } + /* load in the fonts from %WINDOWSDIR%\\Fonts first of all */ + GetWindowsDirectoryA(windowsdir, sizeof(windowsdir)); + strcat(windowsdir, "\\Fonts"); + wine_get_unix_file_name(windowsdir, unixname, sizeof(unixname)); + ReadFontDir(unixname); + + /* then look in any directories that we've specified in the config file */ if(RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\FontDirs", - &hkey) != ERROR_SUCCESS) { - TRACE("Can't open FontDirs key in config file\n"); - return FALSE; - } + &hkey) == ERROR_SUCCESS) { - RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &valuelen, - &datalen, NULL, NULL); + RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &valuelen, &datalen, NULL, NULL); - valuelen++; /* returned value doesn't include room for '\0' */ - value = HeapAlloc(GetProcessHeap(), 0, valuelen); - data = HeapAlloc(GetProcessHeap(), 0, datalen); + valuelen++; /* returned value doesn't include room for '\0' */ + value = HeapAlloc(GetProcessHeap(), 0, valuelen); + data = HeapAlloc(GetProcessHeap(), 0, datalen); - dlen = datalen; - vlen = valuelen; - while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data, - &dlen) == ERROR_SUCCESS) { - TRACE("Got %s=%s\n", value, (LPSTR)data); - ReadFontDir((LPSTR)data); - /* reset dlen and vlen */ dlen = datalen; vlen = valuelen; + while(RegEnumValueA(hkey, i++, value, &vlen, NULL, &type, data, + &dlen) == ERROR_SUCCESS) { + TRACE("Got %s=%s\n", value, (LPSTR)data); + ReadFontDir((LPSTR)data); + /* reset dlen and vlen */ + dlen = datalen; + vlen = valuelen; + } + HeapFree(GetProcessHeap(), 0, data); + HeapFree(GetProcessHeap(), 0, value); + RegCloseKey(hkey); } - HeapFree(GetProcessHeap(), 0, data); - HeapFree(GetProcessHeap(), 0, value); - RegCloseKey(hkey); + DumpFontList(); return TRUE; } -static FT_Face OpenFontFile(char *file, LONG height) +static LONG calc_ppem_for_height(FT_Face ft_face, LONG height) { - FT_Error err; TT_OS2 *pOS2; - FT_Face ft_face; LONG ppem; - err = FT_New_Face(library, file, 0, &ft_face); - if(err) { - ERR("FT_New_Face rets %d\n", err); - return 0; - } - pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); if(height == 0) height = 16; @@ -260,14 +376,221 @@ static FT_Face OpenFontFile(char *file, LONG height) if(height > 0) ppem = ft_face->units_per_EM * height / - (pOS2->usWinAscent + pOS2->usWinDescent); + (pOS2->usWinAscent + pOS2->usWinDescent); else ppem = -height; + return ppem; +} + +static LONG load_VDMX(GdiFont, LONG); + +static FT_Face OpenFontFile(GdiFont font, char *file, LONG height) +{ + FT_Error err; + FT_Face ft_face; + LONG ppem; + + err = FT_New_Face(library, file, 0, &ft_face); + if(err) { + ERR("FT_New_Face rets %d\n", err); + return 0; + } + + /* set it here, as load_VDMX needs it */ + font->ft_face = ft_face; + + /* load the VDMX table if we have one */ + ppem = load_VDMX(font, height); + if(ppem == 0) + ppem = calc_ppem_for_height(ft_face, height); + FT_Set_Pixel_Sizes(ft_face, 0, ppem); + return ft_face; } +static int get_nearest_charset(Face *face, int lfcharset) +{ + CHARSETINFO csi; + TranslateCharsetInfo((DWORD*)lfcharset, &csi, TCI_SRCCHARSET); + + if(csi.fs.fsCsb[0] & face->fsCsb[0]) return lfcharset; + + if(face->fsCsb[0] & 0x1) return ANSI_CHARSET; + + if(face->fsCsb[0] & (1L << 31)) return SYMBOL_CHARSET; + + FIXME("returning DEFAULT_CHARSET face->fsCsb[0] = %08lx file = %s\n", + face->fsCsb[0], face->file); + return DEFAULT_CHARSET; +} + +static GdiFont alloc_font(void) +{ + GdiFont ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); + ret->gmsize = INIT_GM_SIZE; + ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + ret->gmsize * sizeof(*ret->gm)); + ret->next = NULL; + return ret; +} + +static void free_font(GdiFont font) +{ + FT_Done_Face(font->ft_face); + HeapFree(GetProcessHeap(), 0, font->gm); + HeapFree(GetProcessHeap(), 0, font); +} + + +/************************************************************* + * load_VDMX + * + * load the vdmx entry for the specified height + */ + +#define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (FT_ULong)_x4 << 24 ) | \ + ( (FT_ULong)_x3 << 16 ) | \ + ( (FT_ULong)_x2 << 8 ) | \ + (FT_ULong)_x1 ) + +#define MS_VDMX_TAG MS_MAKE_TAG('V', 'D', 'M', 'X') + +typedef struct { + BYTE bCharSet; + BYTE xRatio; + BYTE yStartRatio; + BYTE yEndRatio; +} Ratios; + + +static LONG load_VDMX(GdiFont font, LONG height) +{ + BYTE hdr[6], tmp[2], group[4]; + BYTE devXRatio, devYRatio; + USHORT numRecs, numRatios; + DWORD offset = -1; + LONG ppem = 0; + int i, result; + + result = WineEngGetFontData(font, MS_VDMX_TAG, 0, hdr, 6); + + if(result == GDI_ERROR) /* no vdmx table present, use linear scaling */ + return ppem; + + /* FIXME: need the real device aspect ratio */ + devXRatio = 1; + devYRatio = 1; + + numRecs = GET_BE_WORD(&hdr[2]); + numRatios = GET_BE_WORD(&hdr[4]); + + for(i = 0; i < numRatios; i++) { + Ratios ratio; + + offset = (3 * 2) + (i * sizeof(Ratios)); + WineEngGetFontData(font, MS_VDMX_TAG, offset, &ratio, sizeof(Ratios)); + offset = -1; + + TRACE("Ratios[%d] %d %d : %d -> %d\n", i, ratio.bCharSet, ratio.xRatio, ratio.yStartRatio, ratio.yEndRatio); + + if(ratio.bCharSet != 1) + continue; + + if((ratio.xRatio == 0 && + ratio.yStartRatio == 0 && + ratio.yEndRatio == 0) || + (devXRatio == ratio.xRatio && + devYRatio >= ratio.yStartRatio && + devYRatio <= ratio.yEndRatio)) + { + offset = (3 * 2) + (numRatios * 4) + (i * 2); + WineEngGetFontData(font, MS_VDMX_TAG, offset, tmp, 2); + offset = GET_BE_WORD(tmp); + break; + } + } + + if(offset < 0) { + FIXME("No suitable ratio found"); + return ppem; + } + + if(WineEngGetFontData(font, MS_VDMX_TAG, offset, group, 4) != GDI_ERROR) { + USHORT recs; + BYTE startsz, endsz; + BYTE *vTable; + + recs = GET_BE_WORD(group); + startsz = group[2]; + endsz = group[3]; + + TRACE("recs=%d startsz=%d endsz=%d\n", recs, startsz, endsz); + + vTable = HeapAlloc(GetProcessHeap(), 0, recs * 6); + result = WineEngGetFontData(font, MS_VDMX_TAG, offset + 4, vTable, recs * 6); + if(result == GDI_ERROR) { + FIXME("Failed to retrieve vTable\n"); + goto end; + } + + if(height > 0) { + for(i = 0; i < recs; i++) { + SHORT yMax = GET_BE_WORD(&vTable[(i * 6) + 2]); + SHORT yMin = GET_BE_WORD(&vTable[(i * 6) + 4]); + ppem = GET_BE_WORD(&vTable[i * 6]); + + if(yMax + -yMin == height) { + font->yMax = yMax; + font->yMin = yMin; + TRACE("ppem %ld found; height=%ld yMax=%d yMin=%d\n", ppem, height, font->yMax, font->yMin); + break; + } + if(yMax + -yMin > height) { + if(--i < 0) { + ppem = 0; + goto end; /* failed */ + } + font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]); + font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]); + TRACE("ppem %ld found; height=%ld yMax=%d yMin=%d\n", ppem, height, font->yMax, font->yMin); + break; + } + } + if(!font->yMax) { + ppem = 0; + TRACE("ppem not found for height %ld\n", height); + } + } else { + ppem = -height; + if(ppem < startsz || ppem > endsz) + goto end; + + for(i = 0; i < recs; i++) { + USHORT yPelHeight; + yPelHeight = GET_BE_WORD(&vTable[i * 6]); + + if(yPelHeight > ppem) + break; /* failed */ + + if(yPelHeight == ppem) { + font->yMax = GET_BE_WORD(&vTable[(i * 6) + 2]); + font->yMin = GET_BE_WORD(&vTable[(i * 6) + 4]); + TRACE("ppem %ld found; yMax=%d yMin=%d\n", ppem, font->yMax, font->yMin); + break; + } + } + } + end: + HeapFree(GetProcessHeap(), 0, vTable); + } + + return ppem; +} + + /************************************************************* * WineEngCreateFontInstance * @@ -282,11 +605,28 @@ GdiFont WineEngCreateFontInstance(HFONT hfont) FONTOBJ *font = GDI_GetObjPtr(hfont, FONT_MAGIC); LOGFONTW *plf = &font->logfont; - TRACE("%s, h=%ld, it=%d, weight=%ld\n", debugstr_w(plf->lfFaceName), - plf->lfHeight, plf->lfItalic, plf->lfWeight); + TRACE("%s, h=%ld, it=%d, weight=%ld, PandF=%02x, charset=%d orient %ld escapement %ld\n", + debugstr_w(plf->lfFaceName), plf->lfHeight, plf->lfItalic, + plf->lfWeight, plf->lfPitchAndFamily, plf->lfCharSet, plf->lfOrientation, + plf->lfEscapement); - ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); - ret->ref = 1; + /* check the cache first */ + for(ret = GdiFontList; ret; ret = ret->next) { + if(ret->hfont == hfont) { + GDI_ReleaseObj(hfont); + TRACE("returning cached gdiFont(%p) for hFont %x\n", ret, hfont); + return ret; + } + } + + if(!FontList) /* No fonts installed */ + { + GDI_ReleaseObj(hfont); + TRACE("No fonts installed\n"); + return NULL; + } + + ret = alloc_font(); strcpyW(FaceName, plf->lfFaceName); @@ -295,6 +635,37 @@ GdiFont WineEngCreateFontInstance(HFONT hfont) if(!strcmpiW(family->FamilyName, FaceName)) break; } + + if(!family) { /* do other aliases here */ + if(!strcmpiW(FaceName, SystemW)) + strcpyW(FaceName, defSystem); + else if(!strcmpiW(FaceName, MSSansSerifW)) + strcpyW(FaceName, defSans); + else if(!strcmpiW(FaceName, HelvW)) + strcpyW(FaceName, defSans); + else + goto not_found; + + for(family = FontList; family; family = family->next) { + if(!strcmpiW(family->FamilyName, FaceName)) + break; + } + } + } + +not_found: + if(!family) { + if(plf->lfPitchAndFamily & FIXED_PITCH || + plf->lfPitchAndFamily & FF_MODERN) + strcpyW(FaceName, defFixed); + else if(plf->lfPitchAndFamily & FF_ROMAN) + strcpyW(FaceName, defSerif); + else if(plf->lfPitchAndFamily & FF_SWISS) + strcpyW(FaceName, defSans); + for(family = FontList; family; family = family->next) { + if(!strcmpiW(family->FamilyName, FaceName)) + break; + } } if(!family) { @@ -309,40 +680,73 @@ GdiFont WineEngCreateFontInstance(HFONT hfont) if(!(face->Italic ^ it) && !(face->Bold ^ bd)) break; } - if(!face) face = family->FirstFace; + if(!face) { + face = family->FirstFace; + if(it && !face->Italic) ret->fake_italic = TRUE; + if(bd && !face->Bold) ret->fake_bold = TRUE; + } + ret->charset = get_nearest_charset(face, plf->lfCharSet); TRACE("Choosen %s %s\n", debugstr_w(family->FamilyName), debugstr_w(face->StyleName)); - ret->ft_face = OpenFontFile(face->file, plf->lfHeight); + ret->ft_face = OpenFontFile(ret, face->file, plf->lfHeight); + if(ret->charset == SYMBOL_CHARSET) + FT_Select_Charmap(ret->ft_face, ft_encoding_symbol); + ret->orientation = plf->lfOrientation; GDI_ReleaseObj(hfont); - TRACE("returning %p\n", ret); + + TRACE("caching: gdiFont=%p hfont=%x\n", ret, hfont); + ret->hfont = hfont; + ret->next = GdiFontList; + GdiFontList = ret; + return ret; } -/************************************************************* - * WineEngAddRefFont - * - */ -DWORD WineEngAddRefFont(GdiFont font) +static void DumpGdiFontList(void) { - return ++font->ref; -} + GdiFont gdiFont; -/************************************************************* - * WineEngDecRefFont - * - */ -DWORD WineEngDecRefFont(GdiFont font) -{ - DWORD ret = --font->ref; - - if(ret == 0) { - FT_Done_Face(font->ft_face); - HeapFree(GetProcessHeap(), 0, font); + TRACE("---------- gdiFont Cache ----------\n"); + for(gdiFont = GdiFontList; gdiFont; gdiFont = gdiFont->next) { + FONTOBJ *font = GDI_GetObjPtr(gdiFont->hfont, FONT_MAGIC); + LOGFONTW *plf = &font->logfont; + TRACE("gdiFont=%p hfont=%x (%s)\n", + gdiFont, gdiFont->hfont, debugstr_w(plf->lfFaceName)); + GDI_ReleaseObj(gdiFont->hfont); } - return ret; +} + +/************************************************************* + * WineEngDestroyFontInstance + * + * free the gdiFont associated with this handle + * + */ +BOOL WineEngDestroyFontInstance(HFONT handle) +{ + GdiFont gdiFont; + GdiFont gdiPrev = NULL; + + TRACE("destroying hfont=%x\n", handle); + if(TRACE_ON(font)) + DumpGdiFontList(); + + for(gdiFont = GdiFontList; gdiFont; gdiFont = gdiFont->next) { + if(gdiFont->hfont == handle) { + if(gdiPrev) + gdiPrev->next = gdiFont->next; + else + GdiFontList = gdiFont->next; + + free_font(gdiFont); + return TRUE; + } + gdiPrev = gdiFont; + } + return FALSE; } static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, @@ -350,10 +754,9 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, { OUTLINETEXTMETRICW *potm; UINT size; - GdiFont font = HeapAlloc(GetProcessHeap(),0,sizeof(*font)); + GdiFont font = alloc_font(); - font->ref = 1; - font->ft_face = OpenFontFile(face->file, 100); + font->ft_face = OpenFontFile(font, face->file, 100); memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW)); @@ -368,7 +771,7 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, pntm->ntmTm.tmDescent = TM.tmDescent; pntm->ntmTm.tmInternalLeading = TM.tmInternalLeading; pntm->ntmTm.tmExternalLeading = TM.tmExternalLeading; - pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWeight = TM.tmAveCharWidth; + pntm->ntmTm.tmAveCharWidth = pelf->elfLogFont.lfWidth = TM.tmAveCharWidth; pntm->ntmTm.tmMaxCharWidth = TM.tmMaxCharWidth; pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = TM.tmWeight; pntm->ntmTm.tmOverhang = TM.tmOverhang; @@ -384,6 +787,9 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, pntm->ntmTm.tmPitchAndFamily = TM.tmPitchAndFamily; pelf->elfLogFont.lfPitchAndFamily = (TM.tmPitchAndFamily & 0xf1) + 1; pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = TM.tmCharSet; + pelf->elfLogFont.lfOutPrecision = OUT_STROKE_PRECIS; + pelf->elfLogFont.lfClipPrecision = CLIP_STROKE_PRECIS; + pelf->elfLogFont.lfQuality = DRAFT_QUALITY; pntm->ntmTm.ntmFlags = TM.tmItalic ? NTM_ITALIC : 0; if(TM.tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD; @@ -404,15 +810,15 @@ static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName), LF_FACESIZE); strncpyW(pelf->elfFullName, - (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFullName), + (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFaceName), LF_FULLFACESIZE); strncpyW(pelf->elfStyle, (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName), LF_FACESIZE); - pelf->elfScript[0] = '\0'; /* FIXME */ + pelf->elfScript[0] = '\0'; /* This will get set in WineEngEnumFonts */ HeapFree(GetProcessHeap(), 0, potm); - WineEngDecRefFont(font); + free_font(font); return; } @@ -428,32 +834,98 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, ENUMLOGFONTEXW elf; NEWTEXTMETRICEXW ntm; DWORD type, ret = 1; + FONTSIGNATURE fs; + CHARSETINFO csi; + int i; - TRACE("facename = %s\n", debugstr_w(plf->lfFaceName)); + TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet); if(plf->lfFaceName[0]) { for(family = FontList; family; family = family->next) { if(!strcmpiW(plf->lfFaceName, family->FamilyName)) { for(face = family->FirstFace; face; face = face->next) { GetEnumStructs(face, &elf, &ntm, &type); - TRACE("enuming '%s'\n", - debugstr_w(elf.elfLogFont.lfFaceName)); - ret = proc(&elf, &ntm, type, lparam); - if(!ret) break; + for(i = 0; i < 32; i++) { + if(face->fsCsb[0] & (1L << i)) { + fs.fsCsb[0] = 1L << i; + fs.fsCsb[1] = 0; + if(!TranslateCharsetInfo(fs.fsCsb, &csi, + TCI_SRCFONTSIG)) + csi.ciCharset = DEFAULT_CHARSET; + if(i == 31) csi.ciCharset = SYMBOL_CHARSET; + if(csi.ciCharset != DEFAULT_CHARSET) { + elf.elfLogFont.lfCharSet = + ntm.ntmTm.tmCharSet = csi.ciCharset; + if(ElfScriptsW[i]) + strcpyW(elf.elfScript, ElfScriptsW[i]); + else + FIXME("Unknown elfscript for bit %d\n", i); + TRACE("enuming face %s full %s style %s charset %d type %ld script %s it %d weight %ld ntmflags %08lx\n", + debugstr_w(elf.elfLogFont.lfFaceName), + debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle), + csi.ciCharset, type, debugstr_w(elf.elfScript), + elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight, + ntm.ntmTm.ntmFlags); + ret = proc(&elf, &ntm, type, lparam); + if(!ret) goto end; + } + } + } } } } } else { for(family = FontList; family; family = family->next) { GetEnumStructs(family->FirstFace, &elf, &ntm, &type); - TRACE("enuming '%s'\n", debugstr_w(elf.elfLogFont.lfFaceName)); - ret = proc(&elf, &ntm, type, lparam); - if(!ret) break; + for(i = 0; i < 32; i++) { + if(family->FirstFace->fsCsb[0] & (1L << i)) { + fs.fsCsb[0] = 1L << i; + fs.fsCsb[1] = 0; + if(!TranslateCharsetInfo(fs.fsCsb, &csi, + TCI_SRCFONTSIG)) + csi.ciCharset = DEFAULT_CHARSET; + if(i == 31) csi.ciCharset = SYMBOL_CHARSET; + if(csi.ciCharset != DEFAULT_CHARSET) { + elf.elfLogFont.lfCharSet = ntm.ntmTm.tmCharSet = + csi.ciCharset; + if(ElfScriptsW[i]) + strcpyW(elf.elfScript, ElfScriptsW[i]); + else + FIXME("Unknown elfscript for bit %d\n", i); + TRACE("enuming face %s full %s style %s charset = %d type %ld script %s it %d weight %ld ntmflags %08lx\n", + debugstr_w(elf.elfLogFont.lfFaceName), + debugstr_w(elf.elfFullName), debugstr_w(elf.elfStyle), + csi.ciCharset, type, debugstr_w(elf.elfScript), + elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight, + ntm.ntmTm.ntmFlags); + ret = proc(&elf, &ntm, type, lparam); + if(!ret) goto end; + } + } + } } } - +end: return ret; } +static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) +{ + pt->x.value = vec->x >> 6; + pt->x.fract = (vec->x & 0x3f) << 10; + pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12)); + pt->y.value = vec->y >> 6; + pt->y.fract = (vec->y & 0x3f) << 10; + pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12)); + return; +} + +static FT_UInt get_glyph_index(GdiFont font, UINT glyph) +{ + if(font->charset == SYMBOL_CHARSET && glyph < 0x100) + glyph = glyph + 0xf000; + return FT_Get_Char_Index(font->ft_face, glyph); +} + /************************************************************* * WineEngGetGlyphOutline * @@ -468,58 +940,252 @@ DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, { FT_Face ft_face = font->ft_face; FT_UInt glyph_index; - DWORD width, height, pitch, needed; + DWORD width, height, pitch, needed = 0; FT_Bitmap ft_bitmap; + FT_Error err; + INT left, right, top = 0, bottom = 0; + FT_Angle angle = 0; TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); - if(format & GGO_GLYPH_INDEX) + if(format & GGO_GLYPH_INDEX) { glyph_index = glyph; - else - glyph_index = FT_Get_Char_Index(ft_face, glyph); + format &= ~GGO_GLYPH_INDEX; + } else + glyph_index = get_glyph_index(font, glyph); - FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); + if(glyph_index >= font->gmsize) { + font->gmsize = (glyph_index / INIT_GM_SIZE + 1) * INIT_GM_SIZE; + font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm, + font->gmsize * sizeof(*font->gm)); + } else { + if(format == GGO_METRICS && font->gm[glyph_index].init) { + memcpy(lpgm, &font->gm[glyph_index].gm, sizeof(*lpgm)); + return 1; /* FIXME */ + } + } - lpgm->gmBlackBoxX = ft_face->glyph->metrics.width >> 6; - lpgm->gmBlackBoxY = ft_face->glyph->metrics.height >> 6; - lpgm->gmptGlyphOrigin.x = ft_face->glyph->metrics.horiBearingX >> 6; - lpgm->gmptGlyphOrigin.y = ft_face->glyph->metrics.horiBearingY >> 6; - lpgm->gmCellIncX = ft_face->glyph->metrics.horiAdvance >> 6; - lpgm->gmCellIncY = 0; + err = FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); + + if(err) { + FIXME("FT_Load_Glyph on index %x returns %d\n", glyph_index, err); + return GDI_ERROR; + } + + left = ft_face->glyph->metrics.horiBearingX & -64; + right = ((ft_face->glyph->metrics.horiBearingX + + ft_face->glyph->metrics.width) + 63) & -64; + + font->gm[glyph_index].adv = (ft_face->glyph->metrics.horiAdvance + 63) >> 6; + font->gm[glyph_index].lsb = left >> 6; + font->gm[glyph_index].bbx = (right - left) >> 6; + + if(font->orientation == 0) { + top = (ft_face->glyph->metrics.horiBearingY + 63) & -64;; + bottom = (ft_face->glyph->metrics.horiBearingY - + ft_face->glyph->metrics.height) & -64; + lpgm->gmCellIncX = font->gm[glyph_index].adv; + lpgm->gmCellIncY = 0; + } else { + INT xc, yc; + FT_Vector vec; + angle = font->orientation / 10 << 16; + angle |= ((font->orientation % 10) * (1 << 16)) / 10; + TRACE("angle %ld\n", angle >> 16); + for(xc = 0; xc < 2; xc++) { + for(yc = 0; yc < 2; yc++) { + vec.x = ft_face->glyph->metrics.horiBearingX + + xc * ft_face->glyph->metrics.width; + vec.y = ft_face->glyph->metrics.horiBearingY - + yc * ft_face->glyph->metrics.height; + TRACE("Vec %ld,%ld\n", vec.x, vec.y); + FT_Vector_Rotate(&vec, angle); + if(xc == 0 && yc == 0) { + left = right = vec.x; + top = bottom = vec.y; + } else { + if(vec.x < left) left = vec.x; + else if(vec.x > right) right = vec.x; + if(vec.y < bottom) bottom = vec.y; + else if(vec.y > top) top = vec.y; + } + } + } + left = left & -64; + right = (right + 63) & -64; + bottom = bottom & -64; + top = (top + 63) & -64; + + TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom); + vec.x = ft_face->glyph->metrics.horiAdvance; + vec.y = 0; + FT_Vector_Rotate(&vec, angle); + lpgm->gmCellIncX = (vec.x+63) >> 6; + lpgm->gmCellIncY = -(vec.y+63) >> 6; + } + lpgm->gmBlackBoxX = (right - left) >> 6; + lpgm->gmBlackBoxY = (top - bottom) >> 6; + lpgm->gmptGlyphOrigin.x = left >> 6; + lpgm->gmptGlyphOrigin.y = top >> 6; + + memcpy(&font->gm[glyph_index].gm, lpgm, sizeof(*lpgm)); + font->gm[glyph_index].init = TRUE; if(format == GGO_METRICS) - return TRUE; + return 1; /* FIXME */ if(ft_face->glyph->format != ft_glyph_format_outline) { FIXME("loaded a bitmap\n"); return GDI_ERROR; } - if(format == GGO_BITMAP) { + switch(format) { + case GGO_BITMAP: width = lpgm->gmBlackBoxX; height = lpgm->gmBlackBoxY; pitch = (width + 31) / 32 * 4; needed = pitch * height; - if(!buf || !buflen) return needed; + if(!buf || !buflen) break; ft_bitmap.width = width; ft_bitmap.rows = height; ft_bitmap.pitch = pitch; ft_bitmap.pixel_mode = ft_pixel_mode_mono; ft_bitmap.buffer = buf; - FT_Outline_Translate(&ft_face->glyph->outline, - - ft_face->glyph->metrics.horiBearingX, - - (ft_face->glyph->metrics.horiBearingY - - ft_face->glyph->metrics.height) ); + if(font->orientation) { + FT_Matrix matrix; + matrix.xx = matrix.yy = FT_Cos(angle); + matrix.xy = -FT_Sin(angle); + matrix.yx = -matrix.xy; + + FT_Outline_Transform(&ft_face->glyph->outline, &matrix); + } + + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + + /* Note: FreeType will only set 'black' bits for us. */ + memset(buf, 0, needed); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + break; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + case WINE_GGO_GRAY16_BITMAP: + { + int mult, row, col; + BYTE *start, *ptr; + + width = lpgm->gmBlackBoxX; + height = lpgm->gmBlackBoxY; + pitch = (width + 3) / 4 * 4; + needed = pitch * height; + + if(!buf || !buflen) break; + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_grays; + ft_bitmap.buffer = buf; + + if(font->orientation) { + FT_Matrix matrix; + matrix.xx = matrix.yy = FT_Cos(angle); + matrix.xy = -FT_Sin(angle); + matrix.yx = -matrix.xy; + FT_Outline_Transform(&ft_face->glyph->outline, &matrix); + } + + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - } else { + + if(format == GGO_GRAY2_BITMAP) + mult = 5; + else if(format == GGO_GRAY4_BITMAP) + mult = 17; + else if(format == GGO_GRAY8_BITMAP) + mult = 65; + else if(format == WINE_GGO_GRAY16_BITMAP) + break; + else { + assert(0); + break; + } + + start = buf; + for(row = 0; row < height; row++) { + ptr = start; + for(col = 0; col < width; col++, ptr++) { + *ptr = (*(unsigned int*)ptr * mult + 128) / 256; + } + start += pitch; + } + break; + } + + case GGO_NATIVE: + { + int contour, point = 0, first_pt; + FT_Outline *outline = &ft_face->glyph->outline; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + DWORD pph_start, cpfx, type; + + if(buflen == 0) buf = NULL; + + for(contour = 0; contour < outline->n_contours; contour++) { + pph_start = needed; + pph = buf + needed; + first_pt = point; + if(buf) { + pph->dwType = TT_POLYGON_TYPE; + FTVectorToPOINTFX(&outline->points[point], &pph->pfxStart); + } + needed += sizeof(*pph); + point++; + while(point <= outline->contours[contour]) { + ppc = buf + needed; + type = (outline->tags[point] == FT_Curve_Tag_On) ? + TT_PRIM_LINE : TT_PRIM_QSPLINE; + cpfx = 0; + do { + if(buf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } while(point <= outline->contours[contour] && + outline->tags[point] == outline->tags[point-1]); + /* At the end of a contour Windows adds the start point */ + if(point > outline->contours[contour]) { + if(buf) + FTVectorToPOINTFX(&outline->points[first_pt], &ppc->apfx[cpfx]); + cpfx++; + } else if(outline->tags[point] == FT_Curve_Tag_On) { + /* add closing pt for bezier */ + if(buf) + FTVectorToPOINTFX(&outline->points[point], &ppc->apfx[cpfx]); + cpfx++; + point++; + } + if(buf) { + ppc->wType = type; + ppc->cpfx = cpfx; + } + needed += sizeof(*ppc) + (cpfx - 1) * sizeof(POINTFX); + } + if(buf) + pph->cb = needed - pph_start; + } + break; + } + default: FIXME("Unsupported format %d\n", format); return GDI_ERROR; } - return TRUE; + return needed; } /************************************************************* @@ -532,6 +1198,8 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) TT_OS2 *pOS2; TT_HoriHeader *pHori; FT_Fixed x_scale, y_scale; + + TRACE("font=%p, ptm=%p\n", font, ptm); x_scale = ft_face->size->metrics.x_scale; y_scale = ft_face->size->metrics.y_scale; @@ -554,12 +1222,19 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) ft_face->ascender, ft_face->descender, ft_face->height, pHori->Ascender, pHori->Descender, pHori->Line_Gap, ft_face->bbox.yMax, ft_face->bbox.yMin); - - ptm->tmAscent = (FT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6; - ptm->tmDescent = (FT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6; + + if(font->yMax) { + ptm->tmAscent = font->yMax; + ptm->tmDescent = -font->yMin; + ptm->tmInternalLeading = (ptm->tmAscent + ptm->tmDescent) - ft_face->size->metrics.y_ppem; + } else { + ptm->tmAscent = (FT_MulFix(pOS2->usWinAscent, y_scale) + 32) >> 6; + ptm->tmDescent = (FT_MulFix(pOS2->usWinDescent, y_scale) + 32) >> 6; + ptm->tmInternalLeading = (FT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent + - ft_face->units_per_EM, y_scale) + 32) >> 6; + } + ptm->tmHeight = ptm->tmAscent + ptm->tmDescent; - ptm->tmInternalLeading = (FT_MulFix(pOS2->usWinAscent + pOS2->usWinDescent - - ft_face->units_per_EM, y_scale) + 32) >> 6; /* MSDN says: el = MAX(0, LineGap - ((WinAscent + WinDescent) - (Ascender - Descender))) @@ -570,7 +1245,7 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) ptm->tmAveCharWidth = (FT_MulFix(pOS2->xAvgCharWidth, x_scale) + 32) >> 6; ptm->tmMaxCharWidth = (FT_MulFix(ft_face->bbox.xMax - ft_face->bbox.xMin, x_scale) + 32) >> 6; - ptm->tmWeight = pOS2->usWeightClass; + ptm->tmWeight = font->fake_bold ? FW_BOLD : pOS2->usWeightClass; ptm->tmOverhang = 0; ptm->tmDigitizedAspectX = 300; ptm->tmDigitizedAspectY = 300; @@ -578,7 +1253,7 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) ptm->tmLastChar = pOS2->usLastCharIndex; ptm->tmDefaultChar = pOS2->usDefaultChar; ptm->tmBreakChar = pOS2->usBreakChar; - ptm->tmItalic = (ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 1 : 0; + ptm->tmItalic = font->fake_italic ? 255 : ((ft_face->style_flags & FT_STYLE_FLAG_ITALIC) ? 255 : 0); ptm->tmUnderlined = 0; /* entry in OS2 table */ ptm->tmStruckOut = 0; /* entry in OS2 table */ @@ -588,8 +1263,9 @@ BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) ptm->tmPitchAndFamily |= TMPF_VECTOR; if(FT_IS_SFNT(ft_face)) ptm->tmPitchAndFamily |= TMPF_TRUETYPE; + ptm->tmPitchAndFamily |= FF_ROMAN; - ptm->tmCharSet = ANSI_CHARSET; + ptm->tmCharSet = font->charset; return TRUE; } /************************************************************* @@ -608,6 +1284,8 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, WCHAR spaceW[] = {' ', '\0'}; char *cp; + TRACE("font=%p\n", font); + needed = sizeof(*potm); lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0) @@ -674,11 +1352,11 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, potm->otmsCharSlopeRun = pHori->caret_Slope_Run; potm->otmItalicAngle = 0; /* POST table */ potm->otmEMSquare = ft_face->units_per_EM; - potm->otmAscent = pOS2->sTypoAscender; - potm->otmDescent = pOS2->sTypoDescender; - potm->otmLineGap = pOS2->sTypoLineGap; - potm->otmsCapEmHeight = pOS2->sCapHeight; - potm->otmsXHeight = pOS2->sxHeight; + potm->otmAscent = (FT_MulFix(pOS2->sTypoAscender, y_scale) + 32) >> 6; + potm->otmDescent = (FT_MulFix(pOS2->sTypoDescender, y_scale) + 32) >> 6; + potm->otmLineGap = (FT_MulFix(pOS2->sTypoLineGap, y_scale) + 32) >> 6; + potm->otmsCapEmHeight = (FT_MulFix(pOS2->sCapHeight, y_scale) + 32) >> 6; + potm->otmsXHeight = (FT_MulFix(pOS2->sxHeight, y_scale) + 32) >> 6; potm->otmrcFontBox.left = ft_face->bbox.xMin; potm->otmrcFontBox.right = ft_face->bbox.xMax; potm->otmrcFontBox.top = ft_face->bbox.yMin; @@ -687,19 +1365,19 @@ UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, potm->otmMacDescent = 0; potm->otmMacLineGap = 0; potm->otmusMinimumPPEM = 0; /* TT Header */ - potm->otmptSubscriptSize.x = pOS2->ySubscriptXSize; - potm->otmptSubscriptSize.y = pOS2->ySubscriptYSize; - potm->otmptSubscriptOffset.x = pOS2->ySubscriptXOffset; - potm->otmptSubscriptOffset.y = pOS2->ySubscriptYOffset; - potm->otmptSuperscriptSize.x = pOS2->ySuperscriptXSize; - potm->otmptSuperscriptSize.y = pOS2->ySuperscriptYSize; - potm->otmptSuperscriptOffset.x = pOS2->ySuperscriptXOffset; - potm->otmptSuperscriptOffset.y = pOS2->ySuperscriptYOffset; - potm->otmsStrikeoutSize = pOS2->yStrikeoutSize; - potm->otmsStrikeoutPosition = pOS2->yStrikeoutPosition; + potm->otmptSubscriptSize.x = (FT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6; + potm->otmptSubscriptSize.y = (FT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6; + potm->otmptSubscriptOffset.x = (FT_MulFix(pOS2->ySubscriptXOffset, x_scale) + 32) >> 6; + potm->otmptSubscriptOffset.y = (FT_MulFix(pOS2->ySubscriptYOffset, y_scale) + 32) >> 6; + potm->otmptSuperscriptSize.x = (FT_MulFix(pOS2->ySuperscriptXSize, x_scale) + 32) >> 6; + potm->otmptSuperscriptSize.y = (FT_MulFix(pOS2->ySuperscriptYSize, y_scale) + 32) >> 6; + potm->otmptSuperscriptOffset.x = (FT_MulFix(pOS2->ySuperscriptXOffset, x_scale) + 32) >> 6; + potm->otmptSuperscriptOffset.y = (FT_MulFix(pOS2->ySuperscriptYOffset, y_scale) + 32) >> 6; + potm->otmsStrikeoutSize = (FT_MulFix(pOS2->yStrikeoutSize, y_scale) + 32) >> 6; + potm->otmsStrikeoutPosition = (FT_MulFix(pOS2->yStrikeoutPosition, y_scale) + 32) >> 6; potm->otmsUnderscoreSize = 0; /* POST Header */ potm->otmsUnderscorePosition = 0; /* POST Header */ - + /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */ cp = (char*)potm + sizeof(*potm); potm->otmpFamilyName = (LPSTR)(cp - (char*)potm); @@ -739,11 +1417,14 @@ BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar, { UINT c; GLYPHMETRICS gm; + FT_UInt glyph_index; + TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer); for(c = firstChar; c <= lastChar; c++) { WineEngGetGlyphOutline(font, c, GGO_METRICS, &gm, 0, NULL, NULL); - buffer[c - firstChar] = gm.gmCellIncX; + glyph_index = get_glyph_index(font, c); + buffer[c - firstChar] = font->gm[glyph_index].adv; } return TRUE; } @@ -758,6 +1439,7 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, UINT idx; GLYPHMETRICS gm; TEXTMETRICW tm; + FT_UInt glyph_index; TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count, size); @@ -769,7 +1451,8 @@ BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, for(idx = 0; idx < count; idx++) { WineEngGetGlyphOutline(font, wstr[idx], GGO_METRICS, &gm, 0, NULL, NULL); - size->cx += gm.gmCellIncX; + glyph_index = get_glyph_index(font, wstr[idx]); + size->cx += font->gm[glyph_index].adv; } TRACE("return %ld,%ld\n", size->cx, size->cy); return TRUE; @@ -788,6 +1471,9 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf, DWORD len; FT_Error err; + TRACE("font=%p, table=%08lx, offset=%08lx, buf=%p, cbData=%lx\n", + font, table, offset, buf, cbData); + if(!FT_IS_SFNT(ft_face)) return GDI_ERROR; @@ -806,7 +1492,7 @@ DWORD WineEngGetFontData(GdiFont font, DWORD table, DWORD offset, LPVOID buf, err = sfnt->load_any(tt_face, table, offset, buf, &len); if(err) { - ERR("Can't find table %08lx\n", table); + TRACE("Can't find table %08lx.\n", table); return GDI_ERROR; } return len; @@ -822,15 +1508,9 @@ GdiFont WineEngCreateFontInstance(HFONT hfont) { return NULL; } -DWORD WineEngAddRefFont(GdiFont font) +BOOL WineEngDestroyFontInstance(HFONT hfont) { - ERR("called but we don't have FreeType\n"); - return 0; -} -DWORD WineEngDecRefFont(GdiFont font) -{ - ERR("called but we don't have FreeType\n"); - return 0; + return FALSE; } DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lparam) diff --git a/include/config.h.in b/include/config.h.in index d52126ed545..5976ad3e804 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -475,6 +475,9 @@ /* Define if FreeType 2 is installed */ #undef HAVE_FREETYPE +/* Define if you have the header file. */ +#undef HAVE_FREETYPE_FTTRIGON_H + /* Define if we can use ppdev.h for parallel port access */ #undef HAVE_PPDEV diff --git a/include/font.h b/include/font.h index deb37cdf4b0..2ed53f538d2 100644 --- a/include/font.h +++ b/include/font.h @@ -73,9 +73,8 @@ extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW); extern LPWSTR FONT_mbtowc(HDC, LPCSTR, INT, INT*, UINT*); -extern DWORD WineEngAddRefFont(GdiFont); extern GdiFont WineEngCreateFontInstance(HFONT); -extern DWORD WineEngDecRefFont(GdiFont); +extern BOOL WineEngDestroyFontInstance(HFONT handle); extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM); extern BOOL WineEngGetCharWidth(GdiFont, UINT, UINT, LPINT); extern DWORD WineEngGetFontData(GdiFont, DWORD, DWORD, LPVOID, DWORD); diff --git a/include/gdi.h b/include/gdi.h index 5daf3d052aa..5812aabed27 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -521,4 +521,6 @@ extern void CLIPPING_UpdateGCRegion( DC * dc ); /* objects/enhmetafile.c */ extern HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ); +#define WINE_GGO_GRAY16_BITMAP 0x7f + #endif /* __WINE_GDI_H */ diff --git a/objects/dc.c b/objects/dc.c index b06de93473e..267bb0115d7 100644 --- a/objects/dc.c +++ b/objects/dc.c @@ -316,7 +316,6 @@ HDC16 WINAPI GetDCState16( HDC16 hdc ) newdc->hClipRgn = 0; if(dc->gdiFont) { - WineEngAddRefFont(dc->gdiFont); newdc->gdiFont = dc->gdiFont; } else newdc->gdiFont = 0; @@ -775,7 +774,6 @@ BOOL WINAPI DeleteDC( HDC hdc ) if (dc->hClipRgn) DeleteObject( dc->hClipRgn ); if (dc->hVisRgn) DeleteObject( dc->hVisRgn ); if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn ); - if (dc->gdiFont) WineEngDecRefFont( dc->gdiFont ); PATH_DestroyGdiPath(&dc->path); GDI_FreeObject( hdc, dc ); diff --git a/objects/font.c b/objects/font.c index ddb0bca8fc2..acad7106ccc 100644 --- a/objects/font.c +++ b/objects/font.c @@ -1648,7 +1648,33 @@ BOOL16 WINAPI GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar, BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar, LPABC abc ) { - return GetCharABCWidthsW( hdc, firstChar, lastChar, abc ); + INT i, wlen, count = (INT)(lastChar - firstChar + 1); + LPSTR str; + LPWSTR wstr; + BOOL ret = TRUE; + + if(count <= 0) return FALSE; + + str = HeapAlloc(GetProcessHeap(), 0, count); + for(i = 0; i < count; i++) + str[i] = (BYTE)(firstChar + i); + + wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL); + + for(i = 0; i < wlen; i++) + { + if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc)) + { + ret = FALSE; + break; + } + abc++; + } + + HeapFree(GetProcessHeap(), 0, str); + HeapFree(GetProcessHeap(), 0, wstr); + + return ret; } @@ -1671,20 +1697,22 @@ BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar, BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, LPABC abc ) { + DC *dc = DC_GetDCPtr(hdc); int i; - LPINT widths = HeapAlloc(GetProcessHeap(),0,(lastChar-firstChar+1)*sizeof(INT)); + GLYPHMETRICS gm; + BOOL ret = FALSE; - FIXME("(%04x,%04x,%04x,%p), returns slightly bogus values.\n", hdc, firstChar, lastChar, abc); - - GetCharWidth32A(hdc,firstChar,lastChar,widths); - - for (i=firstChar;i<=lastChar;i++) { - abc[i-firstChar].abcA = 0; /* left distance */ - abc[i-firstChar].abcB = widths[i-firstChar];/* width */ - abc[i-firstChar].abcC = 0; /* right distance */ + if(dc->gdiFont) { + for (i=firstChar;i<=lastChar;i++) { + GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL); + abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x; + abc[i-firstChar].abcB = gm.gmBlackBoxX; + abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX; + } + ret = TRUE; } - HeapFree(GetProcessHeap(),0,widths); - return TRUE; + GDI_ReleaseObj(hdc); + return ret; } @@ -1708,8 +1736,20 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 *lpmat2 ) { - return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, - lpmat2); + LPWSTR p = NULL; + DWORD ret; + UINT c; + + if(!(fuFormat & GGO_GLYPH_INDEX)) { + p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL); + c = p[0]; + } else + c = uChar; + ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer, + lpmat2); + if(p) + HeapFree(GetProcessHeap(), 0, p); + return ret; } /*********************************************************************** diff --git a/objects/gdiobj.c b/objects/gdiobj.c index 2e35a64a317..4381f20fdc4 100644 --- a/objects/gdiobj.c +++ b/objects/gdiobj.c @@ -449,6 +449,17 @@ void GDI_CheckNotLock(void) } +/*********************************************************************** + * FONT_DeleteObject + * + */ +static BOOL FONT_DeleteObject(HGDIOBJ hfont, FONTOBJ *fontobj) +{ + WineEngDestroyFontInstance( hfont ); + return GDI_FreeObject( hfont, fontobj ); +} + + /*********************************************************************** * DeleteObject (GDI.69) * SysDeleteObject (GDI.605) @@ -495,7 +506,7 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj ) { case PEN_MAGIC: return GDI_FreeObject( obj, header ); case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header ); - case FONT_MAGIC: return GDI_FreeObject( obj, header ); + case FONT_MAGIC: return FONT_DeleteObject( obj, (FONTOBJ*)header ); case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header); case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header); case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header ); @@ -752,19 +763,15 @@ static HGDIOBJ FONT_SelectObject(DC *dc, HGDIOBJ hFont) { HGDIOBJ ret = FALSE; - if(dc->gdiFont) { - WineEngDecRefFont(dc->gdiFont); - dc->gdiFont = 0; + if(dc->hFont != hFont || dc->gdiFont == NULL) { + if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE) + dc->gdiFont = WineEngCreateFontInstance(hFont); } - if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE) - dc->gdiFont = WineEngCreateFontInstance(hFont); - if(dc->funcs->pSelectObject) ret = dc->funcs->pSelectObject(dc, hFont); if(ret && dc->gdiFont) { - WineEngDecRefFont(dc->gdiFont); dc->gdiFont = 0; }