From 814654ef9fe421458d649b67089ebb075148cb73 Mon Sep 17 00:00:00 2001 From: Huw D M Davies Date: Wed, 12 Sep 2001 20:21:06 +0000 Subject: [PATCH] Lay down the infrastructure for gdi font rendering. Partial implementation of GetGylphOutline and GetOutlineTextMetrics for gdi fonts. --- configure | 287 +++++----- configure.in | 3 +- dlls/gdi/Makefile.in | 3 + dlls/gdi/freetype.c | 835 ++++++++++++++++++++++++++++++ dlls/ttydrv/objects.c | 7 +- dlls/wineps/font.c | 5 +- graphics/enhmetafiledrv/objects.c | 9 +- graphics/metafiledrv/objects.c | 7 +- graphics/win16drv/font.c | 10 +- graphics/x11drv/xfont.c | 11 +- include/config.h.in | 3 + include/font.h | 13 +- include/gdi.h | 3 + objects/dc.c | 9 + objects/font.c | 306 +++++++---- objects/gdiobj.c | 49 +- 16 files changed, 1284 insertions(+), 276 deletions(-) create mode 100644 dlls/gdi/freetype.c diff --git a/configure b/configure index 134adb46e3d..e674f56ee0e 100755 --- a/configure +++ b/configure @@ -4582,21 +4582,22 @@ EOF freetype/tttables.h \ freetype/ftnames.h \ freetype/ftsnames.h \ - freetype/ttnameid.h + freetype/ttnameid.h \ + freetype/ftoutln.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4590: checking for $ac_hdr" >&5 +echo "configure:4591: 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:4600: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4601: \"$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* @@ -4630,19 +4631,19 @@ fi echo $ac_n "checking "for parport header/ppdev.h"""... $ac_c" 1>&6 -echo "configure:4634: checking "for parport header/ppdev.h"" >&5 +echo "configure:4635: 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:4646: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4647: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ppdev="yes" else @@ -4665,12 +4666,12 @@ EOF fi echo $ac_n "checking "for GNU style IPX support"""... $ac_c" 1>&6 -echo "configure:4669: checking "for GNU style IPX support"" >&5 +echo "configure:4670: 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 @@ -4678,7 +4679,7 @@ int main() { ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX ; return 0; } EOF -if { (eval echo configure:4682: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4683: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ipx_gnu="yes" else @@ -4703,12 +4704,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:4707: checking "for linux style IPX support"" >&5 +echo "configure:4708: 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 @@ -4717,7 +4718,7 @@ int main() { ((struct sockaddr_ipx *)0)->sipx_family == AF_IPX ; return 0; } EOF -if { (eval echo configure:4721: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_ipx_linux="yes" else @@ -4744,17 +4745,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:4748: checking for $ac_hdr" >&5 +echo "configure:4749: 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:4758: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4759: \"$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* @@ -4782,12 +4783,12 @@ done echo $ac_n "checking "for Open Sound System"""... $ac_c" 1>&6 -echo "configure:4786: checking "for Open Sound System"" >&5 +echo "configure:4787: 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:4813: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_opensoundsystem="yes" else @@ -4831,12 +4832,12 @@ EOF fi echo $ac_n "checking "for Open Sound System/MIDI interface"""... $ac_c" 1>&6 -echo "configure:4835: checking "for Open Sound System/MIDI interface"" >&5 +echo "configure:4836: 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:4862: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_opensoundsystem_midi="yes" else @@ -4883,7 +4884,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:4887: checking "whether mmap64 works defined as mmap"" >&5 +echo "configure:4888: 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 @@ -4891,7 +4892,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:4926: \"$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 @@ -4950,7 +4951,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:4954: checking "for gcc strength-reduce bug"" >&5 +echo "configure:4955: 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 @@ -4958,7 +4959,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:4978: \"$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 @@ -4994,21 +4995,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:4998: checking "for gcc -mpreferred-stack-boundary=2 support"" >&5 +echo "configure:4999: 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:5013: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_gcc_stack_boundary="yes" else @@ -5031,7 +5032,7 @@ fi echo $ac_n "checking "whether .type must sit inside a .def directive"""... $ac_c" 1>&6 -echo "configure:5035: checking "whether .type must sit inside a .def directive"" >&5 +echo "configure:5036: 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 @@ -5044,14 +5045,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:5056: \"$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 @@ -5075,7 +5076,7 @@ fi echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6 -echo "configure:5079: checking "whether external symbols need an underscore prefix"" >&5 +echo "configure:5080: 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 @@ -5087,14 +5088,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:5099: \"$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 @@ -5118,7 +5119,7 @@ fi echo $ac_n "checking "whether assembler accepts .string"""... $ac_c" 1>&6 -echo "configure:5122: checking "whether assembler accepts .string"" >&5 +echo "configure:5123: 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 @@ -5128,14 +5129,14 @@ cat > conftest_asm.s < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5140: \"$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 @@ -5163,21 +5164,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:5167: checking "whether we can build a GNU style ELF dll"" >&5 +echo "configure:5168: 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:5182: \"$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 @@ -5198,21 +5199,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:5202: checking whether we can build a UnixWare (Solaris) dll" >&5 +echo "configure:5203: 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:5217: \"$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 @@ -5267,21 +5268,21 @@ elif test "$LIBEXT" = "dll"; then else DLL_LINK="-L\$(DLLDIR) \$(DLLS:%=-l%) \$(LIBWINE) \$(LIBUNICODE) \$(X_LIBS) \$(XLIB)" echo $ac_n "checking whether the linker supports --[no]-whole-archive (Linux)""... $ac_c" 1>&6 -echo "configure:5271: checking whether the linker supports --[no]-whole-archive (Linux)" >&5 +echo "configure:5272: checking whether the linker supports --[no]-whole-archive (Linux)" >&5 if eval "test \"`echo '$''{'ac_cv_c_whole_archive'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -Wl,--whole-archive -Wl,--no-whole-archive" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5286: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_whole_archive="yes" else @@ -5301,21 +5302,21 @@ echo "$ac_t""$ac_cv_c_whole_archive" 1>&6 DLL_LINK="-Wl,--whole-archive $DLL_LINK -Wl,--no-whole-archive" else echo $ac_n "checking whether the linker supports -z {all,default}extract (Linux)""... $ac_c" 1>&6 -echo "configure:5305: checking whether the linker supports -z {all,default}extract (Linux)" >&5 +echo "configure:5306: checking whether the linker supports -z {all,default}extract (Linux)" >&5 if eval "test \"`echo '$''{'ac_cv_c_allextract'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -Wl,-z,allextract -Wl,-z,defaultextract" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_c_allextract="yes" else @@ -5350,7 +5351,7 @@ fi wine_cv_libc_reentrant=no echo $ac_n "checking for reentrant libc: __errno_location""... $ac_c" 1>&6 -echo "configure:5354: checking for reentrant libc: __errno_location" >&5 +echo "configure:5355: 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 @@ -5358,14 +5359,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:5370: \"$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 @@ -5388,7 +5389,7 @@ fi echo $ac_n "checking for reentrant libc: __error""... $ac_c" 1>&6 -echo "configure:5392: checking for reentrant libc: __error" >&5 +echo "configure:5393: 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 @@ -5396,14 +5397,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:5408: \"$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 @@ -5426,7 +5427,7 @@ fi echo $ac_n "checking for reentrant libc: ___errno""... $ac_c" 1>&6 -echo "configure:5430: checking for reentrant libc: ___errno" >&5 +echo "configure:5431: 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 @@ -5434,14 +5435,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:5446: \"$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 @@ -5464,7 +5465,7 @@ fi echo $ac_n "checking for reentrant libc: __thr_errno""... $ac_c" 1>&6 -echo "configure:5468: checking for reentrant libc: __thr_errno" >&5 +echo "configure:5469: 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 @@ -5472,14 +5473,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:5484: \"$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 @@ -5502,7 +5503,7 @@ fi echo $ac_n "checking for reentrant libc: __errno""... $ac_c" 1>&6 -echo "configure:5506: checking for reentrant libc: __errno" >&5 +echo "configure:5507: 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 @@ -5510,14 +5511,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:5522: \"$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 @@ -5551,7 +5552,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:5555: checking "for reentrant X libraries"" >&5 +echo "configure:5556: 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 @@ -5600,19 +5601,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:5604: checking for working alloca.h" >&5 +echo "configure:5605: 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:5616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5617: \"$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 @@ -5633,12 +5634,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:5637: checking for alloca" >&5 +echo "configure:5638: 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:5671: \"$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 @@ -5698,12 +5699,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:5702: checking whether alloca needs Cray hooks" >&5 +echo "configure:5703: 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:5732: checking for $ac_func" >&5 +echo "configure:5733: 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:5761: \"$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 @@ -5783,7 +5784,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:5787: checking stack direction for C alloca" >&5 +echo "configure:5788: 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 @@ -5791,7 +5792,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:5815: \"$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 @@ -5870,12 +5871,12 @@ for ac_func in \ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5874: checking for $ac_func" >&5 +echo "configure:5875: 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:5903: \"$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 @@ -5981,17 +5982,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:5985: checking for $ac_hdr" >&5 +echo "configure:5986: 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:5995: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5996: \"$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* @@ -6018,12 +6019,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:6022: checking whether stat file-mode macros are broken" >&5 +echo "configure:6023: 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 @@ -6076,12 +6077,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:6080: checking for working const" >&5 +echo "configure:6081: 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:6135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -6151,21 +6152,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:6155: checking for inline" >&5 +echo "configure:6156: 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:6170: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -6191,12 +6192,12 @@ EOF esac echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:6195: checking for ANSI C header files" >&5 +echo "configure:6196: 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 @@ -6204,7 +6205,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6208: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6209: \"$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* @@ -6221,7 +6222,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 @@ -6239,7 +6240,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 @@ -6260,7 +6261,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -6271,7 +6272,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:6275: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -6295,12 +6296,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:6299: checking for size_t" >&5 +echo "configure:6300: 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 @@ -6328,7 +6329,7 @@ EOF fi echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:6332: checking size of long long" >&5 +echo "configure:6333: 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 @@ -6336,7 +6337,7 @@ else ac_cv_sizeof_long_long=0 else cat > conftest.$ac_ext < #include @@ -6348,7 +6349,7 @@ main() exit(0); } EOF -if { (eval echo configure:6352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6353: \"$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 @@ -6369,12 +6370,12 @@ EOF echo $ac_n "checking "whether linux/input.h is for real"""... $ac_c" 1>&6 -echo "configure:6373: checking "whether linux/input.h is for real"" >&5 +echo "configure:6374: 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 < @@ -6387,7 +6388,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6391: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6392: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_input_h=yes else @@ -6411,12 +6412,12 @@ EOF echo $ac_n "checking "whether we can use re-entrant gethostbyname_r Linux style"""... $ac_c" 1>&6 -echo "configure:6415: checking "whether we can use re-entrant gethostbyname_r Linux style"" >&5 +echo "configure:6416: 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 < @@ -6437,7 +6438,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6441: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6442: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_gethostbyname_r_6=yes else @@ -6463,12 +6464,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:6467: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5 +echo "configure:6468: 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 < @@ -6483,7 +6484,7 @@ int main() { /*empty*/ ; return 0; } EOF -if { (eval echo configure:6487: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6488: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_joystick_22_api=yes else @@ -6510,12 +6511,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:6514: checking "whether sys/vfs.h defines statfs"" >&5 +echo "configure:6515: 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 < @@ -6532,7 +6533,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6536: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6537: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_vfs_has_statfs=yes else @@ -6559,12 +6560,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:6563: checking "whether sys/statfs.h defines statfs"" >&5 +echo "configure:6564: 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 < @@ -6579,7 +6580,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6583: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6584: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_statfs_has_statfs=yes else @@ -6606,12 +6607,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:6610: checking "whether sys/mount.h defines statfs"" >&5 +echo "configure:6611: 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 < @@ -6626,7 +6627,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6630: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6631: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_mount_has_statfs=yes else @@ -6652,7 +6653,7 @@ fi echo $ac_n "checking "for statfs.f_bfree"""... $ac_c" 1>&6 -echo "configure:6656: checking "for statfs.f_bfree"" >&5 +echo "configure:6657: 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 @@ -6661,7 +6662,7 @@ else wine_cv_statfs_bfree=no else cat > conftest.$ac_ext < @@ -6688,7 +6689,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6692: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6693: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bfree=yes else @@ -6712,7 +6713,7 @@ EOF fi echo $ac_n "checking "for statfs.f_bavail"""... $ac_c" 1>&6 -echo "configure:6716: checking "for statfs.f_bavail"" >&5 +echo "configure:6717: 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 @@ -6721,7 +6722,7 @@ else wine_cv_statfs_bavail=no else cat > conftest.$ac_ext < @@ -6748,7 +6749,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6752: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6753: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bavail=yes else @@ -6773,12 +6774,12 @@ fi echo $ac_n "checking "for msg_accrights in struct msghdr"""... $ac_c" 1>&6 -echo "configure:6777: checking "for msg_accrights in struct msghdr"" >&5 +echo "configure:6778: 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 @@ -6786,7 +6787,7 @@ int main() { struct msghdr hdr; hdr.msg_accrights=0 ; return 0; } EOF -if { (eval echo configure:6790: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6791: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_msg_accrights="yes" else @@ -6809,12 +6810,12 @@ fi echo $ac_n "checking "for sa_len in struct sockaddr"""... $ac_c" 1>&6 -echo "configure:6813: checking "for sa_len in struct sockaddr"" >&5 +echo "configure:6814: 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 @@ -6823,7 +6824,7 @@ int main() { static struct sockaddr addr; addr.sa_len = 1 ; return 0; } EOF -if { (eval echo configure:6827: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6828: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sockaddr_sa_len="yes" else @@ -6846,12 +6847,12 @@ fi echo $ac_n "checking "for sun_len in struct sockaddr_un"""... $ac_c" 1>&6 -echo "configure:6850: checking "for sun_len in struct sockaddr_un"" >&5 +echo "configure:6851: 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 @@ -6860,7 +6861,7 @@ int main() { static struct sockaddr_un addr; addr.sun_len = 1 ; return 0; } EOF -if { (eval echo configure:6864: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sockaddr_sun_len="yes" else @@ -6883,12 +6884,12 @@ fi echo $ac_n "checking "whether we need to define __i386__"""... $ac_c" 1>&6 -echo "configure:6887: checking "whether we need to define __i386__"" >&5 +echo "configure:6888: 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 +#include + +DEFAULT_DEBUG_CHANNEL(font); + +#ifdef HAVE_FREETYPE + +#ifdef HAVE_FREETYPE_FREETYPE_H +#include +#endif +#ifdef HAVE_FREETYPE_FTGLYPH_H +#include +#endif +#ifdef HAVE_FREETYPE_TTTABLES_H +#include +#endif +#ifdef HAVE_FREETYPE_FTNAMES_H +#include +#endif +#ifdef HAVE_FREETYPE_FTSNAMES_H +#include +#endif +#ifdef HAVE_FREETYPE_TTNAMEID_H +#include +#endif +#ifdef HAVE_FREETYPE_FTOUTLN_H +#include +#endif + +static FT_Library library = 0; + +typedef struct tagFace { + WCHAR *StyleName; + char *file; + BOOL Italic; + BOOL Bold; + struct tagFace *next; +} Face; + +typedef struct tagFamily { + WCHAR *FamilyName; + Face *FirstFace; + struct tagFamily *next; +} Family; + +struct tagGdiFont { + DWORD ref; + FT_Face ft_face; +}; + +static Family *FontList = NULL; + +static BOOL AddFontFileToList(char *file) +{ + FT_Face ft_face; + WCHAR *FamilyW, *StyleW; + DWORD len; + Family *family = FontList; + Family **insert = &FontList; + Face **insertface; + + 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)); + return FALSE; + } + + if(!FT_IS_SFNT(ft_face)) { /* for now we'll skip everything but TT/OT */ + FT_Done_Face(ft_face); + return FALSE; + } + + len = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0); + FamilyW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, FamilyW, len); + + while(family) { + if(!strcmpW(family->FamilyName, FamilyW)) + break; + insert = &family->next; + family = family->next; + } + if(!family) { + family = *insert = HeapAlloc(GetProcessHeap(), 0, sizeof(*family)); + family->FamilyName = FamilyW; + family->FirstFace = NULL; + family->next = NULL; + } else { + HeapFree(GetProcessHeap(), 0, FamilyW); + } + + len = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0); + StyleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, StyleW, len); + + + for(insertface = &family->FirstFace; *insertface; + insertface = &(*insertface)->next) { + if(!strcmpW((*insertface)->StyleName, StyleW)) { + ERR("Already loaded font %s %s\n", debugstr_w(family->FamilyName), + debugstr_w(StyleW)); + HeapFree(GetProcessHeap(), 0, StyleW); + FT_Done_Face(ft_face); + return FALSE; + } + } + *insertface = HeapAlloc(GetProcessHeap(), 0, sizeof(**insertface)); + (*insertface)->StyleName = StyleW; + (*insertface)->file = HeapAlloc(GetProcessHeap(),0,strlen(file)+1); + strcpy((*insertface)->file, 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; + FT_Done_Face(ft_face); + + TRACE("Added font %s %s\n", debugstr_w(family->FamilyName), + debugstr_w(StyleW)); + return TRUE; +} + +static void DumpFontList(void) +{ + Family *family; + Face *face; + + for(family = FontList; family; family = family->next) { + TRACE("Family: %s\n", debugstr_w(family->FamilyName)); + for(face = family->FirstFace; face; face = face->next) { + TRACE("\t%s\n", debugstr_w(face->StyleName)); + } + } + return; +} + +static BOOL ReadFontDir(char *dirname) +{ + DIR *dir; + struct dirent *dent; + char path[MAX_PATH]; + + dir = opendir(dirname); + if(!dir) { + ERR("Can't open directory %s\n", debugstr_a(dirname)); + return FALSE; + } + while((dent = readdir(dir)) != NULL) { + if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + sprintf(path, "%s/%s", dirname, dent->d_name); + AddFontFileToList(path); + } + return TRUE; +} + +/************************************************************* + * WineEngInit + * + * Initialize FreeType library and create a list of available faces + */ +BOOL WineEngInit(void) +{ + HKEY hkey; + DWORD valuelen, datalen, i = 0, type, dlen, vlen; + LPSTR value; + LPVOID data; + + if(FT_Init_FreeType(&library) != 0) { + ERR("Can't init FreeType library\n"); + return FALSE; + } + + 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; + } + + 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); + + 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); + DumpFontList(); + return TRUE; +} + + +static FT_Face OpenFontFile(char *file, 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; + + /* Calc. height of EM square: + * + * For +ve lfHeight we have + * lfHeight = (winAscent + winDescent) * ppem / units_per_em + * Re-arranging gives: + * ppem = units_per_em * lfheight / (winAscent + winDescent) + * + * For -ve lfHeight we have + * |lfHeight| = ppem + * [i.e. |lfHeight| = (winAscent + winDescent - il) * ppem / units_per_em + * with il = winAscent + winDescent - units_per_em] + * + */ + + if(height > 0) + ppem = ft_face->units_per_EM * height / + (pOS2->usWinAscent + pOS2->usWinDescent); + else + ppem = -height; + + FT_Set_Pixel_Sizes(ft_face, 0, ppem); + return ft_face; +} + +/************************************************************* + * WineEngCreateFontInstance + * + */ +GdiFont WineEngCreateFontInstance(HFONT hfont) +{ + GdiFont ret; + Face *face; + Family *family = NULL; + WCHAR FaceName[LF_FACESIZE]; + BOOL bd, it; + 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); + + ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); + ret->ref = 1; + + strcpyW(FaceName, plf->lfFaceName); + + if(FaceName[0] != '\0') { + for(family = FontList; family; family = family->next) { + if(!strcmpiW(family->FamilyName, FaceName)) + break; + } + } + + if(!family) { + family = FontList; + FIXME("just using first face for now\n"); + } + + it = plf->lfItalic ? 1 : 0; + bd = plf->lfWeight > 550 ? 1 : 0; + + for(face = family->FirstFace; face; face = face->next) { + if(!(face->Italic ^ it) && !(face->Bold ^ bd)) + break; + } + if(!face) face = family->FirstFace; + + TRACE("Choosen %s %s\n", debugstr_w(family->FamilyName), + debugstr_w(face->StyleName)); + + ret->ft_face = OpenFontFile(face->file, plf->lfHeight); + + GDI_ReleaseObj(hfont); + TRACE("returning %p\n", ret); + return ret; +} + +/************************************************************* + * WineEngAddRefFont + * + */ +DWORD WineEngAddRefFont(GdiFont font) +{ + return ++font->ref; +} + +/************************************************************* + * WineEngDecRefFont + * + */ +DWORD WineEngDecRefFont(GdiFont font) +{ + DWORD ret = --font->ref; + + if(ret == 0) { + FT_Done_Face(font->ft_face); + HeapFree(GetProcessHeap(), 0, font); + } + return ret; +} + +static void GetEnumStructs(Face *face, LPENUMLOGFONTEXW pelf, + LPNEWTEXTMETRICEXW pntm, LPDWORD ptype) +{ + OUTLINETEXTMETRICW *potm; + UINT size; + GdiFont font = HeapAlloc(GetProcessHeap(),0,sizeof(*font)); + + font->ref = 1; + font->ft_face = OpenFontFile(face->file, 100); + + memset(&pelf->elfLogFont, 0, sizeof(LOGFONTW)); + + size = WineEngGetOutlineTextMetrics(font, 0, NULL); + potm = HeapAlloc(GetProcessHeap(), 0, size); + WineEngGetOutlineTextMetrics(font, size, potm); + +#define TM potm->otmTextMetrics + + pntm->ntmTm.tmHeight = pelf->elfLogFont.lfHeight = TM.tmHeight; + pntm->ntmTm.tmAscent = TM.tmAscent; + 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.tmMaxCharWidth = TM.tmMaxCharWidth; + pntm->ntmTm.tmWeight = pelf->elfLogFont.lfWeight = TM.tmWeight; + pntm->ntmTm.tmOverhang = TM.tmOverhang; + pntm->ntmTm.tmDigitizedAspectX = TM.tmDigitizedAspectX; + pntm->ntmTm.tmDigitizedAspectY = TM.tmDigitizedAspectY; + pntm->ntmTm.tmFirstChar = TM.tmFirstChar; + pntm->ntmTm.tmLastChar = TM.tmLastChar; + pntm->ntmTm.tmDefaultChar = TM.tmDefaultChar; + pntm->ntmTm.tmBreakChar = TM.tmBreakChar; + pntm->ntmTm.tmItalic = pelf->elfLogFont.lfItalic = TM.tmItalic; + pntm->ntmTm.tmUnderlined = pelf->elfLogFont.lfUnderline = TM.tmUnderlined; + pntm->ntmTm.tmStruckOut = pelf->elfLogFont.lfStrikeOut = TM.tmStruckOut; + pntm->ntmTm.tmPitchAndFamily = TM.tmPitchAndFamily; + pelf->elfLogFont.lfPitchAndFamily = (TM.tmPitchAndFamily & 0xf1) + 1; + pntm->ntmTm.tmCharSet = pelf->elfLogFont.lfCharSet = TM.tmCharSet; + + pntm->ntmTm.ntmFlags = TM.tmItalic ? NTM_ITALIC : 0; + if(TM.tmWeight > 550) pntm->ntmTm.ntmFlags |= NTM_BOLD; + if(pntm->ntmTm.ntmFlags == 0) pntm->ntmTm.ntmFlags = NTM_REGULAR; + + pntm->ntmTm.ntmSizeEM = potm->otmEMSquare; + pntm->ntmTm.ntmCellHeight = 0; + pntm->ntmTm.ntmAvgWidth = 0; + + *ptype = TM.tmPitchAndFamily & TMPF_TRUETYPE ? TRUETYPE_FONTTYPE : 0; + if(!(TM.tmPitchAndFamily & TMPF_VECTOR)) + *ptype |= RASTER_FONTTYPE; + +#undef TM + memset(&pntm->ntmFontSig, 0, sizeof(FONTSIGNATURE)); + + strncpyW(pelf->elfLogFont.lfFaceName, + (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFamilyName), + LF_FACESIZE); + strncpyW(pelf->elfFullName, + (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpFullName), + LF_FULLFACESIZE); + strncpyW(pelf->elfStyle, + (WCHAR*)((char*)potm + (ptrdiff_t)potm->otmpStyleName), + LF_FACESIZE); + pelf->elfScript[0] = '\0'; /* FIXME */ + + HeapFree(GetProcessHeap(), 0, potm); + WineEngDecRefFont(font); + return; +} + +/************************************************************* + * WineEngEnumFonts + * + */ +DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, + LPARAM lparam) +{ + Family *family; + Face *face; + ENUMLOGFONTEXW elf; + NEWTEXTMETRICEXW ntm; + DWORD type, ret = 1; + + TRACE("facename = %s\n", debugstr_w(plf->lfFaceName)); + 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; + } + } + } + } 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; + } + } + + return ret; +} + +/************************************************************* + * WineEngGetGlyphOutline + * + * Behaves in exactly the same way as the win32 api GetGlyphOutline + * except that the first parameter is the HWINEENGFONT of the font in + * question rather than an HDC. + * + */ +DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, + LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, + const MAT2* lpmat) +{ + FT_Face ft_face = font->ft_face; + FT_UInt glyph_index; + DWORD width, height, pitch, needed; + FT_Bitmap ft_bitmap; + + TRACE("%p, %04x, %08x, %p, %08lx, %p, %p\n", font, glyph, format, lpgm, + buflen, buf, lpmat); + + if(format & GGO_GLYPH_INDEX) + glyph_index = glyph; + else + glyph_index = FT_Get_Char_Index(ft_face, glyph); + + FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); + + 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; + + if(format == GGO_METRICS) + return TRUE; + + if(ft_face->glyph->format != ft_glyph_format_outline) { + FIXME("loaded a bitmap\n"); + return GDI_ERROR; + } + + if(format == GGO_BITMAP) { + width = lpgm->gmBlackBoxX; + height = lpgm->gmBlackBoxY; + pitch = (width + 31) / 32 * 4; + needed = pitch * height; + + if(!buf || !buflen) return needed; + 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) ); + + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + } else { + FIXME("Unsupported format %d\n", format); + return GDI_ERROR; + } + return TRUE; +} + +/************************************************************* + * WineEngGetTextMetrics + * + */ +BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) +{ + FT_Face ft_face = font->ft_face; + TT_OS2 *pOS2; + TT_HoriHeader *pHori; + FT_Fixed x_scale, y_scale; + + x_scale = ft_face->size->metrics.x_scale; + y_scale = ft_face->size->metrics.y_scale; + + pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); + if(!pOS2) { + FIXME("Can't find OS/2 table - not TT font?\n"); + return 0; + } + + pHori = FT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea); + if(!pHori) { + FIXME("Can't find HHEA table - not TT font?\n"); + return 0; + } + + TRACE("OS/2 winA = %d winD = %d typoA = %d typoD = %d typoLG = %d FT_Face a = %d, d = %d, h = %d: HORZ a = %d, d = %d lg = %d maxY = %ld minY = %ld\n", + pOS2->usWinAscent, pOS2->usWinDescent, + pOS2->sTypoAscender, pOS2->sTypoDescender, pOS2->sTypoLineGap, + 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; + 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))) + */ + ptm->tmExternalLeading = max(0, (FT_MulFix(pHori->Line_Gap - + ((pOS2->usWinAscent + pOS2->usWinDescent) - + (pHori->Ascender - pHori->Descender)), y_scale) + 32) >> 6); + + 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->tmOverhang = 0; + ptm->tmDigitizedAspectX = 300; + ptm->tmDigitizedAspectY = 300; + ptm->tmFirstChar = pOS2->usFirstCharIndex; + 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->tmUnderlined = 0; /* entry in OS2 table */ + ptm->tmStruckOut = 0; /* entry in OS2 table */ + + /* Yes this is correct; braindead api */ + ptm->tmPitchAndFamily = FT_IS_FIXED_WIDTH(ft_face) ? 0 : TMPF_FIXED_PITCH; + if(FT_IS_SCALABLE(ft_face)) + ptm->tmPitchAndFamily |= TMPF_VECTOR; + if(FT_IS_SFNT(ft_face)) + ptm->tmPitchAndFamily |= TMPF_TRUETYPE; + + ptm->tmCharSet = ANSI_CHARSET; + return TRUE; +} +/************************************************************* + * WineEngGetOutlineTextMetrics + * + */ +UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, + OUTLINETEXTMETRICW *potm) +{ + FT_Face ft_face = font->ft_face; + UINT needed, lenfam, lensty, ret; + TT_OS2 *pOS2; + TT_HoriHeader *pHori; + FT_Fixed x_scale, y_scale; + WCHAR *family_nameW, *style_nameW; + WCHAR spaceW[] = {' ', '\0'}; + char *cp; + + needed = sizeof(*potm); + + lenfam = MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, NULL, 0) + * sizeof(WCHAR); + family_nameW = HeapAlloc(GetProcessHeap(), 0, lenfam); + MultiByteToWideChar(CP_ACP, 0, ft_face->family_name, -1, + family_nameW, lenfam); + + lensty = MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, NULL, 0) + * sizeof(WCHAR); + style_nameW = HeapAlloc(GetProcessHeap(), 0, lensty); + MultiByteToWideChar(CP_ACP, 0, ft_face->style_name, -1, + style_nameW, lensty); + + /* These names should be read from the TT name table */ + + /* length of otmpFamilyName */ + needed += lenfam; + + /* length of otmpFaceName */ + if(!strcasecmp(ft_face->style_name, "regular")) { + needed += lenfam; /* just the family name */ + } else { + needed += lenfam + lensty; /* family + " " + style */ + } + + /* length of otmpStyleName */ + needed += lensty; + + /* length of otmpFullName */ + needed += lenfam + lensty; + + if(needed > cbSize) { + ret = needed; + goto end; + } + + x_scale = ft_face->size->metrics.x_scale; + y_scale = ft_face->size->metrics.y_scale; + + pOS2 = FT_Get_Sfnt_Table(ft_face, ft_sfnt_os2); + if(!pOS2) { + FIXME("Can't find OS/2 table - not TT font?\n"); + ret = 0; + goto end; + } + + pHori = FT_Get_Sfnt_Table(ft_face, ft_sfnt_hhea); + if(!pHori) { + FIXME("Can't find HHEA table - not TT font?\n"); + ret = 0; + goto end; + } + + potm->otmSize = needed; + + WineEngGetTextMetrics(font, &potm->otmTextMetrics); + + potm->otmFiller = 0; + memcpy(&potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT); + potm->otmfsSelection = pOS2->fsSelection; + potm->otmfsType = pOS2->fsType; + potm->otmsCharSlopeRise = pHori->caret_Slope_Rise; + 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->otmrcFontBox.left = ft_face->bbox.xMin; + potm->otmrcFontBox.right = ft_face->bbox.xMax; + potm->otmrcFontBox.top = ft_face->bbox.yMin; + potm->otmrcFontBox.bottom = ft_face->bbox.yMax; + potm->otmMacAscent = 0; /* where do these come from ? */ + 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->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); + strcpyW((WCHAR*)cp, family_nameW); + cp += lenfam; + potm->otmpStyleName = (LPSTR)(cp - (char*)potm); + strcpyW((WCHAR*)cp, style_nameW); + cp += lensty; + potm->otmpFaceName = (LPSTR)(cp - (char*)potm); + strcpyW((WCHAR*)cp, family_nameW); + if(strcasecmp(ft_face->style_name, "regular")) { + strcatW((WCHAR*)cp, spaceW); + strcatW((WCHAR*)cp, style_nameW); + cp += lenfam + lensty; + } else + cp += lenfam; + potm->otmpFullName = (LPSTR)(cp - (char*)potm); + strcpyW((WCHAR*)cp, family_nameW); + strcatW((WCHAR*)cp, spaceW); + strcatW((WCHAR*)cp, style_nameW); + ret = needed; + + end: + HeapFree(GetProcessHeap(), 0, style_nameW); + HeapFree(GetProcessHeap(), 0, family_nameW); + + return ret; +} + + +/************************************************************* + * WineEngGetCharWidth + * + */ +BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar, + LPINT buffer) +{ + UINT c; + GLYPHMETRICS gm; + 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; + } + return TRUE; +} + +/************************************************************* + * WineEngGetTextExtentPoint + * + */ +BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, + LPSIZE size) +{ + UINT idx; + GLYPHMETRICS gm; + TEXTMETRICW tm; + + TRACE("%p, %s, %d, %p\n", font, debugstr_wn(wstr, count), count, + size); + + size->cx = 0; + WineEngGetTextMetrics(font, &tm); + size->cy = tm.tmHeight; + + for(idx = 0; idx < count; idx++) { + WineEngGetGlyphOutline(font, wstr[idx], GGO_METRICS, &gm, 0, NULL, + NULL); + size->cx += gm.gmCellIncX; + } + TRACE("return %ld,%ld\n", size->cx, size->cy); + return TRUE; +} + +#else /* HAVE_FREETYPE */ + +BOOL WineEngInit(void) +{ + return FALSE; +} +GdiFont WineEngCreateFontInstance(HFONT hfont) +{ + return NULL; +} +DWORD WineEngAddRefFont(GdiFont font) +{ + 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; +} + +DWORD WineEngEnumFonts(LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lparam) +{ + return 1; +} + +DWORD WineEngGetGlyphOutline(GdiFont font, UINT glyph, UINT format, + LPGLYPHMETRICS lpgm, DWORD buflen, LPVOID buf, + const MAT2* lpmat) +{ + ERR("called but we don't have FreeType\n"); + return GDI_ERROR; +} + +BOOL WineEngGetTextMetrics(GdiFont font, LPTEXTMETRICW ptm) +{ + ERR("called but we don't have FreeType\n"); + return FALSE; +} + +UINT WineEngGetOutlineTextMetrics(GdiFont font, UINT cbSize, + OUTLINETEXTMETRICW *potm) +{ + ERR("called but we don't have FreeType\n"); + return 0; +} + +BOOL WineEngGetCharWidth(GdiFont font, UINT firstChar, UINT lastChar, + LPINT buffer) +{ + ERR("called but we don't have FreeType\n"); + return FALSE; +} + +BOOL WineEngGetTextExtentPoint(GdiFont font, LPCWSTR wstr, INT count, + LPSIZE size) +{ + ERR("called but we don't have FreeType\n"); + return FALSE; +} + +#endif /* HAVE_FREETYPE */ + diff --git a/dlls/ttydrv/objects.c b/dlls/ttydrv/objects.c index 2c14c7706f6..1c27ae6e10f 100644 --- a/dlls/ttydrv/objects.c +++ b/dlls/ttydrv/objects.c @@ -37,14 +37,9 @@ static HBRUSH TTYDRV_DC_BRUSH_SelectObject(DC *dc, HBRUSH hbrush) */ static HFONT TTYDRV_DC_FONT_SelectObject(DC* dc, HFONT hfont) { - HFONT hPreviousFont; - TRACE("(%p, 0x%04x)\n", dc, hfont); - hPreviousFont = dc->hFont; - dc->hFont = hfont; - - return hPreviousFont; + return TRUE; /* Use device font */ } /*********************************************************************** diff --git a/dlls/wineps/font.c b/dlls/wineps/font.c index 994d8d76764..660b6405bfc 100644 --- a/dlls/wineps/font.c +++ b/dlls/wineps/font.c @@ -130,7 +130,6 @@ static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font, HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont ) { LOGFONTW lf; - HFONT16 prevfont = dc->hFont; PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev; BOOL bd = FALSE, it = FALSE; AFMLISTENTRY *afmle; @@ -143,8 +142,6 @@ HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont ) debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic, lf.lfWeight); - dc->hFont = hfont; - if(lf.lfItalic) it = TRUE; if(lf.lfWeight > 550) @@ -258,7 +255,7 @@ HFONT PSDRV_FONT_SelectObject( DC * dc, HFONT hfont ) physDev->font.tm.tmDigitizedAspectX = physDev->logPixelsY; physDev->font.tm.tmDigitizedAspectY = physDev->logPixelsX; - return prevfont; + return TRUE; /* We'll use a device font for now */ } /*********************************************************************** diff --git a/graphics/enhmetafiledrv/objects.c b/graphics/enhmetafiledrv/objects.c index f6f0d602430..0cd11e6e6ab 100644 --- a/graphics/enhmetafiledrv/objects.c +++ b/graphics/enhmetafiledrv/objects.c @@ -178,7 +178,6 @@ static HFONT EMFDRV_FONT_SelectObject( DC * dc, HFONT hFont ) { EMRSELECTOBJECT emr; DWORD index; - HFONT hOldFont; int i; /* If the object is a stock font object, do not need to create it. @@ -195,17 +194,15 @@ static HFONT EMFDRV_FONT_SelectObject( DC * dc, HFONT hFont ) goto found; } } - if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return 0; + if (!(index = EMFDRV_CreateFontIndirect(dc, hFont ))) return GDI_ERROR; found: emr.emr.iType = EMR_SELECTOBJECT; emr.emr.nSize = sizeof(emr); emr.ihObject = index; if(!EMFDRV_WriteRecord( dc, &emr.emr )) - return FALSE; + return GDI_ERROR; - hOldFont = dc->hFont; - dc->hFont = hFont; - return hOldFont; + return FALSE; } diff --git a/graphics/metafiledrv/objects.c b/graphics/metafiledrv/objects.c index 7f77790dc36..cb89f6f9ae3 100644 --- a/graphics/metafiledrv/objects.c +++ b/graphics/metafiledrv/objects.c @@ -178,13 +178,12 @@ static BOOL MFDRV_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont) */ static HFONT MFDRV_FONT_SelectObject( DC * dc, HFONT hfont ) { - HFONT16 prevHandle = dc->hFont; LOGFONT16 lf16; - if (!GetObject16( hfont, sizeof(lf16), &lf16 )) return 0; + if (!GetObject16( hfont, sizeof(lf16), &lf16 )) return GDI_ERROR; if (MFDRV_CreateFontIndirect(dc, hfont, &lf16)) - return prevHandle; - return 0; + return FALSE; + return GDI_ERROR; } /****************************************************************** diff --git a/graphics/win16drv/font.c b/graphics/win16drv/font.c index 0bfe6aa3c91..b6ad49094e3 100644 --- a/graphics/win16drv/font.c +++ b/graphics/win16drv/font.c @@ -75,12 +75,10 @@ BOOL WIN16DRV_GetTextMetrics( DC *dc, TEXTMETRICW *metrics ) HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont) { WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev; - HPEN prevHandle = dc->hFont; int nSize; - if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf )) return 0; - - dc->hFont = hfont; + if (!GetObject16( hfont, sizeof(physDev->lf), &physDev->lf )) + return GDI_ERROR; TRACE("WIN16DRV_FONT_SelectObject %s h=%d\n", debugstr_a(physDev->lf.lfFaceName), physDev->lf.lfHeight); @@ -146,11 +144,11 @@ HFONT WIN16DRV_FONT_SelectObject( DC * dc, HFONT hfont) physDev->tm.tmMaxCharWidth, physDev->tm.tmWeight); - return prevHandle; + return TRUE; /* We'll use a device font */ } /*********************************************************************** - * GetCharWidth32A (GDI32.@) + * WIN16DRV_GetCharWidth */ BOOL WIN16DRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar, LPINT buffer ) diff --git a/graphics/x11drv/xfont.c b/graphics/x11drv/xfont.c index 79bdbf258d2..0e9b702fd42 100644 --- a/graphics/x11drv/xfont.c +++ b/graphics/x11drv/xfont.c @@ -3146,12 +3146,14 @@ LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont ) */ HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont ) { - HFONT hPrevFont = 0; LOGFONTW logfont; LOGFONT16 lf; X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev; - if (!GetObjectW( hfont, sizeof(logfont), &logfont )) return 0; + if (!GetObjectW( hfont, sizeof(logfont), &logfont )) return GDI_ERROR; + + /* If we want to use a gdi font, we should check for XRender extension + and return FALSE here */ EnterCriticalSection( &crtsc_fonts_X11 ); @@ -3215,12 +3217,9 @@ HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont ) logfont.lfCharSet = charsetMatched; } - hPrevFont = dc->hFont; - dc->hFont = hfont; - LeaveCriticalSection( &crtsc_fonts_X11 ); - return hPrevFont; + return TRUE; /* Use a device font */ } diff --git a/include/config.h.in b/include/config.h.in index dc7b3094000..bc525ddbd89 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -229,6 +229,9 @@ /* Define if you have the header file. */ #undef HAVE_FREETYPE_FTNAMES_H +/* Define if you have the header file. */ +#undef HAVE_FREETYPE_FTOUTLN_H + /* Define if you have the header file. */ #undef HAVE_FREETYPE_FTSNAMES_H diff --git a/include/font.h b/include/font.h index 184db4083c3..c3ec1f06934 100644 --- a/include/font.h +++ b/include/font.h @@ -70,7 +70,18 @@ extern void FONT_TextMetric16ToW(const TEXTMETRIC16 *ptm16, LPTEXTMETRICW ptm32 extern void FONT_TextMetricAToW(const TEXTMETRICA *ptm32A, LPTEXTMETRICW ptm32W ); extern void FONT_NewTextMetricEx16ToW(const NEWTEXTMETRICEX16*, LPNEWTEXTMETRICEXW); extern void FONT_EnumLogFontEx16ToW(const ENUMLOGFONTEX16*, LPENUMLOGFONTEXW); -extern BOOL ENGINE_InitFonts(void); +extern DWORD WineEngAddRefFont(GdiFont); +extern GdiFont WineEngCreateFontInstance(HFONT); +extern DWORD WineEngDecRefFont(GdiFont); +extern DWORD WineEngEnumFonts(LPLOGFONTW, DEVICEFONTENUMPROC, LPARAM); +extern BOOL WineEngGetCharWidth(GdiFont, UINT, UINT, LPINT); +extern DWORD WineEngGetGlyphOutline(GdiFont, UINT glyph, UINT format, + LPGLYPHMETRICS, DWORD buflen, LPVOID buf, + const MAT2*); +extern UINT WineEngGetOutlineTextMetrics(GdiFont, UINT, LPOUTLINETEXTMETRICW); +extern BOOL WineEngGetTextExtentPoint(GdiFont, LPCWSTR, INT, LPSIZE); +extern BOOL WineEngGetTextMetrics(GdiFont, LPTEXTMETRICW); +extern BOOL WineEngInit(void); #endif /* __WINE_FONT_H */ diff --git a/include/gdi.h b/include/gdi.h index 5af26646979..feff4adfbc6 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -50,6 +50,8 @@ typedef struct tagGDIOBJHDR typedef BOOL16 CALLBACK (*DCHOOKPROC)(HDC16,WORD,DWORD,LPARAM); +typedef struct tagGdiFont *GdiFont; + typedef struct tagDC { GDIOBJHDR header; @@ -81,6 +83,7 @@ typedef struct tagDC HANDLE16 hDevice; HPALETTE16 hPalette; + GdiFont gdiFont; GdiPath path; WORD ROPmode; diff --git a/objects/dc.c b/objects/dc.c index 675c9dbef3f..be38bf043e1 100644 --- a/objects/dc.c +++ b/objects/dc.c @@ -57,6 +57,7 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs ) dc->hBitmap = 0; dc->hDevice = 0; dc->hPalette = GetStockObject( DEFAULT_PALETTE ); + dc->gdiFont = 0; dc->ROPmode = R2_COPYPEN; dc->polyFillMode = ALTERNATE; dc->stretchBltMode = BLACKONWHITE; @@ -311,6 +312,13 @@ HDC16 WINAPI GetDCState16( HDC16 hdc ) } else newdc->hClipRgn = 0; + + if(dc->gdiFont) { + WineEngAddRefFont(dc->gdiFont); + newdc->gdiFont = dc->gdiFont; + } else + newdc->gdiFont = 0; + GDI_ReleaseObj( handle ); GDI_ReleaseObj( hdc ); return handle; @@ -767,6 +775,7 @@ BOOL WINAPI DeleteDC( HDC hdc ) if (dc->hGCClipRgn) DeleteObject( dc->hGCClipRgn ); if (dc->pAbortProc) THUNK_Free( (FARPROC)dc->pAbortProc ); if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk ); + 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 b369eef9fa4..2fe07457d94 100644 --- a/objects/font.c +++ b/objects/font.c @@ -7,6 +7,7 @@ #include #include +#include #include "winerror.h" #include "winnls.h" #include "font.h" @@ -724,25 +725,28 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, LPARAM lParam, DWORD dwUnicode) { BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM); - INT ret = 0; + INT ret = 1; DC *dc = DC_GetDCPtr( hDC ); + fontEnum32 fe32; + BOOL enum_gdi_fonts; if (!dc) return 0; + + fe32.lpLogFontParam = plf; + fe32.lpEnumFunc = efproc; + fe32.lpData = lParam; + fe32.dwFlags = dwUnicode; + enum_func = dc->funcs->pEnumDeviceFonts; GDI_ReleaseObj( hDC ); + enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE; - if (enum_func) - { - fontEnum32 fe32; - - fe32.lpLogFontParam = plf; - fe32.lpEnumFunc = efproc; - fe32.lpData = lParam; - - fe32.dwFlags = dwUnicode; - + if (!enum_func && !enum_gdi_fonts) return 0; + + if (enum_gdi_fonts) + ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 ); + if (ret && enum_func) ret = enum_func( hDC, plf, FONT_EnumInstance, (LPARAM)&fe32 ); - } return ret; } @@ -1029,25 +1033,15 @@ BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count, { BOOL ret = FALSE; UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */ - DC * dc = DC_GetDCPtr( hdc ); + UINT wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0); + LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) ); - if (!dc) return FALSE; - - if (dc->funcs->pGetTextExtentPoint) - { - /* str may not be 0 terminated so we can't use HEAP_strdupWtoA. - * So we use MultiByteToWideChar. - */ - UINT wlen = MultiByteToWideChar(codepage,0,str,count,NULL,0); - LPWSTR p = HeapAlloc( GetProcessHeap(), 0, wlen * sizeof(WCHAR) ); - if (p) - { - wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen); - ret = dc->funcs->pGetTextExtentPoint( dc, p, wlen, size ); - HeapFree( GetProcessHeap(), 0, p ); - } + if (p) { + wlen = MultiByteToWideChar(codepage,0,str,count,p,wlen); + ret = GetTextExtentPoint32W( hdc, p, wlen, size ); + HeapFree( GetProcessHeap(), 0, p ); } - GDI_ReleaseObj( hdc ); + TRACE("(%08x %s %d %p): returning %ld x %ld\n", hdc, debugstr_an (str, count), count, size, size->cx, size->cy ); return ret; @@ -1071,12 +1065,15 @@ BOOL WINAPI GetTextExtentPoint32W( { BOOL ret = FALSE; DC * dc = DC_GetDCPtr( hdc ); - if (dc) - { - if(dc->funcs->pGetTextExtentPoint) - ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size ); - GDI_ReleaseObj( hdc ); - } + if (!dc) return FALSE; + + if(dc->gdiFont) + ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size); + else if(dc->funcs->pGetTextExtentPoint) + ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size ); + + GDI_ReleaseObj( hdc ); + TRACE("(%08x %s %d %p): returning %ld x %ld\n", hdc, debugstr_wn (str, count), count, size, size->cx, size->cy ); return ret; @@ -1160,15 +1157,11 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, int index, nFit, extent; SIZE tSize; BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); - if (!dc) return FALSE; - - if (!dc->funcs->pGetTextExtentPoint) goto done; size->cx = size->cy = nFit = extent = 0; for(index = 0; index < count; index++) { - if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) goto done; + if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done; /* GetTextExtentPoint includes intercharacter spacing. */ /* FIXME - justification needs doing yet. Remember that the base * data will not be in logical coordinates. @@ -1191,7 +1184,6 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, hdc,debugstr_wn(str,count),maxExt,nFit, size->cx,size->cy); done: - GDI_ReleaseObj( hdc ); return ret; } @@ -1229,7 +1221,12 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics ) DC * dc = DC_GetDCPtr( hdc ); if (!dc) return FALSE; - if (dc->funcs->pGetTextMetrics && dc->funcs->pGetTextMetrics( dc, metrics )) + if (dc->gdiFont) + ret = WineEngGetTextMetrics(dc->gdiFont, metrics); + else if (dc->funcs->pGetTextMetrics) + ret = dc->funcs->pGetTextMetrics( dc, metrics ); + + if (ret) { /* device layer returns values in device units * therefore we have to convert them to logical */ @@ -1311,63 +1308,131 @@ UINT WINAPI GetOutlineTextMetricsA( UINT cbData, /* [in] Size of metric data array */ LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */ { + char buf[512], *ptr; + UINT ret, needed; + OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf; + INT left, len; + + if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) { + if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0) + return 0; + lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret); + GetOutlineTextMetricsW(hdc, ret, lpOTMW); + } + + needed = sizeof(OUTLINETEXTMETRICA); + if(lpOTMW->otmpFamilyName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpFaceName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpStyleName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1, + NULL, 0, NULL, NULL); + if(lpOTMW->otmpFullName) + needed += WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1, + NULL, 0, NULL, NULL); + + if(!lpOTM) { + ret = needed; + goto end; + } + + if(needed > cbData) { + ret = 0; + goto end; + } - UINT rtn = FALSE; - LPTEXTMETRICA lptxtMetr; - - - - if (lpOTM == 0) - { - - lpOTM = (LPOUTLINETEXTMETRICA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OUTLINETEXTMETRICA)); - rtn = sizeof(OUTLINETEXTMETRICA); - cbData = rtn; - } else - { - cbData = sizeof(*lpOTM); - rtn = cbData; - }; - - lpOTM->otmSize = cbData; - - lptxtMetr =HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TEXTMETRICA)); - - if (!GetTextMetricsA(hdc,lptxtMetr)) - { - return 0; - } else - { - memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA)); - }; - - HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr); - + lpOTM->otmSize = needed; + FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics ); lpOTM->otmFiller = 0; + lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber; + lpOTM->otmfsSelection = lpOTMW->otmfsSelection; + lpOTM->otmfsType = lpOTMW->otmfsType; + lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise; + lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun; + lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle; + lpOTM->otmEMSquare = lpOTMW->otmEMSquare; + lpOTM->otmAscent = lpOTMW->otmAscent; + lpOTM->otmDescent = lpOTMW->otmDescent; + lpOTM->otmLineGap = lpOTMW->otmLineGap; + lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight; + lpOTM->otmsXHeight = lpOTMW->otmsXHeight; + lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox; + lpOTM->otmMacAscent = lpOTMW->otmMacAscent; + lpOTM->otmMacDescent = lpOTMW->otmMacDescent; + lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap; + lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM; + lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize; + lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset; + lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize; + lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset; + lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize; + lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition; + lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize; + lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition; - lpOTM->otmPanoseNumber.bFamilyType = 0; - lpOTM->otmPanoseNumber.bSerifStyle = 0; - lpOTM->otmPanoseNumber.bWeight = 0; - lpOTM->otmPanoseNumber.bProportion = 0; - lpOTM->otmPanoseNumber.bContrast = 0; - lpOTM->otmPanoseNumber.bStrokeVariation = 0; - lpOTM->otmPanoseNumber.bArmStyle = 0; - lpOTM->otmPanoseNumber.bLetterform = 0; - lpOTM->otmPanoseNumber.bMidline = 0; - lpOTM->otmPanoseNumber.bXHeight = 0; - lpOTM->otmfsSelection = 0; - lpOTM->otmfsType = 0; + ptr = (char*)(lpOTM + 1); + left = needed - sizeof(*lpOTM); - /* - Further fill of the structure not implemented, - Needs real values for the structure members - */ + if(lpOTMW->otmpFamilyName) { + lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM); + len = WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1, + ptr, left, NULL, NULL); + left -= len; + ptr += len; + } else + lpOTM->otmpFamilyName = 0; + + if(lpOTMW->otmpFaceName) { + lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM); + len = WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1, + ptr, left, NULL, NULL); + left -= len; + ptr += len; + } else + lpOTM->otmpFaceName = 0; + + if(lpOTMW->otmpStyleName) { + lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM); + len = WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1, + ptr, left, NULL, NULL); + left -= len; + ptr += len; + } else + lpOTM->otmpStyleName = 0; + + if(lpOTMW->otmpFullName) { + lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM); + len = WideCharToMultiByte(CP_ACP, 0, + (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1, + ptr, left, NULL, NULL); + left -= len; + } else + lpOTM->otmpFullName = 0; - return rtn; + assert(left == 0); + + ret = needed; + +end: + if(lpOTMW != (OUTLINETEXTMETRICW *)buf) + HeapFree(GetProcessHeap(), 0, lpOTMW); + + return ret; } + /*********************************************************************** * GetOutlineTextMetricsW [GDI32.@] */ @@ -1376,10 +1441,38 @@ UINT WINAPI GetOutlineTextMetricsW( UINT cbData, /* [in] Size of metric data array */ LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */ { - FIXME("(%d,%d,%p): stub\n", hdc, cbData, lpOTM); - return 0; + DC *dc = DC_GetDCPtr( hdc ); + UINT ret; + + TRACE("(%d,%d,%p)\n", hdc, cbData, lpOTM); + if(!dc) return 0; + + if(dc->gdiFont) + ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM); + + else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here + but really this should just be a return 0. */ + + ret = sizeof(*lpOTM); + if (lpOTM) { + if(cbData < ret) + ret = 0; + else { + memset(lpOTM, 0, ret); + lpOTM->otmSize = sizeof(*lpOTM); + GetTextMetricsW(hdc, &lpOTM->otmTextMetrics); + /* + Further fill of the structure not implemented, + Needs real values for the structure members + */ + } + } + } + GDI_ReleaseObj(hdc); + return ret; } + /*********************************************************************** * GetCharWidth (GDI.350) */ @@ -1428,7 +1521,12 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar, DC * dc = DC_GetDCPtr( hdc ); if (!dc) return FALSE; - if (dc->funcs->pGetCharWidth && dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer)) + if (dc->gdiFont) + ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer ); + else if (dc->funcs->pGetCharWidth) + ret = dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer); + + if (ret) { /* convert device units to logical */ @@ -1589,9 +1687,8 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 *lpmat2 ) { - FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n", - hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 ); - return (DWORD)-1; /* failure */ + return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, + lpmat2); } /*********************************************************************** @@ -1601,9 +1698,22 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 *lpmat2 ) { - FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n", + DC *dc = DC_GetDCPtr(hdc); + DWORD ret; + + TRACE("(%04x, '%c', %04x, %p, %ld, %p, %p)\n", hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 ); - return (DWORD)-1; /* failure */ + + if(!dc) return GDI_ERROR; + + if(dc->gdiFont) + ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm, + cbBuffer, lpBuffer, lpmat2); + else + ret = GDI_ERROR; + + GDI_ReleaseObj(hdc); + return ret; } /*********************************************************************** diff --git a/objects/gdiobj.c b/objects/gdiobj.c index 441871c2230..0947f55c0d9 100644 --- a/objects/gdiobj.c +++ b/objects/gdiobj.c @@ -244,6 +244,9 @@ BOOL GDI_Init(void) } if (hkey) RegCloseKey( hkey ); + + WineEngInit(); + return TRUE; } @@ -732,7 +735,46 @@ HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type) } return ret; } +/*********************************************************************** + * FONT_SelectObject + * + * If the driver supports vector fonts we create a gdi font first and + * then call the driver to give it a chance to supply its own device + * font. If the driver wants to do this it returns TRUE and we can + * delete the gdi font, if the driver wants to use the gdi font it + * should return FALSE, to signal an error return GDI_ERROR. For + * drivers that don't support vector fonts they must supply their own + * font. + */ +static HGDIOBJ FONT_SelectObject(DC *dc, HGDIOBJ hFont) +{ + HGDIOBJ ret = FALSE; + if(dc->gdiFont) { + WineEngDecRefFont(dc->gdiFont); + dc->gdiFont = 0; + } + + 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; + } + + if(ret == GDI_ERROR) + ret = FALSE; /* SelectObject returns FALSE on error */ + else { + ret = dc->hFont; + dc->hFont = hFont; + } + + return ret; +} /*********************************************************************** * SelectObject (GDI.45) @@ -752,7 +794,12 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle ) DC * dc = DC_GetDCUpdate( hdc ); if (!dc) return 0; TRACE("hdc=%04x %04x\n", hdc, handle ); - if (dc->funcs->pSelectObject) + + /* Fonts get a rather different treatment so we'll handle them + separately */ + if(GetObjectType(handle) == OBJ_FONT) + ret = FONT_SelectObject(dc, handle); + else if (dc->funcs->pSelectObject) ret = dc->funcs->pSelectObject( dc, handle ); GDI_ReleaseObj( hdc );