diff options
Diffstat (limited to 'Build/source/libs/libttf')
129 files changed, 56182 insertions, 0 deletions
diff --git a/Build/source/libs/libttf/arch/amigaos/Makefile.gcc b/Build/source/libs/libttf/arch/amigaos/Makefile.gcc new file mode 100644 index 00000000000..ef023723791 --- /dev/null +++ b/Build/source/libs/libttf/arch/amigaos/Makefile.gcc @@ -0,0 +1,69 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for amiga using ADE Enviroment. +# +# You will need GNU make. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/amigaos/Makefile.gcc + +ARCH = arch/amigaos +FT_MAKEFILE = $(ARCH)/Makefile.gcc + +AR = ar +RM = rm + +CC = gcc + +CFLAGS = -Wall -pedantic -ansi -O2 -g -noixemul -I$(ARCH) -I. -Iextend + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ + extend/ftxopen.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttextend.c ttfile.c ttgload.c ttinterp.c ttload.c \ + ttmemory.c ttmutex.c ttobjs.c ttraster.c +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M libttf.a + + +$(OBJ_S): $(SRC_S) $(SRC_M) + + +libttf.a: $($(LIB_FILES)) + $(AR) src $@ $^ + +clean: + $(RM) $($(LIB_FILES)) + +distclean: clean + $(RM) dep.end libttf.a + +depend: $(SRC_S) $(SRC_M) $(SRC_X) + $(CC) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile.gcc diff --git a/Build/source/libs/libttf/arch/amigaos/freetype.c b/Build/source/libs/libttf/arch/amigaos/freetype.c new file mode 100644 index 00000000000..723c8f463ce --- /dev/null +++ b/Build/source/libs/libttf/arch/amigaos/freetype.c @@ -0,0 +1,25 @@ +/* This file is part of the FreeType project */ + +/* Single object library component for AmigaOS */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttfile.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttmemory.c" +#include "ttmutex.c" +#include "ttobjs.c" +#include "ttraster.c" + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/amigaos/ft_conf.h b/Build/source/libs/libttf/arch/amigaos/ft_conf.h new file mode 100644 index 00000000000..6aa4b3f73ea --- /dev/null +++ b/Build/source/libs/libttf/arch/amigaos/ft_conf.h @@ -0,0 +1,220 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for AmigaOS using ADE enviroment */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ + +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ + +/* #undef HAVE_MMAP */ + +/* Define if you have the <stdlib.h> header file. */ + +#define HAVE_STDLIB_H + +/* Define if the X Window System is missing or not being used. */ + +#define X_DISPLAY_MISSING + +/* The number of bytes in a int. */ + +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ + +#define SIZEOF_LONG 4 + +/* Define if you have the getpagesize function. */ + +#define HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ + +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ + +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ + +#define HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ + +#define HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ + +#define HAVE_UNISTD_H + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/ansi/freetype.c b/Build/source/libs/libttf/arch/ansi/freetype.c new file mode 100644 index 00000000000..820687a1533 --- /dev/null +++ b/Build/source/libs/libttf/arch/ansi/freetype.c @@ -0,0 +1,32 @@ +/* This file is part of the FreeType project */ + +/* Single file library component for the ANSI target */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#include "ttfile.c" +#include "ttmemory.c" +#include "ttmutex.c" + +/* the extensions are compiled separately, but we need to */ +/* include the file ttextend.c if we want to support them */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + +/* END */ diff --git a/Build/source/libs/libttf/arch/ansi/ft_conf.h b/Build/source/libs/libttf/arch/ansi/ft_conf.h new file mode 100644 index 00000000000..352e6465cbf --- /dev/null +++ b/Build/source/libs/libttf/arch/ansi/ft_conf.h @@ -0,0 +1,227 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for the ANSI Build */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. Unix-specific */ +#undef HAVE_FCNTL_H + +/* command.com can't pipe stderr into a file; any message would be */ +/* written into the graphics screen. */ +#define HAVE_PRINT_FUNCTION 1 + +#define Print( format, ap ) vfprintf( stdout, (format), (ap) ) + + +/* The number of bytes in a int. We use the ANSI header file limits.h */ +/* for determining it since there is no easy way to guess. */ +/* */ +#include <limits.h> +#if UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#else +#error "Unsupported number of bytes in `int' type!" +#endif + +/* We now try to guess the size of longs in the same way */ +/* */ +#if ULONG_MAX == 0xFFFFFFFF +#define SIZEOF_LONG 4 +#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#define TT_CONFIG_OPTION_STATIC_RASTER + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/debugger/Makefile b/Build/source/libs/libttf/arch/debugger/Makefile new file mode 100644 index 00000000000..6da004b8526 --- /dev/null +++ b/Build/source/libs/libttf/arch/debugger/Makefile @@ -0,0 +1,96 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for emx-gcc under OS/2 or under +# Unix with extra debugging capabilities. +# +# You will need GNU make. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/debugger/Makefile + +ARCH = arch/debugger +FT_MAKEFILE = $(ARCH)/Makefile + +CC = gcc + +#CFLAGS = -W -Wall -O0 -g -ansi -pedantic -I$(ARCH) -I. -Iextend + +CFLAGS = -Wall -O0 -g -ansi -I$(ARCH) -I. -Iextend + +#CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend + +# Detect OS/2 to add the flag -DOS2 when compiling ttinterp.c +# +ifdef OS2_SHELL +OS := OS2 +RM := del +else +OS := UNIX # Unix build otherwise +RM := rm -f +endif + +TTFILE = ./ttfile.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxopen.c \ + extend/ftxgdef.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + +# We place the library file in the ARCH directory, so that it doesn't +# interfere with the normal build. +# +LIBTTF_A = $(ARCH)/libttf.a + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< -D$(OS) + +.PHONY: all debug clean distclean depend + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S $(LIBTTF_A) + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M $(LIBTTF_A) + +$(OBJ_S): $(SRC_S) $(SRC_M) + +$(LIBTTF_A): $($(LIB_FILES)) + -$(RM) $@ + ar src $@ $^ + +clean: +ifdef OS2_SHELL + -$(RM) $(subst /,\,$(LIBTTF_A)) + -$(RM) $(subst /,\,$(OBJS_S)) +else + -$(RM) $(LIBTTF_A) + -$(RM) $(OBJS_S) +endif + +distclean: clean + -$(RM) dep.end + +depend: $(SRC_S) $(SRC_M) $(SRC_X) + $(CC) $(CFLAGS) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile diff --git a/Build/source/libs/libttf/arch/debugger/freetype.c b/Build/source/libs/libttf/arch/debugger/freetype.c new file mode 100644 index 00000000000..b431cdfadc5 --- /dev/null +++ b/Build/source/libs/libttf/arch/debugger/freetype.c @@ -0,0 +1,32 @@ +/* This file is part of the FreeType project */ + +/* Single file library component for the debugging target */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#include "ttfile.c" +#include "ttmemory.c" +#include "ttmutex.c" + +/* the extensions are compiled separately, but we need to */ +/* include the file ttextend.c if we want to support them */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + +/* END */ diff --git a/Build/source/libs/libttf/arch/debugger/ft_conf.h b/Build/source/libs/libttf/arch/debugger/ft_conf.h new file mode 100644 index 00000000000..061b3781f5d --- /dev/null +++ b/Build/source/libs/libttf/arch/debugger/ft_conf.h @@ -0,0 +1,236 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for a debugging build */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. Unix-specific */ +#undef HAVE_FCNTL_H + +/* command.com can't pipe stderr into a file; any message would be */ +/* written into the graphics screen. */ +#define HAVE_PRINT_FUNCTION 1 + +#define Print( format, ap ) vfprintf( stdout, (format), (ap) ) + + +/* The number of bytes in a int. We use the ANSI header file limits.h */ +/* for determining it since there is no easy way to guess. */ +/* */ +#include <limits.h> +#if UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#else +#error "Unsupported number of bytes in `int' type!" +#endif + +/* We now try to guess the size of longs in the same way */ +/* */ +#if ULONG_MAX == 0xFFFFFFFF +#define SIZEOF_LONG 4 +#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ +/* */ +/* For debugging, we use a jump table; this allows some interesting */ +/* things during development. */ + +#undef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a `static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine. */ +/* */ +/* We use a static interpreter in the debugger; this helps in setting */ +/* data breakpoints to fixed memory addresses. */ + +#define TT_CONFIG_OPTION_STATIC_INTERPRETER + +/* an extra for the debugger */ +#define DEBUG_INTERPRETER + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ + +#define TT_CONFIG_OPTION_STATIC_RASTER + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode. */ +/* Set to DEBUG_LEVEL_TRACE for the debugger. */ +#define DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/mac/README b/Build/source/libs/libttf/arch/mac/README new file mode 100644 index 00000000000..80334869bdd --- /dev/null +++ b/Build/source/libs/libttf/arch/mac/README @@ -0,0 +1,47 @@ + +This is the readme of the freetype.hqx archive in the contrib/mac +subdirectory. Please note that the FreeType team does *not* support the +Macintosh platform due to lack of knowledge. All questions regarding the +code should be sent to both David Williss and the freetype-devel list. + + +---------------------------------------------------------------------------- + + +These are CodeWarrior projects for building the FreeType library on a Macintosh +I've only provided PPC projects here, but building for 68K shouldn't be hard. +There are two directories here (OK, "folders"). One contains a project for +building freetype.ppc.lib and the other is for freetype.ppc.dll. (I havn't +actually tested the DLL yet.) + +The Macintosh stores TrueType fonts in a "Fonts" folder under the "System" +folder. There is a standard MacOS API for finding this folder, so I use it. +However, the fonts aren't normal flat files. They have all the data in +resources in the resource fork. Each font is an 'sfnt' resource, and each +file can have more than one 'sfnt' resource. + +To get at them, I made a copy of ttmmap.c from the Unix implementation and +modified it to load/release the resource and lock/unlock the handle as needed. +This only required a change to the open and close functions. After that, it +works just as if it was using Unix memory mapping. + +One thing however. Because of the bizarre scheme for storing the fonts, I +made up a way of specifying the font filename. + + fonts:/fontfile/fontname + +Where fonts:/ is a literal string that means "the fonts folder", fontfile is +the name of the actual file and fontname is the name of the 'sfnt' resource. +Currently, this is the only thing it understands. It might be nice if some +day (2.0 maybe?) ttfile.c and ttmmap.c wern't mutialy exclusive and it could +decide which method to use based on the filename or something. + +Another thing that I had to change to make this work. It seems that Macintosh +TrueType fonts have no OS/2 table, so ttload.c needs to be modified to make +that nonfatal, at least on a Macintosh. + +--- + +David Williss +MicroImages, Inc. +dwilliss@microimages.com diff --git a/Build/source/libs/libttf/arch/mac/freetype.c b/Build/source/libs/libttf/arch/mac/freetype.c new file mode 100644 index 00000000000..5db4438d373 --- /dev/null +++ b/Build/source/libs/libttf/arch/mac/freetype.c @@ -0,0 +1,48 @@ +/* This file is *not* part of the FreeType project, because the team */ +/* lacks the necessary expertise to support it. */ + +/* freetype.c for MacOS */ +/* single object library component for MacOS */ + +/* Written by Dave Willis <dwilliss@microimages.com> on 1998-07-30. */ +/* Modified by Antoine Leca for the 1.3 release, but untested. */ + +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* Note, you should define the EXPORT_DEF and EXPORT_FUNC macros here */ +/* if you want to build a DLL. If undefined, the macros are defined */ +/* as "export" and "" (i.e. nothing), which is the normal behaviour. */ +/* The macros are placed before each high-level API function */ +/* declaration. You can then use them to take any compiler-specific */ +/* pragma for DLL-exported symbols. See 'ttconfig.h' for details. */ + + +/* first include common core components */ + +#define MAC_MAIN_OBJECT +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#include "ttmmap.c" /* Was "ttfile.c" */ +#include "ttmemory.c" +#include "ttmutex.c" + +/* finally, add some extensions */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/mac/ft_conf.h b/Build/source/libs/libttf/arch/mac/ft_conf.h new file mode 100644 index 00000000000..4043ae5250e --- /dev/null +++ b/Build/source/libs/libttf/arch/mac/ft_conf.h @@ -0,0 +1,211 @@ +/* This file is *not* part of the FreeType project, because the team */ +/* lacks the necessary expertise to support it. */ + +/* ft_conf.h for MacOS */ + +/* Written by Dave Willis <dwilliss@microimages.com> on 1998-07-30. */ +/* Modified by Antoine Leca for the 1.3 release, but untested. */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the 'const' keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/mac/ttmmap.c b/Build/source/libs/libttf/arch/mac/ttmmap.c new file mode 100644 index 00000000000..3a7a917fb33 --- /dev/null +++ b/Build/source/libs/libttf/arch/mac/ttmmap.c @@ -0,0 +1,1069 @@ +/******************************************************************* + * + * ttmmap.c 2.0 + * + * Memory-Mapped file component ( replaces ttfile.c ). + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Changes between 2.0 and 1.3 : + * + * - adopted new design/separation introduced in ttfile.c 2.0 + * + ******************************************************************/ + +#include "ttconfig.h" + +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <folders.h> +#include <resources.h> + + +#include "freetype.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttengine.h" +#include "ttmutex.h" +#include "ttmemory.h" +#include "ttfile.h" /* our prototypes */ + + /* This definition is mandatory for each file component! */ + EXPORT_FUNC + const TFileFrame TT_Null_FileFrame = { NULL, 0, 0 }; + + /* It has proven useful to do some bounds checks during */ + /* development phase. Define DEBUG_FILE when compiling */ + /* this component to enable them. */ + +#ifdef DEBUG_FILE +#define CHECK_FRAME( frame, n ) \ + do { \ + if ( frame.cursor+n > frame.address + frame.size ) \ + Panic( "Frame boundary error!\n" ); \ + } while ( 0 ) +#else +#define CHECK_FRAME( frame, n ) \ + do { \ + } while( 0 ) +#endif + + struct _TFileMap + { + String* base; /* base address of mapped file */ + Int refcount; /* reference count for handle region */ + Long size; /* stream size in file */ + Long offset; /* offset in file */ + Handle handle; /* Macintosh style handle to lock/unlock */ + short resid; /* Id of resource file to close when done */ + }; + + typedef struct _TFileMap TFileMap; + +#define MAP_Address( map ) (Byte*)( (map)->base + (map)->offset ) + + /* The stream record structure */ + typedef struct _TStream_Rec + { + TFileMap* map; /* mapped file description */ + Long pos ; /* cursor in mapped file */ + } TStream_Rec; + + typedef TStream_Rec* PStream_Rec; + +#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) ) + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /**** ****/ + /**** N O N R E E N T R A N T I M P L E M E N T A T I O N ****/ + /**** ****/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* The TFile_Component structure holds all the data that was */ + /* previously declared static or global in this component. */ + /* */ + /* It is accessible through the 'engine.file_component' */ + /* variable in re-entrant builds, or directly through the */ + /* static 'files' variable in other builds. */ + + struct _TFile_Component + { + TMutex lock; /* used by the thread-safe build only */ + PStream_Rec stream; /* current stream */ + TFileFrame frame; /* current frame */ + }; + + typedef struct _TFile_Component TFile_Component; + +/* The macro CUR_Stream denotes the current input stream */ +/* Note that for the re-entrant version, the 'stream' name has been */ +/* chosen according to the macro STREAM_ARGS. */ + +/* The macro CUR_Frame denotes the current file frame */ +/* Note that for the re-entrant version, the 'frame' name has been */ +/* chosen according to the macro FRAME_ARGS. */ + +/* The macro STREAM_VAR is used when calling public functions */ +/* that need an 'optional' stream argument. */ + +#define CUR_Stream files.stream /* thread-safe macros */ +#define CUR_Frame files.frame + +#define STREAM_VARS /* void */ +#define STREAM_VAR /* void */ + + /* the 'files' variable is only defined in non-reentrant builds */ + + static TFile_Component files; + + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + MUTEX_Create( files.lock ); + files.stream = NULL; + ZERO_Frame( files.frame ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + MUTEX_Destroy( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream org_stream, + TT_Stream* stream ) + { + MUTEX_Lock( files.lock ); + *stream = org_stream; + files.stream = STREAM2REC( org_stream ); /* set current stream */ + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream + * + * Output : Error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + HANDLE_Set( *stream, NULL ); + MUTEX_Release( files.lock ); + + return TT_Err_Ok; + } + +#else /* TT_CONFIG_OPTION_THREAD_SAFE */ + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /******** ********/ + /******** R E E N T R A N T I M P L E M E N T A T I O N ********/ + /******** ********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +#define CUR_Stream STREAM2REC( stream ) /* re-entrant macros */ +#define CUR_Frame (*frame) + +#define STREAM_VARS stream, +#define STREAM_VAR stream + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + engine.file_component = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code. The output stream is set to NULL in + * case of Failure. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream input_stream, + TT_Stream* copy ) + { + TT_Error error; + PStream_Rec stream_rec; + PStream_Rec copy_rec; + + + stream_rec = STREAM2REC( input_stream ); + + if ( ALLOC( copy_rec, sizeof ( TStream_Rec ) ) ) + goto Fail; + + HANDLE_Set( *copy, copy_rec ); + + copy_rec->map->refcount++; + copy_rec->pos = 0; + + return TT_Err_Ok; + + Fail: + HANDLE_Set( *copy, NULL ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream + * + * Output : error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + return TT_Close_Stream( stream ); + } + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /*********** ***********/ + /*********** C O M M O N I M P L E M E N T A T I O N ***********/ + /*********** ***********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/******************************************************************* + * + * Function : AllocateMap + * + * Description : Allocates a new map from the table. + * + * Output : Pointer to new stream rec. NULL in case of failure. + * + ******************************************************************/ + + static + TFileMap* Allocate_Map( void ) + { + TFileMap* result; + + + if ( MEM_Alloc( result, sizeof ( TFileMap ) ) ) + return NULL; + + result->refcount = 1; + return result; + } + + +/******************************************************************* + * + * Function : ReleaseMap + * + * Description : Releases a used map to the table if reference i + * counter reaches zero. + * + * Input : map + * + * Output : None. + * + * Note : Called by TT_Close_File() + * + ******************************************************************/ + + static + void Release_Map ( TFileMap* map ) + { + map->refcount--; + if ( map->refcount <= 0 ) + { + /* MacOS System calls */ + HUnlock(map->handle); + ReleaseResource(map->handle); + CloseResFile(map->resid); + + FREE( map ); + } + } + + +/* Whadda ya mean "strdup undefined"? Fine, I'll define my own! */ +static char *mystrdup(const char *str) { + char *ret; + + if ( TT_Alloc(strlen(str) + 1, (void**)&ret) != 0 ) return(NULL); + strcpy(ret, str); + return(ret); + } + +/******************************************************************* + * + * Function : TT_Open_Stream + * + * Description : Opens the font file and saves the total file size. + * + * Input : error address of stream's error variable + * (re-entrant build only). + * filepathname pathname of the file to open + * stream address of target TT_Stream structure + * + * Output : SUCCESS on success, FAILURE on error. + * The target stream is set to -1 in case of failure. + * + ******************************************************************/ +/* +** This is not a totally generic implementation. It currently assumes the filename +** starts with "fonts:" and uses slashes instead of colons like Mac code normally +** would. Given a filename of the form "fonts:/filename/resname", Load the resource +** and lock the handle +** +** The "fonts:" at the beginning is just a convention I came up with to +** indicate the Fonts folder inside the current System folder (find via FindFolder()) +*/ + + LOCAL_FUNC + TT_Error TT_Open_Stream( const String* filepathname, + TT_Stream* stream ) + { + TT_Error error; + Int file; + PStream_Rec stream_rec; + TFileMap* map; + + int size, err = 0; + short vRefNum, res = -1; + Str255 FontName; + char *cp, *p, *fname, *sep; + Str63 myName; + long dirID; + + + if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) ) + return error; + + map = Allocate_Map(); + if ( !map ) + { + error = TT_Err_Out_Of_Memory; + goto Memory_Fail; + } + + stream_rec = STREAM2REC( *stream ); + + /* Find the dirID of the Fonts folder in the current System folder */ + if (FindFolder(kOnSystemDisk, kFontsFolderType, kDontCreateFolder, &vRefNum, &dirID)) + goto File_Fail; + + /* Break the name apart */ + fname = mystrdup(filepathname); /* Make a copy so we can muck with it */ + sep = ":/"; /* Things that can seperate file path componants */ + + strtok(fname, sep); /* Skip over "fonts:" */ + + if ((p = strtok(NULL, sep)) == NULL) /* Get filename */ + goto File_Fail; + strcpy(myName + 1, p); /* Make this a Pascal string (Yuck!) */ + myName[0] = strlen(p); + + if ((p = strtok(NULL, sep)) == NULL) /* Get res name */ + goto File_Fail; + strcpy(FontName+1, p); /* Make this a Pascal string (Yuck!) */ + FontName[0] = strlen(p); + + FREE( fname ); + + if ((cp = strchr(FontName, '.')) != NULL) /* Strip off ".ttf" , if any */ + *cp = 0; + + /* Read the font into a buffer */ + if ((map->resid = HOpenResFile(vRefNum, dirID, myName, fsRdPerm)) == -1) + goto File_Fail; + + if ((map->handle = Get1NamedResource('sfnt', FontName)) == NULL) + goto Map_Fail; + + HLock(map->handle); + map->base = *map->handle; + map->offset = 0; + map->size = GetResourceSizeOnDisk(map->handle); + + if ( map->base == NULL ) + goto Lock_Fail; + + stream_rec->map = map; + stream_rec->pos = 0; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + CUR_Stream = stream_rec; +#endif + + return TT_Err_Ok; + + Lock_Fail: + ReleaseResource(map->handle); + + Map_Fail: + CloseResFile(map->resid); + + File_Fail: + error = TT_Err_Could_Not_Open_File; + FREE( map ); + + Memory_Fail: + FREE( *stream ); + FREE( fname ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Close_Stream + * + * Description : Closes a stream. + * + * Input : stream + * + * Output : SUCCESS (always) + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Close_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + Release_Map( rec->map ); + FREE( rec ); + + HANDLE_Set( *stream, NULL ); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Flush_Stream + * + * Description : Flushes a stream, i.e., closes its file handle. + * + * Input : stream address of target TT_Stream structure + * + * Output : Error code + * + * NOTE : Never flush the current opened stream. This means that + * you should _never_ call this function between a + * TT_Use_Stream() and a TT_Done_Stream()! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Flush_Stream( TT_Stream* stream ) + { + /* XXX - DUMMY IMPLEMENTATION */ + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Stream_Size + * + * Description : Returns the length of a given stream, even if it + * is flushed. + * + * Input : stream the stream + * + * Output : Length of stream in bytes. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Stream_Size( TT_Stream stream ) + { + PStream_Rec rec = STREAM2REC( stream ); + + + if ( rec ) + return rec->map->size; + else + return 0; /* invalid stream - return 0 */ + } + + +/******************************************************************* + * + * Function : TT_Seek_File + * + * Description : Seeks the file cursor to a different position. + * + * Input : position new position in file + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Seek_File( STREAM_ARGS Long position ) + { + if ( position > CUR_Stream->map->size ) + return TT_Err_Invalid_File_Offset; + + CUR_Stream->pos = position; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Skip_File + * + * Description : Skips forward the file cursor. + * + * Input : distance number of bytes to skip + * + * Output : see TT_Seek_File + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Skip_File( STREAM_ARGS Long distance ) + { + return TT_Seek_File( STREAM_VARS CUR_Stream->pos + distance ); + } + + +/******************************************************************* + * + * Function : TT_Read_File + * + * Description : Reads a chunk of the file and copies it to memory. + * + * Input : buffer target buffer + * count length in bytes to read + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_File( STREAM_ARGS void* buffer, Long count ) + { + if ( CUR_Stream->pos + count > CUR_Stream->map->size ) + return TT_Err_Invalid_File_Read; + + MEM_Copy( buffer, + MAP_Address( CUR_Stream->map ) + CUR_Stream->pos, count ); + CUR_Stream->pos += count; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Read_At_File + * + * Description : Reads file at a specified position. + * + * Input : position position to seek to before read + * buffer target buffer + * count number of bytes to read + * + * Output : SUCCESS on success. FAILURE if error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_At_File( STREAM_ARGS Long position, + void* buffer, + Long count ) + { + TT_Error error; + + + if ( (error = TT_Seek_File( STREAM_VARS position )) || + (error = TT_Read_File( STREAM_VARS buffer, count )) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_File_Pos + * + * Description : Returns current file seek pointer. + * + * Input : none + * + * Output : current file position + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_File_Pos( STREAM_ARG ) + { + return CUR_Stream->pos; + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : Error code + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that aSize is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( CUR_Stream->pos + size > CUR_Stream->map->size ) + return TT_Err_Invalid_Frame_Access; + + CUR_Frame.size = size; + CUR_Frame.address = MAP_Address( CUR_Stream->map ) + CUR_Stream->pos; + CUR_Frame.cursor = CUR_Frame.address; + + CUR_Stream->pos += size; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : Error code + * + * Notes: The function truncates 'size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that aSize is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. The 'overflow' is set to zero. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + Long readBytes; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + readBytes = CUR_Stream->map->size - CUR_Stream->pos; + if ( size > readBytes ) + { + /* There is overflow, we allocate a new block then */ + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + + CUR_Frame.size = size; + + /* copy the valid part */ + MEM_Copy( CUR_Frame.address, + MAP_Address( CUR_Stream->map ) + CUR_Stream->pos, + readBytes ); + } + else + { + CUR_Frame.size = size; + CUR_Frame.address = MAP_Address( CUR_Stream->map ) + CUR_Stream->pos; + } + + CUR_Frame.cursor = CUR_Frame.address; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + /* If we were using a duplicate in case of overflow, free it now */ + if ( CUR_Frame.address < (Byte*)CUR_Stream->map->base || + CUR_Frame.address >= (Byte*)CUR_Stream->map->base + + CUR_Stream->map->size ) + FREE( CUR_Frame.address ); + + ZERO_Frame( files.frame ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : GET_Byte + * + * Description : Extracts a byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted Byte + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + Byte TT_Get_Byte( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Byte)(*CUR_Frame.cursor++); + } + +#endif + + +/******************************************************************* + * + * Function : GET_Char + * + * Description : Extracts a signed byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted char + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Char TT_Get_Char( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Char)(*CUR_Frame.cursor++); + } + + +/******************************************************************* + * + * Function : GET_Short + * + * Description : Extracts a short from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted short + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Short TT_Get_Short( FRAME_ARG ) + { + Short getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((Short)CUR_Frame.cursor[0] << 8) | + (Short)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } + + +/******************************************************************* + * + * Function : GET_UShort + * + * Description : Extracts an unsigned short from the frame. + * + * Input : None or current frame + * + * Output : Extracted ushort + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + UShort TT_Get_UShort( FRAME_ARG ) + { + UShort getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((UShort)CUR_Frame.cursor[0] << 8) | + (UShort)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } + +#endif + + +/******************************************************************* + * + * Function : GET_Long + * + * Description : Extracts a long from the frame. + * + * Input : None or current frame + * + * Output : Extracted long + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Get_Long( FRAME_ARG ) + { + Long getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ((Long)CUR_Frame.cursor[0] << 24) | + ((Long)CUR_Frame.cursor[1] << 16) | + ((Long)CUR_Frame.cursor[2] << 8 ) | + (Long)CUR_Frame.cursor[3]; + + CUR_Frame.cursor += 4; + + return getlong; + } + + +/******************************************************************* + * + * Function : GET_ULong + * + * Description : Extracts an unsigned long from the frame. + * + * Input : None + * + * Output : Extracted ulong + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + ULong TT_Get_ULong( FRAME_ARG ) + { + ULong getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ( ((ULong)CUR_Frame.cursor[0] << 24) | + ((ULong)CUR_Frame.cursor[1] << 16) | + ((ULong)CUR_Frame.cursor[2] << 8 ) | + (ULong)CUR_Frame.cursor[3] ); + + CUR_Frame.cursor += 4; + + return getlong; + } + +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.BC b/Build/source/libs/libttf/arch/msdos/Makefile.BC new file mode 100644 index 00000000000..ba5d50b38cc --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.BC @@ -0,0 +1,132 @@ +# This file is part of the FreeType project. +# +# It builds the library for Borland C++ for MS-DOS, large model. +# Due to size constraints, it does not try to pack all modules into one +# (`single-object mode'). +# +# You will need Borland MAKE. +# Tested with Borland C++ v.3.1, 4.02, 5.0. +# +# Use this file while in the lib directory with the following statement: +# +# make -farch/msdos/Makefile.BC +# +# +# A debug version can be obtained with +# +# make -DDEBUG -farch/msdos/Makefile.BC +# +# A special version enabled to handle big fonts (with more than 16,384 +# glyphs) can be obtained with +# +# make -DBIGFONTS -farch/msdos/Makefile.BC + +ARCH = arch\msdos +FT_MAKEFILE = $(ARCH)\Makefile.BC + +CC = bcc +LIB = tlib /c /e + +# Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern +# Borland compilers (from BC++ 3.1 on) can increase the limit on +# the length of identifiers. +!if ! $d(DEBUG) +CFLAGS = -ml -A -O2 -3 -i40 -w-nak -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig -I$(ARCH);.;extend +!else +CFLAGS = -v -N -ml -A -i40 -w-nak -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig -I$(ARCH);.;extend +!endif + + +!if $d(BIGFONTS) +CFLAGS = $(CFLAGS) -DTT_HUGE_PTR=__huge + +TTFILE = $(ARCH)\.\hugefile.c +TTMEMORY = $(ARCH)\.\hugemem.c +!else +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +!endif +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces before the \ at end of line, +# otherwise the substitution for TLIB command line will fail. +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ + extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c\ + extend\ftxsbit.c extend\ftxgsub.c extend\ftxgpos.c\ + extend\ftxopen.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c\ + ttgload.c ttinterp.c ttload.c ttobjs.c\ + ttraster.c ttextend.c ttdebug.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\.\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Borland's make does not handle $($(LIB_FILES)), and using +# -DLIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing TLIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# It is commented out below. See Makefile.TC for an application. +.c.obj: + $(CC) -c -o$* @&&| + $(CFLAGS) $< +| +# $(LIB) libttf +-$*.obj + + +!if !$d(DEBUG) +# Skipped if DEBUG build +# (but it changes nothing, since we always build in multiple parts). +all: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_M: = + ) +| + +!endif + + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_M: = + ) +| + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(**: = + ) +| + +!if $d(BIGFONTS) +$(TTMEMORY:.c=.obj): $(TTMEMORY) + $(CC) -c -o$* @&&| + $(CFLAGS) -A- $*.c +| +!endif + + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak + -del response + +distclean: clean + -del libttf.lib + +!include "$(ARCH)\depend.dos" + +# end of Makefile diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.MS b/Build/source/libs/libttf/arch/msdos/Makefile.MS new file mode 100644 index 00000000000..3c793faff94 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.MS @@ -0,0 +1,117 @@ +# This file is part of the FreeType project. +# +# It builds the library for Microsoft C for MS-DOS, large model. +# It also works for Visual C++ 1.x 16-bits compiler, but you should +# instead use the Makefile customized for it, Makefile.VC. +# Due to size constraints, it does not try to pack all modules into one. +# +# You will need NMAKE. +# +# Use this file while in the lib directory with the following statement: +# +# nmake /f arch\msdos\Makefile.MS +# +# +# A debug version can be obtained with +# +# nmake DEBUG=1 /f arch\msdos\Makefile.MS +# +# A special version enabled to handle big fonts (with more than 16,384 +# glyphs) can be obtained with +# +# nmake BIGFONTS=1 /f arch\msdos\Makefile.MS + +ARCH = arch\msdos +FT_MAKEFILE = $(ARCH)\Makefile.MS + +CC = cl /nologo +LIB = lib /noignorecase /nologo + +!ifndef DEBUG +CFLAGS = /Ox /AL /W2 /G2 /I$(ARCH) /I. /Iextend +!else +CFLAGS = /Zi /AL /W2 /G2 /I$(ARCH) /I. /Iextend +!endif + + +!ifndef BIGFONTS +CFLAGS = $(CFLAGS) /Za + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +!else +CFLAGS = $(CFLAGS) /DTT_HUGE_PTR=__huge /Ze + +TTFILE = $(ARCH)\hugefile.c +TTMEMORY = $(ARCH)\hugemem.c +!endif + +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces between the file names or at end of line, otherwise +# the substitution for LIB command line will fail. Thank you. +# +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ +extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c extend\ftxsbit.c\ +extend\ftxopen.c extend\ftxgsub.c extend\ftxgpos.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c\ +ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Microsoft's NMAKE does not handle $($(LIB_FILES)), and using +# LIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing LIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# It is commented out below. See Makefile.TC for an application. +.c.obj: + @$(CC) /c /Fo$@ @<< + $(CFLAGS) $*.c +<< +# $(LIB) libttf +-$*.obj + + +!ifndef DEBUG +# Skipped if DEBUG build +# (but it changes nothing, since we always build in multiple parts). +all: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = ^ ); +<<KEEP +!endif + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = ^ ); +<<KEEP + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + $(LIB) $@ +-$(?: =-+); + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del response + +distclean: clean + -del libttf.lib + +!include "$(ARCH)\depend.dos" + +# end of Makefile.MS diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.TC b/Build/source/libs/libttf/arch/msdos/Makefile.TC new file mode 100644 index 00000000000..a3316c53f23 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.TC @@ -0,0 +1,86 @@ +# This file is part of the FreeType project. +# +# It builds the library for Turbo C for MS-DOS, large model. +# Due to size constraints, it does not try to pack all modules into one. +# +# You will need Borland MAKE. +# Tested with Turbo C v.1.5, v.2.0, Turbo C++ v.1.0 +# Turbo C v.1.0 (May '87) is too old (lack of structure assignment) +# to compile FreeType. Update your compiler. ;-) +# +# Use this file while in the lib directory with the following statement: +# +# make -farch/msdos/Makefile.TC +# +# +# A debug version can be obtained (except for TC1.5) with +# +# make -DDEBUG -farch/msdos/Makefile.TC + +ARCH = arch\msdos +FT_MAKEFILE = $(ARCH)\Makefile.TC + +CC = tcc +LIB = tlib /c + +!if ! $d(DEBUG) +CFLAGS = -ml -A -a -G -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig -I$(ARCH);.;extend +!else +# For Turbo C v.1.5, replace the -v option below by -y. +CFLAGS = -v -N -ml -A -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig -I$(ARCH);.;extend +!endif + + +TTFILE = .\ttfile.obj +TTMEMORY = .\ttmemory.obj +TTMUTEX = .\ttmutex.obj + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +OBJS_X = extend\ftxgasp.obj extend\ftxkern.obj extend\ftxpost.obj \ + extend\ftxcmap.obj extend\ftxwidth.obj extend\ftxerr18.obj \ + extend\ftxsbit.obj extend\ftxopen.obj extend\ftxgsub.obj \ + extend\ftxgpos.obj extend\ftxgdef.obj +# the line below does not work with these old versions of make... +# OBJS_X = $(SRC_X:.c=.obj) + +OBJS_M = ttapi.obj ttcache.obj ttcalc.obj ttcmap.obj ttdebug.obj \ + ttgload.obj ttinterp.obj ttload.obj ttobjs.obj \ + ttraster.obj ttextend.obj $(PORT) $(OBJS_X) +# OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +# Not used here because the compiler runs out of memory... +OBJ_S = $(ARCH)\freetype.obj +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Borland's make is very primitive, we include each .obj +# in the library as soon as it is compiled. + +.c.obj: + $(CC) $(CFLAGS) -c -o$* $< + $(LIB) libttf +-$*.obj + + +!if !$d(DEBUG) +# Skipped if DEBUG build +# (but it changes nothing, since we always build in multiple parts). +all: $(OBJS_M) + +!endif + +debug: $(OBJS_M) + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak +# -del response + +distclean: clean + -del libttf.lib + +!include "$(ARCH)\depend.dos" + +# end of Makefile diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.VC b/Build/source/libs/libttf/arch/msdos/Makefile.VC new file mode 100644 index 00000000000..e9d0855ad08 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.VC @@ -0,0 +1,117 @@ +# This file is part of the FreeType project. +# +# It builds the library for Microsoft Visual C++ 1.x for MS-DOS, large model. +# It also works for Microsoft C/C++ v.7.0 16-bit compiler, but not for +# previous versions (use Makefile.MS instead). +# +# You will need NMAKE. +# +# Use this file while in the lib directory with the following statement: +# +# nmake /f arch\msdos\Makefile.VC +# +# +# A debug version can be obtained with +# +# nmake DEBUG=1 /f arch\msdos\Makefile.VC +# +# A special version enabled to handle big fonts (with more than 16,384 +# glyphs) can be obtained with +# +# nmake BIGFONTS=1 /f arch\msdos\Makefile.VC + +ARCH = arch\msdos +FT_MAKEFILE = $(ARCH)\Makefile.VC + +CC = cl /nologo +LIB = lib /noignorecase /nologo + +# One can also consider using "set MSC_CMD_FLAGS=/Gr /Op- /Gy /YX". +# With Microsoft C/C++ 7.0, use /G2 instead of /G3. +!ifndef DEBUG +CFLAGS = $(CFLAGS) /Ox /AL /W2 /G3 /I$(ARCH) /I. /Iextend +!else +CFLAGS = $(CFLAGS) /Zi /Ge /AL /W2 /G3 /I$(ARCH) /I. /Iextend +!endif + + +!ifndef BIGFONTS +CFLAGS = $(CFLAGS) /Za + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +!else +CFLAGS = $(CFLAGS) /DTT_HUGE_PTR=__huge /Ze + +TTFILE = $(ARCH)\hugefile.c +TTMEMORY = $(ARCH)\hugemem.c +!endif + +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces between the file names or at end of line, otherwise +# the substitution for LIB command line will fail. Thank you. +# +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ +extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c extend\ftxsbit.c\ +extend\ftxopen.c extend\ftxgsub.c extend\ftxgpos.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c\ +ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Microsoft's NMAKE does not handle $($(LIB_FILES)), and using +# LIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing LIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# It is commented out below. See Makefile.TC for an application. +.c.obj: + @$(CC) /c /Fo$@ @<< + $(CFLAGS) $*.c +<< +# $(LIB) libttf +-$*.obj + + +!ifndef DEBUG +# Skipped if DEBUG build +all: $(OBJS_S) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_S: = + ); +<<KEEP +!endif + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = + ); +<<KEEP + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + $(LIB) $@ +-$(?: =-+); + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del response + +distclean: clean + -del libttf.lib + +!include "$(ARCH)\depend.dos" + +# end of Makefile.VC diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.dm b/Build/source/libs/libttf/arch/msdos/Makefile.dm new file mode 100644 index 00000000000..710c355bf53 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.dm @@ -0,0 +1,84 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for emx-gcc or djgpp under MSDOS. +# +# You will need dmake. +# +# Use this file while in the lib directory with the following statement: +# +# dmake -r -f arch/msdos/Makefile.dm + +ARCH = arch/msdos +FT_MAKEFILE = $(ARCH)/Makefile.dm +FT_MAKE = dmake -r + +.IMPORT: COMSPEC +SHELL := $(COMSPEC) +SHELLFLAGS := /c +GROUPSHELL := $(SHELL) +GROUPFLAGS := $(SHELLFLAGS) +GROUPSUFFIX := .bat +SHELLMETAS := *"?<>&| + +CC = gcc + +CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend +# CFLAGS = -Wall -ansi -O2 -s -I$(ARCH) -I. -Iextend + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxopen.c \ + extend/ftxgdef.c extend/ftxerr18.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttfile.c ttgload.c ttinterp.c ttload.c \ + ttmemory.c ttmutex.c ttobjs.c ttraster.c ttextend.c +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M libttf.a + + +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) $(CFLAGS) -c -o $@ $(SRC_S) + +libttf.a: $($(LIB_FILES)) + +-del $@ + ar src $@ @$(mktmp $(<:t"\n")\n) + +clean: +-[ + del *.o + del extend\*.o + del $(ARCH)\*.o +] + +distclean: clean +-[ + del dep.end + del libttf.a +] + +# depend: $(SRC_S) $(SRC_M) $(SRC_X) +# $(CC) -E -M @$(mktmp $(<:t"\n")\n) > dep.end + +# ifeq (dep.end,$(wildcard dep.end)) +# include dep.end +# endif + +# end of Makefile.dm diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.gcc b/Build/source/libs/libttf/arch/msdos/Makefile.gcc new file mode 100644 index 00000000000..3325538fb4a --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.gcc @@ -0,0 +1,92 @@ +# This file is part of the FreeType project. +# +# It builds the library for emx-gcc or djgpp under MSDOS. +# +# You will need GNU make. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/msdos/Makefile.gcc +# +# If you have the GNU gettext package installed with DJGPP, you can also try +# +# make -f arch/msdos/Makefile.gcc HAVE_GETTEXT + +ARCH = arch/msdos +FT_MAKEFILE = $(ARCH)/Makefile.gcc + +CC = gcc + +ifndef GETTEXT +GETTEXT=NO_GETTEXT +endif + +ifdef DEBUG +CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend -D$(GETTEXT) +else +CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend -D$(GETTEXT) +endif + + +TTFILE = ./ttfile.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ + extend/ftxopen.c extend/ftxerr18.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M DEBUG=1 libttf.a + +HAVE_GETTEXT: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S GETTEXT=HAVE_GETTEXT \ + libttf.a + +$(OBJ_S): $(SRC_S) $(SRC_M) + +libttf.a: $($(LIB_FILES)) + -del $@ + ar src $@ $^ + +clean: + -del *.o + -del extend\*.o + -del $(ARCH)\*.o + -del response + +distclean: clean + -del dep.end + -del libttf.a + +depend: $(SRS_S) $(SRC_M) $(SRC_X) + $(CC) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile.gcc diff --git a/Build/source/libs/libttf/arch/msdos/Makefile.wat b/Build/source/libs/libttf/arch/msdos/Makefile.wat new file mode 100644 index 00000000000..e2df1e36f44 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/Makefile.wat @@ -0,0 +1,88 @@ +# This file is part of the FreeType project +# +# This builds the Watcom library with Watcom's wcc386 under DOS +# +# You'll need Watcom's wmake +# +# +# Invoke by "wmake -f arch\msdos\Makefile.wat" while in the "lib" directory +# +# This will build "freetype\lib\libttf.lib" +# + +ARCH = arch\msdos +FT_MAKEFILE = $(ARCH)\Makefile.wat +FT_MAKE = wmake -h + + +.EXTENSIONS: +.EXTENSIONS: .lib .obj .c .h +.obj:.;.\extend;.\$(ARCH) +.c:.;.\extend;.\$(ARCH) +.h:.;.\extend;.\$(ARCH) + +CC = wcc386 + +CCFLAGS = /otexanl+ /s /w4 /zq /d3 -I$(ARCH) -I. -Iextend + + +# FIXME: should use something like OBJ = $(SRC:.c=.obj) + +SRC_X = ftxgasp.c ftxkern.c ftxpost.c & + ftxcmap.c ftxwidth.c ftxsbit.c ftxerr18.c & + ftxgsub.c ftxgpos.c ftxopen.c ftxgdef.c +OBJS_X = ftxgasp.obj ftxkern.obj ftxpost.obj & + ftxcmap.obj ftxwidth.obj ftxsbit.obj ftxerr18.obj & + ftxgsub.obj ftxgpos.obj ftxopen.obj ftxgdef.obj + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c & + ttfile.c ttgload.c ttinterp.c & + ttload.c ttmemory.c ttmutex.c ttobjs.c ttraster.c & + ttextend.c +OBJS_M = ttapi.obj ttcache.obj ttcalc.obj ttcmap.obj ttdebug.obj & + ttfile.obj ttgload.obj ttinterp.obj & + ttload.obj ttmemory.obj ttmutex.obj ttobjs.obj ttraster.obj & + ttextend.obj $(OBJS_X) + +SRC_S = freetype.c +OBJ_S = freetype.obj +OBJS_S = $(OBJ_S) $(OBJ_X) + + +.c.obj: + $(CC) $(CCFLAGS) $[* /fo=$[*.obj + +libname = libttf +libfile = $(libname).lib +cmdfile = $(libname).lst + + +all: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S $(libfile) + +debug: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M $(libfile) + + +$(libfile): $($(LIB_FILES)) + wlib -q -n $(libfile) @$(cmdfile) + +# is this correct? Know nothing about wmake and the Watcom compiler... +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) $(CCFLAGS) $(SRC_S) /fo=$(OBJ_S) + +$(cmdfile): $($(LIB_FILES)) + @for %i in ($($(LIB_FILES))) do @%append $(cmdfile) +-%i + +clean: .symbolic + @-erase $(OBJ_S) + @-erase $(OBJS_M) + @-erase $(cmdfile) + +distclean: .symbolic clean + @-erase $(libfile) + +new: .symbolic + @-wtouch *.c + +# end of Makefile.wat diff --git a/Build/source/libs/libttf/arch/msdos/depend.dos b/Build/source/libs/libttf/arch/msdos/depend.dos new file mode 100644 index 00000000000..9039c57d2df --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/depend.dos @@ -0,0 +1,107 @@ +# This dependency file to be used with various MS-DOS compilers +# has been generated automatically with the script `makedep' on +# 07-Mar-2000. + +ttapi.obj: ttapi.c ttconfig.h arch\msdos\ft_conf.h freetype.h fterrid.h \ + ftnameid.h ttengine.h tttypes.h ttmutex.h ttcalc.h ttmemory.h \ + ttcache.h ttfile.h ttdebug.h ttobjs.h tttables.h ttcmap.h ttload.h \ + ttgload.h ttraster.h ttextend.h +ttcache.obj: ttcache.c ttengine.h tttypes.h ttconfig.h \ + arch\msdos\ft_conf.h freetype.h fterrid.h ftnameid.h ttmutex.h \ + ttmemory.h ttcache.h ttobjs.h tttables.h ttcmap.h ttdebug.h +ttcalc.obj: ttcalc.c ttcalc.h ttconfig.h arch\msdos\ft_conf.h freetype.h \ + fterrid.h ftnameid.h ttdebug.h tttypes.h tttables.h +ttcmap.obj: ttcmap.c ttobjs.h ttconfig.h arch\msdos\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttdebug.h ttfile.h ttmemory.h ttload.h +ttdebug.obj: ttdebug.c ttdebug.h ttconfig.h arch\msdos\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h tttables.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h ttcmap.h +ttextend.obj: ttextend.c ttextend.h ttconfig.h arch\msdos\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttmemory.h +ttfile.obj: ttfile.c ttconfig.h arch\msdos\ft_conf.h freetype.h \ + fterrid.h ftnameid.h tttypes.h ttdebug.h ttengine.h ttmutex.h \ + ttmemory.h ttfile.h +ttgload.obj: ttgload.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h ttgload.h \ + ttmemory.h tttags.h ttload.h +ttinterp.obj: ttinterp.c freetype.h fterrid.h ftnameid.h tttypes.h \ + ttconfig.h arch\msdos\ft_conf.h ttdebug.h ttcalc.h ttmemory.h \ + ttinterp.h ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h \ + ttcmap.h +ttload.obj: ttload.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h \ + ttmemory.h tttags.h ttload.h +ttmemory.obj: ttmemory.c ttdebug.h ttconfig.h arch\msdos\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmemory.h ttengine.h \ + ttmutex.h +ttmutex.obj: ttmutex.c ttmutex.h ttconfig.h arch\msdos\ft_conf.h +ttobjs.obj: ttobjs.c ttobjs.h ttconfig.h arch\msdos\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttfile.h ttdebug.h ttcalc.h ttmemory.h ttload.h \ + ttinterp.h ttextend.h +ttraster.obj: ttraster.c ttraster.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttengine.h tttypes.h ttmutex.h \ + ttdebug.h ttcalc.h ttmemory.h +extend\ftxcmap.obj: extend\ftxcmap.c extend\ftxcmap.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\msdos\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxerr18.obj: extend\ftxerr18.c ttconfig.h arch\msdos\ft_conf.h \ + extend\ftxerr18.h freetype.h fterrid.h ftnameid.h extend\ftxkern.h \ + extend\ftxpost.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h +extend\ftxgasp.obj: extend\ftxgasp.c extend\ftxgasp.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\msdos\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxgdef.obj: extend\ftxgdef.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgpos.obj: extend\ftxgpos.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgsub.obj: extend\ftxgsub.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxkern.obj: extend\ftxkern.c extend\ftxkern.h freetype.h fterrid.h \ + ftnameid.h ttextend.h ttconfig.h arch\msdos\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttdebug.h \ + ttmemory.h ttfile.h ttload.h tttags.h +extend\ftxopen.obj: extend\ftxopen.c tttypes.h ttconfig.h arch\msdos\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxpost.obj: extend\ftxpost.c extend\ftxpost.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\msdos\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttload.h ttfile.h \ + ttdebug.h tttags.h ttmemory.h ttextend.h +extend\ftxsbit.obj: extend\ftxsbit.c extend\ftxsbit.h freetype.h fterrid.h \ + ftnameid.h ttobjs.h ttconfig.h arch\msdos\ft_conf.h ttengine.h \ + tttypes.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h ttdebug.h \ + ttload.h ttmemory.h tttags.h ttextend.h +extend\ftxwidth.obj: extend\ftxwidth.c extend\ftxwidth.h freetype.h fterrid.h \ + ftnameid.h ttdebug.h ttconfig.h arch\msdos\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h \ + tttags.h ttload.h +arch\msdos\freetype.obj: arch\msdos\freetype.c ttapi.c ttconfig.h \ + arch\msdos\ft_conf.h freetype.h fterrid.h ftnameid.h ttengine.h \ + tttypes.h ttmutex.h ttcalc.h ttmemory.h ttcache.h ttfile.h ttdebug.h \ + ttobjs.h tttables.h ttcmap.h ttload.h ttgload.h ttraster.h ttextend.h \ + ttcache.c ttcalc.c ttcmap.c ttdebug.c ttgload.c tttags.h ttinterp.c \ + ttinterp.h ttload.c ttobjs.c ttraster.c arch\msdos\hugefile.c \ + ttfile.c arch\msdos\hugemem.c ttmutex.c ttextend.c +arch\msdos\hugefile.obj: arch\msdos\hugefile.c ttconfig.h arch\msdos\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttfile.c ttdebug.h \ + ttengine.h ttmutex.h ttmemory.h ttfile.h +arch\msdos\hugemem.obj: arch\msdos\hugemem.c ttdebug.h ttconfig.h \ + arch\msdos\ft_conf.h tttypes.h freetype.h fterrid.h ftnameid.h \ + ttmemory.h ttengine.h ttmutex.h diff --git a/Build/source/libs/libttf/arch/msdos/freetype.c b/Build/source/libs/libttf/arch/msdos/freetype.c new file mode 100644 index 00000000000..943d5f24776 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/freetype.c @@ -0,0 +1,39 @@ +/* This file is part of the FreeType project */ + +/* Single object library component for MSDOS. */ +/* Note that low-optimizing 16-bit compilers (such as Borland ones) can't */ +/* successfully compile this file, because it exceeds 64K of code size. */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#ifdef TT_HUGE_PTR +#include "arch/msdos/hugefile.c" +#include "arch/msdos/hugemem.c" +#else +#include "ttfile.c" +#include "ttmemory.c" +#endif +#include "ttmutex.c" + +/* finally, add some extensions */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/msdos/ft_conf.h b/Build/source/libs/libttf/arch/msdos/ft_conf.h new file mode 100644 index 00000000000..0199a5c2027 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/ft_conf.h @@ -0,0 +1,253 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for MSDOS */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#if defined( __EMX__ ) || defined( __DJGPP__ ) || defined( __GO32__ ) +/* some compilers are known to have <unistd.h>; */ +/* add yours if needed, and report to us the update. */ +#define HAVE_UNISTD_H +#else +/* most MS-DOS compilers lack <unistd.h> */ +#undef HAVE_UNISTD_H +#endif + +/* Define if you need <conio.h> for console I/O functions. */ +#ifdef __EMX__ +#define HAVE_CONIO_H +#endif + +/* Define if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the <libintl.h> header file. */ +#undef HAVE_LIBINTL_H + +/* Define if you have the libintl library. */ +#undef HAVE_LIBINTL + +/* DJGPP v.2 may feature the GNU gettext package, with some subtleties. */ +/* The macro HAVE_GETTEXT has to be set in the makefile. */ +#ifdef HAVE_GETTEXT +#define HAVE_LOCALE_H +#define HAVE_LIBINTL_H +#define HAVE_LIBINTL +#define LOCALEDIR "/usr/djgpp/share/locale" +/* Due to a name conflict, gettext is renamed gettext__ in DJGPP */ +#define gettext( str ) gettext__( str ) +#endif + +/* command.com can't pipe stderr into a file; any message would be */ +/* written into the graphics screen. */ +#define HAVE_PRINT_FUNCTION 1 + +#define Print( format, ap ) vfprintf( stdout, (format), (ap) ) + +/* The number of bytes in a int. We use the ANSI header file limits.h */ +/* for determining it since there is no easy way to guess. */ +#include <limits.h> +#if UINT_MAX == 0xFFFF +#define SIZEOF_INT 2 +#elif UINT_MAX == 0xFFFFFFFF +#define SIZEOF_INT 4 +#else +#error "Unsupported number of bytes in `int' type!" +#endif + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/msdos/hugefile.c b/Build/source/libs/libttf/arch/msdos/hugefile.c new file mode 100644 index 00000000000..901e0d6eae5 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/hugefile.c @@ -0,0 +1,84 @@ +/******************************************************************* + * + * hugefile.c + * + * File I/O Component (body) for dealing with "huge" objects under + * MS-DOS. Relies on the "default" version, with a small hook. + * + * Written by Antoine Leca based on ideas from Dave Hoo. + * Copyright 1999 by Dave Hoo, Antoine Leca, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTE + * + * This file #includes the normal version, to avoid discrepancies + * between versions. It uses only ANSI-mandated "tricks", so + * any ANSI-compliant compiler should be able to compile this file. + * + ******************************************************************/ + +#include "ttconfig.h" +#include "tttypes.h" + +/* Here we include <stdio.h>, to have the proper definition of fread */ +#include <stdio.h> + +/* Then, we divert the use of fread to our version */ +#undef fread +#define fread(ptr, size, n, stream) huge_fread(ptr, size, n, stream) + + LOCAL_FUNC + Long huge_fread ( void *ptr, size_t size, Long n, FILE *stream ); + +/* Now, we include the "normal" version of ttfile.c */ +/* The ANSI/ISO standard mandates that the include of <stdio.h> */ +/* there have no bad effects. */ +#include "ttfile.c" + +/* Then, we define our implementation of fread that makes use of */ +/* "huge"-allocated memory. */ + +/******************************************************************* + * + * Function : huge_fread + * + * Description : replacement version of fread that handles + * "huge"-allocated memory. + * + * Input : See the reference for the runtime library function fread + * + * Output : See the reference for the runtime library function fread + * + * Notes : + * + ******************************************************************/ + + LOCAL_DEF + Long huge_fread ( void *ptr, size_t size, Long n, FILE *stream ) + { + char TT_HUGE_PTR * p = (char TT_HUGE_PTR *) ptr; + ULong left = (ULong)n * size; + size_t toRead; + + while ( left ) + { + toRead = (left > 0x8000) ? 0x8000 : left; + if ( (fread)( p, 1, toRead, stream ) != toRead) + return -1; + else + { + left -= (ULong) toRead; + p += toRead; + } + } + return n * size; + } + + +/* END */ diff --git a/Build/source/libs/libttf/arch/msdos/hugemem.c b/Build/source/libs/libttf/arch/msdos/hugemem.c new file mode 100644 index 00000000000..aa44c69f01f --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/hugemem.c @@ -0,0 +1,496 @@ +/******************************************************************* + * + * hugemem.c + * + * Memory management component (body) + * for dealing with "huge" objects with 16-bit MS-DOS. + * + * Written by Dave Hoo and Antoine Leca. + * Copyright 1999 by Dave Hoo, Antoine Leca, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include <limits.h> + +#include "ttdebug.h" +#include "ttmemory.h" +#include "ttengine.h" + +#ifndef TT_HUGE_PTR +#error "This component needs TT_HUGE_PTR to be #defined." +#endif + +/* ---- Microsoft C compilers support ------------------------------------ */ + +#if defined( M_I86 ) || defined( _M_I86 ) + +#include <malloc.h> +#define huge_alloc( size ) _halloc ( size, 1 ) +#define huge_free( block ) _hfree ( block ) + +#endif /* Microsoft compilers */ + +/* ---- Borland C compiler support --------------------------------------- */ + +#ifdef __TURBOC__ + +#include <alloc.h> +#define huge_alloc( size ) farmalloc ( size ) +#define huge_free( block ) farfree ( block ) + +#endif + +#if !defined( huge_alloc ) || !defined( huge_free ) +#error "Your compiler is not (yet) supported. Check the source file!" +#endif + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE +#error "This component needs static allocation and is not re-entrant." +#endif + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_memory + + +#ifdef DEBUG_MEMORY + +#include <stdio.h> + +#define MAX_TRACKED_BLOCKS 1024 + + struct TMemRec_ + { + void* base; + Long size; + }; + + typedef struct TMemRec_ TMemRec; + + static TMemRec pointers[MAX_TRACKED_BLOCKS + 1]; + + static Int num_alloc; + static Int num_free; + static Int num_realloc; /* counts only `real' reallocations + (i.e., an existing buffer will be resized + to a value larger than zero */ + + static Int fail_alloc; + static Int fail_realloc; + static Int fail_free; + +#else + + /* We need a tracing stack of the calls to big chunks of memory, */ + /* in order to call the matching version of free(). */ + +#define MAX_TRACKED_BIGCHUNKS 16 + + struct TMemRec_ + { + void* base; + Long size; + }; + + typedef struct TMemRec_ TMemRec; + + static TMemRec pointers[MAX_TRACKED_BIGCHUNKS + 1]; + +#endif /* DEBUG_MEMORY */ + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + Long TTMemory_Allocated; + Long TTMemory_MaxAllocated; +#endif + + +/******************************************************************* + * + * Function : TT_Alloc + * + * Description : Allocates memory from the heap buffer. + * + * Input : Size size of the memory to be allocated + * P pointer to a buffer pointer + * + * Output : Error code. + * + * NOTE : The newly allocated block should _always_ be zeroed + * on return. Many parts of the engine rely on this to + * work properly. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Alloc( ULong Size, void** P ) + { + Int i; + + + if ( !P ) + return TT_Err_Invalid_Argument; + /* Also see below for another case of "invalid argument". */ + + if ( Size > 0 ) + { + if ( Size > ( UINT_MAX & ~0xFu ) ) + *P = (void*)huge_alloc( Size ); + else + *P = (void*)malloc( Size ); + if ( !*P ) + return TT_Err_Out_Of_Memory; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated += Size; + TTMemory_MaxAllocated += Size; +#endif + +#ifdef DEBUG_MEMORY + + num_alloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_alloc++; + else + { + pointers[i].base = *P; + pointers[i].size = Size; + } + +#else + + if ( Size > ( UINT_MAX & ~0xFu ) ) + { + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BIGCHUNKS ) + /* We fail badly here. Increase MAX_TRACKED_BIGCHUNKS if needed. */ + return TT_Err_Invalid_Argument; + else + { + pointers[i].base = *P; + pointers[i].size = Size; + } + } + +#endif /* DEBUG_MEMORY */ + + if ( Size > ( UINT_MAX & ~0xFu ) ) + { + char TT_HUGE_PTR * p = (char TT_HUGE_PTR *) *P; + ULong left = (ULong)Size; + size_t toClear; + + while ( left ) + { + toClear = (left > 0xFF00) ? 0xFF00 : left; + MEM_Set( p, 0, toClear ); + left -= (ULong) toClear; + p += toClear; + } + } + else + MEM_Set( *P, 0, Size ); + } + else + *P = NULL; + + return TT_Err_Ok; + } + + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + +/******************************************************************* + * + * Function : TT_Realloc + * + * Description : Reallocates memory from the heap buffer. + * + * Input : Size new size of the memory to be allocated; + * if zero, TT_Free() will be called + * P pointer to a buffer pointer; if *P == NULL, + * TT_Alloc() will be called + * + * Output : Error code. + * + * NOTES : It's not necessary to zero the memory in case the + * reallocated buffer is larger than before -- the + * application has to take care of this. + * + * If the memory request fails, TT_Free() will be + * called on *P, and TT_Err_Out_Of_Memory returned. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Realloc( ULong Size, void** P ) + { + void* Q; + +#ifdef DEBUG_MEMORY + Int i; +#endif + + + if ( !P ) + return TT_Err_Invalid_Argument; + + if ( !*P ) + return TT_Alloc( Size, P ); + + if ( Size == 0 ) + return TT_Free( P ); + + if ( Size > ( UINT_MAX & ~0xFu ) ) + Q = NULL; /* Do not even try to deal with big chunks of memory. */ + else + Q = (void*)realloc( *P, Size ); + if ( !Q ) + { + TT_Free( *P ); + return TT_Err_Out_Of_Memory; + } + +#ifdef DEBUG_MEMORY + + num_realloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_realloc++; + else + { +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated += Size - pointers[i].size; + if ( Size > pointers[i].size ) + TTMemory_MaxAllocated += Size - pointers[i].size; +#endif + + pointers[i].base = Q; + pointers[i].size = Size; + } +#endif /* DEBUG_MEMORY */ + + *P = Q; + + return TT_Err_Ok; + } + + +#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE */ + + +/******************************************************************* + * + * Function : TT_Free + * + * Description : Releases a previously allocated block of memory. + * + * Input : P pointer to memory block + * + * Output : Always SUCCESS. + * + * Note : The pointer must _always_ be set to NULL by this function. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Free( void** P ) + { + Int i; + Long Size = 0; + + + if ( !P || !*P ) + return TT_Err_Ok; + +#ifdef DEBUG_MEMORY + + num_free++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_free++; + else + { +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated -= pointers[i].size; +#endif + + Size = pointers[i].size; + pointers[i].base = NULL; + pointers[i].size = 0; + } + +#else + + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != *P ) + i++; + + /* If we did not found the pointer, then this is a "small" chunk. */ + + if ( i < MAX_TRACKED_BIGCHUNKS ) + { + Size = pointers[i].size; + pointers[i].base = NULL; + pointers[i].base = NULL; + } + +#endif /* DEBUG_MEMORY */ + + if ( Size > ( UINT_MAX & ~0xFu ) ) + huge_free( *P ); + else + free( *P ); + + *P = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Init + * + * Description : Initializes the memory. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Init( void ) + { +#ifdef DEBUG_MEMORY + Int i; + + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + pointers[i].base = NULL; + pointers[i].size = 0; + } + + num_alloc = 0; + num_realloc = 0; + num_free = 0; + + fail_alloc = 0; + fail_realloc = 0; + fail_free = 0; +#else + Int i; + + for ( i = 0; i < MAX_TRACKED_BIGCHUNKS; i++ ) + { + pointers[i].base = NULL; + pointers[i].size = 0; + } +#endif + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated = 0; + TTMemory_MaxAllocated = 0; +#endif + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Done + * + * Description : Finalizes memory usage. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Done( void ) + { +#ifdef DEBUG_MEMORY + Int i, num_leaked, tot_leaked; + + + num_leaked = 0; + tot_leaked = 0; + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + num_leaked ++; + tot_leaked += pointers[i].size; + } + } + + fprintf( stderr, + "%d memory allocations, of which %d failed\n", + num_alloc, + fail_alloc ); + + fprintf( stderr, + "%d memory reallocations, of which %d failed\n", + num_realloc, + fail_realloc ); + + fprintf( stderr, + "%d memory frees, of which %d failed\n", + num_free, + fail_free ); + + if ( num_leaked > 0 ) + { + fprintf( stderr, + "There are %d leaked memory blocks, totalizing %d bytes\n", + num_leaked, tot_leaked ); + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + fprintf( stderr, + "index: %4d (base: $%08lx, size: %08ld)\n", + i, + (long)pointers[i].base, + pointers[i].size ); + } + } + } + else + fprintf( stderr, "No memory leaks !\n" ); + +#endif /* DEBUG_MEMORY */ + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/arch/msdos/makedep b/Build/source/libs/libttf/arch/msdos/makedep new file mode 100644 index 00000000000..d566ed84243 --- /dev/null +++ b/Build/source/libs/libttf/arch/msdos/makedep @@ -0,0 +1,26 @@ +# makedep +# +# This shell script creates a dependency file necessary for older compilers +# on the MS-DOS platform. + +echo "\ +# This dependency file to be used with various MS-DOS compilers +# has been generated automatically with the script \`makedep' on +# `date +%d-%b-%Y`. +" > depend.dos + +(cd ../.. + gcc -MM -Iarch/msdos -I. *.c | \ + sed -e "s/\.o:/.obj:/" -e "s:/:\\\\:g") >> depend.dos + +(cd ../.. + gcc -MM -Iarch/msdos -I. -Iextend extend/*.c | \ + sed -e "s/^\(.*\)\.o:/extend\\\\\1.obj:/" -e "s:/:\\\\:g") >> depend.dos + +(cd ../.. + gcc -MM -Iarch/msdos -I. -Iextend \ + -DTT_HUGE_PTR -Dhuge_alloc -Dhuge_free arch/msdos/*.c | \ + sed -e "s/^\(.*\)\.o:/arch\\\\msdos\\\\\1.obj:/" \ + -e "s:/:\\\\:g") >> depend.dos + +# eof diff --git a/Build/source/libs/libttf/arch/os2/Makefile.dm b/Build/source/libs/libttf/arch/os2/Makefile.dm new file mode 100644 index 00000000000..a5c18f714a5 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/Makefile.dm @@ -0,0 +1,84 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for emx-gcc under OS/2 +# +# You will need dmake. +# +# Use this file while in the lib directory with the following statement: +# +# dmake -r -f arch/os2/Makefile.dm + +ARCH = arch/os2 +FT_MAKEFILE = $(ARCH)/Makefile.dm +FT_MAKE = dmake -r + +.IMPORT: COMSPEC +SHELL := $(COMSPEC) +SHELLFLAGS := /c +GROUPSHELL := $(SHELL) +GROUPFLAGS := $(SHELLFLAGS) +GROUPSUFFIX := .cmd +SHELLMETAS := *"?<>&| + +CC = gcc + +CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend +# CFLAGS = -Wall -ansi -O2 -s -I$(ARCH) -I. -Iextend + +TTFILE = $(ARCH)/os2file.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxopen.c \ + extend/ftxgdef.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M libttf.a + + +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) $(CFLAGS) -c -o $@ $(SRC_S) + + +libttf.a: $($(LIB_FILES)) + +-del $@ + ar src $@ @$(mktmp $(<:t"\n")\n) + +clean: + -+del $(subst,/,\ $($(LIB_FILES))) + +distclean: clean + -+del dep.end libttf.a + +# depend: $(SRC_S) $(SRC_M) $(SRC_X) +# $(CC) -E -M @$(mktmp $(<:t"\n")\n) > dep.end + +# ifeq (dep.end,$(wildcard dep.end)) +# include dep.end +# endif + +# end of Makefile.dm diff --git a/Build/source/libs/libttf/arch/os2/Makefile.emx b/Build/source/libs/libttf/arch/os2/Makefile.emx new file mode 100644 index 00000000000..4ba9128def7 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/Makefile.emx @@ -0,0 +1,91 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for emx-gcc under OS/2. +# +# You will need GNU make. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/os2/Makefile.emx + +ARCH = arch/os2 +FT_MAKEFILE = $(ARCH)/Makefile.emx + +CC = gcc + +#CFLAGS = -W -Wall -O0 -g -ansi -pedantic -I$(ARCH) -I. -Iextend + +CFLAGS = -Wall -O3 -fno-inline -fomit-frame-pointer \ + -g -ansi -pedantic -I$(ARCH) -I. -Iextend + +#CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend + +TTFILE = $(ARCH)/os2file.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxopen.c \ + extend/ftxgdef.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + +SRCD_S = $(ARCH)/freetypd.c +OBJD_S = $(SRCD_S:.c=.o) +OBJDS_S = $(OBJD_S) $(OBJS_X) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M libttf.a + +debugger: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJDS_S libttfd.a + +$(OBJ_S): $(SRC_S) $(SRC_M) +$(OBJD_S): $(SRCD_S) $(SRC_M) + +libttf.a: $($(LIB_FILES)) + -del $@ + ar src $@ $^ + +libttfd.a: $(OBJDS) + +libttfd.a: $(OBJDS) + -del $@ + ar src $@ $^ + +clean: + -del $(subst /,\,$(OBJS_S)) + -del $(subst /,\,$(OBJS_M)) + +distclean: clean + -del dep.end + -del libttf.a + +depend: $(SRC_S) $(SRC_M) $(SRC_X) + $(CC) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile.emx diff --git a/Build/source/libs/libttf/arch/os2/Makefile.icc b/Build/source/libs/libttf/arch/os2/Makefile.icc new file mode 100644 index 00000000000..e633c8d9408 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/Makefile.icc @@ -0,0 +1,73 @@ +# This file is part of the FreeType project. +# +# It builds the library and test programs for IBM VisualAge C++ under OS/2. +# +# You will need nmake. +# +# Use this file while in the lib directory with the following statement: +# +# nmake -f arch\os2\Makefile.icc +# + +ARCH = arch\os2 +FT_MAKEFILE = $(ARCH)\Makefile.icc +FT_MAKE = $(MAKE) -nologo + +CC = icc +CFLAGS = -O+ -Ti- -Tm- -Sa -W3 -Wpro- -Wcnd- -Q+ -Iarch\os2 -I. -Iextend + +# NOTE: Optimizations are discarded, as it seems that Visual Age +# is buggy when producing ttraster.obj. The resulting code +# crashes under some circumstances (performing vertical dropout +# control when rendering smoothed outlines)! + +TTFILE = $(ARCH)\os2file.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c \ + extend\ftxcmap.c extend\ftxwidth.c extend\ftxsbit.c \ + extend\ftxgsub.c extend\ftxgpos.c extend\ftxopen.c \ + extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c \ + ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +all: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJS_S)" libttf.lib + +debug: + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJS_M)" libttf.lib + + +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) -C $(CFLAGS) /Fo$@ $*.c + +$(OBJS_X): + $(CC) -C $(CFLAGS) /Fo$@ $*.c + +$(ARCH)\os2file.obj: + $(CC) -C $(CFLAGS) /Fo$@ $*.c + +libttf.lib: $(LIB_FILES) + !ilib /nologo /noignorecase /nobackup $@ +$?,, + +clean: + -del *.obj + -del extend\*.obj + -del arch\os2\*.obj + +distclean: clean + -del libttf.lib + +# end of Makefile.icc diff --git a/Build/source/libs/libttf/arch/os2/Makefile.wat b/Build/source/libs/libttf/arch/os2/Makefile.wat new file mode 100644 index 00000000000..4fe8adff09c --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/Makefile.wat @@ -0,0 +1,88 @@ +# This file is part of the FreeType project. +# +# This builds the Watcom library with Watcom's wcc386 under OS/2. +# +# You'll need Watcom's wmake. +# +# +# Invoke by "wmake -f arch\os2\Makefile.wat" when in the "lib" directory +# +# This will build "freetype\lib\libttf.lib" + +ARCH = arch\os2 +FT_MAKEFILE = $(ARCH)\Makefile.wat +FT_MAKE = wmake -h + + +.EXTENSIONS: +.EXTENSIONS: .lib .obj .c .h +.obj:.;.\extend;.\$(ARCH) +.c:.;.\extend;.\$(ARCH) +.h:.;.\extend;.\$(ARCH) + +CC = wcc386 + +CCFLAGS = /otexanl+ /s /w5 /zq -Iarch\os2 -I. -Iextend + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +TTFILE_OBJ = ttfile.obj +TTMEMORY_OBJ = ttmemory.obj +TTMUTEX_OBJ = ttmutex.obj + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) +PORT_OBJS = $(TTFILE_OBJ) $(TTMEMORY_OBJ) $(TTMUTEX_OBJ) + +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c & + extend\ftxcmap.c extend\ftxwidth.c extend\ftxsbit.c & + extend\ftxgsub.c extend\ftxgpos.c extend\ftxopen.c & + extend\ftxgdef.c + +OBJS_X = extend\ftxgasp.obj extend\ftxkern.obj extend\ftxpost.obj & + extend\ftxcmap.obj extend\ftxwidth.obj extend\ftxsbit.obj & + extend\ftxgsub.obj extend\ftxgpos.obj extend\ftxopen.obj & + extend\ftxgdef.obj + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c & + ttgload.c ttinterp.c ttload.c ttobjs.c & + ttraster.c ttextend.c $(PORT) + +OBJS_M = ttapi.obj ttcache.obj ttcalc.obj ttcmap.obj & + ttgload.obj ttinterp.obj ttload.obj ttobjs.obj & + ttraster.obj ttextend.obj $(PORT_OBJS) $(OBJS_X) + +SRC_S = freetype.c +OBJ_S = freetype.obj +OBJS_S = $(OBJ_S) $(OBJS_X) + + +.c.obj: + $(CC) $(CCFLAGS) $[* /fo=$[*.obj + +all: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) libttf.lib + +debug: .symbolic + $(FT_MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJS_M)" libttf.lib + + +libttf.lib: $(OBJS_M) + wlib -q -n libttf.lib $(OBJS_M) + +# is this correct? Know nothing about wmake and the Watcom compiler... +$(OBJ_S): $(SRC_S) $(SRC_M) + $(CC) $(CCFLAGS) $(SRC_S) /fo=$(OBJ_S) + +clean: .symbolic + @-erase $(OBJS_M) + @-erase *.err + +distclean: .symbolic clean + @-erase libttf.lib + +new: .symbolic + @-wtouch *.c + +# end of Makefile.wat diff --git a/Build/source/libs/libttf/arch/os2/freetype.c b/Build/source/libs/libttf/arch/os2/freetype.c new file mode 100644 index 00000000000..7a115cff672 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/freetype.c @@ -0,0 +1,32 @@ +/* This file is part of the FreeType project */ + +/* Single file library component for OS/2 */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#include "os2file.c" +#include "ttmemory.c" +#include "ttmutex.c" + +/* the extensions are compiled separately, but we need to */ +/* include the file ttextend.c if we want to support them */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + +/* END */ diff --git a/Build/source/libs/libttf/arch/os2/ft_conf.h b/Build/source/libs/libttf/arch/os2/ft_conf.h new file mode 100644 index 00000000000..c7026c711e2 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/ft_conf.h @@ -0,0 +1,239 @@ +/******************************************************************* + * + * ft_conf.h (OS/2 version) + * + * High-level interface specification. + * + * Copyright 1996-1998 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This file is used to contain the definition of several + * configuration-specific macros. + * + ******************************************************************/ + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + + +/**********************************************************************/ +/* */ +/* We begin by a series of macros that are automatically set by the */ +/* 'configure' script on Unix. They must be set manually on OS/2, */ +/* so here they are : */ +/* */ +/**********************************************************************/ + +#define OS2 + +/* Define to empty if the keyword "const" does not work. */ +/* #undef const */ + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you need <conio.h> for console I/O functions. */ +#if defined(__EMX__) || defined(__IBMC__) +#define HAVE_CONIO_H +#endif + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/os2/os2file.c b/Build/source/libs/libttf/arch/os2/os2file.c new file mode 100644 index 00000000000..e6003fd4dd3 --- /dev/null +++ b/Build/source/libs/libttf/arch/os2/os2file.c @@ -0,0 +1,1237 @@ +/******************************************************************* + * + * os2file.c (OS2 version) 2.1 + * + * File I/O Component (body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTES: + * + * This implementation relies on the OS/2 file API. It was provided + * by the PM FreeType DLL author, Michal Necasek. + * + ******************************************************************/ + +#include "ttconfig.h" + +#include <os2.h> /* !Mike! */ + +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "freetype.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttengine.h" +#include "ttmutex.h" +#include "ttmemory.h" +#include "ttfile.h" /* our prototypes */ + + +/* For now, we don't define additional error messages in the core library */ +/* to report open-on demand errors. Define these errors as standard ones. */ + +#define TT_Err_Could_Not_ReOpen_File TT_Err_Could_Not_Open_File +#define TT_Err_Could_Not_ReSeek_File TT_Err_Could_Not_Open_File + + + /* This definition is mandatory for each file component! */ + EXPORT_FUNC + const TFileFrame TT_Null_FileFrame = { NULL, 0, 0 }; + + +/* It has proven useful to do some bounds checks during development phase. */ +/* They should probably be undefined for speed reasons in a later release. */ + +#if 0 +#define CHECK_FRAME( frame, n ) \ + do { \ + if ( frame.cursor + n > frame.address + frame.size ) \ + Panic( "Frame boundary error!\n" ); \ + } while ( 0 ) +#else +#define CHECK_FRAME( frame, n ) \ + do { \ + } while ( 0 ) +#endif + + + /* Because a stream can be flushed, i.e., its file handle can be */ + /* closed to save system resources, we must keep the stream's file */ + /* pathname to be able to re-open it on demand when it is flushed. */ + + struct _TStream_Rec + { + Bool opened; /* is the stream handle opened ? */ + String* name; /* the file's pathname */ + Long position; /* current pos. within the file */ + + HFILE file; /* file handle !Mike! */ + Long base; /* stream base in file */ + Long size; /* stream size in file */ + }; + + typedef struct _TStream_Rec TStream_Rec; + typedef TStream_Rec* PStream_Rec; + + + /* We support embedded TrueType files by allowing them to be */ + /* inside any file, at any location, hence the 'base' argument. */ + /* Note, however, that the current implementation does not allow you */ + /* to specify a 'base' index when opening a file. */ + /* (will come later) */ + /* I still don't know if this will turn out useful... - DavidT */ + +#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) ) + + static TT_Error Stream_Activate ( PStream_Rec stream ); + static TT_Error Stream_Deactivate( PStream_Rec stream ); + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /**** ****/ + /**** N O N R E E N T R A N T I M P L E M E N T A T I O N ****/ + /**** ****/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* In non-reentrant builds, we allocate a single block where we'll */ + /* place all the frames smaller than FRAME_CACHE_SIZE, rather than */ + /* allocating a new block on each access. Bigger frames will be */ + /* malloced normally in the heap. */ + /* */ + /* See TT_Access_Frame() and TT_Forget_Frame() for details. */ + +#define FRAME_CACHE_SIZE 2048 + + /* The TFile_Component structure holds all the data that was */ + /* previously declared static or global in this component. */ + /* */ + /* It is accessible through the 'engine.file_component' */ + /* variable in re-entrant builds, or directly through the */ + /* static 'files' variable in other builds. */ + + struct _TFile_Component + { + TMutex lock; /* used by the thread-safe build only */ + Byte* frame_cache; /* frame cache */ + PStream_Rec stream; /* current stream */ + TFileFrame frame; /* current frame */ + }; + + typedef struct _TFile_Component TFile_Component; + + static TFile_Component files; + +#define CUR_Stream files.stream +#define CUR_Frame files.frame + +#define STREAM_VARS /* void */ +#define STREAM_VAR /* void */ + +/* The macro CUR_Stream denotes the current input stream. */ +/* Note that for the re-entrant version, the 'stream' name has been */ +/* chosen according to the macro STREAM_ARGS. */ + +/* The macro CUR_Frame denotes the current file frame. */ +/* Note that for the re-entrant version, the 'frame' name has been */ +/* chosen according to the macro FRAME_ARGS. */ + +/* The macro STREAM_VAR is used when calling public functions */ +/* that need an 'optional' stream argument. */ + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + TT_Error error; + + MUTEX_Create( files.lock ); + files.stream = NULL; + ZERO_Frame( files.frame ); + + if ( ALLOC( files.frame_cache, FRAME_CACHE_SIZE ) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + FREE( files.frame_cache ); + MUTEX_Destroy( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream org_stream, + TT_Stream* stream ) + { + MUTEX_Lock( files.lock ); /* lock file mutex */ + + *stream = org_stream; /* copy the stream */ + files.stream = STREAM2REC( org_stream ); /* set current stream */ + + Stream_Activate( files.stream ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream target stream + * + * Output : Error code. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + HANDLE_Set( *stream, NULL ); + MUTEX_Release( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( size <= FRAME_CACHE_SIZE ) + { + /* use the cache */ + CUR_Frame.address = files.frame_cache; + CUR_Frame.size = FRAME_CACHE_SIZE; + } + else + { + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + } + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + if ( size > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + CUR_Frame.address = NULL; + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * `size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function truncates `size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + Long readBytes, requested; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( size <= FRAME_CACHE_SIZE ) + { + /* use the cache */ + CUR_Frame.address = files.frame_cache; + CUR_Frame.size = FRAME_CACHE_SIZE; + } + else + { + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + } + + requested = size; + readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR ); + if ( size > readBytes ) + size = readBytes; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + if ( requested > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + CUR_Frame.address = NULL; + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + if ( CUR_Frame.size > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + + ZERO_Frame( CUR_Frame ); + + return TT_Err_Ok; + } + + +#else /* TT_CONFIG_OPTION_THREAD_SAFE */ + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /******** ********/ + /******** R E E N T R A N T I M P L E M E N T A T I O N ********/ + /******** ********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/* a simple macro to access the file component's data */ +#define files ( *((TFile_Component*)engine.file_component) ) + +#define CUR_Stream STREAM2REC( stream ) /* re-entrant macros */ +#define CUR_Frame (*frame) + +#define STREAM_VARS stream, +#define STREAM_VAR stream + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Duplicates a stream for a new usage. + * + * Input : input_stream source stream to duplicate + * copy address of target duplicate stream + * + * Output : error code. + * The target stream is set to NULL in case of failure. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream input_stream, + TT_Stream* copy ) + { + PStream_Rec rec = STREAM2REC( input_stream ); + + return TT_Open_Stream( rec->name, copy ); + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream target stream + * + * Output : + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + return TT_Close_Stream( stream ); + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS int size ) + { + TT_Error error; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + FREE( CUR_Frame.address ); + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * `size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function truncates `size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS int size ) + { + TT_Error error; + Long readBytes; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + + readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR ); + if ( size > readBytes ) + size = readBytes; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + FREE( CUR_Frame.address ); + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + FREE( CUR_Frame.address ); + ZERO_Frame( CUR_Frame ); + + return TT_Err_Ok; + } + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /*********** ***********/ + /*********** C O M M O N I M P L E M E N T A T I O N ***********/ + /*********** ***********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/******************************************************************* + * + * Function : Stream_Activate + * + * Description : activates a stream, this will either: + * - open a new file handle if the stream is closed + * - move the stream to the head of the linked list + * + * Input : stream the stream to activate + * + * Output : error condition. + * + * Note : this function is also called with fresh new streams + * created by TT_Open_Stream(). They have their 'size' + * field set to -1. + * + ******************************************************************/ + + static TT_Error Stream_Activate( PStream_Rec stream ) + { + ULONG ulAction; /* !Mike! */ + + if ( !stream->opened ) + { +#if 0 + if ( !(stream->file = fopen( stream->name, "rb" )) ) /* !Mike! */ +#endif + +/* XXX : Strange. GCC/EMX wants an (Byte*) for the file name? */ +#ifdef __EMX__ + + if ( DosOpen( (Byte*)stream->name, &(stream->file), + &ulAction, 0, + 0, OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL ) ) + return TT_Err_Could_Not_ReOpen_File; + +#else + + if ( DosOpen( stream->name, &(stream->file), + &ulAction, 0, + 0, OPEN_ACTION_OPEN_IF_EXISTS, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL ) ) + return TT_Err_Could_Not_ReOpen_File; + +#endif /* __EMX__ */ + + stream->opened = TRUE; + + /* A newly created stream has a size field of -1 */ + if ( stream->size < 0 ) + { +#if 0 + fseek( stream->file, 0, SEEK_END ); /* !Mike! */ + stream->size = ftell( stream->file ); +#endif + + DosSetFilePtr( stream->file, 0, FILE_END, (ULONG *)&(stream->size) ); +#if 0 + fseek( stream->file, 0, SEEK_SET ); +#endif + + DosSetFilePtr( stream->file, 0, FILE_BEGIN, &ulAction ); + } + + /* Reset cursor in file */ + if ( stream->position ) + { +#if 0 /* !Mike! */ + if ( fseek( stream->file, stream->position, SEEK_SET ) != 0 ) +#endif + + if ( DosSetFilePtr( stream->file, stream->position, + FILE_BEGIN, &ulAction ) ) + { + /* error during seek */ +#if 0 + fclose( stream->file ); /* !Mike! */ +#endif + + DosClose( stream->file ); + stream->opened = FALSE; + return TT_Err_Could_Not_ReSeek_File; + } + } + } + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Stream_DeActivate + * + * Description : deactivates a stream, this will: + * - close its file handle if it was opened + * - remove it from the opened list if necessary + * + * Input : stream the stream to deactivate + * + * Output : Error condition + * + * Note : the function is called whenever a stream is deleted + * (_not_ when a stream handle's is closed due to an + * activation). However, the stream record isn't + * destroyed by it... + * + ******************************************************************/ + + static TT_Error Stream_Deactivate( PStream_Rec stream ) + { + if ( stream->opened ) + { + /* Save its current position within the file */ +#if 0 + stream->position = ftell( stream->file ); /* !Mike! */ +#endif + + DosSetFilePtr( stream->file, 0, FILE_CURRENT, + (ULONG *)&(stream->position) ); +#if 0 + fclose( stream->file ); /* !Mike! */ +#endif + + DosClose( stream->file ); + stream->file = 0; + stream->opened = FALSE; + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Stream_Size + * + * Description : Returns the length of a given stream, even if it + * is flushed. + * + * Input : stream the stream + * + * Output : length of stream in bytes. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Stream_Size( TT_Stream stream ) + { + PStream_Rec rec = STREAM2REC( stream ); + + + if ( rec ) + return rec->size; + else + return 0; /* invalid stream - return 0 */ + } + + +/******************************************************************* + * + * Function : TT_Open_Stream + * + * Description : Opens the font file and saves the total file size. + * + * Input : error address of stream's error variable + * (re-entrant build only) + * filepathname pathname of the file to open + * stream address of target TT_Stream structure + * + * Output : SUCCESS on sucess, FAILURE on error. + * The target stream is set to -1 in case of failure. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Open_Stream( const String* filepathname, + TT_Stream* stream ) + { + int len; + TT_Error error; + PStream_Rec stream_rec; + + + if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) ) + return error; + + stream_rec = STREAM2REC( *stream ); + + stream_rec->file = NULLHANDLE; /* !Mike! */ + stream_rec->size = -1; + stream_rec->base = 0; + stream_rec->opened = FALSE; + stream_rec->position = 0; + + len = strlen( filepathname ) + 1; + if ( ALLOC( stream_rec->name, len ) ) + goto Fail; + + strncpy( (String*)stream_rec->name, filepathname, len ); + + error = Stream_Activate( stream_rec ); + if ( error ) + goto Fail_Activate; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + CUR_Stream = stream_rec; +#endif + + return TT_Err_Ok; + + Fail_Activate: + FREE( stream_rec->name ); + Fail: + FREE( stream_rec ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Close_Stream + * + * Description : Closes a stream. + * + * Input : stream address of target TT_Stream structure + * + * Output : SUCCESS (always). + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Close_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + Stream_Deactivate( rec ); + FREE( rec->name ); + FREE( rec ); + + HANDLE_Set( *stream, NULL ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Flush_Stream + * + * Description : Flushes a stream, i.e., closes its file handle. + * + * Input : stream address of target TT_Stream structure + * + * Output : Error code + * + * NOTE : Never flush the current opened stream. This means that + * you should _never_ call this function between a + * TT_Use_Stream() and a TT_Done_Stream()! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Flush_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + if ( rec ) + { + Stream_Deactivate( rec ); + return TT_Err_Ok; + } + else + return TT_Err_Invalid_Argument; + } + + +/******************************************************************* + * + * Function : TT_Seek_File + * + * Description : Seeks the file cursor to a different position. + * + * Input : position new position in file + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Seek_File( STREAM_ARGS long position ) + { + ULONG ibActual; /* !Mike! */ + + + position += CUR_Stream->base; + +#if 0 + if ( fseek( CUR_Stream->file, position, SEEK_SET ) ) /* !Mike! */ +#endif + + if ( DosSetFilePtr( CUR_Stream->file, position, FILE_BEGIN , &ibActual ) ) + return TT_Err_Invalid_File_Offset; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Skip_File + * + * Description : Skips forward the file cursor. + * + * Input : distance number of bytes to skip + * + * Output : see TT_Seek_File() + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Skip_File( STREAM_ARGS long distance ) + { + ULONG ibActual; /* !Mike! */ + + +#if 0 + return TT_Seek_File( STREAM_VARS ftell( CUR_Stream->file ) - + CUR_Stream->base + distance ); /* !Mike! */ +#endif + + DosSetFilePtr( CUR_Stream->file, 0, FILE_CURRENT, &ibActual ); + return TT_Seek_File( STREAM_VARS ibActual - CUR_Stream->base + distance ); + } + + +/******************************************************************* + * + * Function : TT_Read_File + * + * Description : Reads a chunk of the file and copies it to memory. + * + * Input : buffer target buffer + * count length in bytes to read + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_File( STREAM_ARGS void* buffer, long count ) + { + ULONG cbActual; /* !Mike! */ + +#if 0 /* !Mike! */ + if ( fread( buffer, 1, count, CUR_Stream->file ) != (unsigned long)count ) +#endif + + DosRead( CUR_Stream->file, buffer, count, &cbActual ); + if ( cbActual != (unsigned long)count ) + return TT_Err_Invalid_File_Read; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Read_At_File + * + * Description : Reads file at a specified position. + * + * Input : position position to seek to before read + * buffer target buffer + * count number of bytes to read + * + * Output : SUCCESS on success. FAILURE if error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_At_File( STREAM_ARGS long position, + void* buffer, + long count ) + { + TT_Error error; + + + if ( ( error = TT_Seek_File( STREAM_VARS position ) ) || + ( error = TT_Read_File( STREAM_VARS buffer, count ) ) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_File_Pos + * + * Description : Returns current file seek pointer. + * + * Input : none + * + * Output : current file position + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_File_Pos( STREAM_ARG ) + { + ULONG ibActual; /* !Mike! */ + + +#if 0 + return ftell( CUR_Stream->file ) - CUR_Stream->base; /* !Mike! */ +#endif + + DosSetFilePtr( CUR_Stream->file, 0, FILE_CURRENT, &ibActual ); + return ibActual - CUR_Stream->base; + } + + +/******************************************************************* + * + * Function : GET_Byte + * + * Description : Extracts a byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted Byte. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + Byte TT_Get_Byte( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Byte)(*CUR_Frame.cursor++); + } +#endif + +/******************************************************************* + * + * Function : GET_Char + * + * Description : Extracts a signed byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted char. + * + ******************************************************************/ + + EXPORT_FUNC + Char TT_Get_Char( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Char)(*CUR_Frame.cursor++); + } + + +/******************************************************************* + * + * Function : GET_Short + * + * Description : Extracts a short from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted short. + * + ******************************************************************/ + + EXPORT_FUNC + short TT_Get_Short( FRAME_ARG ) + { + short getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((short)CUR_Frame.cursor[0] << 8) | + (short)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } + + +/******************************************************************* + * + * Function : GET_UShort + * + * Description : Extracts an unsigned short from the frame. + * + * Input : None or current frame + * + * Output : Extracted ushort. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + unsigned short TT_Get_UShort( FRAME_ARG ) + { + unsigned short getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((unsigned short)CUR_Frame.cursor[0] << 8) | + (unsigned short)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } +#endif + +/******************************************************************* + * + * Function : GET_Long + * + * Description : Extracts a long from the frame. + * + * Input : None or current frame + * + * Output : Extracted long. + * + ******************************************************************/ + + EXPORT_FUNC + long TT_Get_Long( FRAME_ARG ) + { + long getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ((long)CUR_Frame.cursor[0] << 24) | + ((long)CUR_Frame.cursor[1] << 16) | + ((long)CUR_Frame.cursor[2] << 8 ) | + (long)CUR_Frame.cursor[3]; + + CUR_Frame.cursor += 4; + + return getlong; + } + + +/******************************************************************* + * + * Function : GET_ULong + * + * Description : Extracts an unsigned long from the frame. + * + * Input : None + * + * Output : Extracted ulong. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + unsigned long TT_Get_ULong( FRAME_ARG ) + { + unsigned long getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ( ((unsigned long)CUR_Frame.cursor[0] << 24) | + ((unsigned long)CUR_Frame.cursor[1] << 16) | + ((unsigned long)CUR_Frame.cursor[2] << 8 ) | + (unsigned long)CUR_Frame.cursor[3] ); + + CUR_Frame.cursor += 4; + + return getlong; + } +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/unix/Makefile.in b/Build/source/libs/libttf/arch/unix/Makefile.in new file mode 100644 index 00000000000..321cc7f8f72 --- /dev/null +++ b/Build/source/libs/libttf/arch/unix/Makefile.in @@ -0,0 +1,244 @@ +# This file is part of the FreeType project. +# +# lib/arch/unix/Makefile.in + +ARCH = arch/unix +FT_MAKEFILE = $(ARCH)/Makefile + +RM = @RM@ +RMF = @RM@ -f +RMDIR = @RMDIR@ +LN_S = @LN_S@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +VPATH = @srcdir@/../.. +srcdir = @srcdir@/../.. + +top_builddir=.. + +CC = @CC@ +CPP = @CPP@ + +LIBTOOL = $(top_builddir)/libtool +MKINSTALLDIRS = $(srcdir)/../mkinstalldirs + +version_info = @version_info@ + +include $(top_builddir)/MakeSub + +############### PORTABILITY COMPONENTS ######################## + +# location of memory component +MEMSRC = ttmemory.c + +# location of file component +FILESRC = @TT_FILE_COMPONENT@ + +# location of mutex component +MUTEXSRC = ttmutex.c + +# location of default extensions +FTEXTDIR = $(srcdir)/extend + + +# default extensions sources +EXTSRC = $(FTEXTDIR)/ftxkern.c \ + $(FTEXTDIR)/ftxgasp.c \ + $(FTEXTDIR)/ftxpost.c \ + $(FTEXTDIR)/ftxcmap.c \ + $(FTEXTDIR)/ftxsbit.c \ + $(FTEXTDIR)/ftxwidth.c \ + $(FTEXTDIR)/ftxerr18.c \ + $(FTEXTDIR)/ftxgsub.c \ + $(FTEXTDIR)/ftxgpos.c \ + $(FTEXTDIR)/ftxgdef.c \ + $(FTEXTDIR)/ftxopen.c + +EXTOBJ = ftxkern.lo \ + ftxgasp.lo \ + ftxpost.lo \ + ftxcmap.lo \ + ftxsbit.lo \ + ftxwidth.lo \ + ftxerr18.lo \ + ftxgsub.lo \ + ftxgpos.lo \ + ftxgdef.lo \ + ftxopen.lo + +# all engine sources +SRC_M = $(srcdir)/ttapi.c \ + $(srcdir)/ttcache.c \ + $(srcdir)/ttcalc.c \ + $(srcdir)/ttcmap.c \ + $(srcdir)/ttdebug.c \ + $(srcdir)/ttextend.c \ + $(srcdir)/ttgload.c \ + $(srcdir)/ttinterp.c \ + $(srcdir)/ttload.c \ + $(srcdir)/ttobjs.c \ + $(srcdir)/ttraster.c \ + $(srcdir)/$(FILESRC) \ + $(srcdir)/$(MEMSRC) \ + $(srcdir)/$(MUTEXSRC) +SRC_S = $(srcdir)/$(ARCH)/freetype.c + +# all header files +HEADERS = $(srcdir)/freetype.h \ + $(srcdir)/fterrid.h \ + $(srcdir)/ftnameid.h \ + $(FTEXTDIR)/ftxkern.h \ + $(FTEXTDIR)/ftxgasp.h \ + $(FTEXTDIR)/ftxcmap.h \ + $(FTEXTDIR)/ftxsbit.h \ + $(FTEXTDIR)/ftxpost.h \ + $(FTEXTDIR)/ftxwidth.h \ + $(FTEXTDIR)/ftxerr18.h \ + $(FTEXTDIR)/ftxgsub.h \ + $(FTEXTDIR)/ftxgpos.h \ + $(FTEXTDIR)/ftxgdef.h \ + $(FTEXTDIR)/ftxopen.h + +# all engine objects +OBJ_M = ttapi.lo \ + ttcache.lo \ + ttcalc.lo \ + ttcmap.lo \ + ttdebug.lo \ + ttextend.lo \ + ttgload.lo \ + ttinterp.lo \ + ttload.lo \ + ttobjs.lo \ + ttraster.lo \ + file.lo \ + memory.lo \ + mutex.lo \ + $(EXTOBJ) +OBJ_S = freetype.lo $(EXTOBJ) + + +# include paths +INCLUDES = -I. -I$(top_builddir) -I$(srcdir) -I$(FTEXTDIR) + +# C flags +CFLAGS = @CFLAGS@ @XX_CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +FT_CFLAGS = $(CFLAGS) $(INCLUDES) + +# linker flags +FT_LIBS = @LIBS@ + +# i18n stuff +LOCALEDIR = @LOCALEDIR@ + + +all: do_link + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJ_S)" libttf.la + +debug: do_link + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES="$(OBJ_M)" libttf.la + + +do_link: + -$(RMF) memory.c file.c mutex.c + $(LN_S) $(srcdir)/$(MEMSRC) memory.c + $(LN_S) $(srcdir)/$(FILESRC) file.c + $(LN_S) $(srcdir)/$(MUTEXSRC) mutex.c + + +.SUFFIXES: .lo +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $< + +ftxkern.lo: $(FTEXTDIR)/ftxkern.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxkern.c + +ftxgasp.lo: $(FTEXTDIR)/ftxgasp.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxgasp.c + +ftxpost.lo: $(FTEXTDIR)/ftxpost.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxpost.c + +ftxcmap.lo: $(FTEXTDIR)/ftxcmap.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxcmap.c + +ftxsbit.lo: $(FTEXTDIR)/ftxsbit.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxsbit.c + +ftxwidth.lo: $(FTEXTDIR)/ftxwidth.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxwidth.c + +ftxerr18.lo: $(FTEXTDIR)/ftxerr18.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) \ + -DLOCALEDIR='"$(LOCALEDIR)"' \ + $(FTEXTDIR)/ftxerr18.c + +ftxgsub.lo: $(FTEXTDIR)/ftxgsub.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxgsub.c + +ftxgpos.lo: $(FTEXTDIR)/ftxgpos.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxgpos.c + +ftxgdef.lo: $(FTEXTDIR)/ftxgdef.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxgdef.c + +ftxopen.lo: $(FTEXTDIR)/ftxopen.c + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) $(FTEXTDIR)/ftxopen.c + +freetype.lo: $(SRC_S) $(SRC_M) + $(LIBTOOL) --mode=compile $(CC) -c $(FT_CFLAGS) \ + -DLOCALEDIR='"$(LOCALEDIR)"' \ + -DTT_MAKE_OPTION_SINGLE_OBJECT \ + $(SRC_S) + +libttf.la: $(LIB_FILES) + $(LIBTOOL) --mode=link $(CC) -o libttf.la $(LIB_FILES) \ + -rpath $(libdir) \ + -version-info $(version_info) $(FT_LIBS) + +install: libttf.la + $(MKINSTALLDIRS) $(libdir) $(includedir)/freetype + $(LIBTOOL) --mode=install $(INSTALL) libttf.la $(libdir) + -for P in $(HEADERS) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype ; \ + done + +uninstall: + -$(LIBTOOL) --mode=uninstall $(RM) $(libdir)/libttf.la + -$(RMF) $(includedir)/freetype/* + -$(RMDIR) $(includedir)/freetype + +clean: + -$(RMF) $(OBJ_S) $(OBJ_M) *.o + +distclean: clean + -$(RMF) file.c memory.c mutex.c + -$(RMF) libttf.la + -$(RMF) *.orig *~ core *.core + -$(RMF) $(ARCH)/Makefile + -$(RMF) .libs/* + -$(RMDIR) .libs + +depend: do_link + (echo '/^#.* PUT NO STUFF BELOW/,$$d' ; echo w ; echo q) | \ + ed - $(ARCH)/Makefile + echo '# Dependencies generated by make depend: PUT NO STUFF BELOW' \ + >> $(ARCH)/Makefile + for file in $(SRC_S) $(SRC_M) $(EXTSRC) ; do \ + $(CPP) $(CPPFLAGS) $(INCLUDES) $$file | \ + sed -n -e 's|^# [1-9][0-9]* "\([^/].*\.h\)".*|\1|p' \ + -e 's|^# [1-9][0-9]* "\($(srcdir)/.*\.h\)".*|\1|p' | \ + sed -e 's|/\./|.|g' -e "s/^/`basename $$file .c`.lo: /" ; \ + done | \ + sort -u | \ + awk '{ if (LINE == 1) \ + { line = last = $$1 } \ + else if ($$1 != last) \ + { print line ; line = last = $$1 } \ + line = line " " $$2 } \ + END { print line }' >> $(ARCH)/Makefile + +# Dependencies generated by make depend: PUT NO STUFF BELOW diff --git a/Build/source/libs/libttf/arch/unix/freetype.c b/Build/source/libs/libttf/arch/unix/freetype.c new file mode 100644 index 00000000000..9a4860dbd2c --- /dev/null +++ b/Build/source/libs/libttf/arch/unix/freetype.c @@ -0,0 +1,27 @@ +/* This file is part of the FreeType project */ + +/* Single object library component for Unix */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* The Makefile creates proper links to following three files */ + +#include "file.c" +#include "memory.c" +#include "mutex.c" + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/unix/ttmmap.c b/Build/source/libs/libttf/arch/unix/ttmmap.c new file mode 100644 index 00000000000..aac7c1052e6 --- /dev/null +++ b/Build/source/libs/libttf/arch/unix/ttmmap.c @@ -0,0 +1,1027 @@ +/******************************************************************* + * + * ttmmap.c 2.0 + * + * Memory-Mapped file component ( replaces ttfile.c ). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Changes between 2.0 and 1.3 : + * + * - adopted new design/separation introduced in ttfile.c 2.0 + * + ******************************************************************/ + +#include "ttconfig.h" + +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <sys/mman.h> +#ifndef MAP_FILE +#define MAP_FILE 0x00 +#endif + +/* + * The prototype for munmap() is not provided on SunOS. This needs to + * have a check added later to see if the GNU C library is being used. + * If so, then this prototype is not needed. + */ +#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4) + extern int munmap( caddr_t addr, int len ); +#endif + +#include <sys/stat.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + + +#include "freetype.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttengine.h" +#include "ttmutex.h" +#include "ttmemory.h" +#include "ttfile.h" /* our prototypes */ + + /* This definition is mandatory for each file component! */ + EXPORT_FUNC + const TFileFrame TT_Null_FileFrame = { NULL, 0, 0 }; + + /* It has proven useful to do some bounds checks during */ + /* development phase. Define DEBUG_FILE when compiling */ + /* this component to enable them. */ + +#ifdef DEBUG_FILE +#define CHECK_FRAME( frame, n ) \ + do { \ + if ( frame.cursor + n > frame.address + frame.size ) \ + Panic( "Frame boundary error!\n" ); \ + } while ( 0 ) +#else +#define CHECK_FRAME( frame, n ) \ + do { \ + } while( 0 ) +#endif + + struct _TFileMap + { + String* base; /* base address of mapped file */ + Int refcount; /* reference count for mmaped region */ + Long size; /* stream size in file */ + Long offset; /* offset in file */ + }; + + typedef struct _TFileMap TFileMap; + +#define MAP_Address( map ) (Byte*)( (map)->base + (map)->offset ) + + /* The stream record structure */ + typedef struct _TStream_Rec + { + TFileMap* map; /* mapped file description */ + Long pos ; /* cursor in mapped file */ + } TStream_Rec; + + typedef TStream_Rec* PStream_Rec; + +#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) ) + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /**** ****/ + /**** N O N R E E N T R A N T I M P L E M E N T A T I O N ****/ + /**** ****/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* The TFile_Component structure holds all the data that was */ + /* previously declared static or global in this component. */ + /* */ + /* It is accessible through the 'engine.file_component' */ + /* variable in re-entrant builds, or directly through the */ + /* static 'files' variable in other builds. */ + + struct _TFile_Component + { + TMutex lock; /* used by the thread-safe build only */ + PStream_Rec stream; /* current stream */ + TFileFrame frame; /* current frame */ + }; + + typedef struct _TFile_Component TFile_Component; + +/* The macro CUR_Stream denotes the current input stream */ +/* Note that for the re-entrant version, the 'stream' name has been */ +/* chosen according to the macro STREAM_ARGS. */ + +/* The macro CUR_Frame denotes the current file frame */ +/* Note that for the re-entrant version, the 'frame' name has been */ +/* chosen according to the macro FRAME_ARGS. */ + +/* The macro STREAM_VAR is used when calling public functions */ +/* that need an 'optional' stream argument. */ + +#define CUR_Stream files.stream /* thread-safe macros */ +#define CUR_Frame files.frame + +#define STREAM_VARS /* void */ +#define STREAM_VAR /* void */ + + /* the 'files' variable is only defined in non-reentrant builds */ + + static TFile_Component files; + + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + MUTEX_Create( files.lock ); + files.stream = NULL; + ZERO_Frame( files.frame ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + MUTEX_Destroy( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream org_stream, + TT_Stream* stream ) + { + MUTEX_Lock( files.lock ); + *stream = org_stream; + files.stream = STREAM2REC( org_stream ); /* set current stream */ + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream + * + * Output : Error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + HANDLE_Set( *stream, NULL ); + MUTEX_Release( files.lock ); + + return TT_Err_Ok; + } + +#else /* TT_CONFIG_OPTION_THREAD_SAFE */ + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /******** ********/ + /******** R E E N T R A N T I M P L E M E N T A T I O N ********/ + /******** ********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +#define CUR_Stream STREAM2REC( stream ) /* re-entrant macros */ +#define CUR_Frame (*frame) + +#define STREAM_VARS stream, +#define STREAM_VAR stream + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + engine.file_component = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code. The output stream is set to NULL in + * case of Failure. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream input_stream, + TT_Stream* copy ) + { + TT_Error error; + PStream_Rec stream_rec; + PStream_Rec copy_rec; + + + stream_rec = STREAM2REC( input_stream ); + + if ( ALLOC( copy_rec, sizeof ( TStream_Rec ) ) ) + goto Fail; + + HANDLE_Set( *copy, copy_rec ); + + copy_rec->map->refcount++; + copy_rec->pos = 0; + + return TT_Err_Ok; + + Fail: + HANDLE_Set( *copy, NULL ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream + * + * Output : error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + return TT_Close_Stream( stream ); + } + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /*********** ***********/ + /*********** C O M M O N I M P L E M E N T A T I O N ***********/ + /*********** ***********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/******************************************************************* + * + * Function : AllocateMap + * + * Description : Allocates a new map from the table. + * + * Output : Pointer to new stream rec. NULL in case of failure. + * + ******************************************************************/ + + static + TFileMap* Allocate_Map( void ) + { + TFileMap* result; + + + if ( MEM_Alloc( result, sizeof ( TFileMap ) ) ) + return NULL; + + result->refcount = 1; + return result; + } + + +/******************************************************************* + * + * Function : ReleaseMap + * + * Description : Releases a used map to the table if reference i + * counter reaches zero. + * + * Input : map + * + * Output : None. + * + * Note : Called by TT_Close_File() + * + ******************************************************************/ + + static + void Release_Map ( TFileMap* map ) + { + map->refcount--; + if ( map->refcount <= 0 ) + { + munmap ( (void*)map->base, map->size ); + FREE( map ); + } + } + + +/******************************************************************* + * + * Function : TT_Open_Stream + * + * Description : Opens the font file and saves the total file size. + * + * Input : error address of stream's error variable + * (re-entrant build only). + * filepathname pathname of the file to open + * stream address of target TT_Stream structure + * + * Output : SUCCESS on success, FAILURE on error. + * The target stream is set to -1 in case of failure. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Open_Stream( const String* filepathname, + TT_Stream* stream ) + { + TT_Error error; + Int file; + PStream_Rec stream_rec; + TFileMap* map; + struct stat stat_buf; + + + if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) ) + return error; + + map = Allocate_Map(); + if ( !map ) + { + error = TT_Err_Out_Of_Memory; + goto Memory_Fail; + } + + stream_rec = STREAM2REC( *stream ); + + file = open( (String*)filepathname, O_RDONLY ); + if ( file < 0 ) + goto File_Fail; + + if ( fstat( file, &stat_buf ) < 0 ) + goto Map_Fail; + + map->offset = 0; + map->size = stat_buf.st_size + map->offset; + map->base = mmap( NULL, + map->size, + PROT_READ, + MAP_FILE | MAP_PRIVATE, + file, + 0 ); + + if ( (long)map->base == -1 ) + goto Map_Fail; + + close( file ); + + stream_rec->map = map; + stream_rec->pos = 0; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + CUR_Stream = stream_rec; +#endif + + return TT_Err_Ok; + + Map_Fail: + close( file ); + + File_Fail: + error = TT_Err_Could_Not_Open_File; + FREE( map ); + + Memory_Fail: + FREE( *stream ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Close_Stream + * + * Description : Closes a stream. + * + * Input : stream + * + * Output : SUCCESS (always) + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Close_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + Release_Map( rec->map ); + FREE( rec ); + + HANDLE_Set( *stream, NULL ); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Flush_Stream + * + * Description : Flushes a stream, i.e., closes its file handle. + * + * Input : stream address of target TT_Stream structure + * + * Output : Error code + * + * NOTE : Never flush the current opened stream. This means that + * you should _never_ call this function between a + * TT_Use_Stream() and a TT_Done_Stream()! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Flush_Stream( TT_Stream* stream ) + { + /* XXX - DUMMY IMPLEMENTATION */ + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Stream_Size + * + * Description : Returns the length of a given stream, even if it + * is flushed. + * + * Input : stream the stream + * + * Output : Length of stream in bytes. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Stream_Size( TT_Stream stream ) + { + PStream_Rec rec = STREAM2REC( stream ); + + + if ( rec ) + return rec->map->size; + else + return 0; /* invalid stream - return 0 */ + } + + +/******************************************************************* + * + * Function : TT_Seek_File + * + * Description : Seeks the file cursor to a different position. + * + * Input : position new position in file + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Seek_File( STREAM_ARGS Long position ) + { + if ( position > CUR_Stream->map->size ) + return TT_Err_Invalid_File_Offset; + + CUR_Stream->pos = position; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Skip_File + * + * Description : Skips forward the file cursor. + * + * Input : distance number of bytes to skip + * + * Output : see TT_Seek_File + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Skip_File( STREAM_ARGS Long distance ) + { + return TT_Seek_File( STREAM_VARS CUR_Stream->pos + distance ); + } + + +/******************************************************************* + * + * Function : TT_Read_File + * + * Description : Reads a chunk of the file and copies it to memory. + * + * Input : buffer target buffer + * count length in bytes to read + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_File( STREAM_ARGS void* buffer, Long count ) + { + if ( CUR_Stream->pos + count > CUR_Stream->map->size ) + return TT_Err_Invalid_File_Read; + + MEM_Copy( buffer, + MAP_Address( CUR_Stream->map ) + CUR_Stream->pos, count ); + CUR_Stream->pos += count; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Read_At_File + * + * Description : Reads file at a specified position. + * + * Input : position position to seek to before read + * buffer target buffer + * count number of bytes to read + * + * Output : SUCCESS on success. FAILURE if error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_At_File( STREAM_ARGS Long position, + void* buffer, + Long count ) + { + TT_Error error; + + + if ( (error = TT_Seek_File( STREAM_VARS position )) || + (error = TT_Read_File( STREAM_VARS buffer, count )) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_File_Pos + * + * Description : Returns current file seek pointer. + * + * Input : none + * + * Output : current file position + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_File_Pos( STREAM_ARG ) + { + return CUR_Stream->pos; + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : Error code + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that aSize is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( CUR_Stream->pos + size > CUR_Stream->map->size ) + return TT_Err_Invalid_Frame_Access; + + CUR_Frame.size = size; + CUR_Frame.address = MAP_Address( CUR_Stream->map ) + CUR_Stream->pos; + CUR_Frame.cursor = CUR_Frame.address; + + CUR_Stream->pos += size; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx() + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : Error code + * + * Notes: The function truncates 'size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that aSize is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. The 'overflow' is set to zero. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + Long readBytes; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + readBytes = CUR_Stream->map->size - CUR_Stream->pos; + if ( size > readBytes ) + { + /* There is overflow, we allocate a new block then */ + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + + CUR_Frame.size = size; + + /* copy the valid part */ + MEM_Copy( CUR_Frame.address, + MAP_Address( CUR_Stream->map ) + CUR_Stream->pos, + readBytes ); + } + else + { + CUR_Frame.size = size; + CUR_Frame.address = MAP_Address( CUR_Stream->map ) + CUR_Stream->pos; + } + + CUR_Frame.cursor = CUR_Frame.address; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + /* If we were using a duplicate in case of overflow, free it now */ + if ( CUR_Frame.address < (Byte*)CUR_Stream->map->base || + CUR_Frame.address >= (Byte*)CUR_Stream->map->base + + CUR_Stream->map->size ) + FREE( CUR_Frame.address ); + + ZERO_Frame( files.frame ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : GET_Byte + * + * Description : Extracts a byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted Byte + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + Byte TT_Get_Byte( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Byte)(*CUR_Frame.cursor++); + } + +#endif + + +/******************************************************************* + * + * Function : GET_Char + * + * Description : Extracts a signed byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted char + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Char TT_Get_Char( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Char)(*CUR_Frame.cursor++); + } + + +/******************************************************************* + * + * Function : GET_Short + * + * Description : Extracts a short from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted short + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Short TT_Get_Short( FRAME_ARG ) + { + Short getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((Short)CUR_Frame.cursor[0] << 8) | + (Short)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } + + +/******************************************************************* + * + * Function : GET_UShort + * + * Description : Extracts an unsigned short from the frame. + * + * Input : None or current frame + * + * Output : Extracted ushort + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + UShort TT_Get_UShort( FRAME_ARG ) + { + UShort getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = ((UShort)CUR_Frame.cursor[0] << 8) | + (UShort)CUR_Frame.cursor[1]; + + CUR_Frame.cursor += 2; + + return getshort; + } + +#endif + + +/******************************************************************* + * + * Function : GET_Long + * + * Description : Extracts a long from the frame. + * + * Input : None or current frame + * + * Output : Extracted long + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Get_Long( FRAME_ARG ) + { + Long getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ((Long)CUR_Frame.cursor[0] << 24) | + ((Long)CUR_Frame.cursor[1] << 16) | + ((Long)CUR_Frame.cursor[2] << 8 ) | + (Long)CUR_Frame.cursor[3]; + + CUR_Frame.cursor += 4; + + return getlong; + } + + +/******************************************************************* + * + * Function : GET_ULong + * + * Description : Extracts an unsigned long from the frame. + * + * Input : None + * + * Output : Extracted ulong + * + * NOTES : We consider that the programmer is intelligent enough + * not to try to get a byte that is out of the frame. Hence, + * we provide no bounds check here. (A misbehaving client + * could easily page fault using this call.) + * + ******************************************************************/ + +#if 0 + + EXPORT_FUNC + ULong TT_Get_ULong( FRAME_ARG ) + { + ULong getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ( ((ULong)CUR_Frame.cursor[0] << 24) | + ((ULong)CUR_Frame.cursor[1] << 16) | + ((ULong)CUR_Frame.cursor[2] << 8 ) | + (ULong)CUR_Frame.cursor[3] ); + + CUR_Frame.cursor += 4; + + return getlong; + } + +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/vms/README b/Build/source/libs/libttf/arch/vms/README new file mode 100644 index 00000000000..b450611f4ac --- /dev/null +++ b/Build/source/libs/libttf/arch/vms/README @@ -0,0 +1,20 @@ +This directory contains two files for compiling the FreeType library under +VMS: + + ft_conf.h the configuration file for the FreeType library + descrip.mms a makefile to be used with either MMS or MMK + +The files are such designed that after unpacking of freetype-1.4 one can +give the command + + MMS/DESCR=[.LIB.ARCH.VMS] + +to build the libraries. (Of course, for MMK use `MMK' on the command line +instead of `MMS'.) The makefile contains a `clean' target, but no `install' +target since I'm note sure where to install the library and the include +files. + +I did NOT do the test programs but I tested it with my own programs. + + + Jouk Jansen <joukj@hrem.stm.tudelft.nl> diff --git a/Build/source/libs/libttf/arch/vms/descrip.mms b/Build/source/libs/libttf/arch/vms/descrip.mms new file mode 100644 index 00000000000..9115316dff2 --- /dev/null +++ b/Build/source/libs/libttf/arch/vms/descrip.mms @@ -0,0 +1,155 @@ +# This file is part of the FreeType project. +# +# DESCRIP.MMS: Make file for VMS using MMS or MMK +# Created by Jouk Jansen (joukj@hrem.stm.tudelft.nl) + +ARCH = arch.unix + +CC = cc + +############### PORTABILITY COMPONENTS ######################## + +# location of memory component +MEMSRC = ttmemory.c + +# location of file component +FILESRC = ttfile.c + +# location of mutex component +MUTEXSRC = ttmutex.c + +# location of default extensions +FTEXTDIR = [.lib.extend] + +# default extensions sources +EXTSRC = $(FTEXTDIR)ftxkern.c \ + $(FTEXTDIR)ftxgasp.c \ + $(FTEXTDIR)ftxpost.c \ + $(FTEXTDIR)ftxcmap.c \ + $(FTEXTDIR)ftxsbit.c \ + $(FTEXTDIR)ftxwidth.c \ + $(FTEXTDIR)ftxerr18.c \ + $(FTEXTDIR)ftxgsub.c \ + $(FTEXTDIR)ftxgpos.c \ + $(FTEXTDIR)ftxopen.c \ + $(FTEXTDIR)ftxgdef.c + +EXTOBJ = [.lib]ftxkern.obj, \ + [.lib]ftxgasp.obj, \ + [.lib]ftxpost.obj, \ + [.lib]ftxcmap.obj, \ + [.lib]ftxsbit.obj, \ + [.lib]ftxwidth.obj, \ + [.lib]ftxerr18.obj, \ + [.lib]ftxgsub.obj, \ + [.lib]ftxgpos.obj, \ + [.lib]ftxopen.obj, \ + [.lib]ftxgdef.obj + +# all engine sources +SRC_M = [.lib]ttapi.c \ + [.lib]ttcache.c \ + [.lib]ttcalc.c \ + [.lib]ttcmap.c \ + [.lib]ttdebug.c \ + [.lib]ttextend.c \ + [.lib]ttgload.c \ + [.lib]ttinterp.c \ + [.lib]ttload.c \ + [.lib]ttobjs.c \ + [.lib]ttraster.c \ + [.lib]$(FILESRC) \ + [.lib]$(MEMSRC) \ + [.lib]$(MUTEXSRC) +SRC_S = [.lib.$(ARCH)]freetype.c + +# all header files with path +HEADERS = [.lib]freetype.h \ + [.lib]fterrid.h \ + [.lib]ftnameid.h \ + $(FTEXTDIR)ftxkern.h \ + $(FTEXTDIR)ftxgasp.h \ + $(FTEXTDIR)ftxcmap.h \ + $(FTEXTDIR)ftxsbit.h \ + $(FTEXTDIR)ftxpost.h \ + $(FTEXTDIR)ftxwidth.h \ + $(FTEXTDIR)ftxerr18.h \ + $(FTEXTDIR)ftxgsub.h \ + $(FTEXTDIR)ftxgpos.h \ + $(FTEXTDIR)ftxgdef.h \ + $(FTEXTDIR)ftxopen.h + +# all engine objects +OBJ_M = [.lib]ttapi.obj, \ + [.lib]ttcache.obj, \ + [.lib]ttcalc.obj, \ + [.lib]ttcmap.obj, \ + [.lib]ttdebug.obj, \ + [.lib]ttextend.obj, \ + [.lib]ttgload.obj, \ + [.lib]ttinterp.obj, \ + [.lib]ttload.obj, \ + [.lib]ttobjs.obj, \ + [.lib]ttraster.obj, \ + [.lib]file.obj, \ + [.lib]memory.obj, \ + [.lib]mutex.obj, \ + $(EXTOBJ) +OBJ_S = [.lib]freetype.obj + + +# include paths +INCLUDES = /include=([.lib],[],$(FTEXTDIR)) + +# C flags +CFLAGS = $(INCLUDES)/obj=[.lib] + +all : do_link [.lib]libttf.olb + library/compress [.lib]libttf.olb + +do_link : + if f$search( "[.lib]memory.c" ) .nes. "" then set file/remove [.lib]memory.c; + if f$search( "[.lib]file.c" ) .nes. "" then set file/remove [.lib]file.c; + if f$search( "[.lib]mutex.c" ) .nes. "" then set file/remove [.lib]mutex.c; + if f$search( "[.lib]ft_conf.h" ) .nes. "" then set file/remove [.lib]ft_conf.h; + set file/enter=[.lib]memory.c [.lib]$(MEMSRC) + set file/enter=[.lib]file.c [.lib]$(FILESRC) + set file/enter=[.lib]mutex.c [.lib]$(MUTEXSRC) + set file/enter=[.lib]ft_conf.h [.lib.arch.vms]ft_conf.h + +[.lib]ftxkern.obj : $(FTEXTDIR)ftxkern.c + +[.lib]ftxgasp.obj : $(FTEXTDIR)ftxgasp.c + +[.lib]ftxpost.obj : $(FTEXTDIR)ftxpost.c + +[.lib]ftxcmap.obj : $(FTEXTDIR)ftxcmap.c + +[.lib]ftxsbit.obj : $(FTEXTDIR)ftxsbit.c + +[.lib]ftxwidth.obj : $(FTEXTDIR)ftxwidth.c + +[.lib]ftxerr18.obj : $(FTEXTDIR)ftxerr18.c + +[.lib]ftxgsub.obj : $(FTEXTDIR)ftxgsub.c + +[.lib]ftxgpos.obj : $(FTEXTDIR)ftxgpos.c + +[.lib]ftxgdef.obj : $(FTEXTDIR)ftxgdef.c + +[.lib]ftxopen.obj : $(FTEXTDIR)ftxopen.c + +[.lib]freetype.obj : $(SRC_S) $(SRC_M) + + +[.lib]libttf.olb : $(OBJ_M) + library/create [.lib]libttf.olb $(OBJ_M) + + +clean : + delete [.lib]*.obj;* + delete [.lib]*.olb;* + if f$search( "[.lib]memory.c" ) .nes. "" then set file/remove [.lib]memory.c; + if f$search( "[.lib]file.c" ) .nes. "" then set file/remove [.lib]file.c; + if f$search( "[.lib]mutex.c" ) .nes. "" then set file/remove [.lib]mutex.c; + if f$search( "[.lib]ft_conf.h" ) .nes. "" then set file/remove [.lib]ft_conf.h; diff --git a/Build/source/libs/libttf/arch/vms/ft_conf.h b/Build/source/libs/libttf/arch/vms/ft_conf.h new file mode 100644 index 00000000000..b1315e63571 --- /dev/null +++ b/Build/source/libs/libttf/arch/vms/ft_conf.h @@ -0,0 +1,215 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for VMS using MMS or MMK */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +/* #undef HAVE_MMAP */ + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if the X Window System is missing or not being used. */ +/* #undef X_DISPLAY_MISSING */ + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE 1 + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the <libintl.h> header file. */ +/* #undef HAVE_LIBINTL_H */ + +/* Define if you have the libintl library. */ +/* #undef HAVE_LIBINTL */ + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #undef HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +/* #undef TT_CONFIG_OPTION_THREAD_SAFE */ + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +/* #undef DEBUG_LEVEL_TRACE */ + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +/* #undef DEBUG_LEVEL_ERROR */ + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/win16/Makefile.BC b/Build/source/libs/libttf/arch/win16/Makefile.BC new file mode 100644 index 00000000000..bbf540ebb9a --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/Makefile.BC @@ -0,0 +1,180 @@ +# This file is part of the FreeType project. +# +# It builds the library for Borland C++ for 16-bit Windows, large model. +# Due to size constraints, it does not try to pack all modules into one. +# +# You will need Borland MAKE. +# Tested with Borland C++ v.4.0 and 5.0. +# +# Use this file while in the lib directory with the following statement: +# +# make -farch/win16/Makefile.BC +# +# +# A DLL version of the library can be built with +# +# make -DDLL -farch/win16/Makefile.BC dll +# +# Debug versions can be obtained with +# +# make -DDEBUG -farch\win16\Makefile.BC +# +# Special versions enabled to handle big fonts (with more than 16,384 +# glyphs) can be obtained with +# +# make -DBIGFONTS -farch/win16/Makefile.BC + +ARCH = arch\win16 +FT_MAKEFILE = $(ARCH)\Makefile.BC +FT_DLL = ft14_16.dll + +CC = bcc +LIB = tlib /c /e +IMPLIB = implib -c -o + +SPURIOUS_WARNINGS = -w-nak -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig + +# Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern +# Borland compilers (from BC++ 3.1 on) can increase the limit on +# the length of identifiers. +!if ! $d(DEBUG) +CFLAGS = -O2 -3 -ml -A -i40 -I$(ARCH);.;extend $(SPURIOUS_WARNINGS) +DLLFLAGS = -ml -WD -lC +!else +CFLAGS = -v -N -ml -A -i40 -I$(ARCH);.;extend $(SPURIOUS_WARNINGS) +DLLFLAGS = -v -ml -WD -lC +!endif + +CFLAGS = $(CFLAGS) -W + +FT_DEF = $(FT_DLL:.dll=.def) +!if $d(DLL) +CFLAGS = $(CFLAGS) -WD +!endif + + +!if $d(BIGFONTS) +CFLAGS = $(CFLAGS) -DTT_HUGE_PTR=__huge + +TTFILE = $(ARCH)\hugefile.c +TTMEMORY = $(ARCH)\hugemem.c +!else +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +!endif +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces before the \ at end of line, +# otherwise the substitution for TLIB command line will fail. +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ + extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c\ + extend\ftxsbit.c extend\ftxgsub.c extend\ftxgpos.c\ + extend\ftxopen.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c\ + ttgload.c ttinterp.c ttload.c ttobjs.c\ + ttraster.c ttextend.c ttdebug.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Borland make does not handle $($(LIB_FILES)), and using +# -DLIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing TLIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# See ../msdos/Makefile.TC for an application. +.c.obj: + @$(CC) -c -o$* @&&| + $(CFLAGS) $< +| + + +!if ! $d(DEBUG) +# Skipped if DEBUG build +# (but it changes nothing, since we always build in multiple parts). +all: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_M: = + ) +| +!endif + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_M: = + ) +| + +$(FT_DEF): $(ARCH)\ttf.def + -copy $(ARCH)\ttf.def $(FT_DEF) + +dll $(FT_DLL): $(OBJS_M) $(FT_DEF) +!if $d(DLL) + $(CC) -e$(FT_DLL) @&&| + $(DLLFLAGS) $(OBJS_M) +| + $(IMPLIB) libttf $(FT_DEF) +!else +# Re-invoke with flag set. Unfortunately, this discards the other flags. + make -DDLL -f$(ARCH)/Makefile.BC dll +!endif + +install: $(FT_DLL) +!if $d(INSTALL_DIR) + copy $(FT_DLL) $(INSTALL_DIR) +!else + copy $(FT_DLL) C:\WINDOWS +!endif + + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + -del libttf.lib + echo -+$(**: =-+)> response + $(LIB) libttf.lib @&&| ++ $(**: = + ) +| + +!if $d(BIGFONTS) +$(TTMEMORY:.c=.obj): $(TTMEMORY) + $(CC) -c -o$* @&&| + $(CFLAGS) -A- $*.c +| + +$(TTFILE:.c=.obj): $(TTFILE) + $(CC) -c -o$* @&&| + $(CFLAGS) -A- $*.c +| +!endif + + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak + -del response + -del *.def + +distclean: clean + -del libttf.lib + -del *.dll + -del $(FT_DEF) + -del C:\WINDOWS\$(FT_DLL) +!if $d(INSTALL_DIR) + -del $(INSTALL_DIR)\$(FT_DLL) +!endif + +!include "$(ARCH)\depend.win" + +# end of Makefile diff --git a/Build/source/libs/libttf/arch/win16/Makefile.MS b/Build/source/libs/libttf/arch/win16/Makefile.MS new file mode 100644 index 00000000000..9ff0b6749a4 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/Makefile.MS @@ -0,0 +1,106 @@ +# This file is part of the FreeType project. +# +# It builds the library for Microsoft C for Windows, large model. +# It also works for Visual C++ 1.x 16-bit compilers, but you should +# instead use the Makefile customized for it, Makefile.VC. +# Due to size constraints, it does not try to pack all modules into one. +# +# You will need NMAKE. +# +# Use this file while in the lib directory with the following statement: +# +# nmake /f arch\win16\Makefile.MS +# +# +# A debug version can be obtained with +# +# nmake DEBUG=1 /f arch\win16\Makefile.MS + +ARCH = arch\win16 +FT_MAKEFILE = $(ARCH)\Makefile.MS + +CC = cl /nologo +LIB = lib /noignorecase /nologo + +!ifndef DEBUG +CFLAGS = /Ox /AL /Za /W2 /G2 -I$(ARCH) -I. -Iextend +!else +CFLAGS = /Zi /AL /Za /W2 /G2 -I$(ARCH) -I. -Iextend +!endif + +# Use /Gw instead with Microsoft C version 6 +CFLAGS = $(CFLAGS) /GA + + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces between the file names or at end of line, otherwise +# the substitution for LIB command line will fail. Thank you. +# +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ +extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c extend\ftxsbit.c\ +extend\ftxopen.c extend\ftxgsub.c extend\ftxgpos.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c\ +ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Microsoft's NMAKE does not handle $($(LIB_FILES)), and using +# LIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing LIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# See ..\msdos\Makefile.TC for an application. +.c.obj: + $(CC) /c /Fo$@ @<< + $(CFLAGS) $*.c +<< + + +!ifndef DEBUG +# Skipped if DEBUG build +# (but it changes nothing, since we always build in multiple parts). +all: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = ^ ); +<<KEEP +!endif + + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = ^ ); +<<KEEP + + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + $(LIB) $@ +-$(?: =-+); + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del response + +distclean: clean + -del libttf.lib + +!include "$(ARCH)\depend.win" + +# end of Makefile.MS diff --git a/Build/source/libs/libttf/arch/win16/Makefile.VC b/Build/source/libs/libttf/arch/win16/Makefile.VC new file mode 100644 index 00000000000..e7663839328 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/Makefile.VC @@ -0,0 +1,175 @@ +# This file is part of the FreeType project. +# +# It builds the library for Microsoft Visual C++ 1.x for 16-bit Windows, +# large model. It also works for Microsoft C/C++ v.7.0 16-bit compiler, +# but not for previous versions (see Makefile.MS instead). +# +# You will need NMAKE. +# +# Use this file while in the lib directory with the following statement: +# +# nmake /f arch\win16\Makefile.VC +# +# +# A DLL version of the library can be built with +# +# nmake DLL=1 /f arch\win16\Makefile.VC dll +# +# Debug versions can be obtained with +# +# nmake DEBUG=1 /f arch\win16\Makefile.VC +# +# Special versions enabled to handle big fonts (with more than 16,384 +# glyphs) can be obtained with +# +# nmake BIGFONTS=1 /f arch\win16\Makefile.VC + +ARCH = arch\win16 +FT_MAKEFILE = $(ARCH)\Makefile.VC +FT_DLL = ft14_16.dll + +CC = cl /nologo +LIB = lib /noignorecase /nologo +IMPLIB = implib /noignorecase /nologo + +# One can also consider using "set MSC_CMD_FLAGS=/Gr /Op- /Gy /YX". +# With Microsoft C/C++ 7.0, use /G2 instead of /G3. +!ifndef DEBUG +CFLAGS = /Ox /AL /Za /W2 /G3 -I$(ARCH) -I. -Iextend +DLLFLAGS = /AL /Ld +!else +CFLAGS = /Zi /Ge /AL /Za /W2 /G3 -I$(ARCH) -I. -Iextend +DLLFLAGS = /AL /Lw /Zi +!endif + +FT_DEF = $(FT_DLL:.dll=.def) +!ifdef DLL +CFLAGS = $(CFLAGS) /GD /GEf +!else +CFLAGS = $(CFLAGS) /GA +!endif + + +!ifdef BIGFONTS +CFLAGS = $(CFLAGS) /DTT_HUGE_PTR=__huge + +TTFILE = $(ARCH)\hugefile.c +TTMEMORY = $(ARCH)\hugemem.c +!else +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +!endif +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces between the file names or at end of line, otherwise +# the substitution for LIB command line will fail. Thank you. +# +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ +extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c extend\ftxsbit.c\ +extend\ftxopen.c extend\ftxgsub.c extend\ftxgpos.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c\ +ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Microsoft's NMAKE does not handle $($(LIB_FILES)), and using +# LIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing LIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# See ..\msdos\Makefile.TC for an application. +.c.obj: + @$(CC) /c /Fo$@ @<< + $(CFLAGS) $*.c +<< + + +!ifndef DEBUG +# Skipped if DEBUG build +all: $(OBJS_S) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_S: = + ); +<<KEEP +!endif + + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @<<response ++ $(OBJS_M: = + ); +<<KEEP + +$(FT_DEF): $(ARCH)\ttf.def + -copy $(ARCH)\ttf.def $(FT_DEF) + +dll $(FT_DLL): $(OBJS_M) $(FT_DEF) +!ifdef DLL + $(CC) /Fe$(FT_DLL) @<< + $(DLLFLAGS) $** +<< + $(IMPLIB) libttf.lib $(FT_DEF) +!else +# Re-invoke with flag set. Unfortunately, this discards the other flags. + $(MAKE) DLL=1 /f $(ARCH)/Makefile.VC dll +!endif + +install: $(FT_DLL) +!ifdef INSTALL_DIR + copy $(FT_DLL) $(INSTALL_DIR) +!else + copy $(FT_DLL) C:\WINDOWS +!endif + + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + $(LIB) $@ +-$(?: =-+); + +!ifdef BIGFONTS +$(TTFILE:.c=.obj): + $(CC) /c /Fo$@ @<< + $(CFLAGS) /Ze $*.c + +$(TTMEMORY:.c=.obj): + $(CC) /c /Fo$@ @<< + $(CFLAGS) /Ze $*.c +<< + +$(OBJ_S): + $(CC) /c /Fo$@ @<< + $(CFLAGS) /Ze $*.c +<< +!endif + + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak + -del response + +distclean: clean + -del libttf.lib + -del *.dll + -del $(FT_DLL:.dll=.def) + -del C:\WINDOWS\$(FT_DLL) +!ifdef INSTALL_DIR + -del $(INSTALL_DIR)\$(FT_DLL) +!endif + +!include "$(ARCH)\depend.win" + +# end of Makefile.VC diff --git a/Build/source/libs/libttf/arch/win16/depend.win b/Build/source/libs/libttf/arch/win16/depend.win new file mode 100644 index 00000000000..6b3612cbfd2 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/depend.win @@ -0,0 +1,109 @@ +# This dependency file to be used with various Windows compilers +# has been generated automatically with the script `makedep' on +# 07-Mar-2000. + +ttapi.obj: ttapi.c ttconfig.h arch\win16\ft_conf.h freetype.h fterrid.h \ + ftnameid.h ttengine.h tttypes.h ttmutex.h ttcalc.h ttmemory.h \ + ttcache.h ttfile.h ttdebug.h ttobjs.h tttables.h ttcmap.h ttload.h \ + ttgload.h ttraster.h ttextend.h +ttcache.obj: ttcache.c ttengine.h tttypes.h ttconfig.h \ + arch\win16\ft_conf.h freetype.h fterrid.h ftnameid.h ttmutex.h \ + ttmemory.h ttcache.h ttobjs.h tttables.h ttcmap.h ttdebug.h +ttcalc.obj: ttcalc.c ttcalc.h ttconfig.h arch\win16\ft_conf.h freetype.h \ + fterrid.h ftnameid.h ttdebug.h tttypes.h tttables.h +ttcmap.obj: ttcmap.c ttobjs.h ttconfig.h arch\win16\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttdebug.h ttfile.h ttmemory.h ttload.h +ttdebug.obj: ttdebug.c ttdebug.h ttconfig.h arch\win16\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h tttables.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h ttcmap.h +ttextend.obj: ttextend.c ttextend.h ttconfig.h arch\win16\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttmemory.h +ttfile.obj: ttfile.c ttconfig.h arch\win16\ft_conf.h freetype.h \ + fterrid.h ftnameid.h tttypes.h ttdebug.h ttengine.h ttmutex.h \ + ttmemory.h ttfile.h +ttgload.obj: ttgload.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h ttgload.h \ + ttmemory.h tttags.h ttload.h +ttinterp.obj: ttinterp.c freetype.h fterrid.h ftnameid.h tttypes.h \ + ttconfig.h arch\win16\ft_conf.h ttdebug.h ttcalc.h ttmemory.h \ + ttinterp.h ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h \ + ttcmap.h +ttload.obj: ttload.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h \ + ttmemory.h tttags.h ttload.h +ttmemory.obj: ttmemory.c ttdebug.h ttconfig.h arch\win16\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmemory.h ttengine.h \ + ttmutex.h +ttmutex.obj: ttmutex.c ttmutex.h ttconfig.h arch\win16\ft_conf.h +ttobjs.obj: ttobjs.c ttobjs.h ttconfig.h arch\win16\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttfile.h ttdebug.h ttcalc.h ttmemory.h ttload.h \ + ttinterp.h ttextend.h +ttraster.obj: ttraster.c ttraster.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttengine.h tttypes.h ttmutex.h \ + ttdebug.h ttcalc.h ttmemory.h +extend\ftxcmap.obj: extend\ftxcmap.c extend\ftxcmap.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win16\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxerr18.obj: extend\ftxerr18.c ttconfig.h arch\win16\ft_conf.h \ + extend\ftxerr18.h freetype.h fterrid.h ftnameid.h extend\ftxkern.h \ + extend\ftxpost.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h +extend\ftxgasp.obj: extend\ftxgasp.c extend\ftxgasp.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win16\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxgdef.obj: extend\ftxgdef.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgpos.obj: extend\ftxgpos.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgsub.obj: extend\ftxgsub.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxkern.obj: extend\ftxkern.c extend\ftxkern.h freetype.h fterrid.h \ + ftnameid.h ttextend.h ttconfig.h arch\win16\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttdebug.h \ + ttmemory.h ttfile.h ttload.h tttags.h +extend\ftxopen.obj: extend\ftxopen.c tttypes.h ttconfig.h arch\win16\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxpost.obj: extend\ftxpost.c extend\ftxpost.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win16\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttload.h ttfile.h \ + ttdebug.h tttags.h ttmemory.h ttextend.h +extend\ftxsbit.obj: extend\ftxsbit.c extend\ftxsbit.h freetype.h fterrid.h \ + ftnameid.h ttobjs.h ttconfig.h arch\win16\ft_conf.h ttengine.h \ + tttypes.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h ttdebug.h \ + ttload.h ttmemory.h tttags.h ttextend.h +extend\ftxwidth.obj: extend\ftxwidth.c extend\ftxwidth.h freetype.h fterrid.h \ + ftnameid.h ttdebug.h ttconfig.h arch\win16\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h \ + tttags.h ttload.h +!ifndef __MAKE__ +arch\win16\freetype.obj: arch\win16\freetype.c ttapi.c ttconfig.h \ + arch\win16\ft_conf.h freetype.h fterrid.h ftnameid.h ttengine.h \ + tttypes.h ttmutex.h ttcalc.h ttmemory.h ttcache.h ttfile.h ttdebug.h \ + ttobjs.h tttables.h ttcmap.h ttload.h ttgload.h ttraster.h ttextend.h \ + ttcache.c ttcalc.c ttcmap.c ttdebug.c ttgload.c tttags.h ttinterp.c \ + ttinterp.h ttload.c ttobjs.c ttraster.c arch\win16\hugefile.c \ + ttfile.c arch\win16\hugemem.c ttmutex.c ttextend.c +arch\win16\hugefile.obj: arch\win16\hugefile.c ttconfig.h arch\win16\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttfile.c ttdebug.h \ + ttengine.h ttmutex.h ttmemory.h ttfile.h +arch\win16\hugemem.obj: arch\win16\hugemem.c ttdebug.h ttconfig.h \ + arch\win16\ft_conf.h tttypes.h freetype.h fterrid.h ftnameid.h \ + ttmemory.h ttengine.h ttmutex.h +!endif diff --git a/Build/source/libs/libttf/arch/win16/freetype.c b/Build/source/libs/libttf/arch/win16/freetype.c new file mode 100644 index 00000000000..1ff2c887de7 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/freetype.c @@ -0,0 +1,39 @@ +/* This file is part of the FreeType project */ + +/* Single object library component for 16-bit Windows. */ +/* Note that low-optimizing compilers (such as Borland ones) cannot */ +/* successfully compile this file, because it exceeds 64K of code size. */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#ifdef TT_HUGE_PTR +#include "arch/win16/hugefile.c" +#include "arch/win16/hugemem.c" +#else +#include "ttfile.c" +#include "ttmemory.c" +#endif +#include "ttmutex.c" + +/* finally, add some extensions */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/win16/ft_conf.h b/Build/source/libs/libttf/arch/win16/ft_conf.h new file mode 100644 index 00000000000..8578ab93148 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/ft_conf.h @@ -0,0 +1,209 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for 16-bit Windows */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define if you need <conio.h> for console I/O functions. */ +#undef HAVE_CONIO_H + +/* Define if you have the <locale.h> header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the <libintl.h> header file. */ +#undef HAVE_LIBINTL_H + +/* Define if you have the libintl library. */ +#undef HAVE_LIBINTL + +/* command.com can't pipe stderr into a file; any message would be */ +/* written into the graphics screen. */ +#define HAVE_PRINT_FUNCTION 1 + +#define Print( format, ap ) vfprintf( stdout, (format), (ap) ) + +/* The number of bytes in a int. */ +#define SIZEOF_INT 2 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#undef LONG64 +#undef INT64 + +#endif /* FT_CONF_H */ + +/* End of ft_conf.h */ diff --git a/Build/source/libs/libttf/arch/win16/hugefile.c b/Build/source/libs/libttf/arch/win16/hugefile.c new file mode 100644 index 00000000000..17b5f5948f7 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/hugefile.c @@ -0,0 +1,51 @@ +/******************************************************************* + * + * hugefile.c + * + * File I/O Component (body) for dealing with "huge" objects + * under 16-bit Windows. Relies on the "default" version, with + * a small hook. Requires Windows 3.1+. + * + * Written by Antoine Leca based on ideas from Dave Hoo. + * Copyright 1999 by Dave Hoo, Antoine Leca, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTE + * + * This file #includes the normal version, to avoid discrepancies + * between versions. It uses only ANSI-mandated "tricks", so + * any ANSI-compliant compiler should be able to compile this file. + * + ******************************************************************/ + +#include "ttconfig.h" +#include "tttypes.h" + +#include <windows.h> + + /* Here we include <stdio.h>, to have the proper definition of fread */ +#include <stdio.h> + + /* Some compilers define fileno(), some define _fileno()... */ +#ifndef _fileno +#define _fileno(stream) fileno(stream) +#endif + + /* Then, we divert the use of fread to the Windows version */ +#undef fread +#define fread(ptr, size, n, stream) \ + _hread( _fileno(stream), (char TT_HUGE_PTR *) ptr, (ULong)n * size ) + + + /* Now, we include the "normal" version of `ttfile.c' */ + /* The ANSI/ISO standard mandates that the include of <stdio.h> */ + /* there have no bad effects. */ +#include "ttfile.c" + +/* END */ diff --git a/Build/source/libs/libttf/arch/win16/hugemem.c b/Build/source/libs/libttf/arch/win16/hugemem.c new file mode 100644 index 00000000000..c1abe5f1535 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/hugemem.c @@ -0,0 +1,539 @@ +/******************************************************************* + * + * hugemem.c + * + * Memory management component (body) + * for dealing with "huge" objects with 16-bit Windows. + * + * Written by Antoine Leca based on ideas from Dave Hoo. + * Copyright 1999 by Dave Hoo, Antoine Leca, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include <limits.h> +#include <windows.h> + +#include "ttdebug.h" +#include "ttmemory.h" +#include "ttengine.h" + +#ifndef TT_HUGE_PTR +#error "This component needs TT_HUGE_PTR to be #defined." +#endif + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE +#error "This component needs static allocation and is not re-entrant." +#endif + + /* If the memory reclaimed is abobve this limit, alloc directly from */ + /* global heap. Else, alloc using malloc (using suballocation). */ +#ifndef MEMORY_MIN_GLOBAL +#define MEMORY_MIN_GLOBAL 4096 +#endif + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_memory + + +#ifdef DEBUG_MEMORY + +#include <stdio.h> + +#define MAX_TRACKED_BLOCKS 1024 + + struct TMemRec_ + { + void* base; + Long size; + }; + + typedef struct TMemRec_ TMemRec; + + static TMemRec pointers[MAX_TRACKED_BLOCKS + 1]; + + static Int num_alloc; + static Int num_free; + static Int num_realloc; /* counts only `real' reallocations + (i.e., an existing buffer will be resized + to a value larger than zero */ + + static Int fail_alloc; + static Int fail_realloc; + static Int fail_free; + +#else + + /* We need a tracing stack of the calls to big chunks of memory, */ + /* in order to call the matching version of free(). */ + +#define MAX_TRACKED_BIGCHUNKS 64 + + struct TMemRec_ + { + void* base; + }; + + typedef struct TMemRec_ TMemRec; + + static TMemRec pointers[MAX_TRACKED_BIGCHUNKS + 1]; + +#endif /* DEBUG_MEMORY */ + + +#ifndef TT_CONFIG_REENTRANT + Long TTMemory_Allocated; + Long TTMemory_MaxAllocated; +#endif + + +/******************************************************************* + * + * Function : TT_Alloc + * + * Description : Allocates memory from the heap buffer. + * + * Input : Size size of the memory to be allocated + * P pointer to a buffer pointer + * + * Output : Error code. + * + * NOTE : The newly allocated block should _always_ be zeroed + * on return. Many parts of the engine rely on this to + * work properly. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Alloc( ULong Size, void** P ) + { + Int i; + + + if ( !P ) + return TT_Err_Invalid_Argument; + /* Also see below for another case of "invalid argument". */ + + if ( Size > 0 ) + { + if ( Size >= MEMORY_MIN_GLOBAL ) + { + HANDLE hMem; + + hMem = GlobalAlloc( GMEM_ZEROINIT, Size ); + if ( !hMem ) + return TT_Err_Out_Of_Memory; + + *P = (void*)GlobalLock( hMem ); + } + else + *P = (void*)malloc( Size ); + + if ( !*P ) + return TT_Err_Out_Of_Memory; + +#ifndef TT_CONFIG_REENTRANT + TTMemory_MaxAllocated += Size; + TTMemory_Allocated += Size; +#endif + +#ifdef DEBUG_MEMORY + + num_alloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_alloc++; + else + { + pointers[i].base = *P; + pointers[i].size = Size; + } + +#else + + if ( Size >= MEMORY_MIN_GLOBAL ) + { + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BIGCHUNKS ) + /* We fail badly here. Increase MAX_TRACKED_BIGCHUNKS if needed. */ + return TT_Err_Invalid_Argument; + else + pointers[i].base = *P; + } + +#endif /* DEBUG_MEMORY */ + + /* The nice thing about GlobalAlloc is that it zeroes the memory. */ + + if ( Size < MEMORY_MIN_GLOBAL ) + MEM_Set( *P, 0, Size ); + + } + else + *P = NULL; + + return TT_Err_Ok; + } + + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + +/******************************************************************* + * + * Function : TT_Realloc + * + * Description : Reallocates memory from the heap buffer. + * + * Input : Size new size of the memory to be allocated; + * if zero, TT_Free() will be called + * P pointer to a buffer pointer; if *P == NULL, + * TT_Alloc() will be called + * + * Output : Error code. + * + * NOTES : It's not necessary to zero the memory in case the + * reallocated buffer is larger than before -- the + * application has to take care of this. + * + * If the memory request fails, TT_Free() will be + * called on *P, and TT_Err_Out_Of_Memory returned. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Realloc( ULong Size, void** P ) + { + ULong oldSize; + void* Q; + Int i; + + + if ( !P ) + return TT_Err_Invalid_Argument; + + if ( !*P ) + return TT_Alloc( Size, P ); + + if ( Size == 0 ) + return TT_Free( P ); + +#ifdef DEBUG_MEMORY + + num_realloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_realloc++; + else + oldSize = pointers[i].size; + +#else + + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != *P ) + i++; + + /* If we did not found the pointer, then this is a "small" chunk. */ + + if ( i < MAX_TRACKED_BIGCHUNKS ) + { + /* Signal we found a big one. Real size does not matter. */ + oldSize = MEMORY_MIN_GLOBAL; + } + +#endif /* DEBUG_MEMORY */ + + if ( oldSize >= MEMORY_MIN_GLOBAL ) + { + /* Deal with a big chunk. */ + HANDLE hMem, hNewMem; + + hMem = GlobalHandle ( (ULong)*P >> 16 ) & 0xFFFF; + if ( !hMem ) /* Bad call... */ + return TT_Err_Invalid_Argument; + + GlobalUnlock( hMem ); + hNewMem = GlobalReAlloc( hMem, Size, 0 ); + if ( hNewMem ) + *P = (void*)GlobalLock( hNewMem ); + } + if ( Size >= MEMORY_MIN_GLOBAL ) + { + /* A small chunk crosses the limit... */ + + if( TT_Alloc( Size, &Q ) != TT_Err_Ok ) + Q = NULL; /* Failed to create the new block. */ + else + MEM_Copy( Q, *P, oldSize ); + + /* We need to register the new entry. */ +#ifndef DEBUG_MEMORY + + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BIGCHUNKS ) + /* We fail badly here. Increase MAX_TRACKED_BIGCHUNKS if needed. */ + return TT_Err_Invalid_Argument; +#endif /* DEBUG_MEMORY */ + } + else + Q = (void*)realloc( *P, Size ); + + if ( !Q ) + { + TT_Free( *P ); + return TT_Err_Out_Of_Memory; + } + +#ifdef DEBUG_MEMORY + + if ( i < MAX_TRACKED_BLOCKS ) + { +#ifndef TT_CONFIG_REENTRANT + TTMemory_Allocated += Size - pointers[i].size; + if ( Size > pointers[i].size ) + TTMemory_MaxAllocated += Size - pointers[i].size; +#endif + + pointers[i].base = Q; + pointers[i].size = Size; + } +#else + if ( i < MAX_TRACKED_BIGCHUNKS ) + { + pointers[i].base = Q; + } +#endif /* DEBUG_MEMORY */ + + *P = Q; + + return TT_Err_Ok; + } + + +#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE */ + + +/******************************************************************* + * + * Function : TT_Free + * + * Description : Releases a previously allocated block of memory. + * + * Input : P pointer to memory block + * + * Output : Always SUCCESS. + * + * Note : The pointer must _always_ be set to NULL by this function. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Free( void** P ) + { + Int i; + Long Size = 0; + + + if ( !P || !*P ) + return TT_Err_Ok; + +#ifdef DEBUG_MEMORY + + num_free++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_free++; + else + { +#ifndef TT_CONFIG_REENTRANT + TTMemory_Allocated -= pointers[i].size; +#endif + + Size = pointers[i].size; + pointers[i].base = NULL; + pointers[i].size = 0; + } + +#else + + i = 0; + while ( i < MAX_TRACKED_BIGCHUNKS && pointers[i].base != *P ) + i++; + + /* If we did not found the pointer, then this is a "small" chunk. */ + + if ( i < MAX_TRACKED_BIGCHUNKS ) + { + pointers[i].base = NULL; + /* Signal we found a big one. Real size does not matter. */ + Size = MEMORY_MIN_GLOBAL; + } + +#endif /* DEBUG_MEMORY */ + + if ( Size >= MEMORY_MIN_GLOBAL ) + { + HANDLE hMem; + + hMem = GlobalHandle ( (ULong)*P >> 16 ) & 0xFFFF; + if ( !hMem ) /* Bad call... */ + return TT_Err_Invalid_Argument; + + GlobalUnlock( hMem ); + GlobalFree ( hMem ); + } + else + free( *P ); + + *P = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Init + * + * Description : Initializes the memory. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Init( void ) + { +#ifdef DEBUG_MEMORY + Int i; + + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + pointers[i].base = NULL; + pointers[i].size = 0; + } + + num_alloc = 0; + num_realloc = 0; + num_free = 0; + + fail_alloc = 0; + fail_realloc = 0; + fail_free = 0; +#else + Int i; + + for ( i = 0; i < MAX_TRACKED_BIGCHUNKS; i++ ) + { + pointers[i].base = NULL; + } +#endif + + +#ifndef TT_CONFIG_REENTRANT + TTMemory_Allocated = 0; + TTMemory_MaxAllocated = 0; +#endif + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Done + * + * Description : Finalizes memory usage. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Done( void ) + { +#ifdef DEBUG_MEMORY + Int i, num_leaked, tot_leaked; + + + num_leaked = 0; + tot_leaked = 0; + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + num_leaked ++; + tot_leaked += pointers[i].size; + } + } + + fprintf( stderr, + "%d memory allocations, of which %d failed\n", + num_alloc, + fail_alloc ); + + fprintf( stderr, + "%d memory reallocations, of which %d failed\n", + num_realloc, + fail_realloc ); + + fprintf( stderr, + "%d memory frees, of which %d failed\n", + num_free, + fail_free ); + + if ( num_leaked > 0 ) + { + fprintf( stderr, + "There are %d leaked memory blocks, totalizing %d bytes\n", + num_leaked, tot_leaked ); + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + fprintf( stderr, + "index: %4d (base: $%08lx, size: %08ld)\n", + i, + (long)pointers[i].base, + pointers[i].size ); + } + } + } + else + fprintf( stderr, "No memory leaks !\n" ); + +#endif /* DEBUG_MEMORY */ + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/arch/win16/makedef b/Build/source/libs/libttf/arch/win16/makedef new file mode 100644 index 00000000000..f16fbb15f96 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/makedef @@ -0,0 +1,24 @@ +# makedef +# +# This shell script creates a .DEF file necessary for building as DLL +# on the Windows 16-bit platform. + +echo "\ +; This definition file to be used to built the library as DLL +; has been generated automatically with the script \`makedef' on +; `date +%d-%b-%Y`. + +LIBRARY ft14_16 +DESCRIPTION 'FreeType 1.4 16-bit DLL © 1996-2000 Turner, Wilhelm, Lemberg' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +EXPORTS +" > ttf.def + +(cd ../.. + sed -n -e "/^ *EXPORT_DEF/!d ; n ; s/(.*$//" \ + -e "s/;$//" -e "s/ const / /" -e "s/ *[a-zA-Z][a-zA-Z_\*]* //" \ + -e "s/ *//g" -e "s/^\(.*\)/ _\1/" -e "p" *.h extend/*.h) >> ttf.def + +# eof diff --git a/Build/source/libs/libttf/arch/win16/makedep b/Build/source/libs/libttf/arch/win16/makedep new file mode 100644 index 00000000000..594952bd2a1 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/makedep @@ -0,0 +1,32 @@ +# makedep +# +# This shell script creates a dependency file necessary for older compilers +# on the Windows 16-bit platform. + +echo "\ +# This dependency file to be used with various Windows compilers +# has been generated automatically with the script \`makedep' on +# `date +%d-%b-%Y`. +" > depend.win + +(cd ../.. + gcc -MM -Iarch/win16 -I. \ + *.c | \ + sed -e "s/\.o:/.obj:/" -e "s:/:\\\\:g") >> depend.win + +(cd ../.. + gcc -MM -Iarch/win16 -I. -Iextend \ + extend/*.c | \ + sed -e "s/^\(.*\)\.o:/extend\\\\\1.obj:/" -e "s:/:\\\\:g") >> depend.win + +echo "!ifndef __MAKE__" >> depend.win + +(cd ../.. + gcc -MM -Iarch/win16 -I. -Iextend -DTT_HUGE_PTR \ + arch/win16/*.c | \ + sed -e "s/^\(.*\)\.o:/arch\\\\win16\\\\\1.obj:/" \ + -e "s:/:\\\\:g") >> depend.win + +echo "!endif" >> depend.win + +# eof diff --git a/Build/source/libs/libttf/arch/win16/ttf.def b/Build/source/libs/libttf/arch/win16/ttf.def new file mode 100644 index 00000000000..3ebc14cddb2 --- /dev/null +++ b/Build/source/libs/libttf/arch/win16/ttf.def @@ -0,0 +1,130 @@ +; This definition file to be used to built the library as DLL +; has been generated automatically with the script `makedef' on +; 07-Mar-2000. + +LIBRARY ft14_16 +DESCRIPTION 'FreeType 1.4 16-bit DLL © 1996-2000 Turner, Wilhelm, Lemberg' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +EXPORTS + + _TT_FreeType_Version + _TT_Init_FreeType + _TT_Done_FreeType + _TT_Set_Raster_Gray_Palette + _TT_Open_Face + _TT_Open_Collection + _TT_Get_Face_Properties + _TT_Set_Face_Pointer + _TT_Get_Face_Pointer + _TT_Flush_Face + _TT_Get_Face_Metrics + _TT_Close_Face + _TT_Get_Font_Data + _TT_New_Instance + _TT_Set_Instance_Resolutions + _TT_Set_Instance_CharSize + _TT_Set_Instance_CharSizes + _TT_Set_Instance_PixelSizes + _TT_Set_Instance_Transform_Flags + _TT_Get_Instance_Metrics + _TT_Set_Instance_Pointer + _TT_Get_Instance_Pointer + _TT_Done_Instance + _TT_New_Glyph + _TT_Done_Glyph + _TT_Load_Glyph + _TT_Get_Glyph_Outline + _TT_Get_Glyph_Metrics + _TT_Get_Glyph_Big_Metrics + _TT_Get_Glyph_Bitmap + _TT_Get_Glyph_Pixmap + _TT_New_Outline + _TT_Done_Outline + _TT_Copy_Outline + _TT_Get_Outline_Bitmap + _TT_Get_Outline_Pixmap + _TT_Get_Outline_BBox + _TT_Transform_Outline + _TT_Translate_Outline + _TT_Transform_Vector + _TT_MulDiv + _TT_MulFix + _TT_Get_CharMap_Count + _TT_Get_CharMap_ID + _TT_Get_CharMap + _TT_Char_Index + _TT_Get_Name_Count + _TT_Get_Name_ID + _TT_Get_Name_String + _TT_Register_Extension + _TT_Extension_Get + _TT_Use_Stream + _TT_Done_Stream + _TT_Flush_Stream + _TT_Read_File + _TT_Seek_File + _TT_Skip_File + _TT_Read_At_File + _TT_File_Pos + _TT_Stream_Size + _TT_Null_FileFrame + _TT_Access_Frame + _TT_Check_And_Access_Frame + _TT_Forget_Frame + _TT_Get_Char + _TT_Get_Short + _TT_Get_Long + _TT_LookUp_Table + _TT_Alloc + _TT_Realloc + _TT_Free + _TT_CharMap_First + _TT_CharMap_Next + _TT_CharMap_Last + _TT_ErrToString18 + _TT_Get_Face_Gasp_Flags + _TT_Init_GDEF_Extension + _TT_Load_GDEF_Table + _TT_GDEF_Get_Glyph_Property + _TT_GDEF_Build_ClassDefinition + _TT_Init_GPOS_Extension + _TT_Load_GPOS_Table + _TT_GPOS_Select_Script + _TT_GPOS_Select_Language + _TT_GPOS_Select_Feature + _TT_GPOS_Query_Scripts + _TT_GPOS_Query_Languages + _TT_GPOS_Query_Features + _TT_GPOS_Add_Feature + _TT_GPOS_Clear_Features + _TT_GPOS_Register_Glyph_Function + _TT_GPOS_Register_MM_Function + _TT_GPOS_Apply_String + _TT_Init_GSUB_Extension + _TT_Load_GSUB_Table + _TT_GSUB_Select_Script + _TT_GSUB_Select_Language + _TT_GSUB_Select_Feature + _TT_GSUB_Query_Scripts + _TT_GSUB_Query_Languages + _TT_GSUB_Query_Features + _TT_GSUB_Add_Feature + _TT_GSUB_Clear_Features + _TT_GSUB_Register_Alternate_Function + _TT_GSUB_Apply_String + _TT_GSUB_Add_String + _TT_Init_Kerning_Extension + _TT_Get_Kerning_Directory + _TT_Load_Kerning_Table + _TT_Init_Post_Extension + _TT_Load_PS_Names + _TT_Get_PS_Name + _TT_Init_SBit_Extension + _TT_Get_Face_Bitmaps + _TT_New_SBit_Image + _TT_Done_SBit_Image + _TT_Get_SBit_Strike + _TT_Load_Glyph_Bitmap + _TT_Get_Face_Widths diff --git a/Build/source/libs/libttf/arch/win32/Makefile.BC b/Build/source/libs/libttf/arch/win32/Makefile.BC new file mode 100644 index 00000000000..a2a74d91392 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/Makefile.BC @@ -0,0 +1,161 @@ +# This file is part of the FreeType project. +# +# It builds the library for Borland C++ for Win32. +# +# You will need Borland MAKE. +# Tested with Borland C++ v.5.0 and Borland C++ builder 4.0. +# Does not work with Borland C++ 4.0, since it needs __declspec. +# +# Use this file while in the lib directory with the following statement: +# +# make -farch/win32/Makefile.BC +# +# +# A DLL version of the library can be built with +# +# make -DDLL -farch/win32/Makefile.BC dll +# +# A debug version can be obtained with +# +# make -DDEBUG -farch/win32/Makefile.BC + +ARCH = arch\win32 +FT_MAKEFILE = $(ARCH)\Makefile.BC +FT_DLL = ft14_32.dll + +CC = bcc32 +LIB = tlib /c /e +IMPLIB = implib -c + +SPURIOUS_WARNINGS = -w-nak -w-par -w-use -w-aus -w-stu -w-stv -w-cln -w-sig + +!if ! $d(DEBUG) +CFLAGS = -O2 -A -i40 -I$(ARCH);.;extend $(SPURIOUS_WARNINGS) +DLLFLAGS = -WD +!else +CFLAGS = -v -A -i40 -I$(ARCH);.;extend $(SPURIOUS_WARNINGS) +DLLFLAGS = -v -WD +!endif + +FT_DEF = $(FT_DLL:.dll=.def) +!if $d(DLL) +CFLAGS = $(CFLAGS) \ + -DEXPORT_DEF=__declspec(dllexport) -DEXPORT_FUNC=__declspec(dllexport) +!endif + + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces before the \ at end of line, +# otherwise the substitution for TLIB command line will fail. +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ + extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c\ + extend\ftxsbit.c extend\ftxgsub.c extend\ftxgpos.c\ + extend\ftxopen.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c\ + ttgload.c ttinterp.c ttload.c ttobjs.c\ + ttraster.c ttextend.c ttdebug.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Borland make does not handle $($(LIB_FILES)), and using +# -DLIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing TLIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# See ../msdos/Makefile.TC for an application. +.c.obj: + $(CC) -c -o$* @&&| + $(CFLAGS) $< +| + + +!if ! $d(DEBUG) +# Skipped if DEBUG build +all: $(OBJS_S) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_S: = + ) +| + +dll $(FT_DLL): $(OBJS_S) $(FT_DEF) +!if $d(DLL) + $(CC) @&&| + $(DLLFLAGS) -e$(FT_DLL) $(OBJS_S) +| + $(IMPLIB) libttf $(FT_DLL) +!else + $(MAKE) -DDLL -f$(FT_MAKEFILE) dll # Re-invoke with flag set. +!endif +!endif + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) libttf.lib @&&| ++ $(OBJS_M: = + ) +| + +!ifdef DEBUG +dll $(FT_DLL): $(OBJS_M) $(FT_DEF) +!if $d(DLL) + $(CC) @&&| + $(DLLFLAGS) -e$(FT_DLL) $(OBJS_M) +| + $(IMPLIB) libttf $(FT_DLL) +!else + $(MAKE) -DDEBUG -DDLL -f$(FT_MAKEFILE) dll +!endif +!endif + +install: $(FT_DLL) +!ifdef INSTALL_DIR + copy $(FT_DLL) $(INSTALL_DIR) +!else + copy $(FT_DLL) C:\WINDOWS +!endif + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + -del libttf.lib + echo -+$(**: =-+)> response + $(LIB) libttf.lib @&&| ++ $(**: = + ) +| + +$(FT_DEF): $(ARCH)\ttf.def + -copy $(ARCH)\ttf.def $(FT_DEF) + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak + -del response + -del *.def + -del *.tds + +distclean: clean + -del libttf.lib + -del *.dll + -del $(FT_DEF) + -del C:\WINDOWS\$(FT_DLL) +!if $d(INSTALL_DIR) + -del $(INSTALL_DIR)\$(FT_DLL) +!endif + +!include "$(ARCH)\depend.win" + +# end of Makefile diff --git a/Build/source/libs/libttf/arch/win32/Makefile.CL b/Build/source/libs/libttf/arch/win32/Makefile.CL new file mode 100644 index 00000000000..5b1cb14a2e7 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/Makefile.CL @@ -0,0 +1,165 @@ +# This file is part of the FreeType project. +# +# It builds the library for Microsoft Visual C++ for 32-bit Windows. +# +# You will need NMAKE. +# +# Use this file while in the lib directory with the following statement: +# +# nmake /f arch\win32\Makefile.CL +# +# +# A DLL version of the library can be built with +# +# nmake DLL=1 /f arch\win32\Makefile.CL dll +# +# Debug versions can be obtained with +# +# nmake DEBUG=1 /f arch\win32\Makefile.CL + +ARCH = arch\win32 +FT_MAKEFILE = $(ARCH)\Makefile.CL +FT_DLL = ft14_32.dll + +CC = cl /nologo +LIB = lib /nologo +LINK = link /nologo + +CFLAGS = /Za /W2 -I$(ARCH) -I. -Iextend + +!ifndef DEBUG +CFLAGS = $(CFLAGS) /Ox +DLLFLAGS = /RELEASE +!else +CFLAGS = $(CFLAGS) /Zi /Ge +DLLFLAGS = /DEBUG +!endif + +!ifdef DLL +CFLAGS = $(CFLAGS) /GD \ + /DEXPORT_DEF=__declspec(dllexport) /DEXPORT_FUNC=__declspec(dllexport) +!else +CFLAGS = $(CFLAGS) /GA +!endif + + +TTFILE = .\ttfile.c +TTMEMORY = .\ttmemory.c +TTMUTEX = .\ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +# Do not insert spaces between the file names or at end of line, otherwise +# the substitution for LIB command line will fail. Thank you. +# +SRC_X = extend\ftxgasp.c extend\ftxkern.c extend\ftxpost.c\ +extend\ftxcmap.c extend\ftxwidth.c extend\ftxerr18.c extend\ftxsbit.c\ +extend\ftxopen.c extend\ftxgsub.c extend\ftxgpos.c extend\ftxgdef.c +OBJS_X = $(SRC_X:.c=.obj) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c\ +ttgload.c ttinterp.c ttload.c ttobjs.c ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.obj) $(OBJS_X) + +SRC_S = $(ARCH)\freetype.c +OBJ_S = $(SRC_S:.c=.obj) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +# Since Microsoft's NMAKE does not handle $($(LIB_FILES)), and using +# LIB_FILES="$(OBJS_S)" will excess the capacity of COMMAND.COM, we cheat +# by constructing LIB's response file directly in the `all' target. +# +# Another solution, useful during debugging of part of the library, +# would be to include each .obj in the library as soon as it is compiled. +# See ..\msdos\Makefile.TC for an application. +.c.obj: + @$(CC) /c /Fo$@ @<< + $(CFLAGS) $*.c +<< + + +!ifndef DEBUG +# Skipped if DEBUG build +all: $(OBJS_S) + -del libttf.lib + $(LIB) /OUT:libttf.lib @<<response + $(OBJS_S) +<<KEEP + +dll $(FT_DLL): $(OBJS_S) +!ifdef DLL + $(LINK) @<<response + $(DLLFLAGS) + /DLL + /OUT:$(FT_DLL) + /IMPLIB:libttf.lib + /DEF:$(ARCH)\ttf.def + $** +<<KEEP +!else + $(MAKE) DLL=1 /f $(FT_MAKEFILE) dll # Re-invoke with flag set. +!endif + +!endif + + +debug: $(OBJS_M) + -del libttf.lib + $(LIB) /OUT:libttf.lib @<<response + $(OBJS_M) +<<KEEP + +!ifdef DEBUG +dll $(FT_DLL): $(OBJS_M) +!ifdef DLL + $(LINK) @<<response + $(DLLFLAGS) + /DLL + /OUT:$(FT_DLL) + /IMPLIB:libttf.lib + /DEF:$(ARCH)\ttf.def + $** +<<KEEP +!else + $(MAKE) DLL=1 DEBUG=1 /f $(FT_MAKEFILE) dll # Re-invoke with flag set. +!endif +!endif + +install: $(FT_DLL) +!ifdef INSTALL_DIR + copy $(FT_DLL) $(INSTALL_DIR) +!else + copy $(FT_DLL) C:\WINDOWS +!endif + + +$(OBJ_S): $(SRC_S) $(SRC_M) + +# Not used here because it excesses the capacity of COMMAND.COM... +libttf.lib: $(LIB_FILES) + $(LIB) /OUT:$@ $** + + +clean: + -del *.obj + -del extend\*.obj + -del $(ARCH)\*.obj + -del libttf.bak + -del response + -del *.exp + -del *.pch + -del *.ilk + +distclean: clean + -del libttf.lib + -del *.dll + -del *.pdb + -del C:\WINDOWS\$(FT_DLL) +!ifdef INSTALL_DIR + -del $(INSTALL_DIR)\$(FT_DLL) +!endif + +!include "$(ARCH)\depend.win" + +# end of Makefile.CL diff --git a/Build/source/libs/libttf/arch/win32/Makefile.Min b/Build/source/libs/libttf/arch/win32/Makefile.Min new file mode 100644 index 00000000000..526adff9ee0 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/Makefile.Min @@ -0,0 +1,98 @@ +# This file is part of the FreeType project. +# +# It builds the library for MinGW32 gcc under Win9x. +# +# You will need a port of GNU make; the MinGW32 port works. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/win32/Makefile.Min +# +# +# When compared to the other Makefiles for gcc, there is a difference +# here, because COMMAND.COM on Win 9x is not able to process more than +# 126 characters. So the command line for ar use the * shell character. +# +# This is not as safe as normal, because unnecessary files may be +# included by mistake in the library. +# The normal behaviour can be restored by defining NON_LIMITED_SHELL=1 + +ARCH = arch/win32 +FT_MAKEFILE = $(ARCH)/Makefile.Min + +CC = gcc + +ifdef DEBUG +CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend +else +CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend +endif + + +TTFILE = ./ttfile.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ + extend/ftxopen.c extend/ftxerr18.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=$(OBJS_S) OBJ_LOC=$(ARCH) libttf.a + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=$(OBJS_M) DEBUG=1 OBJ_LOC=. libttf.a + +$(OBJ_S): $(SRC_S) $(SRC_M) + +ifdef NOT_LIMITED_SHELL +libttf.a: $(LIB_FILES) + -del $@ + ar src $@ $^ +else +# The previous command exceeds the capacity of COMMAND.COM, +# so we cheat by passing * character to ar +libttf.a: $(LIB_FILES) + -del $@ + ar src $@ $(OBJ_LOC)/*.o extend/*.o +endif + + +clean: + -del *.o + -del extend\*.o + -del $(subst /,\,$(ARCH)\*.o) + -del response + +distclean: clean + -del dep.end + -del libttf.a + +depend: $(SRS_S) $(SRC_M) $(SRC_X) + $(CC) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile.Min diff --git a/Build/source/libs/libttf/arch/win32/Makefile.VC b/Build/source/libs/libttf/arch/win32/Makefile.VC new file mode 100644 index 00000000000..7974aa734d8 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/Makefile.VC @@ -0,0 +1,195 @@ +# Visual C++ 2.x, 4.x, 5.0 and 6.0 makefile for freetype +# adapted from suns example makefile (related to the TCL script language) + +# Does not depend on the presence of any environment variables in +# order to compile freetype; all needed information is derived from +# location of the compiler directories. + +# +# Project directories +# +# ROOT = top of source tree +# +# TMPDIR = location where .obj files should be stored during build +# +# TOOLS32 = location of VC++ 32-bit development tools. Note that the +# VC++ 2.0 header files are broken, so you need to use the +# ones that come with the developer network CD's, or later +# versions of VC++. +# + +ROOT = ..\.. +TMPDIR = . +#TOOLS32 = c:\msdev # VC++ 2.x,4.x +#TOOLS32 = c:\Program Files\devstudio\vc # VC++ 5.x +TOOLS32 = c:\Program Files\Microsoft Visual Studio\Vc98 # VC++ 6.x +INSTALLDIR = c:\WINNT\SYSTEM32 + +# Set this to the appropriate value of /MACHINE: for your platform +MACHINE = IX86 + +# Comment the following line to compile with symbols +NODEBUG=1 + + +###################################################################### +# Do not modify below this line +###################################################################### + +TTF = ttf +TTFLIB = $(TTF).lib +TTFDLL = $(TTF).dll + +TTFOBJS = \ + $(TMPDIR)\ttapi.obj \ + $(TMPDIR)\ttcache.obj \ + $(TMPDIR)\ttcalc.obj \ + $(TMPDIR)\ttcmap.obj \ + $(TMPDIR)\ttdebug.obj \ + $(TMPDIR)\ttfile.obj \ + $(TMPDIR)\ttgload.obj \ + $(TMPDIR)\ttinterp.obj \ + $(TMPDIR)\ttload.obj \ + $(TMPDIR)\ttmemory.obj \ + $(TMPDIR)\ttmutex.obj \ + $(TMPDIR)\ttobjs.obj \ + $(TMPDIR)\ttraster.obj \ + $(TMPDIR)\ttextend.obj \ + $(TMPDIR)\ftxcmap.obj \ + $(TMPDIR)\ftxgasp.obj \ + $(TMPDIR)\ftxkern.obj \ + $(TMPDIR)\ftxpost.obj \ + $(TMPDIR)\ftxwidth.obj \ + $(TMPDIR)\ftxerr18.obj + + +PATH=$(TOOLS32)\bin;$(PATH) + +cc32 = "$(TOOLS32)\bin\cl.exe" +link32 = "$(TOOLS32)\bin\link.exe" +include32 = "-I$(TOOLS32)\include" -I$(ROOT)\arch\win32 +CP = copy +RM = del + +TTF_INCLUDES = -I$(ROOT) +TTF_DEFINES = -nologo -D__WIN32__ -D__WIN32DLL__ + +TTF_CFLAGS = $(cdebug) $(cflags) $(cvarsdll) $(include32) \ + $(TTF_INCLUDES) $(TTF_DEFINES) +CON_CFLAGS = $(cdebug) $(cflags) $(cvars) $(include32) -DCONSOLE +DOS_CFLAGS = $(cdebug) $(cflags) $(include16) -AL + +###################################################################### +# Link flags +###################################################################### + +!IFDEF NODEBUG +ldebug = /RELEASE +!ELSE +ldebug = -debug:full -debugtype:cv +!ENDIF + +# declarations common to all linker options +lcommon = /NODEFAULTLIB /RELEASE /NOLOGO + +# declarations for use on Intel i386, i486, and Pentium systems +!IF "$(MACHINE)" == "IX86" +DLLENTRY = @12 +lflags = $(lcommon) /MACHINE:$(MACHINE) +!ELSE +lflags = $(lcommon) /MACHINE:$(MACHINE) +!ENDIF + +conlflags = $(lflags) -subsystem:console -entry:mainCRTStartup +guilflags = $(lflags) -subsystem:windows -entry:WinMainCRTStartup +dlllflags = $(lflags) -entry:_DllMainCRTStartup$(DLLENTRY) -dll + +!IF "$(MACHINE)" == "PPC" +libc = libc.lib +libcdll = crtdll.lib +!ELSE +libc = libc.lib oldnames.lib +libcdll = msvcrt.lib oldnames.lib +!ENDIF + +baselibs = kernel32.lib $(optlibs) advapi32.lib +winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib + +guilibs = $(libc) $(winlibs) +conlibs = $(libc) $(baselibs) +guilibsdll = $(libcdll) $(winlibs) +conlibsdll = $(libcdll) $(baselibs) + +###################################################################### +# Compile flags +###################################################################### + +!IFDEF NODEBUG +cdebug = -O2 -Gs -GD +!ELSE +cdebug = -Z7 -Od -WX +!ENDIF + +# declarations common to all compiler options +ccommon = -c -W3 -nologo -YX -Dtry=__try -Dexcept=__except + +# NEED BYTEORDER INFORMATION HERE !! +!IF "$(MACHINE)" == "IX86" +cflags = $(ccommon) -D_X86_=1 +!ELSE +!IF "$(MACHINE)" == "MIPS" +cflags = $(ccommon) -D_MIPS_=1 +!ELSE +!IF "$(MACHINE)" == "PPC" +cflags = $(ccommon) -D_PPC_=1 +!ELSE +!IF "$(MACHINE)" == "ALPHA" +cflags = $(ccommon) -D_ALPHA_=1 +!ENDIF +!ENDIF +!ENDIF +!ENDIF + +cvars = -DWIN32 -D_WIN32 +cvarsmt = $(cvars) -D_MT +cvarsdll = $(cvarsmt) -D_DLL + +###################################################################### +# Project specific targets +###################################################################### + +release: $(TTFDLL) +all: $(TTFDLL) + +install: $(TTFDLL) + -@md $(INSTALLDIR) + -@$(CP) $(TTFDLL) $(INSTALLDIR) + + + +$(TTFDLL): $(TTFOBJS) ttf.def + $(link32) $(ldebug) $(dlllflags) \ + $(guilibsdll) -out:$(TTFDLL) -def:ttf.def $(TTFOBJS) + +#ttf.def: $(TTFOBJS) +# ..\..\tcl8.0.4\win\release\dumpexts -o $@ ttf.dll $(TTFOBJS) + + +# +# Implicit rules +# + +{$(ROOT)\extend}.c{$(TMPDIR)}.obj: + $(cc32) $(TTF_CFLAGS) -Fo$(TMPDIR)\ $< + +{$(ROOT)}.c{$(TMPDIR)}.obj: + $(cc32) $(TTF_CFLAGS) -Fo$(TMPDIR)\ $< + + +clean: + -@del *.exp + -@del *.lib + -@del *.dll + -@del $(TMPDIR)\*.obj + -@del *.pch + -@del *.pdb diff --git a/Build/source/libs/libttf/arch/win32/Makefile.gcc b/Build/source/libs/libttf/arch/win32/Makefile.gcc new file mode 100644 index 00000000000..68c9f4e6ce9 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/Makefile.gcc @@ -0,0 +1,96 @@ +# This file is part of the FreeType project. +# +# It builds the library for gcc under Win32. +# This Makefile will fail with MinGW32 ports of gcc and make under +# bare-bones Windows 9X, because of the limitations of command.com. +# Use Makefile.min instead. +# +# You will need GNU make. +# +# Use this file while in the lib directory with the following statement: +# +# make -f arch/win32/Makefile.gcc +# +# +# If you have the GNU gettext package installed, you can also try +# +# make -f arch/win32/Makefile.gcc HAVE_GETTEXT + +ARCH = arch/win32 +FT_MAKEFILE = $(ARCH)/Makefile.gcc + +CC = gcc + +ifndef GETTEXT +GETTEXT=NO_GETTEXT +endif + +ifdef DEBUG +CFLAGS = -Wall -O2 -g -ansi -pedantic -I$(ARCH) -I. -Iextend -D$(GETTEXT) +else +CFLAGS = -Wall -ansi -pedantic -O2 -s -I$(ARCH) -I. -Iextend -D$(GETTEXT) +endif + + +TTFILE = ./ttfile.c +TTMEMORY = ./ttmemory.c +TTMUTEX = ./ttmutex.c + +PORT = $(TTFILE) $(TTMEMORY) $(TTMUTEX) + +SRC_X = extend/ftxgasp.c extend/ftxkern.c extend/ftxpost.c \ + extend/ftxcmap.c extend/ftxwidth.c extend/ftxsbit.c \ + extend/ftxgsub.c extend/ftxgpos.c extend/ftxgdef.c \ + extend/ftxopen.c extend/ftxerr18.c +OBJS_X = $(SRC_X:.c=.o) + +SRC_M = ttapi.c ttcache.c ttcalc.c ttcmap.c ttdebug.c \ + ttgload.c ttinterp.c ttload.c ttobjs.c \ + ttraster.c ttextend.c $(PORT) +OBJS_M = $(SRC_M:.c=.o) $(OBJS_X) + +SRC_S = $(ARCH)/freetype.c +OBJ_S = $(SRC_S:.c=.o) +OBJS_S = $(OBJ_S) $(OBJS_X) + + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: all debug clean distclean depend + + +all: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S libttf.a + +debug: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_M DEBUG=1 libttf.a + +HAVE_GETTEXT: + $(MAKE) -f $(FT_MAKEFILE) LIB_FILES=OBJS_S GETTEXT=HAVE_GETTEXT \ + libttf.a + +$(OBJ_S): $(SRC_S) $(SRC_M) + +libttf.a: $($(LIB_FILES)) + -del $@ + ar src $@ $^ + +clean: + -del *.o + -del extend\*.o + -del $(subst /,\,$(ARCH)/*.o) + -del response + +distclean: clean + -del dep.end + -del libttf.a + +depend: $(SRS_S) $(SRC_M) $(SRC_X) + $(CC) -E -M $^ > dep.end + +ifeq (dep.end,$(wildcard dep.end)) + include dep.end +endif + +# end of Makefile.gcc diff --git a/Build/source/libs/libttf/arch/win32/depend.win b/Build/source/libs/libttf/arch/win32/depend.win new file mode 100644 index 00000000000..3f81600d244 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/depend.win @@ -0,0 +1,103 @@ +# This dependency file to be used with various Win32 compilers +# has been generated automatically with the script `makedep' on +# 07-Mar-2000. + +ttapi.obj: ttapi.c ttconfig.h arch\win32\ft_conf.h freetype.h fterrid.h \ + ftnameid.h ttengine.h tttypes.h ttmutex.h ttcalc.h ttmemory.h \ + ttcache.h ttfile.h ttdebug.h ttobjs.h tttables.h ttcmap.h ttload.h \ + ttgload.h ttraster.h ttextend.h +ttcache.obj: ttcache.c ttengine.h tttypes.h ttconfig.h \ + arch\win32\ft_conf.h freetype.h fterrid.h ftnameid.h ttmutex.h \ + ttmemory.h ttcache.h ttobjs.h tttables.h ttcmap.h ttdebug.h +ttcalc.obj: ttcalc.c ttcalc.h ttconfig.h arch\win32\ft_conf.h freetype.h \ + fterrid.h ftnameid.h ttdebug.h tttypes.h tttables.h +ttcmap.obj: ttcmap.c ttobjs.h ttconfig.h arch\win32\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttdebug.h ttfile.h ttmemory.h ttload.h +ttdebug.obj: ttdebug.c ttdebug.h ttconfig.h arch\win32\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h tttables.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h ttcmap.h +ttextend.obj: ttextend.c ttextend.h ttconfig.h arch\win32\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttmemory.h +ttfile.obj: ttfile.c ttconfig.h arch\win32\ft_conf.h freetype.h \ + fterrid.h ftnameid.h tttypes.h ttdebug.h ttengine.h ttmutex.h \ + ttmemory.h ttfile.h +ttgload.obj: ttgload.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h ttgload.h \ + ttmemory.h tttags.h ttload.h +ttinterp.obj: ttinterp.c freetype.h fterrid.h ftnameid.h tttypes.h \ + ttconfig.h arch\win32\ft_conf.h ttdebug.h ttcalc.h ttmemory.h \ + ttinterp.h ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h \ + ttcmap.h +ttload.obj: ttload.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h \ + ttengine.h ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h \ + ttmemory.h tttags.h ttload.h +ttmemory.obj: ttmemory.c ttdebug.h ttconfig.h arch\win32\ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmemory.h ttengine.h \ + ttmutex.h +ttmutex.obj: ttmutex.c ttmutex.h ttconfig.h arch\win32\ft_conf.h +ttobjs.obj: ttobjs.c ttobjs.h ttconfig.h arch\win32\ft_conf.h ttengine.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttfile.h ttdebug.h ttcalc.h ttmemory.h ttload.h \ + ttinterp.h ttextend.h +ttraster.obj: ttraster.c ttraster.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttengine.h tttypes.h ttmutex.h \ + ttdebug.h ttcalc.h ttmemory.h +extend\ftxcmap.obj: extend\ftxcmap.c extend\ftxcmap.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win32\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxerr18.obj: extend\ftxerr18.c ttconfig.h arch\win32\ft_conf.h \ + extend\ftxerr18.h freetype.h fterrid.h ftnameid.h extend\ftxkern.h \ + extend\ftxpost.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h +extend\ftxgasp.obj: extend\ftxgasp.c extend\ftxgasp.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win32\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h +extend\ftxgdef.obj: extend\ftxgdef.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgpos.obj: extend\ftxgpos.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxgsub.obj: extend\ftxgsub.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttags.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxkern.obj: extend\ftxkern.c extend\ftxkern.h freetype.h fterrid.h \ + ftnameid.h ttextend.h ttconfig.h arch\win32\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttdebug.h \ + ttmemory.h ttfile.h ttload.h tttags.h +extend\ftxopen.obj: extend\ftxopen.c tttypes.h ttconfig.h arch\win32\ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttload.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h tttables.h ttcmap.h ttextend.h ttmemory.h \ + ttfile.h ttdebug.h extend\ftxopen.h extend\ftxgdef.h extend\ftxgsub.h \ + extend\ftxgpos.h extend\ftxopenf.h +extend\ftxpost.obj: extend\ftxpost.c extend\ftxpost.h freetype.h fterrid.h \ + ftnameid.h tttypes.h ttconfig.h arch\win32\ft_conf.h ttobjs.h \ + ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttload.h ttfile.h \ + ttdebug.h tttags.h ttmemory.h ttextend.h +extend\ftxsbit.obj: extend\ftxsbit.c extend\ftxsbit.h freetype.h fterrid.h \ + ftnameid.h ttobjs.h ttconfig.h arch\win32\ft_conf.h ttengine.h \ + tttypes.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h ttdebug.h \ + ttload.h ttmemory.h tttags.h ttextend.h +extend\ftxwidth.obj: extend\ftxwidth.c extend\ftxwidth.h freetype.h fterrid.h \ + ftnameid.h ttdebug.h ttconfig.h arch\win32\ft_conf.h tttypes.h \ + ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h ttfile.h \ + tttags.h ttload.h +!ifndef __MAKE__ +arch\win32\freetype.obj: arch\win32\freetype.c ttapi.c ttconfig.h \ + arch\win32\ft_conf.h freetype.h fterrid.h ftnameid.h ttengine.h \ + tttypes.h ttmutex.h ttcalc.h ttmemory.h ttcache.h ttfile.h ttdebug.h \ + ttobjs.h tttables.h ttcmap.h ttload.h ttgload.h ttraster.h ttextend.h \ + ttcache.c ttcalc.c ttcmap.c ttdebug.c ttgload.c tttags.h ttinterp.c \ + ttinterp.h ttload.c ttobjs.c ttraster.c ttfile.c ttmemory.c ttmutex.c \ + ttextend.c +!endif diff --git a/Build/source/libs/libttf/arch/win32/freetype.c b/Build/source/libs/libttf/arch/win32/freetype.c new file mode 100644 index 00000000000..8c391a77a8b --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.c @@ -0,0 +1,42 @@ +/* This file is part of the FreeType project */ + +/* single object library component for Win32 */ +#define TT_MAKE_OPTION_SINGLE_OBJECT + +/* Note, you should define the EXPORT_DEF and EXPORT_FUNC macros */ +/* here if you want to build a Win32 DLL. If undefined, the */ +/* macros default to "extern"/"" (nothing), which is suitable */ +/* for static libraries. See `ttconfig.h' for details. */ + +/* The macro EXPORT_DEF is placed before each high-level API */ +/* function declaration, and EXPORT_FUNC before each definition */ +/* (body). You can then use it to take any compiler-specific */ +/* pragma for DLL-exported symbols */ + +/* first include common core components */ + +#include "ttapi.c" +#include "ttcache.c" +#include "ttcalc.c" +#include "ttcmap.c" +#include "ttdebug.c" +#include "ttgload.c" +#include "ttinterp.c" +#include "ttload.c" +#include "ttobjs.c" +#include "ttraster.c" + +/* then system-specific (or ANSI) components */ + +#include "ttfile.c" +#include "ttmemory.c" +#include "ttmutex.c" + +/* finally, add some extensions */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.c" +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/arch/win32/freetype.dsp b/Build/source/libs/libttf/arch/win32/freetype.dsp new file mode 100644 index 00000000000..38b3068bdb9 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.dsp @@ -0,0 +1,208 @@ +# Microsoft Developer Studio Project File - Name="freetype" - Package Owner=<4> + +# Microsoft Developer Studio Generated Build File, Format Version 5.00 + +# ** DO NOT EDIT ** + + + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + + + +CFG=freetype - Win32 Debug + +!MESSAGE This is not a valid makefile. To build this project using NMAKE, + +!MESSAGE use the Export Makefile command and run + +!MESSAGE + +!MESSAGE NMAKE /f "freetype.mak". + +!MESSAGE + +!MESSAGE You can specify a configuration when running NMAKE + +!MESSAGE by defining the macro CFG on the command line. For example: + +!MESSAGE + +!MESSAGE NMAKE /f "freetype.mak" CFG="freetype - Win32 Debug" + +!MESSAGE + +!MESSAGE Possible choices for configuration are: + +!MESSAGE + +!MESSAGE "freetype - Win32 Release" (based on "Win32 (x86) Static Library") + +!MESSAGE "freetype - Win32 Debug" (based on "Win32 (x86) Static Library") + +!MESSAGE + + + +# Begin Project + +# PROP Scc_ProjName "" + +# PROP Scc_LocalPath "" + +CPP=cl.exe + + + +!IF "$(CFG)" == "freetype - Win32 Release" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 0 + +# PROP BASE Output_Dir "Release" + +# PROP BASE Intermediate_Dir "Release" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 0 + +# PROP Output_Dir "Release" + +# PROP Intermediate_Dir "Release" + +# PROP Target_Dir "" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c + +# ADD CPP /nologo /W3 /GX /O1 /I "." /I "..\.." /I "..\..\extend" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c + +# SUBTRACT CPP /YX + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + + + +!ELSEIF "$(CFG)" == "freetype - Win32 Debug" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 1 + +# PROP BASE Output_Dir "Debug" + +# PROP BASE Intermediate_Dir "Debug" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 1 + +# PROP Output_Dir "Debug" + +# PROP Intermediate_Dir "Debug" + +# PROP Target_Dir "" + +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c + +# ADD CPP /nologo /W3 /GX /Zi /O1 /I "." /I "..\.." /I "..\..\extend" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c + +# SUBTRACT CPP /YX + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + + + +!ENDIF + + + +# Begin Target + + + +# Name "freetype - Win32 Release" + +# Name "freetype - Win32 Debug" + +# Begin Source File + + + +SOURCE=.\freetype.c + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\Extend\Ftxcmap.c + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\Extend\ftxerr18.c + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\Extend\Ftxgasp.c + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\Extend\Ftxkern.c + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\Extend\ftxpost.c + +# End Source File + +# End Target + +# End Project + diff --git a/Build/source/libs/libttf/arch/win32/freetype.dsw b/Build/source/libs/libttf/arch/win32/freetype.dsw new file mode 100644 index 00000000000..43933921a5a --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.dsw @@ -0,0 +1,58 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 + +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + + + +############################################################################### + + + +Project: "freetype"=.\freetype.dsp - Package Owner=<4> + + + +Package=<5> + +{{{ + +}}} + + + +Package=<4> + +{{{ + +}}} + + + +############################################################################### + + + +Global: + + + +Package=<5> + +{{{ + +}}} + + + +Package=<3> + +{{{ + +}}} + + + +############################################################################### + + + diff --git a/Build/source/libs/libttf/arch/win32/freetype.ide b/Build/source/libs/libttf/arch/win32/freetype.ide Binary files differnew file mode 100644 index 00000000000..f5c4043e572 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.ide diff --git a/Build/source/libs/libttf/arch/win32/freetype.mak b/Build/source/libs/libttf/arch/win32/freetype.mak new file mode 100644 index 00000000000..2cb684e20ab --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +!IF "$(CFG)" == "" +CFG=freetype - Win32 Debug +!MESSAGE No configuration specified. Defaulting to freetype - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "freetype - Win32 Release" && "$(CFG)" !=\ + "freetype - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "freetype.mak" CFG="freetype - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "freetype - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "freetype - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "freetype - Win32 Debug" +CPP=cl.exe + +!IF "$(CFG)" == "freetype - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\freetype.lib" + +CLEAN : + -@erase ".\Release\freetype.lib" + -@erase ".\Release\Ftxkern.obj" + -@erase ".\Release\ftxpost.obj" + -@erase ".\Release\ftxerr18.obj" + -@erase ".\Release\Ftxcmap.obj" + -@erase ".\Release\Freetype.obj" + -@erase ".\Release\Ftxgasp.obj" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I "..\.." /I "..\..\extend" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "." /I "..\.." /I "..\..\extend" /D "WIN32"\ + /D "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)/freetype.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS= +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/freetype.bsc" +BSC32_SBRS= +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +LIB32_FLAGS=/nologo /out:"$(OUTDIR)/freetype.lib" +LIB32_OBJS= \ + "$(INTDIR)/Ftxkern.obj" \ + "$(INTDIR)/ftxpost.obj" \ + "$(INTDIR)/ftxerr18.obj" \ + "$(INTDIR)/Ftxcmap.obj" \ + "$(INTDIR)/Freetype.obj" \ + "$(INTDIR)/Ftxgasp.obj" + +"$(OUTDIR)\freetype.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ELSEIF "$(CFG)" == "freetype - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\freetype.lib" + +CLEAN : + -@erase ".\Debug\freetype.lib" + -@erase ".\Debug\Freetype.obj" + -@erase ".\Debug\Ftxkern.obj" + -@erase ".\Debug\ftxpost.obj" + -@erase ".\Debug\Ftxcmap.obj" + -@erase ".\Debug\Ftxgasp.obj" + -@erase ".\Debug\ftxerr18.obj" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "." /I "..\.." /I "..\..\extend" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MLd /W3 /GX /Z7 /Od /I "." /I "..\.." /I "..\..\extend" /D\ + "WIN32" /D "_DEBUG" /D "_WINDOWS" /Fp"$(INTDIR)/freetype.pch" /YX\ + /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS= +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/freetype.bsc" +BSC32_SBRS= +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +LIB32_FLAGS=/nologo /out:"$(OUTDIR)/freetype.lib" +LIB32_OBJS= \ + "$(INTDIR)/Freetype.obj" \ + "$(INTDIR)/Ftxkern.obj" \ + "$(INTDIR)/ftxpost.obj" \ + "$(INTDIR)/Ftxcmap.obj" \ + "$(INTDIR)/Ftxgasp.obj" \ + "$(INTDIR)/ftxerr18.obj" + +"$(OUTDIR)\freetype.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "freetype - Win32 Release" +# Name "freetype - Win32 Debug" + +!IF "$(CFG)" == "freetype - Win32 Release" + +!ELSEIF "$(CFG)" == "freetype - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=\Freetype\Lib\Extend\ftxpost.c +DEP_CPP_FTXPO=\ + ".\..\..\Extend\ftxpost.h"\ + ".\..\..\tttypes.h"\ + ".\..\..\ttobjs.h"\ + ".\..\..\tttables.h"\ + ".\..\..\ttload.h"\ + ".\..\..\ttfile.h"\ + ".\..\..\tttags.h"\ + ".\..\..\ttmemory.h"\ + ".\..\..\ttextend.h"\ + ".\..\..\freetype.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + "..\..\ttengine.h"\ + "..\..\ttmutex.h"\ + "..\..\ttcache.h"\ + "..\..\ttcmap.h"\ + ".\..\..\ttdebug.h"\ + + +"$(INTDIR)\ftxpost.obj" : $(SOURCE) $(DEP_CPP_FTXPO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\Freetype\Lib\Extend\ftxerr18.c +DEP_CPP_FTXER=\ + ".\..\..\Extend\ftxerr18.h"\ + ".\..\..\Extend\ftxkern.h"\ + ".\..\..\Extend\ftxpost.h"\ + ".\..\..\freetype.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + + +"$(INTDIR)\ftxerr18.obj" : $(SOURCE) $(DEP_CPP_FTXER) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\Freetype\Lib\Extend\Ftxgasp.c +DEP_CPP_FTXGA=\ + ".\..\..\Extend\ftxgasp.h"\ + ".\..\..\tttypes.h"\ + ".\..\..\ttobjs.h"\ + ".\..\..\tttables.h"\ + ".\..\..\freetype.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + "..\..\ttengine.h"\ + "..\..\ttmutex.h"\ + "..\..\ttcache.h"\ + "..\..\ttcmap.h"\ + + +"$(INTDIR)\Ftxgasp.obj" : $(SOURCE) $(DEP_CPP_FTXGA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\Freetype\Lib\Extend\Ftxkern.c +DEP_CPP_FTXKE=\ + ".\..\..\Extend\ftxkern.h"\ + ".\..\..\ttextend.h"\ + ".\..\..\tttypes.h"\ + ".\..\..\ttdebug.h"\ + ".\..\..\ttmemory.h"\ + ".\..\..\ttfile.h"\ + ".\..\..\ttobjs.h"\ + ".\..\..\ttload.h"\ + ".\..\..\tttags.h"\ + ".\..\..\freetype.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + "..\..\ttengine.h"\ + "..\..\ttmutex.h"\ + "..\..\ttcache.h"\ + ".\..\..\tttables.h"\ + "..\..\ttcmap.h"\ + + +"$(INTDIR)\Ftxkern.obj" : $(SOURCE) $(DEP_CPP_FTXKE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=\Freetype\Lib\Extend\Ftxcmap.c +DEP_CPP_FTXCM=\ + ".\..\..\Extend\ftxcmap.h"\ + ".\..\..\tttypes.h"\ + ".\..\..\ttobjs.h"\ + ".\..\..\tttables.h"\ + ".\..\..\freetype.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + "..\..\ttengine.h"\ + "..\..\ttmutex.h"\ + "..\..\ttcache.h"\ + "..\..\ttcmap.h"\ + + +"$(INTDIR)\Ftxcmap.obj" : $(SOURCE) $(DEP_CPP_FTXCM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Freetype.c +DEP_CPP_FREET=\ + ".\..\..\ttapi.c"\ + ".\..\..\ttcache.c"\ + ".\..\..\ttcalc.c"\ + ".\..\..\ttcmap.c"\ + ".\..\..\ttgload.c"\ + ".\..\..\ttinterp.c"\ + ".\..\..\ttload.c"\ + ".\..\..\ttobjs.c"\ + ".\..\..\ttraster.c"\ + ".\..\..\ttfile.c"\ + ".\..\..\ttmemory.c"\ + ".\..\..\ttmutex.c"\ + ".\..\..\ttextend.c"\ + ".\..\..\freetype.h"\ + "..\..\ttengine.h"\ + "..\..\ttcalc.h"\ + ".\..\..\ttmemory.h"\ + "..\..\ttcache.h"\ + ".\..\..\ttfile.h"\ + ".\..\..\ttobjs.h"\ + ".\..\..\ttload.h"\ + "..\..\ttgload.h"\ + "..\..\ttraster.h"\ + ".\..\..\ttextend.h"\ + "..\..\ttconfig.h"\ + ".\ft_conf.h"\ + "..\..\ttmutex.h"\ + ".\..\..\tttypes.h"\ + ".\..\..\ttdebug.h"\ + ".\..\..\tttables.h"\ + "..\..\ttcmap.h"\ + ".\..\..\tttags.h"\ + "..\..\ttinterp.h"\ + {$(INCLUDE)}"\unistd.h"\ + + +"$(INTDIR)\Freetype.obj" : $(SOURCE) $(DEP_CPP_FREET) "$(INTDIR)" + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/Build/source/libs/libttf/arch/win32/freetype.mdp b/Build/source/libs/libttf/arch/win32/freetype.mdp Binary files differnew file mode 100644 index 00000000000..9082b5a70a9 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/freetype.mdp diff --git a/Build/source/libs/libttf/arch/win32/ft_conf.h b/Build/source/libs/libttf/arch/win32/ft_conf.h new file mode 100644 index 00000000000..63819dd95c5 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/ft_conf.h @@ -0,0 +1,210 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for Win32 */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +#ifndef WIN32 +#define WIN32 +#endif + +/* Define to empty if the 'const' keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/arch/win32/makedef b/Build/source/libs/libttf/arch/win32/makedef new file mode 100644 index 00000000000..158f10faa2f --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/makedef @@ -0,0 +1,24 @@ +# makedef +# +# This shell script creates a .DEF file necessary for building as DLL +# on the Windows 32-bit platform. + +echo "\ +; This definition file to be used to built the library as DLL +; has been generated automatically with the script \`makedef' on +; `date +%d-%b-%Y`. + +LIBRARY ft14_32 +DESCRIPTION 'FreeType 1.4 32-bit DLL © 1996-2000 Turner, Wilhelm, Lemberg' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +EXPORTS +" > ttf.def + +(cd ../.. + sed -n -e "/^ *EXPORT_DEF/!d ; n ; s/(.*$//" \ + -e "s/;$//" -e "s/ const / /" -e "s/ *[a-zA-Z][a-zA-Z_\*]* //" \ + -e "s/ *//g" -e "s/^/ /" -e "p" *.h extend/*.h) >> ttf.def + +# eof diff --git a/Build/source/libs/libttf/arch/win32/makedep b/Build/source/libs/libttf/arch/win32/makedep new file mode 100644 index 00000000000..34ade91f25b --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/makedep @@ -0,0 +1,29 @@ +# makedep +# +# This shell script creates a dependency file necessary for some compilers +# on the Win32 platform. + +echo "\ +# This dependency file to be used with various Win32 compilers +# has been generated automatically with the script \`makedep' on +# `date +%d-%b-%Y`. +" > depend.win + +(cd ../.. + gcc -MM -Iarch/win32 -I. *.c | \ + sed -e "s/\.o:/.obj:/" -e "s:/:\\\\:g") >> depend.win + +(cd ../.. + gcc -MM -Iarch/win32 -I. -Iextend extend/*.c | \ + sed -e "s/^\(.*\)\.o:/extend\\\\\1.obj:/" -e "s:/:\\\\:g") >> depend.win + +echo "!ifndef __MAKE__" >> depend.win + +(cd ../.. + gcc -MM -Iarch/win32 -I. -Iextend arch/win32/*.c | \ + sed -e "s/^\(.*\)\.o:/arch\\\\win32\\\\\1.obj:/" \ + -e "s:/:\\\\:g") >> depend.win + +echo "!endif" >> depend.win + +# eof diff --git a/Build/source/libs/libttf/arch/win32/ttf.def b/Build/source/libs/libttf/arch/win32/ttf.def new file mode 100644 index 00000000000..96fe92f2482 --- /dev/null +++ b/Build/source/libs/libttf/arch/win32/ttf.def @@ -0,0 +1,130 @@ +; This definition file to be used to built the library as DLL +; has been generated automatically with the script `makedef' on +; 07-Mar-2000. + +LIBRARY ft14_32 +DESCRIPTION 'FreeType 1.4 32-bit DLL © 1996-2000 Turner, Wilhelm, Lemberg' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +EXPORTS + + TT_FreeType_Version + TT_Init_FreeType + TT_Done_FreeType + TT_Set_Raster_Gray_Palette + TT_Open_Face + TT_Open_Collection + TT_Get_Face_Properties + TT_Set_Face_Pointer + TT_Get_Face_Pointer + TT_Flush_Face + TT_Get_Face_Metrics + TT_Close_Face + TT_Get_Font_Data + TT_New_Instance + TT_Set_Instance_Resolutions + TT_Set_Instance_CharSize + TT_Set_Instance_CharSizes + TT_Set_Instance_PixelSizes + TT_Set_Instance_Transform_Flags + TT_Get_Instance_Metrics + TT_Set_Instance_Pointer + TT_Get_Instance_Pointer + TT_Done_Instance + TT_New_Glyph + TT_Done_Glyph + TT_Load_Glyph + TT_Get_Glyph_Outline + TT_Get_Glyph_Metrics + TT_Get_Glyph_Big_Metrics + TT_Get_Glyph_Bitmap + TT_Get_Glyph_Pixmap + TT_New_Outline + TT_Done_Outline + TT_Copy_Outline + TT_Get_Outline_Bitmap + TT_Get_Outline_Pixmap + TT_Get_Outline_BBox + TT_Transform_Outline + TT_Translate_Outline + TT_Transform_Vector + TT_MulDiv + TT_MulFix + TT_Get_CharMap_Count + TT_Get_CharMap_ID + TT_Get_CharMap + TT_Char_Index + TT_Get_Name_Count + TT_Get_Name_ID + TT_Get_Name_String + TT_Register_Extension + TT_Extension_Get + TT_Use_Stream + TT_Done_Stream + TT_Flush_Stream + TT_Read_File + TT_Seek_File + TT_Skip_File + TT_Read_At_File + TT_File_Pos + TT_Stream_Size + TT_Null_FileFrame + TT_Access_Frame + TT_Check_And_Access_Frame + TT_Forget_Frame + TT_Get_Char + TT_Get_Short + TT_Get_Long + TT_LookUp_Table + TT_Alloc + TT_Realloc + TT_Free + TT_CharMap_First + TT_CharMap_Next + TT_CharMap_Last + TT_ErrToString18 + TT_Get_Face_Gasp_Flags + TT_Init_GDEF_Extension + TT_Load_GDEF_Table + TT_GDEF_Get_Glyph_Property + TT_GDEF_Build_ClassDefinition + TT_Init_GPOS_Extension + TT_Load_GPOS_Table + TT_GPOS_Select_Script + TT_GPOS_Select_Language + TT_GPOS_Select_Feature + TT_GPOS_Query_Scripts + TT_GPOS_Query_Languages + TT_GPOS_Query_Features + TT_GPOS_Add_Feature + TT_GPOS_Clear_Features + TT_GPOS_Register_Glyph_Function + TT_GPOS_Register_MM_Function + TT_GPOS_Apply_String + TT_Init_GSUB_Extension + TT_Load_GSUB_Table + TT_GSUB_Select_Script + TT_GSUB_Select_Language + TT_GSUB_Select_Feature + TT_GSUB_Query_Scripts + TT_GSUB_Query_Languages + TT_GSUB_Query_Features + TT_GSUB_Add_Feature + TT_GSUB_Clear_Features + TT_GSUB_Register_Alternate_Function + TT_GSUB_Apply_String + TT_GSUB_Add_String + TT_Init_Kerning_Extension + TT_Get_Kerning_Directory + TT_Load_Kerning_Table + TT_Init_Post_Extension + TT_Load_PS_Names + TT_Get_PS_Name + TT_Init_SBit_Extension + TT_Get_Face_Bitmaps + TT_New_SBit_Image + TT_Done_SBit_Image + TT_Get_SBit_Strike + TT_Load_Glyph_Bitmap + TT_Get_Face_Widths diff --git a/Build/source/libs/libttf/depend.mak b/Build/source/libs/libttf/depend.mak new file mode 100644 index 00000000000..51d25bb2114 --- /dev/null +++ b/Build/source/libs/libttf/depend.mak @@ -0,0 +1,52 @@ +# DO NOT DELETE + +$(objdir)/ttapi.obj: ttapi.c ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttengine.h tttypes.h ttmutex.h ttcalc.h \ + ttmemory.h \ + ttcache.h ttfile.h ttdebug.h ttobjs.h tttables.h ttcmap.h ttload.h \ + ttgload.h ttraster.h ttextend.h +$(objdir)/ttcache.obj: ttcache.c ttengine.h tttypes.h ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttmutex.h ttmemory.h \ + ttcache.h ttobjs.h tttables.h ttcmap.h ttdebug.h +$(objdir)/ttcalc.obj: ttcalc.c ttcalc.h ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h tttypes.h tttables.h +$(objdir)/ttcmap.obj: ttcmap.c ttobjs.h ttconfig.h ft_conf.h \ + ttengine.h tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttdebug.h ttfile.h ttmemory.h \ + ttload.h +$(objdir)/ttdebug.obj: ttdebug.c ttdebug.h ttconfig.h ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h tttables.h ttobjs.h ttengine.h \ + ttmutex.h ttcache.h ttcmap.h +$(objdir)/ttextend.obj: ttextend.c ttextend.h ttconfig.h ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttobjs.h ttengine.h ttmutex.h \ + ttcache.h tttables.h ttcmap.h ttmemory.h \ + ttconfig.h +$(objdir)/ttfile.obj: ttfile.c ft_conf.h \ + freetype.h fterrid.h ftnameid.h tttypes.h ttdebug.h ttengine.h ttmutex.h \ + ttmemory.h ttfile.h +$(objdir)/ttgload.obj: ttgload.c tttypes.h ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h ttengine.h \ + ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h ttgload.h ttmemory.h \ + tttags.h ttload.h +$(objdir)/ttinterp.obj: ttinterp.c freetype.h fterrid.h ftnameid.h tttypes.h \ + ttconfig.h ft_conf.h \ + ttdebug.h ttcalc.h ttmemory.h \ + ttinterp.h ttobjs.h ttengine.h ttmutex.h ttcache.h tttables.h ttcmap.h \ + tttypes.h +$(objdir)/ttload.obj: ttload.c ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttdebug.h ttcalc.h ttfile.h ttengine.h \ + ttmutex.h tttables.h ttobjs.h ttcache.h ttcmap.h ttmemory.h \ + tttags.h ttload.h +$(objdir)/ttmemory.obj: ttmemory.c ttdebug.h ttconfig.h ft_conf.h \ + tttypes.h freetype.h fterrid.h ftnameid.h ttmemory.h \ + ttengine.h ttmutex.h +$(objdir)/ttmutex.obj: ttmutex.c ttmutex.h ttconfig.h ft_conf.h \ + ttobjs.h +$(objdir)/ttobjs.obj: ttobjs.c ttconfig.h ft_conf.h \ + ttengine.h tttypes.h freetype.h fterrid.h ftnameid.h ttmutex.h ttcache.h \ + tttables.h ttcmap.h ttfile.h ttdebug.h ttcalc.h ttmemory.h \ + ttload.h ttinterp.h ttextend.h +$(objdir)/ttraster.obj: ttraster.c ttraster.h ttconfig.h ft_conf.h \ + freetype.h fterrid.h ftnameid.h ttengine.h tttypes.h ttmutex.h ttdebug.h \ + ttcalc.h ttmemory.h \ + diff --git a/Build/source/libs/libttf/extend/ftxcmap.c b/Build/source/libs/libttf/extend/ftxcmap.c new file mode 100644 index 00000000000..09786b63d94 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxcmap.c @@ -0,0 +1,348 @@ +/******************************************************************* + * + * ftxcmap.h 1.0 + * + * API extension for iterating over Cmaps + * + * Copyright 1996-1999 by Juliusz Chroboczek, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + ******************************************************************/ + +#include "ttconfig.h" +#include "ftxcmap.h" + +#include "tttypes.h" +#include "ttobjs.h" +#include "tttables.h" + +static Long charmap_first4 ( PCMap4, UShort* ); +static Long charmap_next4 ( PCMap4, UShort, UShort* ); +static Long charmap_last4 ( PCMap4, UShort* ); +static UShort charmap_find_id4( PCMap4, UShort, TCMap4Segment*, UShort ); + + +/******************************************************************* + * + * Function : TT_CharMap_First + * + * Description : Returns the first valid character code in a + * given character map. Also returns the corresponding + * glyph index. + * + * Input : charMap handle to the target character map + * id address where the glyph index will be + * be returned in case of success + * + * Output : First valid character code. -1 in case of failure. + * + * Notes : + * + ******************************************************************/ + +EXPORT_FUNC +TT_Long TT_CharMap_First( TT_CharMap charMap, + TT_UShort* id ) +{ + PCMapTable cmap; + UShort i, c; + + + if ( !( cmap = HANDLE_CharMap( charMap ) ) ) + return -1; + + switch ( cmap->format ) + { + case 0: + if ( id ) + *id = cmap->c.cmap0.glyphIdArray[0]; + return 0; + + case 4: + return charmap_first4( &cmap->c.cmap4, id ); + + case 6: + if ( cmap->c.cmap6.entryCount < 1 ) + return -1; + + if ( id ) + *id = cmap->c.cmap6.glyphIdArray[0]; + return cmap->c.cmap6.firstCode; + + default: + /* Now loop from 0 to 65535. We can't use a simple "for' on */ + /* 16-bits systems, hence the "strange" loop here.. */ + i = 0; + do + { + c = TT_Char_Index( charMap, i ); + if ( c > 0 ) + { + if ( id ) + *id = c; + return i; + } + i++; + } while ( i != 0 ); /* because i is UShort! */ + + return -1; + } +} + + +static Long charmap_first4( PCMap4 cmap4, + UShort* id ) +{ + UShort firstCode; + + + if ( cmap4->segCountX2 / 2 < 1 ) + return -1; + + firstCode = cmap4->segments[0].startCount; + + if ( id ) + *id = charmap_find_id4( cmap4, firstCode, &(cmap4->segments[0]), 0 ); + + return firstCode; +} + + +/******************************************************************* + * + * Function : TT_CharMap_Next + * + * Description : Returns the next valid character code in a given + * charMap. + * + * Input : charMap handle to the target char. map + * index starting character code + * id address where the glyph index of the next + * character will be returned + * + * Output : Next valid character code after 'index'. -1 in case + * of failure. + * + * Notes : + * + ******************************************************************/ + +EXPORT_FUNC +TT_Long TT_CharMap_Next( TT_CharMap charMap, + TT_UShort index, + TT_UShort* id ) +{ + PCMapTable cmap; + UShort i, c; + + + cmap = HANDLE_CharMap( charMap ); + if ( !cmap ) + return -1; + + switch ( cmap->format ) + { + case 0: + if ( index < 255 ) + { + if ( id ) + *id = cmap->c.cmap0.glyphIdArray[index + 1]; + return index + 1; + } + else + return -1; + + case 4: + return charmap_next4( &cmap->c.cmap4, index, id ); + + case 6: + { + UShort firstCode = cmap->c.cmap6.firstCode; + + + if ( index + 1 < firstCode + cmap->c.cmap6.entryCount ) + { + if ( id ) + *id = cmap->c.cmap6.glyphIdArray[index + 1 - firstCode]; + return index + 1; + } + else + return -1; + } + + default: + /* Now loop from 0 to 65535. We can't use a simple "for" on */ + /* 16-bits systems, hence the "strange" loop here.. */ + i = 0; + do + { + c = TT_Char_Index( charMap, i ); + if ( c > 0 ) + { + if ( id ) + *id = c; + return i; + } + i++; + } while ( i != 0 ); /* because i is UShort! */ + + return -1; + } +} + + +static Long charmap_next4( PCMap4 cmap4, + UShort charCode, + UShort* id) +{ + UShort segCount, nextCode; + UShort i; + TCMap4Segment seg4; + + + if ( charCode == 0xFFFF ) + return -1; /* get it out of the way now */ + + segCount = cmap4->segCountX2 / 2; + + for ( i = 0; i < segCount; i++ ) + if ( charCode < cmap4->segments[i].endCount ) + break; + + /* Safety check - even though the last endCount should be 0xFFFF */ + if ( i >= segCount ) + return -1; + + seg4 = cmap4->segments[i]; + + if ( charCode < seg4.startCount ) + nextCode = seg4.startCount; + else + nextCode = charCode + 1; + + if ( id ) + *id = charmap_find_id4( cmap4, nextCode, &seg4, i ); + + return nextCode; +} + + +static UShort +charmap_find_id4( PCMap4 cmap4, + UShort charCode, + TCMap4Segment* seg4, + UShort i ) +{ + UShort index1; + + + if ( seg4->idRangeOffset == 0 ) + return (charCode + seg4->idDelta) & 0xFFFF; + else + { + index1 = seg4->idRangeOffset / 2 + charCode-seg4->startCount - + ( cmap4->segCountX2 / 2 - i ); + + if ( index1 >= cmap4->numGlyphId || cmap4->glyphIdArray[index1] == 0 ) + return 0; + else + return (cmap4->glyphIdArray[index1] + seg4->idDelta) & 0xFFFF; + } +} + + +/******************************************************************* + * + * Function : TT_CharMap_Last + * + * Description : Returns the last valid character code in a + * given character map. Also returns the corresponding + * glyph index. + * + * Input : charMap handle to the target character map + * id address where the glyph index will be + * be returned in case of success + * + * Output : Last valid character code. -1 in case of failure. + * + * Notes : + * + ******************************************************************/ + +EXPORT_FUNC +TT_Long TT_CharMap_Last( TT_CharMap charMap, + TT_UShort* id ) +{ + PCMapTable cmap; + UShort i, c; + + + if ( !( cmap = HANDLE_CharMap( charMap ) ) ) + return -1; + + switch ( cmap->format ) + { + case 0: + if ( id ) + *id = cmap->c.cmap0.glyphIdArray[255]; + return 255; + + case 4: + return charmap_last4( &cmap->c.cmap4, id ); + + case 6: + if ( cmap->c.cmap6.entryCount < 1 ) + return -1; + + if ( id ) + *id = cmap->c.cmap6.glyphIdArray[cmap->c.cmap6.entryCount - 1]; + return cmap->c.cmap6.firstCode + cmap->c.cmap6.entryCount - 1; + + default: + i = 65535; + do + { + c = TT_Char_Index( charMap, i ); + if ( c > 0 ) + { + if ( id ) + *id = c; + return i; + } + i--; + } while ( i != 0 ); + + return -1; + } +} + + +static Long charmap_last4( PCMap4 cmap4, + UShort* id ) +{ + UShort lastCode; + + + if ( cmap4->segCountX2 / 2 < 1 ) + return -1; + + lastCode = cmap4->segments[cmap4->segCountX2 / 2 - 1].endCount; + + if ( id ) + *id = charmap_find_id4( cmap4, + lastCode, + &(cmap4->segments[cmap4->segCountX2 / 2 - 1]), + 0 ); + + return lastCode; +} + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxcmap.h b/Build/source/libs/libttf/extend/ftxcmap.h new file mode 100644 index 00000000000..38ed8e1d337 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxcmap.h @@ -0,0 +1,60 @@ +/******************************************************************* + * + * ftxcmap.h 1.0 + * + * API extension for iterating over Cmaps + * + * Copyright 1996-1999 by Juliusz Chroboczek, + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + ******************************************************************/ + +#ifndef FTXCMAP_H +#define FTXCMAP_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* Find the first entry of a Cmap. Its glyph index is returned */ + /* in the "id" field, while the function returns the first valid */ + /* character code in the Cmap. It returns -1 in case of failure. */ + + EXPORT_DEF + TT_Long TT_CharMap_First( TT_CharMap charMap, + TT_UShort* id ); + + + /* Find the next entry of Cmap. Same return conventions. */ + + EXPORT_DEF + TT_Long TT_CharMap_Next( TT_CharMap charMap, + TT_UShort startId, + TT_UShort* id ); + + /* Find the last entry of a Cmap. Its glyph index is returned */ + /* in the "id" field, while the function returns the last valid */ + /* character code in the Cmap. It returns -1 in case of failure. */ + + EXPORT_DEF + TT_Long TT_CharMap_Last( TT_CharMap charMap, + TT_UShort* id ); + + +#ifdef __cplusplus +} +#endif + +#endif /* FTXCMAP_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxerr18.c b/Build/source/libs/libttf/extend/ftxerr18.c new file mode 100644 index 00000000000..ac8934a0165 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxerr18.c @@ -0,0 +1,241 @@ +/****************************************************************************/ +/* */ +/* Erwin Dieterich, 15. 10. 1997 */ +/* - 15. 08. 1999 */ +/* */ +/* TT_ErrToString: translate error codes to character strings */ +/* */ +/* This extension provides internationalized error strings from the */ +/* various error messages. It uses the "gettext" package if available */ +/* or returns English/American message strings if not. */ +/* */ +/* If you do not want to use it, or if you encounter some problems */ +/* compiling this file, try to disable nls support when invoking */ +/* ./configure (on Unix). */ +/* */ +/* */ +/****************************************************************************/ + +#include "ttconfig.h" + +#include "ftxerr18.h" +#include "ftxkern.h" +#include "ftxpost.h" +#include "ftxopen.h" + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif + +#ifdef HAVE_LIBINTL_H +#include <libintl.h> +#undef _ +#define _( String ) dgettext( "freetype", String ) +#else +#define _( String ) ( String ) +#endif + + +EXPORT_FUNC +TT_String* TT_ErrToString18( TT_Error error ) +{ + + switch ( error ) + { + /* ----- high-level API error codes ----- */ + case TT_Err_Ok: + return _( "Successful function call, no error." ); + + case TT_Err_Invalid_Face_Handle: + return _( "Invalid face handle." ); + case TT_Err_Invalid_Instance_Handle: + return _( "Invalid instance handle." ); + case TT_Err_Invalid_Glyph_Handle: + return _( "Invalid glyph handle." ); + case TT_Err_Invalid_CharMap_Handle: + return _( "Invalid charmap handle." ); + case TT_Err_Invalid_Result_Address: + return _( "Invalid result address." ); + case TT_Err_Invalid_Glyph_Index: + return _( "Invalid glyph index." ); + case TT_Err_Invalid_Argument: + return _( "Invalid argument." ); + case TT_Err_Could_Not_Open_File: + return _( "Could not open file." ); + case TT_Err_File_Is_Not_Collection: + return _( "File is not a TrueType collection." ); + + case TT_Err_Table_Missing: + return _( "Mandatory table missing." ); + case TT_Err_Invalid_Horiz_Metrics: + return _( "Invalid horizontal metrics (hmtx table broken)." ); + case TT_Err_Invalid_CharMap_Format: + return _( "Invalid charmap format." ); + case TT_Err_Invalid_PPem: + return _( "Invalid ppem value." ); + case TT_Err_Invalid_Vert_Metrics: + return _( "Invalid vertical metrics (vmtx table broken)." ); + + case TT_Err_Invalid_File_Format: + return _( "Invalid file format." ); + + case TT_Err_Invalid_Engine: + return _( "Invalid engine." ); + case TT_Err_Too_Many_Extensions: + return _( "Too many extensions." ); + case TT_Err_Extensions_Unsupported: + return _( "Extensions unsupported." ); + case TT_Err_Invalid_Extension_Id: + return _( "Invalid extension id." ); + + case TT_Err_No_Vertical_Data: + return _( "No vertical data in font." ); + + case TT_Err_Max_Profile_Missing: + return _( "Maximum Profile (maxp) table missing." ); + case TT_Err_Header_Table_Missing: + return _( "Font Header (head) table missing." ); + case TT_Err_Horiz_Header_Missing: + return _( "Horizontal Header (hhea) table missing." ); + case TT_Err_Locations_Missing: + return _( "Index to Location (loca) table missing." ); + case TT_Err_Name_Table_Missing: + return _( "Naming (name) table missing." ); + case TT_Err_CMap_Table_Missing: + return _( "Character to Glyph Index Mapping (cmap) tables missing." ); + case TT_Err_Hmtx_Table_Missing: + return _( "Horizontal Metrics (hmtx) table missing." ); + case TT_Err_OS2_Table_Missing: + return _( "OS/2 table missing." ); + case TT_Err_Post_Table_Missing: + return _( "PostScript (post) table missing." ); + case TT_Err_Glyf_Table_Missing: + return _( "Glyph (glyf) table missing." ); + + + /* ----- memory component error codes ----- */ + case TT_Err_Out_Of_Memory: + return _( "Out of memory." ); + + + /* ----- file component error codes ----- */ + case TT_Err_Invalid_File_Offset: + return _( "Invalid file offset." ); + case TT_Err_Invalid_File_Read: + return _( "Invalid file read." ); + case TT_Err_Invalid_Frame_Access: + return _( "Invalid frame access." ); + + + /* ----- glyph loader error codes ----- */ + case TT_Err_Too_Many_Points: + return _( "Too many points." ); + case TT_Err_Too_Many_Contours: + return _( "Too many contours." ); + case TT_Err_Invalid_Composite: + return _( "Invalid composite glyph." ); + case TT_Err_Too_Many_Ins: + return _( "Too many instructions." ); + + + /* ----- byte-code interpreter error codes ----- */ + case TT_Err_Invalid_Opcode: + return _( "Invalid opcode." ); + case TT_Err_Too_Few_Arguments: + return _( "Too few arguments." ); + case TT_Err_Stack_Overflow: + return _( "Stack overflow." ); + case TT_Err_Code_Overflow: + return _( "Code overflow." ); + case TT_Err_Bad_Argument: + return _( "Bad argument." ); + case TT_Err_Divide_By_Zero: + return _( "Divide by zero." ); + case TT_Err_Storage_Overflow: + return _( "Storage overflow." ); + case TT_Err_Cvt_Overflow: + return _( "Control Value (cvt) table overflow." ); + case TT_Err_Invalid_Reference: + return _( "Invalid reference." ); + case TT_Err_Invalid_Distance: + return _( "Invalid distance." ); + case TT_Err_Interpolate_Twilight: + return _( "Interpolate twilight points." ); + case TT_Err_Debug_OpCode: + return _( "`DEBUG' opcode found." ); + case TT_Err_ENDF_In_Exec_Stream: + return _( "`ENDF' in byte-code stream." ); + case TT_Err_Out_Of_CodeRanges: + return _( "Out of code ranges." ); + case TT_Err_Nested_DEFS: + return _( "Nested function definitions." ); + case TT_Err_Invalid_CodeRange: + return _( "Invalid code range." ); + case TT_Err_Invalid_Displacement: + return _( "Invalid displacement." ); + case TT_Err_Execution_Too_Long: + return _( "Endless loop encountered while executing instructions." ); + + + /* ----- internal failure error codes ----- */ + case TT_Err_Nested_Frame_Access: + return _( "Nested frame access." ); + case TT_Err_Invalid_Cache_List: + return _( "Invalid cache list." ); + case TT_Err_Could_Not_Find_Context: + return _( "Could not find context." ); + case TT_Err_Unlisted_Object: + return _( "Unlisted object." ); + + + /* ----- scan-line converter error codes ----- */ + case TT_Err_Raster_Pool_Overflow: + return _( "Raster pool overflow." ); + case TT_Err_Raster_Negative_Height: + return _( "Raster: negative height encountered." ); + case TT_Err_Raster_Invalid_Value: + return _( "Raster: invalid value." ); + case TT_Err_Raster_Not_Initialized: + return _( "Raster not initialized." ); + + + /* ----- engine extensions error codes ----- */ + case TT_Err_Invalid_Kerning_Table_Format: + return _( "Invalid kerning (kern) table format." ); + case TT_Err_Invalid_Kerning_Table: + return _( "Invalid kerning (kern) table." ); + case TT_Err_Invalid_Post_Table_Format: + return _( "Invalid PostScript (post) table format." ); + case TT_Err_Invalid_Post_Table: + return _( "Invalid PostScript (post) table." ); + + + /* ----- TrueType Open extension error codes ----- */ + + case TTO_Err_Invalid_SubTable_Format: + return _( "Invalid TrueType Open subtable format." ); + case TTO_Err_Invalid_SubTable: + return _( "Invalid TrueType Open subtable." ); + case TTO_Err_Not_Covered: + return _( "Glyph(s) not covered by lookup." ); + case TTO_Err_Too_Many_Nested_Contexts: + return _( "Too many nested context substitutions." ); + case TTO_Err_Invalid_GSUB_SubTable_Format: + return _( "Invalid glyph substitution (GSUB) table format." ); + case TTO_Err_Invalid_GSUB_SubTable: + return _( "Invalid glyph substitution (GSUB) table." ); + case TTO_Err_Invalid_GPOS_SubTable_Format: + return _( "Invalid glyph positioning (GPOS) table format." ); + case TTO_Err_Invalid_GPOS_SubTable: + return _( "Invalid glyph positioning (GPOS) table." ); + + + default: + ; + } + + return _( "Invalid Error Number." ); +} + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxerr18.h b/Build/source/libs/libttf/extend/ftxerr18.h new file mode 100644 index 00000000000..3ad060be359 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxerr18.h @@ -0,0 +1,38 @@ +/****************************************************************************/ +/* */ +/* Erwin Dieterich, 15. 10. 1997 */ +/* - 15. 08. 1999 */ +/* */ +/* TT_ErrToString: translate error codes to character strings */ +/* */ +/* This extension provides internationalized error strings from the */ +/* various error messages. It uses the "gettext" package where available */ +/* or returns english/american message strings if not. */ +/* */ +/* If you do not want to use it, or if you encounter some problems */ +/* compiling this file, try to disable nls support by configuring */ +/* FreeType with ./configure --disable-nls */ +/* */ +/* */ +/****************************************************************************/ + +#ifndef FTXERR18_H +#define FTXERR18_H + +#include "freetype.h" + +#ifdef __cplusplus + extern "C" { +#endif + + EXPORT_DEF + TT_String* TT_ErrToString18( TT_Error i ); + +#ifdef __cplusplus + } +#endif + +#endif /* FTXERR18_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgasp.c b/Build/source/libs/libttf/extend/ftxgasp.c new file mode 100644 index 00000000000..aca43157d8d --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgasp.c @@ -0,0 +1,70 @@ +/******************************************************************* + * + * ftxgasp.c 1.0 + * + * Gasp table support API extension body + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The gasp table is currently loaded by the core engine, but the + * standard API doesn't give access to it. This file is used to + * demonstrate the use of a simple API extension. + * + ******************************************************************/ + +#include "ttconfig.h" +#include "ftxgasp.h" + +#include "tttypes.h" +#include "ttobjs.h" +#include "tttables.h" + + + EXPORT_FUNC + TT_Error TT_Get_Face_Gasp_Flags( TT_Face face, + TT_UShort point_size, + TT_Bool* grid_fit, + TT_Bool* smooth_font ) + { + PFace faze = HANDLE_Face( face ); + UShort i, flag; + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( faze->gasp.numRanges == 0 || !faze->gasp.gaspRanges ) + return TT_Err_Table_Missing; + + for ( i = 0; i < faze->gasp.numRanges; i++ ) + { + if ( point_size <= faze->gasp.gaspRanges[i].maxPPEM ) + { + flag = faze->gasp.gaspRanges[i].gaspFlag; + + *grid_fit = ( (flag & GASP_GRIDFIT) != 0 ); + *smooth_font = ( (flag & GASP_DOGRAY ) != 0 ); + + return TT_Err_Ok; + } + } + + /* for very large fonts we enable font smoothing and discard */ + /* grid fitting */ + + *grid_fit = 0; + *smooth_font = 1; + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgasp.h b/Build/source/libs/libttf/extend/ftxgasp.h new file mode 100644 index 00000000000..a0dde720c0f --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgasp.h @@ -0,0 +1,53 @@ +/******************************************************************* + * + * ftxgasp.h 1.0 + * + * Gasp table support API extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The gasp table is currently loaded by the core engine, but the + * standard API doesn't give access to it. This file is used to + * demonstrate the use of a simple API extension. + * + ******************************************************************/ + +#ifndef FTXGASP_H +#define FTXGASP_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + /* This function returns for a given 'point_size' the values of the */ + /* gasp flags 'grid_fit' and 'smooth_font'. The returned values */ + /* are booleans (where 0 = NO, and 1 = YES). */ + + /* Note that this function will return TT_Err_Table_Missing if */ + /* the font file doesn't contain any gasp table. */ + + EXPORT_DEF + TT_Error TT_Get_Face_Gasp_Flags( TT_Face face, + TT_UShort point_size, + TT_Bool* grid_fit, + TT_Bool* smooth_font ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXGASP_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgdef.c b/Build/source/libs/libttf/extend/ftxgdef.c new file mode 100644 index 00000000000..a4be21ecc90 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgdef.c @@ -0,0 +1,1127 @@ +/******************************************************************* + * + * ftxgdef.c + * + * TrueType Open GDEF table support. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "tttypes.h" +#include "tttags.h" +#include "ttload.h" +#include "ttextend.h" +#include "ttmemory.h" +#include "ttfile.h" + +#include "ftxopen.h" +#include "ftxopenf.h" + + +#define GDEF_ID Build_Extension_ID( 'G', 'D', 'E', 'F' ) + + + static TT_Error Load_AttachList( TTO_AttachList* al, + PFace input ); + static TT_Error Load_LigCaretList( TTO_LigCaretList* lcl, + PFace input ); + + static void Free_AttachList( TTO_AttachList* al ); + static void Free_LigCaretList( TTO_LigCaretList* lcl ); + + static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef ); + + + + /********************** + * Extension Functions + **********************/ + + + static TT_Error GDEF_Create( void* ext, + PFace face ) + { + DEFINE_LOAD_LOCALS( face->stream ); + + TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext; + Long table; + + + /* by convention */ + + if ( !gdef ) + return TT_Err_Ok; + + /* a null offset indicates that there is no GDEF table */ + + gdef->offset = 0; + + /* we store the start offset and the size of the subtable */ + + table = TT_LookUp_Table( face, TTAG_GDEF ); + if ( table < 0 ) + return TT_Err_Ok; /* The table is optional */ + + if ( FILE_Seek( face->dirTables[table].Offset ) || + ACCESS_Frame( 4L ) ) + return error; + + gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ + gdef->Version = GET_ULong(); + + FORGET_Frame(); + + gdef->loaded = FALSE; + + return TT_Err_Ok; + } + + + static TT_Error GDEF_Destroy( void* ext, + PFace face ) + { + TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext; + + + /* by convention */ + + if ( !gdef ) + return TT_Err_Ok; + + if ( gdef->loaded ) + { + Free_LigCaretList( &gdef->LigCaretList ); + Free_AttachList( &gdef->AttachList ); + Free_ClassDefinition( &gdef->GlyphClassDef ); + Free_ClassDefinition( &gdef->MarkAttachClassDef ); + + Free_NewGlyphClasses( gdef ); + } + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_Init_GDEF_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + return TT_Register_Extension( _engine, + GDEF_ID, + sizeof ( TTO_GDEFHeader ), + GDEF_Create, + GDEF_Destroy ); + } + + + EXPORT_FUNC + TT_Error TT_Load_GDEF_Table( TT_Face face, + TTO_GDEFHeader* retptr ) + { + ULong cur_offset, new_offset, base_offset; + + TT_Error error; + TT_Stream stream; + TTO_GDEFHeader* gdef; + + PFace faze = HANDLE_Face( face ); + + + if ( !retptr ) + return TT_Err_Invalid_Argument; + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + error = TT_Extension_Get( faze, GDEF_ID, (void**)&gdef ); + if ( error ) + return error; + + if ( gdef->offset == 0 ) + return TT_Err_Table_Missing; /* no GDEF table; nothing to do */ + + /* now access stream */ + + if ( USE_Stream( faze->stream, stream ) ) + return error; + + base_offset = gdef->offset; + + /* skip version */ + + if ( FILE_Seek( base_offset + 4L ) || + ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + /* all GDEF subtables are optional */ + + if ( new_offset ) + { + new_offset += base_offset; + + /* only classes 1-4 are allowed here */ + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ClassDefinition( &gdef->GlyphClassDef, 5, + faze ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + } + else + gdef->GlyphClassDef.loaded = FALSE; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_AttachList( &gdef->AttachList, + faze ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + gdef->AttachList.loaded = FALSE; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LigCaretList( &gdef->LigCaretList, + faze ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + else + gdef->LigCaretList.loaded = FALSE; + + /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We + first have to scan the LookupFlag values to find out whether we + must load it or not. Here we only store the current file offset. */ + + gdef->MarkAttachClassDef_offset = FILE_Pos(); + gdef->MarkAttachClassDef.loaded = FALSE; + + gdef->LastGlyph = 0; + gdef->NewGlyphClasses = NULL; + gdef->loaded = TRUE; + + *retptr = *gdef; + DONE_Stream( stream ); + + return TT_Err_Ok; + + Fail2: + Free_AttachList( &gdef->AttachList ); + + Fail1: + Free_ClassDefinition( &gdef->GlyphClassDef ); + + /* release stream */ + + DONE_Stream( stream ); + + return error; + } + + + + /******************************* + * AttachList related functions + *******************************/ + + + /* AttachPoint */ + + static TT_Error Load_AttachPoint( TTO_AttachPoint* ap, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* pi; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ap->PointCount = GET_UShort(); + + FORGET_Frame(); + + ap->PointIndex = NULL; + + if ( count ) + { + if ( ALLOC_ARRAY( ap->PointIndex, count, UShort ) ) + return error; + + pi = ap->PointIndex; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( pi ); + return error; + } + + for ( n = 0; n < count; n++ ) + pi[n] = GET_UShort(); + + FORGET_Frame(); + } + + return TT_Err_Ok; + } + + + static void Free_AttachPoint( TTO_AttachPoint* ap ) + { + FREE( ap->PointIndex ); + } + + + /* AttachList */ + + static TT_Error Load_AttachList( TTO_AttachList* al, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_AttachPoint* ap; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &al->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = al->GlyphCount = GET_UShort(); + + FORGET_Frame(); + + al->AttachPoint = NULL; + + if ( ALLOC_ARRAY( al->AttachPoint, count, TTO_AttachPoint ) ) + goto Fail2; + + ap = al->AttachPoint; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_AttachPoint( &ap[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + al->loaded = TRUE; + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_AttachPoint( &ap[n] ); + + FREE( ap ); + + Fail2: + Free_Coverage( &al->Coverage ); + return error; + } + + + static void Free_AttachList( TTO_AttachList* al ) + { + UShort n, count; + + TTO_AttachPoint* ap; + + + if ( !al->loaded ) + return; + + if ( al->AttachPoint ) + { + count = al->GlyphCount; + ap = al->AttachPoint; + + for ( n = 0; n < count; n++ ) + Free_AttachPoint( &ap[n] ); + + FREE( ap ); + } + + Free_Coverage( &al->Coverage ); + } + + + + /********************************* + * LigCaretList related functions + *********************************/ + + + /* CaretValueFormat1 */ + /* CaretValueFormat2 */ + /* CaretValueFormat3 */ + /* CaretValueFormat4 */ + + static TT_Error Load_CaretValue( TTO_CaretValue* cv, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + cv->CaretValueFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( cv->CaretValueFormat ) + { + case 1: + if ( ACCESS_Frame( 2L ) ) + return error; + + cv->cvf.cvf1.Coordinate = GET_Short(); + + FORGET_Frame(); + + break; + + case 2: + if ( ACCESS_Frame( 2L ) ) + return error; + + cv->cvf.cvf2.CaretValuePoint = GET_UShort(); + + FORGET_Frame(); + + break; + + case 3: + if ( ACCESS_Frame( 4L ) ) + return error; + + cv->cvf.cvf3.Coordinate = GET_Short(); + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &cv->cvf.cvf3.Device, + input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + break; + + case 4: + if ( ACCESS_Frame( 2L ) ) + return error; + + cv->cvf.cvf4.IdCaretValue = GET_UShort(); + + FORGET_Frame(); + break; + + default: + return TTO_Err_Invalid_GDEF_SubTable_Format; + } + + return TT_Err_Ok; + } + + + static void Free_CaretValue( TTO_CaretValue* cv ) + { + if ( cv->CaretValueFormat == 3 ) + Free_Device( &cv->cvf.cvf3.Device ); + } + + + /* LigGlyph */ + + static TT_Error Load_LigGlyph( TTO_LigGlyph* lg, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_CaretValue* cv; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = lg->CaretCount = GET_UShort(); + + FORGET_Frame(); + + lg->CaretValue = NULL; + + if ( ALLOC_ARRAY( lg->CaretValue, count, TTO_CaretValue ) ) + return error; + + cv = lg->CaretValue; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_CaretValue( &cv[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_CaretValue( &cv[n] ); + + FREE( cv ); + return error; + } + + + static void Free_LigGlyph( TTO_LigGlyph* lg ) + { + UShort n, count; + + TTO_CaretValue* cv; + + + if ( lg->CaretValue ) + { + count = lg->CaretCount; + cv = lg->CaretValue; + + for ( n = 0; n < count; n++ ) + Free_CaretValue( &cv[n] ); + + FREE( cv ); + } + } + + + /* LigCaretList */ + + static TT_Error Load_LigCaretList( TTO_LigCaretList* lcl, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_LigGlyph* lg; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &lcl->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = lcl->LigGlyphCount = GET_UShort(); + + FORGET_Frame(); + + lcl->LigGlyph = NULL; + + if ( ALLOC_ARRAY( lcl->LigGlyph, count, TTO_LigGlyph ) ) + goto Fail2; + + lg = lcl->LigGlyph; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LigGlyph( &lg[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + lcl->loaded = TRUE; + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_LigGlyph( &lg[n] ); + + FREE( lg ); + + Fail2: + Free_Coverage( &lcl->Coverage ); + return error; + } + + + static void Free_LigCaretList( TTO_LigCaretList* lcl ) + { + UShort n, count; + + TTO_LigGlyph* lg; + + + if ( !lcl->loaded ) + return; + + if ( lcl->LigGlyph ) + { + count = lcl->LigGlyphCount; + lg = lcl->LigGlyph; + + for ( n = 0; n < count; n++ ) + Free_LigGlyph( &lg[n] ); + + FREE( lg ); + } + + Free_Coverage( &lcl->Coverage ); + } + + + + /*********** + * GDEF API + ***********/ + + + static UShort Get_New_Class( TTO_GDEFHeader* gdef, + UShort glyphID, + UShort index ) + { + UShort glyph_index, array_index; + UShort byte, bits; + + TTO_ClassRangeRecord* gcrr; + UShort** ngc; + + + if ( glyphID >= gdef->LastGlyph ) + return 0; + + gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; + ngc = gdef->NewGlyphClasses; + + if ( glyphID < gcrr[index].Start ) + { + array_index = 0; + if ( index == 0 ) + glyph_index = glyphID; + else + glyph_index = glyphID - gcrr[index - 1].End - 1; + } + else + { + array_index = index + 1; + glyph_index = glyphID - gcrr[index].End - 1; + } + + byte = ngc[array_index][glyph_index / 4 + 1]; + bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); + + return bits & 0x000F; + } + + + EXPORT_FUNC + TT_Error TT_GDEF_Get_Glyph_Property( TTO_GDEFHeader* gdef, + TT_UShort glyphID, + TT_UShort* property ) + { + UShort class, index; + + TT_Error error; + + + if ( !gdef || !property ) + return TT_Err_Invalid_Argument; + + /* first, we check for mark attach classes */ + + if ( gdef->MarkAttachClassDef.loaded ) + { + error = Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + if ( !error ) + { + *property = class << 8; + return TT_Err_Ok; + } + } + + error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + + /* if we have a constructed class table, check whether additional + values have been assigned */ + + if ( error == TTO_Err_Not_Covered && gdef->NewGlyphClasses ) + class = Get_New_Class( gdef, glyphID, index ); + + switch ( class ) + { + case UNCLASSIFIED_GLYPH: + *property = 0; + break; + + case SIMPLE_GLYPH: + *property = TTO_BASE_GLYPH; + break; + + case LIGATURE_GLYPH: + *property = TTO_LIGATURE; + break; + + case MARK_GLYPH: + *property = TTO_MARK; + break; + + case COMPONENT_GLYPH: + *property = TTO_COMPONENT; + break; + } + + return TT_Err_Ok; + } + + + static TT_Error Make_ClassRange( TTO_ClassDefinition* cd, + UShort start, + UShort end, + UShort class ) + { + TT_Error error; + UShort index; + + TTO_ClassDefFormat2* cdf2; + TTO_ClassRangeRecord* crr; + + + cdf2 = &cd->cd.cd2; + + cdf2->ClassRangeCount++; + + if ( REALLOC_ARRAY( cdf2->ClassRangeRecord, cdf2->ClassRangeCount, + TTO_ClassRangeRecord ) ) + return error; + + crr = cdf2->ClassRangeRecord; + index = cdf2->ClassRangeCount - 1; + + crr[index].Start = start; + crr[index].End = end; + crr[index].Class = class; + + cd->Defined[class] = TRUE; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GDEF_Build_ClassDefinition( TTO_GDEFHeader* gdef, + TT_UShort num_glyphs, + TT_UShort glyph_count, + TT_UShort* glyph_array, + TT_UShort* class_array ) + { + UShort start, curr_glyph, curr_class; + UShort n, count; + TT_Error error; + + TTO_ClassDefinition* gcd; + TTO_ClassRangeRecord* gcrr; + UShort** ngc; + + + if ( !gdef || !glyph_array || !class_array ) + return TT_Err_Invalid_Argument; + + gcd = &gdef->GlyphClassDef; + + /* We build a format 2 table */ + + gcd->ClassFormat = 2; + + /* A GlyphClassDef table contains at most 5 different class values */ + + if ( ALLOC_ARRAY( gcd->Defined, 5, Bool ) ) + return error; + + gcd->cd.cd2.ClassRangeCount = 0; + gcd->cd.cd2.ClassRangeRecord = NULL; + + start = glyph_array[0]; + curr_class = class_array[0]; + curr_glyph = start; + + if ( curr_class >= 5 ) + { + error = TT_Err_Invalid_Argument; + goto Fail4; + } + + glyph_count--; + + for ( n = 0; n <= glyph_count; n++ ) + { + if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] ) + { + if ( n == glyph_count ) + { + if ( ( error = Make_ClassRange( gcd, start, + curr_glyph, + curr_class ) ) != TT_Err_Ok ) + goto Fail3; + } + else + { + if ( curr_glyph == 0xFFFF ) + { + error = TT_Err_Invalid_Argument; + goto Fail3; + } + else + curr_glyph++; + } + } + else + { + if ( ( error = Make_ClassRange( gcd, start, + curr_glyph - 1, + curr_class ) ) != TT_Err_Ok ) + goto Fail3; + + if ( curr_glyph > glyph_array[n] ) + { + error = TT_Err_Invalid_Argument; + goto Fail3; + } + + start = glyph_array[n]; + curr_class = class_array[n]; + curr_glyph = start; + + if ( curr_class >= 5 ) + { + error = TT_Err_Invalid_Argument; + goto Fail3; + } + + if ( n == glyph_count ) + { + if ( ( error = Make_ClassRange( gcd, start, + curr_glyph, + curr_class ) ) != TT_Err_Ok ) + goto Fail3; + } + else + { + if ( curr_glyph == 0xFFFF ) + { + error = TT_Err_Invalid_Argument; + goto Fail3; + } + else + curr_glyph++; + } + } + } + + /* now prepare the arrays for class values assigned during the lookup + process */ + + if ( ALLOC_ARRAY( gdef->NewGlyphClasses, + gcd->cd.cd2.ClassRangeCount + 1, UShort* ) ) + goto Fail2; + + count = gcd->cd.cd2.ClassRangeCount; + gcrr = gcd->cd.cd2.ClassRangeRecord; + ngc = gdef->NewGlyphClasses; + + /* We allocate arrays for all glyphs not covered by the class range + records. Each element holds four class values. */ + + if ( gcrr[0].Start ) + { + if ( ALLOC_ARRAY( ngc[0], gcrr[0].Start / 4 + 1, UShort ) ) + goto Fail1; + } + + for ( n = 1; n < count; n++ ) + { + if ( gcrr[n].Start - gcrr[n - 1].End > 1 ) + if ( ALLOC_ARRAY( ngc[n], + ( gcrr[n].Start - gcrr[n - 1].End - 1 ) / 4 + 1, + UShort ) ) + goto Fail1; + } + + if ( gcrr[count - 1].End != num_glyphs - 1 ) + { + if ( ALLOC_ARRAY( ngc[count], + ( num_glyphs - gcrr[count - 1].End - 1 ) / 4 + 1, + UShort ) ) + goto Fail1; + } + + gdef->LastGlyph = num_glyphs - 1; + + gdef->MarkAttachClassDef_offset = 0L; + gdef->MarkAttachClassDef.loaded = FALSE; + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + FREE( ngc[n] ); + + Fail2: + FREE( gdef->NewGlyphClasses ); + + Fail3: + FREE( gcd->cd.cd2.ClassRangeRecord ); + + Fail4: + FREE( gcd->Defined ); + return error; + } + + + static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef ) + { + UShort** ngc; + UShort n, count; + + + if ( gdef->NewGlyphClasses ) + { + count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1; + ngc = gdef->NewGlyphClasses; + + for ( n = 0; n < count; n++ ) + FREE( ngc[n] ); + + FREE( ngc ); + } + } + + + TT_Error Add_Glyph_Property( TTO_GDEFHeader* gdef, + UShort glyphID, + UShort property ) + { + TT_Error error; + UShort class, new_class, index; + UShort byte, bits, mask; + UShort array_index, glyph_index; + + TTO_ClassRangeRecord* gcrr; + UShort** ngc; + + + error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + + /* we don't accept glyphs covered in `GlyphClassDef' */ + + if ( !error ) + return TTO_Err_Not_Covered; + + switch ( property ) + { + case 0: + new_class = UNCLASSIFIED_GLYPH; + break; + + case TTO_BASE_GLYPH: + new_class = SIMPLE_GLYPH; + break; + + case TTO_LIGATURE: + new_class = LIGATURE_GLYPH; + break; + + case TTO_MARK: + new_class = MARK_GLYPH; + break; + + case TTO_COMPONENT: + new_class = COMPONENT_GLYPH; + break; + + default: + return TT_Err_Invalid_Argument; + } + + gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; + ngc = gdef->NewGlyphClasses; + + if ( glyphID < gcrr[index].Start ) + { + array_index = 0; + if ( index == 0 ) + glyph_index = glyphID; + else + glyph_index = glyphID - gcrr[index - 1].End - 1; + } + else + { + array_index = index + 1; + glyph_index = glyphID - gcrr[index].End - 1; + } + + byte = ngc[array_index][glyph_index / 4 + 1]; + bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); + class = bits & 0x000F; + + /* we don't overwrite existing entries */ + + if ( !class ) + { + bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 ); + mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) ); + + ngc[array_index][glyph_index / 4 + 1] &= mask; + ngc[array_index][glyph_index / 4 + 1] |= bits; + } + + return TT_Err_Ok; + } + + + TT_Error Check_Property( TTO_GDEFHeader* gdef, + UShort index, + UShort flags, + UShort* property ) + { + TT_Error error; + + + if ( gdef ) + { + error = TT_GDEF_Get_Glyph_Property( gdef, index, property ); + if ( error ) + return error; + + /* This is OpenType 1.2 */ + + if ( flags & IGNORE_SPECIAL_MARKS ) + if ( (flags & 0xFF00) != *property ) + return TTO_Err_Not_Covered; + + if ( flags & *property ) + return TTO_Err_Not_Covered; + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgdef.h b/Build/source/libs/libttf/extend/ftxgdef.h new file mode 100644 index 00000000000..33872321f65 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgdef.h @@ -0,0 +1,216 @@ +/******************************************************************* + * + * ftxgdef.h + * + * TrueType Open GDEF table support + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FTXOPEN_H +#error "Don't include this file! Use ftxopen.h instead." +#endif + +#ifndef FTXGDEF_H +#define FTXGDEF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TTO_Err_Invalid_GDEF_SubTable_Format 0x1030 +#define TTO_Err_Invalid_GDEF_SubTable 0x1031 + + +/* GDEF glyph classes */ + +#define UNCLASSIFIED_GLYPH 0 +#define SIMPLE_GLYPH 1 +#define LIGATURE_GLYPH 2 +#define MARK_GLYPH 3 +#define COMPONENT_GLYPH 4 + +/* GDEF glyph properties, corresponding to class values 1-4. Note that + TTO_COMPONENT has no corresponding flag in the LookupFlag field. */ + +#define TTO_BASE_GLYPH 0x0002 +#define TTO_LIGATURE 0x0004 +#define TTO_MARK 0x0008 +#define TTO_COMPONENT 0x0010 + + + /* Attachment related structures */ + + struct TTO_AttachPoint_ + { + TT_UShort PointCount; /* size of the PointIndex array */ + TT_UShort* PointIndex; /* array of contour points */ + }; + + typedef struct TTO_AttachPoint_ TTO_AttachPoint; + + + struct TTO_AttachList_ + { + TT_Bool loaded; + + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort GlyphCount; /* number of glyphs with + attachments */ + TTO_AttachPoint* AttachPoint; /* array of AttachPoint tables */ + }; + + typedef struct TTO_AttachList_ TTO_AttachList; + + + /* Ligature Caret related structures */ + + struct TTO_CaretValueFormat1_ + { + TT_Short Coordinate; /* x or y value (in design units) */ + }; + + typedef struct TTO_CaretValueFormat1_ TTO_CaretValueFormat1; + + + struct TTO_CaretValueFormat2_ + { + TT_UShort CaretValuePoint; /* contour point index on glyph */ + }; + + typedef struct TTO_CaretValueFormat2_ TTO_CaretValueFormat2; + + + struct TTO_CaretValueFormat3_ + { + TT_Short Coordinate; /* x or y value (in design units) */ + TTO_Device Device; /* Device table for x or y value */ + }; + + typedef struct TTO_CaretValueFormat3_ TTO_CaretValueFormat3; + + + struct TTO_CaretValueFormat4_ + { + TT_UShort IdCaretValue; /* metric ID */ + }; + + typedef struct TTO_CaretValueFormat4_ TTO_CaretValueFormat4; + + + struct TTO_CaretValue_ + { + TT_UShort CaretValueFormat; /* 1, 2, 3, or 4 */ + + union + { + TTO_CaretValueFormat1 cvf1; + TTO_CaretValueFormat2 cvf2; + TTO_CaretValueFormat3 cvf3; + TTO_CaretValueFormat4 cvf4; + } cvf; + }; + + typedef struct TTO_CaretValue_ TTO_CaretValue; + + + struct TTO_LigGlyph_ + { + TT_Bool loaded; + + TT_UShort CaretCount; /* number of caret values */ + TTO_CaretValue* CaretValue; /* array of caret values */ + }; + + typedef struct TTO_LigGlyph_ TTO_LigGlyph; + + + struct TTO_LigCaretList_ + { + TT_Bool loaded; + + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort LigGlyphCount; /* number of ligature glyphs */ + TTO_LigGlyph* LigGlyph; /* array of LigGlyph tables */ + }; + + typedef struct TTO_LigCaretList_ TTO_LigCaretList; + + + /* The `NewGlyphClasses' field is not defined in the TTO specification. + We use it for fonts with a constructed `GlyphClassDef' structure + (i.e., which don't have a GDEF table) to collect glyph classes + assigned during the lookup process. The number of arrays in this + pointer array is GlyphClassDef->cd.cd2.ClassRangeCount+1; the nth + array then contains the glyph class values of the glyphs not covered + by the ClassRangeRecords structures with index n-1 and n. We store + glyph class values for four glyphs in a single array element. + + `LastGlyph' is identical to the number of glyphs minus one in the + font; we need it only if `NewGlyphClasses' is not NULL (to have an + upper bound for the last array). + + Note that we first store the file offset to the `MarkAttachClassDef' + field (which has been introduced in OpenType 1.2) -- since the + `Version' field value hasn't been increased to indicate that we have + one more field for some obscure reason, we must parse the GSUB table + to find out whether class values refer to this table. Only then we + can finally load the MarkAttachClassDef structure if necessary. */ + + struct TTO_GDEFHeader_ + { + TT_Bool loaded; + TT_ULong offset; + + TT_Fixed Version; + + TTO_ClassDefinition GlyphClassDef; + TTO_AttachList AttachList; + TTO_LigCaretList LigCaretList; + TT_ULong MarkAttachClassDef_offset; + TTO_ClassDefinition MarkAttachClassDef; /* new in OT 1.2 */ + + TT_UShort LastGlyph; + TT_UShort** NewGlyphClasses; + }; + + typedef struct TTO_GDEFHeader_ TTO_GDEFHeader; + + + /* finally, the GDEF API */ + + EXPORT_DEF + TT_Error TT_Init_GDEF_Extension( TT_Engine engine ); + + EXPORT_DEF + TT_Error TT_Load_GDEF_Table( TT_Face face, + TTO_GDEFHeader* gdef ); + + EXPORT_DEF + TT_Error TT_GDEF_Get_Glyph_Property( TTO_GDEFHeader* gdef, + TT_UShort glyphID, + TT_UShort* property ); + EXPORT_DEF + TT_Error TT_GDEF_Build_ClassDefinition( TTO_GDEFHeader* gdef, + TT_UShort num_glyphs, + TT_UShort glyph_count, + TT_UShort* glyph_array, + TT_UShort* class_array ); + + +#ifdef __cplusplus +} +#endif + +#endif /* FTXGDEF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgpos.c b/Build/source/libs/libttf/extend/ftxgpos.c new file mode 100644 index 00000000000..25eff3ade52 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgpos.c @@ -0,0 +1,6169 @@ +/******************************************************************* + * + * ftxgpos.c + * + * TrueType Open GPOS table support. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +/* XXX There is *a lot* of duplicated code (cf. formats 7 and 8), but + I don't care currently. I believe that it would be possible to + save about 50% of TTO code by carefully designing the structures, + sharing as much as possible with extensive use of macros. This + is something for a volunteer :-) */ + +#include "tttypes.h" +#include "tttags.h" +#include "ttload.h" +#include "ttextend.h" +#include "ttmemory.h" +#include "ttfile.h" + +#include "ftxopen.h" +#include "ftxopenf.h" + + +#define GPOS_ID Build_Extension_ID( 'G', 'P', 'O', 'S' ) + + + struct GPOS_Instance_ + { + TTO_GPOSHeader* gpos; + TT_Instance instance; + TT_Glyph glyph; + UShort load_flags; /* how the glyph should be loaded */ + TT_Bool r2l; + + UShort last; /* the last valid glyph -- used + with cursive positioning */ + TT_Pos anchor_x; /* the coordinates of the anchor point */ + TT_Pos anchor_y; /* of the last valid glyph */ + }; + + typedef struct GPOS_Instance_ GPOS_Instance; + + + static TT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort context_length, + int nesting_level ); + + + + /********************** + * Extension Functions + **********************/ + + /* the client application must replace this with something more + meaningful if multiple master fonts are to be supported. */ + + static TT_Error default_mmfunc( TT_Instance instance, + TT_UShort metric_id, + TT_Pos* metric_value, + void* data ) + { + return TTO_Err_No_MM_Interpreter; + } + + + static TT_Error GPOS_Create( void* ext, + PFace face ) + { + DEFINE_LOAD_LOCALS( face->stream ); + + TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext; + Long table; + + + /* by convention */ + + if ( !gpos ) + return TT_Err_Ok; + + /* a null offset indicates that there is no GPOS table */ + + gpos->offset = 0; + + /* we store the start offset and the size of the subtable */ + + table = TT_LookUp_Table( face, TTAG_GPOS ); + if ( table < 0 ) + return TT_Err_Ok; /* The table is optional */ + + if ( FILE_Seek( face->dirTables[table].Offset ) || + ACCESS_Frame( 4L ) ) + return error; + + gpos->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ + gpos->Version = GET_ULong(); + + FORGET_Frame(); + + /* a default mmfunc() handler which just returns an error */ + + gpos->mmfunc = default_mmfunc; + + /* the default glyph function is TT_Load_Glyph() */ + + gpos->gfunc = TT_Load_Glyph; + + gpos->loaded = FALSE; + + return TT_Err_Ok; + } + + + static TT_Error GPOS_Destroy( void* ext, + PFace face ) + { + TTO_GPOSHeader* gpos = (TTO_GPOSHeader*)ext; + + + /* by convention */ + + if ( !gpos ) + return TT_Err_Ok; + + if ( gpos->loaded ) + { + Free_LookupList( &gpos->LookupList, GPOS ); + Free_FeatureList( &gpos->FeatureList ); + Free_ScriptList( &gpos->ScriptList ); + } + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_Init_GPOS_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + return TT_Register_Extension( _engine, + GPOS_ID, + sizeof ( TTO_GPOSHeader ), + GPOS_Create, + GPOS_Destroy ); + } + + + EXPORT_FUNC + TT_Error TT_Load_GPOS_Table( TT_Face face, + TTO_GPOSHeader* retptr, + TTO_GDEFHeader* gdef ) + { + ULong cur_offset, new_offset, base_offset; + + UShort i, num_lookups; + TT_Error error; + TT_Stream stream; + TTO_GPOSHeader* gpos; + TTO_Lookup* lo; + + PFace faze = HANDLE_Face( face ); + + + if ( !retptr ) + return TT_Err_Invalid_Argument; + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + error = TT_Extension_Get( faze, GPOS_ID, (void**)&gpos ); + if ( error ) + return error; + + if ( gpos->offset == 0 ) + return TT_Err_Table_Missing; /* no GPOS table; nothing to do */ + + /* now access stream */ + + if ( USE_Stream( faze->stream, stream ) ) + return error; + + base_offset = gpos->offset; + + /* skip version */ + + if ( FILE_Seek( base_offset + 4L ) || + ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ScriptList( &gpos->ScriptList, + faze ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_FeatureList( &gpos->FeatureList, + faze ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LookupList( &gpos->LookupList, + faze, GPOS ) ) != TT_Err_Ok ) + goto Fail2; + + gpos->gdef = gdef; /* can be NULL */ + + /* We now check the LookupFlags for values larger than 0xFF to find + out whether we need to load the `MarkAttachClassDef' field of the + GDEF table -- this hack is necessary for OpenType 1.2 tables since + the version field of the GDEF table hasn't been incremented. + + For constructed GDEF tables, we only load it if + `MarkAttachClassDef_offset' is not zero (nevertheless, a build of + a constructed mark attach table is not supported currently). */ + + if ( gdef && + gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) + { + lo = gpos->LookupList.Lookup; + num_lookups = gpos->LookupList.LookupCount; + + for ( i = 0; i < num_lookups; i++ ) + { + if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS ) + { + if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || + ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( !new_offset ) + return TTO_Err_Invalid_GDEF_SubTable; + + new_offset += base_offset; + + if ( FILE_Seek( new_offset ) || + ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef, + 256, faze ) ) != TT_Err_Ok ) + goto Fail1; + + break; + } + } + } + + gpos->loaded = TRUE; + *retptr = *gpos; + DONE_Stream( stream ); + + return TT_Err_Ok; + + Fail1: + Free_LookupList( &gpos->LookupList, GPOS ); + + Fail2: + Free_FeatureList( &gpos->FeatureList ); + + Fail3: + Free_ScriptList( &gpos->ScriptList ); + + /* release stream */ + + DONE_Stream( stream ); + + return error; + } + + + + /***************************** + * SubTable related functions + *****************************/ + + /* shared tables */ + + /* ValueRecord */ + + /* There is a subtle difference in the specs between a `table' and a + `record' -- offsets for device tables in ValueRecords are taken from + the parent table and not the parent record. */ + + static TT_Error Load_ValueRecord( TTO_ValueRecord* vr, + UShort format, + ULong base_offset, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset; + + + if ( format & HAVE_X_PLACEMENT ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + vr->XPlacement = GET_Short(); + + FORGET_Frame(); + } + else + vr->XPlacement = 0; + + if ( format & HAVE_Y_PLACEMENT ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + vr->YPlacement = GET_Short(); + + FORGET_Frame(); + } + else + vr->YPlacement = 0; + + if ( format & HAVE_X_ADVANCE ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + vr->XAdvance = GET_Short(); + + FORGET_Frame(); + } + else + vr->XAdvance = 0; + + if ( format & HAVE_Y_ADVANCE ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + vr->YAdvance = GET_Short(); + + FORGET_Frame(); + } + else + vr->YAdvance = 0; + + if ( format & HAVE_X_PLACEMENT_DEVICE ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &vr->XPlacementDevice, + input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + } + else + goto empty1; + } + else + { + empty1: + vr->XPlacementDevice.StartSize = 0; + vr->XPlacementDevice.EndSize = 0; + vr->XPlacementDevice.DeltaValue = NULL; + } + + if ( format & HAVE_Y_PLACEMENT_DEVICE ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &vr->YPlacementDevice, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + } + else + goto empty2; + } + else + { + empty2: + vr->YPlacementDevice.StartSize = 0; + vr->YPlacementDevice.EndSize = 0; + vr->YPlacementDevice.DeltaValue = NULL; + } + + if ( format & HAVE_X_ADVANCE_DEVICE ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &vr->XAdvanceDevice, + input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + else + goto empty3; + } + else + { + empty3: + vr->XAdvanceDevice.StartSize = 0; + vr->XAdvanceDevice.EndSize = 0; + vr->XAdvanceDevice.DeltaValue = NULL; + } + + if ( format & HAVE_Y_ADVANCE_DEVICE ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &vr->YAdvanceDevice, + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + goto empty4; + } + else + { + empty4: + vr->YAdvanceDevice.StartSize = 0; + vr->YAdvanceDevice.EndSize = 0; + vr->YAdvanceDevice.DeltaValue = NULL; + } + + if ( format & HAVE_X_ID_PLACEMENT ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + vr->XIdPlacement = GET_UShort(); + + FORGET_Frame(); + } + else + vr->XIdPlacement = 0; + + if ( format & HAVE_Y_ID_PLACEMENT ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + vr->YIdPlacement = GET_UShort(); + + FORGET_Frame(); + } + else + vr->YIdPlacement = 0; + + if ( format & HAVE_X_ID_ADVANCE ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + vr->XIdAdvance = GET_UShort(); + + FORGET_Frame(); + } + else + vr->XIdAdvance = 0; + + if ( format & HAVE_Y_ID_ADVANCE ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + vr->YIdAdvance = GET_UShort(); + + FORGET_Frame(); + } + else + vr->YIdAdvance = 0; + + return TT_Err_Ok; + + Fail1: + Free_Device( &vr->YAdvanceDevice ); + + Fail2: + Free_Device( &vr->XAdvanceDevice ); + + Fail3: + Free_Device( &vr->YPlacementDevice ); + return error; + } + + + static void Free_ValueRecord( TTO_ValueRecord* vr, + UShort format ) + { + if ( format & HAVE_Y_ADVANCE_DEVICE ) + Free_Device( &vr->YAdvanceDevice ); + if ( format & HAVE_X_ADVANCE_DEVICE ) + Free_Device( &vr->XAdvanceDevice ); + if ( format & HAVE_Y_PLACEMENT_DEVICE ) + Free_Device( &vr->YPlacementDevice ); + if ( format & HAVE_X_PLACEMENT_DEVICE ) + Free_Device( &vr->XPlacementDevice ); + } + + + static TT_Error Get_ValueRecord( GPOS_Instance* gpi, + TTO_ValueRecord* vr, + UShort format, + TTO_GPOS_Data* gd ) + { + TT_Pos value; + Short pixel_value; + TT_Error error = TT_Err_Ok; + TTO_GPOSHeader* gpos = gpi->gpos; + PInstance ins; + + UShort x_ppem, y_ppem; + Fixed x_scale, y_scale; + + + if ( !format ) + return TT_Err_Ok; + + ins = HANDLE_Instance( gpi->instance ); + + x_ppem = ins->metrics.x_ppem; + y_ppem = ins->metrics.y_ppem; + x_scale = TT_MulDiv( 0x10000, + ins->metrics.x_scale1, + ins->metrics.x_scale2 ); + y_scale = TT_MulDiv( 0x10000, + ins->metrics.y_scale1, + ins->metrics.y_scale2 ); + + /* design units -> fractional pixel */ + + if ( format & HAVE_X_PLACEMENT ) + gd->x_pos += x_scale * vr->XPlacement / 0x10000; + if ( format & HAVE_Y_PLACEMENT ) + gd->y_pos += y_scale * vr->YPlacement / 0x10000; + if ( format & HAVE_X_ADVANCE ) + gd->x_advance += x_scale * vr->XAdvance / 0x10000; + if ( format & HAVE_Y_ADVANCE ) + gd->y_advance += y_scale * vr->YAdvance / 0x10000; + + /* we use the device tables only if gpi->glyph.z is not NULL */ + + if ( gpi->glyph.z ) + { + /* pixel -> fractional pixel */ + + if ( format & HAVE_X_PLACEMENT_DEVICE ) + { + Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value ); + gd->x_pos += pixel_value << 6; + } + if ( format & HAVE_Y_PLACEMENT_DEVICE ) + { + Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value ); + gd->y_pos += pixel_value << 6; + } + if ( format & HAVE_X_ADVANCE_DEVICE ) + { + Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value ); + gd->x_advance += pixel_value << 6; + } + if ( format & HAVE_Y_ADVANCE_DEVICE ) + { + Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value ); + gd->y_advance += pixel_value << 6; + } + } + + /* values returned from mmfunc() are already in fractional pixels */ + + if ( format & HAVE_X_ID_PLACEMENT ) + { + error = (gpos->mmfunc)( gpi->instance, vr->XIdPlacement, + &value, gpos->data ); + if ( error ) + return error; + gd->x_pos += value; + } + if ( format & HAVE_Y_ID_PLACEMENT ) + { + error = (gpos->mmfunc)( gpi->instance, vr->YIdPlacement, + &value, gpos->data ); + if ( error ) + return error; + gd->y_pos += value; + } + if ( format & HAVE_X_ID_ADVANCE ) + { + error = (gpos->mmfunc)( gpi->instance, vr->XIdAdvance, + &value, gpos->data ); + if ( error ) + return error; + gd->x_advance += value; + } + if ( format & HAVE_Y_ID_ADVANCE ) + { + error = (gpos->mmfunc)( gpi->instance, vr->YIdAdvance, + &value, gpos->data ); + if ( error ) + return error; + gd->y_advance += value; + } + + return error; + } + + + /* AnchorFormat1 */ + /* AnchorFormat2 */ + /* AnchorFormat3 */ + /* AnchorFormat4 */ + + static TT_Error Load_Anchor( TTO_Anchor* an, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + an->PosFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( an->PosFormat ) + { + case 1: + if ( ACCESS_Frame( 4L ) ) + return error; + + an->af.af1.XCoordinate = GET_Short(); + an->af.af1.YCoordinate = GET_Short(); + + FORGET_Frame(); + break; + + case 2: + if ( ACCESS_Frame( 6L ) ) + return error; + + an->af.af2.XCoordinate = GET_Short(); + an->af.af2.YCoordinate = GET_Short(); + an->af.af2.AnchorPoint = GET_UShort(); + + FORGET_Frame(); + break; + + case 3: + if ( ACCESS_Frame( 6L ) ) + return error; + + an->af.af3.XCoordinate = GET_Short(); + an->af.af3.YCoordinate = GET_Short(); + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &an->af.af3.XDeviceTable, + input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + } + else + { + an->af.af3.XDeviceTable.StartSize = 0; + an->af.af3.XDeviceTable.EndSize = 0; + an->af.af3.XDeviceTable.DeltaValue = 0; + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Device( &an->af.af3.YDeviceTable, + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + else + { + an->af.af3.YDeviceTable.StartSize = 0; + an->af.af3.YDeviceTable.EndSize = 0; + an->af.af3.YDeviceTable.DeltaValue = 0; + } + break; + + case 4: + if ( ACCESS_Frame( 4L ) ) + return error; + + an->af.af4.XIdAnchor = GET_UShort(); + an->af.af4.YIdAnchor = GET_UShort(); + + FORGET_Frame(); + break; + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; + + Fail: + Free_Device( &an->af.af3.XDeviceTable ); + return error; + } + + + static void Free_Anchor( TTO_Anchor* an ) + { + if ( an->PosFormat == 3 ) + { + Free_Device( &an->af.af3.YDeviceTable ); + Free_Device( &an->af.af3.XDeviceTable ); + } + } + + + static TT_Error Get_Anchor( GPOS_Instance* gpi, + TTO_Anchor* an, + TT_UShort glyph_index, + TT_Pos* x_value, + TT_Pos* y_value ) + { + TT_Error error = TT_Err_Ok; + + PInstance ins; + PGlyph glyph; + TTO_GPOSHeader* gpos = gpi->gpos; + UShort ap; + + Short pixel_value; + UShort load_flags; + + UShort x_ppem, y_ppem; + Fixed x_scale, y_scale; + + + ins = HANDLE_Instance( gpi->instance ); + + x_ppem = ins->metrics.x_ppem; + y_ppem = ins->metrics.y_ppem; + x_scale = TT_MulDiv( 0x10000, + ins->metrics.x_scale1, + ins->metrics.x_scale2 ); + y_scale = TT_MulDiv( 0x10000, + ins->metrics.y_scale1, + ins->metrics.y_scale2 ); + + switch ( an->PosFormat ) + { + case 0: + /* The special case of an empty AnchorTable */ + + return TTO_Err_Not_Covered; + + case 1: + *x_value = x_scale * an->af.af1.XCoordinate / 0x10000; + *y_value = y_scale * an->af.af1.YCoordinate / 0x10000; + break; + + case 2: + /* glyphs must be scaled */ + + load_flags = gpi->load_flags | TTLOAD_SCALE_GLYPH; + + /* we use the glyph contour point only if gpi->glyph.z is not NULL */ + + if ( gpi->glyph.z ) + { + error = (gpos->gfunc)( gpi->instance, gpi->glyph, + glyph_index, load_flags ); + if ( error ) + return error; + + glyph = HANDLE_Glyph( gpi->glyph ); + ap = an->af.af2.AnchorPoint; + + /* if outline.n_points is set to zero by gfunc(), we use the + design coordinate value pair. This can happen e.g. for + sbit glyphs */ + + if ( !glyph->outline.n_points ) + goto no_contour_point; + + if ( ap >= glyph->outline.n_points ) + return TTO_Err_Invalid_GPOS_SubTable; + + *x_value = glyph->outline.points[ap].x; + *y_value = glyph->outline.points[ap].y; + } + else + { + no_contour_point: + *x_value = x_scale * an->af.af3.XCoordinate / 0x10000; + *y_value = y_scale * an->af.af3.YCoordinate / 0x10000; + } + break; + + case 3: + /* we use the device tables only if gpi->glyph.z is not NULL */ + + if ( gpi->glyph.z ) + { + Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value ); + *x_value = pixel_value << 6; + Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value ); + *y_value = pixel_value << 6; + } + else + *x_value = *y_value = 0; + + *x_value += x_scale * an->af.af3.XCoordinate / 0x10000; + *y_value += y_scale * an->af.af3.YCoordinate / 0x10000; + break; + + case 4: + error = (gpos->mmfunc)( gpi->instance, an->af.af4.XIdAnchor, + x_value, gpos->data ); + if ( error ) + return error; + + error = (gpos->mmfunc)( gpi->instance, an->af.af4.YIdAnchor, + y_value, gpos->data ); + if ( error ) + return error; + break; + } + + return error; + } + + + /* MarkArray */ + + static TT_Error Load_MarkArray ( TTO_MarkArray* ma, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_MarkRecord* mr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ma->MarkCount = GET_UShort(); + + FORGET_Frame(); + + ma->MarkRecord = NULL; + + if ( ALLOC_ARRAY( ma->MarkRecord, count, TTO_MarkRecord ) ) + return error; + + mr = ma->MarkRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + mr[n].Class = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &mr[n].MarkAnchor, input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_Anchor( &mr[n].MarkAnchor ); + + FREE( mr ); + return error; + } + + + static void Free_MarkArray( TTO_MarkArray* ma ) + { + UShort n, count; + + TTO_MarkRecord* mr; + + + if ( ma->MarkRecord ) + { + count = ma->MarkCount; + mr = ma->MarkRecord; + + for ( n = 0; n < count; n++ ) + Free_Anchor( &mr[n].MarkAnchor ); + + FREE( mr ); + } + } + + + /* LookupType 1 */ + + /* SinglePosFormat1 */ + /* SinglePosFormat2 */ + + TT_Error Load_SinglePos( TTO_SinglePos* sp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count, format; + ULong cur_offset, new_offset, base_offset; + + TTO_ValueRecord* vr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 6L ) ) + return error; + + sp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + format = sp->ValueFormat = GET_UShort(); + + FORGET_Frame(); + + if ( !format ) + return TTO_Err_Invalid_GPOS_SubTable; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &sp->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + switch ( sp->PosFormat ) + { + case 1: + error = Load_ValueRecord( &sp->spf.spf1.Value, format, + base_offset, input ); + if ( error ) + goto Fail2; + break; + + case 2: + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = sp->spf.spf2.ValueCount = GET_UShort(); + + FORGET_Frame(); + + sp->spf.spf2.Value = NULL; + + if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, TTO_ValueRecord ) ) + goto Fail2; + + vr = sp->spf.spf2.Value; + + for ( n = 0; n < count; n++ ) + { + error = Load_ValueRecord( &vr[n], format, base_offset, input ); + if ( error ) + goto Fail1; + } + break; + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_ValueRecord( &vr[n], format ); + + FREE( vr ); + + Fail2: + Free_Coverage( &sp->Coverage ); + return error; + } + + + void Free_SinglePos( TTO_SinglePos* sp ) + { + UShort n, count, format; + + TTO_ValueRecord* v; + + + format = sp->ValueFormat; + + switch ( sp->PosFormat ) + { + case 1: + Free_ValueRecord( &sp->spf.spf1.Value, format ); + break; + + case 2: + if ( sp->spf.spf2.Value ) + { + count = sp->spf.spf2.ValueCount; + v = sp->spf.spf2.Value; + + for ( n = 0; n < count; n++ ) + Free_ValueRecord( &v[n], format ); + + FREE( v ); + } + break; + } + + Free_Coverage( &sp->Coverage ); + } + + + static TT_Error Lookup_SinglePos( GPOS_Instance* gpi, + TTO_SinglePos* sp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + UShort index, property; + TT_Error error; + TTO_GPOSHeader* gpos = gpi->gpos; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &sp->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + switch ( sp->PosFormat ) + { + case 1: + error = Get_ValueRecord( gpi, &sp->spf.spf1.Value, + sp->ValueFormat, &out[in->pos] ); + if ( error ) + return error; + break; + + case 2: + if ( index >= sp->spf.spf2.ValueCount ) + return TTO_Err_Invalid_GPOS_SubTable; + error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index], + sp->ValueFormat, &out[in->pos] ); + if ( error ) + return error; + break; + + default: + return TTO_Err_Invalid_GPOS_SubTable; + } + + (in->pos)++; + + return TT_Err_Ok; + } + + + /* LookupType 2 */ + + /* PairSet */ + + static TT_Error Load_PairSet ( TTO_PairSet* ps, + UShort format1, + UShort format2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong base_offset; + + TTO_PairValueRecord* pvr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ps->PairValueCount = GET_UShort(); + + FORGET_Frame(); + + ps->PairValueRecord = NULL; + + if ( ALLOC_ARRAY( ps->PairValueRecord, count, TTO_PairValueRecord ) ) + return error; + + pvr = ps->PairValueRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + pvr[n].SecondGlyph = GET_UShort(); + + FORGET_Frame(); + + if ( format1 ) + { + error = Load_ValueRecord( &pvr[n].Value1, format1, + base_offset, input ); + if ( error ) + goto Fail; + } + if ( format2 ) + { + error = Load_ValueRecord( &pvr[n].Value2, format2, + base_offset, input ); + if ( error ) + goto Fail; + } + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + { + if ( format1 ) + Free_ValueRecord( &pvr[n].Value1, format1 ); + if ( format2 ) + Free_ValueRecord( &pvr[n].Value2, format2 ); + } + + FREE( pvr ); + return error; + } + + + static void Free_PairSet( TTO_PairSet* ps, + UShort format1, + UShort format2 ) + { + UShort n, count; + + TTO_PairValueRecord* pvr; + + + if ( ps->PairValueRecord ) + { + count = ps->PairValueCount; + pvr = ps->PairValueRecord; + + for ( n = 0; n < count; n++ ) + { + if ( format1 ) + Free_ValueRecord( &pvr[n].Value1, format1 ); + if ( format2 ) + Free_ValueRecord( &pvr[n].Value2, format2 ); + } + + FREE( pvr ); + } + } + + + /* PairPosFormat1 */ + + static TT_Error Load_PairPos1( TTO_PairPosFormat1* ppf1, + UShort format1, + UShort format2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_PairSet* ps; + + + base_offset = FILE_Pos() - 8L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ppf1->PairSetCount = GET_UShort(); + + FORGET_Frame(); + + ppf1->PairSet = NULL; + + if ( ALLOC_ARRAY( ppf1->PairSet, count, TTO_PairSet ) ) + goto Fail; + + ps = ppf1->PairSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_PairSet( &ps[n], format1, + format2, input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_PairSet( &ps[n], format1, format2 ); + + FREE( ps ); + return error; + } + + + static void Free_PairPos1( TTO_PairPosFormat1* ppf1, + UShort format1, + UShort format2 ) + { + UShort n, count; + + TTO_PairSet* ps; + + + if ( ppf1->PairSet ) + { + count = ppf1->PairSetCount; + ps = ppf1->PairSet; + + for ( n = 0; n < count; n++ ) + Free_PairSet( &ps[n], format1, format2 ); + + FREE( ps ); + } + } + + + /* PairPosFormat2 */ + + static TT_Error Load_PairPos2( TTO_PairPosFormat2* ppf2, + UShort format1, + UShort format2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort m, n, count1, count2; + ULong cur_offset, new_offset1, new_offset2, base_offset; + + TTO_Class1Record* c1r; + TTO_Class2Record* c2r; + + + base_offset = FILE_Pos() - 8L; + + if ( ACCESS_Frame( 8L ) ) + return error; + + new_offset1 = GET_UShort() + base_offset; + new_offset2 = GET_UShort() + base_offset; + + /* `Class1Count' and `Class2Count' are the upper limits for class + values, thus we read it now to make additional safety checks. */ + + count1 = ppf2->Class1Count = GET_UShort(); + count2 = ppf2->Class2Count = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset1 ) || + ( error = Load_ClassDefinition( &ppf2->ClassDef1, count1, + input ) ) != TT_Err_Ok ) + return error; + if ( FILE_Seek( new_offset2 ) || + ( error = Load_ClassDefinition( &ppf2->ClassDef2, count2, + input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + + ppf2->Class1Record = NULL; + + if ( ALLOC_ARRAY( ppf2->Class1Record, count1, TTO_Class1Record ) ) + goto Fail1; + + c1r = ppf2->Class1Record; + + for ( m = 0; m < count1; m++ ) + { + c1r[m].Class2Record = NULL; + + if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, TTO_Class2Record ) ) + goto Fail1; + + c2r = c1r[m].Class2Record; + + for ( n = 0; n < count2; n++ ) + { + if ( format1 ) + { + error = Load_ValueRecord( &c2r[n].Value1, format1, + base_offset, input ); + if ( error ) + goto Fail1; + } + if ( format2 ) + { + error = Load_ValueRecord( &c2r[n].Value2, format2, + base_offset, input ); + if ( error ) + goto Fail1; + } + } + } + + return TT_Err_Ok; + + Fail1: + for ( m = 0; m < count1; m++ ) + { + c2r = c1r[m].Class2Record; + + for ( n = 0; n < count2; n++ ) + { + if ( format1 ) + Free_ValueRecord( &c2r[n].Value1, format1 ); + if ( format2 ) + Free_ValueRecord( &c2r[n].Value2, format2 ); + } + + FREE( c2r ); + } + + FREE( c1r ); + + Free_ClassDefinition( &ppf2->ClassDef2 ); + + Fail2: + Free_ClassDefinition( &ppf2->ClassDef1 ); + return error; + } + + + static void Free_PairPos2( TTO_PairPosFormat2* ppf2, + UShort format1, + UShort format2 ) + { + UShort m, n, count1, count2; + + TTO_Class1Record* c1r; + TTO_Class2Record* c2r; + + + if ( ppf2->Class1Record ) + { + c1r = ppf2->Class1Record; + count1 = ppf2->Class1Count; + count2 = ppf2->Class2Count; + + for ( m = 0; m < count1; m++ ) + { + c2r = c1r[m].Class2Record; + + for ( n = 0; n < count2; n++ ) + { + if ( format1 ) + Free_ValueRecord( &c2r[n].Value1, format1 ); + if ( format2 ) + Free_ValueRecord( &c2r[n].Value2, format2 ); + } + + FREE( c2r ); + } + + FREE( c1r ); + + Free_ClassDefinition( &ppf2->ClassDef2 ); + Free_ClassDefinition( &ppf2->ClassDef1 ); + } + } + + + TT_Error Load_PairPos( TTO_PairPos* pp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort format1, format2; + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 8L ) ) + return error; + + pp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + format1 = pp->ValueFormat1 = GET_UShort(); + format2 = pp->ValueFormat2 = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &pp->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + switch ( pp->PosFormat ) + { + case 1: + error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, input ); + if ( error ) + goto Fail; + break; + + case 2: + error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, input ); + if ( error ) + goto Fail; + break; + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; + + Fail: + Free_Coverage( &pp->Coverage ); + return error; + } + + + void Free_PairPos( TTO_PairPos* pp ) + { + UShort format1, format2; + + + format1 = pp->ValueFormat1; + format2 = pp->ValueFormat2; + + switch ( pp->PosFormat ) + { + case 1: + Free_PairPos1( &pp->ppf.ppf1, format1, format2 ); + break; + + case 2: + Free_PairPos2( &pp->ppf.ppf2, format1, format2 ); + break; + } + + Free_Coverage( &pp->Coverage ); + } + + + static TT_Error Lookup_PairPos1( GPOS_Instance* gpi, + TTO_PairPosFormat1* ppf1, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort first_pos, + UShort index, + UShort format1, + UShort format2 ) + { + TT_Error error; + UShort numpvr, glyph2; + + TTO_PairValueRecord* pvr; + + + if ( index >= ppf1->PairSetCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + pvr = ppf1->PairSet[index].PairValueRecord; + if ( !pvr ) + return TTO_Err_Invalid_GPOS_SubTable; + + glyph2 = in->string[in->pos]; + + for ( numpvr = ppf1->PairSet[index].PairValueCount; + numpvr; + numpvr--, pvr++ ) + { + if ( glyph2 == pvr->SecondGlyph ) + { + error = Get_ValueRecord( gpi, &pvr->Value1, format1, + &out[first_pos] ); + if ( error ) + return error; + return Get_ValueRecord( gpi, &pvr->Value2, format2, + &out[in->pos] ); + } + } + + return TTO_Err_Not_Covered; + } + + + static TT_Error Lookup_PairPos2( GPOS_Instance* gpi, + TTO_PairPosFormat2* ppf2, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort first_pos, + UShort format1, + UShort format2 ) + { + TT_Error error; + UShort cl1, cl2; + + TTO_Class1Record* c1r; + TTO_Class2Record* c2r; + + + error = Get_Class( &ppf2->ClassDef1, in->string[first_pos], + &cl1, NULL ); + if ( error ) + return error; + error = Get_Class( &ppf2->ClassDef2, in->string[in->pos], + &cl2, NULL ); + if ( error ) + return error; + + c1r = &ppf2->Class1Record[cl1]; + if ( !c1r ) + return TTO_Err_Invalid_GPOS_SubTable; + c2r = &c1r->Class2Record[cl2]; + + error = Get_ValueRecord( gpi, &c2r->Value1, format1, &out[first_pos] ); + if ( error ) + return error; + return Get_ValueRecord( gpi, &c2r->Value2, format2, &out[in->pos] ); + } + + + static TT_Error Lookup_PairPos( GPOS_Instance* gpi, + TTO_PairPos* pp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + TT_Error error; + UShort index, property, first_pos; + TTO_GPOSHeader* gpos = gpi->gpos; + + + if ( in->pos >= in->length ) + return TTO_Err_Not_Covered; /* Not enough glyphs in input */ + + if ( context_length != 0xFFFF && context_length < 2 ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + /* second glyph */ + + first_pos = in->pos; + (in->pos)++; + + while ( CHECK_Property( gpos->gdef, in->string[in->pos], + flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos < in->length ) + (in->pos)++; + else + break; + } + + switch ( pp->PosFormat ) + { + case 1: + error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out, + first_pos, index, + pp->ValueFormat1, pp->ValueFormat2 ); + break; + + case 2: + error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, in, out, first_pos, + pp->ValueFormat1, pp->ValueFormat2 ); + break; + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + /* adjusting the `next' glyph */ + + if ( pp->ValueFormat2 ) + (in->pos)++; + + return error; + } + + + /* LookupType 3 */ + + /* CursivePosFormat1 */ + + TT_Error Load_CursivePos( TTO_CursivePos* cp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_EntryExitRecord* eer; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + cp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &cp->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = cp->EntryExitCount = GET_UShort(); + + FORGET_Frame(); + + cp->EntryExitRecord = NULL; + + if ( ALLOC_ARRAY( cp->EntryExitRecord, count, TTO_EntryExitRecord ) ) + goto Fail2; + + eer = cp->EntryExitRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &eer[n].EntryAnchor, + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + eer[n].EntryAnchor.PosFormat = 0; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &eer[n].ExitAnchor, + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + eer[n].ExitAnchor.PosFormat = 0; + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + { + Free_Anchor( &eer[n].EntryAnchor ); + Free_Anchor( &eer[n].ExitAnchor ); + } + + FREE( eer ); + + Fail2: + Free_Coverage( &cp->Coverage ); + return error; + } + + + void Free_CursivePos( TTO_CursivePos* cp ) + { + UShort n, count; + + TTO_EntryExitRecord* eer; + + + if ( cp->EntryExitRecord ) + { + count = cp->EntryExitCount; + eer = cp->EntryExitRecord; + + for ( n = 0; n < count; n++ ) + { + Free_Anchor( &eer[n].EntryAnchor ); + Free_Anchor( &eer[n].ExitAnchor ); + } + + FREE( eer ); + } + + Free_Coverage( &cp->Coverage ); + } + + + static TT_Error Lookup_CursivePos( GPOS_Instance* gpi, + TTO_CursivePos* cp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + UShort index, property; + TT_Error error; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_EntryExitRecord* eer; + TT_Pos entry_x, entry_y; + TT_Pos exit_x, exit_y; + + + if ( context_length != 0xFFFF && context_length < 1 ) + { + gpi->last = 0xFFFF; + return TTO_Err_Not_Covered; + } + + /* Glyphs not having the right GDEF properties will be ignored, i.e., + gpi->last won't be reset (contrary to user defined properties). */ + + if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) ) + return error; + + /* We don't handle mark glyphs here. According to Andrei, this isn't + possible, but who knows... */ + + if ( property == MARK_GLYPH ) + { + gpi->last = 0xFFFF; + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &cp->Coverage, in->string[in->pos], &index ); + if ( error ) + { + gpi->last = 0xFFFF; + return error; + } + + if ( index >= cp->EntryExitCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + eer = &cp->EntryExitRecord[index]; + + /* Now comes the messiest part of the whole OpenType + specification. At first glance, cursive connections seem easy + to understand, but there are pitfalls! The reason is, that + the specs don't mention how to compute the advance values + resp. glyph offsets. I was told it would be an omission, to + be fixed in the next OpenType version... Again many thanks to + Andrei Burago <andreib@microsoft.com> for clarifications. + + Consider the following example: + + | xadv1 | + +---------+ + | | + +-----+--+ 1 | + | | .| | + | 0+--+------+ + | 2 | + | | + 0+--------+ + | xadv2 | + + glyph1: advance width = 12 + anchor point = (3,1) + + glyph2: advance width = 11 + anchor point = (9,4) + + LSB is 1 for both glyphs (so the boxes drawn above are glyph + bboxes). Writing direction is R2L; `0' denotes the glyph's + coordinate origin. + + Now the surprising part: The advance width of the *left* glyph + (resp. of the *bottom* glyph) will be modified, no matter + whether the writing direction is L2R or R2L (resp. T2B or + B2T)! This assymetry is caused by the fact that the glyph's + coordinate origin is always the lower left corner for all + writing directions. + + Continuing the above example, we can compute the new + (horizontal) advance width of glyph2 as + + 9 - 3 = 6 , + + and the new vertical offset of glyph2 as + + 1 - 4 = -3 . + + + Vertical writing direction is far more complicated: + + a) Assuming that we recompute the advance height of the lower glyph: + + -- + +---------+ + -- | | + +-----+--+ 1 | yadv1 + | | .| | + yadv2 | 0+--+------+ -- BSB1 -- + | 2 | -- -- y_offset + | | + BSB2 -- 0+--------+ -- + -- -- + + glyph1: advance height = 6 + anchor point = (3,1) + + glyph2: advance height = 7 + anchor point = (9,4) + + TSB is 1 for both glyphs; writing direction is T2B. + + + BSB1 = yadv1 - (TSB1 + ymax1) + BSB2 = yadv2 - (TSB2 + ymax2) + y_offset = y2 - y1 + + vertical advance width of glyph2 + = y_offset + BSB2 - BSB1 + = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1)) + = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1) + = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1 + + + b) Assuming that we recompute the advance height of the upper glyph: + + -- -- + +---------+ -- TSB1 + -- -- | | + TSB2 -- +-----+--+ 1 | yadv1 ymax1 + | | .| | + yadv2 | 0+--+------+ -- -- + ymax2 | 2 | -- y_offset + | | + -- 0+--------+ -- + -- + + glyph1: advance height = 6 + anchor point = (3,1) + + glyph2: advance height = 7 + anchor point = (9,4) + + TSB is 1 for both glyphs; writing direction is T2B. + + y_offset = y2 - y1 + + vertical advance width of glyph2 + = TSB1 + ymax1 + y_offset - (TSB2 + ymax2) + = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2 + + + Comparing a) with b) shows that b) is easier to compute. I'll wait + for a reply from Andrei to see what should really be implemented... + + Since horizontal advance widths or vertical advance heights + can be used alone but not together, no ambiguity occurs. */ + + if ( gpi->last == 0xFFFF ) + goto end; + + /* Get_Anchor() returns TTO_Err_Not_Covered if there is no anchor + table. */ + + error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos], + &entry_x, &entry_y ); + if ( error == TTO_Err_Not_Covered ) + goto end; + if ( error ) + return error; + + if ( gpi->r2l ) + { + out[in->pos].x_advance = entry_x - gpi->anchor_x; + out[in->pos].new_advance = TRUE; + } + else + { + out[gpi->last].x_advance = gpi->anchor_x - entry_x; + out[gpi->last].new_advance = TRUE; + } + + out[in->pos].y_pos = gpi->anchor_y - entry_y + out[gpi->last].y_pos; + + end: + error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos], + &exit_x, &exit_y ); + if ( error == TTO_Err_Not_Covered ) + gpi->last = 0xFFFF; + else + { + gpi->last = in->pos; + gpi->anchor_x = exit_x; + gpi->anchor_y = exit_y; + } + if ( error ) + return error; + + (in->pos)++; + + return TT_Err_Ok; + } + + + /* LookupType 4 */ + + /* BaseArray */ + + static TT_Error Load_BaseArray( TTO_BaseArray* ba, + UShort num_classes, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort m, n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_BaseRecord* br; + TTO_Anchor* ban; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ba->BaseCount = GET_UShort(); + + FORGET_Frame(); + + ba->BaseRecord = NULL; + + if ( ALLOC_ARRAY( ba->BaseRecord, count, TTO_BaseRecord ) ) + return error; + + br = ba->BaseRecord; + + for ( m = 0; m < count; m++ ) + { + br[m].BaseAnchor = NULL; + + if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, TTO_Anchor ) ) + goto Fail; + + ban = br[m].BaseAnchor; + + for ( n = 0; n < num_classes; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &ban[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + } + + return TT_Err_Ok; + + Fail: + for ( m = 0; m < count; m++ ) + { + ban = br[m].BaseAnchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &ban[n] ); + + FREE( ban ); + } + + FREE( br ); + return error; + } + + + static void Free_BaseArray( TTO_BaseArray* ba, + UShort num_classes ) + { + UShort m, n, count; + + TTO_BaseRecord* br; + TTO_Anchor* ban; + + + if ( ba->BaseRecord ) + { + count = ba->BaseCount; + br = ba->BaseRecord; + + for ( m = 0; m < count; m++ ) + { + ban = br[m].BaseAnchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &ban[n] ); + + FREE( ban ); + } + + FREE( br ); + } + } + + + /* MarkBasePosFormat1 */ + + TT_Error Load_MarkBasePos( TTO_MarkBasePos* mbp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + mbp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mbp->MarkCoverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mbp->BaseCoverage, input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 4L ) ) + goto Fail2; + + mbp->ClassCount = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_MarkArray( &mbp->MarkArray, input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount, + input ) ) != TT_Err_Ok ) + goto Fail1; + + return TT_Err_Ok; + + Fail1: + Free_MarkArray( &mbp->MarkArray ); + + Fail2: + Free_Coverage( &mbp->BaseCoverage ); + + Fail3: + Free_Coverage( &mbp->MarkCoverage ); + return error; + } + + + void Free_MarkBasePos( TTO_MarkBasePos* mbp ) + { + Free_BaseArray( &mbp->BaseArray, mbp->ClassCount ); + Free_MarkArray( &mbp->MarkArray ); + Free_Coverage( &mbp->BaseCoverage ); + Free_Coverage( &mbp->MarkCoverage ); + } + + + static TT_Error Lookup_MarkBasePos( GPOS_Instance* gpi, + TTO_MarkBasePos* mbp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + UShort i, j, mark_index, base_index, property, class; + TT_Pos x_mark_value, y_mark_value, x_base_value, y_base_value; + TT_Error error; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_MarkArray* ma; + TTO_BaseArray* ba; + TTO_BaseRecord* br; + TTO_Anchor* mark_anchor; + TTO_Anchor* base_anchor; + + TTO_GPOS_Data* o; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( flags & IGNORE_BASE_GLYPHS ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gpos->gdef, in->string[in->pos], + flags, &property ) ) + return error; + + error = Coverage_Index( &mbp->MarkCoverage, in->string[in->pos], + &mark_index ); + if ( error ) + return error; + + /* now we search backwards for a base glyph */ + + i = 1; + j = in->pos - 1; + + while ( i <= in->pos ) + { + error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], + &property ); + if ( error ) + return error; + + if ( property != TTO_MARK ) + break; + + i++; + j--; + } + + if ( property != TTO_BASE_GLYPH ) + return TTO_Err_Not_Covered; + + if ( i > in->pos ) + return TTO_Err_Not_Covered; + + error = Coverage_Index( &mbp->BaseCoverage, in->string[j], + &base_index ); + if ( error ) + return error; + + ma = &mbp->MarkArray; + + if ( mark_index >= ma->MarkCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + class = ma->MarkRecord[mark_index].Class; + mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; + + if ( class >= mbp->ClassCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + ba = &mbp->BaseArray; + + if ( base_index >= ba->BaseCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + br = &ba->BaseRecord[base_index]; + base_anchor = &br->BaseAnchor[class]; + + error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], + &x_mark_value, &y_mark_value ); + if ( error ) + return error; + error = Get_Anchor( gpi, base_anchor, in->string[j], + &x_base_value, &y_base_value ); + if ( error ) + return error; + + /* anchor points are not cumulative */ + + o = &out[in->pos]; + + o->x_pos = x_base_value - x_mark_value; + o->y_pos = y_base_value - y_mark_value; + o->x_advance = 0; + o->y_advance = 0; + o->back = i; + + (in->pos)++; + + return TT_Err_Ok; + } + + + /* LookupType 5 */ + + /* LigatureAttach */ + + static TT_Error Load_LigatureAttach( TTO_LigatureAttach* lat, + UShort num_classes, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort m, n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ComponentRecord* cr; + TTO_Anchor* lan; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = lat->ComponentCount = GET_UShort(); + + FORGET_Frame(); + + lat->ComponentRecord = NULL; + + if ( ALLOC_ARRAY( lat->ComponentRecord, count, TTO_ComponentRecord ) ) + return error; + + cr = lat->ComponentRecord; + + for ( m = 0; m < count; m++ ) + { + cr[m].LigatureAnchor = NULL; + + if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, TTO_Anchor ) ) + goto Fail; + + lan = cr[m].LigatureAnchor; + + for ( n = 0; n < num_classes; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( new_offset ) + { + new_offset += base_offset; + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &lan[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + else + lan[n].PosFormat = 0; + } + } + + return TT_Err_Ok; + + Fail: + for ( m = 0; m < count; m++ ) + { + lan = cr[m].LigatureAnchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &lan[n] ); + + FREE( lan ); + } + + FREE( cr ); + return error; + } + + + static void Free_LigatureAttach( TTO_LigatureAttach* lat, + UShort num_classes ) + { + UShort m, n, count; + + TTO_ComponentRecord* cr; + TTO_Anchor* lan; + + + if ( lat->ComponentRecord ) + { + count = lat->ComponentCount; + cr = lat->ComponentRecord; + + for ( m = 0; m < count; m++ ) + { + lan = cr[m].LigatureAnchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &lan[n] ); + + FREE( lan ); + } + + FREE( cr ); + } + } + + + /* LigatureArray */ + + static TT_Error Load_LigatureArray( TTO_LigatureArray* la, + UShort num_classes, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_LigatureAttach* lat; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = la->LigatureCount = GET_UShort(); + + FORGET_Frame(); + + la->LigatureAttach = NULL; + + if ( ALLOC_ARRAY( la->LigatureAttach, count, TTO_LigatureAttach ) ) + return error; + + lat = la->LigatureAttach; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LigatureAttach( &lat[n], num_classes, + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_LigatureAttach( &lat[n], num_classes ); + + FREE( lat ); + return error; + } + + + static void Free_LigatureArray( TTO_LigatureArray* la, + UShort num_classes ) + { + UShort n, count; + + TTO_LigatureAttach* lat; + + + if ( la->LigatureAttach ) + { + count = la->LigatureCount; + lat = la->LigatureAttach; + + for ( n = 0; n < count; n++ ) + Free_LigatureAttach( &lat[n], num_classes ); + + FREE( lat ); + } + } + + + /* MarkLigPosFormat1 */ + + TT_Error Load_MarkLigPos( TTO_MarkLigPos* mlp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + mlp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mlp->MarkCoverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mlp->LigatureCoverage, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 4L ) ) + goto Fail2; + + mlp->ClassCount = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_MarkArray( &mlp->MarkArray, input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, + input ) ) != TT_Err_Ok ) + goto Fail1; + + return TT_Err_Ok; + + Fail1: + Free_MarkArray( &mlp->MarkArray ); + + Fail2: + Free_Coverage( &mlp->LigatureCoverage ); + + Fail3: + Free_Coverage( &mlp->MarkCoverage ); + return error; + } + + + void Free_MarkLigPos( TTO_MarkLigPos* mlp ) + { + Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount ); + Free_MarkArray( &mlp->MarkArray ); + Free_Coverage( &mlp->LigatureCoverage ); + Free_Coverage( &mlp->MarkCoverage ); + } + + + static TT_Error Lookup_MarkLigPos( GPOS_Instance* gpi, + TTO_MarkLigPos* mlp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + UShort i, j, mark_index, lig_index, property, class; + UShort mark_glyph; + TT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value; + TT_Error error; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_MarkArray* ma; + TTO_LigatureArray* la; + TTO_LigatureAttach* lat; + TTO_ComponentRecord* cr; + UShort comp_index; + TTO_Anchor* mark_anchor; + TTO_Anchor* lig_anchor; + + TTO_GPOS_Data* o; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( flags & IGNORE_LIGATURES ) + return TTO_Err_Not_Covered; + + mark_glyph = in->string[in->pos]; + + if ( CHECK_Property( gpos->gdef, mark_glyph, flags, &property ) ) + return error; + + error = Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index ); + if ( error ) + return error; + + /* now we search backwards for a ligature */ + + i = 1; + j = in->pos - 1; + + while ( i <= in->pos ) + { + error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], + &property ); + if ( error ) + return error; + + if ( property != TTO_MARK ) + break; + + i++; + j--; + } + + if ( property != TTO_LIGATURE ) + return TTO_Err_Not_Covered; + + if ( i > in->pos ) + return TTO_Err_Not_Covered; + + error = Coverage_Index( &mlp->LigatureCoverage, in->string[j], + &lig_index ); + if ( error ) + return error; + + ma = &mlp->MarkArray; + + if ( mark_index >= ma->MarkCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + class = ma->MarkRecord[mark_index].Class; + mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; + + if ( class >= mlp->ClassCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + la = &mlp->LigatureArray; + + if ( lig_index >= la->LigatureCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + lat = &la->LigatureAttach[lig_index]; + + /* We must now check whether the ligature ID of the current mark glyph + is identical to the ligature ID of the found ligature. If yes, we + can directly use the component index. If not, we attach the mark + glyph to the last component of the ligature. */ + + if ( in->ligIDs && in->components && + in->ligIDs[j] == in->ligIDs[in->pos] ) + { + comp_index = in->components[in->pos]; + if ( comp_index >= lat->ComponentCount ) + return TTO_Err_Not_Covered; + } + else + comp_index = lat->ComponentCount - 1; + + cr = &lat->ComponentRecord[comp_index]; + lig_anchor = &cr->LigatureAnchor[class]; + + error = Get_Anchor( gpi, mark_anchor, in->string[in->pos], + &x_mark_value, &y_mark_value ); + if ( error ) + return error; + error = Get_Anchor( gpi, lig_anchor, in->string[j], + &x_lig_value, &y_lig_value ); + if ( error ) + return error; + + /* anchor points are not cumulative */ + + o = &out[in->pos]; + + o->x_pos = x_lig_value - x_mark_value; + o->y_pos = y_lig_value - y_mark_value; + o->x_advance = 0; + o->y_advance = 0; + o->back = i; + + (in->pos)++; + + return TT_Err_Ok; + } + + + /* LookupType 6 */ + + /* Mark2Array */ + + static TT_Error Load_Mark2Array( TTO_Mark2Array* m2a, + UShort num_classes, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort m, n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Mark2Record* m2r; + TTO_Anchor* m2an; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = m2a->Mark2Count = GET_UShort(); + + FORGET_Frame(); + + m2a->Mark2Record = NULL; + + if ( ALLOC_ARRAY( m2a->Mark2Record, count, TTO_Mark2Record ) ) + return error; + + m2r = m2a->Mark2Record; + + for ( m = 0; m < count; m++ ) + { + m2r[m].Mark2Anchor = NULL; + + if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, TTO_Anchor ) ) + goto Fail; + + m2an = m2r[m].Mark2Anchor; + + for ( n = 0; n < num_classes; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Anchor( &m2an[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + } + + return TT_Err_Ok; + + Fail: + for ( m = 0; m < count; m++ ) + { + m2an = m2r[m].Mark2Anchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &m2an[n] ); + + FREE( m2an ); + } + + FREE( m2r ); + return error; + } + + + static void Free_Mark2Array( TTO_Mark2Array* m2a, + UShort num_classes ) + { + UShort m, n, count; + + TTO_Mark2Record* m2r; + TTO_Anchor* m2an; + + + if ( m2a->Mark2Record ) + { + count = m2a->Mark2Count; + m2r = m2a->Mark2Record; + + for ( m = 0; m < count; m++ ) + { + m2an = m2r[m].Mark2Anchor; + + for ( n = 0; n < num_classes; n++ ) + Free_Anchor( &m2an[n] ); + + FREE( m2an ); + } + + FREE( m2r ); + } + } + + + /* MarkMarkPosFormat1 */ + + TT_Error Load_MarkMarkPos( TTO_MarkMarkPos* mmp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + ULong cur_offset, new_offset, base_offset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + mmp->PosFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mmp->Mark1Coverage, + input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &mmp->Mark2Coverage, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 4L ) ) + goto Fail2; + + mmp->ClassCount = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_MarkArray( &mmp->Mark1Array, input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, + input ) ) != TT_Err_Ok ) + goto Fail1; + + return TT_Err_Ok; + + Fail1: + Free_MarkArray( &mmp->Mark1Array ); + + Fail2: + Free_Coverage( &mmp->Mark2Coverage ); + + Fail3: + Free_Coverage( &mmp->Mark1Coverage ); + return error; + } + + + void Free_MarkMarkPos( TTO_MarkMarkPos* mmp ) + { + Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount ); + Free_MarkArray( &mmp->Mark1Array ); + Free_Coverage( &mmp->Mark2Coverage ); + Free_Coverage( &mmp->Mark1Coverage ); + } + + + static TT_Error Lookup_MarkMarkPos( GPOS_Instance* gpi, + TTO_MarkMarkPos* mmp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length ) + { + UShort j, mark1_index, mark2_index, property, class; + TT_Pos x_mark1_value, y_mark1_value, + x_mark2_value, y_mark2_value; + TT_Error error; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_MarkArray* ma1; + TTO_Mark2Array* ma2; + TTO_Mark2Record* m2r; + TTO_Anchor* mark1_anchor; + TTO_Anchor* mark2_anchor; + + TTO_GPOS_Data* o; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( flags & IGNORE_MARKS ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gpos->gdef, in->string[in->pos], + flags, &property ) ) + return error; + + error = Coverage_Index( &mmp->Mark1Coverage, in->string[in->pos], + &mark1_index ); + if ( error ) + return error; + + /* now we check the preceding glyph whether it is a suitable + mark glyph */ + + if ( in->pos == 0 ) + return TTO_Err_Not_Covered; + + j = in->pos - 1; + error = TT_GDEF_Get_Glyph_Property( gpos->gdef, in->string[j], + &property ); + if ( error ) + return error; + + if ( flags & IGNORE_SPECIAL_MARKS ) + { + if ( property != (flags & 0xFF00) ) + return TTO_Err_Not_Covered; + } + else + { + if ( property != TTO_MARK ) + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &mmp->Mark2Coverage, in->string[j], + &mark2_index ); + if ( error ) + return error; + + ma1 = &mmp->Mark1Array; + + if ( mark1_index >= ma1->MarkCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + class = ma1->MarkRecord[mark1_index].Class; + mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor; + + if ( class >= mmp->ClassCount ) + return TTO_Err_Invalid_GPOS_SubTable; + + ma2 = &mmp->Mark2Array; + + if ( mark2_index >= ma2->Mark2Count ) + return TTO_Err_Invalid_GPOS_SubTable; + + m2r = &ma2->Mark2Record[mark2_index]; + mark2_anchor = &m2r->Mark2Anchor[class]; + + error = Get_Anchor( gpi, mark1_anchor, in->string[in->pos], + &x_mark1_value, &y_mark1_value ); + if ( error ) + return error; + error = Get_Anchor( gpi, mark2_anchor, in->string[j], + &x_mark2_value, &y_mark2_value ); + if ( error ) + return error; + + /* anchor points are not cumulative */ + + o = &out[in->pos]; + + o->x_pos = x_mark2_value - x_mark1_value; + o->y_pos = y_mark2_value - y_mark1_value; + o->x_advance = 0; + o->y_advance = 0; + o->back = 1; + + (in->pos)++; + + return TT_Err_Ok; + } + + + /* Do the actual positioning for a context positioning (either format + 7 or 8). This is only called after we've determined that the input + matches the subrule. */ + + static TT_Error Do_ContextPos( GPOS_Instance* gpi, + UShort GlyphCount, + UShort PosCount, + TTO_PosLookupRecord* pos, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + int nesting_level ) + { + TT_Error error; + UShort i, old_pos; + + + i = 0; + + while ( i < GlyphCount ) + { + if ( PosCount && i == pos->SequenceIndex ) + { + old_pos = in->pos; + + /* Do a positioning */ + + error = Do_Glyph_Lookup( gpi, pos->LookupListIndex, in, out, + GlyphCount, nesting_level ); + + if ( error ) + return error; + + pos++; + PosCount--; + i += in->pos - old_pos; + } + else + { + i++; + (in->pos)++; + } + } + + return TT_Err_Ok; + } + + + /* LookupType 7 */ + + /* PosRule */ + + static TT_Error Load_PosRule( TTO_PosRule* pr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* i; + + TTO_PosLookupRecord* plr; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + pr->GlyphCount = GET_UShort(); + pr->PosCount = GET_UShort(); + + FORGET_Frame(); + + pr->Input = NULL; + + count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( pr->Input, count, UShort ) ) + return error; + + i = pr->Input; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + i[n] = GET_UShort(); + + FORGET_Frame(); + + pr->PosLookupRecord = NULL; + + count = pr->PosCount; + + if ( ALLOC_ARRAY( pr->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = pr->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + FREE( i ); + return error; + } + + + static void Free_PosRule( TTO_PosRule* pr ) + { + FREE( pr->PosLookupRecord ); + FREE( pr->Input ); + } + + + /* PosRuleSet */ + + static TT_Error Load_PosRuleSet( TTO_PosRuleSet* prs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_PosRule* pr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = prs->PosRuleCount = GET_UShort(); + + FORGET_Frame(); + + prs->PosRule = NULL; + + if ( ALLOC_ARRAY( prs->PosRule, count, TTO_PosRule ) ) + return error; + + pr = prs->PosRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_PosRule( &pr[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_PosRule( &pr[n] ); + + FREE( pr ); + return error; + } + + + static void Free_PosRuleSet( TTO_PosRuleSet* prs ) + { + UShort n, count; + + TTO_PosRule* pr; + + + if ( prs->PosRule ) + { + count = prs->PosRuleCount; + pr = prs->PosRule; + + for ( n = 0; n < count; n++ ) + Free_PosRule( &pr[n] ); + + FREE( pr ); + } + } + + + /* ContextPosFormat1 */ + + static TT_Error Load_ContextPos1( TTO_ContextPosFormat1* cpf1, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_PosRuleSet* prs; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &cpf1->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = cpf1->PosRuleSetCount = GET_UShort(); + + FORGET_Frame(); + + cpf1->PosRuleSet = NULL; + + if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, TTO_PosRuleSet ) ) + goto Fail2; + + prs = cpf1->PosRuleSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_PosRuleSet( &prs[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_PosRuleSet( &prs[n] ); + + FREE( prs ); + + Fail2: + Free_Coverage( &cpf1->Coverage ); + return error; + } + + + static void Free_Context1( TTO_ContextPosFormat1* cpf1 ) + { + UShort n, count; + + TTO_PosRuleSet* prs; + + + if ( cpf1->PosRuleSet ) + { + count = cpf1->PosRuleSetCount; + prs = cpf1->PosRuleSet; + + for ( n = 0; n < count; n++ ) + Free_PosRuleSet( &prs[n] ); + + FREE( prs ); + } + + Free_Coverage( &cpf1->Coverage ); + } + + + /* PosClassRule */ + + static TT_Error Load_PosClassRule( TTO_ContextPosFormat2* cpf2, + TTO_PosClassRule* pcr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* c; + TTO_PosLookupRecord* plr; + Bool* d; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + pcr->GlyphCount = GET_UShort(); + pcr->PosCount = GET_UShort(); + + FORGET_Frame(); + + if ( pcr->GlyphCount > cpf2->MaxContextLength ) + cpf2->MaxContextLength = pcr->GlyphCount; + + pcr->Class = NULL; + + count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( pcr->Class, count, UShort ) ) + return error; + + c = pcr->Class; + d = cpf2->ClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + { + c[n] = GET_UShort(); + + /* We check whether the specific class is used at all. If not, + class 0 is used instead. */ + + if ( !d[c[n]] ) + c[n] = 0; + } + + FORGET_Frame(); + + pcr->PosLookupRecord = NULL; + + count = pcr->PosCount; + + if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = pcr->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + FREE( c ); + return error; + } + + + static void Free_PosClassRule( TTO_PosClassRule* pcr ) + { + FREE( pcr->PosLookupRecord ); + FREE( pcr->Class ); + } + + + /* PosClassSet */ + + static TT_Error Load_PosClassSet( TTO_ContextPosFormat2* cpf2, + TTO_PosClassSet* pcs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_PosClassRule* pcr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = pcs->PosClassRuleCount = GET_UShort(); + + FORGET_Frame(); + + pcs->PosClassRule = NULL; + + if ( ALLOC_ARRAY( pcs->PosClassRule, count, TTO_PosClassRule ) ) + return error; + + pcr = pcs->PosClassRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_PosClassRule( cpf2, &pcr[n], + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_PosClassRule( &pcr[n] ); + + FREE( pcr ); + return error; + } + + + static void Free_PosClassSet( TTO_PosClassSet* pcs ) + { + UShort n, count; + + TTO_PosClassRule* pcr; + + + if ( pcs->PosClassRule ) + { + count = pcs->PosClassRuleCount; + pcr = pcs->PosClassRule; + + for ( n = 0; n < count; n++ ) + Free_PosClassRule( &pcr[n] ); + + FREE( pcr ); + } + } + + + /* ContextPosFormat2 */ + + static TT_Error Load_ContextPos2( TTO_ContextPosFormat2* cpf2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_PosClassSet* pcs; + + + base_offset = FILE_Pos() - 2; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &cpf2->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 4L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + /* `PosClassSetCount' is the upper limit for class values, thus we + read it now to make an additional safety check. */ + + count = cpf2->PosClassSetCount = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ClassDefinition( &cpf2->ClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + cpf2->PosClassSet = NULL; + cpf2->MaxContextLength = 0; + + if ( ALLOC_ARRAY( cpf2->PosClassSet, count, TTO_PosClassSet ) ) + goto Fail2; + + pcs = cpf2->PosClassSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + if ( new_offset != base_offset ) /* not a NULL offset */ + { + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_PosClassSet( cpf2, &pcs[n], + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + { + /* we create a PosClassSet table with no entries */ + + cpf2->PosClassSet[n].PosClassRuleCount = 0; + cpf2->PosClassSet[n].PosClassRule = NULL; + } + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_PosClassSet( &pcs[n] ); + + FREE( pcs ); + + Fail2: + Free_ClassDefinition( &cpf2->ClassDef ); + + Fail3: + Free_Coverage( &cpf2->Coverage ); + return error; + } + + + static void Free_Context2( TTO_ContextPosFormat2* cpf2 ) + { + UShort n, count; + + TTO_PosClassSet* pcs; + + + if ( cpf2->PosClassSet ) + { + count = cpf2->PosClassSetCount; + pcs = cpf2->PosClassSet; + + for ( n = 0; n < count; n++ ) + Free_PosClassSet( &pcs[n] ); + + FREE( pcs ); + } + + Free_ClassDefinition( &cpf2->ClassDef ); + Free_Coverage( &cpf2->Coverage ); + } + + + /* ContextPosFormat3 */ + + static TT_Error Load_ContextPos3( TTO_ContextPosFormat3* cpf3, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Coverage* c; + TTO_PosLookupRecord* plr; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 4L ) ) + return error; + + cpf3->GlyphCount = GET_UShort(); + cpf3->PosCount = GET_UShort(); + + FORGET_Frame(); + + cpf3->Coverage = NULL; + + count = cpf3->GlyphCount; + + if ( ALLOC_ARRAY( cpf3->Coverage, count, TTO_Coverage ) ) + return error; + + c = cpf3->Coverage; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &c[n], input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + + cpf3->PosLookupRecord = NULL; + + count = cpf3->PosCount; + + if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = cpf3->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + return error; + } + + + static void Free_Context3( TTO_ContextPosFormat3* cpf3 ) + { + UShort n, count; + + TTO_Coverage* c; + + + FREE( cpf3->PosLookupRecord ); + + if ( cpf3->Coverage ) + { + count = cpf3->GlyphCount; + c = cpf3->Coverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + } + + + /* ContextPos */ + + TT_Error Load_ContextPos( TTO_ContextPos* cp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ACCESS_Frame( 2L ) ) + return error; + + cp->PosFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( cp->PosFormat ) + { + case 1: + return Load_ContextPos1( &cp->cpf.cpf1, input ); + + case 2: + return Load_ContextPos2( &cp->cpf.cpf2, input ); + + case 3: + return Load_ContextPos3( &cp->cpf.cpf3, input ); + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + void Free_ContextPos( TTO_ContextPos* cp ) + { + switch ( cp->PosFormat ) + { + case 1: + Free_Context1( &cp->cpf.cpf1 ); + break; + + case 2: + Free_Context2( &cp->cpf.cpf2 ); + break; + + case 3: + Free_Context3( &cp->cpf.cpf3 ); + break; + } + } + + + static TT_Error Lookup_ContextPos1( GPOS_Instance* gpi, + TTO_ContextPosFormat1* cpf1, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + UShort i, j, k, numpr; + TT_Error error; + UShort* s_in; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_PosRule* pr; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &cpf1->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + pr = cpf1->PosRuleSet[index].PosRule; + numpr = cpf1->PosRuleSet[index].PosRuleCount; + + for ( k = 0; k < numpr; k++ ) + { + if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) + continue; + + if ( in->pos + pr[k].GlyphCount > in->length ) + continue; /* context is too long */ + + s_in = &in->string[in->pos]; + + for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != pr[k].Input[i - 1] ) + break; + } + + if ( i == pr[k].GlyphCount ) + return Do_ContextPos( gpi, pr[k].GlyphCount, + pr[k].PosCount, pr[k].PosLookupRecord, + in, out, + nesting_level ); + } + + return TTO_Err_Not_Covered; + } + + + static TT_Error Lookup_ContextPos2( GPOS_Instance* gpi, + TTO_ContextPosFormat2* cpf2, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + TT_Error error; + UShort i, j, k, known_classes; + + UShort* classes; + UShort* s_in; + UShort* cl; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_PosClassSet* pcs; + TTO_PosClassRule* pr; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, UShort ) ) + return error; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + /* Note: The coverage table in format 2 doesn't give an index into + anything. It just lets us know whether or not we need to + do any lookup at all. */ + + error = Coverage_Index( &cpf2->Coverage, in->string[in->pos], &index ); + if ( error ) + goto End; + + error = Get_Class( &cpf2->ClassDef, in->string[in->pos], + &classes[0], NULL ); + if ( error ) + goto End; + known_classes = 0; + + pcs = &cpf2->PosClassSet[classes[0]]; + if ( !pcs ) + { + error = TTO_Err_Invalid_GPOS_SubTable; + goto End; + } + + for ( k = 0; k < pcs->PosClassRuleCount; k++ ) + { + pr = &pcs->PosClassRule[k]; + + if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) + continue; + + if ( in->pos + pr->GlyphCount > in->length ) + continue; /* context is too long */ + + s_in = &in->string[in->pos]; + cl = pr->Class; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + break; + } + + if ( i > known_classes ) + { + /* Keeps us from having to do this for each rule */ + + error = Get_Class( &cpf2->ClassDef, s_in[j], &classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + known_classes = i; + } + + if ( cl[i - 1] != classes[i] ) + break; + } + + if ( i == pr->GlyphCount ) + { + error = Do_ContextPos( gpi, pr->GlyphCount, + pr->PosCount, pr->PosLookupRecord, + in, out, + nesting_level ); + goto End; + } + } + + error = TTO_Err_Not_Covered; + + End: + FREE( classes ); + return error; + } + + + static TT_Error Lookup_ContextPos3( GPOS_Instance* gpi, + TTO_ContextPosFormat3* cpf3, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + TT_Error error; + UShort index, i, j, property; + UShort* s_in; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_Coverage* c; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount ) + return TTO_Err_Not_Covered; + + if ( in->pos + cpf3->GlyphCount > in->length ) + return TTO_Err_Not_Covered; /* context is too long */ + + s_in = &in->string[in->pos]; + c = cpf3->Coverage; + + for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &c[i], s_in[j], &index ); + if ( error ) + return error; + } + + return Do_ContextPos( gpi, cpf3->GlyphCount, + cpf3->PosCount, cpf3->PosLookupRecord, + in, out, + nesting_level ); + } + + + static TT_Error Lookup_ContextPos( GPOS_Instance* gpi, + TTO_ContextPos* cp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + switch ( cp->PosFormat ) + { + case 1: + return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, in, out, + flags, context_length, nesting_level ); + + case 2: + return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, in, out, + flags, context_length, nesting_level ); + + case 3: + return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, in, out, + flags, context_length, nesting_level ); + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + /* LookupType 8 */ + + /* ChainPosRule */ + + static TT_Error Load_ChainPosRule( TTO_ChainPosRule* cpr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* b; + UShort* i; + UShort* l; + + TTO_PosLookupRecord* plr; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + cpr->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + cpr->Backtrack = NULL; + + count = cpr->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( cpr->Backtrack, count, UShort ) ) + return error; + + b = cpr->Backtrack; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail4; + + for ( n = 0; n < count; n++ ) + b[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + cpr->InputGlyphCount = GET_UShort(); + + FORGET_Frame(); + + cpr->Input = NULL; + + count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( cpr->Input, count, UShort ) ) + goto Fail4; + + i = cpr->Input; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail3; + + for ( n = 0; n < count; n++ ) + i[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + cpr->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + cpr->Lookahead = NULL; + + count = cpr->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( cpr->Lookahead, count, UShort ) ) + goto Fail3; + + l = cpr->Lookahead; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + l[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + cpr->PosCount = GET_UShort(); + + FORGET_Frame(); + + cpr->PosLookupRecord = NULL; + + count = cpr->PosCount; + + if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = cpr->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + FREE( l ); + + Fail3: + FREE( i ); + + Fail4: + FREE( b ); + return error; + } + + + static void Free_ChainPosRule( TTO_ChainPosRule* cpr ) + { + FREE( cpr->PosLookupRecord ); + FREE( cpr->Lookahead ); + FREE( cpr->Input ); + FREE( cpr->Backtrack ); + } + + + /* ChainPosRuleSet */ + + static TT_Error Load_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainPosRule* cpr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cprs->ChainPosRuleCount = GET_UShort(); + + FORGET_Frame(); + + cprs->ChainPosRule = NULL; + + if ( ALLOC_ARRAY( cprs->ChainPosRule, count, TTO_ChainPosRule ) ) + return error; + + cpr = cprs->ChainPosRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainPosRule( &cpr[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_ChainPosRule( &cpr[n] ); + + FREE( cpr ); + return error; + } + + + static void Free_ChainPosRuleSet( TTO_ChainPosRuleSet* cprs ) + { + UShort n, count; + + TTO_ChainPosRule* cpr; + + + if ( cprs->ChainPosRule ) + { + count = cprs->ChainPosRuleCount; + cpr = cprs->ChainPosRule; + + for ( n = 0; n < count; n++ ) + Free_ChainPosRule( &cpr[n] ); + + FREE( cpr ); + } + } + + + /* ChainContextPosFormat1 */ + + static TT_Error Load_ChainContextPos1( TTO_ChainContextPosFormat1* ccpf1, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainPosRuleSet* cprs; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ccpf1->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = ccpf1->ChainPosRuleSetCount = GET_UShort(); + + FORGET_Frame(); + + ccpf1->ChainPosRuleSet = NULL; + + if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, TTO_ChainPosRuleSet ) ) + goto Fail2; + + cprs = ccpf1->ChainPosRuleSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainPosRuleSet( &cprs[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_ChainPosRuleSet( &cprs[n] ); + + FREE( cprs ); + + Fail2: + Free_Coverage( &ccpf1->Coverage ); + return error; + } + + + static void Free_ChainContext1( TTO_ChainContextPosFormat1* ccpf1 ) + { + UShort n, count; + + TTO_ChainPosRuleSet* cprs; + + + if ( ccpf1->ChainPosRuleSet ) + { + count = ccpf1->ChainPosRuleSetCount; + cprs = ccpf1->ChainPosRuleSet; + + for ( n = 0; n < count; n++ ) + Free_ChainPosRuleSet( &cprs[n] ); + + FREE( cprs ); + } + + Free_Coverage( &ccpf1->Coverage ); + } + + + /* ChainPosClassRule */ + + static TT_Error Load_ChainPosClassRule( + TTO_ChainContextPosFormat2* ccpf2, + TTO_ChainPosClassRule* cpcr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* b; + UShort* i; + UShort* l; + TTO_PosLookupRecord* plr; + Bool* d; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + cpcr->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength ) + ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount; + + cpcr->Backtrack = NULL; + + count = cpcr->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( cpcr->Backtrack, count, UShort ) ) + return error; + + b = cpcr->Backtrack; + d = ccpf2->BacktrackClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail4; + + for ( n = 0; n < count; n++ ) + { + b[n] = GET_UShort(); + + /* We check whether the specific class is used at all. If not, + class 0 is used instead. */ + + if ( !d[b[n]] ) + b[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + cpcr->InputGlyphCount = GET_UShort(); + + if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength ) + ccpf2->MaxInputLength = cpcr->InputGlyphCount; + + FORGET_Frame(); + + cpcr->Input = NULL; + + count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( cpcr->Input, count, UShort ) ) + goto Fail4; + + i = cpcr->Input; + d = ccpf2->InputClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail3; + + for ( n = 0; n < count; n++ ) + { + i[n] = GET_UShort(); + + if ( !d[i[n]] ) + i[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + cpcr->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength ) + ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount; + + cpcr->Lookahead = NULL; + + count = cpcr->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( cpcr->Lookahead, count, UShort ) ) + goto Fail3; + + l = cpcr->Lookahead; + d = ccpf2->LookaheadClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + { + l[n] = GET_UShort(); + + if ( !d[l[n]] ) + l[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + cpcr->PosCount = GET_UShort(); + + FORGET_Frame(); + + cpcr->PosLookupRecord = NULL; + + count = cpcr->PosCount; + + if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = cpcr->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + FREE( l ); + + Fail3: + FREE( i ); + + Fail4: + FREE( b ); + return error; + } + + + static void Free_ChainPosClassRule( TTO_ChainPosClassRule* cpcr ) + { + FREE( cpcr->PosLookupRecord ); + FREE( cpcr->Lookahead ); + FREE( cpcr->Input ); + FREE( cpcr->Backtrack ); + } + + + /* PosClassSet */ + + static TT_Error Load_ChainPosClassSet( + TTO_ChainContextPosFormat2* ccpf2, + TTO_ChainPosClassSet* cpcs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainPosClassRule* cpcr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cpcs->ChainPosClassRuleCount = GET_UShort(); + + FORGET_Frame(); + + cpcs->ChainPosClassRule = NULL; + + if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count, + TTO_ChainPosClassRule ) ) + return error; + + cpcr = cpcs->ChainPosClassRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n], + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_ChainPosClassRule( &cpcr[n] ); + + FREE( cpcr ); + return error; + } + + + static void Free_ChainPosClassSet( TTO_ChainPosClassSet* cpcs ) + { + UShort n, count; + + TTO_ChainPosClassRule* cpcr; + + + if ( cpcs->ChainPosClassRule ) + { + count = cpcs->ChainPosClassRuleCount; + cpcr = cpcs->ChainPosClassRule; + + for ( n = 0; n < count; n++ ) + Free_ChainPosClassRule( &cpcr[n] ); + + FREE( cpcr ); + } + } + + + /* ChainContextPosFormat2 */ + + static TT_Error Load_ChainContextPos2( TTO_ChainContextPosFormat2* ccpf2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + ULong backtrack_offset, input_offset, lookahead_offset; + + TTO_ChainPosClassSet* cpcs; + + + base_offset = FILE_Pos() - 2; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ccpf2->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 8L ) ) + goto Fail5; + + backtrack_offset = GET_UShort() + base_offset; + input_offset = GET_UShort() + base_offset; + lookahead_offset = GET_UShort() + base_offset; + + /* `ChainPosClassSetCount' is the upper limit for input class values, + thus we read it now to make an additional safety check. */ + + count = ccpf2->ChainPosClassSetCount = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( backtrack_offset ) || + ( error = Load_ClassDefinition( &ccpf2->BacktrackClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail5; + if ( FILE_Seek( input_offset ) || + ( error = Load_ClassDefinition( &ccpf2->InputClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail4; + if ( FILE_Seek( lookahead_offset ) || + ( error = Load_ClassDefinition( &ccpf2->LookaheadClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + ccpf2->ChainPosClassSet = NULL; + ccpf2->MaxBacktrackLength = 0; + ccpf2->MaxInputLength = 0; + ccpf2->MaxLookaheadLength = 0; + + if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, TTO_ChainPosClassSet ) ) + goto Fail2; + + cpcs = ccpf2->ChainPosClassSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + if ( new_offset != base_offset ) /* not a NULL offset */ + { + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n], + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + { + /* we create a ChainPosClassSet table with no entries */ + + ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0; + ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL; + } + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_ChainPosClassSet( &cpcs[n] ); + + FREE( cpcs ); + + Fail2: + Free_ClassDefinition( &ccpf2->LookaheadClassDef ); + + Fail3: + Free_ClassDefinition( &ccpf2->InputClassDef ); + + Fail4: + Free_ClassDefinition( &ccpf2->BacktrackClassDef ); + + Fail5: + Free_Coverage( &ccpf2->Coverage ); + return error; + } + + + static void Free_ChainContext2( TTO_ChainContextPosFormat2* ccpf2 ) + { + UShort n, count; + + TTO_ChainPosClassSet* cpcs; + + + if ( ccpf2->ChainPosClassSet ) + { + count = ccpf2->ChainPosClassSetCount; + cpcs = ccpf2->ChainPosClassSet; + + for ( n = 0; n < count; n++ ) + Free_ChainPosClassSet( &cpcs[n] ); + + FREE( cpcs ); + } + + Free_ClassDefinition( &ccpf2->LookaheadClassDef ); + Free_ClassDefinition( &ccpf2->InputClassDef ); + Free_ClassDefinition( &ccpf2->BacktrackClassDef ); + + Free_Coverage( &ccpf2->Coverage ); + } + + + /* ChainContextPosFormat3 */ + + static TT_Error Load_ChainContextPos3( TTO_ChainContextPosFormat3* ccpf3, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort backtrack_count, input_count, lookahead_count; + ULong cur_offset, new_offset, base_offset; + + TTO_Coverage* b; + TTO_Coverage* i; + TTO_Coverage* l; + TTO_PosLookupRecord* plr; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + ccpf3->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccpf3->BacktrackCoverage = NULL; + + backtrack_count = ccpf3->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count, + TTO_Coverage ) ) + return error; + + b = ccpf3->BacktrackCoverage; + + for ( n = 0; n < backtrack_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &b[n], input ) ) != TT_Err_Ok ) + goto Fail4; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + ccpf3->InputGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccpf3->InputCoverage = NULL; + + input_count = ccpf3->InputGlyphCount; + + if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, TTO_Coverage ) ) + goto Fail4; + + i = ccpf3->InputCoverage; + + for ( n = 0; n < input_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &i[n], input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + ccpf3->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccpf3->LookaheadCoverage = NULL; + + lookahead_count = ccpf3->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count, + TTO_Coverage ) ) + goto Fail3; + + l = ccpf3->LookaheadCoverage; + + for ( n = 0; n < lookahead_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &l[n], input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + ccpf3->PosCount = GET_UShort(); + + FORGET_Frame(); + + ccpf3->PosLookupRecord = NULL; + + count = ccpf3->PosCount; + + if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, TTO_PosLookupRecord ) ) + goto Fail2; + + plr = ccpf3->PosLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + plr[n].SequenceIndex = GET_UShort(); + plr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( plr ); + + Fail2: + for ( n = 0; n < lookahead_count; n++ ) + Free_Coverage( &l[n] ); + + FREE( l ); + + Fail3: + for ( n = 0; n < input_count; n++ ) + Free_Coverage( &i[n] ); + + FREE( i ); + + Fail4: + for ( n = 0; n < backtrack_count; n++ ) + Free_Coverage( &b[n] ); + + FREE( b ); + return error; + } + + + static void Free_ChainContext3( TTO_ChainContextPosFormat3* ccpf3 ) + { + UShort n, count; + + TTO_Coverage* c; + + + FREE( ccpf3->PosLookupRecord ); + + if ( ccpf3->LookaheadCoverage ) + { + count = ccpf3->LookaheadGlyphCount; + c = ccpf3->LookaheadCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + + if ( ccpf3->InputCoverage ) + { + count = ccpf3->InputGlyphCount; + c = ccpf3->InputCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + + if ( ccpf3->BacktrackCoverage ) + { + count = ccpf3->BacktrackGlyphCount; + c = ccpf3->BacktrackCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + } + + + /* ChainContextPos */ + + TT_Error Load_ChainContextPos( TTO_ChainContextPos* ccp, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ACCESS_Frame( 2L ) ) + return error; + + ccp->PosFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( ccp->PosFormat ) + { + case 1: + return Load_ChainContextPos1( &ccp->ccpf.ccpf1, input ); + + case 2: + return Load_ChainContextPos2( &ccp->ccpf.ccpf2, input ); + + case 3: + return Load_ChainContextPos3( &ccp->ccpf.ccpf3, input ); + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + void Free_ChainContextPos( TTO_ChainContextPos* ccp ) + { + switch ( ccp->PosFormat ) + { + case 1: + Free_ChainContext1( &ccp->ccpf.ccpf1 ); + break; + + case 2: + Free_ChainContext2( &ccp->ccpf.ccpf2 ); + break; + + case 3: + Free_ChainContext3( &ccp->ccpf.ccpf3 ); + break; + } + } + + + static TT_Error Lookup_ChainContextPos1( + GPOS_Instance* gpi, + TTO_ChainContextPosFormat1* ccpf1, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + UShort i, j, k, num_cpr, curr_pos; + UShort bgc, igc, lgc; + TT_Error error; + UShort* s_in; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_ChainPosRule* cpr; + TTO_ChainPosRule curr_cpr; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &ccpf1->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule; + num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount; + + for ( k = 0; k < num_cpr; k++ ) + { + curr_cpr = cpr[k]; + bgc = curr_cpr.BacktrackGlyphCount; + igc = curr_cpr.InputGlyphCount; + lgc = curr_cpr.LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + continue; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + continue; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + + for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + break; + } + + if ( s_in[j] != curr_cpr.Backtrack[i - 1] ) + break; + } + + if ( i != 0 ) + continue; + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != curr_cpr.Input[i - 1] ) + break; + } + + if ( i != igc ) + continue; + + /* we are starting to check for lookahead glyphs right after the + last context glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != curr_cpr.Lookahead[i] ) + break; + } + + if ( i == lgc ) + return Do_ContextPos( gpi, igc, + curr_cpr.PosCount, + curr_cpr.PosLookupRecord, + in, out, + nesting_level ); + } + + return TTO_Err_Not_Covered; + } + + + static TT_Error Lookup_ChainContextPos2( + GPOS_Instance* gpi, + TTO_ChainContextPosFormat2* ccpf2, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + TT_Error error; + UShort i, j, k, curr_pos; + UShort bgc, igc, lgc; + UShort known_backtrack_classes, + known_input_classes, + known_lookahead_classes; + + UShort* backtrack_classes; + UShort* input_classes; + UShort* lookahead_classes; + + UShort* s_in; + + UShort* bc; + UShort* ic; + UShort* lc; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_ChainPosClassSet* cpcs; + TTO_ChainPosClassRule cpcr; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + /* Note: The coverage table in format 2 doesn't give an index into + anything. It just lets us know whether or not we need to + do any lookup at all. */ + + error = Coverage_Index( &ccpf2->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, UShort ) ) + return error; + known_backtrack_classes = 0; + + if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, UShort ) ) + goto End3; + known_input_classes = 1; + + if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, UShort ) ) + goto End2; + known_lookahead_classes = 0; + + error = Get_Class( &ccpf2->InputClassDef, in->string[in->pos], + &input_classes[0], NULL ); + if ( error ) + goto End1; + + cpcs = &ccpf2->ChainPosClassSet[input_classes[0]]; + if ( !cpcs ) + { + error = TTO_Err_Invalid_GPOS_SubTable; + goto End1; + } + + for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ ) + { + cpcr = cpcs->ChainPosClassRule[k]; + bgc = cpcr.BacktrackGlyphCount; + igc = cpcr.InputGlyphCount; + lgc = cpcr.LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + continue; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + continue; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array. + Note that `known_backtrack_classes' starts at index 0. */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + bc = cpcr.Backtrack; + + for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + break; + } + + if ( i >= known_backtrack_classes ) + { + /* Keeps us from having to do this for each rule */ + + error = Get_Class( &ccpf2->BacktrackClassDef, s_in[j], + &backtrack_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_backtrack_classes = i; + } + + if ( bc[bgc - 1 - i] != backtrack_classes[i] ) + break; + } + + if ( i != bgc ) + continue; + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + ic = cpcr.Input; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( i >= known_input_classes ) + { + error = Get_Class( &ccpf2->InputClassDef, s_in[j], + &input_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_input_classes = i; + } + + if ( ic[i - 1] != input_classes[i] ) + break; + } + + if ( i != igc ) + continue; + + /* we are starting to check for lookahead glyphs right after the + last context glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + lc = cpcr.Lookahead; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( i >= known_lookahead_classes ) + { + error = Get_Class( &ccpf2->LookaheadClassDef, s_in[j], + &lookahead_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_lookahead_classes = i; + } + + if ( lc[i] != lookahead_classes[i] ) + break; + } + + if ( i == lgc ) + { + error = Do_ContextPos( gpi, igc, + cpcr.PosCount, + cpcr.PosLookupRecord, + in, out, + nesting_level ); + goto End1; + } + } + + error = TTO_Err_Not_Covered; + + End1: + FREE( lookahead_classes ); + + End2: + FREE( input_classes ); + + End3: + FREE( backtrack_classes ); + return error; + } + + + static TT_Error Lookup_ChainContextPos3( + GPOS_Instance* gpi, + TTO_ChainContextPosFormat3* ccpf3, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, i, j, curr_pos, property; + UShort bgc, igc, lgc; + TT_Error error; + UShort* s_in; + TTO_GPOSHeader* gpos = gpi->gpos; + + TTO_Coverage* bc; + TTO_Coverage* ic; + TTO_Coverage* lc; + TTO_GDEFHeader* gdef; + + + gdef = gpos->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + bgc = ccpf3->BacktrackGlyphCount; + igc = ccpf3->InputGlyphCount; + lgc = ccpf3->LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + return TTO_Err_Not_Covered; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + return TTO_Err_Not_Covered; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + bc = ccpf3->BacktrackCoverage; + + for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &bc[i - 1], s_in[j], &index ); + if ( error ) + return error; + } + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + ic = ccpf3->InputCoverage; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &ic[i], s_in[j], &index ); + if ( error ) + return error; + } + + /* we are starting for lookahead glyphs right after the last context + glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + lc = ccpf3->LookaheadCoverage; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &lc[i], s_in[j], &index ); + if ( error ) + return error; + } + + return Do_ContextPos( gpi, igc, + ccpf3->PosCount, + ccpf3->PosLookupRecord, + in, out, + nesting_level ); + } + + + static TT_Error Lookup_ChainContextPos( + GPOS_Instance* gpi, + TTO_ChainContextPos* ccp, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + switch ( ccp->PosFormat ) + { + case 1: + return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, in, out, + flags, context_length, + nesting_level ); + + case 2: + return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, in, out, + flags, context_length, + nesting_level ); + + case 3: + return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, in, out, + flags, context_length, + nesting_level ); + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + + /*********** + * GPOS API + ***********/ + + + EXPORT_FUNC + TT_Error TT_GPOS_Select_Script( TTO_GPOSHeader* gpos, + TT_ULong script_tag, + TT_UShort* script_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + + + if ( !gpos || !script_index ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + for ( n = 0; n < sl->ScriptCount; n++ ) + if ( script_tag == sr[n].ScriptTag ) + { + *script_index = n; + + return TT_Err_Ok; + } + + return TTO_Err_Not_Covered; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Select_Language( TTO_GPOSHeader* gpos, + TT_ULong language_tag, + TT_UShort script_index, + TT_UShort* language_index, + TT_UShort* req_feature_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + + + if ( !gpos || !language_index || !req_feature_index ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + for ( n = 0; n < s->LangSysCount; n++ ) + if ( language_tag == lsr[n].LangSysTag ) + { + *language_index = n; + *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; + + return TT_Err_Ok; + } + + return TTO_Err_Not_Covered; + } + + + /* selecting 0xFFFF for language_index asks for the values of the + default language (DefaultLangSys) */ + + EXPORT_FUNC + TT_Error TT_GPOS_Select_Feature( TTO_GPOSHeader* gpos, + TT_ULong feature_tag, + TT_UShort script_index, + TT_UShort language_index, + TT_UShort* feature_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + TTO_LangSys* ls; + UShort* fi; + + TTO_FeatureList* fl; + TTO_FeatureRecord* fr; + + + if ( !gpos || !feature_index ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + fl = &gpos->FeatureList; + fr = fl->FeatureRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( language_index == 0xFFFF ) + ls = &s->DefaultLangSys; + else + { + if ( language_index >= s->LangSysCount ) + return TT_Err_Invalid_Argument; + + ls = &lsr[language_index].LangSys; + } + + fi = ls->FeatureIndex; + + for ( n = 0; n < ls->FeatureCount; n++ ) + { + if ( fi[n] >= fl->FeatureCount ) + return TTO_Err_Invalid_GPOS_SubTable_Format; + + if ( feature_tag == fr[fi[n]].FeatureTag ) + { + *feature_index = fi[n]; + + return TT_Err_Ok; + } + } + + return TTO_Err_Not_Covered; + } + + + /* The next three functions return a null-terminated list */ + + EXPORT_FUNC + TT_Error TT_GPOS_Query_Scripts( TTO_GPOSHeader* gpos, + TT_ULong** script_tag_list ) + { + UShort n; + TT_Error error; + ULong* stl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + + + if ( !gpos || !script_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, ULong ) ) + return error; + + for ( n = 0; n < sl->ScriptCount; n++ ) + stl[n] = sr[n].ScriptTag; + stl[n] = 0; + + *script_tag_list = stl; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Query_Languages( TTO_GPOSHeader* gpos, + TT_UShort script_index, + TT_ULong** language_tag_list ) + { + UShort n; + TT_Error error; + ULong* ltl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + + + if ( !gpos || !language_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, ULong ) ) + return error; + + for ( n = 0; n < s->LangSysCount; n++ ) + ltl[n] = lsr[n].LangSysTag; + ltl[n] = 0; + + *language_tag_list = ltl; + + return TT_Err_Ok; + } + + + /* selecting 0xFFFF for language_index asks for the values of the + default language (DefaultLangSys) */ + + EXPORT_FUNC + TT_Error TT_GPOS_Query_Features( TTO_GPOSHeader* gpos, + TT_UShort script_index, + TT_UShort language_index, + TT_ULong** feature_tag_list ) + { + UShort n; + TT_Error error; + ULong* ftl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + TTO_LangSys* ls; + UShort* fi; + + TTO_FeatureList* fl; + TTO_FeatureRecord* fr; + + + if ( !gpos || !feature_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gpos->ScriptList; + sr = sl->ScriptRecord; + + fl = &gpos->FeatureList; + fr = fl->FeatureRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( language_index == 0xFFFF ) + ls = &s->DefaultLangSys; + else + { + if ( language_index >= s->LangSysCount ) + return TT_Err_Invalid_Argument; + + ls = &lsr[language_index].LangSys; + } + + fi = ls->FeatureIndex; + + if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, ULong ) ) + return error; + + for ( n = 0; n < ls->FeatureCount; n++ ) + { + if ( fi[n] >= fl->FeatureCount ) + { + FREE( ftl ); + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + ftl[n] = fr[fi[n]].FeatureTag; + } + ftl[n] = 0; + + *feature_tag_list = ftl; + + return TT_Err_Ok; + } + + + /* Do an individual subtable lookup. Returns TT_Err_Ok if positioning + has been done, or TTO_Err_Not_Covered if not. */ + + static TT_Error Do_Glyph_Lookup( GPOS_Instance* gpi, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GPOS_Data* out, + UShort context_length, + int nesting_level ) + { + TT_Error error = TT_Err_Ok; + UShort i, flags; + TTO_GPOSHeader* gpos = gpi->gpos; + TTO_Lookup* lo; + + + nesting_level++; + + if ( nesting_level > TTO_MAX_NESTING_LEVEL ) + return TTO_Err_Too_Many_Nested_Contexts; + + lo = &gpos->LookupList.Lookup[lookup_index]; + flags = lo->LookupFlag; + + for ( i = 0; i < lo->SubTableCount; i++ ) + { + switch ( lo->LookupType ) + { + case GPOS_LOOKUP_SINGLE: + error = Lookup_SinglePos( gpi, + &lo->SubTable[i].st.gpos.single, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_PAIR: + error = Lookup_PairPos( gpi, + &lo->SubTable[i].st.gpos.pair, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_CURSIVE: + error = Lookup_CursivePos( gpi, + &lo->SubTable[i].st.gpos.cursive, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_MARKBASE: + error = Lookup_MarkBasePos( gpi, + &lo->SubTable[i].st.gpos.markbase, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_MARKLIG: + error = Lookup_MarkLigPos( gpi, + &lo->SubTable[i].st.gpos.marklig, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_MARKMARK: + error = Lookup_MarkMarkPos( gpi, + &lo->SubTable[i].st.gpos.markmark, + in, out, + flags, context_length ); + break; + + case GPOS_LOOKUP_CONTEXT: + error = Lookup_ContextPos( gpi, + &lo->SubTable[i].st.gpos.context, + in, out, + flags, context_length, + nesting_level ); + break; + + case GPOS_LOOKUP_CHAIN: + error = Lookup_ChainContextPos( gpi, + &lo->SubTable[i].st.gpos.chain, + in, out, + flags, context_length, + nesting_level ); + break; + } + + /* Check whether we have a successful positioning or an error other + than TTO_Err_Not_Covered */ + + if ( error != TTO_Err_Not_Covered ) + return error; + } + + return TTO_Err_Not_Covered; + } + + + /* apply one lookup to the input string object */ + + static TT_Error Do_String_Lookup( GPOS_Instance* gpi, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GPOS_Data* out ) + { + TT_Error error = TTO_Err_Not_Covered; + TTO_GPOSHeader* gpos = gpi->gpos; + + UShort* properties = gpos->LookupList.Properties; + UShort* p_in = in->properties; + + int nesting_level = 0; + + + gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */ + + in->pos = 0; + + while ( in->pos < in->length ) + { + if ( ~p_in[in->pos] & properties[lookup_index] ) + { + /* 0xFFFF indicates that we don't have a context length yet. */ + + /* Note that the connection between mark and base glyphs hold + exactly one (string) lookup. For example, it would be possible + that in the first lookup, mark glyph X is attached to base + glyph A, and in the next lookup it is attached to base glyph B. + It is up to the font designer to provide meaningful lookups and + lookup order. */ + + error = Do_Glyph_Lookup( gpi, lookup_index, in, out, + 0xFFFF, nesting_level ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + else + { + /* Contrary to properties defined in GDEF, user-defined properties + will always stop a possible cursive positioning. */ + gpi->last = 0xFFFF; + + error = TTO_Err_Not_Covered; + } + + if ( error == TTO_Err_Not_Covered ) + (in->pos)++; + } + + return error; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos, + TT_UShort feature_index, + TT_UShort property ) + { + UShort i; + + TTO_Feature feature; + UShort* properties; + UShort* index; + + + if ( !gpos || + feature_index >= gpos->FeatureList.FeatureCount ) + return TT_Err_Invalid_Argument; + + properties = gpos->LookupList.Properties; + + feature = gpos->FeatureList.FeatureRecord[feature_index].Feature; + index = feature.LookupListIndex; + + for ( i = 0; i < feature.LookupListCount; i++ ) + properties[index[i]] |= property; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Clear_Features( TTO_GPOSHeader* gpos ) + { + UShort i; + + UShort* properties; + + + if ( !gpos ) + return TT_Err_Invalid_Argument; + + properties = gpos->LookupList.Properties; + + for ( i = 0; i < gpos->LookupList.LookupCount; i++ ) + properties[i] = 0; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Register_Glyph_Function( TTO_GPOSHeader* gpos, + TTO_GlyphFunction gfunc ) + { + if ( !gpos ) + return TT_Err_Invalid_Argument; + + gpos->gfunc = gfunc; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GPOS_Register_MM_Function( TTO_GPOSHeader* gpos, + TTO_MMFunction mmfunc, + void* data ) + { + if ( !gpos ) + return TT_Err_Invalid_Argument; + + gpos->mmfunc = mmfunc; + gpos->data = data; + + return TT_Err_Ok; + } + + + /* If `dvi' is TRUE, glyph contour points for anchor points and device + tables are ignored -- you will get device independent values. */ + + EXPORT_FUNC + TT_Error TT_GPOS_Apply_String( TT_Instance instance, + TT_Glyph glyph, + TTO_GPOSHeader* gpos, + TT_UShort load_flags, + TTO_GSUB_String* in, + TTO_GPOS_Data** out, + TT_Bool dvi, + TT_Bool r2l ) + { + TT_Error error = TTO_Err_Not_Covered; + GPOS_Instance gpi; + + UShort j; + + UShort* properties; + + + if ( !instance.z || !gpos || + !in || in->length == 0 || in->pos >= in->length ) + return TT_Err_Invalid_Argument; + + properties = gpos->LookupList.Properties; + + gpi.instance = instance; + if ( dvi ) + gpi.glyph.z = NULL; + else + gpi.glyph = glyph; + gpi.gpos = gpos; + gpi.load_flags = load_flags; + gpi.r2l = r2l; + + if ( *out ) + FREE( *out ); + if ( ALLOC_ARRAY( *out, in->length, TTO_GPOS_Data ) ) + return error; + + for ( j = 0; j < gpos->LookupList.LookupCount; j++ ) + if ( !properties || properties[j] ) + { + error = Do_String_Lookup( &gpi, j, in, *out ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgpos.h b/Build/source/libs/libttf/extend/ftxgpos.h new file mode 100644 index 00000000000..af7ab39f2df --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgpos.h @@ -0,0 +1,857 @@ +/******************************************************************* + * + * ftxgpos.h + * + * TrueType Open GPOS table support + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FTXOPEN_H +#error "Don't include this file! Use ftxopen.h instead." +#endif + +#ifndef FTXGPOS_H +#define FTXGPOS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TTO_Err_Invalid_GPOS_SubTable_Format 0x1020 +#define TTO_Err_Invalid_GPOS_SubTable 0x1021 + + +/* Lookup types for glyph positioning */ + +#define GPOS_LOOKUP_SINGLE 1 +#define GPOS_LOOKUP_PAIR 2 +#define GPOS_LOOKUP_CURSIVE 3 +#define GPOS_LOOKUP_MARKBASE 4 +#define GPOS_LOOKUP_MARKLIG 5 +#define GPOS_LOOKUP_MARKMARK 6 +#define GPOS_LOOKUP_CONTEXT 7 +#define GPOS_LOOKUP_CHAIN 8 + + + /* A pointer to a function which loads a glyph. Its parameters are + the same as in a call to TT_Load_Glyph() -- if no glyph loading + function will be registered with TTO_GPOS_Register_Glyph_Function(), + TT_Load_Glyph() will be called indeed. The purpose of this function + pointer is to provide a hook for caching glyph outlines and sbits + (using the instance's generic pointer to hold the data). + + If for some reason no outline data is available (e.g. for an + embedded bitmap glyph), _glyph->outline.n_points should be set to + zero. _glyph can be computed with + + _glyph = HANDLE_Glyph( glyph ) */ + + typedef TT_Error (*TTO_GlyphFunction)(TT_Instance instance, + TT_Glyph glyph, + TT_UShort glyphIndex, + TT_UShort loadFlags ); + + + /* A pointer to a function which accesses the PostScript interpreter. + Multiple Master fonts need this interface to convert a metric ID + (as stored in an OpenType font version 1.2 or higher) `metric_id' + into a metric value (returned in `metric_value'). + + `data' points to the user-defined structure specified during a + call to TT_GPOS_Register_MM_Function(). + + `metric_value' must be returned as a scaled value (but shouldn't + be rounded). */ + + typedef TT_Error (*TTO_MMFunction)(TT_Instance instance, + TT_UShort metric_id, + TT_Pos* metric_value, + void* data ); + + + struct TTO_GPOSHeader_ + { + TT_Bool loaded; + TT_ULong offset; + + TT_Fixed Version; + + TTO_ScriptList ScriptList; + TTO_FeatureList FeatureList; + TTO_LookupList LookupList; + + TTO_GDEFHeader* gdef; + + /* the next field is used for a callback function to get the + glyph outline. */ + + TTO_GlyphFunction gfunc; + + /* this is OpenType 1.2 -- Multiple Master fonts need this + callback function to get various metric values from the + PostScript interpreter. */ + + TTO_MMFunction mmfunc; + void* data; + }; + + typedef struct TTO_GPOSHeader_ TTO_GPOSHeader; + + + /* shared tables */ + + struct TTO_ValueRecord_ + { + TT_Short XPlacement; /* horizontal adjustment for + placement */ + TT_Short YPlacement; /* vertical adjustment for + placement */ + TT_Short XAdvance; /* horizontal adjustment for + advance */ + TT_Short YAdvance; /* vertical adjustment for + advance */ + TTO_Device XPlacementDevice; /* device table for horizontal + placement */ + TTO_Device YPlacementDevice; /* device table for vertical + placement */ + TTO_Device XAdvanceDevice; /* device table for horizontal + advance */ + TTO_Device YAdvanceDevice; /* device table for vertical + advance */ + TT_UShort XIdPlacement; /* horizontal placement metric ID */ + TT_UShort YIdPlacement; /* vertical placement metric ID */ + TT_UShort XIdAdvance; /* horizontal advance metric ID */ + TT_UShort YIdAdvance; /* vertical advance metric ID */ + }; + + typedef struct TTO_ValueRecord_ TTO_ValueRecord; + + +/* Mask values to scan the value format of the ValueRecord structure. + We always expand compressed ValueRecords of the font. */ + +#define HAVE_X_PLACEMENT 0x0001 +#define HAVE_Y_PLACEMENT 0x0002 +#define HAVE_X_ADVANCE 0x0004 +#define HAVE_Y_ADVANCE 0x0008 +#define HAVE_X_PLACEMENT_DEVICE 0x0010 +#define HAVE_Y_PLACEMENT_DEVICE 0x0020 +#define HAVE_X_ADVANCE_DEVICE 0x0040 +#define HAVE_Y_ADVANCE_DEVICE 0x0080 +#define HAVE_X_ID_PLACEMENT 0x0100 +#define HAVE_Y_ID_PLACEMENT 0x0200 +#define HAVE_X_ID_ADVANCE 0x0400 +#define HAVE_Y_ID_ADVANCE 0x0800 + + + struct TTO_AnchorFormat1_ + { + TT_Short XCoordinate; /* horizontal value */ + TT_Short YCoordinate; /* vertical value */ + }; + + typedef struct TTO_AnchorFormat1_ TTO_AnchorFormat1; + + + struct TTO_AnchorFormat2_ + { + TT_Short XCoordinate; /* horizontal value */ + TT_Short YCoordinate; /* vertical value */ + TT_UShort AnchorPoint; /* index to glyph contour point */ + }; + + typedef struct TTO_AnchorFormat2_ TTO_AnchorFormat2; + + + struct TTO_AnchorFormat3_ + { + TT_Short XCoordinate; /* horizontal value */ + TT_Short YCoordinate; /* vertical value */ + TTO_Device XDeviceTable; /* device table for X coordinate */ + TTO_Device YDeviceTable; /* device table for Y coordinate */ + }; + + typedef struct TTO_AnchorFormat3_ TTO_AnchorFormat3; + + + struct TTO_AnchorFormat4_ + { + TT_UShort XIdAnchor; /* horizontal metric ID */ + TT_UShort YIdAnchor; /* vertical metric ID */ + }; + + typedef struct TTO_AnchorFormat4_ TTO_AnchorFormat4; + + + struct TTO_Anchor_ + { + TT_UShort PosFormat; /* 1, 2, 3, or 4 -- 0 indicates + that there is no Anchor table */ + + union + { + TTO_AnchorFormat1 af1; + TTO_AnchorFormat2 af2; + TTO_AnchorFormat3 af3; + TTO_AnchorFormat4 af4; + } af; + }; + + typedef struct TTO_Anchor_ TTO_Anchor; + + + struct TTO_MarkRecord_ + { + TT_UShort Class; /* mark class */ + TTO_Anchor MarkAnchor; /* anchor table */ + }; + + typedef struct TTO_MarkRecord_ TTO_MarkRecord; + + + struct TTO_MarkArray_ + { + TT_UShort MarkCount; /* number of MarkRecord tables */ + TTO_MarkRecord* MarkRecord; /* array of MarkRecord tables */ + }; + + typedef struct TTO_MarkArray_ TTO_MarkArray; + + + /* LookupType 1 */ + + struct TTO_SinglePosFormat1_ + { + TTO_ValueRecord Value; /* ValueRecord for all covered + glyphs */ + }; + + typedef struct TTO_SinglePosFormat1_ TTO_SinglePosFormat1; + + + struct TTO_SinglePosFormat2_ + { + TT_UShort ValueCount; /* number of ValueRecord tables */ + TTO_ValueRecord* Value; /* array of ValueRecord tables */ + }; + + typedef struct TTO_SinglePosFormat2_ TTO_SinglePosFormat2; + + + struct TTO_SinglePos_ + { + TT_UShort PosFormat; /* 1 or 2 */ + TTO_Coverage Coverage; /* Coverage table */ + + TT_UShort ValueFormat; /* format of ValueRecord table */ + + union + { + TTO_SinglePosFormat1 spf1; + TTO_SinglePosFormat2 spf2; + } spf; + }; + + typedef struct TTO_SinglePos_ TTO_SinglePos; + + + /* LookupType 2 */ + + struct TTO_PairValueRecord_ + { + TT_UShort SecondGlyph; /* glyph ID for second glyph */ + TTO_ValueRecord Value1; /* pos. data for first glyph */ + TTO_ValueRecord Value2; /* pos. data for second glyph */ + }; + + typedef struct TTO_PairValueRecord_ TTO_PairValueRecord; + + + struct TTO_PairSet_ + { + TT_UShort PairValueCount; + /* number of PairValueRecord tables */ + TTO_PairValueRecord* PairValueRecord; + /* array of PairValueRecord tables */ + }; + + typedef struct TTO_PairSet_ TTO_PairSet; + + + struct TTO_PairPosFormat1_ + { + TT_UShort PairSetCount; /* number of PairSet tables */ + TTO_PairSet* PairSet; /* array of PairSet tables */ + }; + + typedef struct TTO_PairPosFormat1_ TTO_PairPosFormat1; + + + struct TTO_Class2Record_ + { + TTO_ValueRecord Value1; /* pos. data for first glyph */ + TTO_ValueRecord Value2; /* pos. data for second glyph */ + }; + + typedef struct TTO_Class2Record_ TTO_Class2Record; + + + struct TTO_Class1Record_ + { + TTO_Class2Record* Class2Record; /* array of Class2Record tables */ + }; + + typedef struct TTO_Class1Record_ TTO_Class1Record; + + + struct TTO_PairPosFormat2_ + { + TTO_ClassDefinition ClassDef1; /* class def. for first glyph */ + TTO_ClassDefinition ClassDef2; /* class def. for second glyph */ + TT_UShort Class1Count; /* number of classes in ClassDef1 + table */ + TT_UShort Class2Count; /* number of classes in ClassDef2 + table */ + TTO_Class1Record* Class1Record; /* array of Class1Record tables */ + }; + + typedef struct TTO_PairPosFormat2_ TTO_PairPosFormat2; + + + struct TTO_PairPos_ + { + TT_UShort PosFormat; /* 1 or 2 */ + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort ValueFormat1; /* format of ValueRecord table + for first glyph */ + TT_UShort ValueFormat2; /* format of ValueRecord table + for second glyph */ + + union + { + TTO_PairPosFormat1 ppf1; + TTO_PairPosFormat2 ppf2; + } ppf; + }; + + typedef struct TTO_PairPos_ TTO_PairPos; + + + /* LookupType 3 */ + + struct TTO_EntryExitRecord_ + { + TTO_Anchor EntryAnchor; /* entry Anchor table */ + TTO_Anchor ExitAnchor; /* exit Anchor table */ + }; + + + typedef struct TTO_EntryExitRecord_ TTO_EntryExitRecord; + + struct TTO_CursivePos_ + { + TT_UShort PosFormat; /* always 1 */ + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort EntryExitCount; + /* number of EntryExitRecord tables */ + TTO_EntryExitRecord* EntryExitRecord; + /* array of EntryExitRecord tables */ + }; + + typedef struct TTO_CursivePos_ TTO_CursivePos; + + + /* LookupType 4 */ + + struct TTO_BaseRecord_ + { + TTO_Anchor* BaseAnchor; /* array of base glyph anchor + tables */ + }; + + typedef struct TTO_BaseRecord_ TTO_BaseRecord; + + + struct TTO_BaseArray_ + { + TT_UShort BaseCount; /* number of BaseRecord tables */ + TTO_BaseRecord* BaseRecord; /* array of BaseRecord tables */ + }; + + typedef struct TTO_BaseArray_ TTO_BaseArray; + + + struct TTO_MarkBasePos_ + { + TT_UShort PosFormat; /* always 1 */ + TTO_Coverage MarkCoverage; /* mark glyph coverage table */ + TTO_Coverage BaseCoverage; /* base glyph coverage table */ + TT_UShort ClassCount; /* number of mark classes */ + TTO_MarkArray MarkArray; /* mark array table */ + TTO_BaseArray BaseArray; /* base array table */ + }; + + typedef struct TTO_MarkBasePos_ TTO_MarkBasePos; + + + /* LookupType 5 */ + + struct TTO_ComponentRecord_ + { + TTO_Anchor* LigatureAnchor; /* array of ligature glyph anchor + tables */ + }; + + typedef struct TTO_ComponentRecord_ TTO_ComponentRecord; + + + struct TTO_LigatureAttach_ + { + TT_UShort ComponentCount; + /* number of ComponentRecord tables */ + TTO_ComponentRecord* ComponentRecord; + /* array of ComponentRecord tables */ + }; + + typedef struct TTO_LigatureAttach_ TTO_LigatureAttach; + + + struct TTO_LigatureArray_ + { + TT_UShort LigatureCount; /* number of LigatureAttach tables */ + TTO_LigatureAttach* LigatureAttach; + /* array of LigatureAttach tables */ + }; + + typedef struct TTO_LigatureArray_ TTO_LigatureArray; + + + struct TTO_MarkLigPos_ + { + TT_UShort PosFormat; /* always 1 */ + TTO_Coverage MarkCoverage; /* mark glyph coverage table */ + TTO_Coverage LigatureCoverage; + /* ligature glyph coverage table */ + TT_UShort ClassCount; /* number of mark classes */ + TTO_MarkArray MarkArray; /* mark array table */ + TTO_LigatureArray LigatureArray; /* ligature array table */ + }; + + typedef struct TTO_MarkLigPos_ TTO_MarkLigPos; + + + /* LookupType 6 */ + + struct TTO_Mark2Record_ + { + TTO_Anchor* Mark2Anchor; /* array of mark glyph anchor + tables */ + }; + + typedef struct TTO_Mark2Record_ TTO_Mark2Record; + + + struct TTO_Mark2Array_ + { + TT_UShort Mark2Count; /* number of Mark2Record tables */ + TTO_Mark2Record* Mark2Record; /* array of Mark2Record tables */ + }; + + typedef struct TTO_Mark2Array_ TTO_Mark2Array; + + + struct TTO_MarkMarkPos_ + { + TT_UShort PosFormat; /* always 1 */ + TTO_Coverage Mark1Coverage; /* first mark glyph coverage table */ + TTO_Coverage Mark2Coverage; /* second mark glyph coverave table */ + TT_UShort ClassCount; /* number of combining mark classes */ + TTO_MarkArray Mark1Array; /* MarkArray table for first mark */ + TTO_Mark2Array Mark2Array; /* MarkArray table for second mark */ + }; + + typedef struct TTO_MarkMarkPos_ TTO_MarkMarkPos; + + + /* needed by both lookup type 7 and 8 */ + + struct TTO_PosLookupRecord_ + { + TT_UShort SequenceIndex; /* index into current + glyph sequence */ + TT_UShort LookupListIndex; /* Lookup to apply to that pos. */ + }; + + typedef struct TTO_PosLookupRecord_ TTO_PosLookupRecord; + + + /* LookupType 7 */ + + struct TTO_PosRule_ + { + TT_UShort GlyphCount; /* total number of input glyphs */ + TT_UShort PosCount; /* number of PosLookupRecord tables */ + TT_UShort* Input; /* array of input glyph IDs */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of PosLookupRecord tables */ + }; + + typedef struct TTO_PosRule_ TTO_PosRule; + + + struct TTO_PosRuleSet_ + { + TT_UShort PosRuleCount; /* number of PosRule tables */ + TTO_PosRule* PosRule; /* array of PosRule tables */ + }; + + typedef struct TTO_PosRuleSet_ TTO_PosRuleSet; + + + struct TTO_ContextPosFormat1_ + { + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort PosRuleSetCount; /* number of PosRuleSet tables */ + TTO_PosRuleSet* PosRuleSet; /* array of PosRuleSet tables */ + }; + + typedef struct TTO_ContextPosFormat1_ TTO_ContextPosFormat1; + + + struct TTO_PosClassRule_ + { + TT_UShort GlyphCount; /* total number of context classes */ + TT_UShort PosCount; /* number of PosLookupRecord tables */ + TT_UShort* Class; /* array of classes */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of PosLookupRecord tables */ + }; + + typedef struct TTO_PosClassRule_ TTO_PosClassRule; + + + struct TTO_PosClassSet_ + { + TT_UShort PosClassRuleCount; + /* number of PosClassRule tables */ + TTO_PosClassRule* PosClassRule; /* array of PosClassRule tables */ + }; + + typedef struct TTO_PosClassSet_ TTO_PosClassSet; + + + /* The `MaxContextLength' field is not defined in the TTO specification + but simplifies the implementation of this format. It holds the + maximal context length used in the context rules. */ + + struct TTO_ContextPosFormat2_ + { + TT_UShort MaxContextLength; + /* maximal context length */ + TTO_Coverage Coverage; /* Coverage table */ + TTO_ClassDefinition ClassDef; /* ClassDef table */ + TT_UShort PosClassSetCount; + /* number of PosClassSet tables */ + TTO_PosClassSet* PosClassSet; /* array of PosClassSet tables */ + }; + + typedef struct TTO_ContextPosFormat2_ TTO_ContextPosFormat2; + + + struct TTO_ContextPosFormat3_ + { + TT_UShort GlyphCount; /* number of input glyphs */ + TT_UShort PosCount; /* number of PosLookupRecord tables */ + TTO_Coverage* Coverage; /* array of Coverage tables */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of PosLookupRecord tables */ + }; + + typedef struct TTO_ContextPosFormat3_ TTO_ContextPosFormat3; + + + struct TTO_ContextPos_ + { + TT_UShort PosFormat; /* 1, 2, or 3 */ + + union + { + TTO_ContextPosFormat1 cpf1; + TTO_ContextPosFormat2 cpf2; + TTO_ContextPosFormat3 cpf3; + } cpf; + }; + + typedef struct TTO_ContextPos_ TTO_ContextPos; + + + /* LookupType 8 */ + + struct TTO_ChainPosRule_ + { + TT_UShort BacktrackGlyphCount; + /* total number of backtrack glyphs */ + TT_UShort* Backtrack; /* array of backtrack glyph IDs */ + TT_UShort InputGlyphCount; + /* total number of input glyphs */ + TT_UShort* Input; /* array of input glyph IDs */ + TT_UShort LookaheadGlyphCount; + /* total number of lookahead glyphs */ + TT_UShort* Lookahead; /* array of lookahead glyph IDs */ + TT_UShort PosCount; /* number of PosLookupRecords */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of PosLookupRecords */ + }; + + typedef struct TTO_ChainPosRule_ TTO_ChainPosRule; + + + struct TTO_ChainPosRuleSet_ + { + TT_UShort ChainPosRuleCount; + /* number of ChainPosRule tables */ + TTO_ChainPosRule* ChainPosRule; /* array of ChainPosRule tables */ + }; + + typedef struct TTO_ChainPosRuleSet_ TTO_ChainPosRuleSet; + + + struct TTO_ChainContextPosFormat1_ + { + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort ChainPosRuleSetCount; + /* number of ChainPosRuleSet tables */ + TTO_ChainPosRuleSet* ChainPosRuleSet; + /* array of ChainPosRuleSet tables */ + }; + + typedef struct TTO_ChainContextPosFormat1_ TTO_ChainContextPosFormat1; + + + struct TTO_ChainPosClassRule_ + { + TT_UShort BacktrackGlyphCount; + /* total number of backtrack + classes */ + TT_UShort* Backtrack; /* array of backtrack classes */ + TT_UShort InputGlyphCount; + /* total number of context classes */ + TT_UShort* Input; /* array of context classes */ + TT_UShort LookaheadGlyphCount; + /* total number of lookahead + classes */ + TT_UShort* Lookahead; /* array of lookahead classes */ + TT_UShort PosCount; /* number of PosLookupRecords */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of substitution lookups */ + }; + + typedef struct TTO_ChainPosClassRule_ TTO_ChainPosClassRule; + + + struct TTO_ChainPosClassSet_ + { + TT_UShort ChainPosClassRuleCount; + /* number of ChainPosClassRule + tables */ + TTO_ChainPosClassRule* ChainPosClassRule; + /* array of ChainPosClassRule + tables */ + }; + + typedef struct TTO_ChainPosClassSet_ TTO_ChainPosClassSet; + + + /* The `MaxXXXLength' fields are not defined in the TTO specification + but simplifies the implementation of this format. It holds the + maximal context length used in the specific context rules. */ + + struct TTO_ChainContextPosFormat2_ + { + TTO_Coverage Coverage; /* Coverage table */ + + TT_UShort MaxBacktrackLength; + /* maximal backtrack length */ + TTO_ClassDefinition BacktrackClassDef; + /* BacktrackClassDef table */ + TT_UShort MaxInputLength; + /* maximal input length */ + TTO_ClassDefinition InputClassDef; + /* InputClassDef table */ + TT_UShort MaxLookaheadLength; + /* maximal lookahead length */ + TTO_ClassDefinition LookaheadClassDef; + /* LookaheadClassDef table */ + + TT_UShort ChainPosClassSetCount; + /* number of ChainPosClassSet + tables */ + TTO_ChainPosClassSet* ChainPosClassSet; + /* array of ChainPosClassSet + tables */ + }; + + typedef struct TTO_ChainContextPosFormat2_ TTO_ChainContextPosFormat2; + + + struct TTO_ChainContextPosFormat3_ + { + TT_UShort BacktrackGlyphCount; + /* number of backtrack glyphs */ + TTO_Coverage* BacktrackCoverage; + /* array of backtrack Coverage + tables */ + TT_UShort InputGlyphCount; + /* number of input glyphs */ + TTO_Coverage* InputCoverage; + /* array of input coverage + tables */ + TT_UShort LookaheadGlyphCount; + /* number of lookahead glyphs */ + TTO_Coverage* LookaheadCoverage; + /* array of lookahead coverage + tables */ + TT_UShort PosCount; /* number of PosLookupRecords */ + TTO_PosLookupRecord* PosLookupRecord; + /* array of substitution lookups */ + }; + + typedef struct TTO_ChainContextPosFormat3_ TTO_ChainContextPosFormat3; + + + struct TTO_ChainContextPos_ + { + TT_UShort PosFormat; /* 1, 2, or 3 */ + + union + { + TTO_ChainContextPosFormat1 ccpf1; + TTO_ChainContextPosFormat2 ccpf2; + TTO_ChainContextPosFormat3 ccpf3; + } ccpf; + }; + + typedef struct TTO_ChainContextPos_ TTO_ChainContextPos; + + + union TTO_GPOS_SubTable_ + { + TTO_SinglePos single; + TTO_PairPos pair; + TTO_CursivePos cursive; + TTO_MarkBasePos markbase; + TTO_MarkLigPos marklig; + TTO_MarkMarkPos markmark; + TTO_ContextPos context; + TTO_ChainContextPos chain; + }; + + typedef union TTO_GPOS_SubTable_ TTO_GPOS_SubTable; + + + /* This `string object' is much simpler compared to TTO_GSUB_String. + A call to TTO_GPOS_Apply_String() will allocate it. */ + + struct TTO_GPOS_Data_ + { + TT_Pos x_pos; + TT_Pos y_pos; + TT_Pos x_advance; + TT_Pos y_advance; + TT_UShort back; /* number of glyphs to go back + for drawing current glyph */ + TT_Bool new_advance; /* if set, the advance width values are + absolute, i.e., they won't be + added to the original glyph's value + but rather replace them. */ + }; + + typedef struct TTO_GPOS_Data_ TTO_GPOS_Data; + + + /* finally, the GPOS API */ + + EXPORT_DEF + TT_Error TT_Init_GPOS_Extension( TT_Engine engine ); + + EXPORT_DEF + TT_Error TT_Load_GPOS_Table( TT_Face face, + TTO_GPOSHeader* gpos, + TTO_GDEFHeader* gdef ); + + EXPORT_DEF + TT_Error TT_GPOS_Select_Script( TTO_GPOSHeader* gpos, + TT_ULong script_tag, + TT_UShort* script_index ); + EXPORT_DEF + TT_Error TT_GPOS_Select_Language( TTO_GPOSHeader* gpos, + TT_ULong language_tag, + TT_UShort script_index, + TT_UShort* language_index, + TT_UShort* req_feature_index ); + EXPORT_DEF + TT_Error TT_GPOS_Select_Feature( TTO_GPOSHeader* gpos, + TT_ULong feature_tag, + TT_UShort script_index, + TT_UShort language_index, + TT_UShort* feature_index ); + + EXPORT_DEF + TT_Error TT_GPOS_Query_Scripts( TTO_GPOSHeader* gpos, + TT_ULong** script_tag_list ); + EXPORT_DEF + TT_Error TT_GPOS_Query_Languages( TTO_GPOSHeader* gpos, + TT_UShort script_index, + TT_ULong** language_tag_list ); + EXPORT_DEF + TT_Error TT_GPOS_Query_Features( TTO_GPOSHeader* gpos, + TT_UShort script_index, + TT_UShort language_index, + TT_ULong** feature_tag_list ); + + EXPORT_DEF + TT_Error TT_GPOS_Add_Feature( TTO_GPOSHeader* gpos, + TT_UShort feature_index, + TT_UShort property ); + EXPORT_DEF + TT_Error TT_GPOS_Clear_Features( TTO_GPOSHeader* gpos ); + + EXPORT_DEF + TT_Error TT_GPOS_Register_Glyph_Function( TTO_GPOSHeader* gpos, + TTO_GlyphFunction gfunc ); + + EXPORT_DEF + TT_Error TT_GPOS_Register_MM_Function( TTO_GPOSHeader* gpos, + TTO_MMFunction mmfunc, + void* data ); + + /* If `dvi' is TRUE, glyph contour points for anchor points and device + tables are ignored -- you will get device independent values. */ + + EXPORT_DEF + TT_Error TT_GPOS_Apply_String( TT_Instance instance, + TT_Glyph glyph, + TTO_GPOSHeader* gpos, + TT_UShort load_flags, + TTO_GSUB_String* in, + TTO_GPOS_Data** out, + TT_Bool dvi, + TT_Bool r2l ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXGPOS_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgsub.c b/Build/source/libs/libttf/extend/ftxgsub.c new file mode 100644 index 00000000000..fbac7425d3c --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgsub.c @@ -0,0 +1,4377 @@ +/******************************************************************* + * + * ftxgsub.c + * + * TrueType Open GSUB table support. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +/* XXX There is *a lot* of duplicated code (cf. formats 5 and 6), but + I don't care currently. I believe that it would be possible to + save about 50% of TTO code by carefully designing the structures, + sharing as much as possible with extensive use of macros. This + is something for a volunteer :-) */ + +#include "tttypes.h" +#include "tttags.h" +#include "ttload.h" +#include "ttextend.h" +#include "ttmemory.h" +#include "ttfile.h" + +#include "ftxopen.h" +#include "ftxopenf.h" + + +#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' ) + + +#define ADD_String( in, num_in, out, num_out, glyph_data, component, ligID ) \ + ( ( error = TT_GSUB_Add_String( (in), (num_in), \ + (out), (num_out), \ + (glyph_data), (component), (ligID) \ + ) ) != TT_Err_Ok ) + + + static TT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort context_length, + int nesting_level ); + + + + /********************** + * Auxiliary functions + **********************/ + + + /* The following function copies `num_out' elements from `glyph_data' + to `out', advancing the array pointer in the `in' structure by + `num_in' elements, and in `out' by `num_out' elements. If the + string (resp. the properties) array in `out' is empty or too + small, it allocates resp. reallocates the string (and properties) + array. Finally, it sets the `length' field of `out' equal to + `pos' of the `out' structure. + + If `component' is 0xFFFF, the value `in->component[in->pos]' + will be copied `num_out' times, otherwise `component' itself will + be used to fill `out->component'. + + If `ligID' is 0xFFFF, the value `in->lig_IDs[in->pos]' will be + copied `num_out' times, otherwise `ligID' itself will be used to + fill `out->ligIDs'. + + The properties (if defined) for all replaced glyphs are taken + from the glyph at position `in->pos'. */ + + EXPORT_FUNC + TT_Error TT_GSUB_Add_String( TTO_GSUB_String* in, + UShort num_in, + TTO_GSUB_String* out, + UShort num_out, + UShort* glyph_data, + UShort component, + UShort ligID ) + { + TT_Error error; + UShort i; + UShort p_in; + UShort* p_out; + + + /* sanity check */ + + if ( !in || !out || + in->length == 0 || in->pos >= in->length || + in->length < in->pos + num_in ) + return TT_Err_Invalid_Argument; + + if ( out->pos + num_out >= out->allocated ) + { + ULong size = out->pos + num_out + 256L; + + + /* The following works because all fields in `out' must be + initialized to zero (including the `string' field) for the + first use. */ + + if ( REALLOC_ARRAY( out->string, size, UShort ) ) + return error; + if ( REALLOC_ARRAY( out->components, size, UShort ) ) + return error; + if ( REALLOC_ARRAY( out->ligIDs, size, UShort ) ) + return error; + if ( in->properties ) + if ( REALLOC_ARRAY( out->properties, size, UShort ) ) + return error; + + out->allocated = size; + } + + if ( num_out ) + { + MEM_Copy( &out->string[out->pos], glyph_data, + num_out * sizeof ( UShort ) ); + + if ( component == 0xFFFF ) + component = in->components[in->pos]; + + p_out = out->components; + + for ( i = out->pos; i < out->pos + num_out; i++ ) + p_out[i] = component; + + p_out = out->ligIDs; + + if ( ligID == 0xFFFF ) + ligID = in->ligIDs[in->pos]; + + for ( i = out->pos; i < out->pos + num_out; i++ ) + p_out[i] = ligID; + + if ( in->properties ) + { + p_in = in->properties[in->pos]; + p_out = out->properties; + + for ( i = out->pos; i < out->pos + num_out; i++ ) + p_out[i] = p_in; + } + } + + in->pos += num_in; + out->pos += num_out; + + out->length = out->pos; + + return TT_Err_Ok; + } + + + + /********************** + * Extension Functions + **********************/ + + + static TT_Error GSUB_Create( void* ext, + PFace face ) + { + DEFINE_LOAD_LOCALS( face->stream ); + + TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext; + Long table; + + + /* by convention */ + + if ( !gsub ) + return TT_Err_Ok; + + /* a null offset indicates that there is no GSUB table */ + + gsub->offset = 0; + + /* we store the start offset and the size of the subtable */ + + table = TT_LookUp_Table( face, TTAG_GSUB ); + if ( table < 0 ) + return TT_Err_Ok; /* The table is optional */ + + if ( FILE_Seek( face->dirTables[table].Offset ) || + ACCESS_Frame( 4L ) ) + return error; + + gsub->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ + gsub->Version = GET_ULong(); + + FORGET_Frame(); + + gsub->loaded = FALSE; + + return TT_Err_Ok; + } + + + static TT_Error GSUB_Destroy( void* ext, + PFace face ) + { + TTO_GSUBHeader* gsub = (TTO_GSUBHeader*)ext; + + + /* by convention */ + + if ( !gsub ) + return TT_Err_Ok; + + if ( gsub->loaded ) + { + Free_LookupList( &gsub->LookupList, GSUB ); + Free_FeatureList( &gsub->FeatureList ); + Free_ScriptList( &gsub->ScriptList ); + } + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_Init_GSUB_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + return TT_Register_Extension( _engine, + GSUB_ID, + sizeof ( TTO_GSUBHeader ), + GSUB_Create, + GSUB_Destroy ); + } + + + EXPORT_FUNC + TT_Error TT_Load_GSUB_Table( TT_Face face, + TTO_GSUBHeader* retptr, + TTO_GDEFHeader* gdef ) + { + ULong cur_offset, new_offset, base_offset; + + UShort i, num_lookups; + TT_Error error; + TT_Stream stream; + TTO_GSUBHeader* gsub; + TTO_Lookup* lo; + + PFace faze = HANDLE_Face( face ); + + + if ( !retptr ) + return TT_Err_Invalid_Argument; + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + error = TT_Extension_Get( faze, GSUB_ID, (void**)&gsub ); + if ( error ) + return error; + + if ( gsub->offset == 0 ) + return TT_Err_Table_Missing; /* no GSUB table; nothing to do */ + + /* now access stream */ + + if ( USE_Stream( faze->stream, stream ) ) + return error; + + base_offset = gsub->offset; + + /* skip version */ + + if ( FILE_Seek( base_offset + 4L ) || + ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ScriptList( &gsub->ScriptList, + faze ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_FeatureList( &gsub->FeatureList, + faze ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LookupList( &gsub->LookupList, + faze, GSUB ) ) != TT_Err_Ok ) + goto Fail2; + + gsub->gdef = gdef; /* can be NULL */ + + /* We now check the LookupFlags for values larger than 0xFF to find + out whether we need to load the `MarkAttachClassDef' field of the + GDEF table -- this hack is necessary for OpenType 1.2 tables since + the version field of the GDEF table hasn't been incremented. + + For constructed GDEF tables, we only load it if + `MarkAttachClassDef_offset' is not zero (nevertheless, a build of + a constructed mark attach table is not supported currently). */ + + if ( gdef && + gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) + { + lo = gsub->LookupList.Lookup; + num_lookups = gsub->LookupList.LookupCount; + + for ( i = 0; i < num_lookups; i++ ) + { + if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS ) + { + if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || + ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort(); + + FORGET_Frame(); + + if ( !new_offset ) + return TTO_Err_Invalid_GDEF_SubTable; + + new_offset += base_offset; + + if ( FILE_Seek( new_offset ) || + ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef, + 256, faze ) ) != TT_Err_Ok ) + goto Fail1; + + break; + } + } + } + + gsub->loaded = TRUE; + *retptr = *gsub; + DONE_Stream( stream ); + + return TT_Err_Ok; + + Fail1: + Free_LookupList( &gsub->LookupList, GSUB ); + + Fail2: + Free_FeatureList( &gsub->FeatureList ); + + Fail3: + Free_ScriptList( &gsub->ScriptList ); + + /* release stream */ + + DONE_Stream( stream ); + + return error; + } + + + + /***************************** + * SubTable related functions + *****************************/ + + + /* LookupType 1 */ + + /* SingleSubstFormat1 */ + /* SingleSubstFormat2 */ + + TT_Error Load_SingleSubst( TTO_SingleSubst* ss, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + UShort* s; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + ss->SubstFormat = GET_UShort(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ss->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + switch ( ss->SubstFormat ) + { + case 1: + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + ss->ssf.ssf1.DeltaGlyphID = GET_UShort(); + + FORGET_Frame(); + + break; + + case 2: + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = ss->ssf.ssf2.GlyphCount = GET_UShort(); + + FORGET_Frame(); + + ss->ssf.ssf2.Substitute = NULL; + + if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, UShort ) ) + goto Fail2; + + s = ss->ssf.ssf2.Substitute; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + s[n] = GET_UShort(); + + FORGET_Frame(); + + break; + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + + return TT_Err_Ok; + + Fail1: + FREE( s ); + + Fail2: + Free_Coverage( &ss->Coverage ); + return error; + } + + + void Free_SingleSubst( TTO_SingleSubst* ss ) + { + switch ( ss->SubstFormat ) + { + case 1: + break; + + case 2: + FREE( ss->ssf.ssf2.Substitute ); + break; + } + + Free_Coverage( &ss->Coverage ); + } + + + static TT_Error Lookup_SingleSubst( TTO_SingleSubst* ss, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + TTO_GDEFHeader* gdef ) + { + UShort index, value[1], property; + TT_Error error; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &ss->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + switch ( ss->SubstFormat ) + { + case 1: + value[0] = ( in->string[in->pos] + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF; + if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) ) + return error; + break; + + case 2: + if ( index >= ss->ssf.ssf2.GlyphCount ) + return TTO_Err_Invalid_GSUB_SubTable; + value[0] = ss->ssf.ssf2.Substitute[index]; + if ( ADD_String( in, 1, out, 1, value, 0xFFFF, 0xFFFF ) ) + return error; + break; + + default: + return TTO_Err_Invalid_GSUB_SubTable; + } + + if ( gdef && gdef->NewGlyphClasses ) + { + /* we inherit the old glyph class to the substituted glyph */ + + error = Add_Glyph_Property( gdef, value[0], property ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + + return TT_Err_Ok; + } + + + /* LookupType 2 */ + + /* Sequence */ + + static TT_Error Load_Sequence( TTO_Sequence* s, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* sub; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = s->GlyphCount = GET_UShort(); + + FORGET_Frame(); + + s->Substitute = NULL; + + if ( count ) + { + if ( ALLOC_ARRAY( s->Substitute, count, UShort ) ) + return error; + + sub = s->Substitute; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( sub ); + return error; + } + + for ( n = 0; n < count; n++ ) + sub[n] = GET_UShort(); + + FORGET_Frame(); + } + + return TT_Err_Ok; + } + + + static void Free_Sequence( TTO_Sequence* s ) + { + FREE( s->Substitute ); + } + + + /* MultipleSubstFormat1 */ + + TT_Error Load_MultipleSubst( TTO_MultipleSubst* ms, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Sequence* s; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + ms->SubstFormat = GET_UShort(); /* should be 1 */ + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ms->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = ms->SequenceCount = GET_UShort(); + + FORGET_Frame(); + + ms->Sequence = NULL; + + if ( ALLOC_ARRAY( ms->Sequence, count, TTO_Sequence ) ) + goto Fail2; + + s = ms->Sequence; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Sequence( &s[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_Sequence( &s[n] ); + + FREE( s ); + + Fail2: + Free_Coverage( &ms->Coverage ); + return error; + } + + + void Free_MultipleSubst( TTO_MultipleSubst* ms ) + { + UShort n, count; + + TTO_Sequence* s; + + + if ( ms->Sequence ) + { + count = ms->SequenceCount; + s = ms->Sequence; + + for ( n = 0; n < count; n++ ) + Free_Sequence( &s[n] ); + + FREE( s ); + } + + Free_Coverage( &ms->Coverage ); + } + + + static TT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + TTO_GDEFHeader* gdef ) + { + TT_Error error; + UShort index, property, n, count; + UShort* s; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &ms->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + if ( index >= ms->SequenceCount ) + return TTO_Err_Invalid_GSUB_SubTable; + + count = ms->Sequence[index].GlyphCount; + s = ms->Sequence[index].Substitute; + + if ( ADD_String( in, 1, out, count, s, 0xFFFF, 0xFFFF ) ) + return error; + + if ( gdef && gdef->NewGlyphClasses ) + { + /* this is a guess only ... */ + + if ( property == TTO_LIGATURE ) + property = TTO_BASE_GLYPH; + + for ( n = 0; n < count; n++ ) + { + error = Add_Glyph_Property( gdef, s[n], property ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + } + + return TT_Err_Ok; + } + + + /* LookupType 3 */ + + /* AlternateSet */ + + static TT_Error Load_AlternateSet( TTO_AlternateSet* as, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* a; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = as->GlyphCount = GET_UShort(); + + FORGET_Frame(); + + as->Alternate = NULL; + + if ( ALLOC_ARRAY( as->Alternate, count, UShort ) ) + return error; + + a = as->Alternate; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( a ); + return error; + } + + for ( n = 0; n < count; n++ ) + a[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + static void Free_AlternateSet( TTO_AlternateSet* as ) + { + FREE( as->Alternate ); + } + + + /* AlternateSubstFormat1 */ + + TT_Error Load_AlternateSubst( TTO_AlternateSubst* as, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_AlternateSet* aset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + as->SubstFormat = GET_UShort(); /* should be 1 */ + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &as->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = as->AlternateSetCount = GET_UShort(); + + FORGET_Frame(); + + as->AlternateSet = NULL; + + if ( ALLOC_ARRAY( as->AlternateSet, count, TTO_AlternateSet ) ) + goto Fail2; + + aset = as->AlternateSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_AlternateSet( &aset[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_AlternateSet( &aset[n] ); + + FREE( aset ); + + Fail2: + Free_Coverage( &as->Coverage ); + return error; + } + + + void Free_AlternateSubst( TTO_AlternateSubst* as ) + { + UShort n, count; + + TTO_AlternateSet* aset; + + + if ( as->AlternateSet ) + { + count = as->AlternateSetCount; + aset = as->AlternateSet; + + for ( n = 0; n < count; n++ ) + Free_AlternateSet( &aset[n] ); + + FREE( aset ); + } + + Free_Coverage( &as->Coverage ); + } + + + static TT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub, + TTO_AlternateSubst* as, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + TTO_GDEFHeader* gdef ) + { + TT_Error error; + UShort index, alt_index, property; + + TTO_AlternateSet aset; + + + if ( context_length != 0xFFFF && context_length < 1 ) + return TTO_Err_Not_Covered; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &as->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + aset = as->AlternateSet[index]; + + /* we use a user-defined callback function to get the alternate index */ + + if ( gsub->altfunc ) + alt_index = (gsub->altfunc)( out->pos, in->string[in->pos], + aset.GlyphCount, aset.Alternate, + gsub->data ); + else + alt_index = 0; + + if ( ADD_String( in, 1, out, 1, &aset.Alternate[alt_index], + 0xFFFF, 0xFFFF ) ) + return error; + + if ( gdef && gdef->NewGlyphClasses ) + { + /* we inherit the old glyph class to the substituted glyph */ + + error = Add_Glyph_Property( gdef, aset.Alternate[alt_index], + property ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + + return TT_Err_Ok; + } + + + /* LookupType 4 */ + + /* Ligature */ + + static TT_Error Load_Ligature( TTO_Ligature* l, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* c; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + l->LigGlyph = GET_UShort(); + l->ComponentCount = GET_UShort(); + + FORGET_Frame(); + + l->Component = NULL; + + count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */ + + if ( ALLOC_ARRAY( l->Component, count, UShort ) ) + return error; + + c = l->Component; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( c ); + return error; + } + + for ( n = 0; n < count; n++ ) + c[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + static void Free_Ligature( TTO_Ligature* l ) + { + FREE( l->Component ); + } + + + /* LigatureSet */ + + static TT_Error Load_LigatureSet( TTO_LigatureSet* ls, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Ligature* l; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ls->LigatureCount = GET_UShort(); + + FORGET_Frame(); + + ls->Ligature = NULL; + + if ( ALLOC_ARRAY( ls->Ligature, count, TTO_Ligature ) ) + return error; + + l = ls->Ligature; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Ligature( &l[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_Ligature( &l[n] ); + + FREE( l ); + return error; + } + + + static void Free_LigatureSet( TTO_LigatureSet* ls ) + { + UShort n, count; + + TTO_Ligature* l; + + + if ( ls->Ligature ) + { + count = ls->LigatureCount; + l = ls->Ligature; + + for ( n = 0; n < count; n++ ) + Free_Ligature( &l[n] ); + + FREE( l ); + } + } + + + /* LigatureSubstFormat1 */ + + TT_Error Load_LigatureSubst( TTO_LigatureSubst* ls, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_LigatureSet* lset; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 4L ) ) + return error; + + ls->SubstFormat = GET_UShort(); /* should be 1 */ + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ls->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = ls->LigatureSetCount = GET_UShort(); + + FORGET_Frame(); + + ls->LigatureSet = NULL; + + if ( ALLOC_ARRAY( ls->LigatureSet, count, TTO_LigatureSet ) ) + goto Fail2; + + lset = ls->LigatureSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LigatureSet( &lset[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_LigatureSet( &lset[n] ); + + FREE( lset ); + + Fail2: + Free_Coverage( &ls->Coverage ); + return error; + } + + + void Free_LigatureSubst( TTO_LigatureSubst* ls ) + { + UShort n, count; + + TTO_LigatureSet* lset; + + + if ( ls->LigatureSet ) + { + count = ls->LigatureSetCount; + lset = ls->LigatureSet; + + for ( n = 0; n < count; n++ ) + Free_LigatureSet( &lset[n] ); + + FREE( lset ); + } + + Free_Coverage( &ls->Coverage ); + } + + + static TT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + TTO_GDEFHeader* gdef ) + { + UShort index, property; + TT_Error error; + UShort numlig, i, j, is_mark, first_is_mark = FALSE; + UShort* s_in; + UShort* c; + + TTO_Ligature* lig; + + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + if ( property == TTO_MARK ) + first_is_mark = TRUE; + + error = Coverage_Index( &ls->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + if ( index >= ls->LigatureSetCount ) + return TTO_Err_Invalid_GSUB_SubTable; + + lig = ls->LigatureSet[index].Ligature; + + for ( numlig = ls->LigatureSet[index].LigatureCount; + numlig; + numlig--, lig++ ) + { + if ( in->pos + lig->ComponentCount > in->length ) + continue; /* Not enough glyphs in input */ + + s_in = &in->string[in->pos]; + c = lig->Component; + + is_mark = first_is_mark; + + if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) + break; + + for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + break; + } + + if ( property != TTO_MARK ) + is_mark = FALSE; + + if ( s_in[j] != c[i - 1] ) + break; + } + + if ( i == lig->ComponentCount ) + { + if ( gdef && gdef->NewGlyphClasses ) + { + /* this is just a guess ... */ + + error = Add_Glyph_Property( gdef, lig->LigGlyph, + is_mark ? TTO_MARK : TTO_LIGATURE ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + + if ( i == j ) + { + /* We don't use a new ligature ID if there are no skipped + glyphs and the ligature already has an ID. */ + + if ( in->ligIDs[in->pos] ) + { + if ( ADD_String( in, i, out, 1, &lig->LigGlyph, + 0xFFFF, 0xFFFF ) ) + return error; + } + else + { + if ( ADD_String( in, i, out, 1, &lig->LigGlyph, + 0xFFFF, in->max_ligID ) ) + return error; + + (in->max_ligID)++; + } + } + else + { + if ( ADD_String( in, 1, out, 1, &lig->LigGlyph, + 0xFFFF, in->max_ligID ) ) + return error; + + /* Now we must do a second loop to copy the skipped glyphs to + `out' and assign component values to it. We start with the + glyph after the first component. Glyphs between component + i and i+1 belong to component i. Together with the ligID + value it is later possible to check whether a specific + component value really belongs to a given ligature. */ + + for ( i = 0; i < lig->ComponentCount - 1; i++ ) + { + while ( CHECK_Property( gdef, in->string[in->pos], + flags, &property ) ) + if ( ADD_String( in, 1, out, 1, &in->string[in->pos], + i, in->max_ligID ) ) + return error; + + (in->pos)++; + } + + (in->max_ligID)++; + } + + return TT_Err_Ok; + } + } + + return TTO_Err_Not_Covered; + } + + + /* Do the actual substitution for a context substitution (either format + 5 or 6). This is only called after we've determined that the input + matches the subrule. */ + + static TT_Error Do_ContextSubst( TTO_GSUBHeader* gsub, + UShort GlyphCount, + UShort SubstCount, + TTO_SubstLookupRecord* subst, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + int nesting_level ) + { + TT_Error error; + UShort i, old_pos; + + + i = 0; + + while ( i < GlyphCount ) + { + if ( SubstCount && i == subst->SequenceIndex ) + { + old_pos = in->pos; + + /* Do a substitution */ + + error = Do_Glyph_Lookup( gsub, subst->LookupListIndex, in, out, + GlyphCount, nesting_level ); + + subst++; + SubstCount--; + i += in->pos - old_pos; + + if ( error == TTO_Err_Not_Covered ) + { + /* XXX "can't happen" -- but don't count on it */ + + if ( ADD_String( in, 1, out, 1, &in->string[in->pos], + 0xFFFF, 0xFFFF ) ) + return error; + i++; + } + else if ( error ) + return error; + } + else + { + /* No substitution for this index */ + + if ( ADD_String( in, 1, out, 1, &in->string[in->pos], + 0xFFFF, 0xFFFF ) ) + return error; + i++; + } + } + + return TT_Err_Ok; + } + + + /* LookupType 5 */ + + /* SubRule */ + + static TT_Error Load_SubRule( TTO_SubRule* sr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* i; + + TTO_SubstLookupRecord* slr; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + sr->GlyphCount = GET_UShort(); + sr->SubstCount = GET_UShort(); + + FORGET_Frame(); + + sr->Input = NULL; + + count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( sr->Input, count, UShort ) ) + return error; + + i = sr->Input; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + i[n] = GET_UShort(); + + FORGET_Frame(); + + sr->SubstLookupRecord = NULL; + + count = sr->SubstCount; + + if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = sr->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + FREE( i ); + return error; + } + + + static void Free_SubRule( TTO_SubRule* sr ) + { + FREE( sr->SubstLookupRecord ); + FREE( sr->Input ); + } + + + /* SubRuleSet */ + + static TT_Error Load_SubRuleSet( TTO_SubRuleSet* srs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_SubRule* sr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = srs->SubRuleCount = GET_UShort(); + + FORGET_Frame(); + + srs->SubRule = NULL; + + if ( ALLOC_ARRAY( srs->SubRule, count, TTO_SubRule ) ) + return error; + + sr = srs->SubRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_SubRule( &sr[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_SubRule( &sr[n] ); + + FREE( sr ); + return error; + } + + + static void Free_SubRuleSet( TTO_SubRuleSet* srs ) + { + UShort n, count; + + TTO_SubRule* sr; + + + if ( srs->SubRule ) + { + count = srs->SubRuleCount; + sr = srs->SubRule; + + for ( n = 0; n < count; n++ ) + Free_SubRule( &sr[n] ); + + FREE( sr ); + } + } + + + /* ContextSubstFormat1 */ + + static TT_Error Load_ContextSubst1( TTO_ContextSubstFormat1* csf1, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_SubRuleSet* srs; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &csf1->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = csf1->SubRuleSetCount = GET_UShort(); + + FORGET_Frame(); + + csf1->SubRuleSet = NULL; + + if ( ALLOC_ARRAY( csf1->SubRuleSet, count, TTO_SubRuleSet ) ) + goto Fail2; + + srs = csf1->SubRuleSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_SubRuleSet( &srs[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_SubRuleSet( &srs[n] ); + + FREE( srs ); + + Fail2: + Free_Coverage( &csf1->Coverage ); + return error; + } + + + static void Free_Context1( TTO_ContextSubstFormat1* csf1 ) + { + UShort n, count; + + TTO_SubRuleSet* srs; + + + if ( csf1->SubRuleSet ) + { + count = csf1->SubRuleSetCount; + srs = csf1->SubRuleSet; + + for ( n = 0; n < count; n++ ) + Free_SubRuleSet( &srs[n] ); + + FREE( srs ); + } + + Free_Coverage( &csf1->Coverage ); + } + + + /* SubClassRule */ + + static TT_Error Load_SubClassRule( TTO_ContextSubstFormat2* csf2, + TTO_SubClassRule* scr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* c; + TTO_SubstLookupRecord* slr; + Bool* d; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + scr->GlyphCount = GET_UShort(); + scr->SubstCount = GET_UShort(); + + if ( scr->GlyphCount > csf2->MaxContextLength ) + csf2->MaxContextLength = scr->GlyphCount; + + FORGET_Frame(); + + scr->Class = NULL; + + count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( scr->Class, count, UShort ) ) + return error; + + c = scr->Class; + d = csf2->ClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + { + c[n] = GET_UShort(); + + /* We check whether the specific class is used at all. If not, + class 0 is used instead. */ + + if ( !d[c[n]] ) + c[n] = 0; + } + + FORGET_Frame(); + + scr->SubstLookupRecord = NULL; + + count = scr->SubstCount; + + if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = scr->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + FREE( c ); + return error; + } + + + static void Free_SubClassRule( TTO_SubClassRule* scr ) + { + FREE( scr->SubstLookupRecord ); + FREE( scr->Class ); + } + + + /* SubClassSet */ + + static TT_Error Load_SubClassSet( TTO_ContextSubstFormat2* csf2, + TTO_SubClassSet* scs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_SubClassRule* scr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = scs->SubClassRuleCount = GET_UShort(); + + FORGET_Frame(); + + scs->SubClassRule = NULL; + + if ( ALLOC_ARRAY( scs->SubClassRule, count, TTO_SubClassRule ) ) + return error; + + scr = scs->SubClassRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_SubClassRule( csf2, &scr[n], + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_SubClassRule( &scr[n] ); + + FREE( scr ); + return error; + } + + + static void Free_SubClassSet( TTO_SubClassSet* scs ) + { + UShort n, count; + + TTO_SubClassRule* scr; + + + if ( scs->SubClassRule ) + { + count = scs->SubClassRuleCount; + scr = scs->SubClassRule; + + for ( n = 0; n < count; n++ ) + Free_SubClassRule( &scr[n] ); + + FREE( scr ); + } + } + + + /* ContextSubstFormat2 */ + + static TT_Error Load_ContextSubst2( TTO_ContextSubstFormat2* csf2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_SubClassSet* scs; + + + base_offset = FILE_Pos() - 2; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &csf2->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 4L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + /* `SubClassSetCount' is the upper limit for class values, thus we + read it now to make an additional safety check. */ + + count = csf2->SubClassSetCount = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ClassDefinition( &csf2->ClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + csf2->SubClassSet = NULL; + csf2->MaxContextLength = 0; + + if ( ALLOC_ARRAY( csf2->SubClassSet, count, TTO_SubClassSet ) ) + goto Fail2; + + scs = csf2->SubClassSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + if ( new_offset != base_offset ) /* not a NULL offset */ + { + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_SubClassSet( csf2, &scs[n], + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + { + /* we create a SubClassSet table with no entries */ + + csf2->SubClassSet[n].SubClassRuleCount = 0; + csf2->SubClassSet[n].SubClassRule = NULL; + } + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_SubClassSet( &scs[n] ); + + FREE( scs ); + + Fail2: + Free_ClassDefinition( &csf2->ClassDef ); + + Fail3: + Free_Coverage( &csf2->Coverage ); + return error; + } + + + static void Free_Context2( TTO_ContextSubstFormat2* csf2 ) + { + UShort n, count; + + TTO_SubClassSet* scs; + + + if ( csf2->SubClassSet ) + { + count = csf2->SubClassSetCount; + scs = csf2->SubClassSet; + + for ( n = 0; n < count; n++ ) + Free_SubClassSet( &scs[n] ); + + FREE( scs ); + } + + Free_ClassDefinition( &csf2->ClassDef ); + Free_Coverage( &csf2->Coverage ); + } + + + /* ContextSubstFormat3 */ + + static TT_Error Load_ContextSubst3( TTO_ContextSubstFormat3* csf3, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Coverage* c; + TTO_SubstLookupRecord* slr; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 4L ) ) + return error; + + csf3->GlyphCount = GET_UShort(); + csf3->SubstCount = GET_UShort(); + + FORGET_Frame(); + + csf3->Coverage = NULL; + + count = csf3->GlyphCount; + + if ( ALLOC_ARRAY( csf3->Coverage, count, TTO_Coverage ) ) + return error; + + c = csf3->Coverage; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &c[n], input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + + csf3->SubstLookupRecord = NULL; + + count = csf3->SubstCount; + + if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count, + TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = csf3->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + return error; + } + + + static void Free_Context3( TTO_ContextSubstFormat3* csf3 ) + { + UShort n, count; + + TTO_Coverage* c; + + + FREE( csf3->SubstLookupRecord ); + + if ( csf3->Coverage ) + { + count = csf3->GlyphCount; + c = csf3->Coverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + } + + + /* ContextSubst */ + + TT_Error Load_ContextSubst( TTO_ContextSubst* cs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ACCESS_Frame( 2L ) ) + return error; + + cs->SubstFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( cs->SubstFormat ) + { + case 1: + return Load_ContextSubst1( &cs->csf.csf1, input ); + + case 2: + return Load_ContextSubst2( &cs->csf.csf2, input ); + + case 3: + return Load_ContextSubst3( &cs->csf.csf3, input ); + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + void Free_ContextSubst( TTO_ContextSubst* cs ) + { + switch ( cs->SubstFormat ) + { + case 1: + Free_Context1( &cs->csf.csf1 ); + break; + + case 2: + Free_Context2( &cs->csf.csf2 ); + break; + + case 3: + Free_Context3( &cs->csf.csf3 ); + break; + } + } + + + static TT_Error Lookup_ContextSubst1( + TTO_GSUBHeader* gsub, + TTO_ContextSubstFormat1* csf1, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + UShort i, j, k, numsr; + TT_Error error; + UShort* s_in; + + TTO_SubRule* sr; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &csf1->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + sr = csf1->SubRuleSet[index].SubRule; + numsr = csf1->SubRuleSet[index].SubRuleCount; + + for ( k = 0; k < numsr; k++ ) + { + if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) + continue; + + if ( in->pos + sr[k].GlyphCount > in->length ) + continue; /* context is too long */ + + s_in = &in->string[in->pos]; + + for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != sr[k].Input[i - 1] ) + break; + } + + if ( i == sr[k].GlyphCount ) + return Do_ContextSubst( gsub, sr[k].GlyphCount, + sr[k].SubstCount, sr[k].SubstLookupRecord, + in, out, + nesting_level ); + } + + return TTO_Err_Not_Covered; + } + + + static TT_Error Lookup_ContextSubst2( + TTO_GSUBHeader* gsub, + TTO_ContextSubstFormat2* csf2, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + TT_Error error; + UShort i, j, k, known_classes; + + UShort* classes; + UShort* s_in; + UShort* cl; + + TTO_SubClassSet* scs; + TTO_SubClassRule* sr; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, UShort ) ) + return error; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + /* Note: The coverage table in format 2 doesn't give an index into + anything. It just lets us know whether or not we need to + do any lookup at all. */ + + error = Coverage_Index( &csf2->Coverage, in->string[in->pos], &index ); + if ( error ) + goto End; + + error = Get_Class( &csf2->ClassDef, in->string[in->pos], + &classes[0], NULL ); + if ( error ) + goto End; + known_classes = 0; + + scs = &csf2->SubClassSet[classes[0]]; + if ( !scs ) + { + error = TTO_Err_Invalid_GSUB_SubTable; + goto End; + } + + for ( k = 0; k < scs->SubClassRuleCount; k++ ) + { + sr = &scs->SubClassRule[k]; + + if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) + continue; + + if ( in->pos + sr->GlyphCount > in->length ) + continue; /* context is too long */ + + s_in = &in->string[in->pos]; + cl = sr->Class; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + break; + } + + if ( i > known_classes ) + { + /* Keeps us from having to do this for each rule */ + + error = Get_Class( &csf2->ClassDef, s_in[j], &classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + known_classes = i; + } + + if ( cl[i - 1] != classes[i] ) + break; + } + + if ( i == sr->GlyphCount ) + { + error = Do_ContextSubst( gsub, sr->GlyphCount, + sr->SubstCount, sr->SubstLookupRecord, + in, out, + nesting_level ); + goto End; + } + } + + error = TTO_Err_Not_Covered; + + End: + FREE( classes ); + return error; + } + + + static TT_Error Lookup_ContextSubst3( + TTO_GSUBHeader* gsub, + TTO_ContextSubstFormat3* csf3, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + TT_Error error; + UShort index, i, j, property; + UShort* s_in; + + TTO_Coverage* c; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) + return TTO_Err_Not_Covered; + + if ( in->pos + csf3->GlyphCount > in->length ) + return TTO_Err_Not_Covered; /* context is too long */ + + s_in = &in->string[in->pos]; + c = csf3->Coverage; + + for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( in->pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &c[i], s_in[j], &index ); + if ( error ) + return error; + } + + return Do_ContextSubst( gsub, csf3->GlyphCount, + csf3->SubstCount, csf3->SubstLookupRecord, + in, out, + nesting_level ); + } + + + static TT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub, + TTO_ContextSubst* cs, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + switch ( cs->SubstFormat ) + { + case 1: + return Lookup_ContextSubst1( gsub, &cs->csf.csf1, in, out, + flags, context_length, nesting_level ); + + case 2: + return Lookup_ContextSubst2( gsub, &cs->csf.csf2, in, out, + flags, context_length, nesting_level ); + + case 3: + return Lookup_ContextSubst3( gsub, &cs->csf.csf3, in, out, + flags, context_length, nesting_level ); + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + /* LookupType 6 */ + + /* ChainSubRule */ + + static TT_Error Load_ChainSubRule( TTO_ChainSubRule* csr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort* b; + UShort* i; + UShort* l; + + TTO_SubstLookupRecord* slr; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + csr->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + csr->Backtrack = NULL; + + count = csr->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( csr->Backtrack, count, UShort ) ) + return error; + + b = csr->Backtrack; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail4; + + for ( n = 0; n < count; n++ ) + b[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + csr->InputGlyphCount = GET_UShort(); + + FORGET_Frame(); + + csr->Input = NULL; + + count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( csr->Input, count, UShort ) ) + goto Fail4; + + i = csr->Input; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail3; + + for ( n = 0; n < count; n++ ) + i[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + csr->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + csr->Lookahead = NULL; + + count = csr->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( csr->Lookahead, count, UShort ) ) + goto Fail3; + + l = csr->Lookahead; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + l[n] = GET_UShort(); + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + csr->SubstCount = GET_UShort(); + + FORGET_Frame(); + + csr->SubstLookupRecord = NULL; + + count = csr->SubstCount; + + if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = csr->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + FREE( l ); + + Fail3: + FREE( i ); + + Fail4: + FREE( b ); + return error; + } + + + static void Free_ChainSubRule( TTO_ChainSubRule* csr ) + { + FREE( csr->SubstLookupRecord ); + FREE( csr->Lookahead ); + FREE( csr->Input ); + FREE( csr->Backtrack ); + } + + + /* ChainSubRuleSet */ + + static TT_Error Load_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainSubRule* csr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = csrs->ChainSubRuleCount = GET_UShort(); + + FORGET_Frame(); + + csrs->ChainSubRule = NULL; + + if ( ALLOC_ARRAY( csrs->ChainSubRule, count, TTO_ChainSubRule ) ) + return error; + + csr = csrs->ChainSubRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainSubRule( &csr[n], input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_ChainSubRule( &csr[n] ); + + FREE( csr ); + return error; + } + + + static void Free_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs ) + { + UShort n, count; + + TTO_ChainSubRule* csr; + + + if ( csrs->ChainSubRule ) + { + count = csrs->ChainSubRuleCount; + csr = csrs->ChainSubRule; + + for ( n = 0; n < count; n++ ) + Free_ChainSubRule( &csr[n] ); + + FREE( csr ); + } + } + + + /* ChainContextSubstFormat1 */ + + static TT_Error Load_ChainContextSubst1( + TTO_ChainContextSubstFormat1* ccsf1, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainSubRuleSet* csrs; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ccsf1->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = ccsf1->ChainSubRuleSetCount = GET_UShort(); + + FORGET_Frame(); + + ccsf1->ChainSubRuleSet = NULL; + + if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, TTO_ChainSubRuleSet ) ) + goto Fail2; + + csrs = ccsf1->ChainSubRuleSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainSubRuleSet( &csrs[n], input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_ChainSubRuleSet( &csrs[n] ); + + FREE( csrs ); + + Fail2: + Free_Coverage( &ccsf1->Coverage ); + return error; + } + + + static void Free_ChainContext1( TTO_ChainContextSubstFormat1* ccsf1 ) + { + UShort n, count; + + TTO_ChainSubRuleSet* csrs; + + + if ( ccsf1->ChainSubRuleSet ) + { + count = ccsf1->ChainSubRuleSetCount; + csrs = ccsf1->ChainSubRuleSet; + + for ( n = 0; n < count; n++ ) + Free_ChainSubRuleSet( &csrs[n] ); + + FREE( csrs ); + } + + Free_Coverage( &ccsf1->Coverage ); + } + + + /* ChainSubClassRule */ + + static TT_Error Load_ChainSubClassRule( + TTO_ChainContextSubstFormat2* ccsf2, + TTO_ChainSubClassRule* cscr, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* b; + UShort* i; + UShort* l; + TTO_SubstLookupRecord* slr; + Bool* d; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + cscr->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength ) + ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount; + + cscr->Backtrack = NULL; + + count = cscr->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( cscr->Backtrack, count, UShort ) ) + return error; + + b = cscr->Backtrack; + d = ccsf2->BacktrackClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail4; + + for ( n = 0; n < count; n++ ) + { + b[n] = GET_UShort(); + + /* We check whether the specific class is used at all. If not, + class 0 is used instead. */ + + if ( !d[b[n]] ) + b[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + cscr->InputGlyphCount = GET_UShort(); + + FORGET_Frame(); + + if ( cscr->InputGlyphCount > ccsf2->MaxInputLength ) + ccsf2->MaxInputLength = cscr->InputGlyphCount; + + cscr->Input = NULL; + + count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ + + if ( ALLOC_ARRAY( cscr->Input, count, UShort ) ) + goto Fail4; + + i = cscr->Input; + d = ccsf2->InputClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail3; + + for ( n = 0; n < count; n++ ) + { + i[n] = GET_UShort(); + + if ( !d[i[n]] ) + i[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + cscr->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength ) + ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount; + + cscr->Lookahead = NULL; + + count = cscr->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( cscr->Lookahead, count, UShort ) ) + goto Fail3; + + l = cscr->Lookahead; + d = ccsf2->LookaheadClassDef.Defined; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail2; + + for ( n = 0; n < count; n++ ) + { + l[n] = GET_UShort(); + + if ( !d[l[n]] ) + l[n] = 0; + } + + FORGET_Frame(); + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + cscr->SubstCount = GET_UShort(); + + FORGET_Frame(); + + cscr->SubstLookupRecord = NULL; + + count = cscr->SubstCount; + + if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count, + TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = cscr->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + FREE( l ); + + Fail3: + FREE( i ); + + Fail4: + FREE( b ); + return error; + } + + + static void Free_ChainSubClassRule( TTO_ChainSubClassRule* cscr ) + { + FREE( cscr->SubstLookupRecord ); + FREE( cscr->Lookahead ); + FREE( cscr->Input ); + FREE( cscr->Backtrack ); + } + + + /* SubClassSet */ + + static TT_Error Load_ChainSubClassSet( + TTO_ChainContextSubstFormat2* ccsf2, + TTO_ChainSubClassSet* cscs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ChainSubClassRule* cscr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cscs->ChainSubClassRuleCount = GET_UShort(); + + FORGET_Frame(); + + cscs->ChainSubClassRule = NULL; + + if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count, + TTO_ChainSubClassRule ) ) + return error; + + cscr = cscs->ChainSubClassRule; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainSubClassRule( ccsf2, &cscr[n], + input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_ChainSubClassRule( &cscr[n] ); + + FREE( cscr ); + return error; + } + + + static void Free_ChainSubClassSet( TTO_ChainSubClassSet* cscs ) + { + UShort n, count; + + TTO_ChainSubClassRule* cscr; + + + if ( cscs->ChainSubClassRule ) + { + count = cscs->ChainSubClassRuleCount; + cscr = cscs->ChainSubClassRule; + + for ( n = 0; n < count; n++ ) + Free_ChainSubClassRule( &cscr[n] ); + + FREE( cscr ); + } + } + + + /* ChainContextSubstFormat2 */ + + static TT_Error Load_ChainContextSubst2( + TTO_ChainContextSubstFormat2* ccsf2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + ULong backtrack_offset, input_offset, lookahead_offset; + + TTO_ChainSubClassSet* cscs; + + + base_offset = FILE_Pos() - 2; + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &ccsf2->Coverage, input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + + if ( ACCESS_Frame( 8L ) ) + goto Fail5; + + backtrack_offset = GET_UShort() + base_offset; + input_offset = GET_UShort() + base_offset; + lookahead_offset = GET_UShort() + base_offset; + + /* `ChainSubClassSetCount' is the upper limit for input class values, + thus we read it now to make an additional safety check. */ + + count = ccsf2->ChainSubClassSetCount = GET_UShort(); + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( backtrack_offset ) || + ( error = Load_ClassDefinition( &ccsf2->BacktrackClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail5; + if ( FILE_Seek( input_offset ) || + ( error = Load_ClassDefinition( &ccsf2->InputClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail4; + if ( FILE_Seek( lookahead_offset ) || + ( error = Load_ClassDefinition( &ccsf2->LookaheadClassDef, count, + input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + + ccsf2->ChainSubClassSet = NULL; + ccsf2->MaxBacktrackLength = 0; + ccsf2->MaxInputLength = 0; + ccsf2->MaxLookaheadLength = 0; + + if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, TTO_ChainSubClassSet ) ) + goto Fail2; + + cscs = ccsf2->ChainSubClassSet; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + if ( new_offset != base_offset ) /* not a NULL offset */ + { + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_ChainSubClassSet( ccsf2, &cscs[n], + input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + else + { + /* we create a ChainSubClassSet table with no entries */ + + ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0; + ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL; + } + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_ChainSubClassSet( &cscs[n] ); + + FREE( cscs ); + + Fail2: + Free_ClassDefinition( &ccsf2->LookaheadClassDef ); + + Fail3: + Free_ClassDefinition( &ccsf2->InputClassDef ); + + Fail4: + Free_ClassDefinition( &ccsf2->BacktrackClassDef ); + + Fail5: + Free_Coverage( &ccsf2->Coverage ); + return error; + } + + + static void Free_ChainContext2( TTO_ChainContextSubstFormat2* ccsf2 ) + { + UShort n, count; + + TTO_ChainSubClassSet* cscs; + + + if ( ccsf2->ChainSubClassSet ) + { + count = ccsf2->ChainSubClassSetCount; + cscs = ccsf2->ChainSubClassSet; + + for ( n = 0; n < count; n++ ) + Free_ChainSubClassSet( &cscs[n] ); + + FREE( cscs ); + } + + Free_ClassDefinition( &ccsf2->LookaheadClassDef ); + Free_ClassDefinition( &ccsf2->InputClassDef ); + Free_ClassDefinition( &ccsf2->BacktrackClassDef ); + + Free_Coverage( &ccsf2->Coverage ); + } + + + /* ChainContextSubstFormat3 */ + + static TT_Error Load_ChainContextSubst3( + TTO_ChainContextSubstFormat3* ccsf3, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + UShort backtrack_count, input_count, lookahead_count; + ULong cur_offset, new_offset, base_offset; + + TTO_Coverage* b; + TTO_Coverage* i; + TTO_Coverage* l; + TTO_SubstLookupRecord* slr; + + + base_offset = FILE_Pos() - 2L; + + if ( ACCESS_Frame( 2L ) ) + return error; + + ccsf3->BacktrackGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccsf3->BacktrackCoverage = NULL; + + backtrack_count = ccsf3->BacktrackGlyphCount; + + if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count, + TTO_Coverage ) ) + return error; + + b = ccsf3->BacktrackCoverage; + + for ( n = 0; n < backtrack_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &b[n], input ) ) != TT_Err_Ok ) + goto Fail4; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail4; + + ccsf3->InputGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccsf3->InputCoverage = NULL; + + input_count = ccsf3->InputGlyphCount; + + if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, TTO_Coverage ) ) + goto Fail4; + + i = ccsf3->InputCoverage; + + for ( n = 0; n < input_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &i[n], input ) ) != TT_Err_Ok ) + goto Fail3; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail3; + + ccsf3->LookaheadGlyphCount = GET_UShort(); + + FORGET_Frame(); + + ccsf3->LookaheadCoverage = NULL; + + lookahead_count = ccsf3->LookaheadGlyphCount; + + if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count, + TTO_Coverage ) ) + goto Fail3; + + l = ccsf3->LookaheadCoverage; + + for ( n = 0; n < lookahead_count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Coverage( &l[n], input ) ) != TT_Err_Ok ) + goto Fail2; + (void)FILE_Seek( cur_offset ); + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + ccsf3->SubstCount = GET_UShort(); + + FORGET_Frame(); + + ccsf3->SubstLookupRecord = NULL; + + count = ccsf3->SubstCount; + + if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count, + TTO_SubstLookupRecord ) ) + goto Fail2; + + slr = ccsf3->SubstLookupRecord; + + if ( ACCESS_Frame( count * 4L ) ) + goto Fail1; + + for ( n = 0; n < count; n++ ) + { + slr[n].SequenceIndex = GET_UShort(); + slr[n].LookupListIndex = GET_UShort(); + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail1: + FREE( slr ); + + Fail2: + for ( n = 0; n < lookahead_count; n++ ) + Free_Coverage( &l[n] ); + + FREE( l ); + + Fail3: + for ( n = 0; n < input_count; n++ ) + Free_Coverage( &i[n] ); + + FREE( i ); + + Fail4: + for ( n = 0; n < backtrack_count; n++ ) + Free_Coverage( &b[n] ); + + FREE( b ); + return error; + } + + + static void Free_ChainContext3( TTO_ChainContextSubstFormat3* ccsf3 ) + { + UShort n, count; + + TTO_Coverage* c; + + + FREE( ccsf3->SubstLookupRecord ); + + if ( ccsf3->LookaheadCoverage ) + { + count = ccsf3->LookaheadGlyphCount; + c = ccsf3->LookaheadCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + + if ( ccsf3->InputCoverage ) + { + count = ccsf3->InputGlyphCount; + c = ccsf3->InputCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + + if ( ccsf3->BacktrackCoverage ) + { + count = ccsf3->BacktrackGlyphCount; + c = ccsf3->BacktrackCoverage; + + for ( n = 0; n < count; n++ ) + Free_Coverage( &c[n] ); + + FREE( c ); + } + } + + + /* ChainContextSubst */ + + TT_Error Load_ChainContextSubst( TTO_ChainContextSubst* ccs, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ACCESS_Frame( 2L ) ) + return error; + + ccs->SubstFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( ccs->SubstFormat ) + { + case 1: + return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, input ); + + case 2: + return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, input ); + + case 3: + return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, input ); + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + void Free_ChainContextSubst( TTO_ChainContextSubst* ccs ) + { + switch ( ccs->SubstFormat ) + { + case 1: + Free_ChainContext1( &ccs->ccsf.ccsf1 ); + break; + + case 2: + Free_ChainContext2( &ccs->ccsf.ccsf2 ); + break; + + case 3: + Free_ChainContext3( &ccs->ccsf.ccsf3 ); + break; + } + } + + + static TT_Error Lookup_ChainContextSubst1( + TTO_GSUBHeader* gsub, + TTO_ChainContextSubstFormat1* ccsf1, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + UShort i, j, k, num_csr, curr_pos; + UShort bgc, igc, lgc; + TT_Error error; + UShort* s_in; + + TTO_ChainSubRule* csr; + TTO_ChainSubRule curr_csr; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + error = Coverage_Index( &ccsf1->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + csr = ccsf1->ChainSubRuleSet[index].ChainSubRule; + num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount; + + for ( k = 0; k < num_csr; k++ ) + { + curr_csr = csr[k]; + bgc = curr_csr.BacktrackGlyphCount; + igc = curr_csr.InputGlyphCount; + lgc = curr_csr.LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + continue; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + continue; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + + for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + break; + } + + if ( s_in[j] != curr_csr.Backtrack[i - 1] ) + break; + } + + if ( i != 0 ) + continue; + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != curr_csr.Input[i - 1] ) + break; + } + + if ( i != igc ) + continue; + + /* we are starting to check for lookahead glyphs right after the + last context glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( s_in[j] != curr_csr.Lookahead[i] ) + break; + } + + if ( i == lgc ) + return Do_ContextSubst( gsub, igc, + curr_csr.SubstCount, + curr_csr.SubstLookupRecord, + in, out, + nesting_level ); + } + + return TTO_Err_Not_Covered; + } + + + static TT_Error Lookup_ChainContextSubst2( + TTO_GSUBHeader* gsub, + TTO_ChainContextSubstFormat2* ccsf2, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, property; + TT_Error error; + UShort i, j, k, curr_pos; + UShort bgc, igc, lgc; + UShort known_backtrack_classes, + known_input_classes, + known_lookahead_classes; + + UShort* backtrack_classes; + UShort* input_classes; + UShort* lookahead_classes; + + UShort* s_in; + + UShort* bc; + UShort* ic; + UShort* lc; + + TTO_ChainSubClassSet* cscs; + TTO_ChainSubClassRule ccsr; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + /* Note: The coverage table in format 2 doesn't give an index into + anything. It just lets us know whether or not we need to + do any lookup at all. */ + + error = Coverage_Index( &ccsf2->Coverage, in->string[in->pos], &index ); + if ( error ) + return error; + + if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, UShort ) ) + return error; + known_backtrack_classes = 0; + + if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, UShort ) ) + goto End3; + known_input_classes = 1; + + if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, UShort ) ) + goto End2; + known_lookahead_classes = 0; + + error = Get_Class( &ccsf2->InputClassDef, in->string[in->pos], + &input_classes[0], NULL ); + if ( error ) + goto End1; + + cscs = &ccsf2->ChainSubClassSet[input_classes[0]]; + if ( !cscs ) + { + error = TTO_Err_Invalid_GSUB_SubTable; + goto End1; + } + + for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ ) + { + ccsr = cscs->ChainSubClassRule[k]; + bgc = ccsr.BacktrackGlyphCount; + igc = ccsr.InputGlyphCount; + lgc = ccsr.LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + continue; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + continue; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array. + Note that `known_backtrack_classes' starts at index 0. */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + bc = ccsr.Backtrack; + + for ( i = 0, j = in->pos - 1; i < bgc; i++, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + break; + } + + if ( i >= known_backtrack_classes ) + { + /* Keeps us from having to do this for each rule */ + + error = Get_Class( &ccsf2->BacktrackClassDef, s_in[j], + &backtrack_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_backtrack_classes = i; + } + + if ( bc[bgc - 1 - i] != backtrack_classes[i] ) + break; + } + + if ( i != bgc ) + continue; + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + ic = ccsr.Input; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( i >= known_input_classes ) + { + error = Get_Class( &ccsf2->InputClassDef, s_in[j], + &input_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_input_classes = i; + } + + if ( ic[i - 1] != input_classes[i] ) + break; + } + + if ( i != igc ) + continue; + + /* we are starting to check for lookahead glyphs right after the + last context glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + lc = ccsr.Lookahead; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + break; + } + + if ( i >= known_lookahead_classes ) + { + error = Get_Class( &ccsf2->LookaheadClassDef, s_in[j], + &lookahead_classes[i], NULL ); + if ( error && error != TTO_Err_Not_Covered ) + goto End1; + known_lookahead_classes = i; + } + + if ( lc[i] != lookahead_classes[i] ) + break; + } + + if ( i == lgc ) + { + error = Do_ContextSubst( gsub, igc, + ccsr.SubstCount, + ccsr.SubstLookupRecord, + in, out, + nesting_level ); + goto End1; + } + } + + error = TTO_Err_Not_Covered; + + End1: + FREE( lookahead_classes ); + + End2: + FREE( input_classes ); + + End3: + FREE( backtrack_classes ); + return error; + } + + + static TT_Error Lookup_ChainContextSubst3( + TTO_GSUBHeader* gsub, + TTO_ChainContextSubstFormat3* ccsf3, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + UShort index, i, j, curr_pos, property; + UShort bgc, igc, lgc; + TT_Error error; + UShort* s_in; + + TTO_Coverage* bc; + TTO_Coverage* ic; + TTO_Coverage* lc; + TTO_GDEFHeader* gdef; + + + gdef = gsub->gdef; + + if ( CHECK_Property( gdef, in->string[in->pos], flags, &property ) ) + return error; + + bgc = ccsf3->BacktrackGlyphCount; + igc = ccsf3->InputGlyphCount; + lgc = ccsf3->LookaheadGlyphCount; + + if ( context_length != 0xFFFF && context_length < igc ) + return TTO_Err_Not_Covered; + + /* check whether context is too long; it is a first guess only */ + + if ( bgc > in->pos || in->pos + igc + lgc > in->length ) + return TTO_Err_Not_Covered; + + if ( bgc ) + { + /* Since we don't know in advance the number of glyphs to inspect, + we search backwards for matches in the backtrack glyph array */ + + curr_pos = 0; + s_in = &in->string[curr_pos]; + bc = ccsf3->BacktrackCoverage; + + for ( i = bgc, j = in->pos - 1; i > 0; i--, j-- ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( j > curr_pos ) + j--; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &bc[i - 1], s_in[j], &index ); + if ( error ) + return error; + } + } + + curr_pos = in->pos; + s_in = &in->string[curr_pos]; + ic = ccsf3->InputCoverage; + + /* Start at 1 because [0] is implied */ + + for ( i = 1, j = 1; i < igc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &ic[i], s_in[j], &index ); + if ( error ) + return error; + } + + /* we are starting for lookahead glyphs right after the last context + glyph */ + + curr_pos = j; + s_in = &in->string[curr_pos]; + lc = ccsf3->LookaheadCoverage; + + for ( i = 0, j = 0; i < lgc; i++, j++ ) + { + while ( CHECK_Property( gdef, s_in[j], flags, &property ) ) + { + if ( error && error != TTO_Err_Not_Covered ) + return error; + + if ( curr_pos + j < in->length ) + j++; + else + return TTO_Err_Not_Covered; + } + + error = Coverage_Index( &lc[i], s_in[j], &index ); + if ( error ) + return error; + } + + return Do_ContextSubst( gsub, igc, + ccsf3->SubstCount, + ccsf3->SubstLookupRecord, + in, out, + nesting_level ); + } + + + static TT_Error Lookup_ChainContextSubst( + TTO_GSUBHeader* gsub, + TTO_ChainContextSubst* ccs, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort flags, + UShort context_length, + int nesting_level ) + { + switch ( ccs->SubstFormat ) + { + case 1: + return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, in, out, + flags, context_length, + nesting_level ); + + case 2: + return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, in, out, + flags, context_length, + nesting_level ); + + case 3: + return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, in, out, + flags, context_length, + nesting_level ); + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + + /*********** + * GSUB API + ***********/ + + + EXPORT_FUNC + TT_Error TT_GSUB_Select_Script( TTO_GSUBHeader* gsub, + TT_ULong script_tag, + TT_UShort* script_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + + + if ( !gsub || !script_index ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + for ( n = 0; n < sl->ScriptCount; n++ ) + if ( script_tag == sr[n].ScriptTag ) + { + *script_index = n; + + return TT_Err_Ok; + } + + return TTO_Err_Not_Covered; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Select_Language( TTO_GSUBHeader* gsub, + TT_ULong language_tag, + TT_UShort script_index, + TT_UShort* language_index, + TT_UShort* req_feature_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + + + if ( !gsub || !language_index || !req_feature_index ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + for ( n = 0; n < s->LangSysCount; n++ ) + if ( language_tag == lsr[n].LangSysTag ) + { + *language_index = n; + *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; + + return TT_Err_Ok; + } + + return TTO_Err_Not_Covered; + } + + + /* selecting 0xFFFF for language_index asks for the values of the + default language (DefaultLangSys) */ + + EXPORT_FUNC + TT_Error TT_GSUB_Select_Feature( TTO_GSUBHeader* gsub, + TT_ULong feature_tag, + TT_UShort script_index, + TT_UShort language_index, + TT_UShort* feature_index ) + { + UShort n; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + TTO_LangSys* ls; + UShort* fi; + + TTO_FeatureList* fl; + TTO_FeatureRecord* fr; + + + if ( !gsub || !feature_index ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + fl = &gsub->FeatureList; + fr = fl->FeatureRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( language_index == 0xFFFF ) + ls = &s->DefaultLangSys; + else + { + if ( language_index >= s->LangSysCount ) + return TT_Err_Invalid_Argument; + + ls = &lsr[language_index].LangSys; + } + + fi = ls->FeatureIndex; + + for ( n = 0; n < ls->FeatureCount; n++ ) + { + if ( fi[n] >= fl->FeatureCount ) + return TTO_Err_Invalid_GSUB_SubTable_Format; + + if ( feature_tag == fr[fi[n]].FeatureTag ) + { + *feature_index = fi[n]; + + return TT_Err_Ok; + } + } + + return TTO_Err_Not_Covered; + } + + + /* The next three functions return a null-terminated list */ + + EXPORT_FUNC + TT_Error TT_GSUB_Query_Scripts( TTO_GSUBHeader* gsub, + TT_ULong** script_tag_list ) + { + UShort n; + TT_Error error; + ULong* stl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + + + if ( !gsub || !script_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, ULong ) ) + return error; + + for ( n = 0; n < sl->ScriptCount; n++ ) + stl[n] = sr[n].ScriptTag; + stl[n] = 0; + + *script_tag_list = stl; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Query_Languages( TTO_GSUBHeader* gsub, + TT_UShort script_index, + TT_ULong** language_tag_list ) + { + UShort n; + TT_Error error; + ULong* ltl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + + + if ( !gsub || !language_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, ULong ) ) + return error; + + for ( n = 0; n < s->LangSysCount; n++ ) + ltl[n] = lsr[n].LangSysTag; + ltl[n] = 0; + + *language_tag_list = ltl; + + return TT_Err_Ok; + } + + + /* selecting 0xFFFF for language_index asks for the values of the + default language (DefaultLangSys) */ + + EXPORT_FUNC + TT_Error TT_GSUB_Query_Features( TTO_GSUBHeader* gsub, + TT_UShort script_index, + TT_UShort language_index, + TT_ULong** feature_tag_list ) + { + UShort n; + TT_Error error; + ULong* ftl; + + TTO_ScriptList* sl; + TTO_ScriptRecord* sr; + TTO_Script* s; + TTO_LangSysRecord* lsr; + TTO_LangSys* ls; + UShort* fi; + + TTO_FeatureList* fl; + TTO_FeatureRecord* fr; + + + if ( !gsub || !feature_tag_list ) + return TT_Err_Invalid_Argument; + + sl = &gsub->ScriptList; + sr = sl->ScriptRecord; + + fl = &gsub->FeatureList; + fr = fl->FeatureRecord; + + if ( script_index >= sl->ScriptCount ) + return TT_Err_Invalid_Argument; + + s = &sr[script_index].Script; + lsr = s->LangSysRecord; + + if ( language_index == 0xFFFF ) + ls = &s->DefaultLangSys; + else + { + if ( language_index >= s->LangSysCount ) + return TT_Err_Invalid_Argument; + + ls = &lsr[language_index].LangSys; + } + + fi = ls->FeatureIndex; + + if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, ULong ) ) + return error; + + for ( n = 0; n < ls->FeatureCount; n++ ) + { + if ( fi[n] >= fl->FeatureCount ) + { + FREE( ftl ); + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + ftl[n] = fr[fi[n]].FeatureTag; + } + ftl[n] = 0; + + *feature_tag_list = ftl; + + return TT_Err_Ok; + } + + + /* Do an individual subtable lookup. Returns TT_Err_Ok if substitution + has been done, or TTO_Err_Not_Covered if not. */ + + static TT_Error Do_Glyph_Lookup( TTO_GSUBHeader* gsub, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GSUB_String* out, + UShort context_length, + int nesting_level ) + { + TT_Error error = TT_Err_Ok; + UShort i, flags; + TTO_Lookup* lo; + + + nesting_level++; + + if ( nesting_level > TTO_MAX_NESTING_LEVEL ) + return TTO_Err_Too_Many_Nested_Contexts; + + lo = &gsub->LookupList.Lookup[lookup_index]; + flags = lo->LookupFlag; + + for ( i = 0; i < lo->SubTableCount; i++ ) + { + switch ( lo->LookupType ) + { + case GSUB_LOOKUP_SINGLE: + error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single, + in, out, + flags, context_length, gsub->gdef ); + break; + + case GSUB_LOOKUP_MULTIPLE: + error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple, + in, out, + flags, context_length, gsub->gdef ); + break; + + case GSUB_LOOKUP_ALTERNATE: + error = Lookup_AlternateSubst( gsub, + &lo->SubTable[i].st.gsub.alternate, + in, out, + flags, context_length, gsub->gdef ); + break; + + case GSUB_LOOKUP_LIGATURE: + error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature, + in, out, + flags, context_length, gsub->gdef ); + break; + + case GSUB_LOOKUP_CONTEXT: + error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context, + in, out, + flags, context_length, nesting_level ); + break; + + case GSUB_LOOKUP_CHAIN: + error = Lookup_ChainContextSubst( gsub, + &lo->SubTable[i].st.gsub.chain, + in, out, + flags, context_length, + nesting_level ); + break; + } + + /* Check whether we have a successful substitution or an error other + than TTO_Err_Not_Covered */ + + if ( error != TTO_Err_Not_Covered ) + return error; + } + + return TTO_Err_Not_Covered; + } + + + /* apply one lookup to the input string object */ + + static TT_Error Do_String_Lookup( TTO_GSUBHeader* gsub, + UShort lookup_index, + TTO_GSUB_String* in, + TTO_GSUB_String* out ) + { + TT_Error error = TTO_Err_Not_Covered; + + UShort* properties = gsub->LookupList.Properties; + UShort* p_in = in->properties; + UShort* s_in = in->string; + + int nesting_level = 0; + + + while ( in->pos < in->length ) + { + if ( ~p_in[in->pos] & properties[lookup_index] ) + { + /* 0xFFFF indicates that we don't have a context length yet */ + error = Do_Glyph_Lookup( gsub, lookup_index, in, out, + 0xFFFF, nesting_level ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + } + else + error = TTO_Err_Not_Covered; + + if ( error == TTO_Err_Not_Covered ) + if ( ADD_String( in, 1, out, 1, &s_in[in->pos], 0xFFFF, 0xFFFF ) ) + return error; + } + + return error; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Add_Feature( TTO_GSUBHeader* gsub, + TT_UShort feature_index, + TT_UShort property ) + { + UShort i; + + TTO_Feature feature; + UShort* properties; + UShort* index; + + + if ( !gsub || + feature_index >= gsub->FeatureList.FeatureCount ) + return TT_Err_Invalid_Argument; + + properties = gsub->LookupList.Properties; + + feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; + index = feature.LookupListIndex; + + for ( i = 0; i < feature.LookupListCount; i++ ) + properties[index[i]] |= property; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Clear_Features( TTO_GSUBHeader* gsub ) + { + UShort i; + + UShort* properties; + + + if ( !gsub ) + return TT_Err_Invalid_Argument; + + properties = gsub->LookupList.Properties; + + for ( i = 0; i < gsub->LookupList.LookupCount; i++ ) + properties[i] = 0; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Register_Alternate_Function( TTO_GSUBHeader* gsub, + TTO_AltFunction altfunc, + void* data ) + { + if ( !gsub ) + return TT_Err_Invalid_Argument; + + gsub->altfunc = altfunc; + gsub->data = data; + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub, + TTO_GSUB_String* in, + TTO_GSUB_String* out ) + { + TT_Error error = TTO_Err_Not_Covered; + UShort j; + + TTO_GSUB_String tmp1; + TTO_GSUB_String* ptmp1; + TTO_GSUB_String tmp2; + TTO_GSUB_String* ptmp2; + TTO_GSUB_String* t; + + UShort* properties; + + + if ( !gsub || + !in || !out || in->length == 0 || in->pos >= in->length ) + return TT_Err_Invalid_Argument; + + properties = gsub->LookupList.Properties; + + tmp1.length = in->length; + tmp1.allocated = in->length; + tmp1.pos = in->pos; + tmp1.max_ligID = 1; + + if ( ALLOC_ARRAY( tmp1.string, tmp1.length, UShort ) ) + return error; + MEM_Copy( tmp1.string, in->string, in->length * sizeof ( UShort ) ); + + /* make sure that we always have a `properties', `components', and + `ligIDs' array in the string object */ + + if ( ALLOC_ARRAY( tmp1.components, tmp1.length, UShort ) ) + return error; + if ( ALLOC_ARRAY( tmp1.ligIDs, tmp1.length, UShort ) ) + return error; + if ( ALLOC_ARRAY( tmp1.properties, tmp1.length, UShort ) ) + return error; + if ( in->properties ) + MEM_Copy( tmp1.properties, in->properties, + in->length * sizeof( UShort ) ); + + tmp2.allocated = 0; + tmp2.pos = 0; + tmp2.string = NULL; + tmp2.properties = NULL; + tmp2.components = NULL; + tmp2.ligIDs = NULL; + + ptmp1 = &tmp1; + ptmp2 = &tmp2; + + for ( j = 0; j < gsub->LookupList.LookupCount; j++ ) + if ( properties[j] ) + { + error = Do_String_Lookup( gsub, j, ptmp1, ptmp2 ); + if ( error && error != TTO_Err_Not_Covered ) + return error; + + /* flipping `in' and `out', preparing the next loop */ + + ptmp1->pos = in->pos; + ptmp2->length = ptmp2->pos; + ptmp2->pos = in->pos; + ptmp2->max_ligID = ptmp1->max_ligID; + + t = ptmp2; + ptmp2 = ptmp1; + ptmp1 = t; + } + + out->length = ptmp1->length; + out->pos = 0; + out->allocated = ptmp1->allocated; + out->string = ptmp1->string; + out->components = ptmp1->components; + out->ligIDs = ptmp1->ligIDs; + + if ( in->properties ) + out->properties = ptmp1->properties; + else + { + FREE( ptmp1->properties ); + out->properties = NULL; + } + + FREE( ptmp2->string ); + FREE( ptmp2->properties ); + FREE( ptmp2->components ); + FREE( ptmp2->ligIDs ); + + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxgsub.h b/Build/source/libs/libttf/extend/ftxgsub.h new file mode 100644 index 00000000000..463cd27240a --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxgsub.h @@ -0,0 +1,592 @@ +/******************************************************************* + * + * ftxgsub.h + * + * TrueType Open GSUB table support + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FTXOPEN_H +#error "Don't include this file! Use ftxopen.h instead." +#endif + +#ifndef FTXGSUB_H +#define FTXGSUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define TTO_Err_Invalid_GSUB_SubTable_Format 0x1010 +#define TTO_Err_Invalid_GSUB_SubTable 0x1011 + + +/* Lookup types for glyph substitution */ + +#define GSUB_LOOKUP_SINGLE 1 +#define GSUB_LOOKUP_MULTIPLE 2 +#define GSUB_LOOKUP_ALTERNATE 3 +#define GSUB_LOOKUP_LIGATURE 4 +#define GSUB_LOOKUP_CONTEXT 5 +#define GSUB_LOOKUP_CHAIN 6 + + +/* Use this if a feature applies to all glyphs */ + +#define ALL_GLYPHS 0xFFFF + + + /* A pointer to a function which selects the alternate glyph. `pos' is + the position of the glyph with index `glyphID', `num_alternates' + gives the number of alternates in the `alternates' array. `data' + points to the user-defined structure specified during a call to + TT_GSUB_Register_Alternate_Function(). The function must return an + index into the `alternates' array. */ + + typedef TT_UShort (*TTO_AltFunction)(TT_ULong pos, + TT_UShort glyphID, + TT_UShort num_alternates, + TT_UShort* alternates, + void* data ); + + + struct TTO_GSUBHeader_ + { + TT_Bool loaded; + TT_ULong offset; + + TT_Fixed Version; + + TTO_ScriptList ScriptList; + TTO_FeatureList FeatureList; + TTO_LookupList LookupList; + + TTO_GDEFHeader* gdef; + + /* the next two fields are used for an alternate substitution callback + function to select the proper alternate glyph. */ + + TTO_AltFunction altfunc; + void* data; + }; + + typedef struct TTO_GSUBHeader_ TTO_GSUBHeader; + + + /* LookupType 1 */ + + struct TTO_SingleSubstFormat1_ + { + TT_Short DeltaGlyphID; /* constant added to get + substitution glyph index */ + }; + + typedef struct TTO_SingleSubstFormat1_ TTO_SingleSubstFormat1; + + + struct TTO_SingleSubstFormat2_ + { + TT_UShort GlyphCount; /* number of glyph IDs in + Substitute array */ + TT_UShort* Substitute; /* array of substitute glyph IDs */ + }; + + typedef struct TTO_SingleSubstFormat2_ TTO_SingleSubstFormat2; + + + struct TTO_SingleSubst_ + { + TT_UShort SubstFormat; /* 1 or 2 */ + TTO_Coverage Coverage; /* Coverage table */ + + union + { + TTO_SingleSubstFormat1 ssf1; + TTO_SingleSubstFormat2 ssf2; + } ssf; + }; + + typedef struct TTO_SingleSubst_ TTO_SingleSubst; + + + /* LookupType 2 */ + + struct TTO_Sequence_ + { + TT_UShort GlyphCount; /* number of glyph IDs in the + Substitute array */ + TT_UShort* Substitute; /* string of glyph IDs to + substitute */ + }; + + typedef struct TTO_Sequence_ TTO_Sequence; + + + struct TTO_MultipleSubst_ + { + TT_UShort SubstFormat; /* always 1 */ + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort SequenceCount; /* number of Sequence tables */ + TTO_Sequence* Sequence; /* array of Sequence tables */ + }; + + typedef struct TTO_MultipleSubst_ TTO_MultipleSubst; + + + /* LookupType 3 */ + + struct TTO_AlternateSet_ + { + TT_UShort GlyphCount; /* number of glyph IDs in the + Alternate array */ + TT_UShort* Alternate; /* array of alternate glyph IDs */ + }; + + typedef struct TTO_AlternateSet_ TTO_AlternateSet; + + + struct TTO_AlternateSubst_ + { + TT_UShort SubstFormat; /* always 1 */ + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort AlternateSetCount; + /* number of AlternateSet tables */ + TTO_AlternateSet* AlternateSet; /* array of AlternateSet tables */ + }; + + typedef struct TTO_AlternateSubst_ TTO_AlternateSubst; + + + /* LookupType 4 */ + + struct TTO_Ligature_ + { + TT_UShort LigGlyph; /* glyphID of ligature + to substitute */ + TT_UShort ComponentCount; /* number of components in ligature */ + TT_UShort* Component; /* array of component glyph IDs */ + }; + + typedef struct TTO_Ligature_ TTO_Ligature; + + + struct TTO_LigatureSet_ + { + TT_UShort LigatureCount; /* number of Ligature tables */ + TTO_Ligature* Ligature; /* array of Ligature tables */ + }; + + typedef struct TTO_LigatureSet_ TTO_LigatureSet; + + + struct TTO_LigatureSubst_ + { + TT_UShort SubstFormat; /* always 1 */ + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort LigatureSetCount; /* number of LigatureSet tables */ + TTO_LigatureSet* LigatureSet; /* array of LigatureSet tables */ + }; + + typedef struct TTO_LigatureSubst_ TTO_LigatureSubst; + + + /* needed by both lookup type 5 and 6 */ + + struct TTO_SubstLookupRecord_ + { + TT_UShort SequenceIndex; /* index into current + glyph sequence */ + TT_UShort LookupListIndex; /* Lookup to apply to that pos. */ + }; + + typedef struct TTO_SubstLookupRecord_ TTO_SubstLookupRecord; + + + /* LookupType 5 */ + + struct TTO_SubRule_ + { + TT_UShort GlyphCount; /* total number of input glyphs */ + TT_UShort SubstCount; /* number of SubstLookupRecord + tables */ + TT_UShort* Input; /* array of input glyph IDs */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of SubstLookupRecord + tables */ + }; + + typedef struct TTO_SubRule_ TTO_SubRule; + + + struct TTO_SubRuleSet_ + { + TT_UShort SubRuleCount; /* number of SubRule tables */ + TTO_SubRule* SubRule; /* array of SubRule tables */ + }; + + typedef struct TTO_SubRuleSet_ TTO_SubRuleSet; + + + struct TTO_ContextSubstFormat1_ + { + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort SubRuleSetCount; /* number of SubRuleSet tables */ + TTO_SubRuleSet* SubRuleSet; /* array of SubRuleSet tables */ + }; + + typedef struct TTO_ContextSubstFormat1_ TTO_ContextSubstFormat1; + + + struct TTO_SubClassRule_ + { + TT_UShort GlyphCount; /* total number of context classes */ + TT_UShort SubstCount; /* number of SubstLookupRecord + tables */ + TT_UShort* Class; /* array of classes */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of SubstLookupRecord + tables */ + }; + + typedef struct TTO_SubClassRule_ TTO_SubClassRule; + + + struct TTO_SubClassSet_ + { + TT_UShort SubClassRuleCount; + /* number of SubClassRule tables */ + TTO_SubClassRule* SubClassRule; /* array of SubClassRule tables */ + }; + + typedef struct TTO_SubClassSet_ TTO_SubClassSet; + + + /* The `MaxContextLength' field is not defined in the TTO specification + but simplifies the implementation of this format. It holds the + maximal context length used in the context rules. */ + + struct TTO_ContextSubstFormat2_ + { + TT_UShort MaxContextLength; + /* maximal context length */ + TTO_Coverage Coverage; /* Coverage table */ + TTO_ClassDefinition ClassDef; /* ClassDef table */ + TT_UShort SubClassSetCount; + /* number of SubClassSet tables */ + TTO_SubClassSet* SubClassSet; /* array of SubClassSet tables */ + }; + + typedef struct TTO_ContextSubstFormat2_ TTO_ContextSubstFormat2; + + + struct TTO_ContextSubstFormat3_ + { + TT_UShort GlyphCount; /* number of input glyphs */ + TT_UShort SubstCount; /* number of SubstLookupRecords */ + TTO_Coverage* Coverage; /* array of Coverage tables */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of substitution lookups */ + }; + + typedef struct TTO_ContextSubstFormat3_ TTO_ContextSubstFormat3; + + + struct TTO_ContextSubst_ + { + TT_UShort SubstFormat; /* 1, 2, or 3 */ + + union + { + TTO_ContextSubstFormat1 csf1; + TTO_ContextSubstFormat2 csf2; + TTO_ContextSubstFormat3 csf3; + } csf; + }; + + typedef struct TTO_ContextSubst_ TTO_ContextSubst; + + + /* LookupType 6 */ + + struct TTO_ChainSubRule_ + { + TT_UShort BacktrackGlyphCount; + /* total number of backtrack glyphs */ + TT_UShort* Backtrack; /* array of backtrack glyph IDs */ + TT_UShort InputGlyphCount; + /* total number of input glyphs */ + TT_UShort* Input; /* array of input glyph IDs */ + TT_UShort LookaheadGlyphCount; + /* total number of lookahead glyphs */ + TT_UShort* Lookahead; /* array of lookahead glyph IDs */ + TT_UShort SubstCount; /* number of SubstLookupRecords */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of SubstLookupRecords */ + }; + + typedef struct TTO_ChainSubRule_ TTO_ChainSubRule; + + + struct TTO_ChainSubRuleSet_ + { + TT_UShort ChainSubRuleCount; + /* number of ChainSubRule tables */ + TTO_ChainSubRule* ChainSubRule; /* array of ChainSubRule tables */ + }; + + typedef struct TTO_ChainSubRuleSet_ TTO_ChainSubRuleSet; + + + struct TTO_ChainContextSubstFormat1_ + { + TTO_Coverage Coverage; /* Coverage table */ + TT_UShort ChainSubRuleSetCount; + /* number of ChainSubRuleSet tables */ + TTO_ChainSubRuleSet* ChainSubRuleSet; + /* array of ChainSubRuleSet tables */ + }; + + typedef struct TTO_ChainContextSubstFormat1_ TTO_ChainContextSubstFormat1; + + + struct TTO_ChainSubClassRule_ + { + TT_UShort BacktrackGlyphCount; + /* total number of backtrack + classes */ + TT_UShort* Backtrack; /* array of backtrack classes */ + TT_UShort InputGlyphCount; + /* total number of context classes */ + TT_UShort* Input; /* array of context classes */ + TT_UShort LookaheadGlyphCount; + /* total number of lookahead + classes */ + TT_UShort* Lookahead; /* array of lookahead classes */ + TT_UShort SubstCount; /* number of SubstLookupRecords */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of substitution lookups */ + }; + + typedef struct TTO_ChainSubClassRule_ TTO_ChainSubClassRule; + + + struct TTO_ChainSubClassSet_ + { + TT_UShort ChainSubClassRuleCount; + /* number of ChainSubClassRule + tables */ + TTO_ChainSubClassRule* ChainSubClassRule; + /* array of ChainSubClassRule + tables */ + }; + + typedef struct TTO_ChainSubClassSet_ TTO_ChainSubClassSet; + + + /* The `MaxXXXLength' fields are not defined in the TTO specification + but simplifies the implementation of this format. It holds the + maximal context length used in the specific context rules. */ + + struct TTO_ChainContextSubstFormat2_ + { + TTO_Coverage Coverage; /* Coverage table */ + + TT_UShort MaxBacktrackLength; + /* maximal backtrack length */ + TTO_ClassDefinition BacktrackClassDef; + /* BacktrackClassDef table */ + TT_UShort MaxInputLength; + /* maximal input length */ + TTO_ClassDefinition InputClassDef; + /* InputClassDef table */ + TT_UShort MaxLookaheadLength; + /* maximal lookahead length */ + TTO_ClassDefinition LookaheadClassDef; + /* LookaheadClassDef table */ + + TT_UShort ChainSubClassSetCount; + /* number of ChainSubClassSet + tables */ + TTO_ChainSubClassSet* ChainSubClassSet; + /* array of ChainSubClassSet + tables */ + }; + + typedef struct TTO_ChainContextSubstFormat2_ TTO_ChainContextSubstFormat2; + + + struct TTO_ChainContextSubstFormat3_ + { + TT_UShort BacktrackGlyphCount; + /* number of backtrack glyphs */ + TTO_Coverage* BacktrackCoverage; + /* array of backtrack Coverage + tables */ + TT_UShort InputGlyphCount; + /* number of input glyphs */ + TTO_Coverage* InputCoverage; + /* array of input coverage + tables */ + TT_UShort LookaheadGlyphCount; + /* number of lookahead glyphs */ + TTO_Coverage* LookaheadCoverage; + /* array of lookahead coverage + tables */ + TT_UShort SubstCount; /* number of SubstLookupRecords */ + TTO_SubstLookupRecord* SubstLookupRecord; + /* array of substitution lookups */ + }; + + typedef struct TTO_ChainContextSubstFormat3_ TTO_ChainContextSubstFormat3; + + + struct TTO_ChainContextSubst_ + { + TT_UShort SubstFormat; /* 1, 2, or 3 */ + + union + { + TTO_ChainContextSubstFormat1 ccsf1; + TTO_ChainContextSubstFormat2 ccsf2; + TTO_ChainContextSubstFormat3 ccsf3; + } ccsf; + }; + + typedef struct TTO_ChainContextSubst_ TTO_ChainContextSubst; + + + union TTO_GSUB_SubTable_ + { + TTO_SingleSubst single; + TTO_MultipleSubst multiple; + TTO_AlternateSubst alternate; + TTO_LigatureSubst ligature; + TTO_ContextSubst context; + TTO_ChainContextSubst chain; + }; + + typedef union TTO_GSUB_SubTable_ TTO_GSUB_SubTable; + + + /* A simple string object. It can both `send' and `receive' data. + In case of sending, `length' and `pos' will be used. In case of + receiving, `pos' points to the first free slot, and `allocated' + specifies the amount of allocated memory (and the `length' field + will be ignored). The routine TT_Add_String() will increase the + amount of memory if necessary. After end of receive, `length' + should be set to the value of `pos', and `pos' will be set to zero. + + `properties' (which is treated as a bit field) gives the glyph's + properties: If a certain bit is set for a glyph, the feature which + has the same bit set in its property value is applied. + + `components' is an internal array which tracks components of + ligatures. We need this for MarkToLigature Attachment Positioning + Subtables (in GPOS) together with `ligIDs' (which is used to mark + ligatures and the skipped glyphs during a ligature lookup). + `max_ligID' is increased after a successful ligature lookup. + + NEVER modify any elements of the structure! You should rather copy + its contents if necessary. + + TT_Add_String() will also handle allocation; you should use + free() in case you want to destroy the arrays in the object. */ + + struct TTO_GSUB_String_ + { + TT_ULong length; + TT_ULong pos; + TT_ULong allocated; + TT_UShort* string; + TT_UShort* properties; + TT_UShort* components; + TT_UShort max_ligID; + TT_UShort* ligIDs; + }; + + typedef struct TTO_GSUB_String_ TTO_GSUB_String; + + + /* finally, the GSUB API */ + + EXPORT_DEF + TT_Error TT_Init_GSUB_Extension( TT_Engine engine ); + + EXPORT_DEF + TT_Error TT_Load_GSUB_Table( TT_Face face, + TTO_GSUBHeader* gsub, + TTO_GDEFHeader* gdef ); + + EXPORT_DEF + TT_Error TT_GSUB_Select_Script( TTO_GSUBHeader* gsub, + TT_ULong script_tag, + TT_UShort* script_index ); + EXPORT_DEF + TT_Error TT_GSUB_Select_Language( TTO_GSUBHeader* gsub, + TT_ULong language_tag, + TT_UShort script_index, + TT_UShort* language_index, + TT_UShort* req_feature_index ); + EXPORT_DEF + TT_Error TT_GSUB_Select_Feature( TTO_GSUBHeader* gsub, + TT_ULong feature_tag, + TT_UShort script_index, + TT_UShort language_index, + TT_UShort* feature_index ); + + EXPORT_DEF + TT_Error TT_GSUB_Query_Scripts( TTO_GSUBHeader* gsub, + TT_ULong** script_tag_list ); + EXPORT_DEF + TT_Error TT_GSUB_Query_Languages( TTO_GSUBHeader* gsub, + TT_UShort script_index, + TT_ULong** language_tag_list ); + EXPORT_DEF + TT_Error TT_GSUB_Query_Features( TTO_GSUBHeader* gsub, + TT_UShort script_index, + TT_UShort language_index, + TT_ULong** feature_tag_list ); + + EXPORT_DEF + TT_Error TT_GSUB_Add_Feature( TTO_GSUBHeader* gsub, + TT_UShort feature_index, + TT_UShort property ); + EXPORT_DEF + TT_Error TT_GSUB_Clear_Features( TTO_GSUBHeader* gsub ); + + EXPORT_DEF + TT_Error TT_GSUB_Register_Alternate_Function( TTO_GSUBHeader* gsub, + TTO_AltFunction altfunc, + void* data ); + + EXPORT_DEF + TT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub, + TTO_GSUB_String* in, + TTO_GSUB_String* out ); + + EXPORT_DEF + TT_Error TT_GSUB_Add_String( TTO_GSUB_String* in, + TT_UShort num_in, + TTO_GSUB_String* out, + TT_UShort num_out, + TT_UShort* glyph_data, + TT_UShort component, + TT_UShort ligID ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXGSUB_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxkern.c b/Build/source/libs/libttf/extend/ftxkern.c new file mode 100644 index 00000000000..94e10822816 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxkern.c @@ -0,0 +1,603 @@ +/******************************************************************* + * + * ftxkern.c 1.0 + * + * Kerning support extension. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The kerning support is currently part of the engine extensions. + * + ******************************************************************/ + +#include "ttconfig.h" +#include "ftxkern.h" + +#include "ttextend.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttmemory.h" +#include "ttfile.h" +#include "ttobjs.h" +#include "ttload.h" /* For the macros */ +#include "tttags.h" + +#include <stdlib.h> /* for qsort */ + +/* Required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_any + +#define KERNING_ID Build_Extension_ID( 'k', 'e', 'r', 'n' ) + +#undef KERN_INDEX +#define KERN_INDEX(g1,g2) (((TT_ULong)g1 << 16) | g2) + + /* compare two kerning pairs, for qsort() */ + static + int __cdecl compare_kern_pairs( const void* a, const void* b ) + { + TT_Kern_0_Pair* pair1 = (TT_Kern_0_Pair*)a; + TT_Kern_0_Pair* pair2 = (TT_Kern_0_Pair*)b; + + TT_ULong index1 = KERN_INDEX( pair1->left, pair1->right ); + TT_ULong index2 = KERN_INDEX( pair2->left, pair2->right ); + + return ( index1 < index2 ? -1 : + ( index1 > index2 ? 1 : 0 )); + } + + /* check whether the kern table is sorted */ + static + int is_sorted( TT_Kern_0_Pair* table, TT_ULong num_pairs ) + { + TT_ULong i; + + for ( i=1; i<num_pairs; i++ ) + { + if ( compare_kern_pairs(&table[i-1], &table[i]) != -1 ) + return 0; + } + return 1; + } + + +/******************************************************************* + * + * Function : SubTable_Load_0 + * + * Description : Loads a format 0 kerning subtable data. + * + * Input : kern0 pointer to the kerning subtable + * + * Output : error code + * + * Notes : - Assumes that the stream is already `used' + * + * - the file cursor must be set by the caller + * + * - in case of error, the function _must_ destroy + * the data it allocates! + * + ******************************************************************/ + + static TT_Error Subtable_Load_0( TT_Kern_0* kern0, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort num_pairs, n; + + + if ( ACCESS_Frame( 8L ) ) + return error; + + num_pairs = GET_UShort(); + kern0->nPairs = 0; + kern0->searchRange = GET_UShort(); + kern0->entrySelector = GET_UShort(); + kern0->rangeShift = GET_UShort(); + + /* we only set kern0->nPairs if the subtable has been loaded */ + + FORGET_Frame(); + + if ( ALLOC_ARRAY( kern0->pairs, num_pairs, TT_Kern_0_Pair ) ) + return error; + + if ( ACCESS_Frame( num_pairs * 6L ) ) + goto Fail; + + for ( n = 0; n < num_pairs; n++ ) + { + kern0->pairs[n].left = GET_UShort(); + kern0->pairs[n].right = GET_UShort(); + kern0->pairs[n].value = GET_UShort(); + + if ( kern0->pairs[n].left >= input->numGlyphs || + kern0->pairs[n].right >= input->numGlyphs ) + { + FORGET_Frame(); + error = TT_Err_Invalid_Kerning_Table; + goto Fail; + } + } + + FORGET_Frame(); + + /* we're ok, set the pairs count */ + kern0->nPairs = num_pairs; + + /* the spec says that the kerning pairs must be sorted, + but some brain damaged font producers don't do that correctly.. (JvR 3/4/2000) */ + if ( !is_sorted( kern0->pairs, num_pairs ) ) + qsort( kern0->pairs, num_pairs, sizeof(TT_Kern_0_Pair), compare_kern_pairs ); + + return TT_Err_Ok; + + Fail: + FREE( kern0->pairs ); + return error; + } + + +/******************************************************************* + * + * Function : SubTable_Load_2 + * + * Description : Loads a format 2 kerning subtable data. + * + * Input : kern2 pointer to the kerning subtable + * length subtable length. This is required as + * the subheader doesn't give any indication + * of the size of the `array' table. + * + * Output : error code + * + * Notes : - Assumes that the stream is already `used' + * + * - the file cursor must be set by the caller + * + * - in case of error, the function _must_ destroy + * the data it allocates! + * + ******************************************************************/ + + static TT_Error Subtable_Load_2( TT_Kern_2* kern2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + Long table_base; + + UShort left_offset, right_offset, array_offset; + ULong array_size; + UShort left_max, right_max, n; + + + /* record the table offset */ + table_base = FILE_Pos(); + + if ( ACCESS_Frame( 8L ) ) + return error; + + kern2->rowWidth = GET_UShort(); + left_offset = GET_UShort(); + right_offset = GET_UShort(); + array_offset = GET_UShort(); + + FORGET_Frame(); + + /* first load left and right glyph classes */ + + if ( FILE_Seek( table_base + left_offset ) || + ACCESS_Frame( 4L ) ) + return error; + + kern2->leftClass.firstGlyph = GET_UShort(); + kern2->leftClass.nGlyphs = GET_UShort(); + + FORGET_Frame(); + + if ( ALLOC_ARRAY( kern2->leftClass.classes, + kern2->leftClass.nGlyphs, + UShort ) ) + return error; + + /* load left offsets */ + + if ( ACCESS_Frame( kern2->leftClass.nGlyphs * 2L ) ) + goto Fail_Left; + + for ( n = 0; n < kern2->leftClass.nGlyphs; n++ ) + kern2->leftClass.classes[n] = GET_UShort(); + + FORGET_Frame(); + + /* right class */ + + if ( FILE_Seek( table_base + right_offset ) || + ACCESS_Frame( 4L ) ) + goto Fail_Left; + + kern2->rightClass.firstGlyph = GET_UShort(); + kern2->rightClass.nGlyphs = GET_UShort(); + + FORGET_Frame(); + + if ( ALLOC_ARRAY( kern2->rightClass.classes, + kern2->rightClass.nGlyphs, + UShort ) ) + goto Fail_Left; + + /* load right offsets */ + + if ( ACCESS_Frame( kern2->rightClass.nGlyphs * 2L ) ) + goto Fail_Right; + + for ( n = 0; n < kern2->rightClass.nGlyphs; n++ ) + kern2->rightClass.classes[n] = GET_UShort(); + + FORGET_Frame(); + + /* Now load the kerning array. We don't have its size, we */ + /* must compute it from what we know. */ + + /* We thus compute the maximum left and right offsets and */ + /* add them to get the array size. */ + + left_max = right_max = 0; + + for ( n = 0; n < kern2->leftClass.nGlyphs; n++ ) + left_max = MAX( left_max, kern2->leftClass.classes[n] ); + + for ( n = 0; n < kern2->rightClass.nGlyphs; n++ ) + right_max = MAX( right_max, kern2->leftClass.classes[n] ); + + array_size = left_max + right_max + 2; + + if ( ALLOC( kern2->array, array_size ) ) + goto Fail_Right; + + if ( ACCESS_Frame( array_size ) ) + goto Fail_Array; + + for ( n = 0; n < array_size/2; n++ ) + kern2->array[n] = GET_Short(); + + FORGET_Frame(); + + /* we're good now */ + + return TT_Err_Ok; + + Fail_Array: + FREE( kern2->array ); + + Fail_Right: + FREE( kern2->rightClass.classes ); + kern2->rightClass.nGlyphs = 0; + + Fail_Left: + FREE( kern2->leftClass.classes ); + kern2->leftClass.nGlyphs = 0; + + return error; + } + + +/******************************************************************* + * + * Function : Kerning_Create + * + * Description : Creates the kerning directory if a face is + * loaded. The tables however are loaded on + * demand to save space. + * + * Input : face pointer to the parent face object + * kern pointer to the extension's kerning field + * + * Output : error code + * + * Notes : as in all constructors, the memory allocated isn't + * released in case of failure. Rather, the task is left + * to the destructor (which is called if an error + * occurs during the loading of a face). + * + ******************************************************************/ + + static TT_Error Kerning_Create( void* ext, + PFace face ) + { + DEFINE_LOAD_LOCALS( face->stream ); + + TT_Kerning* kern = (TT_Kerning*)ext; + UShort num_tables; + Long table; + + TT_Kern_Subtable* sub; + + + /* by convention */ + if ( !kern ) + return TT_Err_Ok; + + /* Now load the kerning directory. We're called from the face */ + /* constructor. We thus need not use the stream. */ + + kern->version = 0; + kern->nTables = 0; + kern->tables = NULL; + + table = TT_LookUp_Table( face, TTAG_kern ); + if ( table < 0 ) + return TT_Err_Ok; /* The table is optional */ + + if ( FILE_Seek( face->dirTables[table].Offset ) || + ACCESS_Frame( 4L ) ) + return error; + + kern->version = GET_UShort(); + num_tables = GET_UShort(); + + FORGET_Frame(); + + /* we don't set kern->nTables until we have allocated the array */ + + if ( ALLOC_ARRAY( kern->tables, num_tables, TT_Kern_Subtable ) ) + return error; + + kern->nTables = num_tables; + + /* now load the directory entries, but do _not_ load the tables ! */ + + sub = kern->tables; + + for ( table = 0; table < num_tables; table++ ) + { + if ( ACCESS_Frame( 6L ) ) + return error; + + sub->loaded = FALSE; /* redundant, but good to see */ + sub->version = GET_UShort(); + sub->length = GET_UShort() - 6; /* substract header length */ + sub->format = GET_Byte(); + sub->coverage = GET_Byte(); + + FORGET_Frame(); + + sub->offset = FILE_Pos(); + + /* now skip to the next table */ + + if ( FILE_Skip( sub->length ) ) + return error; + + sub++; + } + + /* that's fine, leave now */ + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Kerning_Destroy + * + * Description : Destroys all kerning information. + * + * Input : kern pointer to the extension's kerning field + * + * Output : error code + * + * Notes : This function is a destructor; it must be able + * to destroy partially built tables. + * + ******************************************************************/ + + static TT_Error Kerning_Destroy( void* ext, + PFace face ) + { + TT_Kerning* kern = (TT_Kerning*)ext; + TT_Kern_Subtable* sub; + UShort n; + + + /* by convention */ + if ( !kern ) + return TT_Err_Ok; + + if ( kern->nTables == 0 ) + return TT_Err_Ok; /* no tables to release */ + + /* scan the table directory and release loaded entries */ + + sub = kern->tables; + for ( n = 0; n < kern->nTables; n++ ) + { + if ( sub->loaded ) + { + switch ( sub->format ) + { + case 0: + FREE( sub->t.kern0.pairs ); + sub->t.kern0.nPairs = 0; + sub->t.kern0.searchRange = 0; + sub->t.kern0.entrySelector = 0; + sub->t.kern0.rangeShift = 0; + break; + + case 2: + FREE( sub->t.kern2.leftClass.classes ); + sub->t.kern2.leftClass.firstGlyph = 0; + sub->t.kern2.leftClass.nGlyphs = 0; + + FREE( sub->t.kern2.rightClass.classes ); + sub->t.kern2.rightClass.firstGlyph = 0; + sub->t.kern2.rightClass.nGlyphs = 0; + + FREE( sub->t.kern2.array ); + sub->t.kern2.rowWidth = 0; + break; + + default: + ; /* invalid subtable format - do nothing */ + } + + sub->loaded = FALSE; + sub->version = 0; + sub->offset = 0; + sub->length = 0; + sub->coverage = 0; + sub->format = 0; + } + sub++; + } + + FREE( kern->tables ); + kern->nTables = 0; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Kerning_Directory + * + * Description : Returns a given face's kerning directory. + * + * Input : face handle to the face object + * directory pointer to client's target directory + * + * Output : error code + * + * Notes : The kerning table directory is loaded with the face + * through the extension constructor. However, the kerning + * tables themselves are only loaded on demand, as they + * may represent a lot of data, unneeded by most uses of + * the engine. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Kerning_Directory( TT_Face face, + TT_Kerning* directory ) + { + PFace faze = HANDLE_Face( face ); + TT_Error error; + TT_Kerning* kerning; + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + /* copy directory header */ + error = TT_Extension_Get( faze, KERNING_ID, (void**)&kerning ); + if ( !error ) + *directory = *kerning; + + return error; + } + + +/******************************************************************* + * + * Function : TT_Load_Kerning_Table + * + * Description : Loads a kerning table intro memory. + * + * Input : face face handle + * kern_index index in the face's kerning directory + * + * Output : error code + * + * Notes : + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Load_Kerning_Table( TT_Face face, + TT_UShort kern_index ) + { + TT_Error error; + TT_Stream stream; + + TT_Kerning* kern; + TT_Kern_Subtable* sub; + + + PFace faze = HANDLE_Face( face ); + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + error = TT_Extension_Get( faze, KERNING_ID, (void**)&kern ); + if ( error ) + return error; + + if ( kern->nTables == 0 ) + return TT_Err_Table_Missing; + + if ( kern_index >= kern->nTables ) + return TT_Err_Invalid_Argument; + + sub = kern->tables + kern_index; + + if ( sub->format != 0 && sub->format != 2 ) + return TT_Err_Invalid_Kerning_Table_Format; + + /* now access stream */ + if ( USE_Stream( faze->stream, stream ) ) + return error; + + if ( FILE_Seek( sub->offset ) ) + goto Fail; + + if ( sub->format == 0 ) + error = Subtable_Load_0( &sub->t.kern0, faze ); + else if ( sub->format == 2 ) + error = Subtable_Load_2( &sub->t.kern2, faze ); + + if ( !error ) + sub->loaded = TRUE; + + Fail: + /* release stream */ + DONE_Stream( stream ); + + return error; + } + + + EXPORT_FUNC + TT_Error TT_Init_Kerning_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + error = TT_Register_Extension( _engine, + KERNING_ID, + sizeof ( TT_Kerning ), + Kerning_Create, + Kerning_Destroy ); + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxkern.h b/Build/source/libs/libttf/extend/ftxkern.h new file mode 100644 index 00000000000..06e221e4be0 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxkern.h @@ -0,0 +1,181 @@ +/******************************************************************* + * + * ftxkern.h 1.0 + * + * High-Level API Kerning extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The kerning support is currently part of the engine extensions. + * + * This file should _not_ depend on engine internal types. + * + ******************************************************************/ + +#ifndef FTXKERN_H +#define FTXKERN_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* The kerning support in FreeType is minimal. This means that */ + /* we do not try to interpret the kerning data in any way to */ + /* `cook' it for a user application. This API lets you access */ + /* directly the kerning tables found in the TrueType file; it's */ + /* up to the client application to apply its own processing on */ + /* these. */ + + /* The reason for this is that we generally do not encourage */ + /* feature-bloat of the core engine. Moreover, not all */ + /* libraries or font servers really need kerning data, or all */ + /* formats of this data. */ + + /************** kerning error codes *****************************/ + + /* we choose the class 0x0A for our errors, this should not */ + /* match with any error code class used in any other extension */ + +#define TT_Err_Invalid_Kerning_Table_Format 0x0A00 +#define TT_Err_Invalid_Kerning_Table 0x0A01 + + + /********** structures definitions ******************************/ + + /* Remember that all types and function are accessible by client */ + /* applications in this section, and thus should have the `TT_' */ + /* prefix. */ + + /* format 0 kerning pair */ + + struct TT_Kern_0_Pair_ + { + TT_UShort left; /* index of left glyph in pair */ + TT_UShort right; /* index of right glyph in pair */ + TT_FWord value; /* kerning value */ + }; + + typedef struct TT_Kern_0_Pair_ TT_Kern_0_Pair; + + + /* format 0 kerning subtable */ + + struct TT_Kern_0_ + { + TT_UShort nPairs; /* number of kerning pairs */ + + TT_UShort searchRange; /* these values are defined by the TT spec */ + TT_UShort entrySelector; /* for table searchs. */ + TT_UShort rangeShift; + + TT_Kern_0_Pair* pairs; /* a table of nPairs `pairs' */ + }; + + typedef struct TT_Kern_0_ TT_Kern_0; + + + /* format 2 kerning glyph class */ + + struct TT_Kern_2_Class_ + { + TT_UShort firstGlyph; /* first glyph in range */ + TT_UShort nGlyphs; /* number of glyphs in range */ + TT_UShort* classes; /* a table giving for each ranged glyph */ + /* its class offset in the subtable pairs */ + /* two-dimensional array */ + }; + + typedef struct TT_Kern_2_Class_ TT_Kern_2_Class; + + + /* format 2 kerning subtable */ + + struct TT_Kern_2_ + { + TT_UShort rowWidth; /* length of one row in bytes */ + TT_Kern_2_Class leftClass; /* left class table */ + TT_Kern_2_Class rightClass; /* right class table */ + TT_FWord* array; /* 2-dimensional kerning values array */ + }; + + typedef struct TT_Kern_2_ TT_Kern_2; + + + /* kerning subtable */ + + struct TT_Kern_Subtable_ + { + TT_Bool loaded; /* boolean; indicates whether the table is */ + /* loaded */ + TT_UShort version; /* table version number */ + TT_Long offset; /* file offset of table */ + TT_UShort length; /* length of table, _excluding_ header */ + TT_Byte coverage; /* lower 8 bit of the coverage table entry */ + TT_Byte format; /* the subtable format, as found in the */ + /* higher 8 bits of the coverage table entry */ + union + { + TT_Kern_0 kern0; + TT_Kern_2 kern2; + } t; + }; + + typedef struct TT_Kern_Subtable_ TT_Kern_Subtable; + + + struct TT_Kerning_ + { + TT_UShort version; /* kern table version number. starts at 0 */ + TT_UShort nTables; /* number of tables */ + + TT_Kern_Subtable* tables; /* the kerning sub-tables */ + }; + + typedef struct TT_Kerning_ TT_Kerning; + + + + /***************** high-level API extension **************************/ + + /* Initialize Kerning extension, must be called after */ + /* TT_Init_FreeType(). There is no need for a finalizer */ + EXPORT_DEF + TT_Error TT_Init_Kerning_Extension( TT_Engine engine ); + + /* Note on the implemented mechanism: */ + + /* The kerning table directory is loaded with the face through the */ + /* extension constructor. However, the tables will only be loaded */ + /* on demand, as they may represent a lot of data, unnecessary to */ + /* most applications. */ + + /* Queries a pointer to the kerning directory for the face object */ + EXPORT_DEF + TT_Error TT_Get_Kerning_Directory( TT_Face face, + TT_Kerning* directory ); + + /* Load the kerning table number `kern_index' in the kerning */ + /* directory. The table will stay in memory until the `face' */ + /* face is destroyed. */ + EXPORT_DEF + TT_Error TT_Load_Kerning_Table( TT_Face face, + TT_UShort kern_index ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXKERN_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxopen.c b/Build/source/libs/libttf/extend/ftxopen.c new file mode 100644 index 00000000000..bbf08bd1991 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxopen.c @@ -0,0 +1,1439 @@ +/******************************************************************* + * + * ftxopen.c + * + * TrueType Open common table support. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "tttypes.h" +#include "ttload.h" +#include "ttextend.h" +#include "ttmemory.h" +#include "ttfile.h" + +#include "ftxopen.h" +#include "ftxopenf.h" + + + /*************************** + * Script related functions + ***************************/ + + + /* LangSys */ + + static TT_Error Load_LangSys( TTO_LangSys* ls, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* fi; + + + if ( ACCESS_Frame( 6L ) ) + return error; + + ls->LookupOrderOffset = GET_UShort(); /* should be 0 */ + ls->ReqFeatureIndex = GET_UShort(); + count = ls->FeatureCount = GET_UShort(); + + FORGET_Frame(); + + ls->FeatureIndex = NULL; + + if ( ALLOC_ARRAY( ls->FeatureIndex, count, UShort ) ) + return error; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( ls->FeatureIndex ); + return error; + } + + fi = ls->FeatureIndex; + + for ( n = 0; n < count; n++ ) + fi[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + static void Free_LangSys( TTO_LangSys* ls ) + { + FREE( ls->FeatureIndex ); + } + + + /* Script */ + + static TT_Error Load_Script( TTO_Script* s, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_LangSysRecord* lsr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + if ( new_offset != base_offset ) /* not a NULL offset */ + { + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LangSys( &s->DefaultLangSys, + input ) ) != TT_Err_Ok ) + return error; + (void)FILE_Seek( cur_offset ); + } + else + { + /* we create a DefaultLangSys table with no entries */ + + s->DefaultLangSys.LookupOrderOffset = 0; + s->DefaultLangSys.ReqFeatureIndex = 0xFFFF; + s->DefaultLangSys.FeatureCount = 0; + s->DefaultLangSys.FeatureIndex = NULL; + } + + if ( ACCESS_Frame( 2L ) ) + goto Fail2; + + count = s->LangSysCount = GET_UShort(); + + /* safety check; otherwise the official handling of TrueType Open + fonts won't work */ + + if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 ) + { + error = TTO_Err_Invalid_SubTable; + goto Fail2; + } + + FORGET_Frame(); + + s->LangSysRecord = NULL; + + if ( ALLOC_ARRAY( s->LangSysRecord, count, TTO_LangSysRecord ) ) + goto Fail2; + + lsr = s->LangSysRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 6L ) ) + goto Fail1; + + lsr[n].LangSysTag = GET_ULong(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_LangSys( &lsr[n].LangSys, input ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + for ( n = 0; n < count; n++ ) + Free_LangSys( &lsr[n].LangSys ); + + FREE( s->LangSysRecord ); + + Fail2: + Free_LangSys( &s->DefaultLangSys ); + return error; + } + + + static void Free_Script( TTO_Script* s ) + { + UShort n, count; + + TTO_LangSysRecord* lsr; + + + Free_LangSys( &s->DefaultLangSys ); + + if ( s->LangSysRecord ) + { + count = s->LangSysCount; + lsr = s->LangSysRecord; + + for ( n = 0; n < count; n++ ) + Free_LangSys( &lsr[n].LangSys ); + + FREE( lsr ); + } + } + + + /* ScriptList */ + + TT_Error Load_ScriptList( TTO_ScriptList* sl, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_ScriptRecord* sr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = sl->ScriptCount = GET_UShort(); + + FORGET_Frame(); + + sl->ScriptRecord = NULL; + + if ( ALLOC_ARRAY( sl->ScriptRecord, count, TTO_ScriptRecord ) ) + return error; + + sr = sl->ScriptRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 6L ) ) + goto Fail; + + sr[n].ScriptTag = GET_ULong(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Script( &sr[n].Script, input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_Script( &sr[n].Script ); + + FREE( sl->ScriptRecord ); + return error; + } + + + void Free_ScriptList( TTO_ScriptList* sl ) + { + UShort n, count; + + TTO_ScriptRecord* sr; + + + if ( sl->ScriptRecord ) + { + count = sl->ScriptCount; + sr = sl->ScriptRecord; + + for ( n = 0; n < count; n++ ) + Free_Script( &sr[n].Script ); + + FREE( sr ); + } + } + + + + /********************************* + * Feature List related functions + *********************************/ + + + /* Feature */ + + static TT_Error Load_Feature( TTO_Feature* f, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* lli; + + + if ( ACCESS_Frame( 4L ) ) + return error; + + f->FeatureParams = GET_UShort(); /* should be 0 */ + count = f->LookupListCount = GET_UShort(); + + FORGET_Frame(); + + f->LookupListIndex = NULL; + + if ( ALLOC_ARRAY( f->LookupListIndex, count, UShort ) ) + return error; + + lli = f->LookupListIndex; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( f->LookupListIndex ); + return error; + } + + for ( n = 0; n < count; n++ ) + lli[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + static void Free_Feature( TTO_Feature* f ) + { + FREE( f->LookupListIndex ); + } + + + /* FeatureList */ + + TT_Error Load_FeatureList( TTO_FeatureList* fl, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_FeatureRecord* fr; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = fl->FeatureCount = GET_UShort(); + + FORGET_Frame(); + + fl->FeatureRecord = NULL; + + if ( ALLOC_ARRAY( fl->FeatureRecord, count, TTO_FeatureRecord ) ) + return error; + + fr = fl->FeatureRecord; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 6L ) ) + goto Fail; + + fr[n].FeatureTag = GET_ULong(); + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Feature( &fr[n].Feature, input ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_Feature( &fr[n].Feature ); + + FREE( fl->FeatureRecord ); + return error; + } + + + void Free_FeatureList( TTO_FeatureList* fl ) + { + UShort n, count; + + TTO_FeatureRecord* fr; + + + if ( fl->FeatureRecord ) + { + count = fl->FeatureCount; + fr = fl->FeatureRecord; + + for ( n = 0; n < count; n++ ) + Free_Feature( &fr[n].Feature ); + + FREE( fr ); + } + } + + + + /******************************** + * Lookup List related functions + ********************************/ + + /* the subroutines of the following two functions are defined in + ftxgsub.c and ftxgpos.c respectively */ + + + /* SubTable */ + + static TT_Error Load_SubTable( TTO_SubTable* st, + PFace input, + TTO_Type table_type, + UShort lookup_type ) + { + if ( table_type == GSUB ) + switch ( lookup_type ) + { + case GSUB_LOOKUP_SINGLE: + return Load_SingleSubst( &st->st.gsub.single, input ); + + case GSUB_LOOKUP_MULTIPLE: + return Load_MultipleSubst( &st->st.gsub.multiple, input ); + + case GSUB_LOOKUP_ALTERNATE: + return Load_AlternateSubst( &st->st.gsub.alternate, input ); + + case GSUB_LOOKUP_LIGATURE: + return Load_LigatureSubst( &st->st.gsub.ligature, input ); + + case GSUB_LOOKUP_CONTEXT: + return Load_ContextSubst( &st->st.gsub.context, input ); + + case GSUB_LOOKUP_CHAIN: + return Load_ChainContextSubst( &st->st.gsub.chain, input ); + + default: + return TTO_Err_Invalid_GSUB_SubTable_Format; + } + else + switch ( lookup_type ) + { + case GPOS_LOOKUP_SINGLE: + return Load_SinglePos( &st->st.gpos.single, input ); + + case GPOS_LOOKUP_PAIR: + return Load_PairPos( &st->st.gpos.pair, input ); + + case GPOS_LOOKUP_CURSIVE: + return Load_CursivePos( &st->st.gpos.cursive, input ); + + case GPOS_LOOKUP_MARKBASE: + return Load_MarkBasePos( &st->st.gpos.markbase, input ); + + case GPOS_LOOKUP_MARKLIG: + return Load_MarkLigPos( &st->st.gpos.marklig, input ); + + case GPOS_LOOKUP_MARKMARK: + return Load_MarkMarkPos( &st->st.gpos.markmark, input ); + + case GPOS_LOOKUP_CONTEXT: + return Load_ContextPos( &st->st.gpos.context, input ); + + case GPOS_LOOKUP_CHAIN: + return Load_ChainContextPos( &st->st.gpos.chain, input ); + + default: + return TTO_Err_Invalid_GPOS_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + static void Free_SubTable( TTO_SubTable* st, + TTO_Type table_type, + UShort lookup_type ) + { + if ( table_type == GSUB ) + switch ( lookup_type ) + { + case GSUB_LOOKUP_SINGLE: + Free_SingleSubst( &st->st.gsub.single ); + break; + + case GSUB_LOOKUP_MULTIPLE: + Free_MultipleSubst( &st->st.gsub.multiple ); + break; + + case GSUB_LOOKUP_ALTERNATE: + Free_AlternateSubst( &st->st.gsub.alternate ); + break; + + case GSUB_LOOKUP_LIGATURE: + Free_LigatureSubst( &st->st.gsub.ligature ); + break; + + case GSUB_LOOKUP_CONTEXT: + Free_ContextSubst( &st->st.gsub.context ); + break; + + case GSUB_LOOKUP_CHAIN: + Free_ChainContextSubst( &st->st.gsub.chain ); + break; + } + else + switch ( lookup_type ) + { + case GPOS_LOOKUP_SINGLE: + Free_SinglePos( &st->st.gpos.single ); + break; + + case GPOS_LOOKUP_PAIR: + Free_PairPos( &st->st.gpos.pair ); + break; + + case GPOS_LOOKUP_CURSIVE: + Free_CursivePos( &st->st.gpos.cursive ); + break; + + case GPOS_LOOKUP_MARKBASE: + Free_MarkBasePos( &st->st.gpos.markbase ); + break; + + case GPOS_LOOKUP_MARKLIG: + Free_MarkLigPos( &st->st.gpos.marklig ); + break; + + case GPOS_LOOKUP_MARKMARK: + Free_MarkMarkPos( &st->st.gpos.markmark ); + break; + + case GPOS_LOOKUP_CONTEXT: + Free_ContextPos( &st->st.gpos.context ); + break; + + case GPOS_LOOKUP_CHAIN: + Free_ChainContextPos ( &st->st.gpos.chain ); + break; + } + } + + + /* Lookup */ + + static TT_Error Load_Lookup( TTO_Lookup* l, + PFace input, + TTO_Type type ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_SubTable* st; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 6L ) ) + return error; + + l->LookupType = GET_UShort(); + l->LookupFlag = GET_UShort(); + count = l->SubTableCount = GET_UShort(); + + FORGET_Frame(); + + l->SubTable = NULL; + + if ( ALLOC_ARRAY( l->SubTable, count, TTO_SubTable ) ) + return error; + + st = l->SubTable; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_SubTable( &st[n], input, + type, l->LookupType ) ) != TT_Err_Ok ) + goto Fail; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < count; n++ ) + Free_SubTable( &st[n], type, l->LookupType ); + + FREE( l->SubTable ); + return error; + } + + + static void Free_Lookup( TTO_Lookup* l, + TTO_Type type ) + { + UShort n, count; + + TTO_SubTable* st; + + + if ( l->SubTable ) + { + count = l->SubTableCount; + st = l->SubTable; + + for ( n = 0; n < count; n++ ) + Free_SubTable( &st[n], type, l->LookupType ); + + FREE( st ); + } + } + + + /* LookupList */ + + TT_Error Load_LookupList( TTO_LookupList* ll, + PFace input, + TTO_Type type ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + ULong cur_offset, new_offset, base_offset; + + TTO_Lookup* l; + + + base_offset = FILE_Pos(); + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = ll->LookupCount = GET_UShort(); + + FORGET_Frame(); + + ll->Lookup = NULL; + + if ( ALLOC_ARRAY( ll->Lookup, count, TTO_Lookup ) ) + return error; + if ( ALLOC_ARRAY( ll->Properties, count, UShort ) ) + goto Fail2; + + l = ll->Lookup; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail1; + + new_offset = GET_UShort() + base_offset; + + FORGET_Frame(); + + cur_offset = FILE_Pos(); + if ( FILE_Seek( new_offset ) || + ( error = Load_Lookup( &l[n], input, type ) ) != TT_Err_Ok ) + goto Fail1; + (void)FILE_Seek( cur_offset ); + } + + return TT_Err_Ok; + + Fail1: + FREE( ll->Properties ); + + for ( n = 0; n < count; n++ ) + Free_Lookup( &l[n], type ); + + Fail2: + FREE( ll->Lookup ); + return error; + } + + + void Free_LookupList( TTO_LookupList* ll, + TTO_Type type ) + { + UShort n, count; + + TTO_Lookup* l; + + + FREE( ll->Properties ); + + if ( ll->Lookup ) + { + count = ll->LookupCount; + l = ll->Lookup; + + for ( n = 0; n < count; n++ ) + Free_Lookup( &l[n], type ); + + FREE( l ); + } + } + + + + /***************************** + * Coverage related functions + *****************************/ + + + /* CoverageFormat1 */ + + static TT_Error Load_Coverage1( TTO_CoverageFormat1* cf1, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* ga; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cf1->GlyphCount = GET_UShort(); + + FORGET_Frame(); + + cf1->GlyphArray = NULL; + + if ( ALLOC_ARRAY( cf1->GlyphArray, count, UShort ) ) + return error; + + ga = cf1->GlyphArray; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( cf1->GlyphArray ); + return error; + } + + for ( n = 0; n < count; n++ ) + ga[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + static void Free_Coverage1( TTO_CoverageFormat1* cf1 ) + { + FREE( cf1->GlyphArray ); + } + + + /* CoverageFormat2 */ + + static TT_Error Load_Coverage2( TTO_CoverageFormat2* cf2, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + TTO_RangeRecord* rr; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cf2->RangeCount = GET_UShort(); + + FORGET_Frame(); + + cf2->RangeRecord = NULL; + + if ( ALLOC_ARRAY( cf2->RangeRecord, count, TTO_RangeRecord ) ) + return error; + + rr = cf2->RangeRecord; + + if ( ACCESS_Frame( count * 6L ) ) + goto Fail; + + for ( n = 0; n < count; n++ ) + { + rr[n].Start = GET_UShort(); + rr[n].End = GET_UShort(); + rr[n].StartCoverageIndex = GET_UShort(); + + /* sanity check; we are limited to 16bit integers */ + if ( rr[n].Start > rr[n].End || + ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >= + 0x10000L ) + { + error = TTO_Err_Invalid_SubTable; + goto Fail; + } + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail: + FREE( cf2->RangeRecord ); + return error; + } + + + static void Free_Coverage2( TTO_CoverageFormat2* cf2 ) + { + FREE( cf2->RangeRecord ); + } + + + TT_Error Load_Coverage( TTO_Coverage* c, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ACCESS_Frame( 2L ) ) + return error; + + c->CoverageFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( c->CoverageFormat ) + { + case 1: + return Load_Coverage1( &c->cf.cf1, input ); + + case 2: + return Load_Coverage2( &c->cf.cf2, input ); + + default: + return TTO_Err_Invalid_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + void Free_Coverage( TTO_Coverage* c ) + { + switch ( c->CoverageFormat ) + { + case 1: + Free_Coverage1( &c->cf.cf1 ); + break; + + case 2: + Free_Coverage2( &c->cf.cf2 ); + break; + } + } + + + static TT_Error Coverage_Index1( TTO_CoverageFormat1* cf1, + UShort glyphID, + UShort* index ) + { + UShort min, max, new_min, new_max, middle; + + UShort* array = cf1->GlyphArray; + + + /* binary search */ + + new_min = 0; + new_max = cf1->GlyphCount - 1; + + do + { + min = new_min; + max = new_max; + + /* we use (min + max) / 2 = max - (max - min) / 2 to avoid + overflow and rounding errors */ + + middle = max - ( ( max - min ) >> 1 ); + + if ( glyphID == array[middle] ) + { + *index = middle; + return TT_Err_Ok; + } + else if ( glyphID < array[middle] ) + { + if ( middle == min ) + break; + new_max = middle - 1; + } + else + { + if ( middle == max ) + break; + new_min = middle + 1; + } + } while ( min < max ); + + return TTO_Err_Not_Covered; + } + + + static TT_Error Coverage_Index2( TTO_CoverageFormat2* cf2, + UShort glyphID, + UShort* index ) + { + UShort min, max, new_min, new_max, middle; + + TTO_RangeRecord* rr = cf2->RangeRecord; + + + /* binary search */ + + new_min = 0; + new_max = cf2->RangeCount - 1; + + do + { + min = new_min; + max = new_max; + + /* we use (min + max) / 2 = max - (max - min) / 2 to avoid + overflow and rounding errors */ + + middle = max - ( ( max - min ) >> 1 ); + + if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End ) + { + *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start; + return TT_Err_Ok; + } + else if ( glyphID < rr[middle].Start ) + { + if ( middle == min ) + break; + new_max = middle - 1; + } + else + { + if ( middle == max ) + break; + new_min = middle + 1; + } + } while ( min < max ); + + return TTO_Err_Not_Covered; + } + + + TT_Error Coverage_Index( TTO_Coverage* c, + UShort glyphID, + UShort* index ) + { + switch ( c->CoverageFormat ) + { + case 1: + return Coverage_Index1( &c->cf.cf1, glyphID, index ); + + case 2: + return Coverage_Index2( &c->cf.cf2, glyphID, index ); + + default: + return TTO_Err_Invalid_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + + /************************************* + * Class Definition related functions + *************************************/ + + + /* ClassDefFormat1 */ + + static TT_Error Load_ClassDef1( TTO_ClassDefinition* cd, + UShort limit, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* cva; + Bool* d; + + TTO_ClassDefFormat1* cdf1; + + + cdf1 = &cd->cd.cd1; + + if ( ACCESS_Frame( 4L ) ) + return error; + + cdf1->StartGlyph = GET_UShort(); + count = cdf1->GlyphCount = GET_UShort(); + + FORGET_Frame(); + + /* sanity check; we are limited to 16bit integers */ + + if ( cdf1->StartGlyph + (long)count >= 0x10000L ) + return TTO_Err_Invalid_SubTable; + + cdf1->ClassValueArray = NULL; + + if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, UShort ) ) + return error; + + d = cd->Defined; + cva = cdf1->ClassValueArray; + + if ( ACCESS_Frame( count * 2L ) ) + goto Fail; + + for ( n = 0; n < count; n++ ) + { + cva[n] = GET_UShort(); + if ( cva[n] >= limit ) + { + error = TTO_Err_Invalid_SubTable; + goto Fail; + } + d[cva[n]] = TRUE; + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail: + FREE( cva ); + + return error; + } + + + static void Free_ClassDef1( TTO_ClassDefFormat1* cdf1 ) + { + FREE( cdf1->ClassValueArray ); + } + + + /* ClassDefFormat2 */ + + static TT_Error Load_ClassDef2( TTO_ClassDefinition* cd, + UShort limit, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + TTO_ClassRangeRecord* crr; + Bool* d; + + TTO_ClassDefFormat2* cdf2; + + + cdf2 = &cd->cd.cd2; + + if ( ACCESS_Frame( 2L ) ) + return error; + + count = cdf2->ClassRangeCount = GET_UShort(); + + FORGET_Frame(); + + cdf2->ClassRangeRecord = NULL; + + if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, TTO_ClassRangeRecord ) ) + return error; + + d = cd->Defined; + crr = cdf2->ClassRangeRecord; + + if ( ACCESS_Frame( count * 6L ) ) + goto Fail; + + for ( n = 0; n < count; n++ ) + { + crr[n].Start = GET_UShort(); + crr[n].End = GET_UShort(); + crr[n].Class = GET_UShort(); + + /* sanity check */ + + if ( crr[n].Start > crr[n].End || + crr[n].Class >= limit ) + { + error = TTO_Err_Invalid_SubTable; + goto Fail; + } + d[crr[n].Class] = TRUE; + } + + FORGET_Frame(); + + return TT_Err_Ok; + + Fail: + FREE( crr ); + + return error; + } + + + static void Free_ClassDef2( TTO_ClassDefFormat2* cdf2 ) + { + FREE( cdf2->ClassRangeRecord ); + } + + + /* ClassDefinition */ + + TT_Error Load_ClassDefinition( TTO_ClassDefinition* cd, + UShort limit, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + + if ( ALLOC_ARRAY( cd->Defined, limit, Bool ) ) + return error; + + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + cd->ClassFormat = GET_UShort(); + + FORGET_Frame(); + + switch ( cd->ClassFormat ) + { + case 1: + error = Load_ClassDef1( cd, limit, input ); + break; + + case 2: + error = Load_ClassDef2( cd, limit, input ); + break; + + default: + error = TTO_Err_Invalid_SubTable_Format; + break; + } + + if ( error ) + goto Fail; + + cd->loaded = TRUE; + + return TT_Err_Ok; + + Fail: + FREE( cd->Defined ); + return error; + } + + + void Free_ClassDefinition( TTO_ClassDefinition* cd ) + { + if ( !cd->loaded ) + return; + + FREE( cd->Defined ); + + switch ( cd->ClassFormat ) + { + case 1: + Free_ClassDef1( &cd->cd.cd1 ); + break; + + case 2: + Free_ClassDef2( &cd->cd.cd2 ); + break; + } + } + + + static TT_Error Get_Class1( TTO_ClassDefFormat1* cdf1, + UShort glyphID, + UShort* class, + UShort* index ) + { + UShort* cva = cdf1->ClassValueArray; + + + *index = 0; + + if ( glyphID >= cdf1->StartGlyph && + glyphID <= cdf1->StartGlyph + cdf1->GlyphCount ) + { + *class = cva[glyphID - cdf1->StartGlyph]; + return TT_Err_Ok; + } + else + { + *class = 0; + return TTO_Err_Not_Covered; + } + } + + + /* we need the index value of the last searched class range record + in case of failure for constructed GDEF tables */ + + static TT_Error Get_Class2( TTO_ClassDefFormat2* cdf2, + UShort glyphID, + UShort* class, + UShort* index ) + { + TT_Error error = TT_Err_Ok; + UShort min, max, new_min, new_max, middle; + + TTO_ClassRangeRecord* crr = cdf2->ClassRangeRecord; + + + /* binary search */ + + new_min = 0; + new_max = cdf2->ClassRangeCount - 1; + + do + { + min = new_min; + max = new_max; + + /* we use (min + max) / 2 = max - (max - min) / 2 to avoid + overflow and rounding errors */ + + middle = max - ( ( max - min ) >> 1 ); + + if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End ) + { + *class = crr[middle].Class; + error = TT_Err_Ok; + break; + } + else if ( glyphID < crr[middle].Start ) + { + if ( middle == min ) + { + *class = 0; + error = TTO_Err_Not_Covered; + break; + } + new_max = middle - 1; + } + else + { + if ( middle == max ) + { + *class = 0; + error = TTO_Err_Not_Covered; + break; + } + new_min = middle + 1; + } + } while ( min < max ); + + if ( index ) + *index = middle; + + return error; + } + + + TT_Error Get_Class( TTO_ClassDefinition* cd, + UShort glyphID, + UShort* class, + UShort* index ) + { + switch ( cd->ClassFormat ) + { + case 1: + return Get_Class1( &cd->cd.cd1, glyphID, class, index ); + + case 2: + return Get_Class2( &cd->cd.cd2, glyphID, class, index ); + + default: + return TTO_Err_Invalid_SubTable_Format; + } + + return TT_Err_Ok; /* never reached */ + } + + + + /*************************** + * Device related functions + ***************************/ + + + TT_Error Load_Device( TTO_Device* d, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, count; + + UShort* dv; + + + if ( ACCESS_Frame( 6L ) ) + return error; + + d->StartSize = GET_UShort(); + d->EndSize = GET_UShort(); + d->DeltaFormat = GET_UShort(); + + FORGET_Frame(); + + if ( d->StartSize > d->EndSize || + d->DeltaFormat == 0 || d->DeltaFormat > 3 ) + return TTO_Err_Invalid_SubTable; + + d->DeltaValue = NULL; + + count = ( ( d->EndSize - d->StartSize + 1 ) >> + ( 4 - d->DeltaFormat ) ) + 1; + + if ( ALLOC_ARRAY( d->DeltaValue, count, UShort ) ) + return error; + + if ( ACCESS_Frame( count * 2L ) ) + { + FREE( d->DeltaValue ); + return error; + } + + dv = d->DeltaValue; + + for ( n = 0; n < count; n++ ) + dv[n] = GET_UShort(); + + FORGET_Frame(); + + return TT_Err_Ok; + } + + + void Free_Device( TTO_Device* d ) + { + FREE( d->DeltaValue ); + } + + + /* Since we have the delta values stored in compressed form, we must + uncompress it now. To simplify the interface, the function always + returns a meaningful value in `value'; the error is just for + information. + | | + format = 1: 0011223344556677|8899101112131415|... + | | + byte 1 byte 2 + + 00: (byte >> 14) & mask + 11: (byte >> 12) & mask + ... + + mask = 0x0003 + | | + format = 2: 0000111122223333|4444555566667777|... + | | + byte 1 byte 2 + + 0000: (byte >> 12) & mask + 1111: (byte >> 8) & mask + ... + + mask = 0x000F + | | + format = 3: 0000000011111111|2222222233333333|... + | | + byte 1 byte 2 + + 00000000: (byte >> 8) & mask + 11111111: (byte >> 0) & mask + .... + + mask = 0x00FF */ + + TT_Error Get_Device( TTO_Device* d, + UShort size, + Short* value ) + { + UShort byte, bits, mask, f, s; + + + f = d->DeltaFormat; + + if ( size >= d->StartSize && size <= d->EndSize ) + { + s = size - d->StartSize; + byte = d->DeltaValue[s >> ( 4 - f )]; + bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) ); + mask = 0xFFFF >> ( 16 - ( 1 << f ) ); + + *value = (Short)( bits & mask ); + + /* conversion to a signed value */ + + if ( *value >= ( ( mask + 1 ) >> 1 ) ) + *value -= mask + 1; + + return TT_Err_Ok; + } + else + { + *value = 0; + return TTO_Err_Not_Covered; + } + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxopen.h b/Build/source/libs/libttf/extend/ftxopen.h new file mode 100644 index 00000000000..0063527a614 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxopen.h @@ -0,0 +1,305 @@ +/******************************************************************* + * + * ftxopen.h + * + * TrueType Open support. + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * This file should be included by the application. Nevertheless, + * the table specific APIs (and structures) are located in files like + * ftxgsub.h or ftxgpos.h; these header files are read by ftxopen.h . + * + ******************************************************************/ + +#ifndef FTXOPEN_H +#define FTXOPEN_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TTO_MAX_NESTING_LEVEL 100 + +#define TTO_Err_Invalid_SubTable_Format 0x1000 +#define TTO_Err_Invalid_SubTable 0x1001 +#define TTO_Err_Not_Covered 0x1002 +#define TTO_Err_Too_Many_Nested_Contexts 0x1003 +#define TTO_Err_No_MM_Interpreter 0x1004 + + + /* Script list related structures */ + + struct TTO_LangSys_ + { + TT_UShort LookupOrderOffset; /* always 0 for TT Open 1.0 */ + TT_UShort ReqFeatureIndex; /* required FeatureIndex */ + TT_UShort FeatureCount; /* number of Feature indices */ + TT_UShort* FeatureIndex; /* array of Feature indices */ + }; + + typedef struct TTO_LangSys_ TTO_LangSys; + + + struct TTO_LangSysRecord_ + { + TT_ULong LangSysTag; /* LangSysTag identifier */ + TTO_LangSys LangSys; /* LangSys table */ + }; + + typedef struct TTO_LangSysRecord_ TTO_LangSysRecord; + + + struct TTO_Script_ + { + TTO_LangSys DefaultLangSys; /* DefaultLangSys table */ + TT_UShort LangSysCount; /* number of LangSysRecords */ + TTO_LangSysRecord* LangSysRecord; /* array of LangSysRecords */ + }; + + typedef struct TTO_Script_ TTO_Script; + + + struct TTO_ScriptRecord_ + { + TT_ULong ScriptTag; /* ScriptTag identifier */ + TTO_Script Script; /* Script table */ + }; + + typedef struct TTO_ScriptRecord_ TTO_ScriptRecord; + + + struct TTO_ScriptList_ + { + TT_UShort ScriptCount; /* number of ScriptRecords */ + TTO_ScriptRecord* ScriptRecord; /* array of ScriptRecords */ + }; + + typedef struct TTO_ScriptList_ TTO_ScriptList; + + + /* Feature list related structures */ + + struct TTO_Feature_ + { + TT_UShort FeatureParams; /* always 0 for TT Open 1.0 */ + TT_UShort LookupListCount; /* number of LookupList indices */ + TT_UShort* LookupListIndex; /* array of LookupList indices */ + }; + + typedef struct TTO_Feature_ TTO_Feature; + + + struct TTO_FeatureRecord_ + { + TT_ULong FeatureTag; /* FeatureTag identifier */ + TTO_Feature Feature; /* Feature table */ + }; + + typedef struct TTO_FeatureRecord_ TTO_FeatureRecord; + + + struct TTO_FeatureList_ + { + TT_UShort FeatureCount; /* number of FeatureRecords */ + TTO_FeatureRecord* FeatureRecord; /* array of FeatureRecords */ + }; + + typedef struct TTO_FeatureList_ TTO_FeatureList; + + + /* Lookup list related structures */ + + struct TTO_SubTable_; /* defined below after inclusion + of ftxgsub.h and ftxgpos.h */ + typedef struct TTO_SubTable_ TTO_SubTable; + + + struct TTO_Lookup_ + { + TT_UShort LookupType; /* Lookup type */ + TT_UShort LookupFlag; /* Lookup qualifiers */ + TT_UShort SubTableCount; /* number of SubTables */ + TTO_SubTable* SubTable; /* array of SubTables */ + }; + + typedef struct TTO_Lookup_ TTO_Lookup; + + + /* The `Properties' field is not defined in the TTO specification but + is needed for processing lookups. If properties[n] is > 0, the + functions TT_GSUB_Apply_String() resp. TT_GPOS_Apply_String() will + process Lookup[n] for glyphs which have the specific bit not set in + the `properties' field of the input string object. */ + + struct TTO_LookupList_ + { + TT_UShort LookupCount; /* number of Lookups */ + TTO_Lookup* Lookup; /* array of Lookup records */ + TT_UShort* Properties; /* array of flags */ + }; + + typedef struct TTO_LookupList_ TTO_LookupList; + + +/* Possible LookupFlag bit masks. `IGNORE_SPECIAL_MARKS' comes from the + OpenType 1.2 specification. */ + +#define IGNORE_BASE_GLYPHS 0x0002 +#define IGNORE_LIGATURES 0x0004 +#define IGNORE_MARKS 0x0008 +#define IGNORE_SPECIAL_MARKS 0xFF00 + + + struct TTO_CoverageFormat1_ + { + TT_UShort GlyphCount; /* number of glyphs in GlyphArray */ + TT_UShort* GlyphArray; /* array of glyph IDs */ + }; + + typedef struct TTO_CoverageFormat1_ TTO_CoverageFormat1; + + + struct TTO_RangeRecord_ + { + TT_UShort Start; /* first glyph ID in the range */ + TT_UShort End; /* last glyph ID in the range */ + TT_UShort StartCoverageIndex; /* coverage index of first + glyph ID in the range */ + }; + + typedef struct TTO_RangeRecord_ TTO_RangeRecord; + + + struct TTO_CoverageFormat2_ + { + TT_UShort RangeCount; /* number of RangeRecords */ + TTO_RangeRecord* RangeRecord; /* array of RangeRecords */ + }; + + typedef struct TTO_CoverageFormat2_ TTO_CoverageFormat2; + + + struct TTO_Coverage_ + { + TT_UShort CoverageFormat; /* 1 or 2 */ + + union + { + TTO_CoverageFormat1 cf1; + TTO_CoverageFormat2 cf2; + } cf; + }; + + typedef struct TTO_Coverage_ TTO_Coverage; + + + struct TTO_ClassDefFormat1_ + { + TT_UShort StartGlyph; /* first glyph ID of the + ClassValueArray */ + TT_UShort GlyphCount; /* size of the ClassValueArray */ + TT_UShort* ClassValueArray; /* array of class values */ + }; + + typedef struct TTO_ClassDefFormat1_ TTO_ClassDefFormat1; + + + struct TTO_ClassRangeRecord_ + { + TT_UShort Start; /* first glyph ID in the range */ + TT_UShort End; /* last glyph ID in the range */ + TT_UShort Class; /* applied to all glyphs in range */ + }; + + typedef struct TTO_ClassRangeRecord_ TTO_ClassRangeRecord; + + + struct TTO_ClassDefFormat2_ + { + TT_UShort ClassRangeCount; + /* number of ClassRangeRecords */ + TTO_ClassRangeRecord* ClassRangeRecord; + /* array of ClassRangeRecords */ + }; + + typedef struct TTO_ClassDefFormat2_ TTO_ClassDefFormat2; + + + /* The `Defined' field is not defined in the TTO specification but + apparently needed for processing fonts like trado.ttf: This font + refers to a class which contains not a single element. We map such + classes to class 0. */ + + struct TTO_ClassDefinition_ + { + TT_Bool loaded; + + TT_Bool* Defined; /* array of Booleans. + If Defined[n] is FALSE, + class n contains no glyphs. */ + TT_UShort ClassFormat; /* 1 or 2 */ + + union + { + TTO_ClassDefFormat1 cd1; + TTO_ClassDefFormat2 cd2; + } cd; + }; + + typedef struct TTO_ClassDefinition_ TTO_ClassDefinition; + + + struct TTO_Device_ + { + TT_UShort StartSize; /* smallest size to correct */ + TT_UShort EndSize; /* largest size to correct */ + TT_UShort DeltaFormat; /* DeltaValue array data format: + 1, 2, or 3 */ + TT_UShort* DeltaValue; /* array of compressed data */ + }; + + typedef struct TTO_Device_ TTO_Device; + + +#include "ftxgdef.h" +#include "ftxgsub.h" +#include "ftxgpos.h" + + + struct TTO_SubTable_ + { + union + { + TTO_GSUB_SubTable gsub; + TTO_GPOS_SubTable gpos; + } st; + }; + + + enum TTO_Type_ + { + GSUB, + GPOS + }; + + typedef enum TTO_Type_ TTO_Type; + + +#ifdef __cplusplus +} +#endif + +#endif /* FTXOPEN_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxopenf.h b/Build/source/libs/libttf/extend/ftxopenf.h new file mode 100644 index 00000000000..df69a64b452 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxopenf.h @@ -0,0 +1,143 @@ +/******************************************************************* + * + * ftxopenf.h + * + * internal TrueType Open functions + * + * Copyright 1996-2000 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FTXOPENF_H +#define FTXOPENF_H + +#include "ftxopen.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* functions from ftxopen.c */ + + TT_Error Load_ScriptList( TTO_ScriptList* sl, + PFace input ); + TT_Error Load_FeatureList( TTO_FeatureList* fl, + PFace input ); + TT_Error Load_LookupList( TTO_LookupList* ll, + PFace input, + TTO_Type type ); + + TT_Error Load_Coverage( TTO_Coverage* c, + PFace input ); + TT_Error Load_ClassDefinition( TTO_ClassDefinition* cd, + UShort limit, + PFace input ); + TT_Error Load_Device( TTO_Device* d, + PFace input ); + + void Free_ScriptList( TTO_ScriptList* sl ); + void Free_FeatureList( TTO_FeatureList* fl ); + void Free_LookupList( TTO_LookupList* ll, + TTO_Type type ); + + void Free_Coverage( TTO_Coverage* c ); + void Free_ClassDefinition( TTO_ClassDefinition* cd ); + void Free_Device( TTO_Device* d ); + + + /* functions from ftxgsub.c */ + + TT_Error Load_SingleSubst( TTO_SingleSubst* ss, + PFace input ); + TT_Error Load_MultipleSubst( TTO_MultipleSubst* ms, + PFace input ); + TT_Error Load_AlternateSubst( TTO_AlternateSubst* as, + PFace input ); + TT_Error Load_LigatureSubst( TTO_LigatureSubst* ls, + PFace input ); + TT_Error Load_ContextSubst( TTO_ContextSubst* cs, + PFace input ); + TT_Error Load_ChainContextSubst( TTO_ChainContextSubst* ccs, + PFace input ); + + void Free_SingleSubst( TTO_SingleSubst* ss ); + void Free_MultipleSubst( TTO_MultipleSubst* ms ); + void Free_AlternateSubst( TTO_AlternateSubst* as ); + void Free_LigatureSubst( TTO_LigatureSubst* ls ); + void Free_ContextSubst( TTO_ContextSubst* cs ); + void Free_ChainContextSubst( TTO_ChainContextSubst* ccs ); + + + /* functions from ftxgpos.c */ + + TT_Error Load_SinglePos( TTO_SinglePos* sp, + PFace input ); + TT_Error Load_PairPos( TTO_PairPos* pp, + PFace input ); + TT_Error Load_CursivePos( TTO_CursivePos* cp, + PFace input ); + TT_Error Load_MarkBasePos( TTO_MarkBasePos* mbp, + PFace input ); + TT_Error Load_MarkLigPos( TTO_MarkLigPos* mlp, + PFace input ); + TT_Error Load_MarkMarkPos( TTO_MarkMarkPos* mmp, + PFace input ); + TT_Error Load_ContextPos( TTO_ContextPos* cp, + PFace input ); + TT_Error Load_ChainContextPos( TTO_ChainContextPos* ccp, + PFace input ); + + void Free_SinglePos( TTO_SinglePos* sp ); + void Free_PairPos( TTO_PairPos* pp ); + void Free_CursivePos( TTO_CursivePos* cp ); + void Free_MarkBasePos( TTO_MarkBasePos* mbp ); + void Free_MarkLigPos( TTO_MarkLigPos* mlp ); + void Free_MarkMarkPos( TTO_MarkMarkPos* mmp ); + void Free_ContextPos( TTO_ContextPos* cp ); + void Free_ChainContextPos( TTO_ChainContextPos* ccp ); + + + /* query functions */ + + TT_Error Coverage_Index( TTO_Coverage* c, + UShort glyphID, + UShort* index ); + TT_Error Get_Class( TTO_ClassDefinition* cd, + UShort glyphID, + UShort* class, + UShort* index ); + TT_Error Get_Device( TTO_Device* d, + UShort size, + Short* value ); + + + /* functions from ftxgdef.c */ + + TT_Error Add_Glyph_Property( TTO_GDEFHeader* gdef, + UShort glyphID, + UShort property ); + + TT_Error Check_Property( TTO_GDEFHeader* gdef, + UShort index, + UShort flags, + UShort* property ); + +#define CHECK_Property( gdef, index, flags, property ) \ + ( ( error = Check_Property( (gdef), (index), (flags), \ + (property) ) ) != TT_Err_Ok ) + +#ifdef __cplusplus +} +#endif + +#endif /* FTXOPENF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxpost.c b/Build/source/libs/libttf/extend/ftxpost.c new file mode 100644 index 00000000000..8b2ac5940c0 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxpost.c @@ -0,0 +1,523 @@ +/******************************************************************* + * + * ftxpost.c + * + * post table support API extension body + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The post table is not completely loaded by the core engine. This + * file loads the missing PS glyph names and implements an API to + * access them. + * + ******************************************************************/ + +#include "ttconfig.h" +#include "ftxpost.h" + +#include "tttypes.h" +#include "ttobjs.h" +#include "tttables.h" +#include "ttload.h" /* for the macros */ +#include "ttfile.h" +#include "tttags.h" +#include "ttmemory.h" +#include "ttextend.h" + + +#define POST_ID Build_Extension_ID( 'p', 'o', 's', 't' ) + + + /* the 258 default Mac PS glyph names */ + + String* TT_Post_Default_Names[258] = + { + /* 0 */ + ".notdef", ".null", "CR", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + /* 10 */ + "quotesingle", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", + /* 20 */ + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "colon", + /* 30 */ + "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", + /* 40 */ + "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", + /* 50 */ + "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", + /* 60 */ + "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "grave", "a", "b", + /* 70 */ + "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", + /* 80 */ + "m", "n", "o", "p", "q", + "r", "s", "t", "u", "v", + /* 90 */ + "w", "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", "Adieresis", "Aring", + /* 100 */ + "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", + "aacute", "agrave", "acircumflex", "adieresis", "atilde", + /* 110 */ + "aring", "ccedilla", "eacute", "egrave", "ecircumflex", + "edieresis", "iacute", "igrave", "icircumflex", "idieresis", + /* 120 */ + "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", + "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", + /* 130 */ + "dagger", "degree", "cent", "sterling", "section", + "bullet", "paragraph", "germandbls", "registered", "copyright", + /* 140 */ + "trademark", "acute", "dieresis", "notequal", "AE", + "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", + /* 150 */ + "yen", "mu", "partialdiff", "summation", "product", + "pi", "integral", "ordfeminine", "ordmasculine", "Omega", + /* 160 */ + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + /* 170 */ + "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + /* 180 */ + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", + "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", + /* 190 */ + "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", + "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", + /* 200 */ + "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", + "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", + /* 210 */ + "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", + "dotlessi", "circumflex", "tilde", "macron", "breve", + /* 220 */ + "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", + "caron", "Lslash", "lslash", "Scaron", "scaron", + /* 230 */ + "Zcaron", "zcaron", "brokenbar", "Eth", "eth", + "Yacute", "yacute", "Thorn", "thorn", "minus", + /* 240 */ + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + /* 250 */ + "Idot", "Scedilla", "scedilla", "Cacute", "cacute", + "Ccaron", "ccaron", "dmacron", + }; + + + + static TT_Error Load_Format_20( TT_Post_20* post20, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort nameindex, n, num; + Byte len; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + num = GET_UShort(); + + FORGET_Frame(); + + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + + /* There already exist fonts which have more than 32768 glyph names */ + /* in this table, so the test for this threshold has been dropped. */ + if ( num > input->numGlyphs ) + return TT_Err_Invalid_Post_Table; + + post20->numGlyphs = num; + + if ( ALLOC_ARRAY( post20->glyphNameIndex, num, TT_UShort ) ) + return error; + + if ( ACCESS_Frame( num * 2L ) ) + goto Fail; + + for ( n = 0; n < num; n++ ) + { + post20->glyphNameIndex[n] = GET_UShort(); + + if ( post20->glyphNameIndex[n] > 258 + num ) + { + FORGET_Frame(); + error = TT_Err_Invalid_Post_Table; + goto Fail; + } + } + + FORGET_Frame(); + + if ( ALLOC_ARRAY( post20->glyphNames, num, Char* ) ) + goto Fail; + + /* We must initialize the glyphNames array for proper */ + /* deallocation. */ + for ( n = 0; n < num; n++ ) + post20->glyphNames[n] = NULL; + + /* Now we can read the glyph names which are stored in */ + /* Pascal string format. */ + for ( n = 0; n < num; n++ ) + { + nameindex = post20->glyphNameIndex[n]; + + if ( nameindex < 258 ) + ; /* default Mac glyph, do nothing */ + else + { + if ( ACCESS_Frame( 1L ) ) + goto Fail1; + + len = GET_Byte(); + + FORGET_Frame(); + + if ( ALLOC_ARRAY( post20->glyphNames[nameindex - 258], + len + 1, Char ) || + FILE_Read( post20->glyphNames[nameindex - 258], len ) ) + goto Fail1; + + /* we make a C string */ + post20->glyphNames[nameindex - 258][len] = '\0'; + } + } + + return TT_Err_Ok; + + + Fail1: + for ( n = 0; n < num; n++ ) + if ( post20->glyphNames[n] ) + FREE( post20->glyphNames[n] ); + + FREE( post20->glyphNames ); + + Fail: + FREE( post20->glyphNameIndex ); + return error; + } + + + static TT_Error Load_Format_25( TT_Post_25* post25, + PFace input ) + { + DEFINE_LOAD_LOCALS( input->stream ); + + UShort n, num; + + + if ( ACCESS_Frame( 2L ) ) + return error; + + /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ + num = GET_UShort(); + + FORGET_Frame(); + + if ( num > input->numGlyphs || num > 258 ) + return TT_Err_Invalid_Post_Table; + + post25->numGlyphs = num; + + if ( ALLOC_ARRAY( post25->offset, num, Char ) ) + return error; + + if ( ACCESS_Frame( num ) ) + goto Fail; + + for ( n = 0; n < num; n++ ) + { + post25->offset[n] = GET_Char(); + + /* We add 128 to the tests to avoid problems with negative */ + /* values for comparison. */ + if ( n + ( post25->offset[n] + 128 ) > num + 128 || + n + ( post25->offset[n] + 128 ) < 128 ) + { + FORGET_Frame(); + error = TT_Err_Invalid_Post_Table; + goto Fail; + } + } + + FORGET_Frame(); + + return TT_Err_Ok; + + + Fail: + FREE( post25->offset ); + return error; + } + + + static TT_Error Post_Create( void* ext, + PFace face ) + { + TT_Post* post = (TT_Post*)ext; + Long table; + + + /* by convention */ + if ( !post ) + return TT_Err_Ok; + + /* we store the start offset and the size of the subtable */ + table = TT_LookUp_Table( face, TTAG_post ); + post->offset = face->dirTables[table].Offset + 32L; + post->length = face->dirTables[table].Length - 32L; + post->loaded = FALSE; + + return TT_Err_Ok; + } + + + static TT_Error Post_Destroy( void* ext, + PFace face ) + { + TT_Post* post = (TT_Post*)ext; + UShort n; + + + /* by convention */ + if ( !post ) + return TT_Err_Ok; + + if ( post->loaded ) + { + switch ( face->postscript.FormatType ) + { + case 0x00010000: /* nothing to do */ + break; + + case 0x00020000: + for ( n = 0; n < post->p.post20.numGlyphs; n++ ) + if ( post->p.post20.glyphNames[n] ) + FREE( post->p.post20.glyphNames[n] ); + FREE( post->p.post20.glyphNames ); + FREE( post->p.post20.glyphNameIndex ); + break; + + case 0x00028000: + FREE( post->p.post25.offset ); + break; + + case 0x00030000: /* nothing to do */ + break; + +#if 0 + case 0x00040000: + break; +#endif + + default: + ; /* invalid format, do nothing */ + } + } + + return TT_Err_Ok; + } + + + EXPORT_FUNC + TT_Error TT_Init_Post_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + error = TT_Register_Extension( _engine, + POST_ID, + sizeof ( TT_Post ), + Post_Create, + Post_Destroy ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Load_PS_Names + * + * Description : Loads the PostScript Glyph Name subtable (if any). + * + * Output : error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Load_PS_Names( TT_Face face, + TT_Post* ppost ) + { + PFace faze = HANDLE_Face( face ); + TT_Error error; + TT_Stream stream; + TT_Post* post; + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + error = TT_Extension_Get( faze, POST_ID, (void**)&post ); + if ( error ) + return error; + + if ( USE_Stream( faze->stream, stream ) ) + return error; + + + switch ( faze->postscript.FormatType ) + { + case 0x00010000: + error = TT_Err_Ok; /* nothing to do */ + break; + + case 0x00020000: + if ( FILE_Seek( post->offset ) ) + goto Fail; + + error = Load_Format_20( &post->p.post20, faze ); + break; + + case 0x00028000: /* 2.5 in 16.16 format */ + if ( FILE_Seek( post->offset ) ) + goto Fail; + + error = Load_Format_25( &post->p.post25, faze ); + break; + + case 0x00030000: + error = TT_Err_Ok; /* nothing to do */ + break; + +#if 0 + case 0x00040000: + break; +#endif + + default: + error = TT_Err_Invalid_Post_Table_Format; + break; + } + + if ( !error ) + { + post->loaded = TRUE; + *ppost = *post; + } + + + Fail: + DONE_Stream( stream ); + + return error; + } + + +/******************************************************************* + * + * Function : TT_Get_PS_Name + * + * Description : Gets the PostScript Glyph Name of a glyph. + * + * Input : index glyph index + * PSname address of a string pointer. + * Will be NULL in case of error; otherwise it + * contains a pointer to the glyph name. + * + * You must not modify the returned string! + * + * Output : error code + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UShort index, + TT_String** PSname ) + { + PFace faze = HANDLE_Face( face ); + TT_Error error; + TT_Post* post; + UShort nameindex; + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( index >= faze->numGlyphs ) + return TT_Err_Invalid_Glyph_Index; + + error = TT_Extension_Get( faze, POST_ID, (void**)&post ); + if ( error ) + return error; + + + *PSname = TT_Post_Default_Names[0]; /* default value */ + + switch ( faze->postscript.FormatType ) + { + case 0x00010000: + if ( index < 258 ) /* paranoid checking */ + *PSname = TT_Post_Default_Names[index]; + break; + + case 0x00020000: + if ( index < post->p.post20.numGlyphs ) + nameindex = post->p.post20.glyphNameIndex[index]; + else + break; + + if ( nameindex < 258 ) + *PSname = TT_Post_Default_Names[nameindex]; + else + *PSname = (String*)post->p.post20.glyphNames[nameindex - 258]; + break; + + case 0x00028000: + if ( index < post->p.post25.numGlyphs ) /* paranoid checking */ + *PSname = TT_Post_Default_Names[index + post->p.post25.offset[index]]; + break; + + case 0x00030000: + break; /* nothing to do */ + +#if 0 + case 0x00040000: + break; +#endif + + default: + ; /* should never happen */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxpost.h b/Build/source/libs/libttf/extend/ftxpost.h new file mode 100644 index 00000000000..534b6080d30 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxpost.h @@ -0,0 +1,107 @@ +/******************************************************************* + * + * ftxpost.h + * + * post table support API extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * The post table is not completely loaded by the core engine. This + * file loads the missing PS glyph names and implements an API to + * access them. + * + ******************************************************************/ + +#ifndef FTXPOST_H +#define FTXPOST_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + /* the 258 standard Mac glyph names, used for format 1.0 and 2.5 */ + + extern TT_String* TT_Post_Default_Names[]; + + + /* format 2.0 table */ + + struct TT_Post_20_ + { + TT_UShort numGlyphs; + TT_UShort* glyphNameIndex; + TT_Char** glyphNames; + }; + + typedef struct TT_Post_20_ TT_Post_20; + + struct TT_Post_25_ + { + TT_UShort numGlyphs; + TT_Char* offset; + }; + + typedef struct TT_Post_25_ TT_Post_25; + +#if 0 + /* format 4.0 table -- not implemented yet */ + + struct TT_Post_40_ + { + }; + + typedef struct TT_Post_40_ TT_Post_40; +#endif + + + struct TT_Post_ + { + TT_Long offset; + TT_Long length; + TT_Bool loaded; + + union + { + TT_Post_20 post20; + TT_Post_25 post25; +#if 0 + TT_Post_40 post40; +#endif + } p; + }; + + typedef struct TT_Post_ TT_Post; + + + EXPORT_DEF + TT_Error TT_Init_Post_Extension( TT_Engine engine ); + + EXPORT_DEF + TT_Error TT_Load_PS_Names( TT_Face face, + TT_Post* post ); + EXPORT_DEF + TT_Error TT_Get_PS_Name( TT_Face face, + TT_UShort index, + TT_String** PSname ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXPOST_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxsbit.c b/Build/source/libs/libttf/extend/ftxsbit.c new file mode 100644 index 00000000000..02162bd2e3f --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxsbit.c @@ -0,0 +1,1391 @@ +/******************************************************************* + * + * ftxsbit.c + * + * Embedded bitmap API extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This extension is used to load the embedded bitmaps present + * in certain TrueType files. + * + ******************************************************************/ + +#include "ftxsbit.h" +#include "ttobjs.h" +#include "ttfile.h" +#include "ttload.h" +#include "ttmemory.h" +#include "tttags.h" +#include "ttextend.h" +#include "ttdebug.h" + + +#define SBIT_ID Build_Extension_ID( 's', 'b', 'i', 't' ) + + +/* Required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_bitmap + +/* In all functions, the stream is taken from the 'face' object */ +#define DEFINE_LOCALS DEFINE_LOAD_LOCALS( face->stream ) +#define DEFINE_LOCALS_WO_FRAME DEFINE_LOAD_LOCALS_WO_FRAME( face->stream ) + + +/*************************** + * + * miscellaneous functions + * + ***************************/ + +/******************************************************************* + * + * Function: Load_BitmapData + * + * Bit-aligned bitmap data -> Byte-aligned bitmap data when pad is 0 + * + ******************************************************************/ + + static + TT_Error Load_BitmapData( TT_SBit_Image* image, + Int image_size, + Byte x_offset, + Byte y_offset, + UShort source_width, + UShort source_height, + Bool byte_padded ) + { + DEFINE_LOCALS; + + Int count; /* number of bits left in rows */ + Int loaded; /* number of bits loaded in the accumulator */ + UShort buff; /* accumulator */ + + PByte line; /* target write cursor */ + PByte limit; + + + if ( ( y_offset + source_height > image->map.rows ) || + ( x_offset + source_width > image->map.width ) ) + return TT_Err_Invalid_Argument; + + if ( ACCESS_Frame( image_size ) ) + return error; + + buff = 0; + loaded = 0; + line = (PByte)image->map.bitmap + + y_offset * image->map.cols; + limit = (PByte)image->map.bitmap + + ( y_offset + source_height ) * image->map.cols; + + for ( ; line < limit; line += image->map.cols ) + { + PByte ptr; + + + ptr = line + x_offset / 8; + count = source_width; + + /* We may assume that `loaded' is less than 8 */ + buff >>= x_offset % 8; + loaded += x_offset % 8; + + /* first of all, read all consecutive bytes */ + while ( count >= 8 ) + { + if ( loaded < 8 ) + { + buff |= ((UShort)GET_Byte()) << (8 - loaded); + loaded += 8; + } + + *ptr++ |= (Byte)(buff >> 8); + buff <<= 8; + loaded -= 8; + count -= 8; + } + + /* now write remaining bits (i.e. end of line with count < 8) */ + if ( count > 0 ) + { + if ( loaded < count ) + { + buff |= ((UShort)GET_Byte()) << (8 - loaded); + loaded += 8; + } + + *ptr |= ((Byte)(buff >> 8)) & ~(0xFF >> count); + buff <<= count; + loaded -= count; + } + + if ( byte_padded ) + { + buff = 0; + loaded = 0; + } + } + + FORGET_Frame(); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function: Crop_Bitmap + * + ******************************************************************/ + + static + void Crop_Bitmap( TT_SBit_Image* image ) + { + /*******************************************************/ + /* In the following situation, some bounding boxes of */ + /* embedded bitmaps are too large. We need to crop it */ + /* to a reasonable size. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | -----> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /*******************************************************/ + + Int rows, count; + Long line_len; + PByte line; + + + /********************************************************************/ + /* */ + /* first of all, check the top-most lines of the bitmap and remove */ + /* them if they're empty. */ + /* */ + { + line = (PByte)image->map.bitmap; + rows = image->map.rows; + line_len = image->map.cols; + + for ( count = 0; count < rows; count++ ) + { + PByte cur = line; + PByte limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Top; + + /* the current line was empty -- skip to next one */ + line = limit; + } + + Found_Top: + /* check that we have at least one filled line */ + if ( count >= rows ) + goto Empty_Bitmap; + + /* now, crop the empty upper lines */ + if ( count > 0 ) + { + line = (PByte)image->map.bitmap; + + MEM_Move( line, line + count*line_len, (rows-count) * line_len ); + + image->metrics.bbox.yMax -= count; + image->metrics.vertBearingY -= count; + image->metrics.horiBearingY -= count; + image->map.rows -= count; + rows -= count; + } + } + + /*******************************************************************/ + /* */ + /* second, crop the lower lines */ + /* */ + { + line = (PByte)image->map.bitmap + (rows-1) * line_len; + + for ( count = 0; count < rows; count++ ) + { + PByte cur = line; + PByte limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Bottom; + + /* the current line was empty -- skip to previous one */ + line -= line_len; + } + + Found_Bottom: + if ( count > 0 ) + { + image->metrics.bbox.yMin += count; + image->map.rows -= count; + rows -= count; + } + } + + /*******************************************************************/ + /* */ + /* third, get rid of the space on the left side of the glyph */ + /* */ + do + { + PByte limit; + + + line = (PByte)image->map.bitmap; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + if ( line[0] & 0x80 ) + goto Found_Left; + + /* shift the whole glyph one pixel to the left */ + line = (PByte)image->map.bitmap; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + Int n, width = image->map.width; + Byte old; + PByte cur = line; + + + old = cur[0] << 1; + + for ( n = 8; n < width; n += 8 ) + { + Byte val; + + + val = cur[1]; + cur[0] = old | (val >> 7); + old = val << 1; + cur++; + } + cur[0] = old; + } + + image->map.width--; + image->metrics.horiBearingX++; + image->metrics.vertBearingX++; + image->metrics.bbox.xMin++; + + } while ( image->map.width > 0 ); + + Found_Left: + + /*********************************************************************/ + /* */ + /* finally, crop the bitmap width to get rid of the space on the */ + /* right side of the glyph. */ + /* */ + do + { + Int right = image->map.width-1; + PByte limit; + Byte mask; + + + line = (PByte)image->map.bitmap + (right >> 3); + limit = line + rows*line_len; + mask = 0x80 >> (right & 7); + + for ( ; line < limit; line += line_len ) + if ( line[0] & mask ) + goto Found_Right; + + /* crop the whole glyph on the right */ + image->map.width--; + image->metrics.bbox.xMax--; + + } while ( image->map.width > 0 ); + + Found_Right: + /* all right, the bitmap was cropped */ + return; + + Empty_Bitmap: + image->map.width = 0; + image->map.rows = 0; + image->map.cols = 0; + image->map.size = 0; + } + +/************* + * + * Main body + * + *************/ + + + static + TT_Error Load_Range_Codes( TT_SBit_Range* range, + PFace face, + Bool load_offsets ) + { + DEFINE_LOCALS; + + ULong count, n, size; + + + (void)face; + + /* read glyph count */ + if ( ACCESS_Frame( 4L ) ) + goto Exit; + count = GET_ULong(); + FORGET_Frame(); + + range->num_glyphs = count; + + /* Allocate glyph offsets table if needed */ + if ( load_offsets ) + { + if ( ALLOC_ARRAY( range->glyph_offsets, count, ULong ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( ALLOC_ARRAY ( range->glyph_codes, count, UShort ) || + ACCESS_Frame( size ) ) + goto Exit; + + for ( n = 0; n < count; n++ ) + { + range->glyph_codes[n] = GET_UShort(); + + if ( load_offsets ) + range->glyph_offsets[n] = (ULong)range->image_offset + GET_UShort(); + } + + FORGET_Frame(); + + Exit: + return error; + } + + + static + TT_Error Load_SBit_Range( TT_SBit_Strike* strike, + TT_SBit_Range* range, + PFace face ) + { + DEFINE_LOCALS; + + UShort format; + + + (void)face; + (void)strike; + + format = range->index_format; + PTRACE6(( "Index Format: %d\n", format )); + + switch( format ) + { + case 1: /* variable metrics with 4-byte offsets */ + case 3: /* variable metrics with 2-byte offsets */ + { + UShort num_glyphs, size_elem; + Bool large = (format == 1); + ULong* cur; + + num_glyphs = range->last_glyph - range->first_glyph + 1; + PTRACE5(( " num glyphs: %hu\n", num_glyphs )); + + range->num_glyphs = num_glyphs; + + num_glyphs++; /* BEWARE */ + + size_elem = large ? 4 : 2; + + if ( ALLOC_ARRAY( range->glyph_offsets, num_glyphs, ULong ) || + ACCESS_Frame( num_glyphs * size_elem ) ) + return error; + + cur = range->glyph_offsets; + + while ( num_glyphs > 0 ) + { + cur[0] = (TT_ULong)( range->image_offset + + (large ? GET_ULong() : GET_UShort()) ); + PTRACE7(( " offset: %d\n", cur[0] )); + cur++; + num_glyphs--; + } + + FORGET_Frame(); + } + break; + + case 2: /* all glyphs have identical metrics */ + case 4: + case 5: + { + error = 0; + + if ( format != 4 ) /* read constant metrics, formats 2 and 5 */ + { + TT_SBit_Metrics* metrics; + + + if ( ACCESS_Frame( 12L ) ) + return error; + + range->image_size = GET_ULong(); + metrics = &range->metrics; + + metrics->height = GET_Byte(); + metrics->width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + metrics->vertBearingX = GET_Char(); + metrics->vertBearingY = GET_Char(); + metrics->vertAdvance = GET_Byte(); + + FORGET_Frame(); + } + + if ( format != 2 ) /* load range codes, formats 4 and 5 */ + error = Load_Range_Codes( range, face, (format == 4) ); + } + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + PTRACE3(( "Embedded Bitmap Location Tables loaded.\n" )); + + return error; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Eblc + * + * Description : Loads the Eblc table directory into face table. + * + * Input : face face record to look for + * + * Output : Error code. + * + ******************************************************************/ + + static + TT_Error Load_TrueType_Eblc( PFace face, + TT_EBLC* eblc ) + { + DEFINE_LOCALS; + + ULong eblc_offset; + UShort i; + Long table; + + TT_SBit_Strike* strike; + + + PTRACE2(( "Load_EBLC_Table( %08lx )\n", (long)face )); + + eblc->version = 0; + + /* Try to find the `EBLC' or `bloc' table in the font files. */ + /* Both tags describe the same table; `EBLC' is for OpenType */ + /* fonts while `bloc' is for TrueType GX fonts. Many fonts */ + /* contain both tags pointing to the same table. */ + + table = TT_LookUp_Table( face, TTAG_EBLC ); + if ( table < 0 ) + table = TT_LookUp_Table( face, TTAG_bloc ); + + if ( table < 0 ) + /* This table is optional */ + return TT_Err_Ok; + + eblc_offset = face->dirTables[table].Offset; + + if ( FILE_Seek( eblc_offset ) || + ACCESS_Frame( 8L ) ) + return error; + + eblc->version = GET_ULong(); + eblc->num_strikes = GET_ULong(); + + FORGET_Frame(); + + PTRACE2(( "-- Tables count: %12u\n", eblc->num_strikes )); + PTRACE2(( "-- Format version: %08lx\n", eblc->version )); + + if ( eblc->version != 0x00020000 ) + { + PERROR(( "Invalid file format!\n" )); + return TT_Err_Invalid_File_Format; + } + + if ( ALLOC_ARRAY( eblc->strikes, eblc->num_strikes, TT_SBit_Strike ) || + ACCESS_Frame( 48L * eblc->num_strikes ) ) + return error; + + strike = eblc->strikes; + + for ( i = 0; i < eblc->num_strikes; i++, strike++ ) + { /* loop through the tables and get all entries */ + ULong indexTablesSize; + TT_SBit_Line_Metrics* metrics; + Int count; + + + strike->ranges_offset = GET_ULong(); + indexTablesSize = GET_ULong(); /* dont' save */ + + strike->num_ranges = GET_ULong(); + strike->color_ref = GET_ULong(); + + /* load horizontal and vertical metrics */ + metrics = &strike->hori; + for ( count = 2; count > 0; count-- ) + { + metrics->ascender = GET_Char(); + metrics->descender = GET_Char(); + metrics->max_width = GET_Byte(); + + metrics->caret_slope_numerator = GET_Char(); + metrics->caret_slope_denominator = GET_Char(); + metrics->caret_offset = GET_Char(); + + metrics->min_origin_SB = GET_Char(); + metrics->min_advance_SB = GET_Char(); + metrics->max_before_BL = GET_Char(); + metrics->min_after_BL = GET_Char(); + metrics->pads[0] = GET_Char(); + metrics->pads[1] = GET_Char(); + + metrics = &strike->vert; + } + + strike->start_glyph = GET_UShort(); + strike->end_glyph = GET_UShort(); + strike->x_ppem = GET_Byte(); + strike->y_ppem = GET_Byte(); + strike->bit_depth = GET_Byte(); + strike->flags = GET_Char(); + + PTRACE4(( " start - end - ppemX - ppemY\n" )); + PTRACE4(( " %04d - %04d - %3u - %3u\n", + strike->start_glyph, + strike->end_glyph, + strike->x_ppem, + strike->y_ppem )); + } + + FORGET_Frame(); + + /* Load EBLC index ranges */ + strike = eblc->strikes; + + for ( i = 0; i < eblc->num_strikes; i++, strike++ ) + { + TT_SBit_Range* range; + UShort count = strike->num_ranges; + + + /* loop through the tables and get all entries */ + if ( ALLOC_ARRAY( strike->sbit_ranges, + strike->num_ranges, + TT_SBit_Range ) || + FILE_Seek( eblc_offset + strike->ranges_offset ) || + ACCESS_Frame( strike->num_ranges * 8L ) ) + return error; + + for ( range = strike->sbit_ranges; count > 0; count--, range++ ) + { + range->first_glyph = GET_UShort(); + range->last_glyph = GET_UShort(); + range->table_offset = eblc_offset + strike->ranges_offset + + GET_ULong(); + } + FORGET_Frame(); + + /* Now, read each index table */ + range = strike->sbit_ranges; + for ( count = strike->num_ranges; count > 0; count--, range++ ) + { + /* Read the header */ + if ( FILE_Seek( range->table_offset ) || + ACCESS_Frame( 8L ) ) + return error;; + + range->index_format = GET_UShort(); + range->image_format = GET_UShort(); + range->image_offset = GET_ULong(); + + FORGET_Frame(); + + error = Load_SBit_Range( strike, range, face ); + if (error) return error; + } + } + + return TT_Err_Ok; + } + + + static + void Free_TrueType_Eblc( TT_EBLC* eblc ) + { + if ( eblc ) + { + ULong i; + TT_SBit_Strike* strike = eblc->strikes; + + + strike = eblc->strikes; + + for ( i = eblc->num_strikes; i > 0; i--, strike++ ) + { + /* for each strike, release all glyph ranges */ + TT_SBit_Range* range = strike->sbit_ranges; + Int n; + + + for ( n = strike->num_ranges; n > 0; n--, range++ ) + { + /* release a range */ + FREE( range->glyph_offsets ); + FREE( range->glyph_codes ); + } + FREE( strike->sbit_ranges ); + strike->num_ranges = 0; + } + FREE( eblc->strikes ); + eblc->num_strikes = 0; + eblc->version = 0; + } + } + + + static + TT_Error Load_SBit_Metrics( TT_Big_Glyph_Metrics* metrics, + TT_SBit_Range* range, + ULong ebdt_offset ) + { + TT_Error error; + Byte height, width; + + + /* copy bitmap metrics for formats 2 and 5 */ + if ( ( ( range->index_format == 2 ) || ( range->index_format == 5 ) ) && + ( range->image_format == 5 ) ) + /* metrics are taken from current image bitmap */ + /* i.e. from `image.metrics' */ + { + TT_SBit_Metrics* rmetrics = &range->metrics; + + + metrics->bbox.xMin = rmetrics->horiBearingX; + metrics->bbox.xMax = metrics->bbox.xMin + rmetrics->width; + + metrics->bbox.yMax = rmetrics->horiBearingY; + metrics->bbox.yMin = metrics->bbox.yMax - rmetrics->height; + + metrics->horiBearingX = rmetrics->horiBearingX; + metrics->horiBearingY = metrics->bbox.yMax; + metrics->horiAdvance = rmetrics->horiAdvance; + + metrics->vertBearingX = rmetrics->vertBearingX; + metrics->vertBearingY = rmetrics->vertBearingY; + metrics->vertAdvance = rmetrics->vertAdvance; + + return TT_Err_Ok; + } + + switch ( range->image_format ) + { + case 1: + case 2: + case 6: + case 7: + case 8: + case 9: + { + Long length = 5L; + + + if ( range->image_format == 8 ) + length++; + + /* read the small metrics */ + if ( ACCESS_Frame( length ) ) + return error; + + height = GET_Byte(); + width = GET_Byte(); + + metrics->horiBearingX = GET_Char(); + metrics->horiBearingY = GET_Char(); + metrics->horiAdvance = GET_Byte(); + + FORGET_Frame(); + + metrics->bbox.xMin = metrics->horiBearingX; + metrics->bbox.yMax = metrics->horiBearingY; + metrics->bbox.xMax = metrics->bbox.xMin + width; + metrics->bbox.yMin = metrics->bbox.yMax - height; + + /* read the rest of the big metrics for the formats */ + /* that support it. */ + if ( ( range->image_format >= 6 ) && ( range->image_format != 8 ) ) + { + if ( ACCESS_Frame( 3L ) ) + return error; + + metrics->vertBearingX = (Int)GET_Char(); + metrics->vertBearingY = (Int)GET_Char(); + metrics->vertAdvance = (Int)GET_Char(); + + FORGET_Frame(); + } + else + { + /* XXX: How can we fill these when the information isn't */ + /* available? */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + } + } + break; + + case 5: /* metrics are taken from current image bitmap */ + /* i.e. from 'image.metrics' */ + break; + + default: + PERROR(( "Unsupported embedded bitmap format!\n" )); + return TT_Err_Invalid_File_Format; + } + + return TT_Err_Ok; + } + + + static + TT_Error Load_SBit_Image( TT_SBit_Strike strike, + UShort glyph_index, + Byte x_offset, + Byte y_offset, + ULong ebdt_offset, + TT_SBit_Image* image, + UShort component_depth ) + { + TT_Error error; + Byte height, width; + + ULong bitmap_offset; + + TT_SBit_Range* range = 0; + + TT_Big_Glyph_Metrics metrics; + + /********************************************************************/ + /* */ + /* Scan the strike's range for the position/metrics of the source */ + /* glyph. */ + { + UShort count = strike.num_ranges; + TT_SBit_Range* cur = strike.sbit_ranges; + + for ( ; count > 0; count--, cur++ ) + { + /* look for the glyph in the current range */ + switch ( cur->index_format ) + { + case 1: + case 2: + case 3: + if ( glyph_index >= cur->first_glyph && + glyph_index <= cur->last_glyph ) + { + UShort delta = glyph_index - cur->first_glyph; + + + range = cur; + bitmap_offset = cur->index_format == 2 + ? cur->image_offset + cur->image_size * delta + : cur->glyph_offsets[delta]; + goto Found; + } + break; + + case 4: + case 5: + { + UShort n; + + + for ( n = 0; n < cur->num_glyphs; n++ ) + if ( cur->glyph_codes[n] == glyph_index ) + { + range = cur; + bitmap_offset = cur->index_format == 4 + ? cur->glyph_offsets[n] + : cur->image_offset + cur->image_size * n; + goto Found; + } + } + break; + + default: + return TT_Err_Invalid_Glyph_Index; + } + } + /* Not found */ + return TT_Err_Invalid_Glyph_Index; + } + + Found: + if ( FILE_Seek( ebdt_offset + bitmap_offset ) ) + return error; + + /* First of all, load the metrics if needed */ + error = Load_SBit_Metrics( &metrics, range, ebdt_offset ); + if ( error ) + return error; + + width = metrics.bbox.xMax - metrics.bbox.xMin; + height = metrics.bbox.yMax - metrics.bbox.yMin; + + if ( !component_depth ) + { + image->metrics = metrics; + + image->map.width = width; + image->map.rows = height; + + image->map.cols = (width + 7) >> 3; + image->map.size = height * image->map.cols; + + if ( REALLOC( image->map.bitmap, image->map.size ) ) + return error; + + MEM_Set( image->map.bitmap, 0, image->map.size ); + } + + /* Now, load the data as needed */ + switch ( range->image_format ) + { + case 1: + case 6: /* byte-aligned data */ + error = Load_BitmapData( image, + height * (( width + 7 ) >> 3), + x_offset, y_offset, + width, height, + 1 ); + if ( error ) + return error; + break; + + case 2: + case 5: + case 7: + error = Load_BitmapData( image, + (width * height + 7) >> 3, + x_offset, y_offset, + width, height, 0 ); + if ( error ) + return error; + break; + + case 8: + case 9: + { + /* Now, load composite sbit glyphs */ + /* This code is not sophisticated */ + + TT_SBit_Component* component_array; + UShort num_components; + + Int i = 0; + + + if ( ACCESS_Frame( 2L ) ) + return error; + num_components = GET_UShort(); + FORGET_Frame(); + + MEM_Alloc( component_array, + sizeof ( TT_SBit_Component ) * num_components ); + + if ( ACCESS_Frame( 4L * num_components ) ) + return error; + + for ( i = 0; i < num_components; i++ ) + { + component_array[i].glyph_code = GET_UShort(); + component_array[i].x_offset = GET_Char(); + component_array[i].y_offset = GET_Char(); + } + + FORGET_Frame(); + + component_depth++; + + for ( i = 0; i < num_components; i++ ) + { + error = Load_SBit_Image( strike, component_array[i].glyph_code, + component_array[i].x_offset, + component_array[i].y_offset, + ebdt_offset, + image, + component_depth ); + if ( error ) + return error; + } + FREE( component_array ); + break; + + default: + return TT_Err_Invalid_File_Format; + } + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function: Load_TrueType_Ebdt + * + ******************************************************************/ + + static + TT_Error Load_TrueType_Ebdt( PFace face, + TT_SBit_Strike strike, + ULong glyph_index, + TT_SBit_Image* image ) + { + DEFINE_LOCALS; + + ULong ebdt_offset; + ULong version; + Long i; + + + /* Try to find the `EBDT' or `bdat' table in the font files. */ + /* Both tags describe the same table, `EBDT' is for OpenType */ + /* fonts, while `bdat' is for TrueType GX fonts. Many fonts */ + /* contain both tags pointing to the same table */ + + i = TT_LookUp_Table( face, TTAG_EBDT ); + if ( i < 0 ) + i = TT_LookUp_Table( face, TTAG_bdat ); + + if ( i < 0 ) + return TT_Err_Table_Missing; + + ebdt_offset = face->dirTables[i].Offset; + + if ( FILE_Seek( ebdt_offset ) || + ACCESS_Frame( 4L ) ) /* read into frame */ + return error; + + version = GET_ULong(); + FORGET_Frame(); + + PTRACE2(( "-- Format version : %08lx\n", version )); + if ( version != 0x00020000 ) + { + PERROR(( "Invalid file format!\n" )); + return TT_Err_Invalid_File_Format; + } + + /* This doesn't compile, I simply commented it out ?? - David */ + /* PTRACE4(( "-- Format: %d\n", range->image_format )); */ + + error = Load_SBit_Image( strike, + glyph_index, + 0, 0, + ebdt_offset, + image, + 0 ); + if ( error ) + return error; + + return TT_Err_Ok; + } + + + static TT_Error EBLC_Create( void* ext, + PFace face ) + { + TT_EBLC* eblc = (TT_EBLC*)ext; + + + /* by convention */ + if ( !eblc ) + return TT_Err_Ok; + + return Load_TrueType_Eblc( face, eblc ); + } + + + static TT_Error EBLC_Destroy( void* ext, + PFace face ) + { + TT_EBLC* eblc = (TT_EBLC*)ext; + + + (void)face; + + if ( eblc ) + Free_TrueType_Eblc( eblc ); + + return TT_Err_Ok; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Init_SBit_Extension */ + /* */ + /* <Description> */ + /* Initialize the embedded bitmaps extension for the */ + /* FreeType engine. */ + /* */ + /* <Input> */ + /* engine :: handle to current FreeType library instance */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_Init_SBit_Extension( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + error = TT_Register_Extension( _engine, + SBIT_ID, + sizeof ( TT_EBLC ), + EBLC_Create, + EBLC_Destroy ); + + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Get_Face_Bitmaps */ + /* */ + /* <Description> */ + /* Loads the `EBLC' table from a font file, if any. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* */ + /* <Output> */ + /* eblc_table :: a descriptor for the EBLC table */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns TT_Err_Table_Missing if the */ + /* font contains no embedded bitmaps. All fields in */ + /* `eblc_table' will then be set to 0. */ + /* */ + EXPORT_FUNC + TT_Error TT_Get_Face_Bitmaps( TT_Face face, + TT_EBLC* eblc_table ) + { + PFace faze = HANDLE_Face( face ); + TT_EBLC* eblc; + TT_Error error; + + + error = TT_Extension_Get( faze, SBIT_ID, (void**)&eblc ); + if ( !error ) + { + if ( eblc->version ) + { + *eblc_table = *eblc; + return TT_Err_Ok; + } + error = TT_Err_Table_Missing; + } + + eblc_table->version = 0; + eblc_table->num_strikes = 0; + eblc_table->strikes = 0; + + return error; + } + + +/******************************************************************* + * + * <Function> TT_Get_SBit_Strike + * + * <Description> + * Loads suitable strike (bitmap sizetable) for given instance. + * This strike includes sbitLineMetrics. + * + * <Input> + * face :: the source face + * instance :: the current size instance + * + * <Output> + * strike :: the bitmap strike descriptor + * + * <Return> + * TrueType error code. 0 means success. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_SBit_Strike( TT_Face face, + TT_Instance instance, + TT_SBit_Strike* strike ) + { + TT_Error error; + PFace faze = HANDLE_Face( face ); + PInstance ins = HANDLE_Instance( instance ); + + TT_EBLC* eblc; + TT_Int x_ppem, y_ppem; + + + if ( !strike || !ins || ins->owner != faze ) + return TT_Err_Invalid_Argument; + + error = TT_Extension_Get( faze, SBIT_ID, (void**)&eblc ); + if ( error ) + goto Exit; + + /********************************************************************/ + /* */ + /* Look for an sbit strike that matches the current x and y ppms */ + /* */ + { + UShort count = eblc->num_strikes; + TT_SBit_Strike* cur = eblc->strikes; + + + x_ppem = ins->metrics.x_ppem; + y_ppem = ins->metrics.y_ppem; + + MEM_Set( strike, 0, sizeof ( TT_SBit_Strike ) ); + + for ( ; count > 0; count--, cur++ ) + if ( cur->x_ppem == x_ppem && + cur->y_ppem == y_ppem ) + { + *strike = *cur; + break; + } + + /* return immediately if we didn't find an appropriate strike */ + if ( !strike->num_ranges ) + error = TT_Err_Invalid_PPem; + } + + Exit: + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_Glyph_Bitmap */ + /* */ + /* <Description> */ + /* Loads a given glyph embedded bitmap. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* instance :: current size/transform instance */ + /* glyph_index :: index of source glyph */ + /* bitmap :: target embedded bitmap descriptor */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns an error if there is no */ + /* embedded bitmap for the glyph at the given */ + /* instance. */ + /* */ + EXPORT_FUNC + TT_Error TT_Load_Glyph_Bitmap( TT_Face face, + TT_Instance instance, + TT_UShort glyph_index, + TT_SBit_Image* image ) + { + TT_Stream stream; + TT_Error error; + + PFace faze = HANDLE_Face( face ); + PInstance ins = HANDLE_Instance( instance ); + + TT_SBit_Strike strike; + + + if ( ins->owner != faze ) + { + error = TT_Err_Invalid_Argument; + goto Fail; + } + + /********************************************************************/ + /* */ + /* Look for an sbit strike that matches the current x and y ppms */ + /* */ + error = TT_Get_SBit_Strike( face, instance, &strike ); + if ( error ) + goto Fail; + + /* return immediately if the glyph index isn't in the strike extent */ + if ( glyph_index < strike.start_glyph || + glyph_index > strike.end_glyph ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Fail; + } + + { + image->bit_depth = 1; + + if ( !USE_Stream( faze->stream, stream ) ) + { + error = Load_TrueType_Ebdt( faze, strike, glyph_index, image ); + + DONE_Stream( stream ); + + /* exit successfully if we can */ + if ( !error ) + { + image->map.flow = TT_Flow_Down; + + Crop_Bitmap( image ); + + /* correct sbit metrics */ + { + TT_Big_Glyph_Metrics* metrics = &image->metrics; + + + metrics->bbox.xMin *= 64; + metrics->bbox.xMax *= 64; + + metrics->bbox.yMax *= 64; + metrics->bbox.yMin *= 64; + + metrics->horiBearingX *= 64; + metrics->horiBearingY *= 64; + metrics->horiAdvance *= 64; + + metrics->vertBearingX *= 64; + metrics->vertBearingY *= 64; + metrics->vertAdvance *= 64; + } + + goto Exit; + } + } + } + + Fail: + image->map.width = 0; + image->map.rows = 0; + image->map.cols = 0; + image->map.size = 0; + image->map.bitmap = 0; + image->map.flow = 0; + image->bit_depth = 0; + + Exit: + return error; + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_New_SBit_Image */ + /* */ + /* <Description> */ + /* Allocates a new embedded bitmap container. */ + /* */ + /* <Output> */ + /* image :: sbit image */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_FUNC + TT_Error TT_New_SBit_Image( TT_SBit_Image** image ) + { + return MEM_Alloc( *image, sizeof ( **image ) ); + } + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Done_SBit_Image */ + /* */ + /* <Description> */ + /* Releases an embedded bitmap container. */ + /* */ + /* <Input> */ + /* image :: sbit image */ + /* */ + EXPORT_FUNC + void TT_Done_SBit_Image( TT_SBit_Image* image ) + { + FREE( image->map.bitmap ); + FREE( image ); + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxsbit.h b/Build/source/libs/libttf/extend/ftxsbit.h new file mode 100644 index 00000000000..05e7b1fc052 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxsbit.h @@ -0,0 +1,490 @@ +/******************************************************************* + * + * ftxsbit.h + * + * embedded bitmap support API extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This extension is used to load the embedded bitmaps present + * in certain TrueType files. + * + ******************************************************************/ + +#ifndef FTXSBIT_H +#define FTXSBIT_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Metrics */ + /* */ + /* <Description> */ + /* A structure used to hold the big metrics of a given */ + /* glyph bitmap in a TrueType or OpenType font. These */ + /* are usually found in the `EBDT' table. */ + /* */ + /* <Fields> */ + /* height :: glyph height in pixels */ + /* width :: glyph width in pixels */ + /* */ + /* horiBearingX :: horizontal left bearing */ + /* horiBearingY :: horizontal top bearing */ + /* horiAdvance :: horizontal advance */ + /* */ + /* vertBearingX :: vertical left bearing */ + /* vertBearingY :: vertical top bearing */ + /* vertAdvance :: vertical advance */ + /* */ + typedef struct TT_SBit_Metrics_ + { + TT_Byte height; + TT_Byte width; + + TT_Char horiBearingX; + TT_Char horiBearingY; + TT_Byte horiAdvance; + + TT_Char vertBearingX; + TT_Char vertBearingY; + TT_Byte vertAdvance; + + } TT_SBit_Metrics; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Small_Metrics */ + /* */ + /* <Description> */ + /* A structure used to hold the small metrics of a given */ + /* glyph bitmap in a TrueType or OpenType font. These */ + /* are usually found in the `EBDT' table. */ + /* */ + /* <Fields> */ + /* height :: glyph height in pixels */ + /* width :: glyph width in pixels */ + /* */ + /* bearingX :: left-side bearing */ + /* bearingY :: top-side bearing */ + /* advance :: advance width or height */ + /* */ + typedef struct TT_SBit_Small_Metrics_ + { + TT_Byte height; + TT_Byte width; + + TT_Char bearingX; + TT_Char bearingY; + TT_Byte advance; + + } TT_SBit_Small_Metrics; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Line_Metrics */ + /* */ + /* <Description> */ + /* A structure used to describe the text line metrics of */ + /* a given bitmap strike, for either horizontal or */ + /* vertical layout. */ + /* */ + /* <Fields> */ + /* ascender :: ascender in pixels */ + /* descender :: descender in pixels */ + /* max_width :: maximum glyph width in pixels */ + /* */ + /* caret_slope_enumerator :: Rise of the caret slope, */ + /* typically set to 1 for non-italic fonts. */ + /* caret_slope_denominator :: Rise of the caret slope, */ + /* typically set to 0 for non-italic fonts. */ + /* caret_offset :: Offset in pixels */ + /* to move the caret for proper positioning. */ + /* */ + /* min_origin_SB :: Minimum of horiBearingX */ + /* (resp. vertBearingY) */ + /* min_advance_SB :: Minimum of */ + /* (hori. advance - ( horiBearingX + width )) */ + /* (resp. vert. advance - ( vertBearingY + height )) */ + /* max_before_BL :: Maximum of horiBearingY */ + /* (resp. Maximum of vertBearingY) */ + /* min_after_BL :: Minimum of ( horiBearingY - height ) */ + /* (resp. vertBearingX - width ) */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + TT_Char ascender; + TT_Char descender; + TT_Byte max_width; + TT_Char caret_slope_numerator; + TT_Char caret_slope_denominator; + TT_Char caret_offset; + TT_Char min_origin_SB; + TT_Char min_advance_SB; + TT_Char max_before_BL; + TT_Char min_after_BL; + TT_Char pads[2]; + + } TT_SBit_Line_Metrics; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Range */ + /* */ + /* <Description> */ + /* A TrueType/OpenType subIndexTable as defined in the */ + /* `EBLC' or `bloc' tables. */ + /* */ + /* <Fields> */ + /* */ + /* first_glyph :: first glyph index in range */ + /* last_glyph :: last glyph index in range */ + /* */ + /* index_format :: format of index table. valid */ + /* values are 1 to 5. */ + /* */ + /* image_format :: format of `EBDT' image data */ + /* image_offset :: offset to image data in `EBDT' */ + /* */ + /* image_size :: for index formats 2 and 5. This is */ + /* the size in bytes of each glyph bitmap */ + /* glyph bitmap */ + /* */ + /* big_metrics :: for index formats 2 and 5. This is */ + /* the big metrics for each glyph bitmap */ + /* */ + /* num_glyphs :: for index formats 4 and 5. This is */ + /* the number of glyphs in the code */ + /* array. */ + /* */ + /* glyph_offsets :: for index formats 1 and 3. */ + /* glyph_codes :: for index formats 4 and 5. */ + /* */ + /* table_offset :: offset of index table in `EBLC' table */ + /* -- only used during strike loading. */ + /* */ + typedef struct TT_SBit_Range + { + TT_UShort first_glyph; + TT_UShort last_glyph; + + TT_UShort index_format; + TT_UShort image_format; + TT_ULong image_offset; + + TT_ULong image_size; + TT_SBit_Metrics metrics; + TT_ULong num_glyphs; + + TT_ULong* glyph_offsets; + TT_UShort* glyph_codes; + + TT_ULong table_offset; + + } TT_SBit_Range; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Strike */ + /* */ + /* <Description> */ + /* A structure used describe a given bitmap strike in the */ + /* `EBLC' or `bloc' tables. */ + /* */ + /* <Fields> */ + /* */ + /* num_index_ranges :: number of index ranges */ + /* index_ranges :: array of glyph index ranges */ + /* */ + /* color_ref :: unused. color reference? */ + /* hori :: line metrics for horizontal layouts. */ + /* vert :: line metrics for vertical layouts. */ + /* */ + /* start_glyph :: lowest glyph index for this strike. */ + /* end_glyph :: higher glyph index for this strike. */ + /* */ + /* x_ppem :: horizontal pixels per EM */ + /* y_ppem :: vertical pixels per EM */ + /* bit_depth :: bit depth. valid values are 1, 2, 4 & 8 */ + /* flags :: vertical or horizontal? */ + /* */ + typedef struct TT_SBit_Strike_ + { + TT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + TT_ULong ranges_offset; + + TT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + TT_UShort start_glyph; + TT_UShort end_glyph; + + TT_Byte x_ppem; + TT_Byte y_ppem; + TT_Byte bit_depth; + TT_Char flags; + + } TT_SBit_Strike; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Component */ + /* */ + /* <Description> */ + /* A simple structure to describe a compound sbit element */ + /* */ + /* <Fields> */ + /* glyph_code :: element's glyph index */ + /* x_offset :: element's left bearing */ + /* y_offset :: element's top bearing */ + /* */ + typedef struct TT_SBit_Component_ + { + TT_UShort glyph_code; + TT_Char x_offset; + TT_Char y_offset; + + } TT_SBit_Component; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Scale */ + /* */ + /* <Description> */ + /* A structure used describe a given bitmap scaling */ + /* table, as defined for the `EBSC' table. */ + /* */ + /* <Fields> */ + /* hori :: horizontal line metrics */ + /* vert :: vertical line metrics */ + /* */ + /* x_ppem :: horizontal pixels per EM */ + /* y_ppem :: vertical pixels per EM */ + /* */ + /* x_ppem_substitute :: substitution x_ppem */ + /* y_ppem_substitute :: substitution y_ppem */ + /* */ + typedef struct TT_SBit_Scale_ + { + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + TT_Byte x_ppem; + TT_Byte y_ppem; + + TT_Byte x_ppem_substitute; + TT_Byte y_ppem_substitute; + + } TT_SBit_Scale; + + + /*************************************************************/ + /* */ + /* <Struct> TT_SBit_Image */ + /* */ + /* <Description> */ + /* A structure used to describe a given embedded bitmap */ + /* image. */ + /* */ + /* <Fields> */ + /* map :: bitmap descriptor */ + /* bit_depth :: pixel bit depth */ + /* metrics :: glyph metrics for the bitmap */ + /* */ + typedef struct TT_SBit_Image_ + { + TT_Raster_Map map; + int bit_depth; + TT_Big_Glyph_Metrics metrics; + + } TT_SBit_Image; + + + /*************************************************************/ + /* */ + /* <Struct> TT_EBLC */ + /* */ + /* <Description> */ + /* A structure used to describe the `EBLC' table from */ + /* a TrueType font. */ + /* */ + /* <Fields> */ + /* version :: version number of the EBLC table */ + /* */ + /* num_strikes :: the number of strikes, i.e. bitmap */ + /* sizes, present in this font */ + /* */ + /* strikes :: array of strikes */ + /* */ + typedef struct TT_EBLC_ + { + TT_ULong version; + TT_ULong num_strikes; + TT_SBit_Strike* strikes; + + } TT_EBLC; + + + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Init_SBit_Extension */ + /* */ + /* <Description> */ + /* Initializes the embedded bitmap extension for the */ + /* FreeType engine. */ + /* */ + /* <Input> */ + /* engine :: handle to current FreeType library instance */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_Init_SBit_Extension( TT_Engine engine ); + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Get_Face_Bitmaps */ + /* */ + /* <Description> */ + /* Loads the `EBLC' table from a font file, if any. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* */ + /* <Output> */ + /* eblc_table :: a descriptor for the EBLC table */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns TT_Err_Table_Missing if the */ + /* font contains no embedded bitmaps. All fields in */ + /* `eblc_table' will then be set to 0. */ + /* */ + EXPORT_DEF + TT_Error TT_Get_Face_Bitmaps( TT_Face face, + TT_EBLC* eblc_table ); + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_New_SBit_Image */ + /* */ + /* <Description> */ + /* Allocates a new embedded bitmap container. */ + /* */ + /* <Output> */ + /* image :: sbit image */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_New_SBit_Image( TT_SBit_Image** image ); + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Done_SBit_Image */ + /* */ + /* <Description> */ + /* Releases an embedded bitmap container. */ + /* */ + /* <Input> */ + /* image :: sbit image */ + /* */ + EXPORT_DEF + void TT_Done_SBit_Image( TT_SBit_Image* image ); + + + /*************************************************************/ + /* */ + /* <Function> TT_Get_SBit_Strike */ + /* */ + /* <Description> */ + /* Loads a suitable strike (bitmap sizetable) for the */ + /* given instance. This strike includes */ + /* sbitLineMetrics. */ + /* */ + /* <Input> */ + /* face :: the source face */ + /* instance :: the current size instance */ + /* */ + /* <Output> */ + /* strike :: the bitmap strike descriptor */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + EXPORT_DEF + TT_Error TT_Get_SBit_Strike( TT_Face face, + TT_Instance instance, + TT_SBit_Strike* strike ); + + + /*************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_Glyph_Bitmap */ + /* */ + /* <Description> */ + /* Loads a given glyph embedded bitmap. */ + /* */ + /* <Input> */ + /* face :: handle to the source TrueType font/face */ + /* instance :: current size/transform instance */ + /* glyph_index :: index of source glyph */ + /* bitmap :: target embedded bitmap descriptor */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function returns an error if there is no */ + /* embedded bitmap for the glyph at the given */ + /* instance. */ + /* */ + EXPORT_DEF + TT_Error TT_Load_Glyph_Bitmap( TT_Face face, + TT_Instance instance, + TT_UShort glyph_index, + TT_SBit_Image* bitmap ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXSBIT_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxwidth.c b/Build/source/libs/libttf/extend/ftxwidth.c new file mode 100644 index 00000000000..bb3a258282b --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxwidth.c @@ -0,0 +1,186 @@ +/******************************************************************* + * + * ftxwidth.c 1.0 + * + * Glyph Widths (and Heights) fast retrieval extension + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This extension is used to parse the "glyf" table of a TrueType + * file in order to extract the bbox of a given range of glyphs. + * + * The bbox is then used to build font unit widths and height + * that are returned in two parallel arrays. + * + * This extension is needed by the FreeType/2 OS/2 Font Driver. + * + ******************************************************************/ + + +#include "ttconfig.h" +#include "ftxwidth.h" +#include "ttdebug.h" +#include "ttobjs.h" +#include "ttfile.h" +#include "tttags.h" +#include "ttload.h" + +/* Required by the tracing mode */ + +#undef TT_COMPONENT +#define TT_COMPONENT trace_any + + + /******************************************************************/ + /* */ + /* Function: TT_Get_Face_Widths */ + /* */ + /* Description: Returns the widths and/or heights of a given */ + /* range of glyphs for a face. */ + /* */ + /* Input: */ + /* face :: face handle */ + /* */ + /* first_glyph :: first glyph in range */ + /* */ + /* last_glyph :: last glyph in range */ + /* */ + /* widths :: address of table receiving the widths */ + /* expressed in font units (ushorts). Set */ + /* this parameter to NULL if you're not */ + /* interested by these values. */ + /* */ + /* heights :: address of table receiving the heights */ + /* expressed in font units (ushorts). Set */ + /* this parameter to NULL if you're not */ + /* interested by these values. */ + /* */ + /* Returns: */ + /* Error code */ + /* */ + /* */ + /******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Face_Widths( TT_Face face, + TT_UShort first_glyph, + TT_UShort last_glyph, + TT_UShort* widths, + TT_UShort* heights ) + { + DEFINE_ALL_LOCALS; + + PFace faze = HANDLE_Face(face); + UShort n; + Long table; + + ULong glyf_offset; /* offset of glyph table in file */ + UShort zero_width = 0; /* width of glyph 0 */ + UShort zero_height = 0; /* height of glyph 0 */ + + Bool zero_loaded = 0; + +#ifndef TT_HUGE_PTR + PStorage locations; +#else + Storage TT_HUGE_PTR * locations; +#endif + TT_BBox bbox; + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( last_glyph >= faze->numGlyphs || + first_glyph > last_glyph ) + return TT_Err_Invalid_Argument; + + /* find "glyf" table */ + table = TT_LookUp_Table( faze, TTAG_glyf ); + if ( table < 0 ) + { + PERROR(( "ERROR: there is no glyph table in this font file!\n" )); + return TT_Err_Glyf_Table_Missing; + } + glyf_offset = faze->dirTables[table].Offset; + + /* now access stream */ + if ( USE_Stream( faze->stream, stream ) ) + return error; + + locations = faze->glyphLocations + first_glyph; + + /* loop to load each glyph in the range */ + for ( n = first_glyph; n <= last_glyph; n++ ) + { + if ( n + 1 < faze->numGlyphs && + locations[0] == locations[1] ) + { + /* Note : Glyph 0 is always used to indicate a missing glyph */ + /* in a range. We must thus return its width and height */ + /* where appropriate when we find an undefined glyph. */ + if ( zero_loaded == 0 ) + { + if ( FILE_Seek( glyf_offset + faze->glyphLocations[0] ) || + ACCESS_Frame( 10L ) ) + goto Fail; + + (void)GET_Short(); /* skip number of contours */ + + bbox.xMin = GET_Short(); + bbox.yMin = GET_Short(); + bbox.xMax = GET_Short(); + bbox.yMax = GET_Short(); + + FORGET_Frame(); + + zero_width = (UShort)(bbox.xMax - bbox.xMin); + zero_height = (UShort)(bbox.yMax - bbox.yMin); + zero_loaded = 1; + } + + if ( widths ) + *widths++ = zero_width; + + if ( heights ) + *heights++ = zero_height; + } + else + { + /* normal glyph, read header */ + if ( FILE_Seek( glyf_offset + locations[0] ) || + ACCESS_Frame( 10L ) ) + goto Fail; + + (void)GET_Short(); /* skip number of contours */ + + bbox.xMin = GET_Short(); + bbox.yMin = GET_Short(); + bbox.xMax = GET_Short(); + bbox.yMax = GET_Short(); + + FORGET_Frame(); + + if ( widths ) + *widths++ = (UShort)(bbox.xMax - bbox.xMin); + + if ( heights ) + *heights++ = (UShort)(bbox.yMax - bbox.yMin); + } + } + + Fail: + DONE_Stream( stream ); + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/extend/ftxwidth.h b/Build/source/libs/libttf/extend/ftxwidth.h new file mode 100644 index 00000000000..5ac72517927 --- /dev/null +++ b/Build/source/libs/libttf/extend/ftxwidth.h @@ -0,0 +1,80 @@ +/******************************************************************* + * + * ftxwidth.h + * + * Glyph Widths (and Heights) fast retrieval extension. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This extension is used to parse the `glyf' table of a TrueType + * file in order to extract the bounding box of a given range of glyphs. + * + * The bounding box is then used to build font unit widths and heights + * that are returned in two parallel arrays. + * + * This extension is needed by the FreeType/2 OS/2 Font Driver. + * + ******************************************************************/ + +#ifndef FTXWIDTH_H +#define FTXWIDTH_H + +#include "freetype.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /******************************************************************/ + /* */ + /* Function: TT_Get_Face_Widths */ + /* */ + /* Description: Returns the widths and/or heights of a given */ + /* range of glyphs for a face. */ + /* */ + /* Input: */ + /* face :: face handle */ + /* */ + /* first_glyph :: first glyph in range */ + /* */ + /* last_glyph :: last glyph in range */ + /* */ + /* widths :: address of table receiving the widths */ + /* expressed in font units (ushorts). Set */ + /* this parameter to NULL if you're not */ + /* interested by these values. */ + /* */ + /* heights :: address of table receiving the heights */ + /* expressed in font units (ushorts). Set */ + /* this parameter to NULL if you're not */ + /* interested by these values */ + /* */ + /* Returns: */ + /* Error code */ + /* */ + /* */ + /******************************************************************/ + + EXPORT_DEF + TT_Error TT_Get_Face_Widths( TT_Face face, + TT_UShort first_glyph, + TT_UShort last_glyph, + TT_UShort* widths, + TT_UShort* heights ); + +#ifdef __cplusplus +} +#endif + +#endif /* FTXWIDTH_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/extend/readme.1st b/Build/source/libs/libttf/extend/readme.1st new file mode 100644 index 00000000000..cce94cdfad1 --- /dev/null +++ b/Build/source/libs/libttf/extend/readme.1st @@ -0,0 +1,61 @@ +This directory contains several extensions to the core engine. + +An extension is a separately compilable unit which can be linked by +a client application to add new functionalities to the engine. + +There are two kinds of extensions: an `API extension' provides +clients with new APIs to access internal engine structures or data, +while an `engine extension' implements new TrueType data or table +management. + +This directory contains the following: + + ftxcmap: An API extension to iterate over cmaps. + + ftxgasp: A simple API extension which returns the TrueType `gasp' + table to client applications, when found in a font file. + Though this table is always loaded by the engine, there + is no function in the core API to access it. The reason + is simple: to demonstrate a simple API extension with + `ftxgasp'! + + ftxkern: This engine extension is used to access kerning data, + when available in a font file. Note that it implements + on-the-fly loading and retrieving of kerning tables. + However, it doesn't interpret or process the data, and + client applications should use it according to the + TrueType specification. + + ftxpost: An engine extension to load the PostScript glyph names + of the `post' table. See the `ftzoom' program for an + example how to use it. + + ftxwidth: A simple extension used to load the widths and heights + of a given range of glyphs in a face. Results are + expressed in unscaled font units. This is required by + the latest version of the FreeType/2 DLL to speed up + font loading in the GRE (the OS/2 GRaphics Engine). It + can be used by other applications though... + + ftxerr18: This extension simply converts a TrueType engine error + code into a corresponding string describing the error. + It is useful if you intend to write a package for end + users and want to give them not `Error code 135' but + `OS/2 table missing'. See docs/errstr.txt for a + description how to use it (really simple!). ftxerr18 + supports localization of error strings (that is: error + strings are automatically translated into supported + languages) using gettext(). See docs/i18n.txt about + using gettext. + + ftxsbit: Embedded bitmap support. This is an engine extension. + See e.g. the `ftstrtto' program for its usage. + + ftxopen, + ftxgsub, + ftxgpos, + ftxgdef: This is experimental stuff for TrueType Open support! + Please ignore it or help debugging :-) + + +--- END --- diff --git a/Build/source/libs/libttf/freetype.h b/Build/source/libs/libttf/freetype.h new file mode 100644 index 00000000000..f5328d4624d --- /dev/null +++ b/Build/source/libs/libttf/freetype.h @@ -0,0 +1,1147 @@ +/******************************************************************* + * + * freetype.h + * + * High-level interface specification. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Note: + * + * This is the only file that should be included by client + * application sources. All other types and functions defined + * in the `tt*.h' files are library internals and should not be + * included. + * + ******************************************************************/ + +#ifndef FREETYPE_H +#define FREETYPE_H + + +#define TT_FREETYPE_MAJOR 1 +#define TT_FREETYPE_MINOR 4 + + +#include "fterrid.h" +#include "ftnameid.h" + +/* To make freetype.h independent from configuration files we check */ +/* whether EXPORT_DEF has been defined already. */ + +#ifndef EXPORT_DEF +#define EXPORT_DEF extern +#endif + +/* The same for TT_Text. If you define the HAVE_TT_TEXT macro, you */ +/* have to provide a typedef declaration for TT_Text before */ +/* including this file. */ + +#ifndef HAVE_TT_TEXT +#define HAVE_TT_TEXT + typedef char TT_Text; /* The data type to represent */ + /* file name string elements. */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + + /*******************************************************************/ + /* */ + /* FreeType types definitions. */ + /* */ + /* All these begin with a 'TT_' prefix. */ + /* */ + /*******************************************************************/ + + typedef int TT_Bool; + + typedef signed long TT_Fixed; /* signed fixed 16.16 float */ + + typedef signed short TT_FWord; /* distance in FUnits */ + typedef unsigned short TT_UFWord; /* unsigned distance */ + + typedef char TT_String; + typedef signed char TT_Char; + typedef unsigned char TT_Byte; + typedef signed short TT_Short; + typedef unsigned short TT_UShort; + typedef int TT_Int; + typedef unsigned int TT_UInt; + typedef signed long TT_Long; + typedef unsigned long TT_ULong; + + typedef signed short TT_F2Dot14; /* Signed fixed float 2.14 used for */ + /* unit vectors, with layout */ + /* */ + /* s : 1 -- sign bit */ + /* m : 1 -- integer bit */ + /* f : 14 -- unsigned fractional */ + /* */ + /* `s:m' is the 2-bit signed int */ + /* value to which the positive */ + /* fractional part should be added. */ + + typedef signed long TT_F26Dot6; /* 26.6 fixed float, used for */ + /* glyph points pixel coordinates. */ + + typedef signed long TT_Pos; /* Point position, expressed either */ + /* in fractional pixels or notional */ + /* units, depending on context. */ + /* For example, glyph coordinates */ + /* returned by TT_Load_Glyph() are */ + /* expressed in font units if */ + /* scaling wasn't requested, and */ + /* in 26.6 fractional pixels if it */ + /* was. */ + + + struct TT_UnitVector_ /* guess what... */ + { + TT_F2Dot14 x; + TT_F2Dot14 y; + }; + + typedef struct TT_UnitVector_ TT_UnitVector; + + + struct TT_Vector_ /* simple vector type */ + { + TT_F26Dot6 x; + TT_F26Dot6 y; + }; + + typedef struct TT_Vector_ TT_Vector; + + + /* A simple 2x2 matrix used for transformations. */ + /* You should use 16.16 fixed floats. */ + /* */ + /* x' = xx*x + xy*y */ + /* y' = yx*x + yy*y */ + /* */ + + struct TT_Matrix_ + { + TT_Fixed xx, xy; + TT_Fixed yx, yy; + }; + + typedef struct TT_Matrix_ TT_Matrix; + + + /* A structure used to describe the source glyph to the renderer. */ + + struct TT_Outline_ + { + TT_Short n_contours; /* number of contours in glyph */ + TT_UShort n_points; /* number of points in the glyph */ + + TT_Vector* points; /* the outline's points */ + TT_Byte* flags; /* the points flags */ + TT_UShort* contours; /* the contour end points */ + + /* The following flag indicates that the outline owns the arrays it */ + /* refers to. Typically, this is true of outlines created from the */ + /* TT_New_Outline() API, while it isn't for those returned by */ + /* TT_Get_Glyph_Outline(). */ + + TT_Bool owner; /* The outline owns the coordinates, */ + /* flags and contours array it uses. */ + + /* The following flags are set automatically by */ + /* TT_Get_Glyph_Outline(). Their meaning is the following: */ + /* */ + /* high_precision If true, the scan-line converter will use a */ + /* higher precision to render bitmaps (i.e., a */ + /* 1/1024 pixel precision). This is important for */ + /* small ppem sizes. */ + /* */ + /* second_pass If true, the scan-line converter performs a */ + /* second sweep phase dedicated to find vertical */ + /* drop-outs. If false, only horizontal drop-outs */ + /* will be checked during the first vertical */ + /* sweep (yes, this is a bit confusing but it is */ + /* really the way it should work). This is */ + /* important for small ppems too. */ + /* */ + /* dropout_mode Specifies the TrueType drop-out mode to use for */ + /* continuity checking. Valid values are 0 (no */ + /* check), 1, 2, 4, and 5. */ + /* */ + /* Most of the engine's users will safely ignore these fields... */ + + TT_Bool high_precision; /* high precision rendering */ + TT_Bool second_pass; /* two sweeps rendering */ + TT_Char dropout_mode; /* dropout mode */ + }; + + typedef struct TT_Outline_ TT_Outline; + + + /* A structure used to describe a simple bounding box. */ + + struct TT_BBox_ + { + TT_Pos xMin; + TT_Pos yMin; + TT_Pos xMax; + TT_Pos yMax; + }; + + typedef struct TT_BBox_ TT_BBox; + + + /* A structure used to return glyph metrics. */ + /* */ + /* The `bearingX' isn't called `left-side bearing' anymore because */ + /* it has different meanings depending on the glyph's orientation. */ + /* */ + /* The same is true for `bearingY', which is the top-side bearing */ + /* defined by the TT_Spec, i.e., the distance from the baseline to */ + /* the top of the glyph's bbox. According to our current convention, */ + /* this is always the same as `bbox.yMax' but we make it appear for */ + /* consistency in its proper field. */ + /* */ + /* The `advance' field is the advance width for horizontal layout, */ + /* and advance height for vertical layouts. */ + + struct TT_Glyph_Metrics_ + { + TT_BBox bbox; /* glyph bounding box */ + + TT_Pos bearingX; /* left-side bearing */ + TT_Pos bearingY; /* top-side bearing, per se the TT spec */ + + TT_Pos advance; /* advance width (or height) */ + }; + + typedef struct TT_Glyph_Metrics_ TT_Glyph_Metrics; + + + /* A structure used to return horizontal _and_ vertical glyph */ + /* metrics. */ + /* */ + /* A glyph can be used either in a horizontal or vertical layout. */ + /* Its glyph metrics vary with orientation. The TT_Big_Glyph_Metrics */ + /* structure is used to return _all_ metrics in one call. */ + + struct TT_Big_Glyph_Metrics_ + { + TT_BBox bbox; /* glyph bounding box */ + + TT_Pos horiBearingX; /* left side bearing in horizontal layouts */ + TT_Pos horiBearingY; /* top side bearing in horizontal layouts */ + + TT_Pos vertBearingX; /* left side bearing in vertical layouts */ + TT_Pos vertBearingY; /* top side bearing in vertical layouts */ + + TT_Pos horiAdvance; /* advance width for horizontal layout */ + TT_Pos vertAdvance; /* advance height for vertical layout */ + + /* The following fields represent unhinted scaled metrics values. */ + /* They can be useful for applications needing to do some device */ + /* independent placement of glyphs. */ + /* */ + /* Applying these metrics to hinted glyphs will most surely ruin */ + /* the grid fitting performed by the bytecode interpreter. These */ + /* values are better used to compute accumulated positioning */ + /* distances. */ + + TT_Pos linearHoriBearingX; /* linearly scaled horizontal lsb */ + TT_Pos linearHoriAdvance; /* linearly scaled horizontal advance */ + + TT_Pos linearVertBearingY; /* linearly scaled vertical tsb */ + TT_Pos linearVertAdvance; /* linearly scaled vertical advance */ + }; + + typedef struct TT_Big_Glyph_Metrics_ TT_Big_Glyph_Metrics; + + + /* A structure used to return instance metrics. */ + + struct TT_Instance_Metrics_ + { + TT_F26Dot6 pointSize; /* char. size in points (1pt = 1/72 inch) */ + + TT_UShort x_ppem; /* horizontal pixels per EM square */ + TT_UShort y_ppem; /* vertical pixels per EM square */ + + TT_Fixed x_scale; /* 16.16 to convert from EM units to 26.6 pix */ + TT_Fixed y_scale; /* 16.16 to convert from EM units to 26.6 pix */ + + TT_UShort x_resolution; /* device horizontal resolution in dpi */ + TT_UShort y_resolution; /* device vertical resolution in dpi */ + }; + + typedef struct TT_Instance_Metrics_ TT_Instance_Metrics; + + + /* Flow constants: */ + /* */ + /* The flow of a bitmap refers to the way lines are oriented */ + /* within the bitmap data, i.e., the orientation of the Y */ + /* coordinate axis. */ + /* */ + /* For example, if the first bytes of the bitmap pertain to */ + /* its top-most line, then the flow is `down'. If these bytes */ + /* pertain to its lowest line, the the flow is `up'. */ + +#define TT_Flow_Down -1 /* bitmap is oriented from top to bottom */ +#define TT_Flow_Up 1 /* bitmap is oriented from bottom to top */ +#define TT_Flow_Error 0 /* an error occurred during rendering */ + + + /* A structure used to describe the target bitmap or pixmap to the */ + /* renderer. Note that there is nothing in this structure that */ + /* gives the nature of the buffer. */ + /* */ + /* IMPORTANT NOTE: */ + /* */ + /* In the case of a pixmap, the `width' and `cols' fields must */ + /* have the _same_ values, and _must_ be padded to 32-bits, i.e., */ + /* be a multiple of 4. Clipping problems will arise otherwise, */ + /* if not even page faults! */ + /* */ + /* The typical settings are: */ + /* */ + /* - for a WxH bitmap: */ + /* */ + /* rows = H */ + /* cols = (W+7) / 8 */ + /* width = W */ + /* flow = your_choice */ + /* */ + /* - for a WxH pixmap: */ + /* */ + /* rows = H */ + /* cols = (W+3) & ~3 */ + /* width = cols */ + /* flow = your_choice */ + + struct TT_Raster_Map_ + { + int rows; /* number of rows */ + int cols; /* number of columns (bytes) per row */ + int width; /* number of pixels per line */ + int flow; /* bitmap orientation */ + + void* bitmap; /* bit/pixmap buffer */ + long size; /* bit/pixmap size in bytes */ + }; + + typedef struct TT_Raster_Map_ TT_Raster_Map; + + + /* ------ The font header TrueType table structure ------ */ + + struct TT_Header_ + { + TT_Fixed Table_Version; + TT_Fixed Font_Revision; + + TT_Long CheckSum_Adjust; + TT_Long Magic_Number; + + TT_UShort Flags; + TT_UShort Units_Per_EM; + + TT_Long Created [2]; + TT_Long Modified[2]; + + TT_FWord xMin; + TT_FWord yMin; + TT_FWord xMax; + TT_FWord yMax; + + TT_UShort Mac_Style; + TT_UShort Lowest_Rec_PPEM; + + TT_Short Font_Direction; + TT_Short Index_To_Loc_Format; + TT_Short Glyph_Data_Format; + }; + + typedef struct TT_Header_ TT_Header; + + + /* ------ The horizontal header TrueType table structure ------ */ + + /*******************************************************/ + /* This structure is the one defined by the TrueType */ + /* specification, plus two fields used to link the */ + /* font-units metrics to the header. */ + + struct TT_Horizontal_Header_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Width_Max; /* advance width maximum */ + + TT_FWord min_Left_Side_Bearing; /* minimum left-sb */ + TT_FWord min_Right_Side_Bearing; /* minimum right-sb */ + TT_FWord xMax_Extent; /* xmax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + + TT_Short Reserved0, + Reserved1, + Reserved2, + Reserved3, + Reserved4; + + TT_Short metric_Data_Format; + TT_UShort number_Of_HMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + }; + + typedef struct TT_Horizontal_Header_ TT_Horizontal_Header; + + + /*******************************************************/ + /* This structure is the one defined by the TrueType */ + /* specification. Note that it has exactly the same */ + /* layout as the horizontal header (both are loaded */ + /* by the same function). */ + + struct TT_Vertical_Header_ + { + TT_Fixed Version; + TT_FWord Ascender; + TT_FWord Descender; + TT_FWord Line_Gap; + + TT_UFWord advance_Height_Max; /* advance height maximum */ + + TT_FWord min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + TT_FWord min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + TT_FWord yMax_Extent; /* xmax or ymax extents */ + TT_FWord caret_Slope_Rise; + TT_FWord caret_Slope_Run; + TT_FWord caret_Offset; + + TT_Short Reserved1, + Reserved2, + Reserved3, + Reserved4; + + TT_Short metric_Data_Format; + TT_UShort number_Of_VMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + }; + + typedef struct TT_Vertical_Header_ TT_Vertical_Header; + + + /* ------ The OS/2 table ------ */ + + /************************************************************************/ + /* Note that since FreeType 1.3, we support Mac fonts which do not have */ + /* an OS/2 table. In this case the `version' field will be set to */ + /* 0xFFFF by the table loader; all other fields should be 0. */ + + struct TT_OS2_ + { + TT_UShort version; /* 0x0001 */ + TT_FWord xAvgCharWidth; + TT_UShort usWeightClass; + TT_UShort usWidthClass; + TT_Short fsType; + TT_FWord ySubscriptXSize; + TT_FWord ySubscriptYSize; + TT_FWord ySubscriptXOffset; + TT_FWord ySubscriptYOffset; + TT_FWord ySuperscriptXSize; + TT_FWord ySuperscriptYSize; + TT_FWord ySuperscriptXOffset; + TT_FWord ySuperscriptYOffset; + TT_FWord yStrikeoutSize; + TT_FWord yStrikeoutPosition; + TT_Short sFamilyClass; + + TT_Byte panose[10]; + + TT_ULong ulUnicodeRange1; /* Bits 0-31 */ + TT_ULong ulUnicodeRange2; /* Bits 32-63 */ + TT_ULong ulUnicodeRange3; /* Bits 64-95 */ + TT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + TT_Char achVendID[4]; + + TT_UShort fsSelection; + TT_UShort usFirstCharIndex; + TT_UShort usLastCharIndex; + TT_Short sTypoAscender; + TT_Short sTypoDescender; + TT_Short sTypoLineGap; + TT_UShort usWinAscent; + TT_UShort usWinDescent; + + /* only version 1 tables: */ + + TT_ULong ulCodePageRange1; /* Bits 0-31 */ + TT_ULong ulCodePageRange2; /* Bits 32-63 */ + }; + + typedef struct TT_OS2_ TT_OS2; + + + /* ------ The PostScript table ------ */ + + struct TT_Postscript_ + { + TT_Fixed FormatType; + TT_Fixed italicAngle; + TT_FWord underlinePosition; + TT_FWord underlineThickness; + TT_ULong isFixedPitch; + TT_ULong minMemType42; + TT_ULong maxMemType42; + TT_ULong minMemType1; + TT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ftxpost.c extension. */ + }; + + typedef struct TT_Postscript_ TT_Postscript; + + + /* ------ The horizontal device metrics table (`hdmx') ------ */ + + struct TT_Hdmx_Record_ + { + TT_Byte ppem; + TT_Byte max_width; + TT_Byte* widths; + }; + + typedef struct TT_Hdmx_Record_ TT_Hdmx_Record; + + + struct TT_Hdmx_ + { + TT_UShort version; + TT_Short num_records; + TT_Hdmx_Record* records; + }; + + typedef struct TT_Hdmx_ TT_Hdmx; + + + /* A structure used to describe face properties. */ + + struct TT_Face_Properties_ + { + TT_UShort num_Glyphs; /* number of glyphs in face */ + TT_UShort max_Points; /* maximum number of points in a glyph */ + TT_UShort max_Contours; /* maximum number of contours in a glyph */ + + TT_UShort num_CharMaps; /* number of charmaps in the face */ + TT_UShort num_Names; /* number of name records in the face */ + + TT_ULong num_Faces; /* 1 for normal TrueType files, and the */ + /* number of embedded faces for TrueType */ + /* collections */ + + TT_Header* header; /* TrueType header table */ + TT_Horizontal_Header* horizontal; /* TrueType horizontal header */ + TT_OS2* os2; /* TrueType OS/2 table */ + TT_Postscript* postscript; /* TrueType Postscript table */ + TT_Hdmx* hdmx; /* TrueType hor. dev. metr. table */ + TT_Vertical_Header* vertical; /* TT Vertical header, if present */ + }; + + typedef struct TT_Face_Properties_ TT_Face_Properties; + + + /* Here are the definitions of the handle types used for FreeType's */ + /* most common objects accessed by the client application. We use */ + /* a simple trick: */ + /* */ + /* Each handle type is a structure that only contains one */ + /* pointer. The advantage of structures is that they are */ + /* mutually exclusive types. We could have defined the */ + /* following types: */ + /* */ + /* typedef void* TT_Stream; */ + /* typedef void* TT_Face; */ + /* typedef void* TT_Instance; */ + /* typedef void* TT_Glyph; */ + /* typedef void* TT_CharMap; */ + /* */ + /* but these would have allowed lines like: */ + /* */ + /* stream = instance; */ + /* */ + /* in the client code this would be a severe bug, unnoticed */ + /* by the compiler! */ + /* */ + /* Thus, we enforce type checking with a simple language */ + /* trick... */ + /* */ + /* NOTE: Some macros are defined in tttypes.h to perform */ + /* automatic type conversions for library hackers... */ + + struct TT_Engine_ { void* z; }; + struct TT_Stream_ { void* z; }; + struct TT_Face_ { void* z; }; + struct TT_Instance_ { void* z; }; + struct TT_Glyph_ { void* z; }; + struct TT_CharMap_ { void* z; }; + + typedef struct TT_Engine_ TT_Engine; /* engine instance */ + typedef struct TT_Stream_ TT_Stream; /* stream handle type */ + typedef struct TT_Face_ TT_Face; /* face handle type */ + typedef struct TT_Instance_ TT_Instance; /* instance handle type */ + typedef struct TT_Glyph_ TT_Glyph; /* glyph handle type */ + typedef struct TT_CharMap_ TT_CharMap; /* character map handle type */ + + + /* Almost all functions return an error code of this type. */ + + typedef long TT_Error; + + + /*******************************************************************/ + /* */ + /* FreeType API */ + /* */ + /* All these begin with a `TT_' prefix. */ + /* */ + /* Most of them are implemented in the `ttapi.c' source file. */ + /* */ + /*******************************************************************/ + + /* Get version information. */ + + EXPORT_DEF + TT_Error TT_FreeType_Version( int *major, + int *minor ); + + + /* Initialize the engine. */ + + EXPORT_DEF + TT_Error TT_Init_FreeType( TT_Engine* engine ); + + + /* Finalize the engine, and release all allocated objects. */ + + EXPORT_DEF + TT_Error TT_Done_FreeType( TT_Engine engine ); + + + /* Set the gray level palette. This is an array of 5 bytes used */ + /* to produce the font smoothed pixmaps. By convention: */ + /* */ + /* palette[0] = background (white) */ + /* palette[1] = light */ + /* palette[2] = medium */ + /* palette[3] = dark */ + /* palette[4] = foreground (black) */ + /* */ + + EXPORT_DEF + TT_Error TT_Set_Raster_Gray_Palette( TT_Engine engine, + TT_Byte* palette ); + + + /* ----------------------- face management ----------------------- */ + + /* Open a new TrueType font file, and returns a handle for */ + /* it in variable '*face'. */ + /* */ + /* Note: The file can be either a TrueType file (*.ttf) or */ + /* a TrueType collection (*.ttc, in this case, only */ + /* the first face is opened). The number of faces in */ + /* the same collection can be obtained in the face's */ + /* properties, using TT_Get_Face_Properties() and the */ + /* `max_Faces' field. */ + + EXPORT_DEF + TT_Error TT_Open_Face( TT_Engine engine, + const TT_Text* fontPathName, + TT_Face* face ); + + + /* Open a TrueType font file located inside a collection. */ + /* The font is assigned by its index in `fontIndex'. */ + + EXPORT_DEF + TT_Error TT_Open_Collection( TT_Engine engine, + const TT_Text* collectionPathName, + TT_ULong fontIndex, + TT_Face* face ); + + + /* Return face properties in the `properties' structure. */ + /* */ + /* Note that since version 1.3, we support font files with no */ + /* OS/2 table (mainly old Mac fonts). In this case, the OS/2 */ + /* `version' field will be set to 0xFFFF, and all other fields */ + /* will be zeroed. */ + + EXPORT_DEF + TT_Error TT_Get_Face_Properties( TT_Face face, + TT_Face_Properties* properties ); + + + /* Set a face object's generic pointer */ + + EXPORT_DEF + TT_Error TT_Set_Face_Pointer( TT_Face face, + void* data ); + + + /* Get a face object's generic pointer */ + + EXPORT_DEF + void* TT_Get_Face_Pointer( TT_Face face ); + + + /* Close a face's file handle to save system resources. The file */ + /* will be re-opened automatically on the next disk access. */ + + EXPORT_DEF + TT_Error TT_Flush_Face( TT_Face face ); + + /* Get a face's glyph metrics expressed in font units. Returns any */ + /* number of arrays. Set the fields to NULL if you are not interested */ + /* by a given array. */ + + EXPORT_DEF + TT_Error TT_Get_Face_Metrics( TT_Face face, + TT_UShort firstGlyph, + TT_UShort lastGlyph, + TT_Short* leftBearings, + TT_UShort* widths, + TT_Short* topBearings, + TT_UShort* heights ); + + + /* Close a given font object, destroying all associated */ + /* instances. */ + + EXPORT_DEF + TT_Error TT_Close_Face( TT_Face face ); + + + /* Get font or table data. */ + + EXPORT_DEF + TT_Error TT_Get_Font_Data( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ); + + +/* A simple macro to build table tags from ASCII chars */ + +#define MAKE_TT_TAG( _x1, _x2, _x3, _x4 ) \ + (((TT_ULong)_x1 << 24) | \ + ((TT_ULong)_x2 << 16) | \ + ((TT_ULong)_x3 << 8) | \ + (TT_ULong)_x4) + + + + /* ----------------------- instance management -------------------- */ + + /* Open a new font instance and returns an instance handle */ + /* for it in `*instance'. */ + + EXPORT_DEF + TT_Error TT_New_Instance( TT_Face face, + TT_Instance* instance ); + + + /* Set device resolution for a given instance. The values are */ + /* given in dpi (Dots Per Inch). Default is 96 in both directions. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Resolutions( TT_Instance instance, + TT_UShort xResolution, + TT_UShort yResolution ); + + + /* Set the pointsize for a given instance. Default is 10pt. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_CharSize( TT_Instance instance, + TT_F26Dot6 charSize ); + + EXPORT_DEF + TT_Error TT_Set_Instance_CharSizes( TT_Instance instance, + TT_F26Dot6 charWidth, + TT_F26Dot6 charHeight ); + +#define TT_Set_Instance_PointSize( ins, ptsize ) \ + TT_Set_Instance_CharSize( ins, ptsize*64L ) + + EXPORT_DEF + TT_Error TT_Set_Instance_PixelSizes( TT_Instance instance, + TT_UShort pixelWidth, + TT_UShort pixelHeight, + TT_F26Dot6 pointSize ); + + + /* This function has been deprecated! Do not use it, as it */ + /* doesn't work reliably. You can perfectly control hinting */ + /* yourself when loading glyphs, then apply transforms as usual. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Transform_Flags( TT_Instance instance, + TT_Bool rotated, + TT_Bool stretched ); + + + /* Return instance metrics in `metrics'. */ + + EXPORT_DEF + TT_Error TT_Get_Instance_Metrics( TT_Instance instance, + TT_Instance_Metrics* metrics ); + + + /* Set an instance's generic pointer. */ + + EXPORT_DEF + TT_Error TT_Set_Instance_Pointer( TT_Instance instance, + void* data ); + + + /* Get an instance's generic pointer. */ + + EXPORT_DEF + void* TT_Get_Instance_Pointer( TT_Instance instance ); + + + /* Close a given instance object, destroying all associated data. */ + + EXPORT_DEF + TT_Error TT_Done_Instance( TT_Instance instance ); + + + + /* ----------------------- glyph management ----------------------- */ + + /* Create a new glyph object related to the given `face'. */ + + EXPORT_DEF + TT_Error TT_New_Glyph( TT_Face face, + TT_Glyph* glyph ); + + + /* Discard (and destroy) a given glyph object. */ + + EXPORT_DEF + TT_Error TT_Done_Glyph( TT_Glyph glyph ); + + +#define TTLOAD_SCALE_GLYPH 1 +#define TTLOAD_HINT_GLYPH 2 +#define TTLOAD_PEDANTIC 128 +#define TTLOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 256 + +#define TTLOAD_DEFAULT (TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH) + + + /* Load and process (scale/transform and hint) a glyph from the */ + /* given `instance'. The glyph and instance handles must be */ + /* related to the same face object. The glyph index can be */ + /* computed with a call to TT_Char_Index(). */ + /* */ + /* The 'load_flags' argument is a combination of the macros */ + /* TTLOAD_SCALE_GLYPH and TTLOAD_HINT_GLYPH. Hinting will be */ + /* applied only if the scaling is selected. */ + /* */ + /* If scaling is off (i.e., load_flags = 0), the returned */ + /* outlines are in EM square coordinates (also called FUnits), */ + /* extracted directly from the font with no hinting. Other */ + /* glyph metrics are also in FUnits. */ + /* */ + /* If scaling is on, the returned outlines are in fractional */ + /* pixel units (i.e. TT_F26Dot6 = 26.6 fixed floats). */ + /* */ + /* NOTE: The glyph index must be in the range 0..num_glyphs-1, */ + /* where `num_glyphs' is the total number of glyphs in */ + /* the font file (given in the face properties). */ + + EXPORT_DEF + TT_Error TT_Load_Glyph( TT_Instance instance, + TT_Glyph glyph, + TT_UShort glyphIndex, + TT_UShort loadFlags ); + + + /* Return glyph outline pointers in `outline'. Note that the returned */ + /* pointers are owned by the glyph object, and will be destroyed with */ + /* it. The client application should _not_ change the pointers. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Outline( TT_Glyph glyph, + TT_Outline* outline ); + + + /* Copy the glyph metrics into `metrics'. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Metrics( TT_Glyph glyph, + TT_Glyph_Metrics* metrics ); + + + /* Copy the glyph's big metrics into `metrics'. */ + /* Necessary to obtain vertical metrics. */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Big_Metrics( TT_Glyph glyph, + TT_Big_Glyph_Metrics* metrics ); + + + /* Render the glyph into a bitmap, with given position offsets. */ + /* */ + /* Note: Only use integer pixel offsets to preserve the fine */ + /* hinting of the glyph and the `correct' anti-aliasing */ + /* (where vertical and horizontal stems aren't grayed). This */ + /* means that `xOffset' and `yOffset' must be multiples */ + /* of 64! */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Bitmap( TT_Glyph glyph, + TT_Raster_Map* bitmap, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + /* Render the glyph into a pixmap, with given position offsets. */ + /* */ + /* Note: Only use integer pixel offsets to preserve the fine */ + /* hinting of the glyph and the `correct' anti-aliasing */ + /* (where vertical and horizontal stems aren't grayed). This */ + /* means that `xOffset' and `yOffset' must be multiples */ + /* of 64! */ + + EXPORT_DEF + TT_Error TT_Get_Glyph_Pixmap( TT_Glyph glyph, + TT_Raster_Map* pixmap, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + + /* ----------------------- outline support ------------------------ */ + + /* Allocate a new outline. Reserve space for `numPoints' and */ + /* `numContours'. */ + + EXPORT_DEF + TT_Error TT_New_Outline( TT_UShort numPoints, + TT_Short numContours, + TT_Outline* outline ); + + + /* Release an outline. */ + + EXPORT_DEF + TT_Error TT_Done_Outline( TT_Outline* outline ); + + + /* Copy an outline into another one. */ + + EXPORT_DEF + TT_Error TT_Copy_Outline( TT_Outline* source, + TT_Outline* target ); + + + /* Render an outline into a bitmap. */ + + EXPORT_DEF + TT_Error TT_Get_Outline_Bitmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* bitmap ); + + + /* Render an outline into a pixmap. */ + + EXPORT_DEF + TT_Error TT_Get_Outline_Pixmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* pixmap ); + + + /* Return an outline's bounding box -- this function is slow as it */ + /* performs a complete scan-line process, without drawing, to get */ + /* the most accurate values. */ + + EXPORT_DEF + TT_Error TT_Get_Outline_BBox( TT_Outline* outline, + TT_BBox* bbox ); + + + /* Apply a transformation to a glyph outline. */ + + EXPORT_DEF + void TT_Transform_Outline( TT_Outline* outline, + TT_Matrix* matrix ); + + + /* Apply a translation to a glyph outline. */ + + EXPORT_DEF + void TT_Translate_Outline( TT_Outline* outline, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ); + + + /* Apply a transformation to a vector. */ + + EXPORT_DEF + void TT_Transform_Vector( TT_F26Dot6* x, + TT_F26Dot6* y, + TT_Matrix* matrix ); + + + /* Compute A*B/C with 64 bits intermediate precision. */ + + EXPORT_DEF + TT_Long TT_MulDiv( TT_Long A, + TT_Long B, + TT_Long C ); + + + /* Compute A*B/0x10000 with 64 bits intermediate precision. */ + /* Useful to multiply by a 16.16 fixed float value. */ + + EXPORT_DEF + TT_Long TT_MulFix( TT_Long A, + TT_Long B ); + + + /* ----------------- character mapping support --------------- */ + + /* Return the number of character mappings found in this file. */ + /* Returns -1 in case of failure (invalid face handle). */ + /* */ + /* DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! */ + /* */ + /* It is retained for backwards compatibility only and will */ + /* fail on 16bit systems. */ + /* */ + /* You can now get the charmap count in the `num_CharMaps' */ + /* field of a face's properties. */ + /* */ + + EXPORT_DEF + int TT_Get_CharMap_Count( TT_Face face ); + + + /* Return the ID of charmap number `charmapIndex' of a given face */ + /* used to enumerate the charmaps present in a TrueType file. */ + + EXPORT_DEF + TT_Error TT_Get_CharMap_ID( TT_Face face, + TT_UShort charmapIndex, + TT_UShort* platformID, + TT_UShort* encodingID ); + + + /* Look up the character maps found in `face' and return a handle */ + /* for the one matching `platformID' and `platformEncodingID' */ + /* (see the TrueType specs relating to the `cmap' table for */ + /* information on these ID numbers). Returns an error code. */ + /* In case of failure, the handle is set to NULL and is invalid. */ + + EXPORT_DEF + TT_Error TT_Get_CharMap( TT_Face face, + TT_UShort charmapIndex, + TT_CharMap* charMap ); + + + /* Translate a character code through a given character map */ + /* and return the corresponding glyph index to be used in */ + /* a TT_Load_Glyph() call. This function returns 0 in case */ + /* of failure. */ + + EXPORT_DEF + TT_UShort TT_Char_Index( TT_CharMap charMap, + TT_ULong charCode ); + + + + /* --------------------- names table support ------------------- */ + + /* Return the number of name strings found in the name table. */ + /* Returns -1 in case of failure (invalid face handle). */ + /* */ + /* DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! */ + /* */ + /* It is retained for backwards compatibility only and will */ + /* fail on 16bit systems. */ + /* */ + /* You can now get the number of name strings in a face with */ + /* the `num_Names' field of its properties. */ + + EXPORT_DEF + int TT_Get_Name_Count( TT_Face face ); + + + /* Return the ID of the name number `nameIndex' of a given face */ + /* used to enumerate the charmaps present in a TrueType file. */ + + EXPORT_DEF + TT_Error TT_Get_Name_ID( TT_Face face, + TT_UShort nameIndex, + TT_UShort* platformID, + TT_UShort* encodingID, + TT_UShort* languageID, + TT_UShort* nameID ); + + + /* Return the address and length of the name number `nameIndex' */ + /* of a given face in the variables `stringPtr' resp. `length'. */ + /* The string is part of the face object and shouldn't be */ + /* written to or released. */ + /* */ + /* Note that for an invalid platform ID a null pointer will be */ + /* returned. */ + + EXPORT_DEF + TT_Error TT_Get_Name_String( TT_Face face, + TT_UShort nameIndex, + TT_String** stringPtr, + TT_UShort* length ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FREETYPE_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ft_conf.h b/Build/source/libs/libttf/ft_conf.h new file mode 100644 index 00000000000..63819dd95c5 --- /dev/null +++ b/Build/source/libs/libttf/ft_conf.h @@ -0,0 +1,210 @@ +/* This file is part of the FreeType project */ + +/* ft_conf.h for Win32 */ + + +/* we need the following because there are some typedefs in this file */ + +#ifndef FT_CONF_H +#define FT_CONF_H + +#ifndef WIN32 +#define WIN32 +#endif + +/* Define to empty if the 'const' keyword does not work. */ +/* #undef const */ + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE + +/* Define if you have the valloc function. */ +#undef HAVE_VALLOC + +/* Define if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/**********************************************************************/ +/* */ +/* The following configuration macros can be tweaked manually by */ +/* a developer to turn on or off certain features or options in the */ +/* TrueType engine. This may be useful to tune it for specific */ +/* purposes.. */ +/* */ +/**********************************************************************/ + + +/*************************************************************************/ +/* Define this if the underlying operating system uses a different */ +/* character width than 8bit for file names. You must then also supply */ +/* a typedef declaration for defining 'TT_Text'. Default is off. */ + +/* #define HAVE_TT_TEXT */ + + +/*************************************************************************/ +/* Define this if you want to generate code to support engine extensions */ +/* Default is on, but if you're satisfied by the basic services provided */ +/* by the engine and need no extensions, undefine this configuration */ +/* macro to save a few more bytes. */ + +#define TT_CONFIG_OPTION_EXTEND_ENGINE + + +/*************************************************************************/ +/* Define this if you want to generate code to support gray-scaling, */ +/* a.k.a. font-smoothing or anti-aliasing. Default is on, but you can */ +/* disable it if you don't need it. */ + +#define TT_CONFIG_OPTION_GRAY_SCALING + + +/*************************************************************************/ +/* Define this if you want to completely disable the use of the bytecode */ +/* interpreter. Doing so will produce a much smaller library, but the */ +/* quality of the rendered glyphs will enormously suffer from this. */ +/* */ +/* This switch was introduced due to the Apple patents issue which */ +/* emerged recently on the FreeType lists. We still do not have Apple's */ +/* opinion on the subject and will change this as soon as we have. */ + +#undef TT_CONFIG_OPTION_NO_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to use a big 'switch' statement within the */ +/* bytecode interpreter. Because some non-optimizing compilers are not */ +/* able to produce jump tables from such statements, undefining this */ +/* configuration macro will generate the appropriate C jump table in */ +/* ttinterp.c. If you use an optimizing compiler, you should leave it */ +/* defined for better performance and code compactness.. */ + +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the TrueType */ +/* bytecode interpreter. This will produce much bigger code, which */ +/* _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_INTERPRETER + + +/*************************************************************************/ +/* Define this if you want to build a 'static' version of the scan-line */ +/* converter (the component which in charge of converting outlines into */ +/* bitmaps). This will produce a bigger object file for "ttraster.c", */ +/* which _may_ be faster on some architectures.. */ +/* */ +/* Do NOT DEFINE THIS is you build a thread-safe version of the engine */ +/* */ +#undef TT_CONFIG_OPTION_STATIC_RASTER + + +/*************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +#undef TT_CONFIG_OPTION_THREAD_SAFE + + +/**********************************************************************/ +/* */ +/* The following macros are used to define the debug level, as well */ +/* as individual tracing levels for each component. There are */ +/* currently three modes of operation : */ +/* */ +/* - trace mode (define DEBUG_LEVEL_TRACE) */ +/* */ +/* The engine prints all error messages, as well as tracing */ +/* ones, filtered by each component's level */ +/* */ +/* - debug mode (define DEBUG_LEVEL_ERROR) */ +/* */ +/* Disable tracing, but keeps error output and assertion */ +/* checks. */ +/* */ +/* - release mode (don't define anything) */ +/* */ +/* Don't include error-checking or tracing code in the */ +/* engine's code. Ideal for releases. */ +/* */ +/* NOTE : */ +/* */ +/* Each component's tracing level is defined in its own source. */ +/* */ +/**********************************************************************/ + +/* Define if you want to use the tracing debug mode */ +#undef DEBUG_LEVEL_TRACE + +/* Define if you want to use the error debug mode - ignored if */ +/* DEBUG_LEVEL_TRACE is defined */ +#undef DEBUG_LEVEL_ERROR + + +/**************************************************************************/ +/* Definition of various integer sizes. These types are used by ttcalc */ +/* and ttinterp (for the 64-bit integers) only.. */ + +#if SIZEOF_INT == 4 + + typedef signed int TT_Int32; + typedef unsigned int TT_Word32; + +#elif SIZEOF_LONG == 4 + + typedef signed long TT_Int32; + typedef unsigned long TT_Word32; + +#else +#error "no 32bit type found" +#endif + +#if SIZEOF_LONG == 8 + +/* LONG64 must be defined when a 64-bit type is available */ +/* INT64 must then be defined to this type.. */ +#define LONG64 +#define INT64 long + +#else + +/* GCC provides the non-ANSI 'long long' 64-bit type. You can activate */ +/* by defining the TT_USE_LONG_LONG macro in 'ft_conf.h'. Note that this */ +/* will produce many -ansi warnings during library compilation. */ +#ifdef TT_USE_LONG_LONG + +#define LONG64 +#define INT64 long long + +#endif /* TT_USE_LONG_LONG */ +#endif + +#endif /* FT_CONF_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/fterrid.h b/Build/source/libs/libttf/fterrid.h new file mode 100644 index 00000000000..0444e6f4704 --- /dev/null +++ b/Build/source/libs/libttf/fterrid.h @@ -0,0 +1,161 @@ +/******************************************************************* + * + * fterrid.h + * + * TrueType Error ID definitions + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FREETYPE_H +#error "Don't include this file! Use freetype.h instead." +#endif + +#ifndef FTERRID_H +#define FTERRID_H + + /************************ error codes declaration **************/ + + /* The error codes are grouped in 'classes' used to indicate the */ + /* 'level' at which the error happened. */ + /* The class is given by an error code's high byte. */ + + + /* ------------- Success is always 0 -------- */ + +#define TT_Err_Ok 0 + + + /* -------- High-level API error codes ------ */ + +#define TT_Err_Invalid_Face_Handle 0x001 +#define TT_Err_Invalid_Instance_Handle 0x002 +#define TT_Err_Invalid_Glyph_Handle 0x003 +#define TT_Err_Invalid_CharMap_Handle 0x004 +#define TT_Err_Invalid_Result_Address 0x005 +#define TT_Err_Invalid_Glyph_Index 0x006 +#define TT_Err_Invalid_Argument 0x007 +#define TT_Err_Could_Not_Open_File 0x008 +#define TT_Err_File_Is_Not_Collection 0x009 + +#define TT_Err_Table_Missing 0x00A +#define TT_Err_Invalid_Horiz_Metrics 0x00B +#define TT_Err_Invalid_CharMap_Format 0x00C +#define TT_Err_Invalid_PPem 0x00D +#define TT_Err_Invalid_Vert_Metrics 0x00E + +#define TT_Err_Invalid_File_Format 0x010 + +#define TT_Err_Invalid_Engine 0x020 +#define TT_Err_Too_Many_Extensions 0x021 +#define TT_Err_Extensions_Unsupported 0x022 +#define TT_Err_Invalid_Extension_Id 0x023 + +#define TT_Err_No_Vertical_Data 0x030 + +#define TT_Err_Max_Profile_Missing 0x080 +#define TT_Err_Header_Table_Missing 0x081 +#define TT_Err_Horiz_Header_Missing 0x082 +#define TT_Err_Locations_Missing 0x083 +#define TT_Err_Name_Table_Missing 0x084 +#define TT_Err_CMap_Table_Missing 0x085 +#define TT_Err_Hmtx_Table_Missing 0x086 +#define TT_Err_OS2_Table_Missing 0x087 +#define TT_Err_Post_Table_Missing 0x088 +#define TT_Err_Glyf_Table_Missing 0x089 + + + /* -------- Memory component error codes ---- */ + + /* this error indicates that an operation cannot */ + /* be performed due to memory exhaustion. */ + +#define TT_Err_Out_Of_Memory 0x100 + + + /* -------- File component error codes ------ */ + + /* these error codes indicate that the file could */ + /* not be accessed properly. Usually, this means */ + /* a broken font file! */ + +#define TT_Err_Invalid_File_Offset 0x200 +#define TT_Err_Invalid_File_Read 0x201 +#define TT_Err_Invalid_Frame_Access 0x202 + + + /* -------- Glyph loader error codes -------- */ + + /* Produced only by the glyph loader, these error */ + /* codes indicate a broken glyph in a font file. */ + +#define TT_Err_Too_Many_Points 0x300 +#define TT_Err_Too_Many_Contours 0x301 +#define TT_Err_Invalid_Composite 0x302 +#define TT_Err_Too_Many_Ins 0x303 + + + /* --- bytecode interpreter error codes ----- */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define TT_Err_Invalid_Opcode 0x400 +#define TT_Err_Too_Few_Arguments 0x401 +#define TT_Err_Stack_Overflow 0x402 +#define TT_Err_Code_Overflow 0x403 +#define TT_Err_Bad_Argument 0x404 +#define TT_Err_Divide_By_Zero 0x405 +#define TT_Err_Storage_Overflow 0x406 +#define TT_Err_Cvt_Overflow 0x407 +#define TT_Err_Invalid_Reference 0x408 +#define TT_Err_Invalid_Distance 0x409 +#define TT_Err_Interpolate_Twilight 0x40A +#define TT_Err_Debug_OpCode 0x40B +#define TT_Err_ENDF_In_Exec_Stream 0x40C +#define TT_Err_Out_Of_CodeRanges 0x40D +#define TT_Err_Nested_DEFS 0x40E +#define TT_Err_Invalid_CodeRange 0x40F +#define TT_Err_Invalid_Displacement 0x410 +#define TT_Err_Execution_Too_Long 0x411 + + + /* ------ internal failure error codes ----- */ + + /* These error codes are produced when an incoherent */ + /* library state has been detected. These reflect a */ + /* severe bug in the engine! (Or a major overwrite */ + /* of your application into the library's data.) */ + +#define TT_Err_Nested_Frame_Access 0x500 +#define TT_Err_Invalid_Cache_List 0x501 +#define TT_Err_Could_Not_Find_Context 0x502 +#define TT_Err_Unlisted_Object 0x503 + + + /* ---- scan-line converter error codes ----- */ + + /* These error codes are produced by the raster component. */ + /* They indicate that an outline structure was incoherently */ + /* setup, or that you're trying to render an horribly */ + /* complex glyph! */ + +#define TT_Err_Raster_Pool_Overflow 0x600 +#define TT_Err_Raster_Negative_Height 0x601 +#define TT_Err_Raster_Invalid_Value 0x602 +#define TT_Err_Raster_Not_Initialized 0x603 + +#endif /* FTERRID_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ftnameid.h b/Build/source/libs/libttf/ftnameid.h new file mode 100644 index 00000000000..5d51234b8c2 --- /dev/null +++ b/Build/source/libs/libttf/ftnameid.h @@ -0,0 +1,628 @@ +/******************************************************************* + * + * ftnameid.h + * + * TrueType Name ID definitions + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef FREETYPE_H +#error "Don't include this file! Use freetype.h instead." +#endif + +#ifndef FTNAMEID_H +#define FTNAMEID_H + +/* + * possible values for the 'Platform' identifier code in the name + * records of the TTF "name" table + */ + +#define TT_PLATFORM_APPLE_UNICODE 0 +#define TT_PLATFORM_MACINTOSH 1 +#define TT_PLATFORM_ISO 2 +#define TT_PLATFORM_MICROSOFT 3 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when the 'Platform' identifier + * code is TT_PLATFORM_APPLE_UNICODE + */ + +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 +#define TT_APPLE_ID_ISO_10646 2 +#define TT_APPLE_ID_UNICODE_2_0 3 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when the 'Platform' identifier + * code is TT_PLATFORM_MACINTOSH + */ + +#define TT_MAC_ID_ROMAN 0 +#define TT_MAC_ID_JAPANESE 1 +#define TT_MAC_ID_TRADITIONAL_CHINESE 2 +#define TT_MAC_ID_KOREAN 3 +#define TT_MAC_ID_ARABIC 4 +#define TT_MAC_ID_HEBREW 5 +#define TT_MAC_ID_GREEK 6 +#define TT_MAC_ID_RUSSIAN 7 +#define TT_MAC_ID_RSYMBOL 8 +#define TT_MAC_ID_DEVANAGARI 9 +#define TT_MAC_ID_GURMUKHI 10 +#define TT_MAC_ID_GUJARATI 11 +#define TT_MAC_ID_ORIYA 12 +#define TT_MAC_ID_BENGALI 13 +#define TT_MAC_ID_TAMIL 14 +#define TT_MAC_ID_TELUGU 15 +#define TT_MAC_ID_KANNADA 16 +#define TT_MAC_ID_MALAYALAM 17 +#define TT_MAC_ID_SINHALESE 18 +#define TT_MAC_ID_BURMESE 19 +#define TT_MAC_ID_KHMER 20 +#define TT_MAC_ID_THAI 21 +#define TT_MAC_ID_LAOTIAN 22 +#define TT_MAC_ID_GEORGIAN 23 +#define TT_MAC_ID_ARMENIAN 24 +#define TT_MAC_ID_MALDIVIAN 25 +#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 +#define TT_MAC_ID_TIBETAN 26 +#define TT_MAC_ID_MONGOLIAN 27 +#define TT_MAC_ID_GEEZ 28 +#define TT_MAC_ID_SLAVIC 29 +#define TT_MAC_ID_VIETNAMESE 30 +#define TT_MAC_ID_SINDHI 31 +#define TT_MAC_ID_UNINTERP 32 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when the 'Platform' identifier + * code is TT_PLATFORM_ISO + */ + +#define TT_ISO_ID_7BIT_ASCII 0 +#define TT_ISO_ID_10646 1 +#define TT_ISO_ID_8859_1 2 + + +/* + * possible values of the platform specific encoding identifier field in + * the name records of the TTF "name" table when the 'Platform' identifier + * code is TT_PLATFORM_MICROSOFT + */ + +#define TT_MS_ID_SYMBOL_CS 0 +#define TT_MS_ID_UNICODE_CS 1 +#define TT_MS_ID_SJIS 2 +#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_BIG_5 4 +#define TT_MS_ID_WANSUNG 5 +#define TT_MS_ID_JOHAB 6 + + + +/* + * possible values of the language identifier field in the name records of + * the TTF "name" table when the 'Platform' identifier code is + * TT_PLATFORM_MACINTOSH + * + * the canonical source for the Apple assigned Language ID's is at + * http://fonts.apple.com/TTRefMan/RM06/Chap6name.html + */ + +#define TT_MAC_LANGID_ENGLISH 0 +#define TT_MAC_LANGID_FRENCH 1 +#define TT_MAC_LANGID_GERMAN 2 +#define TT_MAC_LANGID_ITALIAN 3 +#define TT_MAC_LANGID_DUTCH 4 +#define TT_MAC_LANGID_SWEDISH 5 +#define TT_MAC_LANGID_SPANISH 6 +#define TT_MAC_LANGID_DANISH 7 +#define TT_MAC_LANGID_PORTUGUESE 8 +#define TT_MAC_LANGID_NORWEGIAN 9 +#define TT_MAC_LANGID_HEBREW 10 +#define TT_MAC_LANGID_JAPANESE 11 +#define TT_MAC_LANGID_ARABIC 12 +#define TT_MAC_LANGID_FINNISH 13 +#define TT_MAC_LANGID_GREEK 14 +#define TT_MAC_LANGID_ICELANDIC 15 +#define TT_MAC_LANGID_MALTESE 16 +#define TT_MAC_LANGID_TURKISH 17 +#define TT_MAC_LANGID_CROATIAN 18 +#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 +#define TT_MAC_LANGID_URDU 20 +#define TT_MAC_LANGID_HINDI 21 +#define TT_MAC_LANGID_THAI 22 +#define TT_MAC_LANGID_KOREAN 23 +#define TT_MAC_LANGID_LITHUANIAN 24 +#define TT_MAC_LANGID_POLISH 25 +#define TT_MAC_LANGID_HUNGARIAN 26 +#define TT_MAC_LANGID_ESTONIAN 27 +#define TT_MAC_LANGID_LETTISH 28 +#define TT_MAC_LANGID_SAAMISK 29 +#define TT_MAC_LANGID_FAEROESE 30 +#define TT_MAC_LANGID_FARSI 31 +#define TT_MAC_LANGID_RUSSIAN 32 +#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 +#define TT_MAC_LANGID_FLEMISH 34 +#define TT_MAC_LANGID_IRISH 35 +#define TT_MAC_LANGID_ALBANIAN 36 +#define TT_MAC_LANGID_ROMANIAN 37 +#define TT_MAC_LANGID_CZECH 38 +#define TT_MAC_LANGID_SLOVAK 39 +#define TT_MAC_LANGID_SLOVENIAN 40 +#define TT_MAC_LANGID_YIDDISH 41 +#define TT_MAC_LANGID_SERBIAN 42 +#define TT_MAC_LANGID_MACEDONIAN 43 +#define TT_MAC_LANGID_BULGARIAN 44 +#define TT_MAC_LANGID_UKRAINIAN 45 +#define TT_MAC_LANGID_BYELORUSSIAN 46 +#define TT_MAC_LANGID_UZBEK 47 +#define TT_MAC_LANGID_KAZAKH 48 +#define TT_MAC_LANGID_AZERBAIJANI 49 +#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 +#define TT_MAC_LANGID_ARMENIAN 51 +#define TT_MAC_LANGID_GEORGIAN 52 +#define TT_MAC_LANGID_MOLDAVIAN 53 +#define TT_MAC_LANGID_KIRGHIZ 54 +#define TT_MAC_LANGID_TAJIKI 55 +#define TT_MAC_LANGID_TURKMEN 56 +#define TT_MAC_LANGID_MONGOLIAN 57 +#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 +#define TT_MAC_LANGID_PASHTO 59 +#define TT_MAC_LANGID_KURDISH 60 +#define TT_MAC_LANGID_KASHMIRI 61 +#define TT_MAC_LANGID_SINDHI 62 +#define TT_MAC_LANGID_TIBETAN 63 +#define TT_MAC_LANGID_NEPALI 64 +#define TT_MAC_LANGID_SANSKRIT 65 +#define TT_MAC_LANGID_MARATHI 66 +#define TT_MAC_LANGID_BENGALI 67 +#define TT_MAC_LANGID_ASSAMESE 68 +#define TT_MAC_LANGID_GUJARATI 69 +#define TT_MAC_LANGID_PUNJABI 70 +#define TT_MAC_LANGID_ORIYA 71 +#define TT_MAC_LANGID_MALAYALAM 72 +#define TT_MAC_LANGID_KANNADA 73 +#define TT_MAC_LANGID_TAMIL 74 +#define TT_MAC_LANGID_TELUGU 75 +#define TT_MAC_LANGID_SINHALESE 76 +#define TT_MAC_LANGID_BURMESE 77 +#define TT_MAC_LANGID_KHMER 78 +#define TT_MAC_LANGID_LAO 79 +#define TT_MAC_LANGID_VIETNAMESE 80 +#define TT_MAC_LANGID_INDONESIAN 81 +#define TT_MAC_LANGID_TAGALOG 82 +#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 +#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 +#define TT_MAC_LANGID_AMHARIC 85 +#define TT_MAC_LANGID_TIGRINYA 86 +#define TT_MAC_LANGID_GALLA 87 +#define TT_MAC_LANGID_SOMALI 88 +#define TT_MAC_LANGID_SWAHILI 89 +#define TT_MAC_LANGID_RUANDA 90 +#define TT_MAC_LANGID_RUNDI 91 +#define TT_MAC_LANGID_CHEWA 92 +#define TT_MAC_LANGID_MALAGASY 93 +#define TT_MAC_LANGID_ESPERANTO 94 +#define TT_MAC_LANGID_WELSH 128 +#define TT_MAC_LANGID_BASQUE 129 +#define TT_MAC_LANGID_CATALAN 130 +#define TT_MAC_LANGID_LATIN 131 +#define TT_MAC_LANGID_QUECHUA 132 +#define TT_MAC_LANGID_GUARANI 133 +#define TT_MAC_LANGID_AYMARA 134 +#define TT_MAC_LANGID_TATAR 135 +#define TT_MAC_LANGID_UIGHUR 136 +#define TT_MAC_LANGID_DZONGKHA 137 +#define TT_MAC_LANGID_JAVANESE 138 +#define TT_MAC_LANGID_SUNDANESE 139 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 + + +/* + * possible values of the language identifier field in the name records of + * the TTF "name" table when the 'Platform' identifier code is + * TT_PLATFORM_MICROSOFT + * + * the canonical source for the MS assigned LCID's is at + * http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt + */ + +#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 +#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 +#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 +#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 +#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 +#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 +#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 +#define TT_MS_LANGID_ARABIC_OMAN 0x2001 +#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 +#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 +#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 +#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 +#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 +#define TT_MS_LANGID_ARABIC_UAE 0x3801 +#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 +#define TT_MS_LANGID_ARABIC_QATAR 0x4001 +#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 +#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 +#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 +#define TT_MS_LANGID_CHINESE_PRC 0x0804 +#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 +#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 +#define TT_MS_LANGID_DANISH_DENMARK 0x0406 +#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 +#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 +#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 +#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GREEK_GREECE 0x0408 +#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 +#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 +#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 +#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 +#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 +#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 +#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 +#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 +#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 +#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 +#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 +#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 +#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 +#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a +#define TT_MS_LANGID_SPANISH_MEXICO 0x080a +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a +#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a +#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a +#define TT_MS_LANGID_SPANISH_PANAMA 0x180a +#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a +#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a +#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a +#define TT_MS_LANGID_SPANISH_PERU 0x280a +#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a +#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a +#define TT_MS_LANGID_SPANISH_CHILE 0x340a +#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a +#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a +#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a +#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a +#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a +#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a +#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a +#define TT_MS_LANGID_FINNISH_FINLAND 0x040b +#define TT_MS_LANGID_FRENCH_FRANCE 0x040c +#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c +#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c +#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c +#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c +#define TT_MS_LANGID_FRENCH_MONACO 0x180c +#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d +#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e +#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f +#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 +#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 +#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 +#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 +#define TT_MS_LANGID_POLISH_POLAND 0x0415 +#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 +#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a +#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a +#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a +#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b +#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c +#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d +#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d +#define TT_MS_LANGID_THAI_THAILAND 0x041e +#define TT_MS_LANGID_TURKISH_TURKEY 0x041f +#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 +#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 +#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 +#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 +#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 +#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 +#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428 +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a +#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b +#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c +#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c +#define TT_MS_LANGID_BASQUE_SPAIN 0x042d +#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e +#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 +#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 +#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 +#define TT_MS_LANGID_HINDI_INDIA 0x0439 +#define TT_MS_LANGID_MALTESE_MALTA 0x043a +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e +#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e +#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f +#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 +#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_BENGALI_INDIA 0x0445 +#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 +#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 +#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_TAMIL_INDIA 0x0449 +#define TT_MS_LANGID_TELUGU_INDIA 0x044a +#define TT_MS_LANGID_KANNADA_INDIA 0x044b +#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c +#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d +#define TT_MS_LANGID_MARATHI_INDIA 0x044e +#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f +#define TT_MS_LANGID_KONKANI_INDIA 0x0457 + + +/* + * possible values of the 'Name' identifier field in the name records of + * the TTF "name" table. These values are platform independent. + */ + +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 +/* the following values are from the OpenType spec */ +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 +/* number 15 is reserved */ +#define TT_NAME_ID_PREFERRED_FAMILY 16 +#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 + + +/* + * Bit Mask values for the Unicode Ranges from the TTF "OS2 " table. + */ + +/* General Scripts Area */ + +/* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0000-U+007F */ +/* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ +/* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ +/* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ +/* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ +/* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ +/* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ +/* Bit 7 Greek */ +#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ +/* Bit 8 is reserved (was: Greek Symbols and Coptic) */ +/* Bit 9 Cyrillic */ +#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ +/* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ +/* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ +/* Bit 12 is reserved (was: Hebrew Extended) */ +/* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ +/* Bit 14 is reserved (was: Arabic Extended) */ +/* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ +/* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ +/* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ +/* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ +/* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ +/* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ +/* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ +/* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ +/* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ +/* Bit 24 Thai */ +#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ +/* Bit 25 Lao */ +#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ +/* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ +/* Bit 27 is reserved (was Georgian Extended) */ +/* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ +/* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ +/* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ + +/* Symbols Area */ + +/* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ +/* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ +/* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ +/* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ +/* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ +/* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ +/* Bit 37 Arrows */ +#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ +/* Bit 38 Mathematical Operators */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ +/* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ +/* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ +/* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ +/* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ +/* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ +/* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ +/* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ +/* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ +/* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ + +/* CJK Phonetics and Symbols Area */ + +/* Bit 48 CJK Symbols And Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ +/* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ +/* Bit 50 Katakana */ +#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ +/* Bit 51 Bopomofo */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ +/* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ +/* Bit 53 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */ +/* Bit 54 Enclosed CJK Letters And Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ +/* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ + +/* Hangul Syllables Area */ + +/* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ + +/* Surrogates Area */ + +/* Bit 57 Surrogates */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DFFF */ +/* Bit 58 is reserved for Unicode SubRanges */ + +/* CJK Ideographs Area */ + +/* Bit 59 CJK Unified Ideographs */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + +/* Private Use Area */ + +/* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ + +/* Compatibility Area and Specials */ + +/* Bit 61 CJK Compatibility Ideographs */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */ +/* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ +/* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FSFF */ +/* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ +/* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */ +/* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ +/* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFF */ +/* Bit 68 Halfwidth And Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ +/* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1L << 5) /* U+FEFF, + U+FFF0-U+FFFF */ +/* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FBF */ + + +/* Some compilers have a very limited length of identifiers. */ +#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) +#define HAVE_LIMIT_ON_IDENTS +#endif + +#ifndef HAVE_LIMIT_ON_IDENTS + +/* + * Here some alias #defines in order to be clearer. + * + * These are not always #defined to stay within the 31 character limit + * which some compilers have. + * + * Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern + * Borland compilers (read: from BC++ 3.1 on) can increase this limit. + * If you get a warning with such a compiler, use the -i40 switch. + */ + +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ + TT_UCR_ARABIC_PRESENTATIONS_A +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ + TT_UCR_ARABIC_PRESENTATIONS_B + +#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ + TT_UCR_COMBINING_DIACRITICS +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + TT_UCR_COMBINING_DIACRITICS_SYMB + +#endif /* ndef HAVE_LIMIT_ON_IDENTS */ + +#endif /* FTNAMEID_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/header.h b/Build/source/libs/libttf/header.h new file mode 100644 index 00000000000..ebd5574404b --- /dev/null +++ b/Build/source/libs/libttf/header.h @@ -0,0 +1,49 @@ +/******************************************************************* + * + * Function : + * + * Description : + * + * Input : + * + * Output : + * + * Notes : + * + ******************************************************************/ + +/******************************************************************* + * + * Function : + * + * Description : + * + * Input : None + * + * Output : Error code. + * + ******************************************************************/ + +/******************************************************************* + * + * Function : + * + * Description : + * + ******************************************************************/ + +/******************************************************************* + * + * Component Name (e.g. TTRaster.C) + eventually a version number. + * + * Component Short Description (e.g. Rasterizer). + * + * Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ diff --git a/Build/source/libs/libttf/libttf.rc b/Build/source/libs/libttf/libttf.rc new file mode 100644 index 00000000000..a711bbca2cb --- /dev/null +++ b/Build/source/libs/libttf/libttf.rc @@ -0,0 +1,36 @@ +/* libttf.rc: libttf resources -*- C++ -*- + + Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr> + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this file; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#include <texlive-version.h> + +#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER +#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " FreeType 1.4" + +#define VER_INTERNALNAME_STR TEXLIVE_LIBRARYPREFIX_STR "ttf" +#define VER_ORIGINALFILENAME_STR TEXLIVE_LIBRARYPREFIX_STR "ttf.dll" + +#define VER_FILEDESCRIPTION_STR "TTF DLL" + +#define VER_LEGALCOPYRIGHT_STR "Copyright (c) 1996-1999 by David Turner, Robert Wilhelm, and Werner Lemberg" + +#define VER_FILETYPE VFT_DLL + +#include <texlive.version> + +/* libttf.rc ends here */ diff --git a/Build/source/libs/libttf/ttapi.c b/Build/source/libs/libttf/ttapi.c new file mode 100644 index 00000000000..2f2d8204bb3 --- /dev/null +++ b/Build/source/libs/libttf/ttapi.c @@ -0,0 +1,2219 @@ +/******************************************************************* + * + * ttapi.c + * + * High-level interface implementation + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Notes: + * + * This file is used to implement most of the functions that are + * defined in the file "freetype.h". However, two functions are + * implemented elsewhere : + * + * TT_MulDiv and TT_MulFix are in ttcalc.h/ttcalc.c + * + ******************************************************************/ + +#include "ttconfig.h" + +#include "freetype.h" +#include "ttengine.h" +#include "ttcalc.h" +#include "ttmemory.h" +#include "ttcache.h" +#include "ttfile.h" +#include "ttobjs.h" +#include "ttload.h" +#include "ttgload.h" +#include "ttraster.h" +#include "ttextend.h" + + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_api + + +#ifdef TT_STATIC_RASTER +#define RAS_OPS /* void */ +#define RAS_OP /* void */ +#else +#define RAS_OPS ((TRaster_Instance*)_engine->raster_component), +#define RAS_OP ((TRaster_Instance*)_engine->raster_component) +#endif /* TT_STATIC_RASTER */ + + +#define RENDER_Glyph( glyph, target ) \ + Render_Glyph( RAS_OPS glyph, target ) + +#define RENDER_Gray_Glyph( glyph, target, palette ) \ + Render_Gray_Glyph( RAS_OPS glyph, target, palette ) + + + +/******************************************************************* + * + * Function : TT_FreeType_Version + * + * Description : Returns the major and minor version of the library. + * + * Input : major, minor addresses + * + * Output : Error code. + * + * MT-Note : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_FreeType_Version( int *major, int *minor ) + { + if ( !major || !minor ) + return TT_Err_Invalid_Argument; + + *major = TT_FREETYPE_MAJOR; + *minor = TT_FREETYPE_MINOR; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Init_FreeType + * + * Description : The library's engine initializer. This function + * must be called prior to any call. + * + * Input : engine pointer to a FreeType engine instance + * + * Output : Error code. + * + * MT-Note : This function should be called each time you want + * to create a TT_Engine. It is not necessarily thread + * safe depending on the implementations of ttmemory, + * ttfile and ttmutex, so take care. Their default + * implementations are safe, however. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Init_FreeType( TT_Engine* engine ) + { + PEngine_Instance _engine; + + TT_Error error; + int n; + + + /* first of all, initialize memory sub-system */ + error = TTMemory_Init(); + if ( error ) + return error; + + /* Allocate engine instance */ + if ( ALLOC( _engine, sizeof ( TEngine_Instance ) ) ) + return error; + +#undef TT_FAIL +#define TT_FAIL( x ) ( error = x (_engine) ) != TT_Err_Ok + + /* Initalize components */ + if ( TT_FAIL( TTFile_Init ) || + TT_FAIL( TTCache_Init ) || +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + TT_FAIL( TTExtend_Init ) || +#endif + TT_FAIL( TTObjs_Init ) || + TT_FAIL( TTRaster_Init ) ) + goto Fail; + +#undef TT_FAIL + + /* set the gray palette defaults: 0 to 4 */ + for ( n = 0; n < 5; n++ ) + _engine->raster_palette[n] = (Byte)n; /* Conversion ok, some warn */ + + /* create the engine lock */ + MUTEX_Create( _engine->lock ); + + HANDLE_Set( *engine, _engine ); + return TT_Err_Ok; + + Fail: + TT_Done_FreeType( *engine ); + HANDLE_Set( *engine, NULL ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Done_FreeType + * + * Description : The library's engine finalizer. This function + * will discard all active face and glyph objects + * from the heap. + * + * Input : engine FreeType engine instance + * + * Output : Error code. + * + * MT-Note : Destroys an engine. Not necessarily thread-safe + * depending on the implementations of ttmemory, + * ttfile and ttmutex. The default implementations + * are safe, however. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_FreeType( TT_Engine engine ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + + if ( !_engine ) + return TT_Err_Ok; + + MUTEX_Destroy( _engine->lock ); + + TTRaster_Done( _engine ); + TTObjs_Done ( _engine ); +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + TTExtend_Done( _engine ); +#endif + TTCache_Done ( _engine ); + TTFile_Done ( _engine ); + FREE( _engine ); + + TTMemory_Done(); + + return TT_Err_Ok; + } + + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + +/******************************************************************* + * + * Function : TT_Set_Raster_Gray_Palette + * + * Description : Sets the gray-levels palette used for font + * smoothing. + * + * Input : engine FreeType engine instance + * palette address of palette (a 5 byte array) + * + * Output : Invalid argument if 'palette' is NULL. + * + * MT-Note: NO! Unprotected modification of an engine's palette. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Raster_Gray_Palette( TT_Engine engine, + Byte* palette ) + { + int i; + + + if ( !palette ) + return TT_Err_Invalid_Argument; + + for ( i = 0; i < 5; i++ ) + HANDLE_Engine( engine )->raster_palette[i] = (Byte)palette[i]; + + return TT_Err_Ok; + } + +#endif /* TT_CONFIG_OPTION_GRAY_SCALING */ + + +/******************************************************************* + * + * Function : TT_Open_Face + * + * Description : Creates a new face object from a given font file. + * + * Input : engine FreeType engine instance + * fontPathName the font file's pathname + * face adress of returned face handle + * + * Output : Error code. + * + * Note : The face handle is set to NULL in case of failure. + * + * MT-Note : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Open_Face( TT_Engine engine, + const TT_Text* fontPathName, + TT_Face* face ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TFont_Input input; + TT_Error error; + TT_Stream stream; + PFace _face; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + /* open the file */ + error = TT_Open_Stream( fontPathName, &stream ); + if ( error ) + return error; + + input.stream = stream; + input.fontIndex = 0; + input.engine = _engine; + + /* Create and load the new face object - this is thread-safe */ + error = CACHE_New( _engine->objs_face_cache, + _face, + &input ); + + /* Set the handle */ + HANDLE_Set( *face, _face ); + + if ( error ) + goto Fail; + + return TT_Err_Ok; + + Fail: + TT_Close_Stream( &stream ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Open_Collection + * + * Description : Creates a new face object from a given font file. + * + * Input : engine FreeType engine instance + * collectionPathName the font file's pathname + * fontIndex index of font in TrueType collection + * face adress of returned face handle + * + * Output : Error code. + * + * Note : The face handle is set to NULL in case of failure. + * + * MT-Note : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Open_Collection( TT_Engine engine, + const TT_Text* collectionPathName, + TT_ULong fontIndex, + TT_Face* face ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + + TFont_Input input; + TT_Error error; + TT_Stream stream; + PFace _face; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + /* open the file */ + error = TT_Open_Stream( collectionPathName, &stream ); + if ( error ) + return error; + + input.stream = stream; + input.fontIndex = fontIndex; + input.engine = _engine; + + /* Create and load the new face object - this is thread-safe */ + error = CACHE_New( _engine->objs_face_cache, + _face, + &input ); + + /* Set the handle */ + HANDLE_Set( *face, _face ); + + if ( error ) + goto Fail; + + return TT_Err_Ok; + + Fail: + TT_Close_Stream( &stream ); + + return error; + } + + +/******************************************************************* + * + * Function : TT_Get_Face_Properties + * + * Description : Returns face properties. + * + * Input : face the face handle + * properties address of target properties record + * + * Output : Error code. + * + * Note : Currently, max_Faces is always set to 0. + * + * MT-Note : YES! Reads only permanent data. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Face_Properties( TT_Face face, + TT_Face_Properties* properties ) + { + PFace _face = HANDLE_Face( face ); + + + if ( !_face ) + return TT_Err_Invalid_Face_Handle; + + properties->num_Glyphs = _face->numGlyphs; + properties->max_Points = _face->maxPoints; + properties->max_Contours = _face->maxContours; + properties->num_CharMaps = _face->numCMaps; + properties->num_Names = _face->nameTable.numNameRecords; + + if ( _face->ttcHeader.DirCount == 0 ) + properties->num_Faces = 1; + else + properties->num_Faces = _face->ttcHeader.DirCount; + + properties->header = &_face->fontHeader; + properties->horizontal = &_face->horizontalHeader; + + if ( _face->verticalInfo ) + properties->vertical = &_face->verticalHeader; + else + properties->vertical = NULL; + + properties->os2 = &_face->os2; + properties->postscript = &_face->postscript; + properties->hdmx = &_face->hdmx; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Set_Face_Pointer + * + * Description : Each face object has one pointer, which use is + * reserved to client applications. The TrueType + * engine never accesses or uses this field. + * + * This function is used to set the pointer. + * + * Input : face the given face handle + * data the generic pointer value + * + * Output : Error code. + * + * MT-Note : NO! But this function is reserved to "enlightened" + * developers, so it shouldn't be a problem. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Face_Pointer( TT_Face face, + void* data ) + { + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + else + faze->generic = data; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Face_Pointer + * + * Description : Each face object has one pointer, which use is + * reserved to client applications. The TrueType + * engine never access or use this field. + * + * This function is used to read the pointer. + * + * Input : face the given face handle + * data the generic pointer value + * + * Output : Error code. + * + * MT-Note : NO! But this function is reserved to "enlightened" + * developers, so it shouldn't be a problem. + * + ******************************************************************/ + + EXPORT_FUNC + void* TT_Get_Face_Pointer( TT_Face face ) + { + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return NULL; + else + return faze->generic; + } + + +/******************************************************************* + * + * Function : TT_Get_Face_Metrics + * + * Description : This function returns the original horizontal AND + * vertical metrics as found in the "hmtx" and "vmtx" + * tables. These are the glyphs' left-side-bearings + * and advance widths (horizontal), as well as top + * side bearings and advance heights (vertical). + * + * All are expressed in FONT UNITS, a.k.a. EM + * units. + * + * Input : face The given face handle. + * first Index of first glyph in table. + * last Index of last glyph in table. + * + * leftBearings A pointer to an array of TT_Shorts where the + * left side bearings for the glyphs 'first' + * to 'last' will be returned. If these metrics + * don't interest you, simply set it to NULL. + * + * widths A pointer to an array of TT_UShorts + * where the advance widths for the glyphs + * 'first' to 'last' will be returned. If these + * metrics don't interest you, simply set it + * to NULL. + * + * topBearings A pointer to an array of TT_Shorts where the + * top side bearings for the glyphs 'first' + * to 'last' will be returned. If these metrics + * don't interest you, simply set it to NULL. + * + * heights A pointer to an array of TT_UShorts + * where the advance heights for the glyphs + * 'first' to 'last' will be returned. If these + * metrics don't interest you, simply set it + * to NULL. + * + * Output : Error code. + * + * IMPORTANT NOTE : + * + * As vertical metrics are optional in a TrueType font, this + * function will return an error ( TT_Err_No_Vertical_Data ) + * whenever this function is called on such a face with non-NULL + * 'topBearings' or 'heights' arguments. + * + * When a font has no vertical data, the 'vertical' field in its + * properties structure is set to NULL. + * + * MT-Note : YES! Reads only permanent data. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Face_Metrics( TT_Face face, + TT_UShort firstGlyph, + TT_UShort lastGlyph, + TT_Short* leftBearings, + TT_UShort* widths, + TT_Short* topBearings, + TT_UShort* heights ) + { + PFace _face = HANDLE_Face( face ); + UShort num; + + + if ( !_face ) + return TT_Err_Invalid_Face_Handle; + + /* Check the glyph range */ + if ( lastGlyph >= _face->numGlyphs || firstGlyph > lastGlyph ) + return TT_Err_Invalid_Argument; + + num = lastGlyph - firstGlyph; /* number of elements-1 in each array */ + + /* store the left side bearings and advance widths first */ + { + UShort n; + Short left_bearing; + UShort advance_width; + + + for ( n = 0; n <= num; n++ ) + { + TT_Get_Metrics( &_face->horizontalHeader, + firstGlyph + n, &left_bearing, &advance_width ); + + if ( leftBearings ) leftBearings[n] = left_bearing; + if ( widths ) widths[n] = advance_width; + } + } + + /* check for vertical data if topBearings or heights is non-NULL */ + if ( !topBearings && !heights ) + return TT_Err_Ok; + + if ( !_face->verticalInfo ) + return TT_Err_No_Vertical_Data; + + /* store the top side bearings */ + { + UShort n; + Short top_bearing; + UShort advance_height; + + for ( n = 0; n <= num; n++ ) + { + TT_Get_Metrics( (TT_Horizontal_Header*)&_face->verticalHeader, + firstGlyph + n, &top_bearing, &advance_height ); + + if ( topBearings ) topBearings[n] = top_bearing; + if ( heights ) heights[n] = advance_height; + } + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Flush_Face + * + * Description : This function is used to close an active face's + * file handle or descriptor. This is useful to save + * system resources, if your application uses tons + * of fonts. + * + * Input : face the given face handle + * + * Output : Error code. + * + * MT-Note : YES! (If ttfile is.) + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Flush_Face( TT_Face face ) + { + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + else + return TT_Flush_Stream( &faze->stream ); + } + + +/******************************************************************* + * + * Function : TT_Close_Face + * + * Description : Closes an opened face object. This function + * will destroy all objects associated to the + * face, except the glyphs. + * + * Input : face the given face handle + * + * Output : Error code. + * + * NOTE : The handle is set to NULL on exit. + * + * MT-Note : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Close_Face( TT_Face face ) + { + PFace _face = HANDLE_Face( face ); + + + if ( !_face ) + return TT_Err_Invalid_Face_Handle; + + TT_Close_Stream( &_face->stream ); + + /* delete the face object -- this is thread-safe */ + return CACHE_Done( _face->engine->objs_face_cache, _face ); + } + + +/******************************************************************* + * + * Function : TT_New_Instance + * + * Description : Creates a new instance from a given face. + * + * Input : face parent face handle + * instance address of instance handle + * + * Output : Error code. + * + * Note : The handle is set to NULL in case of failure. + * + * MT-Note : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_New_Instance( TT_Face face, + TT_Instance* instance ) + { + TT_Error error; + PFace _face = HANDLE_Face( face ); + PInstance _ins; + + + if ( !_face ) + return TT_Err_Invalid_Face_Handle; + + /* get a new instance from the face's cache -- this is thread-safe */ + error = CACHE_New( &_face->instances, _ins, _face ); + + HANDLE_Set( *instance, _ins ); + + if ( !error ) + { + error = Instance_Init( _ins ); + if ( error ) + { + HANDLE_Set( *instance, NULL ); + CACHE_Done( &_face->instances, _ins ); + } + } + + return error; + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_Resolutions + * + * Description : Resets an instance to a new device resolution. + * + * Input : instance the instance handle + * xResolution new horizontal device resolution in dpi + * yResolution new vertical device resolution in dpi + * + * Output : Error code. + * + * Note : There is no check for overflow; with other words, + * the product of glyph dimensions times the device + * resolutions must have reasonable values. + * + * MT-Note : You should set the charsize or pixel size immediately + * after this call in multi-threaded programs. This will + * force the instance data to be resetted. Otherwise, you + * may encounter corruption when loading two glyphs from + * the same instance concurrently! + * + * Happily, 99.99% will do just that :-) + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Resolutions( TT_Instance instance, + TT_UShort xResolution, + TT_UShort yResolution ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + ins->metrics.x_resolution = xResolution; + ins->metrics.y_resolution = yResolution; + ins->valid = FALSE; + + /* In the case of a thread-safe implementation, we immediately */ + /* call Instance_Reset in order to change the instance's variable */ + + /* In the case of a non-threaded build, we simply set the 'valid' */ + /* flag to FALSE, which will force the instance's resetting at */ + /* the next glyph loading */ + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_CharSizes + * + * Description : Resets an instance to new point size. + * + * Input : instance the instance handle + * charWidth the new width in 26.6 char points + * charHeight the new height in 26.6 char points + * + * Output : Error code. + * + * Note : There is no check for overflow; with other words, + * the product of glyph dimensions times the device + * resolution must have reasonable values. + * + * MT-Note : NO! This should be called only when setting/resetting + * instances, so there is no need to protect. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_CharSizes( TT_Instance instance, + TT_F26Dot6 charWidth, + TT_F26Dot6 charHeight ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + if ( charWidth < 1 * 64 ) + charWidth = 1 * 64; + + if ( charHeight < 1 * 64 ) + charHeight = 1 * 64; + + ins->metrics.x_scale1 = ( charWidth * ins->metrics.x_resolution ) / 72; + ins->metrics.x_scale2 = ins->owner->fontHeader.Units_Per_EM; + + ins->metrics.y_scale1 = ( charHeight * ins->metrics.y_resolution ) / 72; + ins->metrics.y_scale2 = ins->owner->fontHeader.Units_Per_EM; + + if ( ins->owner->fontHeader.Flags & 8 ) + { + ins->metrics.x_scale1 = (ins->metrics.x_scale1+32) & -64; + ins->metrics.y_scale1 = (ins->metrics.y_scale1+32) & -64; + } + + ins->metrics.x_ppem = ins->metrics.x_scale1 / 64; + ins->metrics.y_ppem = ins->metrics.y_scale1 / 64; + + if ( charWidth > charHeight ) + ins->metrics.pointSize = charWidth; + else + ins->metrics.pointSize = charHeight; + + ins->valid = FALSE; + + return Instance_Reset( ins ); + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_CharSize + * + * Description : Resets an instance to new point size. + * + * Input : instance the instance handle + * charSize the new character size in 26.6 char points + * + * Output : Error code. + * + * Note : There is no check for overflow; with other words, + * the product of glyph dimensions times the device + * resolution must have reasonable values. + * + * MT-Note : NO! This should be called only when setting/resetting + * instances, so there is no need to protect. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_CharSize( TT_Instance instance, + TT_F26Dot6 charSize ) + { + return TT_Set_Instance_CharSizes( instance, charSize, charSize ); + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_PixelSizes + * + * Description : Resets an instance to new pixel sizes + * + * Input : instance the instance handle + * pixelWidth the new width in pixels + * pixelHeight the new height in pixels + * + * Output : Error code. + * + * Note : There is no check for overflow; with other words, + * the product of glyph dimensions times the device + * resolution must have reasonable values. + * + * MT-Note : NO! This should be called only when setting/resetting + * instances, so there is no need to protect. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_PixelSizes( TT_Instance instance, + TT_UShort pixelWidth, + TT_UShort pixelHeight, + TT_F26Dot6 pointSize ) + { + PInstance ins = HANDLE_Instance( instance ); + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + if ( pixelWidth < 1 ) pixelWidth = 1; + if ( pixelHeight < 1 ) pixelHeight = 1; + + ins->metrics.x_ppem = pixelWidth; + ins->metrics.y_ppem = pixelHeight; + ins->metrics.pointSize = pointSize; + + ins->metrics.x_scale1 = ins->metrics.x_ppem * 64L; + ins->metrics.x_scale2 = ins->owner->fontHeader.Units_Per_EM; + ins->metrics.y_scale1 = ins->metrics.y_ppem * 64L; + ins->metrics.y_scale2 = ins->owner->fontHeader.Units_Per_EM; + + ins->valid = FALSE; + + return Instance_Reset( ins ); + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_Transform_Flags + * + * Description : Informs the interpreter about the transformations + * that will be applied to the rendered glyphs. + * + * Input : instance the instance handle + * rotated set to TRUE if the glyph are rotated + * stretched set to TRUE if the glyph are stretched + * + * Output : Error code. + * + * Note : This function is deprecated! It's much better to + * control hinting manually when calling TT_Load_Glyph + * than relying on the font programs... + * + * Never use it, unless calling for trouble ;-) + * + * MT-Note : NO! This should be called only when setting/resetting + * instances, so there is no need to protect. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Transform_Flags( TT_Instance instance, + TT_Bool rotated, + TT_Bool stretched ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + ins->metrics.rotated = rotated; + ins->metrics.stretched = stretched; + ins->valid = FALSE; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Instance_Metrics + * + * Description : Returns instance metrics. + * + * Input : instance the instance handle + * metrics address of target instance metrics record + * + * Output : Error code. + * + * MT-Note : YES! Reads only semi-permanent data. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Instance_Metrics( TT_Instance instance, + TT_Instance_Metrics* metrics ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + if ( !ins->valid ) + Instance_Reset( ins ); + + metrics->pointSize = ins->metrics.pointSize; + + metrics->x_scale = TT_MulDiv( 0x10000, + ins->metrics.x_scale1, + ins->metrics.x_scale2 ); + + metrics->y_scale = TT_MulDiv( 0x10000, + ins->metrics.y_scale1, + ins->metrics.y_scale2 ); + + metrics->x_resolution = ins->metrics.x_resolution; + metrics->y_resolution = ins->metrics.y_resolution; + metrics->x_ppem = ins->metrics.x_ppem; + metrics->y_ppem = ins->metrics.y_ppem; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Set_Instance_Pointer + * + * Description : Each instance has one pointer, which use is + * reserved to client applications. The TrueType + * engine never accesses or uses this field. + * + * This function is used to set the pointer. + * + * Input : face the given face handle + * data the generic pointer value + * + * Output : Error code. + * + * MT-Note : NO! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Set_Instance_Pointer( TT_Instance instance, + void* data ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + else + ins->generic = data; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Instance_Pointer + * + * Description : Each instance has one pointer, which use is + * reserved to client applications. The TrueType + * engine never accesses or uses this field. + * + * This function is used to read the pointer. + * + * Input : face the given face handle + * data the generic pointer value + * + * Output : Error code. + * + * MT-Safe : NO! + * + ******************************************************************/ + + EXPORT_FUNC + void* TT_Get_Instance_Pointer( TT_Instance instance ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return NULL; + else + return ins->generic; + } + + +/******************************************************************* + * + * Function : TT_Done_Instance + * + * Description : Closes a given instance. + * + * Input : instance address of instance handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Instance( TT_Instance instance ) + { + PInstance ins = HANDLE_Instance( instance ); + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + /* delete the instance -- this is thread-safe */ + return CACHE_Done( &ins->owner->instances, ins ); + } + + +/******************************************************************* + * + * Function : TT_New_Glyph + * + * Description : Creates a new glyph object related to a given + * face. + * + * Input : face the face handle + * glyph address of target glyph handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_New_Glyph( TT_Face face, + TT_Glyph* glyph ) + { + TT_Error error; + PFace _face = HANDLE_Face( face ); + PGlyph _glyph; + + + if ( !_face ) + return TT_Err_Invalid_Face_Handle; + + /* get a new glyph from the face's cache -- this is thread-safe */ + error = CACHE_New( &_face->glyphs, _glyph, _face ); + + HANDLE_Set( *glyph, _glyph ); + + return error; + } + + +/******************************************************************* + * + * Function : TT_Done_Glyph + * + * Description : Destroys a given glyph object. + * + * Input : glyph the glyph handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Glyph( TT_Glyph glyph ) + { + PGlyph _glyph = HANDLE_Glyph( glyph ); + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + /* delete the engine -- this is thread-safe */ + return CACHE_Done( &_glyph->face->glyphs, _glyph ); + } + + +/******************************************************************* + * + * Function : TT_Load_Glyph + * + * Description : Loads a glyph. + * + * Input : instance the instance handle + * glyph the glyph handle + * glyphIndex the glyph index + * loadFlags flags controlling how to load the glyph + * (none, scaled, hinted, both) + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Load_Glyph( TT_Instance instance, + TT_Glyph glyph, + TT_UShort glyphIndex, + TT_UShort loadFlags ) + { + PInstance _ins; + PGlyph _glyph; + TT_Error error; + + + _ins = HANDLE_Instance( instance ); + + if ( !_ins ) + loadFlags &= ~(TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH); + + if ( (loadFlags & TTLOAD_SCALE_GLYPH) == 0 ) + _ins = 0; + + _glyph = HANDLE_Glyph( glyph ); + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + if ( _ins ) + { + if ( _ins->owner != _glyph->face ) + return TT_Err_Invalid_Face_Handle; + + if ( !_ins->valid ) + { + /* This code can only be called in non thread-safe builds */ + error = Instance_Reset( _ins ); + if ( error ) + return error; + } + } + + return Load_TrueType_Glyph( _ins, _glyph, glyphIndex, loadFlags ); + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Outline + * + * Description : Returns the glyph's outline data. + * + * Input : glyph the glyph handle + * outline address where the glyph outline will be returned + * + * Output : Error code. + * + * MT-Safe : YES! Reads only semi-permanent data. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Outline( TT_Glyph glyph, + TT_Outline* outline ) + { + PGlyph _glyph = HANDLE_Glyph( glyph ); + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + *outline = _glyph->outline; + outline->owner = FALSE; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Metrics + * + * Description : Extracts the glyph's horizontal metrics information. + * + * Input : glyph glyph object handle + * metrics address where metrics will be returned + * + * Output : Error code. + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Metrics( TT_Glyph glyph, + TT_Glyph_Metrics* metrics ) + { + PGlyph _glyph = HANDLE_Glyph( glyph ); + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + metrics->bbox = _glyph->metrics.bbox; + metrics->bearingX = _glyph->metrics.horiBearingX; + metrics->bearingY = _glyph->metrics.horiBearingY; + metrics->advance = _glyph->metrics.horiAdvance; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Big_Metrics + * + * Description : Extracts the glyph's big metrics information. + * + * Input : glyph glyph object handle + * metrics address where big metrics will be returned + * + * Output : Error code. + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Big_Metrics( TT_Glyph glyph, + TT_Big_Glyph_Metrics* metrics ) + { + PGlyph _glyph = HANDLE_Glyph( glyph ); + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + *metrics = _glyph->metrics; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Glyph_Bitmap + * + * Description : Produces a bitmap from a glyph outline. + * + * Input : glyph the glyph container's handle + * bitmap target bitmap description block + * xOffset x offset in fractional pixels (26.6 format) + * yOffset y offset in fractional pixels (26.6 format) + * + * Output : Error code. + * + * Note : Only use integer pixel offsets if you want to preserve + * the fine hints applied to the outline. This means that + * xOffset and yOffset must be multiples of 64! + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Bitmap( TT_Glyph glyph, + TT_Raster_Map* bitmap, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + PEngine_Instance _engine; + TT_Engine engine; + TT_Error error; + PGlyph _glyph = HANDLE_Glyph( glyph ); + + TT_Outline outline; + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + _engine = _glyph->face->engine; + HANDLE_Set( engine, _engine ); + + outline = _glyph->outline; + /* XXX : For now, use only dropout mode 2 */ + /* outline.dropout_mode = _glyph->scan_type; */ + outline.dropout_mode = 2; + + TT_Translate_Outline( &outline, xOffset, yOffset ); + error = TT_Get_Outline_Bitmap( engine, &outline, bitmap ); + TT_Translate_Outline( &outline, -xOffset, -yOffset ); + + return error; + } + + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + +/******************************************************************* + * + * Function : TT_Get_Glyph_Pixmap + * + * Description : Produces a grayscaled pixmap from a glyph + * outline. + * + * Input : glyph the glyph container's handle + * pixmap target pixmap description block + * xOffset x offset in fractional pixels (26.6 format) + * yOffset y offset in fractional pixels (26.6 format) + * + * Output : Error code. + * + * Note : Only use integer pixel offsets to preserve the fine + * hinting of the glyph and the 'correct' anti-aliasing + * (where vertical and horizontal stems aren't grayed). + * This means that xOffset and yOffset must be multiples + * of 64! + * + * You can experiment with offsets of +32 to get 'blurred' + * versions of the glyphs (a nice effect at large sizes that + * some graphic designers may appreciate :) + * + * MT-Safe : NO! Glyph containers can't be shared. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Glyph_Pixmap( TT_Glyph glyph, + TT_Raster_Map* pixmap, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + PEngine_Instance _engine; + TT_Engine engine; + TT_Error error; + PGlyph _glyph = HANDLE_Glyph( glyph ); + + TT_Outline outline; + + + if ( !_glyph ) + return TT_Err_Invalid_Glyph_Handle; + + _engine = _glyph->face->engine; + HANDLE_Set(engine,_engine); + + outline = _glyph->outline; + /* XXX : For now, use only dropout mode 2 */ + /* outline.dropout_mode = _glyph->scan_type; */ + outline.dropout_mode = 2; + + TT_Translate_Outline( &outline, xOffset, yOffset ); + error = TT_Get_Outline_Pixmap( engine, &outline, pixmap ); + TT_Translate_Outline( &outline, -xOffset, -yOffset ); + + return error; + } + +#endif /* TT_CONFIG_OPTION_GRAY_SCALING */ + + + static const TT_Outline null_outline + = { 0, 0, NULL, NULL, NULL, 0, 0, 0, 0 }; + + +/******************************************************************* + * + * Function : TT_New_Outline + * + * Description : Creates a new TrueType outline, reserving + * array space for a given number of points and + * contours. + * + * Input : numPoints number of points + * numContours number of contours + * outline address of target outline structure + * + * Output : Error code + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_New_Outline( TT_UShort numPoints, + TT_Short numContours, + TT_Outline* outline ) + { + TT_Error error; + + + if ( !outline ) + return TT_Err_Invalid_Argument; + + *outline = null_outline; + + if ( ALLOC( outline->points, numPoints*2*sizeof ( TT_F26Dot6 ) ) || + ALLOC( outline->flags, numPoints *sizeof ( Byte ) ) || + ALLOC( outline->contours, numContours*sizeof ( UShort ) ) ) + goto Fail; + + outline->n_points = numPoints; + outline->n_contours = numContours; + outline->owner = TRUE; + return TT_Err_Ok; + + Fail: + outline->owner = TRUE; + TT_Done_Outline( outline ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Done_Outline + * + * Description : Deletes an outline created through TT_New_Outline(). + * Calling this function for outlines returned + * by TT_Get_Glyph_Outline() yields an error. + * + * Input : outline address of outline + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Outline( TT_Outline* outline ) + { + if ( outline ) + { + if ( outline->owner ) + { + FREE( outline->points ); + FREE( outline->flags ); + FREE( outline->contours ); + } + *outline = null_outline; + return TT_Err_Ok; + } + else + return TT_Err_Invalid_Argument; + } + + +/******************************************************************* + * + * Function : TT_Get_Outline_Bitmap + * + * Description : Render a TrueType outline into a bitmap. + * Note that the bitmap must be created by the caller. + * + * Input : outline the outline to render + * bitmap the target bitmap + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Outline_Bitmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* bitmap ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + if ( !outline || !bitmap ) + return TT_Err_Invalid_Argument; + + MUTEX_Lock( _engine->raster_lock ); + error = RENDER_Glyph( outline, bitmap ); + MUTEX_Release( _engine->raster_lock ); + + return error; + } + + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + +/******************************************************************* + * + * Function : TT_Get_Outline_Pixmap + * + * Description : Render a TrueType outline into a pixmap. + * Note that the pixmap must be created by the caller. + * + * Input : outline the outline to render + * pixmap the target pixmap + * + * Output : Error code + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Outline_Pixmap( TT_Engine engine, + TT_Outline* outline, + TT_Raster_Map* pixmap ) + { + PEngine_Instance _engine = HANDLE_Engine( engine ); + TT_Error error; + + + if ( !_engine ) + return TT_Err_Invalid_Engine; + + if ( !outline || !pixmap ) + return TT_Err_Invalid_Argument; + + MUTEX_Lock( _engine->raster_lock ); + error = RENDER_Gray_Glyph( outline, pixmap, _engine->raster_palette ); + MUTEX_Release( _engine->raster_lock ); + return error; + } + +#endif /* TT_CONFIG_OPTION_GRAY_SCALING */ + + +/******************************************************************* + * + * Function : TT_Copy_Outline + * + * Description : Copy an outline into another. The source and + * target outlines must have the same points and + * contours numbers. + * + * Input : source address of source outline + * target address of target outline + * + * Output : Error code + * + * Note : This function doesn't touch the target outline's 'owner' + * field. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Copy_Outline( TT_Outline* source, + TT_Outline* target ) + { + if ( !source || !target || + source->n_points != target->n_points || + source->n_contours != target->n_contours ) + return TT_Err_Invalid_Argument; + + MEM_Copy( target->points, source->points, + source->n_points * 2 * sizeof ( TT_F26Dot6 ) ); + + MEM_Copy( target->flags, source->flags, + source->n_points * sizeof ( Byte ) ); + + MEM_Copy( target->contours, source->contours, + source->n_contours * sizeof ( Short ) ); + + target->high_precision = source->high_precision; + target->second_pass = target->second_pass; + target->dropout_mode = source->dropout_mode; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Transform_Outline + * + * Description : Applies a simple transformation to an outline. + * + * Input : outline the glyph's outline. Can be extracted + * from a glyph container through + * TT_Get_Glyph_Outline(). + * + * matrix simple matrix with 16.16 fixed floats + * + * Output : Error code (always TT_Err_Ok). + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Transform_Outline( TT_Outline* outline, + TT_Matrix* matrix ) + { + UShort n; + TT_F26Dot6 x, y; + TT_Vector* vec; + + + vec = outline->points; + for ( n = 0; n < outline->n_points; n++ ) + { + x = TT_MulFix( vec->x, matrix->xx ) + + TT_MulFix( vec->y, matrix->xy ); + + y = TT_MulFix( vec->x, matrix->yx ) + + TT_MulFix( vec->y, matrix->yy ); + + vec->x = x; + vec->y = y; + vec++; + } + } + + +/******************************************************************* + * + * Function : TT_Transform_Vector + * + * Description : Apply a simple transform to a vector + * + * Input : x, y the vector. + * + * matrix simple matrix with 16.16 fixed floats + * + * Output : None. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Transform_Vector( TT_F26Dot6* x, + TT_F26Dot6* y, + TT_Matrix* matrix ) + { + TT_F26Dot6 xz, yz; + + + xz = TT_MulFix( *x, matrix->xx ) + + TT_MulFix( *y, matrix->xy ); + + yz = TT_MulFix( *x, matrix->yx ) + + TT_MulFix( *y, matrix->yy ); + + *x = xz; + *y = yz; + } + + +/******************************************************************* + * + * Function : TT_Translate_Outline + * + * Description : Applies a simple translation. + * + * Input : outline no comment :) + * xOffset + * yOffset + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + void TT_Translate_Outline( TT_Outline* outline, + TT_F26Dot6 xOffset, + TT_F26Dot6 yOffset ) + { + UShort n; + TT_Vector* vec = outline->points; + + + for ( n = 0; n < outline->n_points; n++ ) + { + vec->x += xOffset; + vec->y += yOffset; + vec++; + } + } + + +/******************************************************************* + * + * Function : TT_Get_Outline_BBox + * + * Description : Returns an outline's bounding box. + * + * Input : outline no comment :) + * bbox address where the bounding box is returned + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Outline_BBox( TT_Outline* outline, + TT_BBox* bbox ) + { + TT_F26Dot6 x, y; + UShort k; + + + if ( outline && bbox ) + { + if ( outline->n_points == 0 ) + { + bbox->xMin = 0; + bbox->yMin = 0; + bbox->xMax = 0; + bbox->yMax = 0; + } + else + { + TT_Vector* vec = outline->points; + + bbox->xMin = bbox->xMax = vec->x; + bbox->yMin = bbox->yMax = vec->y; + vec++; + + for ( k = 1; k < outline->n_points; k++ ) + { + x = vec->x; + if ( x < bbox->xMin ) bbox->xMin = x; + if ( x > bbox->xMax ) bbox->xMax = x; + y = vec->y; + if ( y < bbox->yMin ) bbox->yMin = y; + if ( y > bbox->yMax ) bbox->yMax = y; + vec++; + } + } + return TT_Err_Ok; + } + else + return TT_Err_Invalid_Argument; + } + + + + /* ----------------- character mappings support ------------- */ + +/******************************************************************* + * + * Function : TT_Get_CharMap_Count + * + * Description : Returns the number of charmaps in a given face. + * + * Input : face face object handle + * + * Output : Number of tables. -1 in case of error (bad handle). + * + * Note : DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! + * + * It is retained for backwards compatibility only and will + * fail on 16bit systems. + * + * MT-Safe : YES ! + * + ******************************************************************/ + + EXPORT_FUNC + int TT_Get_CharMap_Count( TT_Face face ) + { + PFace faze = HANDLE_Face( face ); + + return ( faze ? faze->numCMaps : -1 ); + } + + +/******************************************************************* + * + * Function : TT_Get_CharMap_ID + * + * Description : Returns the ID of a given charmap. + * + * Input : face face object handle + * charmapIndex index of charmap in directory + * platformID address of returned platform ID + * encodingID address of returned encoding ID + * + * Output : error code + * + * MT-Safe : YES ! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_CharMap_ID( TT_Face face, + TT_UShort charmapIndex, + TT_UShort* platformID, + TT_UShort* encodingID ) + { + PCMapTable cmap; + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( charmapIndex >= faze->numCMaps ) + return TT_Err_Invalid_Argument; + + cmap = faze->cMaps + charmapIndex; + + *platformID = cmap->platformID; + *encodingID = cmap->platformEncodingID; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_CharMap + * + * Description : Looks up a charmap. + * + * Input : face face object handle + * charmapIndex index of charmap in directory + * charMap address of returned charmap handle + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_CharMap( TT_Face face, + TT_UShort charmapIndex, + TT_CharMap* charMap ) + { + TT_Error error; + TT_Stream stream; + PCMapTable cmap; + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( charmapIndex >= faze->numCMaps ) + return TT_Err_Invalid_Argument; + + cmap = faze->cMaps + charmapIndex; + + /* Load table if needed */ + error = TT_Err_Ok; + + /* MT-NOTE: We're modifying the face object, so protect it. */ + MUTEX_Lock( faze->lock ); + + if ( !cmap->loaded ) + { + (void)USE_Stream( faze->stream, stream ); + if ( !error ) + { + error = CharMap_Load( cmap, stream ); + DONE_Stream( stream ); + } + + if ( error ) + cmap = NULL; + else + cmap->loaded = TRUE; + } + MUTEX_Release( faze->lock ); + + HANDLE_Set( *charMap, cmap ); + + return error; + } + + +/******************************************************************* + * + * Function : TT_Char_Index + * + * Description : Returns the glyph index corresponding to + * a given character code defined for the 'charmap'. + * + * Input : charMap charmap handle + * charcode character code + * + * Output : glyph index. + * + * Notes : Character code 0 is the unknown glyph, which should never + * be displayed. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_UShort TT_Char_Index( TT_CharMap charMap, + TT_ULong charCode ) + { + PCMapTable cmap = HANDLE_CharMap( charMap ); + + + if ( !cmap ) + return 0; /* we return 0 in case of invalid char map */ + + return CharMap_Index( cmap, charCode ); + } + + +/******************************************************************* + * + * Function : TT_Get_Name_Count + * + * Description : Returns the number of strings found in the + * name table. + * + * Input : face face handle + * + * Output : number of strings. + * + * Notes : Returns -1 on error (invalid handle). + * + * DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! + * + * It is retained for backwards compatibility only and will + * fail on 16bit systems. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + int TT_Get_Name_Count( TT_Face face ) + { + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return -1; + + return faze->nameTable.numNameRecords; + } + + +/******************************************************************* + * + * Function : TT_Get_Name_ID + * + * Description : Returns the IDs of the string number 'nameIndex' + * in the name table of a given face. + * + * Input : face face handle + * nameIndex index of string. First is 0 + * platformID addresses of returned IDs + * encodingID + * languageID + * nameID + * + * Output : Error code. + * + * Notes : Some files have a corrupt or unusual name table, with some + * entries having a platformID > 3. These can usually + * be ignored by a client application. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Name_ID( TT_Face face, + TT_UShort nameIndex, + TT_UShort* platformID, + TT_UShort* encodingID, + TT_UShort* languageID, + TT_UShort* nameID ) + { + TNameRec* namerec; + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( nameIndex >= faze->nameTable.numNameRecords ) + return TT_Err_Invalid_Argument; + + namerec = faze->nameTable.names + nameIndex; + + *platformID = namerec->platformID; + *encodingID = namerec->encodingID; + *languageID = namerec->languageID; + *nameID = namerec->nameID; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Name_String + * + * Description : Returns the address and length of a given + * string found in the name table. + * + * Input : face face handle + * nameIndex string index + * stringPtr address of returned pointer to string + * length address of returned string length + * + * Output : Error code. + * + * Notes : If the string's platformID is invalid, + * stringPtr is NULL, and length is 0. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Name_String( TT_Face face, + TT_UShort nameIndex, + TT_String** stringPtr, + TT_UShort* length ) + { + TNameRec* namerec; + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + if ( nameIndex >= faze->nameTable.numNameRecords ) + return TT_Err_Invalid_Argument; + + namerec = faze->nameTable.names + nameIndex; + + *stringPtr = (String*)namerec->string; + *length = namerec->stringLength; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Get_Font_Data + * + * Description : Loads any font table into client memory. + * + * Input : face Face object to look for. + * + * tag Tag of table to load. Use the value 0 if you + * want to access the whole font file, else set + * this parameter to a valid TrueType table tag + * that you can forge with the MAKE_TT_TAG + * macro. + * + * offset Starting offset in the table (or the file + * if tag == 0). + * + * buffer Address of target buffer + * + * length Address of decision variable: + * + * if length == NULL: + * Load the whole table. Returns an + * error if 'offset' != 0. + * + * if *length == 0 : + * Exit immediately, returning the + * length of the given table, or of + * the font file, depending on the + * value of 'tag'. + * + * if *length != 0 : + * Load the next 'length' bytes of + * table or font, starting at offset + * 'offset' (in table or font too). + * + * Output : Error code. + * + * MT-Safe : YES! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Get_Font_Data( TT_Face face, + TT_ULong tag, + TT_Long offset, + void* buffer, + TT_Long* length ) + { + PFace faze = HANDLE_Face( face ); + + + if ( !faze ) + return TT_Err_Invalid_Face_Handle; + + return Load_TrueType_Any( faze, tag, offset, buffer, length ); + } + + + /************************ callback definition ******************/ + + /* Register a new callback to the TrueType engine -- this should */ + /* only be used by higher-level libraries, not typical clients */ + /* */ + /* This is not part of the current FreeType release, thus */ + /* undefined... */ + +#if 0 + EXPORT_FUNC + TT_Error TT_Register_Callback( TT_Engine engine, + int callback_id, + void* callback_ptr ) + { + PEngine_Instance eng = HANDLE_Engine( engine ); + + + if ( !eng ) + return TT_Err_Invalid_Argument; + + /* currently, we only support one callback */ + if (callback_id != TT_Callback_Glyph_Outline_Load) + return TT_Err_Invalid_Argument; + + eng->glCallback = (TT_Glyph_Loader_Callback)callback_ptr; + return TT_Err_Ok; + } +#endif /* 0 */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttcache.c b/Build/source/libs/libttf/ttcache.c new file mode 100644 index 00000000000..51624194b97 --- /dev/null +++ b/Build/source/libs/libttf/ttcache.c @@ -0,0 +1,463 @@ +/******************************************************************* + * + * ttcache.c 1.1 + * + * Generic object cache + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Changes between 1.1 and 1.0: + * + * - introduced the refresher and finalizer in the cache class + * definition/implementation. + * + ******************************************************************/ + +#include "ttengine.h" +#include "ttmemory.h" +#include "ttcache.h" +#include "ttobjs.h" +#include "ttdebug.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_cache + +#define ZERO_List( list ) list = NULL + +/* The macro FREE_Elements aliases the current engine instance's */ +/* free list_elements recycle list. */ +#define FREE_Elements ( engine->list_free_elements ) + +/* Redefinition of LOCK and UNLOCK macros for New_Element and Done_Element */ +/* Note: The macros are redefined below for the cache functions */ + +#undef LOCK +#define LOCK() MUTEX_Lock ( engine->lock ) + +#undef UNLOCK +#define UNLOCK() MUTEX_Release( engine->lock ) + +/******************************************************************* + * + * Function : Element_New + * + * Description : Gets a new (either fresh or recycled) list + * element. The element is unlisted. + * + * Input : None + * + * Output : List element address. NULL if out of memory. + * + ******************************************************************/ + + static + PList_Element Element_New( PEngine_Instance engine ) + { + PList_Element element; + + + LOCK(); + if ( FREE_Elements ) + { + element = (PList_Element)FREE_Elements; + FREE_Elements = element->next; + } + else + { + if ( !MEM_Alloc( element, sizeof ( TList_Element ) ) ) + { + element->next = NULL; + element->data = NULL; + } + } + + /* Note: in case of failure, Alloc sets the pointer to NULL */ + UNLOCK(); + + return element; + } + + +/******************************************************************* + * + * Function : Element_Done + * + * Description : Recycles an unlinked list element. + * + * Input : The list element to recycle. It _must_ be unlisted. + * + * Output : none. + * + * Note : This function doesn't check the element. + * + ******************************************************************/ + + static + void Element_Done( PEngine_Instance engine, + PList_Element element ) + { + LOCK(); + /* Simply add the list element to the recycle list */ + element->next = (PList_Element)FREE_Elements; + FREE_Elements = element; + UNLOCK(); + } + + +/* Redefinition of LOCK and UNLOCK macros for the cache functions */ +/* Note: The macros are defined above for the list element functions */ + +#undef LOCK +#define LOCK() MUTEX_Lock( *cache->lock ) + +#undef UNLOCK +#define UNLOCK() MUTEX_Release( *cache->lock ) + + +/******************************************************************* + * + * Function : Cache_Create + * + * Description : Creates a new cache that will be used to list + * and recycle several objects of the same class. + * + * Input : clazz a pointer to the cache's class. This is + * a simple structure that describes the + * the cache's object types and recycling + * limits. + * + * cache address of cache to create + * + * lock address of the mutex to use for this + * cache. The mutex will be used to protect + * the cache's lists. Use NULL for unprotected + * cache. + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Cache_Create( PEngine_Instance engine, + PCache_Class clazz, + TCache* cache, + TMutex* lock ) + { + cache->engine = engine; + cache->clazz = clazz; + cache->lock = lock; + cache->idle_count = 0; + + ZERO_List( cache->active ); + ZERO_List( cache->idle ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Cache_Destroy + * + * Description : Destroys a cache and all its idle and active + * objects. This will call each object's destructor + * before freeing it. + * + * Input : cache address of cache to destroy + * + * Output : error code. + * + * Note: This function is not MT-Safe, as we assume that a client + * isn't stupid enough to use an object while destroying it. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Cache_Destroy( TCache* cache ) + { + PDestructor destroy; + PList_Element current; + PList_Element next; + + + /* now destroy all active and idle listed objects */ + + /* get the destructor function */ + destroy = cache->clazz->done; + + /* destroy all elements in active list */ + current = cache->active; + while ( current ) + { + next = current->next; + destroy( current->data ); + FREE( current->data ); + + Element_Done( cache->engine, current ); + current = next; + } + ZERO_List(cache->active); + + /* destroy all elements in idle list */ + current = cache->idle; + while ( current ) + { + next = current->next; + destroy( current->data ); + FREE( current->data ); + + Element_Done( cache->engine, current ); + current = next; + } + ZERO_List(cache->idle); + + cache->clazz = NULL; + cache->idle_count = 0; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Cache_New + * + * Description : Extracts a new object from a cache. This will + * try to recycle an idle object, if any is found. + * Otherwise, a new object will be allocated and + * built (by calling its constructor). + * + * Input : cache address of cache to use + * new_object address of target pointer to the 'new' + * object + * parent_object this pointer is passed to a new object + * constructor (unused if object is + * recycled) + * + * Output : Error code. + * + * Notes: This function is thread-safe, each cache list is protected + * through the cache's mutex, if there is one... + * + * *new_object will be set to NULL in case of failure. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Cache_New( TCache* cache, + void** new_object, + void* parent_object ) + { + TT_Error error; + PList_Element current; + PConstructor build; + PRefresher reset; + void* object; + + + LOCK(); + current = cache->idle; + if ( current ) + { + cache->idle = current->next; + cache->idle_count--; + } + UNLOCK(); + + if ( current ) + { + object = current->data; + reset = cache->clazz->reset; + if ( reset ) + { + error = reset( object, parent_object ); + if ( error ) + { + LOCK(); + current->next = cache->idle; + cache->idle = current; + cache->idle_count++; + UNLOCK(); + goto Exit; + } + } + } + else + { + /* if no object was found in the cache, create a new one */ + build = cache->clazz->init; + + if ( MEM_Alloc( object, cache->clazz->object_size ) ) + goto Memory_Fail; + + current = Element_New( cache->engine ); + if ( !current ) + goto Memory_Fail; + + current->data = object; + + error = build( object, parent_object ); + if ( error ) + { + Element_Done( cache->engine, current ); + goto Fail; + } + } + + LOCK(); + current->next = cache->active; + cache->active = current; + UNLOCK(); + + *new_object = current->data; + return TT_Err_Ok; + + Exit: + *new_object = NULL; + return error; + + Memory_Fail: + error = TT_Err_Out_Of_Memory; + + Fail: + FREE( object ); + goto Exit; + } + + +/******************************************************************* + * + * Function : Cache_Done + * + * Description : Releases an object to the cache. This will either + * recycle or destroy the object, based on the cache's + * class and state. + * + * Input : cache the cache to use + * data the object to recycle/discard + * + * Output : error code. + * + * Notes : The object's destructor is called only when + * the objectwill be effectively destroyed by this + * function. This will not happen during recycling. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Cache_Done( TCache* cache, void* data ) + { + TT_Error error; + PList_Element element; + PList_Element prev; + PFinalizer finalize; + Long limit; + Bool destroy; + + + /* Look for object in active list */ + LOCK(); + + element = cache->active; + prev = NULL; + while ( element ) + { + if ( element->data == data ) + { + if ( prev ) + prev->next = element->next; + else + cache->active = element->next; + goto Suite; + } + prev = element; + element = element->next; + } + + UNLOCK(); + return TT_Err_Unlisted_Object; + + Suite: + + limit = cache->clazz->idle_limit; + destroy = (cache->idle_count >= limit); + UNLOCK(); + + if ( destroy ) + { + /* destroy the object when the cache is full */ + cache->clazz->done( element->data ); + FREE( element->data ); + Element_Done( cache->engine, element ); + } + else + { + /* Finalize the object before adding it to the */ + /* idle list. Return the error if any is found. */ + + finalize = cache->clazz->finalize; + if ( finalize ) + { + error = finalize( element->data ); + if ( error ) + goto Exit; + + /* Note: a failure at finalize time is a severe bug in */ + /* the engine, which is why we allow ourselves to */ + /* lose the object in this case. A finalizer should */ + /* have its own error codes to spot this kind of */ + /* problems easily. */ + } + + LOCK(); + element->next = cache->idle; + cache->idle = element; + cache->idle_count++; + UNLOCK(); + } + + error = TT_Err_Ok; + + Exit: + return error; + } + + + LOCAL_FUNC + TT_Error TTCache_Init( PEngine_Instance engine ) + { + /* Create list elements mutex */ + FREE_Elements = NULL; + return TT_Err_Ok; + } + + + LOCAL_FUNC + TT_Error TTCache_Done( PEngine_Instance engine ) + { + /* We don't protect this function, as this is the end of the engine's */ + /* execution.. */ + PList_Element element, next; + + + /* frees the recycled list elements */ + element = FREE_Elements; + while ( element ) + { + next = element->next; + FREE( element ); + element = next; + } + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttcache.h b/Build/source/libs/libttf/ttcache.h new file mode 100644 index 00000000000..e6f17c3c6ef --- /dev/null +++ b/Build/source/libs/libttf/ttcache.h @@ -0,0 +1,216 @@ +/******************************************************************* + * + * ttcache.h 1.1 + * + * Generic object cache + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This component defines and implements object caches. + * + * An object class is a structure layout that encapsulate one + * given type of data used by the FreeType engine. Each object + * class is completely described by: + * + * - a 'root' or 'leading' structure containing the first + * important fields of the class. The root structure is + * always of fixed size. + * + * It is implemented as a simple C structure, and may + * contain several pointers to sub-tables that can be + * sized and allocated dynamically. + * + * Examples: TFace, TInstance, TGlyph & TExecution_Context + * (defined in 'ttobjs.h') + * + * - we make a difference between 'child' pointers and 'peer' + * pointers. A 'child' pointer points to a sub-table that is + * owned by the object, while a 'peer' pointer points to any + * other kind of data the object isn't responsible for. + * + * An object class is thus usually a 'tree' of 'child' tables. + * + * - each object class needs a constructor and a destructor. + * + * A constructor is a function which receives the address of + * freshly allocated and zeroed object root structure and + * 'builds' all the valid child data that must be associated + * to the object before it becomes 'valid'. + * + * A destructor does the inverse job: given the address of + * a valid object, it must discard all its child data and + * zero its main fields (essentially the pointers and array + * sizes found in the root fields). + * + * + * Important notes: + * + * When the constructor fails to allocate an object, it must + * return immediately with an error code, and not try to release + * what it has previously allocated before the error. The cache + * manager detects the error and calls the destructor on the + * partial object, before returning the error to the caller (along + * with a NULL pointer for the "new" object). + * + * The destructor must thus be able to deal with "partial objects", + * i.e., objects where only part of the child tables are allocated, + * and only release these ones. As the TT_Free() function accepts + * a NULL parameter (and returns successfuly in this case), no check + * is really necessary when using the macro 'FREE()'. + * + * Currently, there is no check in the cache manager to see if a + * destructor fails (double error state!). + * + * This scheme is more compact and more maintanable than the one + * where de-allocation code is duplicated in the constructor + * _and_ the destructor. + * + * + * + * Changes between 1.1 and 1.0: + * + * - introduced the refreshed and finalizer class definition/implementation + * - inserted an engine instance pointer in the cache structure + * + ******************************************************************/ + +#ifndef TTCACHE_H +#define TTCACHE_H + +#include "tttypes.h" +#include "ttconfig.h" +#include "ttmutex.h" + +#ifdef __cplusplus + extern "C" { +#endif + + typedef TT_Error TConstructor( void* object, + void* parent ); + + typedef TT_Error TDestructor ( void* object ); + + typedef TConstructor TRefresher; + typedef TDestructor TFinalizer; + + typedef TConstructor* PConstructor; + typedef TDestructor* PDestructor; + typedef TRefresher* PRefresher; + typedef TFinalizer* PFinalizer; + + + /* A Cache class record holds the data necessary to define */ + /* a cache kind. */ + struct TCache_Class_ + { + ULong object_size; + Long idle_limit; + PConstructor init; + PDestructor done; + PRefresher reset; + PFinalizer finalize; + }; + + typedef struct TCache_Class_ TCache_Class; + typedef TCache_Class* PCache_Class; + + + + /* Simple list node record. A list element is said to be 'unlinked' */ + /* when it doesn't belong to any list. */ + struct TList_Element_; + + typedef struct TList_Element_ TList_Element; + typedef TList_Element* PList_Element; + + struct TList_Element_ + { + PList_Element next; + void* data; + }; + + + /* Simple singly-linked list record - LIFO style, no tail field */ + typedef PList_Element TSingle_List; + + struct TCache_ + { + PEngine_Instance engine; + PCache_Class clazz; /* 'class' is a reserved word in C++ */ + TMutex* lock; + TSingle_List active; + TSingle_List idle; + Long idle_count; + }; + + typedef struct TCache_ TCache; + typedef TCache* PCache; + + /* Returns a new list element, either fresh or recycled. */ + /* Note: the returned element is unlinked. */ + + /* An object cache holds two lists tracking the active and */ + /* idle objects that are currently created and used by the */ + /* engine. It can also be 'protected' by a mutex. */ + + /* Initializes a new cache, of class 'clazz', pointed by 'cache', */ + /* protected by the 'lock' mutex. Set 'lock' to NULL if the cache */ + /* doesn't need protection */ + + LOCAL_DEF + TT_Error Cache_Create( PEngine_Instance engine, + PCache_Class clazz, + TCache* cache, + TMutex* lock ); + + /* Destroys a cache and all its listed objects */ + + LOCAL_DEF + TT_Error Cache_Destroy( TCache* cache ); + + + /* Extracts a new object from the cache */ + + LOCAL_DEF + TT_Error Cache_New( TCache* cache, + void** new_object, + void* parent_object ); + + + /* Returns an object to the cache, or discards it depending */ + /* on the cache class' 'idle_limit' field */ + + LOCAL_DEF + TT_Error Cache_Done( TCache* cache, void* data ); + +#define CACHE_New( _cache, _newobj, _parent ) \ + Cache_New( (TCache*)_cache, (void**)&_newobj, (void*)_parent ) + +#define CACHE_Done( _cache, _obj ) \ + Cache_Done( (TCache*)_cache, (void*)_obj ) + + + + LOCAL_DEF + TT_Error TTCache_Init( PEngine_Instance engine ); + + LOCAL_DEF + TT_Error TTCache_Done( PEngine_Instance engine ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTCACHE_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttcalc.c b/Build/source/libs/libttf/ttcalc.c new file mode 100644 index 00000000000..0733624279b --- /dev/null +++ b/Build/source/libs/libttf/ttcalc.c @@ -0,0 +1,403 @@ +/******************************************************************* + * + * ttcalc.c + * + * Arithmetic Computations (body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "ttcalc.h" +#include "ttdebug.h" +#include "tttables.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_calc + + +/* Support for 1-complement arithmetic has been totally dropped in this */ +/* release. You can still write your own code if you need it... */ + + static const Long Roots[63] = + { + 1, 1, 2, 3, 4, 5, 8, 11, + 16, 22, 32, 45, 64, 90, 128, 181, + 256, 362, 512, 724, 1024, 1448, 2048, 2896, + 4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340, + + 65536, 92681, 131072, 185363, 262144, 370727, + 524288, 741455, 1048576, 1482910, 2097152, 2965820, + 4194304, 5931641, 8388608, 11863283, 16777216, 23726566, + + 33554432, 47453132, 67108864, 94906265, + 134217728, 189812531, 268435456, 379625062, + 536870912, 759250125, 1073741824, 1518500250, + 2147483647 + }; + + +#ifdef LONG64 + + EXPORT_FUNC + TT_Long TT_MulDiv( TT_Long a, TT_Long b, TT_Long c ) + { + Long s; + + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + s ^= c; c = ABS( c ); + + a = ((TT_Int64)a * b + c/2) / c; + return ( s < 0 ) ? -a : a; + } + + + EXPORT_FUNC + TT_Long TT_MulFix( TT_Long a, TT_Long b ) + { + Long s; + + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + + a = ((TT_Int64)a * b + 0x8000) / 0x10000; + return ( s < 0 ) ? -a : a; + } + + + LOCAL_FUNC + Int Order64( TT_Int64 z ) + { + Int j = 0; + + + while ( z ) + { + z = (unsigned INT64)z >> 1; + j++; + } + return j - 1; + } + + + LOCAL_FUNC + TT_Int32 Sqrt64( TT_Int64 l ) + { + TT_Int64 r, s; + + + if ( l <= 0 ) return 0; + if ( l == 1 ) return 1; + + r = Roots[Order64( l )]; + + do + { + s = r; + r = ( r + l/r ) >> 1; + } + while ( r > s || r*r > l ); + + return r; + } + +#else /* LONG64 */ + + + /* The TT_MulDiv function has been optimized thanks to ideas from */ + /* Graham Asher. The trick is to optimize computation when everything */ + /* fits within 32-bits (a rather common case). */ + /* */ + /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */ + /* */ + /* 46340 is FLOOR(SQRT(2^31-1)). */ + /* */ + /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ + /* */ + /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ + /* */ + /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ + /* */ + /* and 2*0x157F0 = 176096 */ + /* */ + + EXPORT_FUNC + TT_Long TT_MulDiv( TT_Long a, TT_Long b, TT_Long c ) + { + long s; + + + if ( a == 0 || b == c ) + return a; + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + s ^= c; c = ABS( c ); + + if ( a <= 46340 && b <= 46340 && c <= 176095 ) + { + a = ( a*b + c/2 )/c; + } + else + { + TT_Int64 temp, temp2; + + MulTo64( a, b, &temp ); + temp2.hi = (TT_Int32)(c >> 31); + temp2.lo = (TT_Word32)(c / 2); + Add64( &temp, &temp2, &temp ); + a = Div64by32( &temp, c ); + } + + return ( s < 0 ) ? -a : a; + } + + /* The optimization for TT_MulFix is different. We could simply be */ + /* happy by applying the same principles than with TT_MulDiv, because */ + /* */ + /* c = 0x10000 < 176096 */ + /* */ + /* however, in most cases, we have a 'b' with a value around 0x10000 */ + /* which is greater than 46340. */ + /* */ + /* According to Graham's testing, most cases have 'a' < 100, so a good */ + /* idea is to use bounds like 1024 and 2097151 (= floor(2^31-1)/1024 ) */ + /* for 'a' and 'b' respectively.. */ + /* */ + + EXPORT_FUNC + TT_Long TT_MulFix( TT_Long a, TT_Long b ) + { + long s; + + if ( a == 0 || b == 0x10000 ) + return a; + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + + if ( a <= 1024 && b <= 2097151 ) + { + a = ( a*b + 0x8000 ) >> 16; + } + else + { + TT_Int64 temp, temp2; + + MulTo64( a, b, &temp ); + temp2.hi = 0; + temp2.lo = 0x8000; + Add64( &temp, &temp2, &temp ); + a = Div64by32( &temp, 0x10000 ); + } + + return ( s < 0 ) ? -a : a; + } + + + LOCAL_FUNC + void Neg64( TT_Int64* x ) + { + /* Remember that -(0x80000000) == 0x80000000 with 2-complement! */ + /* We take care of that here. */ + + x->hi ^= 0xFFFFFFFFUL; + x->lo ^= 0xFFFFFFFFUL; + x->lo++; + + if ( !x->lo ) + { + x->hi++; + if ( x->hi == 0x80000000UL ) /* Check -MaxInt32 - 1 */ + { + x->lo--; + x->hi--; /* We return 0x7FFFFFFF! */ + } + } + } + + + LOCAL_FUNC + void Add64( TT_Int64* x, TT_Int64* y, TT_Int64* z ) + { + register TT_Word32 lo, hi; + + + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < x->lo ); + + z->lo = lo; + z->hi = hi; + } + + + LOCAL_FUNC + void Sub64( TT_Int64* x, TT_Int64* y, TT_Int64* z ) + { + register TT_Word32 lo, hi; + + + lo = x->lo - y->lo; + hi = x->hi - y->hi - ( (TT_Int32)lo < 0 ); + + z->lo = lo; + z->hi = hi; + } + + + LOCAL_FUNC + void MulTo64( TT_Int32 x, TT_Int32 y, TT_Int64* z ) + { + TT_Int32 s; + TT_Word32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + + s = x; x = ABS( x ); + s ^= y; y = ABS( y ); + + lo1 = x & 0x0000FFFF; hi1 = x >> 16; + lo2 = y & 0x0000FFFF; hi2 = y >> 16; + + lo = lo1*lo2; + i1 = lo1*hi2; + i2 = lo2*hi1; + hi = hi1*hi2; + + /* Check carry overflow of i1 + i2 */ + + if ( i2 ) + { + if ( i1 >= (TT_Word32)-(TT_Int32)i2 ) hi += 1L << 16; + i1 += i2; + } + + i2 = i1 >> 16; + i1 = i1 << 16; + + /* Check carry overflow of i1 + lo */ + if ( i1 ) + { + if ( lo >= (TT_Word32)-(TT_Int32)i1 ) hi++; + lo += i1; + } + + hi += i2; + + z->lo = lo; + z->hi = hi; + + if ( s < 0 ) Neg64( z ); + } + + + LOCAL_FUNC + TT_Int32 Div64by32( TT_Int64* x, TT_Int32 y ) + { + TT_Int32 s; + TT_Word32 q, r, i, lo; + + + s = x->hi; if ( s < 0 ) Neg64( x ); + s ^= y; y = ABS( y ); + + /* Shortcut */ + if ( x->hi == 0 ) + { + q = x->lo / y; + return ( s < 0 ) ? -(TT_Int32)q : (TT_Int32)q; + } + + r = x->hi; + lo = x->lo; + + if ( r >= (TT_Word32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ) ? 0x80000001UL : 0x7FFFFFFFUL; + /* Return Max/Min Int32 if divide overflow */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (TT_Word32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + return ( s < 0 ) ? -(TT_Int32)q : (TT_Int32)q; + } + + + LOCAL_FUNC + Int Order64( TT_Int64* z ) + { + TT_Word32 i; + Int j; + + + if ( z->hi ) + { + i = z->hi; + j = 32; + } + else + { + i = z->lo; + j = 0; + } + + while ( i > 0 ) + { + i >>= 1; + j++; + } + return j-1; + } + + + LOCAL_FUNC + TT_Int32 Sqrt64( TT_Int64* l ) + { + TT_Int64 l2; + TT_Int32 r, s; + + + if ( (TT_Int32)l->hi < 0 || + (l->hi == 0 && l->lo == 0) ) return 0; + + s = Order64( l ); + if ( s == 0 ) return 1; + + r = Roots[s]; + do + { + s = r; + r = ( r + Div64by32(l,r) ) >> 1; + MulTo64( r, r, &l2 ); + Sub64 ( l, &l2, &l2 ); + } + while ( r > s || (TT_Int32)l2.hi < 0 ); + + return r; + } + +#endif /* LONG64 */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttcalc.h b/Build/source/libs/libttf/ttcalc.h new file mode 100644 index 00000000000..9b4c306b0ed --- /dev/null +++ b/Build/source/libs/libttf/ttcalc.h @@ -0,0 +1,97 @@ +/******************************************************************* + * + * ttcalc.h + * + * Arithmetic Computations (specification). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef TTCALC_H +#define TTCALC_H + +#include "ttconfig.h" +#include "freetype.h" + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef LONG64 + + typedef INT64 TT_Int64; + +#define ADD_64( x, y, z ) z = x + y +#define SUB_64( x, y, z ) z = x - y +#define MUL_64( x, y, z ) z = (TT_Int64)(x) * (y) + +#define DIV_64( x, y ) ( (x) / (y) ) + +#define SQRT_64( x ) Sqrt64( x ) +#define SQRT_32( x ) Sqrt32( x ) + + LOCAL_DEF TT_Int32 Sqrt64( TT_Int64 l ); + +#else /* LONG64 */ + + struct TT_Int64_ + { + TT_Word32 lo; + TT_Word32 hi; + }; + + typedef struct TT_Int64_ TT_Int64; + +#define ADD_64( x, y, z ) Add64( &x, &y, &z ) +#define SUB_64( x, y, z ) Sub64( &x, &y, &z ) +#define MUL_64( x, y, z ) MulTo64( x, y, &z ) + +#define DIV_64( x, y ) Div64by32( &x, y ) + +#define SQRT_64( x ) Sqrt64( &x ) +#define SQRT_32( x ) Sqrt32( x ) + + LOCAL_DEF void Add64( TT_Int64* x, TT_Int64* y, TT_Int64* z ); + LOCAL_DEF void Sub64( TT_Int64* x, TT_Int64* y, TT_Int64* z ); + + LOCAL_DEF void MulTo64( TT_Int32 x, TT_Int32 y, TT_Int64* z ); + + LOCAL_DEF TT_Int32 Div64by32( TT_Int64* x, TT_Int32 y ); + + LOCAL_DEF int Order64( TT_Int64* z ); + + LOCAL_DEF TT_Int32 Sqrt64( TT_Int64* l ); + +#endif /* LONG64 */ + + /* The two following functions are now part of the API! */ + + /* TT_Long TT_MulDiv( TT_Long a, TT_Long b, TT_Long c ); */ + /* TT_Long TT_MulFix( TT_Long a, TT_Long b ); */ + + +#define INT_TO_F26DOT6( x ) ( (Long)(x) << 6 ) +#define INT_TO_F2DOT14( x ) ( (Long)(x) << 14 ) +#define INT_TO_FIXED( x ) ( (Long)(x) << 16 ) +#define F2DOT14_TO_FIXED( x ) ( (Long)(x) << 2 ) +#define FLOAT_TO_FIXED( x ) ( (Long)(x * 65536.0) ) + +#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ((x) + 32) & -64) \ + : ( -((32 - (x)) & -64) ) ) + +#ifdef __cplusplus + } +#endif + +#endif /* TTCALC_H */ + +/* END */ diff --git a/Build/source/libs/libttf/ttcmap.c b/Build/source/libs/libttf/ttcmap.c new file mode 100644 index 00000000000..2dd58ece6d9 --- /dev/null +++ b/Build/source/libs/libttf/ttcmap.c @@ -0,0 +1,503 @@ +/******************************************************************* + * + * ttcmap.c 1.0 + * + * TrueType Character Mappings + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "ttobjs.h" +#include "ttdebug.h" +#include "ttfile.h" +#include "ttmemory.h" +#include "ttload.h" +#include "ttcmap.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_cmap + + +/******************************************************************* + * + * Function : CharMap_Load + * + * Description : Loads a given charmap into memory. + * + * Input : cmap pointer to cmap table + * + * Output : Error code. + * + * Notes : - Assumes the the stream is already used (opened). + * + * - In case of error, releases all partially allocated + * tables. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error CharMap_Load( PCMapTable cmap, + TT_Stream input ) + { + DEFINE_LOAD_LOCALS( input ); + + UShort num_SH, num_Seg, i; + + UShort u, l; + + PCMap0 cmap0; + PCMap2 cmap2; + PCMap4 cmap4; + PCMap6 cmap6; + + PCMap2SubHeader cmap2sub; + PCMap4Segment segments; + + + if ( cmap->loaded ) + return TT_Err_Ok; + + if ( FILE_Seek( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( ALLOC( cmap0->glyphIdArray, 256L ) || + FILE_Read( (void*)cmap0->glyphIdArray, 256L ) ) + goto Fail; + + break; + + case 2: + num_SH = 0; + cmap2 = &cmap->c.cmap2; + + /* allocate subheader keys */ + + if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, UShort ) || + ACCESS_Frame( 512L ) ) + goto Fail; + + for ( i = 0; i < 256; i++ ) + { + u = GET_UShort() / 8; + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FORGET_Frame(); + + /* load subheaders */ + + cmap2->numGlyphId = l = + ( ( cmap->length - 2L * (256 + 3) - num_SH * 8L ) & 0xffff) / 2; + + if ( ALLOC_ARRAY( cmap2->subHeaders, + num_SH + 1, + TCMap2SubHeader ) || + ACCESS_Frame( ( num_SH + 1 ) * 8L ) ) + goto Fail; + + cmap2sub = cmap2->subHeaders; + + for ( i = 0; i <= num_SH; i++ ) + { + cmap2sub->firstCode = GET_UShort(); + cmap2sub->entryCount = GET_UShort(); + cmap2sub->idDelta = GET_Short(); + /* we apply the location offset immediately */ + cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2; + + cmap2sub++; + } + + FORGET_Frame(); + + /* load glyph ids */ + + if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap2->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + case 4: + cmap4 = &cmap->c.cmap4; + + /* load header */ + + if ( ACCESS_Frame( 8L ) ) + goto Fail; + + cmap4->segCountX2 = GET_UShort(); + cmap4->searchRange = GET_UShort(); + cmap4->entrySelector = GET_UShort(); + cmap4->rangeShift = GET_UShort(); + + num_Seg = cmap4->segCountX2 / 2; + + FORGET_Frame(); + + /* load segments */ + + if ( ALLOC_ARRAY( cmap4->segments, + num_Seg, + TCMap4Segment ) || + ACCESS_Frame( (num_Seg * 4 + 1) * 2L ) ) + goto Fail; + + segments = cmap4->segments; + + for ( i = 0; i < num_Seg; i++ ) + segments[i].endCount = GET_UShort(); + + (void)GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].startCount = GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idDelta = GET_Short(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idRangeOffset = GET_UShort(); + + FORGET_Frame(); + + cmap4->numGlyphId = l = + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xffff ) / 2; + + /* load ids */ + + if ( ALLOC_ARRAY( cmap4->glyphIdArray, l , UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + cmap6->firstCode = GET_UShort(); + cmap6->entryCount = GET_UShort(); + + FORGET_Frame(); + + l = cmap6->entryCount; + + if ( ALLOC_ARRAY( cmap6->glyphIdArray, + cmap6->entryCount, + Short ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap6->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + break; + + default: /* corrupt character mapping table */ + return TT_Err_Invalid_CharMap_Format; + + } + return TT_Err_Ok; + + Fail: + CharMap_Free( cmap ); + return error; + } + + +/******************************************************************* + * + * Function : CharMap_Free + * + * Description : Releases a given charmap table. + * + * Input : cmap pointer to cmap table + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error CharMap_Free( PCMapTable cmap ) + { + if ( !cmap ) + return TT_Err_Ok; + + switch ( cmap->format ) + { + case 0: + FREE( cmap->c.cmap0.glyphIdArray ); + break; + + case 2: + FREE( cmap->c.cmap2.subHeaderKeys ); + FREE( cmap->c.cmap2.subHeaders ); + FREE( cmap->c.cmap2.glyphIdArray ); + break; + + case 4: + FREE( cmap->c.cmap4.segments ); + FREE( cmap->c.cmap4.glyphIdArray ); + cmap->c.cmap4.segCountX2 = 0; + break; + + case 6: + FREE( cmap->c.cmap6.glyphIdArray ); + cmap->c.cmap6.entryCount = 0; + break; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : CharMap_Index + * + * Description : Performs charcode->glyph index translation. + * + * Input : cmap pointer to cmap table + * + * Output : Glyph index, 0 in case of failure. + * + ******************************************************************/ + + static UShort code_to_index0( ULong charCode, PCMap0 cmap0 ); + static UShort code_to_index2( ULong charCode, PCMap2 cmap2 ); + static UShort code_to_index4( ULong charCode, PCMap4 cmap4 ); + static UShort code_to_index6( ULong charCode, PCMap6 cmap6 ); + + + LOCAL_FUNC + UShort CharMap_Index( PCMapTable cmap, + ULong charcode ) + { + switch ( cmap->format ) + { + case 0: + return code_to_index0( charcode, &cmap->c.cmap0 ); + case 2: + return code_to_index2( charcode, &cmap->c.cmap2 ); + case 4: + return code_to_index4( charcode, &cmap->c.cmap4 ); + case 6: + return code_to_index6( charcode, &cmap->c.cmap6 ); + default: + return 0; + } + } + + +/******************************************************************* + * + * Function : code_to_index0 + * + * Description : Converts the character code into a glyph index. + * Uses format 0. + * charCode will be masked to get a value in the range + * 0x00-0xFF. + * + * Input : charCode the wanted character code + * cmap0 a pointer to a cmap table in format 0 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index0( ULong charCode, + PCMap0 cmap0 ) + { + if ( charCode <= 0xFF ) + return cmap0->glyphIdArray[charCode]; + else + return 0; + } + + +/******************************************************************* + * + * Function : code_to_index2 + * + * Description : Converts the character code into a glyph index. + * Uses format 2. + * + * Input : charCode the wanted character code + * cmap2 a pointer to a cmap table in format 2 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index2( ULong charCode, + PCMap2 cmap2 ) + { + UShort index1, idx, offset; + TCMap2SubHeader sh2; + + + index1 = cmap2->subHeaderKeys[charCode <= 0xFF ? + charCode : (charCode >> 8)]; + + if ( index1 == 0 ) + { + if ( charCode <= 0xFF ) + return cmap2->glyphIdArray[charCode]; /* 8bit character code */ + else + return 0; + } + else /* 16bit character code */ + { + if ( charCode <= 0xFF ) + return 0; + + sh2 = cmap2->subHeaders[index1]; + + if ( (charCode & 0xFF) < sh2.firstCode ) + return 0; + + if ( (charCode & 0xFF) >= (sh2.firstCode + sh2.entryCount) ) + return 0; + + offset = sh2.idRangeOffset / 2 + (charCode & 0xFF) - sh2.firstCode; + if ( offset < cmap2->numGlyphId ) + idx = cmap2->glyphIdArray[offset]; + else + return 0; + + if ( idx ) + return (idx + sh2.idDelta) & 0xFFFF; + else + return 0; + } + } + + +/******************************************************************* + * + * Function : code_to_index4 + * + * Description : Converts the character code into a glyph index. + * Uses format 4. + * + * Input : charCode the wanted character code + * cmap4 a pointer to a cmap table in format 4 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist. + * + ******************************************************************/ + + static UShort code_to_index4( ULong charCode, + PCMap4 cmap4 ) + { + UShort index1, segCount; + UShort i; + TCMap4Segment seg4; + + + segCount = cmap4->segCountX2 / 2; + + for ( i = 0; i < segCount; i++ ) + if ( charCode <= cmap4->segments[i].endCount ) + break; + + /* Safety check - even though the last endCount should be 0xFFFF */ + if ( i >= segCount ) + return 0; + + seg4 = cmap4->segments[i]; + + if ( charCode < seg4.startCount ) + return 0; + + if ( seg4.idRangeOffset == 0 ) + return ( charCode + seg4.idDelta ) & 0xFFFF; + else + { + index1 = seg4.idRangeOffset / 2 + (charCode - seg4.startCount) - + (segCount - i); + + if ( index1 < cmap4->numGlyphId ) + { + if ( cmap4->glyphIdArray[index1] == 0 ) + return 0; + else + return ( cmap4->glyphIdArray[index1] + seg4.idDelta ) & 0xFFFF; + } + else + return 0; + } + } + + +/******************************************************************* + * + * Function : code_to_index6 + * + * Description : Converts the character code into a glyph index. + * Uses format 6. + * + * Input : charCode the wanted character code + * cmap6 a pointer to a cmap table in format 6 + * + * Output : Glyph index into the glyphs array. + * 0 if the glyph does not exist (`missing character glyph'). + * + ******************************************************************/ + + static UShort code_to_index6( ULong charCode, + PCMap6 cmap6 ) + { + UShort firstCode; + + + firstCode = cmap6->firstCode; + + if ( charCode < firstCode ) + return 0; + + if ( charCode >= (firstCode + cmap6->entryCount) ) + return 0; + + return cmap6->glyphIdArray[charCode - firstCode]; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttcmap.h b/Build/source/libs/libttf/ttcmap.h new file mode 100644 index 00000000000..f6be5f108e4 --- /dev/null +++ b/Build/source/libs/libttf/ttcmap.h @@ -0,0 +1,169 @@ +/******************************************************************* + * + * ttcmap.h 1.0 + * + * TrueType Character Mappings + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + ******************************************************************/ + +#ifndef TTCMAP_H +#define TTCMAP_H + +#include "ttconfig.h" +#include "tttypes.h" + + +#ifdef __cplusplus + extern "C" { +#endif + + /* format 0 */ + + struct TCMap0_ + { + PByte glyphIdArray; + }; + + typedef struct TCMap0_ TCMap0; + typedef TCMap0* PCMap0; + + + /* format 2 */ + + struct TCMap2SubHeader_ + { + UShort firstCode; /* first valid low byte */ + UShort entryCount; /* number of valid low bytes */ + Short idDelta; /* delta value to glyphIndex */ + UShort idRangeOffset; /* offset from here to 1st code */ + }; + + typedef struct TCMap2SubHeader_ TCMap2SubHeader; + typedef TCMap2SubHeader* PCMap2SubHeader; + + struct TCMap2_ + { + PUShort subHeaderKeys; + /* high byte mapping table */ + /* value = subHeader index * 8 */ + + PCMap2SubHeader subHeaders; + PUShort glyphIdArray; + UShort numGlyphId; /* control value */ + }; + + typedef struct TCMap2_ TCMap2; + typedef TCMap2* PCMap2; + + + /* format 4 */ + + struct TCMap4Segment_ + { + UShort endCount; + UShort startCount; + Short idDelta; /* in the specs defined as UShort but the + example there gives negative values... */ + UShort idRangeOffset; + }; + + typedef struct TCMap4Segment_ TCMap4Segment; + typedef TCMap4Segment* PCMap4Segment; + + struct TCMap4_ + { + UShort segCountX2; /* number of segments * 2 */ + UShort searchRange; /* these parameters can be used */ + UShort entrySelector; /* for a binary search */ + UShort rangeShift; + + PCMap4Segment segments; + PUShort glyphIdArray; + UShort numGlyphId; /* control value */ + }; + + typedef struct TCMap4_ TCMap4; + typedef TCMap4* PCMap4; + + + /* format 6 */ + + struct TCMap6_ + { + UShort firstCode; /* first character code of subrange */ + UShort entryCount; /* number of character codes in subrange */ + + PUShort glyphIdArray; + }; + + typedef struct TCMap6_ TCMap6; + typedef TCMap6* PCMap6; + + + /* charmap table */ + + struct TCMapTable_ + { + UShort platformID; + UShort platformEncodingID; + UShort format; + UShort length; + UShort version; + + Bool loaded; + ULong offset; + + union + { + TCMap0 cmap0; + TCMap2 cmap2; + TCMap4 cmap4; + TCMap6 cmap6; + } c; + }; + + typedef struct TCMapTable_ TCMapTable; + typedef TCMapTable* PCMapTable; + + + + /* Load character mappings directory when face is loaded. */ + /* The mappings themselves are only loaded on demand. */ + + LOCAL_DEF + TT_Error CharMap_Load( PCMapTable table, + TT_Stream input ); + + + /* Destroy one character mapping table */ + + LOCAL_DEF + TT_Error CharMap_Free( PCMapTable table ); + + + /* Use character mapping table to perform mapping */ + + LOCAL_DEF + UShort CharMap_Index( PCMapTable cmap, + ULong charCode ); + + /* NOTE: The PFace type isn't defined at this point */ + +#ifdef __cplusplus + } +#endif + +#endif /* TTCMAP_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttconfig.h b/Build/source/libs/libttf/ttconfig.h new file mode 100644 index 00000000000..258b957e51c --- /dev/null +++ b/Build/source/libs/libttf/ttconfig.h @@ -0,0 +1,298 @@ +/******************************************************************* + * + * ttconfig.h 1.0 + * + * Configuration settings header file (spec only). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Notes: + * + * All the configuration #define statements have been gathered in + * this file to allow easy check and modification. + * + ******************************************************************/ + +#ifndef TTCONFIG_H +#define TTCONFIG_H + + + +/* ------------ auto configuration ------------------------------------- */ + + +/*************************************************************************/ +/* Here we include the file ft_conf.h for system dependent stuff. */ +/* The specific makefile is responsible for providing the right path to */ +/* this file. */ + +#include "ft_conf.h" + + +/**************************************************************************/ +/* Define TT_CONFIG_THREAD_SAFE if you want to build a thread-safe */ +/* version of the library. */ + +/* #define TT_CONFIG_OPTION_THREAD_SAFE */ + + + +/* ------------ general debugging -------------------------------------- */ + + +/************************************************************************* + * + * There are now three debugging modes: + * + * - trace mode: + * + * Error and trace messages are sent to the log file + * (which can be the standard error output). Define + * DEBUG_LEVEL_TRACE to enable this mode. + * + * - error mode: + * + * Only error messages are generated. Define + * DEBUG_LEVEL_ERROR to enable this mode. + * + * - release mode: + * + * Error messages are neither sent nor generated. The code is + * free from any debugging parts. + * + * + * Note that you should link the engine with the 'ttdebug' component. + * in case either DEBUG_LEVEL_TRACE or DEBUG_LEVEL_ERROR is defined. + * + * Please consult ttdebug.h for more details. */ + +/* #define DEBUG_LEVEL_TRACE */ +/* #define DEBUG_LEVEL_ERROR */ + + + +/* ------------ special debugging -------------------------------------- */ + + +/*************************************************************************/ +/* Define this if you want to generate a special debug version of the */ +/* rasterizer. This will progressively draw the glyphs while the */ +/* computations are done directly on the graphics screen... (with */ +/* inverted glyphs). */ +/* */ +/* Use it at your own risk! It is not maintained currently. */ +/* */ +/* IMPORTANT: This is reserved to developers willing to debug the */ +/* rasterizer, which seems working very well in its */ +/* current state... */ + +/* #define DEBUG_RASTER */ + + +/*************************************************************************/ +/* Define this to have a simple debugger version of RunIns(). */ +/* */ +/* Use it at your own risk! It is not maintained currently. */ + +/* #define DEBUG_INTERPRETER */ + + +/*************************************************************************/ +/* Define this to have some housekeeping of allocation and deallocation. */ +/* */ +/* Please note that probably not all OS-specific versions of ttmemory.c */ +/* provide this functionality. */ + +/* #define DEBUG_MEMORY */ + + +/*************************************************************************/ +/* Define this to have bounds checking for file buffer frames. */ +/* */ +/* Please note that probably not all OS-specific versions of ttfile.c */ +/* provide this functionality. */ + +/* #define DEBUG_FILE */ + + + +/* ------------ arithmetic and processor support ----------------------- */ + + +/*************************************************************************/ +/* Define TT_USE_LONG_LONG if you want to enable the use of the */ +/* 'long long' 64-bit type provided by gcc and other compilers. Note */ +/* that : */ +/* */ +/* 1. The type isn't ANSI, and thus will produce many warnings */ +/* during library compilation. */ +/* */ +/* 2. Though the generated object files are slightly smaller, the */ +/* resulting executables are bigger of about 4Kb! gcc must be */ +/* linking some extra code in there! */ +/* */ +/* 3. There is really no speed gain in doing so (but it may help */ +/* debug the ttcalc component). */ +/* */ +/* IMPORTANT NOTE: You don't need to define it on 64-bits machines! */ +/* */ +/* NOTE 2 : This flag used to be _GNUC_LONG64_ */ + +/* #define TT_USE_LONG_LONG */ + + +/*************************************************************************/ +/* define ALIGNMENT to your processor/environment preferred alignment */ +/* size. A value of 8 should work on all current processors, even */ +/* 64-bits ones. */ + +#define ALIGNMENT 8 + + + +/* --------------- miscellaneous ----------------------------------- */ + + +/*********************************************************************/ +/* The number of extensions available. Don't change this value */ +/* except if you add new extensions to the engine. */ + +#define TT_MAX_EXTENSIONS 8 + + + +/* --------------- automatic setup -- don't touch ------------------ */ + + +/*********************************************************************/ +/* If HAVE_TT_TEXT is defined we don't provide a default typedef for */ +/* defining TT_Text. */ + +#ifndef HAVE_TT_TEXT +#define HAVE_TT_TEXT + typedef char TT_Text; +#endif + + +/*********************************************************************/ +/* We define NULL in case it's not defined yet. The default */ +/* location is stdlib.h. */ + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + + +/*********************************************************************/ +/* Some systems can't use vfprintf for error messages on stderr; if */ +/* HAVE_PRINT_FUNCTION is defined, the Print macro must be supplied */ +/* externally (having the same parameters). */ +/* */ +/* This is only used by the "ttdebug" component, which should be */ +/* linked to the engine only in debug mode. */ + +#if defined( DEBUG_LEVEL_TRACE ) || defined( DEBUG_LEVEL_ERROR ) +#ifndef HAVE_PRINT_FUNCTION +#define Print( format, ap ) vfprintf( stderr, (format), (ap) ) +#endif +#endif + + +/********************************************************************/ +/* */ +/* I have added the ability to compile the library into a single */ +/* object file. This gets rids of all the external symbols defined */ +/* in each component interface, and de-pollutes the name-space. */ +/* */ +/* I use two macros, namely LOCAL_FUNC and LOCAL_DEF, which only */ +/* apply to functions that are internal to the engine, and */ +/* should never be seen or linked by a client application. */ +/* */ +/* LOCAL_DEF used in header (.h) files, to define a function */ +/* that will be seen by other components. This */ +/* translates to "extern" in normal mode, and to */ +/* "static" in single-object mode. */ +/* */ +/* LOCAL_FUNC used in implementation (.c) files, just before */ +/* the function body. This translates to nothing */ +/* in normal mode, and to "static" in single-object */ +/* mode. */ +/* */ +/* Getting rid of un-necessary symbols makes the "ttcommon" */ +/* renaming macros hack unnecessary. Moreover, the stripped */ +/* single object file (freetype.o) is 52 Kb, instead of the */ +/* previous 57 Kb (size of all combined .o files), and gives */ +/* a better idea of the engine's real code size. */ +/* */ +/* It is called a "MAKE_OPTION" because the macro must be */ +/* defined in the Makefile, rather than this one. It allows */ +/* any developer to quickly switch from one mode to the other */ +/* without messing with "ttconfig.h" each time. */ +/* */ +#ifndef TT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_FUNC /* void */ +#define LOCAL_DEF extern +#else +#define LOCAL_FUNC static +#define LOCAL_DEF static +#endif + + +/*************************************************************************/ +/* Define EXPORT_DEF and EXPORT_FUNC as needed to build e.g. a DLL. All */ +/* variables and functions visible from outside have these prefixes. */ + +#ifdef TTF_DLL +# ifdef MAKE_TTF_DLL +# ifndef EXPORT_DEF +# define EXPORT_DEF __declspec(dllexport) +# endif + +# ifndef EXPORT_FUNC +# define EXPORT_FUNC __declspec(dllexport) +# endif +# else /* ! MAKE_TTF_DLL */ +# ifndef EXPORT_DEF +# define EXPORT_DEF __declspec(dllimport) +# endif + +# ifndef EXPORT_FUNC +# define EXPORT_FUNC __declspec(dllimport) +# endif +# endif /* MAKE_TTF_DLL */ +#else /* ! TTF_DLL */ +# ifndef EXPORT_DEF +# define EXPORT_DEF extern +# endif + +# ifndef EXPORT_FUNC +# define EXPORT_FUNC /* void */ +# endif +#endif /* TTF_DLL */ + + +/* -------------- internal (developer) configuration toggles ------------ */ + + +#undef TT_STATIC_INTERPRETER +/* Do not undefine this configuration macro. It is now a default that */ +/* must be kept in all release builds. */ + + +#undef TT_STATIC_RASTER +/* Define this if you want to generate a static raster. This makes */ +/* a non re-entrant version of the scan-line converter, which is */ +/* about 10% faster and 50% bigger than an indirect one! */ + + +#endif /* TTCONFIG_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttdebug.c b/Build/source/libs/libttf/ttdebug.c new file mode 100644 index 00000000000..4afe2dcc5ba --- /dev/null +++ b/Build/source/libs/libttf/ttdebug.c @@ -0,0 +1,404 @@ +/* Simple debugging component. Temporary */ + +#include "ttdebug.h" +#include "tttables.h" +#include "ttobjs.h" + + +#ifdef DEBUG_LEVEL_TRACE + char tt_trace_levels[trace_max]; +#endif + +#if defined( DEBUG_LEVEL_ERROR ) || defined( DEBUG_LEVEL_TRACE ) + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + + + static String tempStr[128]; + + static const String* OpStr[256] = + { + "SVTCA y", /* Set vectors to coordinate axis y */ + "SVTCA x", /* Set vectors to coordinate axis x */ + "SPvTCA y", /* Set Proj. vec. to coord. axis y */ + "SPvTCA x", /* Set Proj. vec. to coord. axis x */ + "SFvTCA y", /* Set Free. vec. to coord. axis y */ + "SFvTCA x", /* Set Free. vec. to coord. axis x */ + "SPvTL //", /* Set Proj. vec. parallel to segment */ + "SPvTL +", /* Set Proj. vec. normal to segment */ + "SFvTL //", /* Set Free. vec. parallel to segment */ + "SFvTL +", /* Set Free. vec. normal to segment */ + "SPvFS", /* Set Proj. vec. from stack */ + "SFvFS", /* Set Free. vec. from stack */ + "GPV", /* Get projection vector */ + "GFV", /* Get freedom vector */ + "SFvTPv", /* Set free. vec. to proj. vec. */ + "ISECT", /* compute intersection */ + + "SRP0", /* Set reference point 0 */ + "SRP1", /* Set reference point 1 */ + "SRP2", /* Set reference point 2 */ + "SZP0", /* Set Zone Pointer 0 */ + "SZP1", /* Set Zone Pointer 1 */ + "SZP2", /* Set Zone Pointer 2 */ + "SZPS", /* Set all zone pointers */ + "SLOOP", /* Set loop counter */ + "RTG", /* Round to Grid */ + "RTHG", /* Round to Half-Grid */ + "SMD", /* Set Minimum Distance */ + "ELSE", /* Else */ + "JMPR", /* Jump Relative */ + "SCvTCi", /* Set CVT */ + "SSwCi", /* */ + "SSW", /* */ + + "DUP", + "POP", + "CLEAR", + "SWAP", + "DEPTH", + "CINDEX", + "MINDEX", + "AlignPTS", + "INS_$28", + "UTP", + "LOOPCALL", + "CALL", + "FDEF", + "ENDF", + "MDAP[-]", + "MDAP[r]", + + "IUP[y]", + "IUP[x]", + "SHP[0]", + "SHP[1]", + "SHC[0]", + "SHC[1]", + "SHZ[0]", + "SHZ[1]", + "SHPIX", + "IP", + "MSIRP[0]", + "MSIRP[1]", + "AlignRP", + "RTDG", + "MIAP[-]", + "MIAP[r]", + + "NPushB", + "NPushW", + "WS", + "RS", + "WCvtP", + "RCvt", + "GC[0]", + "GC[1]", + "SCFS", + "MD[0]", + "MD[1]", + "MPPEM", + "MPS", + "FlipON", + "FlipOFF", + "DEBUG", + + "LT", + "LTEQ", + "GT", + "GTEQ", + "EQ", + "NEQ", + "ODD", + "EVEN", + "IF", + "EIF", + "AND", + "OR", + "NOT", + "DeltaP1", + "SDB", + "SDS", + + "ADD", + "SUB", + "DIV", + "MUL", + "ABS", + "NEG", + "FLOOR", + "CEILING", + "ROUND[G]", + "ROUND[B]", + "ROUND[W]", + "ROUND[?]", + "NROUND[G]", + "NROUND[B]", + "NROUND[W]", + "NROUND[?]", + + "WCvtF", + "DeltaP2", + "DeltaP3", + "DeltaC1", + "DeltaC2", + "DeltaC3", + "SROUND", + "S45Round", + "JROT", + "JROF", + "ROFF", + "INS_$7B", + "RUTG", + "RDTG", + "SANGW", + "AA", + + "FlipPT", + "FlipRgON", + "FlipRgOFF", + "INS_$83", + "INS_$84", + "ScanCTRL", + "SDPVTL[0]", + "SDPVTL[1]", + "GetINFO", + "IDEF", + "ROLL", + "MAX", + "MIN", + "ScanTYPE", + "IntCTRL", + "INS_$8F", + + "INS_$90", + "INS_$91", + "INS_$92", + "INS_$93", + "INS_$94", + "INS_$95", + "INS_$96", + "INS_$97", + "INS_$98", + "INS_$99", + "INS_$9A", + "INS_$9B", + "INS_$9C", + "INS_$9D", + "INS_$9E", + "INS_$9F", + + "INS_$A0", + "INS_$A1", + "INS_$A2", + "INS_$A3", + "INS_$A4", + "INS_$A5", + "INS_$A6", + "INS_$A7", + "INS_$A8", + "INS_$A9", + "INS_$AA", + "INS_$AB", + "INS_$AC", + "INS_$AD", + "INS_$AE", + "INS_$AF", + + "PushB[0]", + "PushB[1]", + "PushB[2]", + "PushB[3]", + "PushB[4]", + "PushB[5]", + "PushB[6]", + "PushB[7]", + "PushW[0]", + "PushW[1]", + "PushW[2]", + "PushW[3]", + "PushW[4]", + "PushW[5]", + "PushW[6]", + "PushW[7]", + + "MDRP[G]", + "MDRP[B]", + "MDRP[W]", + "MDRP[?]", + "MDRP[rG]", + "MDRP[rB]", + "MDRP[rW]", + "MDRP[r?]", + "MDRP[mG]", + "MDRP[mB]", + "MDRP[mW]", + "MDRP[m?]", + "MDRP[mrG]", + "MDRP[mrB]", + "MDRP[mrW]", + "MDRP[mr?]", + "MDRP[pG]", + "MDRP[pB]", + + "MDRP[pW]", + "MDRP[p?]", + "MDRP[prG]", + "MDRP[prB]", + "MDRP[prW]", + "MDRP[pr?]", + "MDRP[pmG]", + "MDRP[pmB]", + "MDRP[pmW]", + "MDRP[pm?]", + "MDRP[pmrG]", + "MDRP[pmrB]", + "MDRP[pmrW]", + "MDRP[pmr?]", + + "MIRP[G]", + "MIRP[B]", + "MIRP[W]", + "MIRP[?]", + "MIRP[rG]", + "MIRP[rB]", + "MIRP[rW]", + "MIRP[r?]", + "MIRP[mG]", + "MIRP[mB]", + "MIRP[mW]", + "MIRP[m?]", + "MIRP[mrG]", + "MIRP[mrB]", + "MIRP[mrW]", + "MIRP[mr?]", + "MIRP[pG]", + "MIRP[pB]", + + "MIRP[pW]", + "MIRP[p?]", + "MIRP[prG]", + "MIRP[prB]", + "MIRP[prW]", + "MIRP[pr?]", + "MIRP[pmG]", + "MIRP[pmB]", + "MIRP[pmW]", + "MIRP[pm?]", + "MIRP[pmrG]", + "MIRP[pmrB]", + "MIRP[pmrW]", + "MIRP[pmr?]" + }; + + + const String* Cur_U_Line( void* _exec ) + { + String s[32]; + + Int op, i, n; + + PExecution_Context exec; + + + exec = _exec; + + op = exec->code[exec->IP]; + + sprintf( tempStr, "%s", OpStr[op] ); + + if ( op == 0x40 ) + { + n = exec->code[exec->IP + 1]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if ( n > 20 ) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx", exec->code[exec->IP + i + 2] ); + strncat( tempStr, s, 8 ); + } + } + else if ( op == 0x41 ) + { + n = exec->code[exec->IP + 1]; + sprintf( s, "(%d)", n ); + strncat( tempStr, s, 8 ); + + if ( n > 20 ) n = 20; /* limit output */ + + for ( i = 0; i < n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 2], + exec->code[exec->IP + i*2 + 3] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB0 ) + { + n = op - 0xB0; + + for ( i = 0; i <= n; i++ ) + { + sprintf( s, " $%02hx", exec->code[exec->IP + i + 1] ); + strncat( tempStr, s, 8 ); + } + } + else if ( (op & 0xF8) == 0xB8 ) + { + n = op-0xB8; + + for ( i = 0; i <= n; i++ ) + { + sprintf( s, " $%02hx%02hx", exec->code[exec->IP + i*2 + 1], + exec->code[exec->IP + i*2 + 2] ); + strncat( tempStr, s, 8 ); + } + } + + return (String*)tempStr; + } + + + /* the Print() function is defined in ttconfig.h; */ + /* it defaults to vprintf on systems which have it */ + + void TT_Message( const String* fmt, ... ) + { + va_list ap; + + va_start( ap, fmt ); + Print( fmt, ap ); + va_end( ap ); + } + + + void TT_Panic( const String* fmt, ... ) + { + va_list ap; + + va_start( ap, fmt ); + Print( fmt, ap ); + va_end( ap ); + + exit( EXIT_FAILURE ); + } + +#endif /* defined( DEBUG_LEVEL_ERROR ) || defined( DEBUG_LEVEL_TRACE ) */ + +#if defined( DEBUG_LEVEL_TRACE ) + + /* use this function to set the values of tt_trace_levels */ + + void set_tt_trace_levels( int index, char value ) + { + tt_trace_levels[index] = value; + } + +#endif + +/* END */ diff --git a/Build/source/libs/libttf/ttdebug.h b/Build/source/libs/libttf/ttdebug.h new file mode 100644 index 00000000000..8e889dcc622 --- /dev/null +++ b/Build/source/libs/libttf/ttdebug.h @@ -0,0 +1,170 @@ +/******************************************************************* + * + * ttdebug.h + * + * Debugging and Logging component (specification) + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * This component contains various macros and functions used to + * ease the debugging of the FreeType engine. Its main purpose + * is in assertion checking, tracing, and error detection. + * + * There are now three debugging modes: + * + * - trace mode: + * + * Error and trace messages are sent to the log file + * (which can be the standard error output). Define + * DEBUG_LEVEL_TRACE to enable this mode. + * + * - error mode: + * + * Only error messages are generated. Define + * DEBUG_LEVEL_ERROR to enable this mode. + * + * - release mode: + * + * Error messages are neither sent nor generated. The code is + * free from any debugging parts. + * + ******************************************************************/ + +#ifndef TTDEBUG_H +#define TTDEBUG_H + +#include "ttconfig.h" +#include "tttypes.h" + + +#ifdef __cplusplus + extern "C" { +#endif + + +#if defined( DEBUG_LEVEL_TRACE ) + + typedef enum Trace_Component_ + { + trace_any = 0, + trace_api, + trace_interp, + trace_load, + trace_gload, + trace_memory, + trace_file, + trace_mutex, + trace_cache, + trace_calc, + trace_cmap, + trace_extend, + trace_objs, + trace_raster, + + trace_bitmap, + trace_max + + } Trace_Component; + + + /* Here we define an array to hold the trace levels per component. */ + /* Since it is globally defined, all array members are set to 0. */ + /* You should set the values in this array either in your program */ + /* or with your debugger. */ + /* */ + /* Currently, up to eight levels (PTRACE0-PTRACE7, see below) are */ + /* used in some parts of the engine. */ + /* */ + /* For example, to have all tracing messages in the raster */ + /* component, say */ + /* */ + /* #define DEBUG_LEVEL_TRACE */ + /* #include "ttdebug.h" */ + /* */ + /* ... */ + /* set_tt_trace_levels( trace_raster, 7 ) */ + /* */ + /* in your code before initializing the FreeType engine. */ + /* */ + /* Maybe it is better to define DEBUG_LEVEL_TRACE in ttconfig.h... */ + + extern char tt_trace_levels[trace_max]; + + /* IMPORTANT: */ + /* */ + /* Each component must define the macro TT_COMPONENT */ + /* to a valid Trace_Component value before using any */ + /* PTRACEx macro. */ + /* */ + +#define PTRACE( level, varformat ) \ + if ( tt_trace_levels[TT_COMPONENT] >= level ) TT_Message##varformat + +#elif defined( DEBUG_LEVEL_ERROR ) + +#define PTRACE( level, varformat ) /* nothing */ + +#else /* RELEASE MODE */ + +#define TT_Assert( condition, action ) /* nothing */ + +#define PTRACE( level, varformat ) /* nothing */ +#define PERROR( varformat ) /* nothing */ +#define PANIC( varformat ) /* nothing */ + +#endif + + +/************************************************************************/ +/* */ +/* Define macros and fuctions that are common to the debug and trace */ +/* modes. */ +/* */ + +#if defined( DEBUG_LEVEL_TRACE ) || defined( DEBUG_LEVEL_ERROR ) + + +#define TT_Assert( condition, action ) if ( !(condition) ) ( action ) + + void TT_Message( const String* fmt, ... ); + void TT_Panic ( const String* fmt, ... ); + /* print a message and exit */ + + const String* Cur_U_Line( void* exec ); + +#define PERROR( varformat ) TT_Message##varformat +#define PANIC( varformat ) TT_Panic##varformat + +#endif + +#if defined( DEBUG_LEVEL_TRACE ) + + void set_tt_trace_levels( int index, char value ); + +#endif + + +#define PTRACE0( varformat ) PTRACE( 0, varformat ) +#define PTRACE1( varformat ) PTRACE( 1, varformat ) +#define PTRACE2( varformat ) PTRACE( 2, varformat ) +#define PTRACE3( varformat ) PTRACE( 3, varformat ) +#define PTRACE4( varformat ) PTRACE( 4, varformat ) +#define PTRACE5( varformat ) PTRACE( 5, varformat ) +#define PTRACE6( varformat ) PTRACE( 6, varformat ) +#define PTRACE7( varformat ) PTRACE( 7, varformat ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTDEBUG_H */ diff --git a/Build/source/libs/libttf/ttengine.h b/Build/source/libs/libttf/ttengine.h new file mode 100644 index 00000000000..e946d06ce2b --- /dev/null +++ b/Build/source/libs/libttf/ttengine.h @@ -0,0 +1,115 @@ +/******************************************************************* + * + * ttengine.h 1.1 + * + * Engine instance structure definition. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * New in 1.1 : + * + * - added the 'raster_lock' mutex field to synchronize + * scan-line conversion in thread-safe and re-entrant builds. + * + ******************************************************************/ + +#ifndef TTENGINE_H +#define TTENGINE_H + +#include "tttypes.h" +#include "ttconfig.h" +#include "freetype.h" +#include "ttmutex.h" + +#ifdef __cplusplus + extern "C" { +#endif + + /********************************************************************/ + /* */ + /* The freetype engine instance structure. */ + /* */ + /* This structure holds all the data that is necessary to run */ + /* one instance of the freetype engine. It is needed to get a */ + /* completely re-entrant version of the library. */ + /* */ + /* The goal is to move _all_ component-specific variables, either */ + /* static or global in the structure; the component initializers */ + /* and finalizers will all be called with the address of a valid */ + /* TEngine_Instance. */ + /* */ + /********************************************************************/ + + struct TEngine_Instance_ + { + TMutex lock; /* engine lock */ + + void* list_free_elements; + + void* objs_face_class; /* the face cache class */ + void* objs_instance_class; /* the instance cache class */ + void* objs_execution_class; /* the context cache class */ + void* objs_glyph_class; /* the glyph cache class */ + + void* objs_face_cache; /* these caches are used to track */ + void* objs_exec_cache; /* the current face and execution */ + /* context objects */ + + void* file_component; /* ttfile implementation dependent */ + + TMutex raster_lock; /* mutex for this engine's render pool */ + void* raster_component; /* ttraster implementation depedent */ + Byte raster_palette[5]; /* gray-levels palette for anti-aliasing */ + + void* extension_component; /* extensions dependent */ + +#if 0 + TT_Glyph_Loader_Callback glCallback; /* glyph loader callback, if any */ +#endif + }; + + /* NOTE : The raster's lock is only acquired by the Render_Glyph and */ + /* Render_Gray_Glyph functions, which always release it on exit */ + /* They do not lock the engine mutex. This means you shouldn't */ + /* be concerned about deadlocks between the two mutexes, as these */ + /* should never appear.. */ + + typedef struct TEngine_Instance_ TEngine_Instance; + typedef TEngine_Instance* PEngine_Instance; + + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE /* for re-entrant builds */ + +#define ENGINE_ARG TEngine_Instance* _engine +#define ENGINE_ARGS TEngine_Instance* _engine, + +#define ENGINE_VAR _engine +#define ENGINE_VARS _engine, + +#define ENGINE _engine + +#else /* for thread-safe builds */ + +#define ENGINE_ARG /* void */ +#define ENGINE_ARGS + +#define ENGINE_VAR +#define ENGINE_VARS + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + +#ifdef __cplusplus + } +#endif + +#endif /* TTENGINE_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttextend.c b/Build/source/libs/libttf/ttextend.c new file mode 100644 index 00000000000..cb77e7ff885 --- /dev/null +++ b/Build/source/libs/libttf/ttextend.c @@ -0,0 +1,212 @@ +/******************************************************************* + * + * ttextend.h 2.0 + * + * Extensions Interface + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * This is an updated version of the extension component, now + * located in the main library's source directory. It allows + * the dynamic registration/use of various face object extensions + * through a simple API. + * + ******************************************************************/ + +#include "ttextend.h" +#include "ttengine.h" +#include "ttmemory.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_extend + + + struct TExtension_Registry_ + { + Int num_extensions; + Long cur_offset; + TExtension_Class classes[TT_MAX_EXTENSIONS]; + }; + + typedef struct TExtension_Registry_ TExtension_Registry; + typedef TExtension_Registry* PExtension_Registry; + + + + /* Initialize the extension component */ + + LOCAL_FUNC + TT_Error TTExtend_Init( PEngine_Instance engine ) + { + TT_Error error; + PExtension_Registry exts; + + + if ( ALLOC( exts, sizeof ( TExtension_Registry ) ) ) + return error; + + exts->num_extensions = 0; + exts->cur_offset = 0; + engine->extension_component = (void*)exts; + + return TT_Err_Ok; + } + + + /* Finalize the extension component */ + + LOCAL_FUNC + TT_Error TTExtend_Done( PEngine_Instance engine ) + { + FREE( engine->extension_component ); + return TT_Err_Ok; + } + + + /* Register a new extension */ + + EXPORT_FUNC + TT_Error TT_Register_Extension( PEngine_Instance engine, + Long id, + Long size, + PExt_Constructor create, + PExt_Destructor destroy ) + { + PExtension_Registry exts; + PExtension_Class clazz; + Int p; + + + exts = (PExtension_Registry)engine->extension_component; + if ( !exts ) + return TT_Err_Ok; + + p = exts->num_extensions; + + if ( p >= TT_MAX_EXTENSIONS ) + return TT_Err_Too_Many_Extensions; + + clazz = exts->classes + p; + clazz->id = id; + clazz->size = size; + clazz->build = create; + clazz->destroy = destroy; + + clazz->offset = exts->cur_offset; + + exts->num_extensions++; + exts->cur_offset += ( size + ALIGNMENT-1 ) & -ALIGNMENT; + + return TT_Err_Ok; + } + + + /* Query an extension block by extension_ID */ + + EXPORT_FUNC + TT_Error TT_Extension_Get( PFace face, + Long extension_id, + void** extension_block ) + { + PExtension_Registry registry; + PExtension_Class clazz; + Int n; + + + if ( !face->extension ) + return TT_Err_Extensions_Unsupported; + + registry = (PExtension_Registry)face->engine->extension_component; + + for ( n = 0; n < face->n_extensions; n++ ) + { + clazz = registry->classes + n; + if ( clazz->id == extension_id ) + { + *extension_block = (PByte)face->extension + clazz->offset; + return TT_Err_Ok; + } + } + + return TT_Err_Invalid_Extension_Id; + } + + + /* Destroy all extensions within a face object. Called by the */ + /* face object destructor. */ + + LOCAL_FUNC + TT_Error Extension_Destroy( PFace face ) + { + PEngine_Instance engine = face->engine; + PExtension_Registry registry; + PExtension_Class clazz; + Int n; + PByte ext; + + + registry = (PExtension_Registry)engine->extension_component; + + for ( n = 0; n < face->n_extensions; n++ ) + { + clazz = registry->classes + n; + ext = (PByte)face->extension + clazz->offset; + + /* the destructor is optional */ + if ( clazz->destroy ) + clazz->destroy( (void*)ext, face ); + } + + /* destroy the face's extension block too */ + FREE( face->extension ); + face->n_extensions = 0; + + return TT_Err_Ok; + } + + + /* Create an extension within a face object. Called by the */ + /* face object constructor. */ + + LOCAL_FUNC + TT_Error Extension_Create( PFace face ) + { + PEngine_Instance engine = face->engine; + PExtension_Registry registry; + PExtension_Class clazz; + TT_Error error; + Int n; + PByte ext; + + + registry = (PExtension_Registry)engine->extension_component; + + face->n_extensions = registry->num_extensions; + if ( ALLOC( face->extension, registry->cur_offset ) ) + return error; + + for ( n = 0; n < face->n_extensions; n++ ) + { + clazz = registry->classes + n; + ext = (PByte)face->extension + clazz->offset; + error = clazz->build( (void*)ext, face ); + if ( error ) + goto Fail; + } + return TT_Err_Ok; + + Fail: + Extension_Destroy( face ); + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttextend.h b/Build/source/libs/libttf/ttextend.h new file mode 100644 index 00000000000..d5d862282c1 --- /dev/null +++ b/Build/source/libs/libttf/ttextend.h @@ -0,0 +1,168 @@ +/******************************************************************* + * + * ttextend.h 2.0 + * + * Extensions Interface. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * This is an updated version of the extension component, now + * located in the main library's source directory. It allows + * the dynamic registration/use of various face object extensions + * through a simple API. + * + ******************************************************************/ + +#ifndef TTEXTEND_H +#define TTEXTEND_H + +#include "ttconfig.h" +#include "tttypes.h" +#include "ttobjs.h" + + +#ifdef __cplusplus + extern "C" { +#endif + + /* The extensions don't need to be integrated at compile time into */ + /* the engine, only at link time. */ + + + /* When a new face object is created, the face constructor calls */ + /* the extension constructor with the following arguments: */ + /* */ + /* ext : typeless pointer to the face's extension block. */ + /* Its size is the one given at registration time */ + /* in the extension class's 'size' field. */ + /* */ + /* face : the parent face object. Note that the extension */ + /* constructor is called when the face object is */ + /* built. */ + + typedef TT_Error TExt_Constructor( void* ext, PFace face ); + + + /* When a face object is destroyed, the face destructor calls */ + /* the extension destructor with the following arguments. */ + /* */ + /* ext : typeless pointer to the face's extension block. */ + /* Its size is the one given at registration time */ + /* in the extension class's 'size' field. */ + /* */ + /* face : the parent face object. Note that the extension */ + /* destructor is called before the actual face object */ + /* is destroyed. */ + + typedef TT_Error TExt_Destructor ( void* ext, PFace face ); + + typedef TExt_Constructor* PExt_Constructor; + typedef TExt_Destructor* PExt_Destructor; + + + struct TExtension_Class_ + { + Long id; /* extension id */ + Long size; /* size in bytes of extension record */ + PExt_Constructor build; /* the extension's class constructor */ + PExt_Destructor destroy; /* the extension's class destructor */ + + Long offset; /* offset of ext. record in face obj */ + /* (set by the engine) */ + }; + + typedef struct TExtension_Class_ TExtension_Class; + typedef TExtension_Class* PExtension_Class; + + +#define Build_Extension_ID( a, b, c, d ) \ + ( ((ULong)(a) << 24) | \ + ((ULong)(b) << 16) | \ + ((ULong)(c) << 8 ) | \ + (ULong)(d) ) + + /* A note regarding extensions and the single-object compilation */ + /* mode : */ + /* */ + /* When the engine is compiled as a single object file, extensions */ + /* must remain linkable *after* compile time. In order to do this, */ + /* we need to export the functions that an extension may need. */ + /* Fortunately, we can limit ourselves to : */ + /* */ + /* o TT_Register_Extension (previously called Extension_Register) */ + /* which is to be called by each extension on within */ + /* it TT_Init_XXXX_Extension initializer. */ + /* */ + /* o File and frame access functions. Fortunately, these already */ + /* have their names prefixed by "TT_", so no change was needed */ + /* except replacing the LOCAL_DEF keyword with EXPORT_DEF */ + /* */ + /* o Memory access functions, i.e. TT_Alloc and TT_Free. Again, */ + /* the change is minimal */ + /* */ + /* o the table-lookup function : TT_LookUp_Table, formerly known */ + /* as Load_TrueType_Table in ttload.c. */ + /* */ + /* */ + /* Other than that, an extension should be able to #include all */ + /* relevant header files to get access to internal types, but */ + /* should not call engine internal functions.. */ + /* */ + /* If there is a need for a specific internal function call, let */ + /* me known to see if we need to export it by default.. */ + /* - DavidT */ + /* */ + + /* Register a new extension. Called by extension */ + /* service initializers. */ + EXPORT_DEF + TT_Error TT_Register_Extension( PEngine_Instance engine, + Long id, + Long size, + PExt_Constructor create, + PExt_Destructor destroy ); + + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + /* Initialize the extension component */ + LOCAL_DEF + TT_Error TTExtend_Init( PEngine_Instance engine ); + + /* Finalize the extension component */ + LOCAL_DEF + TT_Error TTExtend_Done( PEngine_Instance engine ); + + /* Create an extension within a face object. Called by the */ + /* face object constructor. */ + LOCAL_DEF + TT_Error Extension_Create( PFace face ); + + /* Destroy all extensions within a face object. Called by the */ + /* face object destructor. */ + LOCAL_DEF + TT_Error Extension_Destroy( PFace face ); +#endif + + /* Query an extension block by extension_ID. Called by extension */ + /* service routines. */ + EXPORT_DEF + TT_Error TT_Extension_Get( PFace face, + Long extension_id, + void** extension_block ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTEXTEND_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttfile.c b/Build/source/libs/libttf/ttfile.c new file mode 100644 index 00000000000..07d9698819e --- /dev/null +++ b/Build/source/libs/libttf/ttfile.c @@ -0,0 +1,1175 @@ +/******************************************************************* + * + * ttfile.c (extended version) 2.1 + * + * File I/O Component (body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTES: + * + * This implementation relies on the ANSI libc. You may wish to + * modify it to get rid of libc and go straight to the your + * platform's stream routines. + * + * The same source code can be used for thread-safe and re-entrant + * builds of the library. + * + * Changes between 2.0 and 2.1 : + * + * - it is now possible to close a stream's file handle explicitely + * through the new API "TT_Flush_Stream". This will simply close + * a stream's file handle (useful to save system resources when + * dealing with lots of opened fonts). Of course, the function + * "TT_Use_Stream" will automatically re-open a stream's handle if + * necessary. + * + * - added "TT_Stream_Size" to replace "TT_File_Size" which wasn't + * used anyway. This one returns the size of any stream, even + * flushed one (when the previous TT_File_Size could only return + * the size of the current working stream). This is used by the + * new "Load_TrueType_Any" function in the tables loader. + * + ******************************************************************/ + +#include "ttconfig.h" + +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "freetype.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttengine.h" +#include "ttmutex.h" +#include "ttmemory.h" +#include "ttfile.h" /* our prototypes */ + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_file + + +/* For now, we don't define additional error messages in the core library */ +/* to report open-on demand errors. Define these error as standard ones */ + +#define TT_Err_Could_Not_ReOpen_File TT_Err_Could_Not_Open_File +#define TT_Err_Could_Not_ReSeek_File TT_Err_Could_Not_Open_File + + /* This definition is mandatory for each file component! */ + EXPORT_FUNC + const TFileFrame TT_Null_FileFrame = { NULL, 0, 0 }; + +/* It has proven useful to do some bounds checks during development phase. */ +/* They should probably be undefined for speed reasons in a later release. */ + +#if DEBUG_FILE +#define CHECK_FRAME( frame, n ) \ + do { \ + if ( frame.cursor + n > frame.address + frame.size ) \ + Panic( "Frame boundary error!\n" ); \ + } while ( 0 ) +#else +#define CHECK_FRAME( frame, n ) /* nothing */ +#endif + + /* Because a stream can be flushed, i.e. its file handle can be */ + /* closed to save system resources, we must keep the stream's file */ + /* pathname to be able to re-open it on demand when it is flushed */ + + struct TStream_Rec_; + typedef struct TStream_Rec_ TStream_Rec; + typedef TStream_Rec* PStream_Rec; + + struct TStream_Rec_ + { + Bool opened; /* is the stream handle opened ? */ + TT_Text* name; /* the file's pathname */ + Long position; /* current position within the file */ + + FILE* file; /* file handle */ + Long base; /* stream base in file */ + Long size; /* stream size in file */ + }; + + /* We support embedded TrueType files by allowing them to be */ + /* inside any file, at any location, hence the 'base' argument. */ + /* Note however that the current implementation does not allow you */ + /* to specify a 'base' index when opening a file. */ + /* (will come later) */ + /* I still don't know if this will turn out useful ?? - DavidT */ + +#define STREAM2REC( x ) ( (TStream_Rec*)HANDLE_Val( x ) ) + + static TT_Error Stream_Activate ( PStream_Rec stream ); + static TT_Error Stream_Deactivate( PStream_Rec stream ); + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /**** ****/ + /**** N O N R E E N T R A N T I M P L E M E N T A T I O N ****/ + /**** ****/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* in non-rentrant builds, we allocate a single block where we'll */ + /* place all the frames smaller than FRAME_CACHE_SIZE, rather than */ + /* allocating a new block on each access. Bigger frames will be */ + /* malloced normally in the heap. */ + /* */ + /* See TT_Access_Frame() and TT_Forget_Frame() for details. */ + +#define FRAME_CACHE_SIZE 2048 + + /* The TFile_Component structure holds all the data that was */ + /* previously declared static or global in this component. */ + /* */ + /* It is accessible through the 'engine.file_component' */ + /* variable in re-entrant builds, or directly through the */ + /* static 'files' variable in other builds. */ + + struct TFile_Component_ + { + TMutex lock; /* used by the thread-safe build only */ + Byte* frame_cache; /* frame cache */ + PStream_Rec stream; /* current stream */ + TFileFrame frame; /* current frame */ + }; + + typedef struct TFile_Component_ TFile_Component; + + static TFile_Component files; + +#define CUR_Stream files.stream +#define CUR_Frame files.frame + +#define STREAM_VARS /* void */ +#define STREAM_VAR /* void */ + +/* The macro CUR_Stream denotes the current input stream. */ +/* Note that for the re-entrant version, the 'stream' name has been */ +/* chosen according to the macro STREAM_ARGS. */ + +/* The macro CUR_Frame denotes the current file frame. */ +/* Note that for the re-entrant version, the 'frame' name has been */ +/* chosen according to the macro FRAME_ARGS. */ + +/* The macro STREAM_VAR is used when calling public functions */ +/* that need an 'optional' stream argument. */ + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + TT_Error error; + + + MUTEX_Create( files.lock ); + files.stream = NULL; + ZERO_Frame( files.frame ); + + if ( ALLOC( files.frame_cache, FRAME_CACHE_SIZE ) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + FREE( files.frame_cache ); + MUTEX_Destroy( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Copies or duplicates a given stream. + * + * Input : org_stream original stream + * stream target stream (copy or duplicate) + * + * Output : Error code. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream org_stream, + TT_Stream* stream ) + { + MUTEX_Lock( files.lock ); /* lock file mutex */ + + *stream = org_stream; /* copy the stream */ + files.stream = STREAM2REC(org_stream); /* set current stream */ + + Stream_Activate( files.stream ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream target stream + * + * Output : Error code. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + HANDLE_Set( *stream, NULL ); + MUTEX_Release( files.lock ); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( size <= FRAME_CACHE_SIZE ) + { + /* use the cache */ + CUR_Frame.address = files.frame_cache; + CUR_Frame.size = FRAME_CACHE_SIZE; + } + else + { + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + } + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if (error) + { + if ( size > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + CUR_Frame.address = NULL; + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * `size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function truncates `size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + Long readBytes, requested; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( size <= FRAME_CACHE_SIZE ) + { + /* use the cache */ + CUR_Frame.address = files.frame_cache; + CUR_Frame.size = FRAME_CACHE_SIZE; + } + else + { + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + } + + requested = size; + readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR ); + if ( size > readBytes ) + size = readBytes; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if (error) + { + if ( requested > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + CUR_Frame.address = NULL; + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + if ( CUR_Frame.size > FRAME_CACHE_SIZE ) + FREE( CUR_Frame.address ); + + ZERO_Frame( CUR_Frame ); + + return TT_Err_Ok; + } + + +#else /* TT_CONFIG_OPTION_THREAD_SAFE */ + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /******** ********/ + /******** R E E N T R A N T I M P L E M E N T A T I O N ********/ + /******** ********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/* a simple macro to access the file component's data */ +#define files ( *((TFile_Component*)engine.file_component) ) + +#define CUR_Stream STREAM2REC( stream ) /* re-entrant macros */ +#define CUR_Frame (*frame) + +#define STREAM_VARS stream, +#define STREAM_VAR stream + + +/******************************************************************* + * + * Function : TTFile_Init + * + * Description : Initializes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Init( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTFile_Done + * + * Description : Finalizes the File component. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTFile_Done( PEngine_Instance engine ) + { + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Use_Stream + * + * Description : Duplicates a stream for a new usage. + * + * Input : input_stream source stream to duplicate + * copy address of target duplicate stream + * + * Output : error code. + * The target stream is set to NULL in case of failure. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Use_Stream( TT_Stream input_stream, + TT_Stream* copy ) + { + PStream_Rec rec = STREAM2REC( input_stream ); + + return TT_Open_Stream( rec->name, copy ); + } + + +/******************************************************************* + * + * Function : TT_Done_Stream + * + * Description : Releases a given stream. + * + * Input : stream target stream + * + * Output : + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Done_Stream( TT_Stream* stream ) + { + return TT_Close_Stream( stream ); + } + + +/******************************************************************* + * + * Function : TT_Access_Frame + * + * Description : Notifies the component that we're going to read + * 'size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function fails if the byte range is not within the + * the file, or if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big in both cases). + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + FREE( CUR_Frame.address ); + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Check_And_Access_Frame + * + * Description : Notifies the component that we're going to read + * `size' bytes from the current file position. + * This function should load/cache/map these bytes + * so that they will be addressed by the GET_xxx + * functions easily. + * + * Input : size number of bytes to access. + * + * Output : SUCCESS on success. FAILURE on error. + * + * Notes: The function truncates `size' if the byte range is not + * within the file. + * + * It will fail if there is not enough memory to cache + * the bytes properly (which usually means that `size' is + * too big). + * + * It will fail if you make two consecutive calls + * to TT_Access_Frame(), without a TT_Forget_Frame() between + * them. + * + * The only difference with TT_Access_Frame() is that we + * check that the frame is within the current file. We + * otherwise truncate it. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ) + { + TT_Error error; + Long readBytes; + + + if ( CUR_Frame.address != NULL ) + return TT_Err_Nested_Frame_Access; + + if ( ALLOC( CUR_Frame.address, size ) ) + return error; + CUR_Frame.size = size; + + readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR ); + if ( size > readBytes ) + size = readBytes; + + error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size ); + if ( error ) + { + FREE( CUR_Frame.address ); + CUR_Frame.size = 0; + } + + CUR_Frame.cursor = CUR_Frame.address; + return error; + } + + +/******************************************************************* + * + * Function : TT_Forget_Frame + * + * Description : Releases a cached frame after reading. + * + * Input : None + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Forget_Frame( FRAME_ARG ) + { + if ( CUR_Frame.address == NULL ) + return TT_Err_Nested_Frame_Access; + + FREE( CUR_Frame.address ); + ZERO_Frame( CUR_Frame ); + + return TT_Err_Ok; + } + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + /*********** ***********/ + /*********** C O M M O N I M P L E M E N T A T I O N ***********/ + /*********** ***********/ + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + +/******************************************************************* + * + * Function : Stream_Activate + * + * Description : activates a stream, this will either: + * - open a new file handle if the stream is closed + * - move the stream to the head of the linked list + * + * Input : stream the stream to activate + * + * Output : error condition. + * + * Note : This function is also called with fresh new streams + * created by TT_Open_Stream(). They have their 'size' + * field set to -1. + * + ******************************************************************/ + + static TT_Error Stream_Activate( PStream_Rec stream ) + { + if ( !stream->opened ) + { + if ( (stream->file = fopen( (TT_Text*)stream->name, "rb" )) == 0 ) + return TT_Err_Could_Not_ReOpen_File; + + stream->opened = TRUE; + + /* A newly created stream has a size field of -1 */ + if ( stream->size < 0 ) + { + fseek( stream->file, 0, SEEK_END ); + stream->size = ftell( stream->file ); + fseek( stream->file, 0, SEEK_SET ); + } + + /* Reset cursor in file */ + if ( stream->position ) + { + if ( fseek( stream->file, stream->position, SEEK_SET ) != 0 ) + { + /* error during seek */ + fclose( stream->file ); + stream->opened = FALSE; + return TT_Err_Could_Not_ReSeek_File; + } + } + } + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Stream_DeActivate + * + * Description : deactivates a stream, this will : + * - close its file handle if it was opened + * - remove it from the opened list if necessary + * + * Input : stream the stream to deactivate + * + * Output : Error condition + * + * Note : the function is called whenever a stream is deleted + * (_not_ when a stream handle's is closed due to an + * activation). However, the stream record isn't + * destroyed by it.. + * + ******************************************************************/ + + static TT_Error Stream_Deactivate( PStream_Rec stream ) + { + if ( stream->opened ) + { + /* Save its current position within the file */ + stream->position = ftell( stream->file ); + fclose( stream->file ); + stream->file = 0; + stream->opened = FALSE; + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Stream_Size + * + * Description : Returns the length of a given stream, even if it + * is flushed. + * + * Input : stream the stream + * + * Output : Length of stream in bytes. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Stream_Size( TT_Stream stream ) + { + PStream_Rec rec = STREAM2REC( stream ); + + + if ( rec ) + return rec->size; + else + return 0; /* invalid stream - return 0 */ + } + + +/******************************************************************* + * + * Function : TT_Open_Stream + * + * Description : Opens the font file and saves the total file size. + * + * Input : error address of stream's error variable + * (re-entrant build only) + * filepathname pathname of the file to open + * stream address of target TT_Stream structure + * + * Output : SUCCESS on sucess, FAILURE on error. + * The target stream is set to -1 in case of failure. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Open_Stream( const TT_Text* filepathname, + TT_Stream* stream ) + { + Int len; + TT_Error error; + PStream_Rec stream_rec; + + if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) ) + return error; + + stream_rec = STREAM2REC( *stream ); + + stream_rec->file = NULL; + stream_rec->size = -1L; + stream_rec->base = 0; + stream_rec->opened = FALSE; + stream_rec->position = 0; + + len = strlen( filepathname ) + 1; + if ( ALLOC( stream_rec->name, len ) ) + goto Fail; + + strncpy( stream_rec->name, filepathname, len ); + + error = Stream_Activate( stream_rec ); + if ( error ) + goto Fail_Activate; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + CUR_Stream = stream_rec; +#endif + + return TT_Err_Ok; + + Fail_Activate: + FREE( stream_rec->name ); + Fail: + FREE( stream_rec ); + return error; + } + + +/******************************************************************* + * + * Function : TT_Close_Stream + * + * Description : Closes a stream. + * + * Input : stream address of target TT_Stream structure + * + * Output : SUCCESS (always). + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TT_Close_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + Stream_Deactivate( rec ); + FREE( rec->name ); + FREE( rec ); + + HANDLE_Set( *stream, NULL ); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Flush_Stream + * + * Description : Flushes a stream, i.e., closes its file handle. + * + * Input : stream address of target TT_Stream structure + * + * Output : Error code + * + * NOTE : Never flush the current opened stream. This means that + * you should _never_ call this function between a + * TT_Use_Stream() and a TT_Done_Stream()! + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Flush_Stream( TT_Stream* stream ) + { + PStream_Rec rec = STREAM2REC( *stream ); + + + if ( rec ) + { + Stream_Deactivate( rec ); + return TT_Err_Ok; + } + else + return TT_Err_Invalid_Argument; + } + + +/******************************************************************* + * + * Function : TT_Seek_File + * + * Description : Seeks the file cursor to a different position. + * + * Input : position new position in file + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Seek_File( STREAM_ARGS Long position ) + { + position += CUR_Stream->base; + + if ( fseek( CUR_Stream->file, position, SEEK_SET ) ) + return TT_Err_Invalid_File_Offset; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Skip_File + * + * Description : Skips forward the file cursor. + * + * Input : distance number of bytes to skip + * + * Output : see TT_Seek_File() + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Skip_File( STREAM_ARGS Long distance ) + { + return TT_Seek_File( STREAM_VARS ftell( CUR_Stream->file ) - + CUR_Stream->base + distance ); + } + + +/******************************************************************* + * + * Function : TT_Read_File + * + * Description : Reads a chunk of the file and copies it to memory. + * + * Input : buffer target buffer + * count length in bytes to read + * + * Output : SUCCESS on success. FAILURE if out of range. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_File( STREAM_ARGS void* buffer, Long count ) + { + if ( fread( buffer, 1, count, CUR_Stream->file ) != (ULong)count ) + return TT_Err_Invalid_File_Read; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_Read_At_File + * + * Description : Reads file at a specified position. + * + * Input : position position to seek to before read + * buffer target buffer + * count number of bytes to read + * + * Output : SUCCESS on success. FAILURE if error. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Read_At_File( STREAM_ARGS Long position, + void* buffer, + Long count ) + { + TT_Error error; + + + if ( (error = TT_Seek_File( STREAM_VARS position )) != TT_Err_Ok || + (error = TT_Read_File( STREAM_VARS buffer, count )) != TT_Err_Ok ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TT_File_Pos + * + * Description : Returns current file seek pointer. + * + * Input : none + * + * Output : Current file position. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_File_Pos( STREAM_ARG ) + { + return ftell( CUR_Stream->file ) - CUR_Stream->base; + } + + +/******************************************************************* + * + * Function : GET_Byte + * + * Description : Extracts a byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted Byte. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + Byte TT_Get_Byte( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Byte)(*CUR_Frame.cursor++); + } +#endif + + +/******************************************************************* + * + * Function : GET_Char + * + * Description : Extracts a signed byte from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted char. + * + ******************************************************************/ + EXPORT_FUNC + Char TT_Get_Char( FRAME_ARG ) + { + CHECK_FRAME( CUR_Frame, 1 ); + + return (Char)(*CUR_Frame.cursor++); + } + + +/******************************************************************* + * + * Function : GET_Short + * + * Description : Extracts a short from the current file frame. + * + * Input : None or current frame + * + * Output : Extracted short. + * + ******************************************************************/ + + EXPORT_FUNC + Short TT_Get_Short( FRAME_ARG ) + { + Short getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = (Short)((CUR_Frame.cursor[0] << 8) | + CUR_Frame.cursor[1]); + + CUR_Frame.cursor += 2; + + return getshort; + } + + +/******************************************************************* + * + * Function : GET_UShort + * + * Description : Extracts an unsigned short from the frame. + * + * Input : None or current frame + * + * Output : Extracted ushort. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + UShort TT_Get_UShort( FRAME_ARG ) + { + UShort getshort; + + + CHECK_FRAME( CUR_Frame, 2 ); + + getshort = (UShort)((CUR_Frame.cursor[0] << 8) | + CUR_Frame.cursor[1]); + + CUR_Frame.cursor += 2; + + return getshort; + } +#endif + + +/******************************************************************* + * + * Function : GET_Long + * + * Description : Extracts a long from the frame. + * + * Input : None or current frame + * + * Output : Extracted long. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_Get_Long( FRAME_ARG ) + { + Long getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ((Long)CUR_Frame.cursor[0] << 24) | + ((Long)CUR_Frame.cursor[1] << 16) | + ((Long)CUR_Frame.cursor[2] << 8 ) | + (Long)CUR_Frame.cursor[3]; + + CUR_Frame.cursor += 4; + + return getlong; + } + + +/******************************************************************* + * + * Function : GET_ULong + * + * Description : Extracts an unsigned long from the frame. + * + * Input : None or current frame + * + * Output : Extracted ulong. + * + ******************************************************************/ +#if 0 + EXPORT_FUNC + ULong TT_Get_ULong( FRAME_ARG ) + { + ULong getlong; + + + CHECK_FRAME( CUR_Frame, 4 ); + + getlong = ( ((ULong)CUR_Frame.cursor[0] << 24) | + ((ULong)CUR_Frame.cursor[1] << 16) | + ((ULong)CUR_Frame.cursor[2] << 8 ) | + (ULong)CUR_Frame.cursor[3] ); + + CUR_Frame.cursor += 4; + + return getlong; + } +#endif + + +/* END */ diff --git a/Build/source/libs/libttf/ttfile.h b/Build/source/libs/libttf/ttfile.h new file mode 100644 index 00000000000..eebd1c1d43e --- /dev/null +++ b/Build/source/libs/libttf/ttfile.h @@ -0,0 +1,271 @@ +/******************************************************************* + * + * ttfile.h 1.3 + * + * File I/O Component (specification). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Changes between 1.3 and 1.2: + * + * - all functions report error values now + * + * - the stream semantics have also changed + * + * Changes between 1.2 and 1.1: + * + * - added macros to support re-entrant builds + * + * - added the TT_Duplicate_File function to duplicate streams + * (re-entrant builds only) + * + ******************************************************************/ + +#ifndef TTFILE_H +#define TTFILE_H + +#include "ttconfig.h" +#include "freetype.h" +#include "ttengine.h" +#include "ttdebug.h" + +#ifdef __cplusplus + extern "C" { +#endif + + /* Initialize file component */ + LOCAL_DEF + TT_Error TTFile_Init( PEngine_Instance engine ); + + /* Done with file component */ + LOCAL_DEF + TT_Error TTFile_Done( PEngine_Instance engine ); + + + /**********************************************************************/ + /* */ + /* Stream functions. */ + /* */ + /**********************************************************************/ + + /* Open a file and return a stream handle for it. */ + /* Should only be used for a new face object's main stream. */ + + LOCAL_DEF + TT_Error TT_Open_Stream( const TT_Text* name, + TT_Stream* stream ); + + + /* Closes, then discards, a stream when it's no longer needed. */ + /* Should only be used for a stream opend with TT_Open_Stream(). */ + + LOCAL_DEF + TT_Error TT_Close_Stream( TT_Stream* stream ); + + + /* Informs the component that we're going to use the file */ + /* opened in 'org_stream', and report errors to the 'error' */ + /* variable. */ + + /* in non re-entrant builds, 'org_stream' is simply copied */ + /* to 'stream'. Otherwise, the latter is a duplicate handle */ + /* for the file opened with 'org_stream' */ + + EXPORT_DEF + TT_Error TT_Use_Stream( TT_Stream org_stream, + TT_Stream* stream ); + + /* Informs the component that we don't need to perform file */ + /* operations on the stream 'stream' anymore. This must be */ + /* used with streams "opened" with TT_Use_Stream() only! */ + + /* in re-entrant builds, this will really discard the stream */ + + EXPORT_DEF + TT_Error TT_Done_Stream( TT_Stream* stream ); + + /* Closes the stream's file handle to release system resources */ + /* The function TT_Use_Stream automatically re-activates a */ + /* flushed stream when it uses one */ + + EXPORT_DEF + TT_Error TT_Flush_Stream( TT_Stream* stream ); + +/* The macros STREAM_ARGS and STREAM_ARG let us build a thread-safe */ +/* or re-entrant implementation depending on a single configuration */ +/*define. */ + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE + +#define STREAM_ARGS TT_Stream stream, +#define STREAM_ARG TT_Stream stream + +#else + +#define STREAM_ARGS /* void */ +#define STREAM_ARG void + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /****************************************************************/ + /* */ + /* File Functions. */ + /* */ + /* The following functions perform file operations on the */ + /* currently 'used' stream. In thread-safe builds, only one */ + /* stream can be used at a time. Synchronisation is performed */ + /* through the Use_Stream()/Done_Stream() functions. */ + /* */ + /****************************************************************/ + + /* Read 'count' bytes from file into 'buffer' */ + + EXPORT_DEF + TT_Error TT_Read_File( STREAM_ARGS void* buffer, + Long count ); + + + /* Seek file cursor to a given position */ + + EXPORT_DEF + TT_Error TT_Seek_File( STREAM_ARGS Long position ); + + + /* Skip the next 'distance' bytes in file */ + + EXPORT_DEF + TT_Error TT_Skip_File( STREAM_ARGS Long distance ); + + + /* Read the 'count' bytes at 'position' into 'buffer' */ + + EXPORT_DEF + TT_Error TT_Read_At_File( STREAM_ARGS Long position, + void* buffer, + Long count ); + + /* Return current file position */ + + EXPORT_DEF + Long TT_File_Pos( STREAM_ARG ); + + /* Return length of a given stream, even if it is flushed */ + + EXPORT_DEF + Long TT_Stream_Size( TT_Stream stream ); + + + /********************************************************************/ + /* */ + /* Frame operations. */ + /* */ + /* For a comprehensive explanation of frames, please refer to the */ + /* documentation files. */ + /* */ + /********************************************************************/ + + /* Frame type declaration.*/ + + struct TFileFrame_ + { + Byte* address; /* frame buffer */ + Byte* cursor; /* current cursor position in frame */ + Long size; /* frame size */ + }; + + typedef struct TFileFrame_ TFileFrame; + + EXPORT_DEF + const TFileFrame TT_Null_FileFrame; + + +/* The macro ZERO_Frame is used to define and init a frame. */ +/* It is important to have a default frame of { NULL, NULL, 0 } */ +/* before a call to TT_Access_Frame(). Otherwise, the call will */ +/* fail with a TT_Err_Nested_Frame_Accesses error. */ + +#define ZERO_Frame( frame ) \ + { \ + (frame).address = NULL; \ + (frame).cursor = NULL; \ + (frame).size = 0; \ + } + + +/* The macros FRAME_ARGS and FRAME_ARG let us build a thread-safe */ +/* or re-entrant implementation depending on a single configuration */ +/* define */ + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE + +#define FRAME_ARGS TFileFrame* frame, +#define FRAME_ARG TFileFrame* frame + +#else + +#define FRAME_ARGS /* void */ +#define FRAME_ARG void + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + + /* Access the next 'size' bytes from current position. */ + /* Fails if all bytes cannot be read/accessed. */ + + EXPORT_DEF + TT_Error TT_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ); + + + /* Access the bytes located in the next 'size' bytes of the file. */ + /* Doesn't fail if less than 'size' bytes are accessible (like */ + /* at the end of the file). */ + + EXPORT_DEF + TT_Error TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS Long size ); + + /* Forget frame */ + + EXPORT_DEF + TT_Error TT_Forget_Frame( FRAME_ARG ); + + + /* primitive routines for data accessing */ + + EXPORT_DEF + Char TT_Get_Char ( FRAME_ARG ); + EXPORT_DEF + Short TT_Get_Short( FRAME_ARG ); + EXPORT_DEF + Long TT_Get_Long ( FRAME_ARG ); + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE + +#define TT_Get_Byte( frame ) ( (Byte )TT_Get_Char ( frame ) ) +#define TT_Get_UShort( frame ) ( (UShort)TT_Get_Short( frame ) ) +#define TT_Get_ULong( frame ) ( (ULong )TT_Get_Long ( frame ) ) + +#else + +#define TT_Get_Byte() ( (Byte )TT_Get_Char () ) +#define TT_Get_UShort() ( (UShort)TT_Get_Short() ) +#define TT_Get_ULong() ( (ULong )TT_Get_Long () ) + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + +#ifdef __cplusplus + } +#endif + +#endif /* TTFILE_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttgload.c b/Build/source/libs/libttf/ttgload.c new file mode 100644 index 00000000000..a7ca3179aeb --- /dev/null +++ b/Build/source/libs/libttf/ttgload.c @@ -0,0 +1,1351 @@ +/******************************************************************* + * + * ttgload.c 1.0 + * + * TrueType Glyph Loader. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "tttypes.h" +#include "ttdebug.h" +#include "ttcalc.h" +#include "ttfile.h" + +#include "tttables.h" +#include "ttobjs.h" +#include "ttgload.h" + +#include "ttmemory.h" +#include "tttags.h" +#include "ttload.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_gload + + +/* composite font flags */ + +#define ARGS_ARE_WORDS 0x001 +#define ARGS_ARE_XY_VALUES 0x002 +#define ROUND_XY_TO_GRID 0x004 +#define WE_HAVE_A_SCALE 0x008 +/* reserved 0x010 */ +#define MORE_COMPONENTS 0x020 +#define WE_HAVE_AN_XY_SCALE 0x040 +#define WE_HAVE_A_2X2 0x080 +#define WE_HAVE_INSTR 0x100 +#define USE_MY_METRICS 0x200 + + +/********************************************************/ +/* Return horizontal or vertical metrics in font units */ +/* for a given glyph. The metrics are the left side */ +/* bearing (resp. top side bearing) and advance width */ +/* (resp. advance height). */ +/* */ +/* This function will much probably move to another */ +/* component in the short future, but I haven't decided */ +/* which yet... */ + + LOCAL_FUNC + void TT_Get_Metrics( TT_Horizontal_Header* header, + UShort index, + Short* bearing, + UShort* advance ) + { + PLongMetrics longs_m; + + UShort k = header->number_Of_HMetrics; + + + if ( index < k ) + { + longs_m = (PLongMetrics)header->long_metrics + index; + *bearing = longs_m->bearing; + *advance = longs_m->advance; + } + else + { + *bearing = ((PShortMetrics)header->short_metrics)[index - k]; + *advance = ((PLongMetrics)header->long_metrics)[k - 1].advance; + } + } + + +/********************************************************/ +/* Return horizontal metrics in font units for a given */ +/* glyph. If `check' is true, take care of mono-spaced */ +/* fonts by returning the advance width max. */ + + static void Get_HMetrics( PFace face, + UShort index, + Bool check, + Short* lsb, + UShort* aw ) + { + TT_Get_Metrics( &face->horizontalHeader, index, lsb, aw ); + + if ( check && face->postscript.isFixedPitch ) + *aw = face->horizontalHeader.advance_Width_Max; + } + + +/********************************************************/ +/* Return advance width table for a given pixel size */ +/* if it is found in the font's `hdmx' table (if any). */ + + static PByte Get_Advance_Widths( PFace face, + UShort ppem ) + { + UShort n; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + if ( face->hdmx.records[n].ppem == ppem ) + return face->hdmx.records[n].widths; + + return NULL; + } + + +/********************************************************/ +/* Copy current glyph into original one. */ + +#define cur_to_org( n, zone ) \ + MEM_Copy( (zone)->org, (zone)->cur, (n) * sizeof ( TT_Vector ) ) + +/********************************************************/ +/* copy original glyph into current one */ + +#define org_to_cur( n, zone ) \ + MEM_Copy( (zone)->cur, (zone)->org, (n) * sizeof ( TT_Vector ) ) + +/********************************************************/ +/* translate an array of coordinates */ + + static void translate_array( UShort n, + TT_Vector* coords, + TT_Pos delta_x, + TT_Pos delta_y ) + { + UShort k; + + + if ( delta_x ) + for ( k = 0; k < n; k++ ) + coords[k].x += delta_x; + + if ( delta_y ) + for ( k = 0; k < n; k++ ) + coords[k].y += delta_y; + } + + +/********************************************************/ +/* mount one zone on top of another */ + + static void mount_zone( PGlyph_Zone source, + PGlyph_Zone target ) + { + UShort np; + Short nc; + + np = source->n_points; + nc = source->n_contours; + + target->org = source->org + np; + target->cur = source->cur + np; + target->touch = source->touch + np; + + target->contours = source->contours + nc; + + target->n_points = 0; + target->n_contours = 0; + } + + +/******************************************************************* + * + * Function: Load_Simple_Glyph + * + ******************************************************************/ + + static TT_Error Load_Simple_Glyph( PExecution_Context exec, + TT_Stream input, + Short n_contours, + Short left_contours, + UShort left_points, + UShort load_flags, + PSubglyph_Record subg ) + { + DEFINE_LOAD_LOCALS( input ); + + PGlyph_Zone pts; + Short k; + UShort j; + UShort n_points, n_ins; + PFace face; + Byte* flag; + TT_Vector* vec; + TT_F26Dot6 x, y; + + + face = exec->face; + + /* simple check */ + if ( n_contours > left_contours ) + { + PTRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n", + subg->index, n_contours, left_contours )); + return TT_Err_Too_Many_Contours; + } + + + /* preparing the execution context */ + mount_zone( &subg->zone, &exec->pts ); + + /* reading the contours endpoints */ + if ( ACCESS_Frame( (n_contours + 1) * 2L ) ) + return error; + + PTRACE4(( " Contour endpoints:" )); + + for ( k = 0; k < n_contours; k++ ) + { + exec->pts.contours[k] = GET_UShort(); + PTRACE4(( " %d", exec->pts.contours[k] )); + } + PTRACE4(( "\n" )); + + if ( n_contours > 0 ) + n_points = exec->pts.contours[n_contours - 1] + 1; + else + n_points = 0; + + n_ins = GET_UShort(); + + FORGET_Frame(); + + if ( n_points > left_points ) + { + PTRACE0(( "ERROR: Too many points in glyph %ld\n", subg->index )); + return TT_Err_Too_Many_Points; + } + + /* loading instructions */ + + PTRACE4(( " Instructions size: %d\n", n_ins )); + + if ( n_ins > face->maxProfile.maxSizeOfInstructions ) + { + PTRACE0(( "ERROR: Too many instructions!\n" )); + return TT_Err_Too_Many_Ins; + } + + if ( FILE_Read( exec->glyphIns, n_ins ) ) + return error; + + if ( (error = Set_CodeRange( exec, + TT_CodeRange_Glyph, + exec->glyphIns, + n_ins )) != TT_Err_Ok ) + return error; + + + /* read the flags */ + + if ( CHECK_ACCESS_Frame( n_points * 5L ) ) + return error; + + j = 0; + flag = exec->pts.touch; + + while ( j < n_points ) + { + Byte c, cnt; + + flag[j] = c = GET_Byte(); + j++; + + if ( c & 8 ) + { + cnt = GET_Byte(); + while( cnt > 0 ) + { + flag[j++] = c; + cnt--; + } + } + } + + /* read the X */ + + x = 0; + vec = exec->pts.org; + + for ( j = 0; j < n_points; j++ ) + { + if ( flag[j] & 2 ) + { + if ( flag[j] & 16 ) + x += GET_Byte(); + else + x -= GET_Byte(); + } + else + { + if ( (flag[j] & 16) == 0 ) + x += GET_Short(); + } + + vec[j].x = x; + } + + + /* read the Y */ + + y = 0; + + for ( j = 0; j < n_points; j++ ) + { + if ( flag[j] & 4 ) + { + if ( flag[j] & 32 ) + y += GET_Byte(); + else + y -= GET_Byte(); + } + else + { + if ( (flag[j] & 32) == 0 ) + y += GET_Short(); + } + + vec[j].y = y; + } + + FORGET_Frame(); + + /* Now add the two shadow points at n and n + 1. */ + /* We need the left side bearing and advance width. */ + + /* pp1 = xMin - lsb */ + vec[n_points].x = subg->metrics.bbox.xMin - subg->metrics.horiBearingX; + vec[n_points].y = 0; + + /* pp2 = pp1 + aw */ + vec[n_points+1].x = vec[n_points].x + subg->metrics.horiAdvance; + vec[n_points+1].y = 0; + + /* clear the touch flags */ + + for ( j = 0; j < n_points; j++ ) + exec->pts.touch[j] &= TT_Flag_On_Curve; + + exec->pts.touch[n_points ] = 0; + exec->pts.touch[n_points + 1] = 0; + + /* Note that we return two more points that are not */ + /* part of the glyph outline. */ + + n_points += 2; + + /* now eventually scale and hint the glyph */ + + pts = &exec->pts; + pts->n_points = n_points; + pts->n_contours = n_contours; + + if ( (load_flags & TTLOAD_SCALE_GLYPH) == 0 ) + { + /* no scaling, just copy the orig arrays into the cur ones */ + org_to_cur( n_points, pts ); + } + else + { + /* first scale the glyph points */ + + for ( j = 0; j < n_points; j++ ) + { + pts->org[j].x = Scale_X( &exec->metrics, pts->org[j].x ); + pts->org[j].y = Scale_Y( &exec->metrics, pts->org[j].y ); + } + + /* if hinting, round pp1, and shift the glyph accordingly */ + if ( subg->is_hinted ) + { + x = pts->org[n_points - 2].x; + x = ((x+32) & -64) - x; + translate_array( n_points, pts->org, x, 0 ); + + org_to_cur( n_points, pts ); + + pts->cur[n_points - 1].x = (pts->cur[n_points - 1].x + 32) & -64; + + /* now consider hinting */ + if ( n_ins > 0 ) + { + exec->is_composite = FALSE; + exec->pedantic_hinting = load_flags & TTLOAD_PEDANTIC; + + error = Context_Run( exec, FALSE ); + if (error && exec->pedantic_hinting) + return error; + } + } + else + org_to_cur( n_points, pts ); + } + + /* save glyph phantom points */ + if (!subg->preserve_pps) + { + subg->pp1 = pts->cur[n_points - 2]; + subg->pp2 = pts->cur[n_points - 1]; + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_Composite_End + * + ******************************************************************/ + + static + TT_Error Load_Composite_End( UShort n_points, + Short n_contours, + PExecution_Context exec, + PSubglyph_Record subg, + UShort load_flags, + TT_Stream input ) + { + DEFINE_LOAD_LOCALS( input ); + + UShort k, n_ins; + PGlyph_Zone pts; + + + if ( subg->is_hinted && + subg->element_flag & WE_HAVE_INSTR ) + { + if ( ACCESS_Frame( 2L ) ) + return error; + + n_ins = GET_UShort(); /* read size of instructions */ + FORGET_Frame(); + + PTRACE4(( " Instructions size: %d\n", n_ins )); + + if ( n_ins > exec->face->maxProfile.maxSizeOfInstructions ) + { + PTRACE0(( "ERROR: Too many instructions in composite glyph %ld\n", + subg->index )); + return TT_Err_Too_Many_Ins; + } + + if ( FILE_Read( exec->glyphIns, n_ins ) ) + return error; + + error = Set_CodeRange( exec, + TT_CodeRange_Glyph, + exec->glyphIns, + n_ins ); + + if ( error ) + return error; + } + else + n_ins = 0; + + + /* prepare the execution context */ + n_points += 2; + exec->pts = subg->zone; + pts = &exec->pts; + + pts->n_points = n_points; + pts->n_contours = n_contours; + + /* add phantom points */ + pts->cur[n_points - 2] = subg->pp1; + pts->cur[n_points - 1] = subg->pp2; + + pts->touch[n_points - 1] = 0; + pts->touch[n_points - 2] = 0; + + /* if hinting, round the phantom points */ + if ( subg->is_hinted ) + { + pts->cur[n_points - 2].x = (subg->pp1.x + 32) & -64; + pts->cur[n_points - 1].x = (subg->pp2.x + 32) & -64; + } + + for ( k = 0; k < n_points; k++ ) + pts->touch[k] &= TT_Flag_On_Curve; + + cur_to_org( n_points, pts ); + + /* now consider hinting */ + if ( subg->is_hinted && n_ins > 0 ) + { + exec->is_composite = TRUE; + exec->pedantic_hinting = load_flags & TTLOAD_PEDANTIC; + + error = Context_Run( exec, FALSE ); + if (error && exec->pedantic_hinting) + return error; + } + + /* save glyph origin and advance points */ + subg->pp1 = pts->cur[n_points - 2]; + subg->pp2 = pts->cur[n_points - 1]; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Init_Glyph_Component + * + ******************************************************************/ + + static + void Init_Glyph_Component( PSubglyph_Record element, + PSubglyph_Record original, + PExecution_Context exec ) + { + element->index = -1; + element->is_scaled = FALSE; + element->is_hinted = FALSE; + + if ( original ) + mount_zone( &original->zone, &element->zone ); + else + element->zone = exec->pts; + + element->zone.n_contours = 0; + element->zone.n_points = 0; + + element->arg1 = 0; + element->arg2 = 0; + + element->element_flag = 0; + element->preserve_pps = FALSE; + + element->transform.xx = 1L << 16; + element->transform.xy = 0; + element->transform.yx = 0; + element->transform.yy = 1L << 16; + + element->transform.ox = 0; + element->transform.oy = 0; + + element->metrics.horiBearingX = 0; + element->metrics.horiAdvance = 0; + } + + + + LOCAL_FUNC + TT_Error Load_TrueType_Glyph( PInstance instance, + PGlyph glyph, + UShort glyph_index, + UShort load_flags ) + { + enum TPhases_ + { + Load_Exit, + Load_Glyph, + Load_Header, + Load_Simple, + Load_Composite, + Load_End + }; + + typedef enum TPhases_ TPhases; + + DEFINE_ALL_LOCALS; + + PFace face; + + UShort num_points; + Short num_contours; + UShort left_points; + Short left_contours; + UShort num_elem_points; + + Long table; + UShort load_top; + Long k, l; + UShort new_flags; + Long index; + UShort u, v; + + Long glyph_offset, offset; + + TT_F26Dot6 x, y, nx, ny; + + Fixed xx, xy, yx, yy; + + PExecution_Context exec; + + PSubglyph_Record subglyph, subglyph2; + + TGlyph_Zone base_pts; + + TPhases phase; + PByte widths; + +/* TT_Glyph_Loader_Callback cacheCb; */ +/* TT_Outline cached_outline; */ + + + /* first of all, check arguments */ + if ( !glyph ) + return TT_Err_Invalid_Glyph_Handle; + + face = glyph->face; + if ( !face ) + return TT_Err_Invalid_Glyph_Handle; + + if ( glyph_index >= face->numGlyphs ) + return TT_Err_Invalid_Glyph_Index; + + if ( instance && (load_flags & TTLOAD_SCALE_GLYPH) == 0 ) + { + instance = 0; + load_flags &= ~( TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH ); + } + + table = TT_LookUp_Table( face, TTAG_glyf ); + if ( table < 0 ) + { + PTRACE0(( "ERROR: There is no glyph table in this font file!\n" )); + return TT_Err_Glyf_Table_Missing; + } + + glyph_offset = face->dirTables[table].Offset; + + /* query new execution context */ + + if ( instance && instance->debug ) + exec = instance->context; + else + exec = New_Context( face ); + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + Context_Load( exec, face, instance ); + + if ( instance ) + { + if ( instance->GS.instruct_control & 2 ) + exec->GS = Default_GraphicsState; + else + exec->GS = instance->GS; + /* load default graphics state */ + + glyph->outline.high_precision = ( instance->metrics.y_ppem < 24 ); + } + + /* save its critical pointers, as they'll be modified during load */ + base_pts = exec->pts; + + /* init variables */ + left_points = face->maxPoints; + left_contours = face->maxContours; + + num_points = 0; + num_contours = 0; + + load_top = 0; + subglyph = exec->loadStack; + + Init_Glyph_Component( subglyph, NULL, exec ); + + subglyph->index = glyph_index; + subglyph->is_hinted = load_flags & TTLOAD_HINT_GLYPH; + + /* when the cvt program has disabled hinting, the argument */ + /* is ignored. */ + if ( instance && instance->GS.instruct_control & 1 ) + subglyph->is_hinted = FALSE; + + + /* now access stream */ + + if ( USE_Stream( face->stream, stream ) ) + goto Fin; + + /* Main loading loop */ + + phase = Load_Glyph; + index = 0; + + while ( phase != Load_Exit ) + { + subglyph = exec->loadStack + load_top; + + switch ( phase ) + { + /************************************************************/ + /* */ + /* Load_Glyph state */ + /* */ + /* reading a glyph's generic header to determine */ + /* whether it's simple or composite */ + /* */ + /* exit states: Load_Header and Load_End */ + + case Load_Glyph: + /* check glyph index and table */ + + index = subglyph->index; + if ( index < 0 || index >= face->numGlyphs ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Fail; + } + + /* get horizontal metrics */ + + { + Short left_bearing; + UShort advance_width; + + + Get_HMetrics( face, (UShort)index, + !(load_flags & TTLOAD_IGNORE_GLOBAL_ADVANCE_WIDTH), + &left_bearing, + &advance_width ); + + subglyph->metrics.horiBearingX = left_bearing; + subglyph->metrics.horiAdvance = advance_width; + } + + phase = Load_Header; + + + /* The cache callback isn't part of the FreeType release yet */ + /* It is discarded for the moment.. */ + /* */ +#if 0 + if ( instance ) + { + /* is the glyph in an outline cache ? */ + cacheCb = instance->owner->engine->glCallback; + if ( cacheCb && 0 ) /* disabled */ + { + /* we have a callback */ + error = cacheCb( instance->generic, + index, &cached_outline, &x, &y ); + if ( !error ) + { + /* no error, then append the outline to the current subglyph */ + /* error = Append_Outline( subglyph, + &left_points, + &left_contours, + &cached_outline ); */ + phase = Load_End; + } + } + } +#endif + break; + + + /************************************************************/ + /* */ + /* Load_Header state */ + /* */ + /* reading a glyph's generic header to determine */ + /* wether it's simple or composite */ + /* */ + /* exit states: Load_Simple and Load_Composite */ + /* */ + + case Load_Header: /* load glyph */ + + if ( index + 1 < face->numLocations && + face->glyphLocations[index] == face->glyphLocations[index + 1] ) + { + /* as described by Frederic Loyer, these are spaces, and */ + /* not the unknown glyph. */ + + num_contours = 0; + num_points = 0; + + subglyph->metrics.bbox.xMin = 0; + subglyph->metrics.bbox.xMax = 0; + subglyph->metrics.bbox.yMin = 0; + subglyph->metrics.bbox.yMax = 0; + + subglyph->pp1.x = 0; + subglyph->pp2.x = subglyph->metrics.horiAdvance; + if (load_flags & TTLOAD_SCALE_GLYPH) + subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x ); + + exec->glyphSize = 0; + phase = Load_End; + break; + } + + offset = glyph_offset + face->glyphLocations[index]; + + /* read first glyph header */ + if ( FILE_Seek( offset ) || + ACCESS_Frame( 10L ) ) + goto Fail_File; + + num_contours = GET_Short(); + + subglyph->metrics.bbox.xMin = GET_Short(); + subglyph->metrics.bbox.yMin = GET_Short(); + subglyph->metrics.bbox.xMax = GET_Short(); + subglyph->metrics.bbox.yMax = GET_Short(); + + FORGET_Frame(); + + PTRACE6(( "Glyph %ld:\n", index )); + PTRACE6(( " # of contours: %d\n", num_contours )); + PTRACE6(( " xMin: %4d xMax: %4d\n", + subglyph->metrics.bbox.xMin, + subglyph->metrics.bbox.xMax )); + PTRACE6(( " yMin: %4d yMax: %4d\n", + subglyph->metrics.bbox.yMin, + subglyph->metrics.bbox.yMax )); + + if ( num_contours > left_contours ) + { + PTRACE0(( "ERROR: Too many contours for glyph %ld\n", index )); + error = TT_Err_Too_Many_Contours; + goto Fail; + } + + subglyph->pp1.x = subglyph->metrics.bbox.xMin - + subglyph->metrics.horiBearingX; + subglyph->pp1.y = 0; + subglyph->pp2.x = subglyph->pp1.x + subglyph->metrics.horiAdvance; + if (load_flags & TTLOAD_SCALE_GLYPH) + { + subglyph->pp1.x = Scale_X( &exec->metrics, subglyph->pp1.x ); + subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x ); + } + + /* is it a simple glyph ? */ + if ( num_contours > 0 ) + phase = Load_Simple; + else + phase = Load_Composite; + + break; + + + /************************************************************/ + /* */ + /* Load_Simple state */ + /* */ + /* reading a simple glyph (num_contours must be set to */ + /* the glyph's number of contours.) */ + /* */ + /* exit states : Load_End */ + /* */ + + case Load_Simple: + new_flags = load_flags; + + /* disable hinting when scaling */ + if ( !subglyph->is_hinted ) + new_flags &= ~TTLOAD_HINT_GLYPH; + + error = Load_Simple_Glyph( exec, + stream, + num_contours, + left_contours, + left_points, + new_flags, + subglyph ); + if ( error ) + goto Fail; + + /* Note: We could have put the simple loader source there */ + /* but the code is fat enough already :-) */ + + num_points = exec->pts.n_points - 2; + + phase = Load_End; + + break; + + + /************************************************************/ + /* */ + /* Load_Composite state */ + /* */ + /* reading a composite glyph header a pushing a new */ + /* load element on the stack. */ + /* */ + /* exit states: Load_Glyph */ + /* */ + + case Load_Composite: + + /* create a new element on the stack */ + load_top++; + + if ( load_top > face->maxComponents ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + subglyph2 = exec->loadStack + load_top; + + Init_Glyph_Component( subglyph2, subglyph, NULL ); + subglyph2->is_hinted = subglyph->is_hinted; + + /* now read composite header */ + + if ( ACCESS_Frame( 4L ) ) + goto Fail_File; + + subglyph->element_flag = new_flags = GET_UShort(); + + subglyph2->index = GET_UShort(); + + FORGET_Frame(); + + k = 1 + 1; + + if ( new_flags & ARGS_ARE_WORDS ) + k *= 2; + + if ( new_flags & WE_HAVE_A_SCALE ) + k += 2; + + else if ( new_flags & WE_HAVE_AN_XY_SCALE ) + k += 4; + + else if ( new_flags & WE_HAVE_A_2X2 ) + k += 8; + + if ( ACCESS_Frame( k ) ) + goto Fail_File; + + if ( new_flags & ARGS_ARE_WORDS ) + { + k = GET_Short(); + l = GET_Short(); + } + else + { + k = GET_Char(); + l = GET_Char(); + } + + subglyph->arg1 = k; + subglyph->arg2 = l; + + if ( new_flags & ARGS_ARE_XY_VALUES ) + { + subglyph->transform.ox = k; + subglyph->transform.oy = l; + } + + xx = 1L << 16; + xy = 0; + yx = 0; + yy = 1L << 16; + + if ( new_flags & WE_HAVE_A_SCALE ) + { + xx = (Fixed)GET_Short() << 2; + yy = xx; + subglyph2->is_scaled = TRUE; + } + else if ( new_flags & WE_HAVE_AN_XY_SCALE ) + { + xx = (Fixed)GET_Short() << 2; + yy = (Fixed)GET_Short() << 2; + subglyph2->is_scaled = TRUE; + } + else if ( new_flags & WE_HAVE_A_2X2 ) + { + xx = (Fixed)GET_Short() << 2; + xy = (Fixed)GET_Short() << 2; + yx = (Fixed)GET_Short() << 2; + yy = (Fixed)GET_Short() << 2; + subglyph2->is_scaled = TRUE; + } + + FORGET_Frame(); + + subglyph->transform.xx = xx; + subglyph->transform.xy = xy; + subglyph->transform.yx = yx; + subglyph->transform.yy = yy; + + k = TT_MulFix( xx, yy ) - TT_MulFix( xy, yx ); + + /* disable hinting in case of scaling/slanting */ + if ( ABS( k ) != (1L << 16) ) + subglyph2->is_hinted = FALSE; + + subglyph->file_offset = FILE_Pos(); + + phase = Load_Glyph; + + break; + + + /************************************************************/ + /* */ + /* Load_End state */ + /* */ + /* after loading a glyph, apply transformation and offset */ + /* where necessary, pops element and continue or */ + /* stop process. */ + /* */ + /* exit states : Load_Composite and Load_Exit */ + /* */ + + case Load_End: + if ( load_top > 0 ) + { + subglyph2 = subglyph; + + load_top--; + subglyph = exec->loadStack + load_top; + + /* check advance width and left side bearing */ + + if ( !subglyph->preserve_pps && + subglyph->element_flag & USE_MY_METRICS ) + { + subglyph->metrics.horiBearingX = subglyph2->metrics.horiBearingX; + subglyph->metrics.horiAdvance = subglyph2->metrics.horiAdvance; + + subglyph->pp1 = subglyph2->pp1; + subglyph->pp2 = subglyph2->pp2; + + subglyph->preserve_pps = TRUE; + } + + /* apply scale */ + + if ( subglyph2->is_scaled ) + { + TT_Vector* cur = subglyph2->zone.cur; + TT_Vector* org = subglyph2->zone.org; + + for ( u = 0; u < num_points; u++ ) + { + nx = TT_MulFix( cur->x, subglyph->transform.xx ) + + TT_MulFix( cur->y, subglyph->transform.yx ); + + ny = TT_MulFix( cur->x, subglyph->transform.xy ) + + TT_MulFix( cur->y, subglyph->transform.yy ); + + cur->x = nx; + cur->y = ny; + + nx = TT_MulFix( org->x, subglyph->transform.xx ) + + TT_MulFix( org->y, subglyph->transform.yx ); + + ny = TT_MulFix( org->x, subglyph->transform.xy ) + + TT_MulFix( org->y, subglyph->transform.yy ); + + org->x = nx; + org->y = ny; + + cur++; + org++; + } + } + + /* adjust counts */ + + num_elem_points = subglyph->zone.n_points; + + for ( k = 0; k < num_contours; k++ ) + subglyph2->zone.contours[k] += num_elem_points; + + subglyph->zone.n_points += num_points; + subglyph->zone.n_contours += num_contours; + + left_points -= num_points; + left_contours -= num_contours; + + if ( !(subglyph->element_flag & ARGS_ARE_XY_VALUES) ) + { + /* move second glyph according to control points */ + /* the attach points are relative to the specific component */ + + u = (UShort)subglyph->arg1; + v = (UShort)subglyph->arg2; + + if ( u >= num_elem_points || + v >= num_points ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + /* adjust count */ + v += num_elem_points; + + x = subglyph->zone.cur[u].x - subglyph->zone.cur[v].x; + y = subglyph->zone.cur[u].y - subglyph->zone.cur[v].y; + } + else + { + /* apply offset */ + + x = subglyph->transform.ox; + y = subglyph->transform.oy; + + if ( load_flags & TTLOAD_SCALE_GLYPH ) + { + x = Scale_X( &exec->metrics, x ); + y = Scale_Y( &exec->metrics, y ); + + if ( subglyph->element_flag & ROUND_XY_TO_GRID ) + { + x = (x+32) & -64; + y = (y+32) & -64; + } + } + } + + translate_array( num_points, subglyph2->zone.cur, x, y ); + + cur_to_org( num_points, &subglyph2->zone ); + + num_points = subglyph->zone.n_points; + num_contours = subglyph->zone.n_contours; + + /* check for last component */ + + if ( FILE_Seek( subglyph->file_offset ) ) + goto Fail_File; + + if ( subglyph->element_flag & MORE_COMPONENTS ) + phase = Load_Composite; + else + { + error = Load_Composite_End( num_points, + num_contours, + exec, + subglyph, + load_flags, + stream ); + if ( error ) + goto Fail; + + phase = Load_End; + } + } + else + phase = Load_Exit; + + break; + + + case Load_Exit: + break; + } + } + + /* finally, copy the points arrays to the glyph object */ + + exec->pts = base_pts; + + for ( u = 0; u < num_points + 2; u++ ) + { + glyph->outline.points[u] = exec->pts.cur[u]; + glyph->outline.flags [u] = exec->pts.touch[u]; + } + + for ( k = 0; k < num_contours; k++ ) + glyph->outline.contours[k] = exec->pts.contours[k]; + + glyph->outline.n_points = num_points; + glyph->outline.n_contours = num_contours; + glyph->outline.second_pass = TRUE; + + /* translate array so that (0,0) is the glyph's origin */ + translate_array( num_points + 2, + glyph->outline.points, + -subglyph->pp1.x, + 0 ); + + TT_Get_Outline_BBox( &glyph->outline, &glyph->metrics.bbox ); + + if ( subglyph->is_hinted ) + { + /* grid-fit the bounding box */ + glyph->metrics.bbox.xMin &= -64; + glyph->metrics.bbox.yMin &= -64; + glyph->metrics.bbox.xMax = (glyph->metrics.bbox.xMax+63) & -64; + glyph->metrics.bbox.yMax = (glyph->metrics.bbox.yMax+63) & -64; + } + + /* get the device-independent scaled horizontal metrics */ + /* take care of fixed-pitch fonts... */ + { + TT_Pos left_bearing; + TT_Pos advance; + + + left_bearing = subglyph->metrics.horiBearingX; + advance = subglyph->metrics.horiAdvance; + + if ( face->postscript.isFixedPitch ) + advance = face->horizontalHeader.advance_Width_Max; + + if ( load_flags & TTLOAD_SCALE_GLYPH ) + { + left_bearing = Scale_X( &exec->metrics, left_bearing ); + advance = Scale_X( &exec->metrics, advance ); + } + + glyph->metrics.linearHoriBearingX = left_bearing; + glyph->metrics.linearHoriAdvance = advance; + } + + glyph->metrics.horiBearingX = glyph->metrics.bbox.xMin; + glyph->metrics.horiBearingY = glyph->metrics.bbox.yMax; + glyph->metrics.horiAdvance = subglyph->pp2.x - subglyph->pp1.x; + + /* Now take care of vertical metrics. In the case where there is */ + /* no vertical information within the font (relatively common), make */ + /* up some metrics `by hand' ... */ + + { + Short top_bearing; /* vertical top side bearing (EM units) */ + UShort advance_height; /* vertical advance height (EM units) */ + + TT_Pos left; /* scaled vertical left side bearing */ + TT_Pos Top; /* scaled original vertical top side bearing */ + TT_Pos top; /* scaled vertical top side bearing */ + TT_Pos advance; /* scaled vertical advance height */ + + + /* Get the unscaled `tsb' and `ah' values */ + if ( face->verticalInfo && + face->verticalHeader.number_Of_VMetrics > 0 ) + { + /* Don't assume that both the vertical header and vertical */ + /* metrics are present in the same font :-) */ + + TT_Get_Metrics( (TT_Horizontal_Header*)&face->verticalHeader, + glyph_index, + &top_bearing, + &advance_height ); + } + else + { + /* Make up the distances from the horizontal header.. */ + + /* NOTE: The OS/2 values are the only `portable' ones, */ + /* which is why we use them... */ + /* */ + /* NOTE2: The sTypoDescender is negative, which is why */ + /* we compute the baseline-to-baseline distance */ + /* here with : */ + /* ascender - descender + linegap */ + /* */ + top_bearing = (Short) (face->os2.sTypoLineGap / 2); + advance_height = (UShort)(face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap); + } + + /* We must adjust the top_bearing value from the bounding box given + in the glyph header to te bounding box calculated with + TT_Get_Outline_BBox() */ + + /* scale the metrics */ + if ( load_flags & TTLOAD_SCALE_GLYPH ) + { + Top = Scale_Y( &exec->metrics, top_bearing ); + top = Scale_Y( &exec->metrics, + top_bearing + subglyph->metrics.bbox.yMax ) - + glyph->metrics.bbox.yMax; + advance = Scale_Y( &exec->metrics, advance_height ); + } + else + { + Top = top_bearing; + top = top_bearing + subglyph->metrics.bbox.yMax - + glyph->metrics.bbox.yMax; + advance = advance_height; + } + + glyph->metrics.linearVertBearingY = Top; + glyph->metrics.linearVertAdvance = advance; + + /* XXX : for now, we have no better algo for the lsb, but it should */ + /* work ok.. */ + /* */ + left = ( glyph->metrics.bbox.xMin - glyph->metrics.bbox.xMax ) / 2; + + /* grid-fit them if necessary */ + if ( subglyph->is_hinted ) + { + left &= -64; + top = (top + 63) & -64; + advance = (advance + 32) & -64; + } + + glyph->metrics.vertBearingX = left; + glyph->metrics.vertBearingY = top; + glyph->metrics.vertAdvance = advance; + } + + /* Adjust advance width to the value contained in the hdmx table. */ + if ( !exec->face->postscript.isFixedPitch && instance && + subglyph->is_hinted ) + { + widths = Get_Advance_Widths( exec->face, + exec->instance->metrics.x_ppem ); + if ( widths ) + glyph->metrics.horiAdvance = widths[glyph_index] << 6; + } + + glyph->outline.dropout_mode = (Char)exec->GS.scan_type; + + error = TT_Err_Ok; + + Fail_File: + Fail: + DONE_Stream( stream ); + + Fin: + + /* reset the execution context */ + exec->pts = base_pts; + + if ( !instance || !instance->debug ) + Done_Context( exec ); + + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttgload.h b/Build/source/libs/libttf/ttgload.h new file mode 100644 index 00000000000..cfdfb2c8cc9 --- /dev/null +++ b/Build/source/libs/libttf/ttgload.h @@ -0,0 +1,51 @@ +/******************************************************************* + * + * ttgload.h 1.0 + * + * TrueType Glyph Loader. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef TTGLOAD_H +#define TTGLOAD_H + +#include "ttconfig.h" +#include "tttypes.h" +#include "ttobjs.h" + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + void TT_Get_Metrics( TT_Horizontal_Header* header, + UShort index, + Short* bearing, + UShort* advance ); + + + LOCAL_DEF + TT_Error Load_TrueType_Glyph( PInstance instance, + PGlyph glyph, + UShort glyph_index, + UShort load_flags ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTGLOAD_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttinterp.c b/Build/source/libs/libttf/ttinterp.c new file mode 100644 index 00000000000..9158feca799 --- /dev/null +++ b/Build/source/libs/libttf/ttinterp.c @@ -0,0 +1,6654 @@ +/******************************************************************* + * + * ttinterp.c 3.1 + * + * TrueType bytecode intepreter. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * Changes between 3.1 and 3.0: + * + * - A more relaxed version of the interpreter. It is now able to + * ignore errors like out-of-bound array access and writes in order + * to silently support broken glyphs (even if the results are not + * always pretty). + * + * Note that one can use the flag TTLOAD_PEDANTIC to force + * TrueType-compliant interpretation. + * + * - A big #if used to completely disable the interpreter, which + * is due to the Apple patents issues which emerged recently. + * + ******************************************************************/ + +#include "freetype.h" +#include "tttypes.h" +#include "ttdebug.h" +#include "ttcalc.h" +#include "ttmemory.h" +#include "ttinterp.h" + + +#ifdef TT_CONFIG_OPTION_NO_INTERPRETER + + LOCAL_FUNC + TT_Error RunIns( PExecution_Context exc ) + { + /* do nothing - always successful */ + (void)exc; + return TT_Err_Ok; + } + +#else + + +#ifdef DEBUG_INTERPRETER +#include <memory.h> +#include "ttdebug.h" + +/* Define the `getch()' function. On Unix systems, it is an alias */ +/* for `getchar()', and the debugger front end must ensure that the */ +/* `stdin' file descriptor is not in line-by-line input mode. */ +#ifdef OS2 +#include <conio.h> +#else +#define getch getchar +#endif + +#endif /* DEBUG_INTEPRETER */ + + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_interp + + +/* In order to detect infinite loops in the code, we set-up */ +/* a counter within the run loop. a singly stroke of interpretation */ +/* is now limited to a maximum number of opcodes defined below.. */ +/* */ +#define MAX_RUNNABLE_OPCODES 1000000 + + +/* There are two kinds of implementations there: */ +/* */ +/* a. static implementation: */ +/* */ +/* The current execution context is a static variable, */ +/* which fields are accessed directly by the interpreter */ +/* during execution. The context is named 'cur'. */ +/* */ +/* This version is non-reentrant, of course. */ +/* */ +/* */ +/* b. indirect implementation: */ +/* */ +/* The current execution context is passed to _each_ */ +/* function as its first argument, and each field is */ +/* thus accessed indirectly. */ +/* */ +/* This version is, however, fully re-entrant. */ +/* */ +/* */ +/* The idea is that an indirect implementation may be */ +/* slower to execute on the low-end processors that are */ +/* used in some systems (like 386s or even 486s). */ +/* */ +/* When the interpreter started, we had no idea of the */ +/* time that glyph hinting (i.e. executing instructions) */ +/* could take in the whole process of rendering a glyph, */ +/* and a 10 to 30% performance penalty on low-end systems */ +/* didn't seem much of a good idea. This question led us */ +/* to provide two distinct builds of the C version from */ +/* a single source, with the use of macros (again). */ +/* */ +/* Now that the engine is working (and working really */ +/* well!), it seems that the greatest time-consuming */ +/* factors are: file i/o, glyph loading, rasterizing and */ +/* _then_ glyph hinting! */ +/* */ +/* Tests performed with two versions of the 'fttimer' */ +/* program seem to indicate that hinting takes less than 5% */ +/* of the rendering process, which is dominated by glyph */ +/* loading and scan-line conversion by an high order of */ +/* magnitude. */ +/* */ +/* As a consequence, the indirect implementation is now the */ +/* default, as its performance costs can be considered */ +/* negligible in our context. Note, however, that we */ +/* kept the same source with macros because: */ +/* */ +/* - the code is kept very close in design to the */ +/* Pascal one used for development. */ +/* */ +/* - it's much more readable that way! */ +/* */ +/* - it's still open to later experimentation and tuning */ + + + +#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */ + +#define CUR (*exc) /* see ttobjs.h */ + +#else /* static implementation */ + +#define CUR cur + + static TExecution_Context cur; /* static exec. context variable */ + + /* apparently, we have a _lot_ of direct indexing when accessing */ + /* the static 'cur', which makes the code bigger (due to all the */ + /* four bytes addresses). */ + +#endif /* !TT_CONFIG_OPTION_STATIC_INTERPRETER */ + + +#define INS_ARG EXEC_OPS PStorage args /* see ttobjs.h */ + +#define SKIP_Code() SkipCode( EXEC_ARG ) + +#define GET_ShortIns() GetShortIns( EXEC_ARG ) + +#define COMPUTE_Funcs() Compute_Funcs( EXEC_ARG ) + +#define NORMalize( x, y, v ) Normalize( EXEC_ARGS x, y, v ) + +#define SET_SuperRound( scale, flags ) \ + SetSuperRound( EXEC_ARGS scale, flags ) + +#define INS_Goto_CodeRange( range, ip ) \ + Ins_Goto_CodeRange( EXEC_ARGS range, ip ) + +#define CUR_Func_project( x, y ) CUR.func_project( EXEC_ARGS x, y ) +#define CUR_Func_move( z, p, d ) CUR.func_move( EXEC_ARGS z, p, d ) +#define CUR_Func_dualproj( x, y ) CUR.func_dualproj( EXEC_ARGS x, y ) +#define CUR_Func_freeProj( x, y ) CUR.func_freeProj( EXEC_ARGS x, y ) +#define CUR_Func_round( d, c ) CUR.func_round( EXEC_ARGS d, c ) + +#define CUR_Func_read_cvt( index ) \ + CUR.func_read_cvt( EXEC_ARGS index ) + +#define CUR_Func_write_cvt( index, val ) \ + CUR.func_write_cvt( EXEC_ARGS index, val ) + +#define CUR_Func_move_cvt( index, val ) \ + CUR.func_move_cvt( EXEC_ARGS index, val ) + +#define CURRENT_Ratio() Current_Ratio( EXEC_ARG ) +#define CURRENT_Ppem() Current_Ppem( EXEC_ARG ) + +#define CALC_Length() Calc_Length( EXEC_ARG ) + +#define INS_SxVTL( a, b, c, d ) Ins_SxVTL( EXEC_ARGS a, b, c, d ) + +#define COMPUTE_Point_Displacement( a, b, c, d ) \ + Compute_Point_Displacement( EXEC_ARGS a, b, c, d ) + +#define MOVE_Zp2_Point( a, b, c, t ) Move_Zp2_Point( EXEC_ARGS a, b, c, t ) + +#define CUR_Ppem() Cur_PPEM( EXEC_ARG ) + + /* Instruction dispatch function, as used by the interpreter */ + typedef void (*TInstruction_Function)( INS_ARG ); + +#define BOUNDS( x, n ) ( (x) >= (n) ) + + + +/*********************************************************************/ +/* */ +/* Before an opcode is executed, the interpreter verifies that */ +/* there are enough arguments on the stack, with the help of */ +/* the Pop_Push_Count table. */ +/* */ +/* For each opcode, the first column gives the number of arguments */ +/* that are popped from the stack; the second one gives the number */ +/* of those that are pushed in result. */ +/* */ +/* Note that for opcodes with a varying number of parameters, */ +/* either 0 or 1 arg is verified before execution, depending */ +/* on the nature of the instruction: */ +/* */ +/* - if the number of arguments is given by the bytecode */ +/* stream or the loop variable, 0 is chosen. */ +/* */ +/* - if the first argument is a count n that is followed */ +/* by arguments a1..an, then 1 is chosen. */ +/* */ +/*********************************************************************/ + +#undef PACK +#define PACK( x, y ) ((x << 4) | y) + + static const Byte Pop_Push_Count[256] = + { + /* opcodes are gathered in groups of 16 */ + /* please keep the spaces as they are */ + + /* SVTCA y */ PACK( 0, 0 ), + /* SVTCA x */ PACK( 0, 0 ), + /* SPvTCA y */ PACK( 0, 0 ), + /* SPvTCA x */ PACK( 0, 0 ), + /* SFvTCA y */ PACK( 0, 0 ), + /* SFvTCA x */ PACK( 0, 0 ), + /* SPvTL // */ PACK( 2, 0 ), + /* SPvTL + */ PACK( 2, 0 ), + /* SFvTL // */ PACK( 2, 0 ), + /* SFvTL + */ PACK( 2, 0 ), + /* SPvFS */ PACK( 2, 0 ), + /* SFvFS */ PACK( 2, 0 ), + /* GPV */ PACK( 0, 2 ), + /* GFV */ PACK( 0, 2 ), + /* SFvTPv */ PACK( 0, 0 ), + /* ISECT */ PACK( 5, 0 ), + + /* SRP0 */ PACK( 1, 0 ), + /* SRP1 */ PACK( 1, 0 ), + /* SRP2 */ PACK( 1, 0 ), + /* SZP0 */ PACK( 1, 0 ), + /* SZP1 */ PACK( 1, 0 ), + /* SZP2 */ PACK( 1, 0 ), + /* SZPS */ PACK( 1, 0 ), + /* SLOOP */ PACK( 1, 0 ), + /* RTG */ PACK( 0, 0 ), + /* RTHG */ PACK( 0, 0 ), + /* SMD */ PACK( 1, 0 ), + /* ELSE */ PACK( 0, 0 ), + /* JMPR */ PACK( 1, 0 ), + /* SCvTCi */ PACK( 1, 0 ), + /* SSwCi */ PACK( 1, 0 ), + /* SSW */ PACK( 1, 0 ), + + /* DUP */ PACK( 1, 2 ), + /* POP */ PACK( 1, 0 ), + /* CLEAR */ PACK( 0, 0 ), + /* SWAP */ PACK( 2, 2 ), + /* DEPTH */ PACK( 0, 1 ), + /* CINDEX */ PACK( 1, 1 ), + /* MINDEX */ PACK( 1, 0 ), + /* AlignPTS */ PACK( 2, 0 ), + /* INS_$28 */ PACK( 0, 0 ), + /* UTP */ PACK( 1, 0 ), + /* LOOPCALL */ PACK( 2, 0 ), + /* CALL */ PACK( 1, 0 ), + /* FDEF */ PACK( 1, 0 ), + /* ENDF */ PACK( 0, 0 ), + /* MDAP[0] */ PACK( 1, 0 ), + /* MDAP[1] */ PACK( 1, 0 ), + + /* IUP[0] */ PACK( 0, 0 ), + /* IUP[1] */ PACK( 0, 0 ), + /* SHP[0] */ PACK( 0, 0 ), + /* SHP[1] */ PACK( 0, 0 ), + /* SHC[0] */ PACK( 1, 0 ), + /* SHC[1] */ PACK( 1, 0 ), + /* SHZ[0] */ PACK( 1, 0 ), + /* SHZ[1] */ PACK( 1, 0 ), + /* SHPIX */ PACK( 1, 0 ), + /* IP */ PACK( 0, 0 ), + /* MSIRP[0] */ PACK( 2, 0 ), + /* MSIRP[1] */ PACK( 2, 0 ), + /* AlignRP */ PACK( 0, 0 ), + /* RTDG */ PACK( 0, 0 ), + /* MIAP[0] */ PACK( 2, 0 ), + /* MIAP[1] */ PACK( 2, 0 ), + + /* NPushB */ PACK( 0, 0 ), + /* NPushW */ PACK( 0, 0 ), + /* WS */ PACK( 2, 0 ), + /* RS */ PACK( 1, 1 ), + /* WCvtP */ PACK( 2, 0 ), + /* RCvt */ PACK( 1, 1 ), + /* GC[0] */ PACK( 1, 1 ), + /* GC[1] */ PACK( 1, 1 ), + /* SCFS */ PACK( 2, 0 ), + /* MD[0] */ PACK( 2, 1 ), + /* MD[1] */ PACK( 2, 1 ), + /* MPPEM */ PACK( 0, 1 ), + /* MPS */ PACK( 0, 1 ), + /* FlipON */ PACK( 0, 0 ), + /* FlipOFF */ PACK( 0, 0 ), + /* DEBUG */ PACK( 1, 0 ), + + /* LT */ PACK( 2, 1 ), + /* LTEQ */ PACK( 2, 1 ), + /* GT */ PACK( 2, 1 ), + /* GTEQ */ PACK( 2, 1 ), + /* EQ */ PACK( 2, 1 ), + /* NEQ */ PACK( 2, 1 ), + /* ODD */ PACK( 1, 1 ), + /* EVEN */ PACK( 1, 1 ), + /* IF */ PACK( 1, 0 ), + /* EIF */ PACK( 0, 0 ), + /* AND */ PACK( 2, 1 ), + /* OR */ PACK( 2, 1 ), + /* NOT */ PACK( 1, 1 ), + /* DeltaP1 */ PACK( 1, 0 ), + /* SDB */ PACK( 1, 0 ), + /* SDS */ PACK( 1, 0 ), + + /* ADD */ PACK( 2, 1 ), + /* SUB */ PACK( 2, 1 ), + /* DIV */ PACK( 2, 1 ), + /* MUL */ PACK( 2, 1 ), + /* ABS */ PACK( 1, 1 ), + /* NEG */ PACK( 1, 1 ), + /* FLOOR */ PACK( 1, 1 ), + /* CEILING */ PACK( 1, 1 ), + /* ROUND[0] */ PACK( 1, 1 ), + /* ROUND[1] */ PACK( 1, 1 ), + /* ROUND[2] */ PACK( 1, 1 ), + /* ROUND[3] */ PACK( 1, 1 ), + /* NROUND[0] */ PACK( 1, 1 ), + /* NROUND[1] */ PACK( 1, 1 ), + /* NROUND[2] */ PACK( 1, 1 ), + /* NROUND[3] */ PACK( 1, 1 ), + + /* WCvtF */ PACK( 2, 0 ), + /* DeltaP2 */ PACK( 1, 0 ), + /* DeltaP3 */ PACK( 1, 0 ), + /* DeltaCn[0] */ PACK( 1, 0 ), + /* DeltaCn[1] */ PACK( 1, 0 ), + /* DeltaCn[2] */ PACK( 1, 0 ), + /* SROUND */ PACK( 1, 0 ), + /* S45Round */ PACK( 1, 0 ), + /* JROT */ PACK( 2, 0 ), + /* JROF */ PACK( 2, 0 ), + /* ROFF */ PACK( 0, 0 ), + /* INS_$7B */ PACK( 0, 0 ), + /* RUTG */ PACK( 0, 0 ), + /* RDTG */ PACK( 0, 0 ), + /* SANGW */ PACK( 1, 0 ), + /* AA */ PACK( 1, 0 ), + + /* FlipPT */ PACK( 0, 0 ), + /* FlipRgON */ PACK( 2, 0 ), + /* FlipRgOFF */ PACK( 2, 0 ), + /* INS_$83 */ PACK( 0, 0 ), + /* INS_$84 */ PACK( 0, 0 ), + /* ScanCTRL */ PACK( 1, 0 ), + /* SDVPTL[0] */ PACK( 2, 0 ), + /* SDVPTL[1] */ PACK( 2, 0 ), + /* GetINFO */ PACK( 1, 1 ), + /* IDEF */ PACK( 1, 0 ), + /* ROLL */ PACK( 3, 3 ), + /* MAX */ PACK( 2, 1 ), + /* MIN */ PACK( 2, 1 ), + /* ScanTYPE */ PACK( 1, 0 ), + /* InstCTRL */ PACK( 2, 0 ), + /* INS_$8F */ PACK( 0, 0 ), + + /* INS_$90 */ PACK( 0, 0 ), + /* INS_$91 */ PACK( 0, 0 ), + /* INS_$92 */ PACK( 0, 0 ), + /* INS_$93 */ PACK( 0, 0 ), + /* INS_$94 */ PACK( 0, 0 ), + /* INS_$95 */ PACK( 0, 0 ), + /* INS_$96 */ PACK( 0, 0 ), + /* INS_$97 */ PACK( 0, 0 ), + /* INS_$98 */ PACK( 0, 0 ), + /* INS_$99 */ PACK( 0, 0 ), + /* INS_$9A */ PACK( 0, 0 ), + /* INS_$9B */ PACK( 0, 0 ), + /* INS_$9C */ PACK( 0, 0 ), + /* INS_$9D */ PACK( 0, 0 ), + /* INS_$9E */ PACK( 0, 0 ), + /* INS_$9F */ PACK( 0, 0 ), + + /* INS_$A0 */ PACK( 0, 0 ), + /* INS_$A1 */ PACK( 0, 0 ), + /* INS_$A2 */ PACK( 0, 0 ), + /* INS_$A3 */ PACK( 0, 0 ), + /* INS_$A4 */ PACK( 0, 0 ), + /* INS_$A5 */ PACK( 0, 0 ), + /* INS_$A6 */ PACK( 0, 0 ), + /* INS_$A7 */ PACK( 0, 0 ), + /* INS_$A8 */ PACK( 0, 0 ), + /* INS_$A9 */ PACK( 0, 0 ), + /* INS_$AA */ PACK( 0, 0 ), + /* INS_$AB */ PACK( 0, 0 ), + /* INS_$AC */ PACK( 0, 0 ), + /* INS_$AD */ PACK( 0, 0 ), + /* INS_$AE */ PACK( 0, 0 ), + /* INS_$AF */ PACK( 0, 0 ), + + /* PushB[0] */ PACK( 0, 1 ), + /* PushB[1] */ PACK( 0, 2 ), + /* PushB[2] */ PACK( 0, 3 ), + /* PushB[3] */ PACK( 0, 4 ), + /* PushB[4] */ PACK( 0, 5 ), + /* PushB[5] */ PACK( 0, 6 ), + /* PushB[6] */ PACK( 0, 7 ), + /* PushB[7] */ PACK( 0, 8 ), + /* PushW[0] */ PACK( 0, 1 ), + /* PushW[1] */ PACK( 0, 2 ), + /* PushW[2] */ PACK( 0, 3 ), + /* PushW[3] */ PACK( 0, 4 ), + /* PushW[4] */ PACK( 0, 5 ), + /* PushW[5] */ PACK( 0, 6 ), + /* PushW[6] */ PACK( 0, 7 ), + /* PushW[7] */ PACK( 0, 8 ), + + /* MDRP[00] */ PACK( 1, 0 ), + /* MDRP[01] */ PACK( 1, 0 ), + /* MDRP[02] */ PACK( 1, 0 ), + /* MDRP[03] */ PACK( 1, 0 ), + /* MDRP[04] */ PACK( 1, 0 ), + /* MDRP[05] */ PACK( 1, 0 ), + /* MDRP[06] */ PACK( 1, 0 ), + /* MDRP[07] */ PACK( 1, 0 ), + /* MDRP[08] */ PACK( 1, 0 ), + /* MDRP[09] */ PACK( 1, 0 ), + /* MDRP[10] */ PACK( 1, 0 ), + /* MDRP[11] */ PACK( 1, 0 ), + /* MDRP[12] */ PACK( 1, 0 ), + /* MDRP[13] */ PACK( 1, 0 ), + /* MDRP[14] */ PACK( 1, 0 ), + /* MDRP[15] */ PACK( 1, 0 ), + + /* MDRP[16] */ PACK( 1, 0 ), + /* MDRP[17] */ PACK( 1, 0 ), + /* MDRP[18] */ PACK( 1, 0 ), + /* MDRP[19] */ PACK( 1, 0 ), + /* MDRP[20] */ PACK( 1, 0 ), + /* MDRP[21] */ PACK( 1, 0 ), + /* MDRP[22] */ PACK( 1, 0 ), + /* MDRP[23] */ PACK( 1, 0 ), + /* MDRP[24] */ PACK( 1, 0 ), + /* MDRP[25] */ PACK( 1, 0 ), + /* MDRP[26] */ PACK( 1, 0 ), + /* MDRP[27] */ PACK( 1, 0 ), + /* MDRP[28] */ PACK( 1, 0 ), + /* MDRP[29] */ PACK( 1, 0 ), + /* MDRP[30] */ PACK( 1, 0 ), + /* MDRP[31] */ PACK( 1, 0 ), + + /* MIRP[00] */ PACK( 2, 0 ), + /* MIRP[01] */ PACK( 2, 0 ), + /* MIRP[02] */ PACK( 2, 0 ), + /* MIRP[03] */ PACK( 2, 0 ), + /* MIRP[04] */ PACK( 2, 0 ), + /* MIRP[05] */ PACK( 2, 0 ), + /* MIRP[06] */ PACK( 2, 0 ), + /* MIRP[07] */ PACK( 2, 0 ), + /* MIRP[08] */ PACK( 2, 0 ), + /* MIRP[09] */ PACK( 2, 0 ), + /* MIRP[10] */ PACK( 2, 0 ), + /* MIRP[11] */ PACK( 2, 0 ), + /* MIRP[12] */ PACK( 2, 0 ), + /* MIRP[13] */ PACK( 2, 0 ), + /* MIRP[14] */ PACK( 2, 0 ), + /* MIRP[15] */ PACK( 2, 0 ), + + /* MIRP[16] */ PACK( 2, 0 ), + /* MIRP[17] */ PACK( 2, 0 ), + /* MIRP[18] */ PACK( 2, 0 ), + /* MIRP[19] */ PACK( 2, 0 ), + /* MIRP[20] */ PACK( 2, 0 ), + /* MIRP[21] */ PACK( 2, 0 ), + /* MIRP[22] */ PACK( 2, 0 ), + /* MIRP[23] */ PACK( 2, 0 ), + /* MIRP[24] */ PACK( 2, 0 ), + /* MIRP[25] */ PACK( 2, 0 ), + /* MIRP[26] */ PACK( 2, 0 ), + /* MIRP[27] */ PACK( 2, 0 ), + /* MIRP[28] */ PACK( 2, 0 ), + /* MIRP[29] */ PACK( 2, 0 ), + /* MIRP[30] */ PACK( 2, 0 ), + /* MIRP[31] */ PACK( 2, 0 ) + }; + + static const TT_Vector Null_Vector = {0,0}; + +#undef NULL_Vector +#define NULL_Vector (TT_Vector*)&Null_Vector + +/******************************************************************* + * + * Function : Norm + * + * Description : Returns the norm (length) of a vector. + * + * Input : X, Y vector + * + * Output : Returns length in F26dot6. + * + *****************************************************************/ + + static TT_F26Dot6 Norm( TT_F26Dot6 X, TT_F26Dot6 Y ) + { + TT_Int64 T1, T2; + + + MUL_64( X, X, T1 ); + MUL_64( Y, Y, T2 ); + + ADD_64( T1, T2, T1 ); + + return (TT_F26Dot6)SQRT_64( T1 ); + } + + +/******************************************************************* + * + * Function : FUnits_To_Pixels + * + * Description : Scale a distance in FUnits to pixel coordinates. + * + * Input : Distance in FUnits + * + * Output : Distance in 26.6 format. + * + *****************************************************************/ + + static TT_F26Dot6 FUnits_To_Pixels( EXEC_OPS Short distance ) + { + return TT_MulDiv( distance, + CUR.metrics.scale1, + CUR.metrics.scale2 ); + } + + +/******************************************************************* + * + * Function : Current_Ratio + * + * Description : Return the current aspect ratio scaling factor + * depending on the projection vector's state and + * device resolutions. + * + * Input : None + * + * Output : Aspect ratio in 16.16 format, always <= 1.0 . + * + *****************************************************************/ + + static Long Current_Ratio( EXEC_OP ) + { + if ( CUR.metrics.ratio ) + return CUR.metrics.ratio; + + if ( CUR.GS.projVector.y == 0 ) + CUR.metrics.ratio = CUR.metrics.x_ratio; + + else if ( CUR.GS.projVector.x == 0 ) + CUR.metrics.ratio = CUR.metrics.y_ratio; + + else + { + Long x, y; + + + x = TT_MulDiv( CUR.GS.projVector.x, CUR.metrics.x_ratio, 0x4000 ); + y = TT_MulDiv( CUR.GS.projVector.y, CUR.metrics.y_ratio, 0x4000 ); + CUR.metrics.ratio = Norm( x, y ); + } + + return CUR.metrics.ratio; + } + + + static Long Current_Ppem( EXEC_OP ) + { + return TT_MulFix( CUR.metrics.ppem, CURRENT_Ratio() ); + } + + + static TT_F26Dot6 Read_CVT( EXEC_OPS ULong index ) + { + return CUR.cvt[index]; + } + + + static TT_F26Dot6 Read_CVT_Stretched( EXEC_OPS ULong index ) + { + return TT_MulFix( CUR.cvt[index], CURRENT_Ratio() ); + } + + + static void Write_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) + { + CUR.cvt[index] = value; + } + + static void Write_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) + { + CUR.cvt[index] = TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); + } + + + static void Move_CVT( EXEC_OPS ULong index, TT_F26Dot6 value ) + { + CUR.cvt[index] += value; + } + + static void Move_CVT_Stretched( EXEC_OPS ULong index, TT_F26Dot6 value ) + { + CUR.cvt[index] += TT_MulDiv( value, 0x10000, CURRENT_Ratio() ); + } + + +/****************************************************************** + * + * Function : Calc_Length + * + * Description : Computes the length in bytes of current opcode. + * + *****************************************************************/ + + static Bool Calc_Length( EXEC_OP ) + { + CUR.opcode = CUR.code[CUR.IP]; + + switch ( CUR.opcode ) + { + case 0x40: + if ( CUR.IP + 1 >= CUR.codeSize ) + return FAILURE; + + CUR.length = CUR.code[CUR.IP + 1] + 2; + break; + + case 0x41: + if ( CUR.IP + 1 >= CUR.codeSize ) + return FAILURE; + + CUR.length = CUR.code[CUR.IP + 1] * 2 + 2; + break; + + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + CUR.length = CUR.opcode - 0xB0 + 2; + break; + + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + CUR.length = (CUR.opcode - 0xB8) * 2 + 3; + break; + + default: + CUR.length = 1; + break; + } + + /* make sure result is in range */ + + if ( CUR.IP + CUR.length > CUR.codeSize ) + return FAILURE; + + return SUCCESS; + } + + +/******************************************************************* + * + * Function : GetShortIns + * + * Description : Returns a short integer taken from the instruction + * stream at address IP. + * + * Input : None + * + * Output : Short read at Code^[IP..IP+1] + * + * Notes : This one could become a Macro in the C version. + * + *****************************************************************/ + + static Short GetShortIns( EXEC_OP ) + { + /* Reading a byte stream so there is no endianess (DaveP) */ + CUR.IP += 2; + return (Short)((CUR.code[CUR.IP - 2] << 8) + CUR.code[CUR.IP - 1]); + } + + +/******************************************************************* + * + * Function : Ins_Goto_CodeRange + * + * Description : Goes to a certain code range in the instruction + * stream. + * + * + * Input : aRange + * aIP + * + * Output : SUCCESS or FAILURE. + * + *****************************************************************/ + + static Bool Ins_Goto_CodeRange( EXEC_OPS Int aRange, ULong aIP ) + { + TCodeRange* WITH; + + + if ( aRange < 1 || aRange > 3 ) + { + CUR.error = TT_Err_Bad_Argument; + return FAILURE; + } + + WITH = &CUR.codeRangeTable[aRange - 1]; + + if ( WITH->Base == NULL ) /* invalid coderange */ + { + CUR.error = TT_Err_Invalid_CodeRange; + return FAILURE; + } + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for aIP <= Size, instead of aIP < Size. */ + + if ( aIP > WITH->Size ) + { + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + CUR.code = WITH->Base; + CUR.codeSize = WITH->Size; + CUR.IP = aIP; + CUR.curRange = aRange; + + return SUCCESS; + } + + +/******************************************************************* + * + * Function : Direct_Move + * + * Description : Moves a point by a given distance along the + * freedom vector. The point will be touched. + * + * Input : point index of point to move + * distance distance to apply + * zone affected glyph zone + * + * Output : None + * + *****************************************************************/ + + static void Direct_Move( EXEC_OPS PGlyph_Zone zone, + UShort point, + TT_F26Dot6 distance ) + { + TT_F26Dot6 v; + + + v = CUR.GS.freeVector.x; + + if ( v != 0 ) + { + zone->cur[point].x += TT_MulDiv( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->touch[point] |= TT_Flag_Touched_X; + } + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + { + zone->cur[point].y += TT_MulDiv( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->touch[point] |= TT_Flag_Touched_Y; + } + } + + +/******************************************************************/ +/* */ +/* The following versions are used whenever both vectors are both */ +/* along one of the coordinate unit vectors, i.e. in 90% cases. */ +/* */ +/******************************************************************/ + +/******************************************************************* + * Direct_Move_X + * + *******************************************************************/ + + static void Direct_Move_X( EXEC_OPS PGlyph_Zone zone, + UShort point, + TT_F26Dot6 distance ) + { + zone->cur[point].x += distance; + zone->touch[point] |= TT_Flag_Touched_X; + } + + +/******************************************************************* + * Direct_Move_Y + * + *******************************************************************/ + + static void Direct_Move_Y( EXEC_OPS PGlyph_Zone zone, + UShort point, + TT_F26Dot6 distance ) + { + zone->cur[point].y += distance; + zone->touch[point] |= TT_Flag_Touched_Y; + } + + +/******************************************************************* + * + * Function : Round_None + * + * Description : Does not round, but adds engine compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : rounded distance. + * + * NOTE : The spec says very few about the relationship between + * rounding and engine compensation. However, it seems + * from the description of super round that we should + * should add the compensation before rounding. + * + ******************************************************************/ + + static TT_F26Dot6 Round_None( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( val < 0 ) + val = 0; + } + else { + val = distance - compensation; + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_To_Grid + * + * Description : Rounds value to grid after adding engine + * compensation + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + *****************************************************************/ + + static TT_F26Dot6 Round_To_Grid( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = distance + compensation + 32; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( (compensation - distance + 32) & (-64) ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_To_Half_Grid + * + * Description : Rounds value to half grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + *****************************************************************/ + + static TT_F26Dot6 Round_To_Half_Grid( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ((distance + compensation) & (-64)) + 32; + if ( val < 0 ) + val = 0; + } + else + { + val = -( ((compensation - distance) & (-64)) + 32 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_Down_To_Grid + * + * Description : Rounds value down to grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + *****************************************************************/ + + static TT_F26Dot6 Round_Down_To_Grid( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( (compensation - distance) & (-64) ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_Up_To_Grid + * + * Description : Rounds value up to grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + *****************************************************************/ + + static TT_F26Dot6 Round_Up_To_Grid( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = distance + compensation + 63; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( (compensation - distance + 63) & (-64) ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_To_Double_Grid + * + * Description : Rounds value to double grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + *****************************************************************/ + + static TT_F26Dot6 Round_To_Double_Grid( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = distance + compensation + 16; + if ( val > 0 ) + val &= ~31; + else + val = 0; + } + else + { + val = -( (compensation - distance + 16) & (-32) ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_Super + * + * Description : Super-rounds value to grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + * NOTE : The spec says very few about the relationship between + * rounding and engine compensation. However, it seems + * from the description of super round that we should + * should add the compensation before rounding. + * + *****************************************************************/ + + static TT_F26Dot6 Round_Super( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = (distance - CUR.phase + CUR.threshold + compensation) & + (-CUR.period); + if ( val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( (CUR.threshold - CUR.phase - distance + compensation) & + (-CUR.period) ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + +/******************************************************************* + * + * Function : Round_Super_45 + * + * Description : Super-rounds value to grid after adding engine + * compensation. + * + * Input : distance : distance to round + * compensation : engine compensation + * + * Output : Rounded distance. + * + * NOTE : There is a separate function for Round_Super_45 as we + * may need a greater precision. + * + *****************************************************************/ + + static TT_F26Dot6 Round_Super_45( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ) + { + TT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ( (distance - CUR.phase + CUR.threshold + compensation) / + CUR.period ) * CUR.period; + if ( val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( ( (CUR.threshold - CUR.phase - distance + compensation) / + CUR.period ) * CUR.period ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + +/******************************************************************* + * Compute_Round + * + *****************************************************************/ + + static void Compute_Round( EXEC_OPS Byte round_mode ) + { + switch ( round_mode ) + { + case TT_Round_Off: + CUR.func_round = (TRound_Function)Round_None; + break; + + case TT_Round_To_Grid: + CUR.func_round = (TRound_Function)Round_To_Grid; + break; + + case TT_Round_Up_To_Grid: + CUR.func_round = (TRound_Function)Round_Up_To_Grid; + break; + + case TT_Round_Down_To_Grid: + CUR.func_round = (TRound_Function)Round_Down_To_Grid; + break; + + case TT_Round_To_Half_Grid: + CUR.func_round = (TRound_Function)Round_To_Half_Grid; + break; + + case TT_Round_To_Double_Grid: + CUR.func_round = (TRound_Function)Round_To_Double_Grid; + break; + + case TT_Round_Super: + CUR.func_round = (TRound_Function)Round_Super; + break; + + case TT_Round_Super_45: + CUR.func_round = (TRound_Function)Round_Super_45; + break; + } + } + + +/******************************************************************* + * + * Function : SetSuperRound + * + * Description : Sets Super Round parameters. + * + * Input : GridPeriod Grid period + * selector SROUND opcode + * + * Output : None. + * + *****************************************************************/ + + static void SetSuperRound( EXEC_OPS TT_F26Dot6 GridPeriod, + Long selector ) + { + switch ( (Int)(selector & 0xC0) ) + { + case 0: + CUR.period = GridPeriod / 2; + break; + + case 0x40: + CUR.period = GridPeriod; + break; + + case 0x80: + CUR.period = GridPeriod * 2; + break; + + /* This opcode is reserved, but... */ + + case 0xC0: + CUR.period = GridPeriod; + break; + } + + switch ( (Int)(selector & 0x30) ) + { + case 0: + CUR.phase = 0; + break; + + case 0x10: + CUR.phase = CUR.period / 4; + break; + + case 0x20: + CUR.phase = CUR.period / 2; + break; + + case 0x30: + CUR.phase = GridPeriod * 3 / 4; + break; + } + + if ( (selector & 0x0F) == 0 ) + CUR.threshold = CUR.period - 1; + else + CUR.threshold = ( (Int)(selector & 0x0F) - 4 ) * CUR.period / 8; + + CUR.period /= 256; + CUR.phase /= 256; + CUR.threshold /= 256; + } + + +/******************************************************************* + * + * Function : Project + * + * Description : Computes the projection of vector given by (v2-v1) + * along the current projection vector. + * + * Input : v1, v2 input vector + * + * Output : Returns distance in F26dot6 format. + * + *****************************************************************/ + + static TT_F26Dot6 Project( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ) + { + TT_Int64 T1, T2; + + + MUL_64( v1->x - v2->x, CUR.GS.projVector.x, T1 ); + MUL_64( v1->y - v2->y, CUR.GS.projVector.y, T2 ); + + ADD_64( T1, T2, T1 ); + + return (TT_F26Dot6)DIV_64( T1, 0x4000L ); + } + + +/******************************************************************* + * + * Function : Dual_Project + * + * Description : Computes the projection of the vector given by + * (v2-v1) along the current dual vector. + * + * Input : v1, v2 input vector + * + * Output : Returns distance in F26dot6 format. + * + *****************************************************************/ + + static TT_F26Dot6 Dual_Project( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ) + { + TT_Int64 T1, T2; + + + MUL_64( v1->x - v2->x, CUR.GS.dualVector.x, T1 ); + MUL_64( v1->y - v2->y, CUR.GS.dualVector.y, T2 ); + + ADD_64( T1, T2, T1 ); + + return (TT_F26Dot6)DIV_64( T1, 0x4000L ); + } + + +/******************************************************************* + * + * Function : Free_Project + * + * Description : Computes the projection of the vector given by + * (v2-v1) along the current freedom vector. + * + * Input : v1, v2 input vector + * + * Output : Returns distance in F26dot6 format. + * + *****************************************************************/ + + static TT_F26Dot6 Free_Project( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ) + { + TT_Int64 T1, T2; + + + MUL_64( v1->x - v2->x, CUR.GS.freeVector.x, T1 ); + MUL_64( v1->y - v2->y, CUR.GS.freeVector.y, T2 ); + + ADD_64( T1, T2, T1 ); + + return (TT_F26Dot6)DIV_64( T1, 0x4000L ); + } + + +/******************************************************************* + * + * Function : Project_x + * + * Input : Vx, Vy input vector + * + * Output : Returns Vx. + * + * Note : Used as a dummy function. + * + *****************************************************************/ + + static TT_F26Dot6 Project_x( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ) + { + return (v1->x - v2->x); + } + + +/******************************************************************* + * + * Function : Project_y + * + * Input : Vx, Vy input vector + * + * Output : Returns Vy. + * + * Note : Used as a dummy function. + * + *****************************************************************/ + + static TT_F26Dot6 Project_y( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ) + { + return (v1->y - v2->y); + } + + +/******************************************************************* + * + * Function : Compute_Funcs + * + * Description : Computes the projections and movement function + * pointers according to the current graphics state. + * + * Input : None + * + *****************************************************************/ + + static void Compute_Funcs( EXEC_OP ) + { + if ( CUR.GS.freeVector.x == 0x4000 ) + { + CUR.func_freeProj = (TProject_Function)Project_x; + CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; + } + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + { + CUR.func_freeProj = (TProject_Function)Project_y; + CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; + } + else + { + CUR.func_freeProj = (TProject_Function)Free_Project; + CUR.F_dot_P = (Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + + (Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; + } + } + + CUR.cached_metrics = FALSE; + + if ( CUR.GS.projVector.x == 0x4000 ) + CUR.func_project = (TProject_Function)Project_x; + else + { + if ( CUR.GS.projVector.y == 0x4000 ) + CUR.func_project = (TProject_Function)Project_y; + else + CUR.func_project = (TProject_Function)Project; + } + + if ( CUR.GS.dualVector.x == 0x4000 ) + CUR.func_dualproj = (TProject_Function)Project_x; + else + { + if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = (TProject_Function)Project_y; + else + CUR.func_dualproj = (TProject_Function)Dual_Project; + } + + CUR.func_move = (TMove_Function)Direct_Move; + + if ( CUR.F_dot_P == 0x40000000L ) + { + if ( CUR.GS.freeVector.x == 0x4000 ) + CUR.func_move = (TMove_Function)Direct_Move_X; + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + CUR.func_move = (TMove_Function)Direct_Move_Y; + } + } + + /* at small sizes, F_dot_P can become too small, resulting */ + /* in overflows and 'spikes' in a number of glyphs like 'w'. */ + + if ( ABS( CUR.F_dot_P ) < 0x4000000L ) + CUR.F_dot_P = 0x40000000L; + + /* Disable cached aspect ratio */ + CUR.metrics.ratio = 0; + } + + +/******************************************************************* + * + * Function : Normalize + * + * Description : Norms a vector + * + * Input : Vx, Vy input vector + * R normed unit vector + * + * Output : Returns FAILURE if a vector parameter is zero. + * + *****************************************************************/ + + static Bool Normalize( EXEC_OPS TT_F26Dot6 Vx, + TT_F26Dot6 Vy, + TT_UnitVector* R ) + { + TT_F26Dot6 W; + Bool S1, S2; + + + if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L ) + { + Vx *= 0x100; + Vy *= 0x100; + + W = Norm( Vx, Vy ); + + if ( W == 0 ) + { + /* XXX : UNDOCUMENTED! It seems that it's possible to try */ + /* to normalize the vector (0,0). Return immediately */ + return SUCCESS; + } + + R->x = (TT_F2Dot14)TT_MulDiv( Vx, 0x4000L, W ); + R->y = (TT_F2Dot14)TT_MulDiv( Vy, 0x4000L, W ); + + return SUCCESS; + } + + W = Norm( Vx, Vy ); + + Vx = TT_MulDiv( Vx, 0x4000L, W ); + Vy = TT_MulDiv( Vy, 0x4000L, W ); + + W = Vx * Vx + Vy * Vy; + + /* Now, we want that Sqrt( W ) = 0x4000 */ + /* Or 0x1000000 <= W < 0x1004000 */ + + if ( Vx < 0 ) + { + Vx = -Vx; + S1 = TRUE; + } + else + S1 = FALSE; + + if ( Vy < 0 ) + { + Vy = -Vy; + S2 = TRUE; + } + else + S2 = FALSE; + + while ( W < 0x1000000L ) + { + /* We need to increase W, by a minimal amount */ + if ( Vx < Vy ) + Vx++; + else + Vy++; + + W = Vx * Vx + Vy * Vy; + } + + while ( W >= 0x1004000L ) + { + /* We need to decrease W, by a minimal amount */ + if ( Vx < Vy ) + Vx--; + else + Vy--; + + W = Vx * Vx + Vy * Vy; + } + + /* Note that in various cases, we can only */ + /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ + + if ( S1 ) + Vx = -Vx; + + if ( S2 ) + Vy = -Vy; + + R->x = (TT_F2Dot14)Vx; /* Type conversion */ + R->y = (TT_F2Dot14)Vy; /* Type conversion */ + + return SUCCESS; + } + + +/**************************************************************** + * + * Opcodes + * + ****************************************************************/ + + + static Bool Ins_SxVTL( EXEC_OPS UShort aIdx1, + UShort aIdx2, + Int aOpc, + TT_UnitVector* Vec ) + { + Long A, B, C; + TT_Vector* p1; + TT_Vector* p2; + + + if ( BOUNDS( aIdx1, CUR.zp2.n_points ) || + BOUNDS( aIdx2, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return FAILURE; + } + + p1 = CUR.zp1.cur + aIdx2; + p2 = CUR.zp2.cur + aIdx1; + + A = p1->x - p2->x; + B = p1->y - p2->y; + + if ( (aOpc & 1) != 0 ) + { + C = B; /* CounterClockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, Vec ); + return SUCCESS; + } + + +/* When not using the big switch statements, the interpreter uses a */ +/* call table defined later below in this source. Each opcode must */ +/* thus have a corresponding function, even trivial ones. */ +/* */ +/* They're all defined there. */ + +#define DO_SVTCA \ + { \ + Short A, B; \ + \ + \ + A = (Short)(CUR.opcode & 1) << 14; \ + B = A ^ (Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.freeVector.y = B; \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTCA \ + { \ + Short A, B; \ + \ + \ + A = (Short)(CUR.opcode & 1) << 14; \ + B = A ^ (Short)0x4000; \ + \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTCA \ + { \ + Short A, B; \ + \ + \ + A = (Short)(CUR.opcode & 1) << 14; \ + B = A ^ (Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.freeVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTL \ + if ( INS_SxVTL( (UShort)args[1], \ + (UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.projVector) == SUCCESS ) \ + { \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTL \ + if ( INS_SxVTL( (UShort)args[1], \ + (UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.freeVector) == SUCCESS ) \ + COMPUTE_Funcs(); + + +#define DO_SFVTPV \ + CUR.GS.freeVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); + + +#define DO_SPVFS \ + { \ + Short S; \ + Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (Short)args[1]; \ + Y = (Long)S; \ + S = (Short)args[0]; \ + X = (Long)S; \ + \ + NORMalize( X, Y, &CUR.GS.projVector ); \ + \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVFS \ + { \ + Short S; \ + Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (Short)args[1]; \ + Y = (Long)S; \ + S = (Short)args[0]; \ + X = S; \ + \ + NORMalize( X, Y, &CUR.GS.freeVector ); \ + COMPUTE_Funcs(); \ + } + + +#define DO_GPV \ + args[0] = CUR.GS.projVector.x; \ + args[1] = CUR.GS.projVector.y; + + +#define DO_GFV \ + args[0] = CUR.GS.freeVector.x; \ + args[1] = CUR.GS.freeVector.y; + + +#define DO_SRP0 \ + CUR.GS.rp0 = (UShort)args[0]; + + +#define DO_SRP1 \ + CUR.GS.rp1 = (UShort)args[0]; + + +#define DO_SRP2 \ + CUR.GS.rp2 = (UShort)args[0]; + + +#define DO_RTHG \ + CUR.GS.round_state = TT_Round_To_Half_Grid; \ + CUR.func_round = (TRound_Function)Round_To_Half_Grid; + + +#define DO_RTG \ + CUR.GS.round_state = TT_Round_To_Grid; \ + CUR.func_round = (TRound_Function)Round_To_Grid; + + +#define DO_RTDG \ + CUR.GS.round_state = TT_Round_To_Double_Grid; \ + CUR.func_round = (TRound_Function)Round_To_Double_Grid; + + +#define DO_RUTG \ + CUR.GS.round_state = TT_Round_Up_To_Grid; \ + CUR.func_round = (TRound_Function)Round_Up_To_Grid; + + +#define DO_RDTG \ + CUR.GS.round_state = TT_Round_Down_To_Grid; \ + CUR.func_round = (TRound_Function)Round_Down_To_Grid; + + +#define DO_ROFF \ + CUR.GS.round_state = TT_Round_Off; \ + CUR.func_round = (TRound_Function)Round_None; + + +#define DO_SROUND \ + SET_SuperRound( 0x4000L, args[0] ); \ + CUR.GS.round_state = TT_Round_Super; \ + CUR.func_round = (TRound_Function)Round_Super; + + +#define DO_S45ROUND \ + SET_SuperRound( 0x2D41L, args[0] ); \ + CUR.GS.round_state = TT_Round_Super_45; \ + CUR.func_round = (TRound_Function)Round_Super_45; + + +#define DO_SLOOP \ + if ( args[0] < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ + else \ + CUR.GS.loop = args[0]; + + +#define DO_SMD \ + CUR.GS.minimum_distance = (TT_F26Dot6)args[0]; + + +#define DO_SCVTCI \ + CUR.GS.control_value_cutin = (TT_F26Dot6)args[0]; + + +#define DO_SSWCI \ + CUR.GS.single_width_cutin = (TT_F26Dot6)args[0]; + + + /* XXX : UNDOCUMENTED! or bug in the Windows engine? */ + /* */ + /* It seems that the value that is read here is */ + /* expressed in 16.16 format, rather than in */ + /* font units.. */ + /* */ +#define DO_SSW \ + CUR.GS.single_width_value = (TT_F26Dot6)(args[0] >> 10); + + +#define DO_FLIPON \ + CUR.GS.auto_flip = TRUE; + + +#define DO_FLIPOFF \ + CUR.GS.auto_flip = FALSE; + + +#define DO_SDB \ + CUR.GS.delta_base = (Short)args[0]; + + +#define DO_SDS \ + CUR.GS.delta_shift = (Short)args[0]; + + +#define DO_MD /* nothing */ + + +#define DO_MPPEM \ + args[0] = CURRENT_Ppem(); + + +#define DO_MPS \ + args[0] = CUR.metrics.pointSize; + + +#define DO_DUP \ + args[1] = args[0]; + + +#define DO_CLEAR \ + CUR.new_top = 0; + + +#define DO_SWAP \ + { \ + Long L; \ + \ + L = args[0]; \ + args[0] = args[1]; \ + args[1] = L; \ + } + + +#define DO_DEPTH \ + args[0] = CUR.top; + + +#define DO_CINDEX \ + { \ + Long L; \ + \ + \ + L = args[0]; \ + \ + if ( L <= 0 || L > CUR.args ) \ + CUR.error = TT_Err_Invalid_Reference; \ + else \ + args[0] = CUR.stack[CUR.args - L]; \ + } + + +#define DO_JROT \ + if ( args[1] != 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_JMPR \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; + + +#define DO_JROF \ + if ( args[1] == 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_LT \ + args[0] = (args[0] < args[1]); + + +#define DO_LTEQ \ + args[0] = (args[0] <= args[1]); + + +#define DO_GT \ + args[0] = (args[0] > args[1]); + + +#define DO_GTEQ \ + args[0] = (args[0] >= args[1]); + + +#define DO_EQ \ + args[0] = (args[0] == args[1]); + + +#define DO_NEQ \ + args[0] = (args[0] != args[1]); + + +#define DO_ODD \ + args[0] = ( (CUR_Func_round( args[0], 0 ) & 127) == 64 ); + + +#define DO_EVEN \ + args[0] = ( (CUR_Func_round( args[0], 0 ) & 127) == 0 ); + + +#define DO_AND \ + args[0] = ( args[0] && args[1] ); + + +#define DO_OR \ + args[0] = ( args[0] || args[1] ); + + +#define DO_NOT \ + args[0] = !args[0]; + + +#define DO_ADD \ + args[0] += args[1]; + + +#define DO_SUB \ + args[0] -= args[1]; + + +#define DO_DIV \ + if ( args[1] == 0 ) \ + CUR.error = TT_Err_Divide_By_Zero; \ + else \ + args[0] = TT_MulDiv( args[0], 64L, args[1] ); + + +#define DO_MUL \ + args[0] = TT_MulDiv( args[0], args[1], 64L ); + + +#define DO_ABS \ + args[0] = ABS( args[0] ); + + +#define DO_NEG \ + args[0] = -args[0]; + + +#define DO_FLOOR \ + args[0] &= -64; + + +#define DO_CEILING \ + args[0] = (args[0] + 63) & (-64); + + +#define DO_RS \ + { \ + ULong I = (ULong)args[0]; \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR.storage[I]; \ + } + + +#define DO_WS \ + { \ + ULong I = (ULong)args[0]; \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.storage[I] = args[1]; \ + } + + + +#define DO_RCVT \ + { \ + ULong I = (ULong)args[0]; \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR_Func_read_cvt(I); \ + } + + +#define DO_WCVTP \ + { \ + ULong I = (ULong)args[0]; \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR_Func_write_cvt( I, args[1] ); \ + } + + +#define DO_WCVTF \ + { \ + ULong I = (ULong)args[0]; \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.cvt[I] = FUnits_To_Pixels( EXEC_ARGS (Short)args[1] ); \ + } + + +#define DO_DEBUG \ + CUR.error = TT_Err_Debug_OpCode; + + +#define DO_ROUND \ + args[0] = CUR_Func_round( args[0], \ + CUR.metrics.compensations[CUR.opcode-0x68] ); + + +#define DO_NROUND \ + args[0] = Round_None( EXEC_ARGS \ + args[0], \ + CUR.metrics.compensations[CUR.opcode - 0x6C] ); + + +#define DO_MAX \ + if ( args[1] > args[0] ) \ + args[0] = args[1]; + + +#define DO_MIN \ + if ( args[1] < args[0] ) \ + args[0] = args[1]; + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR \ + { \ + CUR.error = TT_Err_Invalid_Reference; \ + return; \ + } + + +/*******************************************/ +/* SVTCA[a] : Set F and P vectors to axis */ +/* CodeRange : $00-$01 */ +/* Stack : --> */ + + static void Ins_SVTCA( INS_ARG ) + { + DO_SVTCA + } + + +/*******************************************/ +/* SPVTCA[a] : Set PVector to Axis */ +/* CodeRange : $02-$03 */ +/* Stack : --> */ + + static void Ins_SPVTCA( INS_ARG ) + { + DO_SPVTCA + } + + +/*******************************************/ +/* SFVTCA[a] : Set FVector to Axis */ +/* CodeRange : $04-$05 */ +/* Stack : --> */ + + static void Ins_SFVTCA( INS_ARG ) + { + DO_SFVTCA + } + +/*******************************************/ +/* SPVTL[a] : Set PVector to Line */ +/* CodeRange : $06-$07 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_SPVTL( INS_ARG ) + { + DO_SPVTL + } + + +/*******************************************/ +/* SFVTL[a] : Set FVector to Line */ +/* CodeRange : $08-$09 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_SFVTL( INS_ARG ) + { + DO_SFVTL + } + + +/*******************************************/ +/* SFVTPV[] : Set FVector to PVector */ +/* CodeRange : $0E */ +/* Stack : --> */ + + static void Ins_SFVTPV( INS_ARG ) + { + DO_SFVTPV + } + + +/*******************************************/ +/* SPVFS[] : Set PVector From Stack */ +/* CodeRange : $0A */ +/* Stack : f2.14 f2.14 --> */ + + static void Ins_SPVFS( INS_ARG ) + { + DO_SPVFS + } + + +/*******************************************/ +/* SFVFS[] : Set FVector From Stack */ +/* CodeRange : $0B */ +/* Stack : f2.14 f2.14 --> */ + + static void Ins_SFVFS( INS_ARG ) + { + DO_SFVFS + } + + +/*******************************************/ +/* GPV[] : Get Projection Vector */ +/* CodeRange : $0C */ +/* Stack : ef2.14 --> ef2.14 */ + + static void Ins_GPV( INS_ARG ) + { + DO_GPV + } + + +/*******************************************/ +/* GFV[] : Get Freedom Vector */ +/* CodeRange : $0D */ +/* Stack : ef2.14 --> ef2.14 */ + + static void Ins_GFV( INS_ARG ) + { + DO_GFV + } + + +/*******************************************/ +/* SRP0[] : Set Reference Point 0 */ +/* CodeRange : $10 */ +/* Stack : uint32 --> */ + + static void Ins_SRP0( INS_ARG ) + { + DO_SRP0 + } + + +/*******************************************/ +/* SRP1[] : Set Reference Point 1 */ +/* CodeRange : $11 */ +/* Stack : uint32 --> */ + + static void Ins_SRP1( INS_ARG ) + { + DO_SRP1 + } + + +/*******************************************/ +/* SRP2[] : Set Reference Point 2 */ +/* CodeRange : $12 */ +/* Stack : uint32 --> */ + + static void Ins_SRP2( INS_ARG ) + { + DO_SRP2 + } + + +/*******************************************/ +/* RTHG[] : Round To Half Grid */ +/* CodeRange : $19 */ +/* Stack : --> */ + + static void Ins_RTHG( INS_ARG ) + { + DO_RTHG + } + + +/*******************************************/ +/* RTG[] : Round To Grid */ +/* CodeRange : $18 */ +/* Stack : --> */ + + static void Ins_RTG( INS_ARG ) + { + DO_RTG + } + + +/*******************************************/ +/* RTDG[] : Round To Double Grid */ +/* CodeRange : $3D */ +/* Stack : --> */ + + static void Ins_RTDG( INS_ARG ) + { + DO_RTDG + } + + +/*******************************************/ +/* RUTG[] : Round Up To Grid */ +/* CodeRange : $7C */ +/* Stack : --> */ + + static void Ins_RUTG( INS_ARG ) + { + DO_RUTG + } + + +/*******************************************/ +/* RDTG[] : Round Down To Grid */ +/* CodeRange : $7D */ +/* Stack : --> */ + + static void Ins_RDTG( INS_ARG ) + { + DO_RDTG + } + + +/*******************************************/ +/* ROFF[] : Round OFF */ +/* CodeRange : $7A */ +/* Stack : --> */ + + static void Ins_ROFF( INS_ARG ) + { + DO_ROFF + } + + +/*******************************************/ +/* SROUND[] : Super ROUND */ +/* CodeRange : $76 */ +/* Stack : Eint8 --> */ + + static void Ins_SROUND( INS_ARG ) + { + DO_SROUND + } + + +/*******************************************/ +/* S45ROUND[]: Super ROUND 45 degrees */ +/* CodeRange : $77 */ +/* Stack : uint32 --> */ + + static void Ins_S45ROUND( INS_ARG ) + { + DO_S45ROUND + } + + +/*******************************************/ +/* SLOOP[] : Set LOOP variable */ +/* CodeRange : $17 */ +/* Stack : int32? --> */ + + static void Ins_SLOOP( INS_ARG ) + { + DO_SLOOP + } + + +/*******************************************/ +/* SMD[] : Set Minimum Distance */ +/* CodeRange : $1A */ +/* Stack : f26.6 --> */ + + static void Ins_SMD( INS_ARG ) + { + DO_SMD + } + + +/**********************************************/ +/* SCVTCI[] : Set Control Value Table Cut In */ +/* CodeRange : $1D */ +/* Stack : f26.6 --> */ + + static void Ins_SCVTCI( INS_ARG ) + { + DO_SCVTCI + } + + +/**********************************************/ +/* SSWCI[] : Set Single Width Cut In */ +/* CodeRange : $1E */ +/* Stack : f26.6 --> */ + + static void Ins_SSWCI( INS_ARG ) + { + DO_SSWCI + } + + +/**********************************************/ +/* SSW[] : Set Single Width */ +/* CodeRange : $1F */ +/* Stack : int32? --> */ + + static void Ins_SSW( INS_ARG ) + { + DO_SSW + } + + +/**********************************************/ +/* FLIPON[] : Set Auto_flip to On */ +/* CodeRange : $4D */ +/* Stack : --> */ + + static void Ins_FLIPON( INS_ARG ) + { + DO_FLIPON + } + + +/**********************************************/ +/* FLIPOFF[] : Set Auto_flip to Off */ +/* CodeRange : $4E */ +/* Stack : --> */ + + static void Ins_FLIPOFF( INS_ARG ) + { + DO_FLIPOFF + } + + +/**********************************************/ +/* SANGW[] : Set Angle Weight */ +/* CodeRange : $7E */ +/* Stack : uint32 --> */ + + static void Ins_SANGW( INS_ARG ) + { + /* instruction not supported anymore */ + } + + +/**********************************************/ +/* SDB[] : Set Delta Base */ +/* CodeRange : $5E */ +/* Stack : uint32 --> */ + + static void Ins_SDB( INS_ARG ) + { + DO_SDB + } + + +/**********************************************/ +/* SDS[] : Set Delta Shift */ +/* CodeRange : $5F */ +/* Stack : uint32 --> */ + + static void Ins_SDS( INS_ARG ) + { + DO_SDS + } + + +/**********************************************/ +/* MPPEM[] : Measure Pixel Per EM */ +/* CodeRange : $4B */ +/* Stack : --> Euint16 */ + + static void Ins_MPPEM( INS_ARG ) + { + DO_MPPEM + } + + +/**********************************************/ +/* MPS[] : Measure PointSize */ +/* CodeRange : $4C */ +/* Stack : --> Euint16 */ + + static void Ins_MPS( INS_ARG ) + { + DO_MPS + } + +/*******************************************/ +/* DUP[] : Duplicate top stack element */ +/* CodeRange : $20 */ +/* Stack : StkElt --> StkElt StkElt */ + + static void Ins_DUP( INS_ARG ) + { + DO_DUP + } + + +/*******************************************/ +/* POP[] : POPs the stack's top elt. */ +/* CodeRange : $21 */ +/* Stack : StkElt --> */ + + static void Ins_POP( INS_ARG ) + { + /* nothing to do */ + } + + +/*******************************************/ +/* CLEAR[] : Clear the entire stack */ +/* CodeRange : $22 */ +/* Stack : StkElt... --> */ + + static void Ins_CLEAR( INS_ARG ) + { + DO_CLEAR + } + + +/*******************************************/ +/* SWAP[] : Swap the top two elements */ +/* CodeRange : $23 */ +/* Stack : 2 * StkElt --> 2 * StkElt */ + + static void Ins_SWAP( INS_ARG ) + { + DO_SWAP + } + + +/*******************************************/ +/* DEPTH[] : return the stack depth */ +/* CodeRange : $24 */ +/* Stack : --> uint32 */ + + static void Ins_DEPTH( INS_ARG ) + { + DO_DEPTH + } + + +/*******************************************/ +/* CINDEX[] : copy indexed element */ +/* CodeRange : $25 */ +/* Stack : int32 --> StkElt */ + + static void Ins_CINDEX( INS_ARG ) + { + DO_CINDEX + } + + +/*******************************************/ +/* EIF[] : End IF */ +/* CodeRange : $59 */ +/* Stack : --> */ + + static void Ins_EIF( INS_ARG ) + { + /* nothing to do */ + } + + +/*******************************************/ +/* JROT[] : Jump Relative On True */ +/* CodeRange : $78 */ +/* Stack : StkElt int32 --> */ + + static void Ins_JROT( INS_ARG ) + { + DO_JROT + } + + +/*******************************************/ +/* JMPR[] : JuMP Relative */ +/* CodeRange : $1C */ +/* Stack : int32 --> */ + + static void Ins_JMPR( INS_ARG ) + { + DO_JMPR + } + + +/*******************************************/ +/* JROF[] : Jump Relative On False */ +/* CodeRange : $79 */ +/* Stack : StkElt int32 --> */ + + static void Ins_JROF( INS_ARG ) + { + DO_JROF + } + + +/*******************************************/ +/* LT[] : Less Than */ +/* CodeRange : $50 */ +/* Stack : int32? int32? --> bool */ + + static void Ins_LT( INS_ARG ) + { + DO_LT + } + + +/*******************************************/ +/* LTEQ[] : Less Than or EQual */ +/* CodeRange : $51 */ +/* Stack : int32? int32? --> bool */ + + static void Ins_LTEQ( INS_ARG ) + { + DO_LTEQ + } + + +/*******************************************/ +/* GT[] : Greater Than */ +/* CodeRange : $52 */ +/* Stack : int32? int32? --> bool */ + + static void Ins_GT( INS_ARG ) + { + DO_GT + } + + +/*******************************************/ +/* GTEQ[] : Greater Than or EQual */ +/* CodeRange : $53 */ +/* Stack : int32? int32? --> bool */ + + static void Ins_GTEQ( INS_ARG ) + { + DO_GTEQ + } + + +/*******************************************/ +/* EQ[] : EQual */ +/* CodeRange : $54 */ +/* Stack : StkElt StkElt --> bool */ + + static void Ins_EQ( INS_ARG ) + { + DO_EQ + } + + +/*******************************************/ +/* NEQ[] : Not EQual */ +/* CodeRange : $55 */ +/* Stack : StkElt StkElt --> bool */ + + static void Ins_NEQ( INS_ARG ) + { + DO_NEQ + } + + +/*******************************************/ +/* ODD[] : Odd */ +/* CodeRange : $56 */ +/* Stack : f26.6 --> bool */ + + static void Ins_ODD( INS_ARG ) + { + DO_ODD + } + + +/*******************************************/ +/* EVEN[] : Even */ +/* CodeRange : $57 */ +/* Stack : f26.6 --> bool */ + + static void Ins_EVEN( INS_ARG ) + { + DO_EVEN + } + + +/*******************************************/ +/* AND[] : logical AND */ +/* CodeRange : $5A */ +/* Stack : uint32 uint32 --> uint32 */ + + static void Ins_AND( INS_ARG ) + { + DO_AND + } + + +/*******************************************/ +/* OR[] : logical OR */ +/* CodeRange : $5B */ +/* Stack : uint32 uint32 --> uint32 */ + + static void Ins_OR( INS_ARG ) + { + DO_OR + } + + +/*******************************************/ +/* NOT[] : logical NOT */ +/* CodeRange : $5C */ +/* Stack : StkElt --> uint32 */ + + static void Ins_NOT( INS_ARG ) + { + DO_NOT + } + + +/*******************************************/ +/* ADD[] : ADD */ +/* CodeRange : $60 */ +/* Stack : f26.6 f26.6 --> f26.6 */ + + static void Ins_ADD( INS_ARG ) + { + DO_ADD + } + + +/*******************************************/ +/* SUB[] : SUBstract */ +/* CodeRange : $61 */ +/* Stack : f26.6 f26.6 --> f26.6 */ + + static void Ins_SUB( INS_ARG ) + { + DO_SUB + } + + +/*******************************************/ +/* DIV[] : DIVide */ +/* CodeRange : $62 */ +/* Stack : f26.6 f26.6 --> f26.6 */ + + static void Ins_DIV( INS_ARG ) + { + DO_DIV + } + + +/*******************************************/ +/* MUL[] : MULtiply */ +/* CodeRange : $63 */ +/* Stack : f26.6 f26.6 --> f26.6 */ + + static void Ins_MUL( INS_ARG ) + { + DO_MUL + } + + +/*******************************************/ +/* ABS[] : ABSolute value */ +/* CodeRange : $64 */ +/* Stack : f26.6 --> f26.6 */ + + static void Ins_ABS( INS_ARG ) + { + DO_ABS + } + + +/*******************************************/ +/* NEG[] : NEGate */ +/* CodeRange : $65 */ +/* Stack : f26.6 --> f26.6 */ + + static void Ins_NEG( INS_ARG ) + { + DO_NEG + } + + +/*******************************************/ +/* FLOOR[] : FLOOR */ +/* CodeRange : $66 */ +/* Stack : f26.6 --> f26.6 */ + + static void Ins_FLOOR( INS_ARG ) + { + DO_FLOOR + } + + +/*******************************************/ +/* CEILING[] : CEILING */ +/* CodeRange : $67 */ +/* f26.6 --> f26.6 */ + + static void Ins_CEILING( INS_ARG ) + { + DO_CEILING + } + +/*******************************************/ +/* RS[] : Read Store */ +/* CodeRange : $43 */ +/* Stack : uint32 --> uint32 */ + + static void Ins_RS( INS_ARG ) + { + DO_RS + } + + +/*******************************************/ +/* WS[] : Write Store */ +/* CodeRange : $42 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_WS( INS_ARG ) + { + DO_WS + } + + +/*******************************************/ +/* WCVTP[] : Write CVT in Pixel units */ +/* CodeRange : $44 */ +/* Stack : f26.6 uint32 --> */ + + static void Ins_WCVTP( INS_ARG ) + { + DO_WCVTP + } + + +/*******************************************/ +/* WCVTF[] : Write CVT in FUnits */ +/* CodeRange : $70 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_WCVTF( INS_ARG ) + { + DO_WCVTF + } + + +/*******************************************/ +/* RCVT[] : Read CVT */ +/* CodeRange : $45 */ +/* Stack : uint32 --> f26.6 */ + + static void Ins_RCVT( INS_ARG ) + { + DO_RCVT + } + + +/********************************************/ +/* AA[] : Adjust Angle */ +/* CodeRange : $7F */ +/* Stack : uint32 --> */ + + static void Ins_AA( INS_ARG ) + { + /* Intentional - no longer supported */ + } + + +/********************************************/ +/* DEBUG[] : DEBUG. Unsupported */ +/* CodeRange : $4F */ +/* Stack : uint32 --> */ + +/* NOTE : The original instruction pops a value from the stack */ + + static void Ins_DEBUG( INS_ARG ) + { + DO_DEBUG + } + +/*******************************************/ +/* ROUND[ab] : ROUND value */ +/* CodeRange : $68-$6B */ +/* Stack : f26.6 --> f26.6 */ + + static void Ins_ROUND( INS_ARG ) + { + DO_ROUND + } + +/*******************************************/ +/* NROUND[ab]: No ROUNDing of value */ +/* CodeRange : $6C-$6F */ +/* Stack : f26.6 --> f26.6 */ + + static void Ins_NROUND( INS_ARG ) + { + DO_NROUND + } + + + +/*******************************************/ +/* MAX[] : MAXimum */ +/* CodeRange : $68 */ +/* Stack : int32? int32? --> int32 */ + + static void Ins_MAX( INS_ARG ) + { + DO_MAX + } + + +/*******************************************/ +/* MIN[] : MINimum */ +/* CodeRange : $69 */ +/* Stack : int32? int32? --> int32 */ + + static void Ins_MIN( INS_ARG ) + { + DO_MIN + } + + +#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + +/* The following functions are called as is within the switch statement */ + +/*******************************************/ +/* MINDEX[] : move indexed element */ +/* CodeRange : $26 */ +/* Stack : int32? --> StkElt */ + + static void Ins_MINDEX( INS_ARG ) + { + Long L, K; + + + L = args[0]; + + if ( L <= 0 || L > CUR.args ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR.stack[CUR.args - L]; + + MEM_Move( (&CUR.stack[CUR.args - L ]), + (&CUR.stack[CUR.args - L + 1]), + (L - 1) * sizeof ( Long ) ); + + CUR.stack[CUR.args - 1] = K; + } + + +/*******************************************/ +/* ROLL[] : roll top three elements */ +/* CodeRange : $8A */ +/* Stack : 3 * StkElt --> 3 * StkElt */ + + static void Ins_ROLL( INS_ARG ) + { + Long A, B, C; + + + A = args[2]; + B = args[1]; + C = args[0]; + + args[2] = C; + args[1] = A; + args[0] = B; + } + + + +/****************************************************************/ +/* */ +/* MANAGING THE FLOW OF CONTROL */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + + static Bool SkipCode( EXEC_OP ) + { + CUR.IP += CUR.length; + + if ( CUR.IP < CUR.codeSize ) + if ( CALC_Length() == SUCCESS ) + return SUCCESS; + + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + +/*******************************************/ +/* IF[] : IF test */ +/* CodeRange : $58 */ +/* Stack : StkElt --> */ + + static void Ins_IF( INS_ARG ) + { + Int nIfs; + Bool Out; + + + if ( args[0] != 0 ) + return; + + nIfs = 1; + Out = 0; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x1b: /* ELSE */ + Out = (nIfs == 1); + break; + + case 0x59: /* EIF */ + nIfs--; + Out = (nIfs == 0); + break; + } + } while ( Out == 0 ); + } + + +/*******************************************/ +/* ELSE[] : ELSE */ +/* CodeRange : $1B */ +/* Stack : --> */ + + static void Ins_ELSE( INS_ARG ) + { + Int nIfs; + + + nIfs = 1; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x59: /* EIF */ + nIfs--; + break; + } + } while ( nIfs != 0 ); + } + + +/****************************************************************/ +/* */ +/* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + + static PDefRecord Locate_FDef( EXEC_OPS Int n, Bool new_def ) + { + PDefRecord def; + UShort hash; + UShort cnt; + + /* The function table is interpreted as a simple hash table */ + /* with indexes computed modulo maxFDefs and the linear search */ + /* of free cells in the case of a collision. */ + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font fit into 0..maxFDefs - 1 range and the lookup is */ + /* reduced to a single step. */ + + /* Minor optimization. */ + if ( !new_def && ( n < 0 || n > CUR.maxFunc ) ) + return NULL; + + for ( cnt = 0; cnt < CUR.maxFDefs; ++cnt ) + { + hash = ( (UShort)n + cnt ) % CUR.maxFDefs; + def = &CUR.FDefs[ hash ]; + if ( !def->Active ) + return new_def ? def : NULL; + if ( def->Opc == n ) + return def; + } + + /* The table is full and the entry has not been found. */ + return NULL; + } + + +/*******************************************/ +/* FDEF[] : Function DEFinition */ +/* CodeRange : $2C */ +/* Stack : uint32 --> */ + + static void Ins_FDEF( INS_ARG ) + { + Int n; + PDefRecord def; + + + /* check that there is enough room */ + if ( CUR.numFDefs >= CUR.maxFDefs ) + { + /* We could introduce a new error message, but we're too close */ + /* from the release to change all the 'po' files again.. */ + CUR.error = TT_Err_Too_Many_Ins; + return; + } + + n = (Int)args[0]; + if ( n < 0 || (ULong)n != args[0] ) + { + /* Gotcha. Function index is uint32 according to the specs */ + /* but TDefRecord.Opc is defined as Int. We cannot store */ + /* the definition of this function. */ + CUR.error = TT_Err_Bad_Argument; + return; + } + + def = Locate_FDef( EXEC_ARGS n, TRUE ); + if ( !def ) + { + /* Oh, oh. Something is wrong. Locate_FDef should never fail here. */ + CUR.error = TT_Err_Too_Many_Ins; + return; + } + + /* Some font programs are broken enough to redefine functions! */ + if ( !def->Active ) + CUR.numFDefs++; + + def->Range = CUR.curRange; + def->Opc = n; + def->Start = CUR.IP + 1; + def->Active = TRUE; + + if ( n > CUR.maxFunc ) + CUR.maxFunc = n; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFS & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2c: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + case 0x2d: /* ENDF */ + return; + } + } + } + + +/*******************************************/ +/* ENDF[] : END Function definition */ +/* CodeRange : $2D */ +/* Stack : --> */ + + static void Ins_ENDF( INS_ARG ) + { + PCallRecord pRec; + + + if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */ + { + CUR.error = TT_Err_ENDF_In_Exec_Stream; + return; + } + + CUR.callTop--; + + pRec = &CUR.callStack[CUR.callTop]; + + pRec->Cur_Count--; + + CUR.step_ins = FALSE; + + if ( pRec->Cur_Count > 0 ) + { + CUR.callTop++; + CUR.IP = pRec->Cur_Restart; + } + else + /* Loop through the current function */ + INS_Goto_CodeRange( pRec->Caller_Range, + pRec->Caller_IP ); + + /* Exit the current call frame. */ + + /* NOTE: When the last intruction of a program */ + /* is a CALL or LOOPCALL, the return address */ + /* is always out of the code range. This is */ + /* a valid address, and it's why we do not test */ + /* the result of Ins_Goto_CodeRange() here! */ + } + + +/*******************************************/ +/* CALL[] : CALL function */ +/* CodeRange : $2B */ +/* Stack : uint32? --> */ + + static void Ins_CALL( INS_ARG ) + { + Int n; + PDefRecord def; + PCallRecord pCrec; + + + n = (Int)args[0]; + def = Locate_FDef( EXEC_ARGS n, FALSE ); + if ( !def ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* check call stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = 1; + pCrec->Cur_Restart = def->Start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->Range, + def->Start ); + + CUR.step_ins = FALSE; + } + + +/*******************************************/ +/* LOOPCALL[]: LOOP and CALL function */ +/* CodeRange : $2A */ +/* Stack : uint32? Eint16? --> */ + + static void Ins_LOOPCALL( INS_ARG ) + { + Int n; + Long count; + PDefRecord def; + PCallRecord pTCR; + + + n = (Int)args[1]; + def = Locate_FDef( EXEC_ARGS n, FALSE ); + if ( !def ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + count = (Long)args[0]; + if ( count <= 0 ) + return; + + pTCR = &CUR.callStack[CUR.callTop]; + + pTCR->Caller_Range = CUR.curRange; + pTCR->Caller_IP = CUR.IP + 1; + pTCR->Cur_Count = count; + pTCR->Cur_Restart = def->Start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->Range, + def->Start ); + + CUR.step_ins = FALSE; + } + + +/*******************************************/ +/* IDEF[] : Instruction DEFinition */ +/* CodeRange : $89 */ +/* Stack : Eint8 --> */ + + static void Ins_IDEF( INS_ARG ) + { + Byte opcode; + PDefRecord def; + PDefRecord limit; + + + opcode = (Byte)args[0]; + + /* First of all, look for the same instruction in our table */ + def = CUR.IDefs; + limit = def + CUR.numIDefs; + for ( ; def < limit; def++ ) + if ( def->Opc == opcode ) + break; + + if ( def == limit ) + { + /* check that there is enough room for a new instruction */ + if ( CUR.numIDefs >= CUR.maxIDefs ) + { + /* XXX Bad error code. See FDEF[]. */ + CUR.error = TT_Err_Too_Many_Ins; + return; + } + CUR.numIDefs++; + } + + def->Opc = opcode; + def->Start = CUR.IP + 1; + def->Range = CUR.curRange; + def->Active = TRUE; + + if ( opcode > CUR.maxIns ) + CUR.maxIns = opcode; + + /* Now skip the whole function definition */ + /* We don't allow nested IDEFs & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2c: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + case 0x2d: /* ENDF */ + return; + } + } + } + + +/****************************************************************/ +/* */ +/* PUSHING DATA ONTO THE INTERPRETER STACK */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + +/*******************************************/ +/* NPUSHB[] : PUSH N Bytes */ +/* CodeRange : $40 */ +/* Stack : --> uint32... */ + + static void Ins_NPUSHB( INS_ARG ) + { + UShort L, K; + + + L = (UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K + 1]; + + CUR.new_top += L; + } + + +/*******************************************/ +/* NPUSHW[] : PUSH N Words */ +/* CodeRange : $41 */ +/* Stack : --> int32... */ + + static void Ins_NPUSHW( INS_ARG ) + { + UShort L, K; + + + L = (UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP += 2; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + CUR.new_top += L; + } + + +/*******************************************/ +/* PUSHB[abc]: PUSH Bytes */ +/* CodeRange : $B0-$B7 */ +/* Stack : --> uint32... */ + + static void Ins_PUSHB( INS_ARG ) + { + UShort L, K; + + + L = (UShort)CUR.opcode - 0xB0 + 1; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K]; + } + + +/*******************************************/ +/* PUSHW[abc]: PUSH Words */ +/* CodeRange : $B8-$BF */ +/* Stack : --> int32... */ + + static void Ins_PUSHW( INS_ARG ) + { + UShort L, K; + + + L = (UShort)CUR.opcode - 0xB8 + 1; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP++; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + } + + + +/****************************************************************/ +/* */ +/* MANAGING THE GRAPHICS STATE */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + +/**********************************************/ +/* GC[a] : Get Coordinate projected onto */ +/* CodeRange : $46-$47 */ +/* Stack : uint32 --> f26.6 */ + +/* BULLSHIT: Measures from the original glyph must be taken */ +/* along the dual projection vector! */ + + static void Ins_GC( INS_ARG ) + { + ULong L; + TT_F26Dot6 R; + + + L = (ULong)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + else + R = 0; + } + else + { + if ( CUR.opcode & 1 ) + R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector ); + else + R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + } + + args[0] = R; + } + + +/**********************************************/ +/* SCFS[] : Set Coordinate From Stack */ +/* CodeRange : $48 */ +/* Stack : f26.6 uint32 --> */ +/* */ +/* Formula: */ +/* */ +/* OA := OA + ( value - OA.p )/( f.p ) * f */ +/* */ + + static void Ins_SCFS( INS_ARG ) + { + Long K; + UShort L; + + + L = (UShort)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + + CUR_Func_move( &CUR.zp2, L, args[1] - K ); + + /* not part of the specs, but here for safety */ + + if ( CUR.GS.gep2 == 0 ) + CUR.zp2.org[L] = CUR.zp2.cur[L]; + } + + +/**********************************************/ +/* MD[a] : Measure Distance */ +/* CodeRange : $49-$4A */ +/* Stack : uint32 uint32 --> f26.6 */ + +/* BULLSHIT: Measure taken in the original glyph must be along */ +/* the dual projection vector. */ + +/* Second BULLSHIT: Flag attributes are inverted! */ +/* 0 => measure distance in original outline */ +/* 1 => measure distance in grid-fitted outline */ + +/* Third one !! : zp0 - zp1, and not "zp2 - zp1" !!! */ +/* */ + + static void Ins_MD( INS_ARG ) + { + UShort K, L; + TT_F26Dot6 D; + + + K = (UShort)args[1]; + L = (UShort)args[0]; + + if( BOUNDS( L, CUR.zp0.n_points ) || + BOUNDS( K, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + else + D = 0; + } + else + { + if ( CUR.opcode & 1 ) + D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); + else + D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K ); + } + + args[0] = D; + } + + +/*******************************************/ +/* SDPVTL[a] : Set Dual PVector to Line */ +/* CodeRange : $86-$87 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_SDPVTL( INS_ARG ) + { + Long A, B, C; + UShort p1, p2; /* was Int in pas type ERROR */ + + + p1 = (UShort)args[1]; + p2 = (UShort)args[0]; + + if ( BOUNDS( p2, CUR.zp1.n_points ) || + BOUNDS( p1, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + { + TT_Vector* v1 = CUR.zp1.org + p2; + TT_Vector* v2 = CUR.zp2.org + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( (CUR.opcode & 1) != 0 ) + { + C = B; /* CounterClockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.dualVector ); + + { + TT_Vector* v1 = CUR.zp1.cur + p2; + TT_Vector* v2 = CUR.zp2.cur + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( (CUR.opcode & 1) != 0 ) + { + C = B; /* CounterClockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.projVector ); + + COMPUTE_Funcs(); + } + + +/*******************************************/ +/* SZP0[] : Set Zone Pointer 0 */ +/* CodeRange : $13 */ +/* Stack : uint32 --> */ + + static void Ins_SZP0( INS_ARG ) + { + switch ( (Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep0 = (UShort)args[0]; + } + + +/*******************************************/ +/* SZP1[] : Set Zone Pointer 1 */ +/* CodeRange : $14 */ +/* Stack : uint32 --> */ + + static void Ins_SZP1( INS_ARG ) + { + switch ( (Int)args[0] ) + { + case 0: + CUR.zp1 = CUR.twilight; + break; + + case 1: + CUR.zp1 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep1 = (UShort)args[0]; + } + + +/*******************************************/ +/* SZP2[] : Set Zone Pointer 2 */ +/* CodeRange : $15 */ +/* Stack : uint32 --> */ + + static void Ins_SZP2( INS_ARG ) + { + switch ( (Int)args[0] ) + { + case 0: + CUR.zp2 = CUR.twilight; + break; + + case 1: + CUR.zp2 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep2 = (UShort)args[0]; + } + + +/*******************************************/ +/* SZPS[] : Set Zone Pointers */ +/* CodeRange : $16 */ +/* Stack : uint32 --> */ + + static void Ins_SZPS( INS_ARG ) + { + switch ( (Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.zp1 = CUR.zp0; + CUR.zp2 = CUR.zp0; + + CUR.GS.gep0 = (UShort)args[0]; + CUR.GS.gep1 = (UShort)args[0]; + CUR.GS.gep2 = (UShort)args[0]; + } + + +/*******************************************/ +/* INSTCTRL[]: INSTruction ConTRol */ +/* CodeRange : $8e */ +/* Stack : int32 int32 --> */ + + static void Ins_INSTCTRL( INS_ARG ) + { + Long K, L; + + + K = args[1]; + L = args[0]; + + if ( K < 1 || K > 2 ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( L != 0 ) + L = K; + + CUR.GS.instruct_control = + (Byte)( CUR.GS.instruct_control & ~(Byte)K ) | (Byte)L; + } + + +/*******************************************/ +/* SCANCTRL[]: SCAN ConTRol */ +/* CodeRange : $85 */ +/* Stack : uint32? --> */ + + static void Ins_SCANCTRL( INS_ARG ) + { + Int A; + + + /* Get Threshold */ + A = (Int)(args[0] & 0xFF); + + if ( A == 0xFF ) + { + CUR.GS.scan_control = TRUE; + return; + } + else if ( A == 0 ) + { + CUR.GS.scan_control = FALSE; + return; + } + + A *= 64; + + if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A ) + CUR.GS.scan_control = TRUE; + + if ( (args[0] & 0x200) != 0 && CUR.metrics.rotated ) + CUR.GS.scan_control = TRUE; + + if ( (args[0] & 0x400) != 0 && CUR.metrics.stretched ) + CUR.GS.scan_control = TRUE; + + if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A ) + CUR.GS.scan_control = FALSE; + + if ( (args[0] & 0x1000) != 0 && CUR.metrics.rotated ) + CUR.GS.scan_control = FALSE; + + if ( (args[0] & 0x2000) != 0 && CUR.metrics.stretched ) + CUR.GS.scan_control = FALSE; +} + + +/*******************************************/ +/* SCANTYPE[]: SCAN TYPE */ +/* CodeRange : $8D */ +/* Stack : uint32? --> */ + + static void Ins_SCANTYPE( INS_ARG ) + { + /* For compatibility with future enhancements, */ + /* we must ignore new modes */ + + if ( args[0] >= 0 && args[0] <= 5 ) + { + if ( args[0] == 3 ) + args[0] = 2; + + CUR.GS.scan_type = (Int)args[0]; + } + } + + + +/****************************************************************/ +/* */ +/* MANAGING OUTLINES */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + +/**********************************************/ +/* FLIPPT[] : FLIP PoinT */ +/* CodeRange : $80 */ +/* Stack : uint32... --> */ + + static void Ins_FLIPPT( INS_ARG ) + { + UShort point; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + CUR.pts.touch[point] ^= TT_Flag_On_Curve; + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* FLIPRGON[]: FLIP RanGe ON */ +/* CodeRange : $81 */ +/* Stack : uint32 uint32 --> */ +/* (but UShorts are sufficient) */ + + static void Ins_FLIPRGON( INS_ARG ) + { + UShort I, K, L; + + + K = (UShort)args[1]; + L = (UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.touch[I] |= TT_Flag_On_Curve; + } + + +/**********************************************/ +/* FLIPRGOFF : FLIP RanGe OFF */ +/* CodeRange : $82 */ +/* Stack : uint32 uint32 --> */ +/* (but UShorts are sufficient) */ + + static void Ins_FLIPRGOFF( INS_ARG ) + { + UShort I, K, L; + + + K = (UShort)args[1]; + L = (UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.touch[I] &= ~TT_Flag_On_Curve; + } + + + static Bool Compute_Point_Displacement( EXEC_OPS + PCoordinates x, + PCoordinates y, + PGlyph_Zone zone, + UShort* refp ) + { + TGlyph_Zone zp; + UShort p; + TT_F26Dot6 d; + + + if ( CUR.opcode & 1 ) + { + zp = CUR.zp0; + p = CUR.GS.rp1; + } + else + { + zp = CUR.zp1; + p = CUR.GS.rp2; + } + + if ( BOUNDS( p, zp.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Displacement; + return FAILURE; + } + + *zone = zp; + *refp = p; + + d = CUR_Func_project( zp.cur + p, zp.org + p ); + + *x = TT_MulDiv(d, (Long)CUR.GS.freeVector.x * 0x10000L, CUR.F_dot_P ); + *y = TT_MulDiv(d, (Long)CUR.GS.freeVector.y * 0x10000L, CUR.F_dot_P ); + + return SUCCESS; + } + + + static void Move_Zp2_Point( EXEC_OPS + UShort point, + TT_F26Dot6 dx, + TT_F26Dot6 dy, + Bool touch ) + { + if ( CUR.GS.freeVector.x != 0 ) + { + CUR.zp2.cur[point].x += dx; + if ( touch ) + CUR.zp2.touch[point] |= TT_Flag_Touched_X; + } + + if ( CUR.GS.freeVector.y != 0 ) + { + CUR.zp2.cur[point].y += dy; + if ( touch ) + CUR.zp2.touch[point] |= TT_Flag_Touched_Y; + } + } + + +/**********************************************/ +/* SHP[a] : SHift Point by the last point */ +/* CodeRange : $32-33 */ +/* Stack : uint32... --> */ + + static void Ins_SHP( INS_ARG ) + { + TGlyph_Zone zp; + UShort refp; + + TT_F26Dot6 dx, + dy; + UShort point; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + point = (UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + /* UNDOCUMENTED! SHP touches the points */ + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* SHC[a] : SHift Contour */ +/* CodeRange : $34-35 */ +/* Stack : uint32 --> */ + + static void Ins_SHC( INS_ARG ) + { + TGlyph_Zone zp; + UShort refp; + TT_F26Dot6 dx, + dy; + + Short contour; + UShort first_point, last_point, i; + + + contour = (UShort)args[0]; + + if ( BOUNDS( contour, CUR.pts.n_contours ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( contour == 0 ) + first_point = 0; + else + first_point = CUR.pts.contours[contour - 1] + 1; + + last_point = CUR.pts.contours[contour]; + + /* XXX: this is probably wrong... at least it prevents memory */ + /* corruption when zp2 is the twilight zone */ + if ( last_point > CUR.zp2.n_points ) + { + if ( CUR.zp2.n_points > 0 ) + last_point = CUR.zp2.n_points - 1; + else + last_point = 0; + } + + /* UNDOCUMENTED! SHC doesn't touch the points */ + for ( i = first_point; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, FALSE ); + } + } + + +/**********************************************/ +/* SHZ[a] : SHift Zone */ +/* CodeRange : $36-37 */ +/* Stack : uint32 --> */ + + static void Ins_SHZ( INS_ARG ) + { + TGlyph_Zone zp; + UShort refp; + TT_F26Dot6 dx, + dy; + + UShort last_point, i; + + + if ( BOUNDS( args[0], 2 ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( CUR.zp2.n_points > 0 ) + last_point = CUR.zp2.n_points - 1; + else + last_point = 0; + + /* UNDOCUMENTED! SHZ doesn't touch the points */ + for ( i = 0; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, FALSE ); + } + } + + +/**********************************************/ +/* SHPIX[] : SHift points by a PIXel amount */ +/* CodeRange : $38 */ +/* Stack : f26.6 uint32... --> */ + + static void Ins_SHPIX( INS_ARG ) + { + TT_F26Dot6 dx, dy; + UShort point; + + + if ( CUR.top < CUR.GS.loop + 1 ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dx = TT_MulDiv( args[0], + (Long)CUR.GS.freeVector.x, + 0x4000 ); + dy = TT_MulDiv( args[0], + (Long)CUR.GS.freeVector.y, + 0x4000 ); + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* MSIRP[a] : Move Stack Indirect Relative */ +/* CodeRange : $3A-$3B */ +/* Stack : f26.6 uint32 --> */ + + static void Ins_MSIRP( INS_ARG ) + { + UShort point; + TT_F26Dot6 distance; + + + point = (UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: UNDOCUMENTED! behaviour */ + if ( CUR.GS.gep0 == 0 ) /* if in twilight zone */ + { + CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0]; + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, args[1] - distance ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( (CUR.opcode & 1) != 0 ) + CUR.GS.rp0 = point; + } + + +/**********************************************/ +/* MDAP[a] : Move Direct Absolute Point */ +/* CodeRange : $2E-$2F */ +/* Stack : uint32 --> */ + + static void Ins_MDAP( INS_ARG ) + { + UShort point; + TT_F26Dot6 cur_dist, + distance; + + + point = (UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? ? */ + if ( (CUR.opcode & 1) != 0 ) + { + cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + distance = CUR_Func_round( cur_dist, + CUR.metrics.compensations[0] ) - cur_dist; + } + else + distance = 0; + + CUR_Func_move( &CUR.zp0, point, distance ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + +/**********************************************/ +/* MIAP[a] : Move Indirect Absolute Point */ +/* CodeRange : $3E-$3F */ +/* Stack : uint32 uint32 --> */ + + static void Ins_MIAP( INS_ARG ) + { + ULong cvtEntry; + UShort point; + TT_F26Dot6 distance, + org_dist; + + + cvtEntry = (ULong)args[1]; + point = (UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* UNDOCUMENTED! */ + /* */ + /* The behaviour of an MIAP instruction is quite */ + /* different when used in the twilight zone. */ + /* */ + /* First, no control value cutin test is performed */ + /* as it would fail anyway. Second, the original */ + /* point, i.e. (org_x,org_y) of zp0.point, is set */ + /* to the absolute, unrounded distance found in */ + /* the CVT. */ + /* */ + /* This is used in the CVT programs of the Microsoft */ + /* fonts Arial, Times, etc., in order to re-adjust */ + /* some key font heights. It allows the use of the */ + /* IP instruction in the twilight zone, which */ + /* otherwise would be "illegal" according to the */ + /* specs :) */ + /* */ + /* We implement it with a special sequence for the */ + /* twilight zone. This is a bad hack, but it seems */ + /* to work. */ + + distance = CUR_Func_read_cvt( cvtEntry ); + + if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ + { + CUR.zp0.org[point].x = TT_MulDiv( CUR.GS.freeVector.x, + distance, 0x4000L ); + CUR.zp0.org[point].y = TT_MulDiv( CUR.GS.freeVector.y, + distance, 0x4000L ); + CUR.zp0.cur[point] = CUR.zp0.org[point]; + } + + org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + + if ( (CUR.opcode & 1) != 0 ) /* rounding and control cutin flag */ + { + if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) + distance = org_dist; + + distance = CUR_Func_round( distance, CUR.metrics.compensations[0] ); + } + + CUR_Func_move( &CUR.zp0, point, distance - org_dist ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + +/**********************************************/ +/* MDRP[abcde] : Move Direct Relative Point */ +/* CodeRange : $C0-$DF */ +/* Stack : uint32 --> */ + + static void Ins_MDRP( INS_ARG ) + { + UShort point; + TT_F26Dot6 org_dist, distance; + + + point = (UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? */ + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + /* single width cutin test */ + + if ( ABS( org_dist ) < CUR.GS.single_width_cutin ) + { + if ( org_dist >= 0 ) + org_dist = CUR.GS.single_width_value; + else + org_dist = -CUR.GS.single_width_value; + } + + /* round flag */ + + if ( (CUR.opcode & 4) != 0 ) + distance = CUR_Func_round( org_dist, + CUR.metrics.compensations[CUR.opcode & 3] ); + else + distance = Round_None( EXEC_ARGS + org_dist, + CUR.metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance flag */ + + if ( (CUR.opcode & 8) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + /* now move the point */ + + org_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, distance - org_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( (CUR.opcode & 16) != 0 ) + CUR.GS.rp0 = point; + } + + +/**********************************************/ +/* MIRP[abcde] : Move Indirect Relative Point */ +/* CodeRange : $E0-$FF */ +/* Stack : int32? uint32 --> */ + + static void Ins_MIRP( INS_ARG ) + { + UShort point; + ULong cvtEntry; + + TT_F26Dot6 cvt_dist, + distance, + cur_dist, + org_dist; + + + point = (UShort)args[0]; + cvtEntry = (ULong)(args[1] + 1); + + /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize + 1 ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( !cvtEntry ) + cvt_dist = 0; + else + cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 ); + + /* single width test */ + + if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin ) + { + if ( cvt_dist >= 0 ) + cvt_dist = CUR.GS.single_width_value; + else + cvt_dist = -CUR.GS.single_width_value; + } + + /* XXX : UNDOCUMENTED! -- twilight zone */ + + if ( CUR.GS.gep1 == 0 ) + { + CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + + TT_MulDiv( cvt_dist, + CUR.GS.freeVector.x, + 0x4000 ); + + CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + + TT_MulDiv( cvt_dist, + CUR.GS.freeVector.y, + 0x4000 ); + + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + cur_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + /* auto-flip test */ + + if ( CUR.GS.auto_flip ) + { + if ( (org_dist ^ cvt_dist) < 0 ) + cvt_dist = -cvt_dist; + } + + /* control value cutin and round */ + + if ( (CUR.opcode & 4) != 0 ) + { + /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ + /* refer to the same zone. */ + + if ( CUR.GS.gep0 == CUR.GS.gep1 ) + if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin ) + cvt_dist = org_dist; + + distance = CUR_Func_round( cvt_dist, + CUR.metrics.compensations[CUR.opcode & 3] ); + } + else + distance = Round_None( EXEC_ARGS + cvt_dist, + CUR.metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance test */ + + if ( (CUR.opcode & 8) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + CUR_Func_move( &CUR.zp1, point, distance - cur_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + + if ( (CUR.opcode & 16) != 0 ) + CUR.GS.rp0 = point; + + /* UNDOCUMENTED! */ + + CUR.GS.rp2 = point; + } + + +/**********************************************/ +/* ALIGNRP[] : ALIGN Relative Point */ +/* CodeRange : $3C */ +/* Stack : uint32 uint32... --> */ + + static void Ins_ALIGNRP( INS_ARG ) + { + UShort point; + TT_F26Dot6 distance; + + + if ( CUR.top < CUR.GS.loop || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, -distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* ISECT[] : moves point to InterSECTion */ +/* CodeRange : $0F */ +/* Stack : 5 * uint32 --> */ + + static void Ins_ISECT( INS_ARG ) + { + UShort point, + a0, a1, + b0, b1; + + TT_F26Dot6 discriminant; + + TT_F26Dot6 dx, dy, + dax, day, + dbx, dby; + + TT_F26Dot6 val; + + TT_Vector R; + + + point = (UShort)args[0]; + + a0 = (UShort)args[1]; + a1 = (UShort)args[2]; + b0 = (UShort)args[3]; + b1 = (UShort)args[4]; + + if ( BOUNDS( b0, CUR.zp0.n_points ) || + BOUNDS( b1, CUR.zp0.n_points ) || + BOUNDS( a0, CUR.zp1.n_points ) || + BOUNDS( a1, CUR.zp1.n_points ) || + BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x; + dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y; + + dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x; + day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y; + + dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x; + dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y; + + CUR.zp2.touch[point] |= TT_Flag_Touched_Both; + + discriminant = TT_MulDiv( dax, -dby, 0x40L ) + + TT_MulDiv( day, dbx, 0x40L ); + + if ( ABS( discriminant ) >= 0x40 ) + { + val = TT_MulDiv( dx, -dby, 0x40L ) + TT_MulDiv( dy, dbx, 0x40L ); + + R.x = TT_MulDiv( val, dax, discriminant ); + R.y = TT_MulDiv( val, day, discriminant ); + + CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x; + CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y; + } + else + { + /* else, take the middle of the middles of A and B */ + + CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x + + CUR.zp1.cur[a1].x + + CUR.zp0.cur[b0].x + + CUR.zp0.cur[b1].x ) / 4; + CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y + + CUR.zp1.cur[a1].y + + CUR.zp0.cur[b0].y + + CUR.zp0.cur[b1].y ) / 4; + } + } + + +/**********************************************/ +/* ALIGNPTS[] : ALIGN PoinTS */ +/* CodeRange : $27 */ +/* Stack : uint32 uint32 --> */ + + static void Ins_ALIGNPTS( INS_ARG ) + { + UShort p1, p2; + TT_F26Dot6 distance; + + + p1 = (UShort)args[0]; + p2 = (UShort)args[1]; + + if ( BOUNDS( args[0], CUR.zp1.n_points ) || + BOUNDS( args[1], CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + distance = CUR_Func_project( CUR.zp0.cur + p2, + CUR.zp1.cur + p1 ) / 2; + + CUR_Func_move( &CUR.zp1, p1, distance ); + CUR_Func_move( &CUR.zp0, p2, -distance ); + } + + +/**********************************************/ +/* IP[] : Interpolate Point */ +/* CodeRange : $39 */ +/* Stack : uint32... --> */ + + static void Ins_IP( INS_ARG ) + { + TT_F26Dot6 org_a, org_b, org_x, + cur_a, cur_b, cur_x, + distance; + UShort point; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: there are some glyphs in some braindead but popular */ + /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ + /* calling IP[] with bad values of rp[12] */ + /* do something sane when this odd thing happens */ + + if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) || + BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) ) + { + org_a = cur_a = 0; + org_b = cur_b = 0; + } + else + { + org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector ); + org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector ); + + cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector ); + cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector ); + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (UShort)CUR.stack[CUR.args]; + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector ); + cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector ); + + if ( ( org_a <= org_b && org_x <= org_a ) || + ( org_a > org_b && org_x >= org_a ) ) + + distance = ( cur_a - org_a ) + ( org_x - cur_x ); + + else if ( ( org_a <= org_b && org_x >= org_b ) || + ( org_a > org_b && org_x < org_b ) ) + + distance = ( cur_b - org_b ) + ( org_x - cur_x ); + + else + /* note: it seems that rounding this value isn't a good */ + /* idea (cf. width of capital 'S' in Times) */ + + distance = TT_MulDiv( cur_b - cur_a, + org_x - org_a, + org_b - org_a ) + ( cur_a - cur_x ); + + CUR_Func_move( &CUR.zp2, point, distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* UTP[a] : UnTouch Point */ +/* CodeRange : $29 */ +/* Stack : uint32 --> */ + + static void Ins_UTP( INS_ARG ) + { + UShort point; + Byte mask; + + + point = (UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + mask = 0xFF; + + if ( CUR.GS.freeVector.x != 0 ) + mask &= ~TT_Flag_Touched_X; + + if ( CUR.GS.freeVector.y != 0 ) + mask &= ~TT_Flag_Touched_Y; + + CUR.zp0.touch[point] &= mask; + } + + + /* Local variables for Ins_IUP: */ + struct LOC_Ins_IUP + { + TT_Vector* orgs; /* original and current coordinate */ + TT_Vector* curs; /* arrays */ + }; + + + static void Shift( UShort p1, + UShort p2, + UShort p, + struct LOC_Ins_IUP* LINK ) + { + UShort i; + TT_F26Dot6 x; + + + x = LINK->curs[p].x - LINK->orgs[p].x; + + for ( i = p1; i < p; i++ ) + LINK->curs[i].x += x; + + for ( i = p + 1; i <= p2; i++ ) + LINK->curs[i].x += x; + } + + + static void Interp( UShort p1, + UShort p2, + UShort ref1, + UShort ref2, + struct LOC_Ins_IUP* LINK ) + { + UShort i; + TT_F26Dot6 x, x1, x2, d1, d2; + + + if ( p1 > p2 ) + return; + + x1 = LINK->orgs[ref1].x; + d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x; + x2 = LINK->orgs[ref2].x; + d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x; + + if ( x1 == x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + x += d2; + + LINK->curs[i].x = x; + } + return; + } + + if ( x1 < x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + { + if ( x >= x2 ) + x += d2; + else + x = LINK->curs[ref1].x + + TT_MulDiv( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + return; + } + + /* x2 < x1 */ + + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + if ( x <= x2 ) + x += d2; + else + { + if ( x >= x1 ) + x += d1; + else + x = LINK->curs[ref1].x + + TT_MulDiv( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + } + + +/**********************************************/ +/* IUP[a] : Interpolate Untouched Points */ +/* CodeRange : $30-$31 */ +/* Stack : --> */ + + static void Ins_IUP( INS_ARG ) + { + struct LOC_Ins_IUP V; + Byte mask; + + UShort first_point; /* first point of contour */ + UShort end_point; /* end point (last+1) of contour */ + + UShort first_touched; /* first touched point in contour */ + UShort cur_touched; /* current touched point in contour */ + + UShort point; /* current point */ + Short contour; /* current contour */ + + + if ( CUR.opcode & 1 ) + { + mask = TT_Flag_Touched_X; + V.orgs = CUR.pts.org; + V.curs = CUR.pts.cur; + } + else + { + mask = TT_Flag_Touched_Y; + V.orgs = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.org) + 1 ); + V.curs = (TT_Vector*)( ((TT_F26Dot6*)CUR.pts.cur) + 1 ); + } + + contour = 0; + point = 0; + + do + { + end_point = CUR.pts.contours[contour]; + first_point = point; + + while ( point <= end_point && (CUR.pts.touch[point] & mask) == 0 ) + point++; + + if ( point <= end_point ) + { + first_touched = point; + cur_touched = point; + + point++; + + while ( point <= end_point ) + { + if ( (CUR.pts.touch[point] & mask) != 0 ) + { + if ( point > 0 ) + Interp( cur_touched + 1, + point - 1, + cur_touched, + point, + &V ); + cur_touched = point; + } + + point++; + } + + if ( cur_touched == first_touched ) + Shift( first_point, end_point, cur_touched, &V ); + else + { + Interp( cur_touched + 1, + end_point, + cur_touched, + first_touched, + &V ); + + if ( first_touched > 0 ) + Interp( first_point, + first_touched - 1, + cur_touched, + first_touched, + &V ); + } + } + contour++; + } while ( contour < CUR.pts.n_contours ); + } + + +/**********************************************/ +/* DELTAPn[] : DELTA Exceptions P1, P2, P3 */ +/* CodeRange : $5D,$71,$72 */ +/* Stack : uint32 (2 * uint32)... --> */ + + static void Ins_DELTAP( INS_ARG ) + { + ULong nump, k; + UShort A; + ULong C; + Long B; + + + nump = (ULong)args[0]; /* some points theoretically may occur more + than once, thus UShort isn't enough */ + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (UShort)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + /* XXX : because some popular fonts contain some invalid DeltaP */ + /* instructions, we simply ignore them when the stacked */ + /* point reference is off limit, rather than returning an */ + /* error. As a delta instruction doesn't change a glyph */ + /* in great ways, this shouldn't be a problem.. */ + + if ( !BOUNDS( A, CUR.zp0.n_points ) ) + { + C = ((ULong)B & 0xF0) >> 4; + + switch ( CUR.opcode ) + { + case 0x5d: + break; + + case 0x71: + C += 16; + break; + + case 0x72: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (Long)C ) + { + B = ((ULong)B & 0xF) - 8; + if ( B >= 0 ) + B++; + B = B * 64L / (1L << CUR.GS.delta_shift); + + CUR_Func_move( &CUR.zp0, A, B ); + } + } + else + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + } + + CUR.new_top = CUR.args; + } + + +/**********************************************/ +/* DELTACn[] : DELTA Exceptions C1, C2, C3 */ +/* CodeRange : $73,$74,$75 */ +/* Stack : uint32 (2 * uint32)... --> */ + + static void Ins_DELTAC( INS_ARG ) + { + ULong nump, k; + ULong A, C; + Long B; + + + nump = (ULong)args[0]; + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (ULong)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + if ( BOUNDS( A, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + C = ((ULong)B & 0xF0) >> 4; + + switch ( CUR.opcode ) + { + case 0x73: + break; + + case 0x74: + C += 16; + break; + + case 0x75: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (Long)C ) + { + B = ((ULong)B & 0xF) - 8; + if ( B >= 0 ) + B++; + B = B * 64L / (1L << CUR.GS.delta_shift); + + CUR_Func_move_cvt( A, B ); + } + } + } + + CUR.new_top = CUR.args; + } + + + +/****************************************************************/ +/* */ +/* MISC. INSTRUCTIONS */ +/* */ +/****************************************************************/ + + +/**********************************************/ +/* GETINFO[] : GET INFOrmation */ +/* CodeRange : $88 */ +/* Stack : uint32 --> uint32 */ + +/* XXX According to Apple specs, bits 1 & 2 of the argument ought to be */ +/* consulted before rotated / stretched info is returned */ + + static void Ins_GETINFO( INS_ARG ) + { + Long K; + + + K = 0; + + /* We return then Windows 3.1 version number */ + /* for the font scaler */ + if ( (args[0] & 1) != 0 ) + K = 3; + + /* Has the glyph been rotated ? */ + if ( CUR.metrics.rotated ) + K |= 0x80; + + /* Has the glyph been stretched ? */ + if ( CUR.metrics.stretched ) + K |= 0x100; + + args[0] = K; + } + + + static void Ins_UNKNOWN( INS_ARG ) + { + /* look up the current instruction in our table */ + PDefRecord def, limit; + + def = CUR.IDefs; + limit = def + CUR.numIDefs; + for ( ; def < limit; def++ ) + { + if ( def->Opc == CUR.opcode && def->Active ) + { + PCallRecord pCrec; + + /* implement instruction as a function call */ + + /* check call stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = 1; + pCrec->Cur_Restart = def->Start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->Range, + def->Start ); + + CUR.step_ins = FALSE; + return; + } + } + + CUR.error = TT_Err_Invalid_Opcode; + } + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + static TInstruction_Function Instruct_Dispatch[256] = + { + /* Opcodes are gathered in groups of 16. */ + /* Please keep the spaces as they are. */ + + /* SVTCA y */ Ins_SVTCA, + /* SVTCA x */ Ins_SVTCA, + /* SPvTCA y */ Ins_SPVTCA, + /* SPvTCA x */ Ins_SPVTCA, + /* SFvTCA y */ Ins_SFVTCA, + /* SFvTCA x */ Ins_SFVTCA, + /* SPvTL // */ Ins_SPVTL, + /* SPvTL + */ Ins_SPVTL, + /* SFvTL // */ Ins_SFVTL, + /* SFvTL + */ Ins_SFVTL, + /* SPvFS */ Ins_SPVFS, + /* SFvFS */ Ins_SFVFS, + /* GPV */ Ins_GPV, + /* GFV */ Ins_GFV, + /* SFvTPv */ Ins_SFVTPV, + /* ISECT */ Ins_ISECT, + + /* SRP0 */ Ins_SRP0, + /* SRP1 */ Ins_SRP1, + /* SRP2 */ Ins_SRP2, + /* SZP0 */ Ins_SZP0, + /* SZP1 */ Ins_SZP1, + /* SZP2 */ Ins_SZP2, + /* SZPS */ Ins_SZPS, + /* SLOOP */ Ins_SLOOP, + /* RTG */ Ins_RTG, + /* RTHG */ Ins_RTHG, + /* SMD */ Ins_SMD, + /* ELSE */ Ins_ELSE, + /* JMPR */ Ins_JMPR, + /* SCvTCi */ Ins_SCVTCI, + /* SSwCi */ Ins_SSWCI, + /* SSW */ Ins_SSW, + + /* DUP */ Ins_DUP, + /* POP */ Ins_POP, + /* CLEAR */ Ins_CLEAR, + /* SWAP */ Ins_SWAP, + /* DEPTH */ Ins_DEPTH, + /* CINDEX */ Ins_CINDEX, + /* MINDEX */ Ins_MINDEX, + /* AlignPTS */ Ins_ALIGNPTS, + /* INS_$28 */ Ins_UNKNOWN, + /* UTP */ Ins_UTP, + /* LOOPCALL */ Ins_LOOPCALL, + /* CALL */ Ins_CALL, + /* FDEF */ Ins_FDEF, + /* ENDF */ Ins_ENDF, + /* MDAP[0] */ Ins_MDAP, + /* MDAP[1] */ Ins_MDAP, + + /* IUP[0] */ Ins_IUP, + /* IUP[1] */ Ins_IUP, + /* SHP[0] */ Ins_SHP, + /* SHP[1] */ Ins_SHP, + /* SHC[0] */ Ins_SHC, + /* SHC[1] */ Ins_SHC, + /* SHZ[0] */ Ins_SHZ, + /* SHZ[1] */ Ins_SHZ, + /* SHPIX */ Ins_SHPIX, + /* IP */ Ins_IP, + /* MSIRP[0] */ Ins_MSIRP, + /* MSIRP[1] */ Ins_MSIRP, + /* AlignRP */ Ins_ALIGNRP, + /* RTDG */ Ins_RTDG, + /* MIAP[0] */ Ins_MIAP, + /* MIAP[1] */ Ins_MIAP, + + /* NPushB */ Ins_NPUSHB, + /* NPushW */ Ins_NPUSHW, + /* WS */ Ins_WS, + /* RS */ Ins_RS, + /* WCvtP */ Ins_WCVTP, + /* RCvt */ Ins_RCVT, + /* GC[0] */ Ins_GC, + /* GC[1] */ Ins_GC, + /* SCFS */ Ins_SCFS, + /* MD[0] */ Ins_MD, + /* MD[1] */ Ins_MD, + /* MPPEM */ Ins_MPPEM, + /* MPS */ Ins_MPS, + /* FlipON */ Ins_FLIPON, + /* FlipOFF */ Ins_FLIPOFF, + /* DEBUG */ Ins_DEBUG, + + /* LT */ Ins_LT, + /* LTEQ */ Ins_LTEQ, + /* GT */ Ins_GT, + /* GTEQ */ Ins_GTEQ, + /* EQ */ Ins_EQ, + /* NEQ */ Ins_NEQ, + /* ODD */ Ins_ODD, + /* EVEN */ Ins_EVEN, + /* IF */ Ins_IF, + /* EIF */ Ins_EIF, + /* AND */ Ins_AND, + /* OR */ Ins_OR, + /* NOT */ Ins_NOT, + /* DeltaP1 */ Ins_DELTAP, + /* SDB */ Ins_SDB, + /* SDS */ Ins_SDS, + + /* ADD */ Ins_ADD, + /* SUB */ Ins_SUB, + /* DIV */ Ins_DIV, + /* MUL */ Ins_MUL, + /* ABS */ Ins_ABS, + /* NEG */ Ins_NEG, + /* FLOOR */ Ins_FLOOR, + /* CEILING */ Ins_CEILING, + /* ROUND[0] */ Ins_ROUND, + /* ROUND[1] */ Ins_ROUND, + /* ROUND[2] */ Ins_ROUND, + /* ROUND[3] */ Ins_ROUND, + /* NROUND[0] */ Ins_NROUND, + /* NROUND[1] */ Ins_NROUND, + /* NROUND[2] */ Ins_NROUND, + /* NROUND[3] */ Ins_NROUND, + + /* WCvtF */ Ins_WCVTF, + /* DeltaP2 */ Ins_DELTAP, + /* DeltaP3 */ Ins_DELTAP, + /* DeltaCn[0] */ Ins_DELTAC, + /* DeltaCn[1] */ Ins_DELTAC, + /* DeltaCn[2] */ Ins_DELTAC, + /* SROUND */ Ins_SROUND, + /* S45Round */ Ins_S45ROUND, + /* JROT */ Ins_JROT, + /* JROF */ Ins_JROF, + /* ROFF */ Ins_ROFF, + /* INS_$7B */ Ins_UNKNOWN, + /* RUTG */ Ins_RUTG, + /* RDTG */ Ins_RDTG, + /* SANGW */ Ins_SANGW, + /* AA */ Ins_AA, + + /* FlipPT */ Ins_FLIPPT, + /* FlipRgON */ Ins_FLIPRGON, + /* FlipRgOFF */ Ins_FLIPRGOFF, + /* INS_$83 */ Ins_UNKNOWN, + /* INS_$84 */ Ins_UNKNOWN, + /* ScanCTRL */ Ins_SCANCTRL, + /* SDPVTL[0] */ Ins_SDPVTL, + /* SDPVTL[1] */ Ins_SDPVTL, + /* GetINFO */ Ins_GETINFO, + /* IDEF */ Ins_IDEF, + /* ROLL */ Ins_ROLL, + /* MAX */ Ins_MAX, + /* MIN */ Ins_MIN, + /* ScanTYPE */ Ins_SCANTYPE, + /* InstCTRL */ Ins_INSTCTRL, + /* INS_$8F */ Ins_UNKNOWN, + + /* INS_$90 */ Ins_UNKNOWN, + /* INS_$91 */ Ins_UNKNOWN, + /* INS_$92 */ Ins_UNKNOWN, + /* INS_$93 */ Ins_UNKNOWN, + /* INS_$94 */ Ins_UNKNOWN, + /* INS_$95 */ Ins_UNKNOWN, + /* INS_$96 */ Ins_UNKNOWN, + /* INS_$97 */ Ins_UNKNOWN, + /* INS_$98 */ Ins_UNKNOWN, + /* INS_$99 */ Ins_UNKNOWN, + /* INS_$9A */ Ins_UNKNOWN, + /* INS_$9B */ Ins_UNKNOWN, + /* INS_$9C */ Ins_UNKNOWN, + /* INS_$9D */ Ins_UNKNOWN, + /* INS_$9E */ Ins_UNKNOWN, + /* INS_$9F */ Ins_UNKNOWN, + + /* INS_$A0 */ Ins_UNKNOWN, + /* INS_$A1 */ Ins_UNKNOWN, + /* INS_$A2 */ Ins_UNKNOWN, + /* INS_$A3 */ Ins_UNKNOWN, + /* INS_$A4 */ Ins_UNKNOWN, + /* INS_$A5 */ Ins_UNKNOWN, + /* INS_$A6 */ Ins_UNKNOWN, + /* INS_$A7 */ Ins_UNKNOWN, + /* INS_$A8 */ Ins_UNKNOWN, + /* INS_$A9 */ Ins_UNKNOWN, + /* INS_$AA */ Ins_UNKNOWN, + /* INS_$AB */ Ins_UNKNOWN, + /* INS_$AC */ Ins_UNKNOWN, + /* INS_$AD */ Ins_UNKNOWN, + /* INS_$AE */ Ins_UNKNOWN, + /* INS_$AF */ Ins_UNKNOWN, + + /* PushB[0] */ Ins_PUSHB, + /* PushB[1] */ Ins_PUSHB, + /* PushB[2] */ Ins_PUSHB, + /* PushB[3] */ Ins_PUSHB, + /* PushB[4] */ Ins_PUSHB, + /* PushB[5] */ Ins_PUSHB, + /* PushB[6] */ Ins_PUSHB, + /* PushB[7] */ Ins_PUSHB, + /* PushW[0] */ Ins_PUSHW, + /* PushW[1] */ Ins_PUSHW, + /* PushW[2] */ Ins_PUSHW, + /* PushW[3] */ Ins_PUSHW, + /* PushW[4] */ Ins_PUSHW, + /* PushW[5] */ Ins_PUSHW, + /* PushW[6] */ Ins_PUSHW, + /* PushW[7] */ Ins_PUSHW, + + /* MDRP[00] */ Ins_MDRP, + /* MDRP[01] */ Ins_MDRP, + /* MDRP[02] */ Ins_MDRP, + /* MDRP[03] */ Ins_MDRP, + /* MDRP[04] */ Ins_MDRP, + /* MDRP[05] */ Ins_MDRP, + /* MDRP[06] */ Ins_MDRP, + /* MDRP[07] */ Ins_MDRP, + /* MDRP[08] */ Ins_MDRP, + /* MDRP[09] */ Ins_MDRP, + /* MDRP[10] */ Ins_MDRP, + /* MDRP[11] */ Ins_MDRP, + /* MDRP[12] */ Ins_MDRP, + /* MDRP[13] */ Ins_MDRP, + /* MDRP[14] */ Ins_MDRP, + /* MDRP[15] */ Ins_MDRP, + + /* MDRP[16] */ Ins_MDRP, + /* MDRP[17] */ Ins_MDRP, + /* MDRP[18] */ Ins_MDRP, + /* MDRP[19] */ Ins_MDRP, + /* MDRP[20] */ Ins_MDRP, + /* MDRP[21] */ Ins_MDRP, + /* MDRP[22] */ Ins_MDRP, + /* MDRP[23] */ Ins_MDRP, + /* MDRP[24] */ Ins_MDRP, + /* MDRP[25] */ Ins_MDRP, + /* MDRP[26] */ Ins_MDRP, + /* MDRP[27] */ Ins_MDRP, + /* MDRP[28] */ Ins_MDRP, + /* MDRP[29] */ Ins_MDRP, + /* MDRP[30] */ Ins_MDRP, + /* MDRP[31] */ Ins_MDRP, + + /* MIRP[00] */ Ins_MIRP, + /* MIRP[01] */ Ins_MIRP, + /* MIRP[02] */ Ins_MIRP, + /* MIRP[03] */ Ins_MIRP, + /* MIRP[04] */ Ins_MIRP, + /* MIRP[05] */ Ins_MIRP, + /* MIRP[06] */ Ins_MIRP, + /* MIRP[07] */ Ins_MIRP, + /* MIRP[08] */ Ins_MIRP, + /* MIRP[09] */ Ins_MIRP, + /* MIRP[10] */ Ins_MIRP, + /* MIRP[11] */ Ins_MIRP, + /* MIRP[12] */ Ins_MIRP, + /* MIRP[13] */ Ins_MIRP, + /* MIRP[14] */ Ins_MIRP, + /* MIRP[15] */ Ins_MIRP, + + /* MIRP[16] */ Ins_MIRP, + /* MIRP[17] */ Ins_MIRP, + /* MIRP[18] */ Ins_MIRP, + /* MIRP[19] */ Ins_MIRP, + /* MIRP[20] */ Ins_MIRP, + /* MIRP[21] */ Ins_MIRP, + /* MIRP[22] */ Ins_MIRP, + /* MIRP[23] */ Ins_MIRP, + /* MIRP[24] */ Ins_MIRP, + /* MIRP[25] */ Ins_MIRP, + /* MIRP[26] */ Ins_MIRP, + /* MIRP[27] */ Ins_MIRP, + /* MIRP[28] */ Ins_MIRP, + /* MIRP[29] */ Ins_MIRP, + /* MIRP[30] */ Ins_MIRP, + /* MIRP[31] */ Ins_MIRP + }; +#endif + + +/****************************************************************/ +/* */ +/* RUN */ +/* */ +/* This function executes a run of opcodes. It will exit */ +/* in the following cases: */ +/* */ +/* - Errors (in which case it returns FALSE) */ +/* */ +/* - Reaching the end of the main code range (returns TRUE). */ +/* Reaching the end of a code range within a function */ +/* call is an error. */ +/* */ +/* - After executing one single opcode, if the flag */ +/* 'Instruction_Trap' is set to TRUE (returns TRUE). */ +/* */ +/* On exit whith TRUE, test IP < CodeSize to know wether it */ +/* comes from a instruction trap or a normal termination. */ +/* */ +/* */ +/* Note: The documented DEBUG opcode pops a value from */ +/* the stack. This behaviour is unsupported, here */ +/* a DEBUG opcode is always an error. */ +/* */ +/* */ +/* THIS IS THE INTERPRETER'S MAIN LOOP */ +/* */ +/* Instructions appear in the specs' order. */ +/* */ +/****************************************************************/ + + LOCAL_FUNC +#ifndef DEBUG_INTERPRETER + TT_Error RunIns( PExecution_Context exc ) +#else + TT_Error RunIns2( PExecution_Context exc ) +#endif + { + UShort A; + PDefRecord WITH; + PCallRecord WITH1; + + Long ins_counter = 0; /* executed instructions counter */ + +#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER + cur = *exc; +#endif + + /* set CVT functions */ + CUR.metrics.ratio = 0; + if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) + { + /* non-square pixels, use the stretched routines */ + CUR.func_read_cvt = Read_CVT_Stretched; + CUR.func_write_cvt = Write_CVT_Stretched; + CUR.func_move_cvt = Move_CVT_Stretched; + } + else + { + /* square pixels, use normal routines */ + CUR.func_read_cvt = Read_CVT; + CUR.func_write_cvt = Write_CVT; + CUR.func_move_cvt = Move_CVT; + } + + COMPUTE_Funcs(); + Compute_Round( EXEC_ARGS (Byte)exc->GS.round_state ); + + do + { + if ( CALC_Length() != SUCCESS ) + { + CUR.error = TT_Err_Code_Overflow; + goto LErrorLabel_; + } + + /* First, let's check for empty stack and overflow */ + + CUR.args = CUR.top - (Pop_Push_Count[CUR.opcode] >> 4); + + /* `args' is the top of the stack once arguments have been popped. */ + /* One can also interpret it as the index of the last argument. */ + + if ( CUR.args < 0 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + goto LErrorLabel_; + } + + CUR.new_top = CUR.args + (Pop_Push_Count[CUR.opcode] & 15); + + /* `new_top' is the new top of the stack, after the instruction's */ + /* execution. `top' will be set to `new_top' after the 'switch' */ + /* statement. */ + + if ( CUR.new_top > CUR.stackSize ) + { + CUR.error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + + CUR.step_ins = TRUE; + CUR.error = TT_Err_Ok; + +#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH + { + PStorage args = CUR.stack + CUR.args; + Byte opcode = CUR.opcode; + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref + + switch ( opcode ) + { + case 0x00: /* SVTCA y */ + case 0x01: /* SVTCA x */ + case 0x02: /* SPvTCA y */ + case 0x03: /* SPvTCA x */ + case 0x04: /* SFvTCA y */ + case 0x05: /* SFvTCA x */ + { + Short AA, BB; + + + AA = (Short)(opcode & 1) << 14; + BB = AA ^ (Short)0x4000; + + if ( opcode < 4 ) + { + CUR.GS.projVector.x = AA; + CUR.GS.projVector.y = BB; + + CUR.GS.dualVector.x = AA; + CUR.GS.dualVector.y = BB; + } + + if ( (opcode & 2) == 0 ) + { + CUR.GS.freeVector.x = AA; + CUR.GS.freeVector.y = BB; + } + + COMPUTE_Funcs(); + } + break; + + case 0x06: /* SPvTL // */ + case 0x07: /* SPvTL + */ + DO_SPVTL + break; + + case 0x08: /* SFvTL // */ + case 0x09: /* SFvTL + */ + DO_SFVTL + break; + + case 0x0A: /* SPvFS */ + DO_SPVFS + break; + + case 0x0B: /* SFvFS */ + DO_SFVFS + break; + + case 0x0C: /* GPV */ + DO_GPV + break; + + case 0x0D: /* GFV */ + DO_GFV + break; + + case 0x0E: /* SFvTPv */ + DO_SFVTPV + break; + + case 0x0F: /* ISECT */ + Ins_ISECT( EXEC_ARGS args ); + break; + + case 0x10: /* SRP0 */ + DO_SRP0 + break; + + case 0x11: /* SRP1 */ + DO_SRP1 + break; + + case 0x12: /* SRP2 */ + DO_SRP2 + break; + + case 0x13: /* SZP0 */ + Ins_SZP0( EXEC_ARGS args ); + break; + + case 0x14: /* SZP1 */ + Ins_SZP1( EXEC_ARGS args ); + break; + + case 0x15: /* SZP2 */ + Ins_SZP2( EXEC_ARGS args ); + break; + + case 0x16: /* SZPS */ + Ins_SZPS( EXEC_ARGS args ); + break; + + case 0x17: /* SLOOP */ + DO_SLOOP + break; + + case 0x18: /* RTG */ + DO_RTG + break; + + case 0x19: /* RTHG */ + DO_RTHG + break; + + case 0x1A: /* SMD */ + DO_SMD + break; + + case 0x1B: /* ELSE */ + Ins_ELSE( EXEC_ARGS args ); + break; + + case 0x1C: /* JMPR */ + DO_JMPR + break; + + case 0x1D: /* SCVTCI */ + DO_SCVTCI + break; + + case 0x1E: /* SSWCI */ + DO_SSWCI + break; + + case 0x1F: /* SSW */ + DO_SSW + break; + + case 0x20: /* DUP */ + DO_DUP + break; + + case 0x21: /* POP */ + /* nothing :-) !! */ + break; + + case 0x22: /* CLEAR */ + DO_CLEAR + break; + + case 0x23: /* SWAP */ + DO_SWAP + break; + + case 0x24: /* DEPTH */ + DO_DEPTH + break; + + case 0x25: /* CINDEX */ + DO_CINDEX + break; + + case 0x26: /* MINDEX */ + Ins_MINDEX( EXEC_ARGS args ); + break; + + case 0x27: /* ALIGNPTS */ + Ins_ALIGNPTS( EXEC_ARGS args ); + break; + + case 0x28: /* ???? */ + Ins_UNKNOWN( EXEC_ARGS args ); + break; + + case 0x29: /* UTP */ + Ins_UTP( EXEC_ARGS args ); + break; + + case 0x2A: /* LOOPCALL */ + Ins_LOOPCALL( EXEC_ARGS args ); + break; + + case 0x2B: /* CALL */ + Ins_CALL( EXEC_ARGS args ); + break; + + case 0x2C: /* FDEF */ + Ins_FDEF( EXEC_ARGS args ); + break; + + case 0x2D: /* ENDF */ + Ins_ENDF( EXEC_ARGS args ); + break; + + case 0x2E: /* MDAP */ + case 0x2F: /* MDAP */ + Ins_MDAP( EXEC_ARGS args ); + break; + + + case 0x30: /* IUP */ + case 0x31: /* IUP */ + Ins_IUP( EXEC_ARGS args ); + break; + + case 0x32: /* SHP */ + case 0x33: /* SHP */ + Ins_SHP( EXEC_ARGS args ); + break; + + case 0x34: /* SHC */ + case 0x35: /* SHC */ + Ins_SHC( EXEC_ARGS args ); + break; + + case 0x36: /* SHZ */ + case 0x37: /* SHZ */ + Ins_SHZ( EXEC_ARGS args ); + break; + + case 0x38: /* SHPIX */ + Ins_SHPIX( EXEC_ARGS args ); + break; + + case 0x39: /* IP */ + Ins_IP( EXEC_ARGS args ); + break; + + case 0x3A: /* MSIRP */ + case 0x3B: /* MSIRP */ + Ins_MSIRP( EXEC_ARGS args ); + break; + + case 0x3C: /* AlignRP */ + Ins_ALIGNRP( EXEC_ARGS args ); + break; + + case 0x3D: /* RTDG */ + DO_RTDG + break; + + case 0x3E: /* MIAP */ + case 0x3F: /* MIAP */ + Ins_MIAP( EXEC_ARGS args ); + break; + + case 0x40: /* NPUSHB */ + Ins_NPUSHB( EXEC_ARGS args ); + break; + + case 0x41: /* NPUSHW */ + Ins_NPUSHW( EXEC_ARGS args ); + break; + + case 0x42: /* WS */ + DO_WS + break; + + Set_Invalid_Ref: + CUR.error = TT_Err_Invalid_Reference; + break; + + case 0x43: /* RS */ + DO_RS + break; + + case 0x44: /* WCVTP */ + DO_WCVTP + break; + + case 0x45: /* RCVT */ + DO_RCVT + break; + + case 0x46: /* GC */ + case 0x47: /* GC */ + Ins_GC( EXEC_ARGS args ); + break; + + case 0x48: /* SCFS */ + Ins_SCFS( EXEC_ARGS args ); + break; + + case 0x49: /* MD */ + case 0x4A: /* MD */ + Ins_MD( EXEC_ARGS args ); + break; + + case 0x4B: /* MPPEM */ + DO_MPPEM + break; + + case 0x4C: /* MPS */ + DO_MPS + break; + + case 0x4D: /* FLIPON */ + DO_FLIPON + break; + + case 0x4E: /* FLIPOFF */ + DO_FLIPOFF + break; + + case 0x4F: /* DEBUG */ + DO_DEBUG + break; + + case 0x50: /* LT */ + DO_LT + break; + + case 0x51: /* LTEQ */ + DO_LTEQ + break; + + case 0x52: /* GT */ + DO_GT + break; + + case 0x53: /* GTEQ */ + DO_GTEQ + break; + + case 0x54: /* EQ */ + DO_EQ + break; + + case 0x55: /* NEQ */ + DO_NEQ + break; + + case 0x56: /* ODD */ + DO_ODD + break; + + case 0x57: /* EVEN */ + DO_EVEN + break; + + case 0x58: /* IF */ + Ins_IF( EXEC_ARGS args ); + break; + + case 0x59: /* EIF */ + /* do nothing */ + break; + + case 0x5A: /* AND */ + DO_AND + break; + + case 0x5B: /* OR */ + DO_OR + break; + + case 0x5C: /* NOT */ + DO_NOT + break; + + case 0x5D: /* DELTAP1 */ + Ins_DELTAP( EXEC_ARGS args ); + break; + + case 0x5E: /* SDB */ + DO_SDB + break; + + case 0x5F: /* SDS */ + DO_SDS + break; + + case 0x60: /* ADD */ + DO_ADD + break; + + case 0x61: /* SUB */ + DO_SUB + break; + + case 0x62: /* DIV */ + DO_DIV + break; + + case 0x63: /* MUL */ + DO_MUL + break; + + case 0x64: /* ABS */ + DO_ABS + break; + + case 0x65: /* NEG */ + DO_NEG + break; + + case 0x66: /* FLOOR */ + DO_FLOOR + break; + + case 0x67: /* CEILING */ + DO_CEILING + break; + + case 0x68: /* ROUND */ + case 0x69: /* ROUND */ + case 0x6A: /* ROUND */ + case 0x6B: /* ROUND */ + DO_ROUND + break; + + case 0x6C: /* NROUND */ + case 0x6D: /* NROUND */ + case 0x6E: /* NRRUND */ + case 0x6F: /* NROUND */ + DO_NROUND + break; + + case 0x70: /* WCVTF */ + DO_WCVTF + break; + + case 0x71: /* DELTAP2 */ + case 0x72: /* DELTAP3 */ + Ins_DELTAP( EXEC_ARGS args ); + break; + + case 0x73: /* DELTAC0 */ + case 0x74: /* DELTAC1 */ + case 0x75: /* DELTAC2 */ + Ins_DELTAC( EXEC_ARGS args ); + break; + + case 0x76: /* SROUND */ + DO_SROUND + break; + + case 0x77: /* S45Round */ + DO_S45ROUND + break; + + case 0x78: /* JROT */ + DO_JROT + break; + + case 0x79: /* JROF */ + DO_JROF + break; + + case 0x7A: /* ROFF */ + DO_ROFF + break; + + case 0x7B: /* ???? */ + Ins_UNKNOWN( EXEC_ARGS args ); + break; + + case 0x7C: /* RUTG */ + DO_RUTG + break; + + case 0x7D: /* RDTG */ + DO_RDTG + break; + + case 0x7E: /* SANGW */ + case 0x7F: /* AA */ + /* nothing - obsolete */ + break; + + case 0x80: /* FLIPPT */ + Ins_FLIPPT( EXEC_ARGS args ); + break; + + case 0x81: /* FLIPRGON */ + Ins_FLIPRGON( EXEC_ARGS args ); + break; + + case 0x82: /* FLIPRGOFF */ + Ins_FLIPRGOFF( EXEC_ARGS args ); + break; + + case 0x83: /* UNKNOWN */ + case 0x84: /* UNKNOWN */ + Ins_UNKNOWN( EXEC_ARGS args ); + break; + + case 0x85: /* SCANCTRL */ + Ins_SCANCTRL( EXEC_ARGS args ); + break; + + case 0x86: /* SDPVTL */ + case 0x87: /* SDPVTL */ + Ins_SDPVTL( EXEC_ARGS args ); + break; + + case 0x88: /* GETINFO */ + Ins_GETINFO( EXEC_ARGS args ); + break; + + case 0x89: /* IDEF */ + Ins_IDEF( EXEC_ARGS args ); + break; + + case 0x8A: /* ROLL */ + Ins_ROLL( EXEC_ARGS args ); + break; + + case 0x8B: /* MAX */ + DO_MAX + break; + + case 0x8C: /* MIN */ + DO_MIN + break; + + case 0x8D: /* SCANTYPE */ + Ins_SCANTYPE( EXEC_ARGS args ); + break; + + case 0x8E: /* INSTCTRL */ + Ins_INSTCTRL( EXEC_ARGS args ); + break; + + case 0x8F: + Ins_UNKNOWN( EXEC_ARGS args ); + break; + + default: + if ( opcode >= 0xE0 ) + Ins_MIRP( EXEC_ARGS args ); + else if ( opcode >= 0xC0 ) + Ins_MDRP( EXEC_ARGS args ); + else if ( opcode >= 0xB8 ) + Ins_PUSHW( EXEC_ARGS args ); + else if ( opcode >= 0xB0 ) + Ins_PUSHB( EXEC_ARGS args ); + else + Ins_UNKNOWN( EXEC_ARGS args ); + } + + } +#else + Instruct_Dispatch[CUR.opcode]( EXEC_ARGS &CUR.stack[CUR.args] ); +#endif + if ( CUR.error != TT_Err_Ok ) + { + switch ( (Int)(CUR.error) ) + { + case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ + A = 0; + + while ( A < CUR.numIDefs ) + { + WITH = &CUR.IDefs[A]; + + if ( WITH->Active && CUR.opcode == WITH->Opc ) + { + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Invalid_Reference; + goto LErrorLabel_; + } + + WITH1 = &CUR.callStack[CUR.callTop]; + + WITH1->Caller_Range = CUR.curRange; + WITH1->Caller_IP = CUR.IP + 1; + WITH1->Cur_Count = 1; + WITH1->Cur_Restart = WITH->Start; + + if ( INS_Goto_CodeRange( WITH->Range, WITH->Start ) == FAILURE ) + goto LErrorLabel_; + + goto LSuiteLabel_; + } + else + { + A++; + continue; + } + } + + CUR.error = TT_Err_Invalid_Opcode; + goto LErrorLabel_; +/* break; Unreachable code warning suppress. Leave in case a later + change to remind the editor to consider break; */ + + default: + goto LErrorLabel_; +/* break; */ + } + } + + CUR.top = CUR.new_top; + + if ( CUR.step_ins ) + CUR.IP += CUR.length; + + /* increment instruction counter and check if we didn't */ + /* run this program for too long ?? (e.g. infinite loops) */ + if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) + { + CUR.error = TT_Err_Execution_Too_Long; + goto LErrorLabel_; + } + + LSuiteLabel_: + + if ( CUR.IP >= CUR.codeSize ) + { + if ( CUR.callTop > 0 ) + { + CUR.error = TT_Err_Code_Overflow; + goto LErrorLabel_; + } + else + goto LNo_Error_; + } + } while ( !CUR.instruction_trap ); + + LNo_Error_: + CUR.error = TT_Err_Ok; + + LErrorLabel_: + +#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER + *exc = cur; +#endif + + return CUR.error; + + + } + + +#ifdef DEBUG_INTERPRETER + + /* This function must be declared by the debugger front end */ + /* in order to specify which code range to debug. */ + + int debug_coderange = TT_CodeRange_Glyph; + + + LOCAL_FUNC + TT_Error RunIns( PExecution_Context exc ) + { + Int A, diff; + ULong next_IP; + Char ch, oldch; + char *temp; + int key; + + TT_Error error = 0; + + TGlyph_Zone save; + TGlyph_Zone pts; + +#define TT_Round_Off 5 +#define TT_Round_To_Half_Grid 0 +#define TT_Round_To_Grid 1 +#define TT_Round_To_Double_Grid 2 +#define TT_Round_Up_To_Grid 4 +#define TT_Round_Down_To_Grid 3 +#define TT_Round_Super 6 +#define TT_Round_Super_45 7 + + const String* round_str[8] = + { + "to half-grid", + "to grid", + "to double grid", + "down to grid", + "up to grid", + "off", + "super", + "super 45" + }; + + /* Check that we're running the code range that is effectively */ + /* asked by the debugger front end. */ + if ( exc->curRange != debug_coderange ) + return RunIns2( exc ); + + pts = exc->pts; + + save.n_points = pts.n_points; + save.n_contours = pts.n_contours; + + MEM_Alloc( save.org, sizeof ( TT_Vector ) * save.n_points ); + MEM_Alloc( save.cur, sizeof ( TT_Vector ) * save.n_points ); + MEM_Alloc( save.touch, sizeof ( Byte ) * save.n_points ); + + exc->instruction_trap = 1; + + oldch = '\0'; + + do + { + if ( exc->IP < exc->codeSize ) + { +#ifdef TT_CONFIG_OPTION_STATIC_INTERPRETER + cur = *exc; +#endif + CALC_Length(); + + exc->args = exc->top - (Pop_Push_Count[exc->opcode] >> 4); + + /* `args' is the top of the stack once arguments have been popped. */ + /* One can also interpret it as the index of the last argument. */ + + /* Print the current line. We use a 80-columns console with the */ + /* following formatting: */ + /* */ + /* [loc]:[addr] [opcode] [disassemby] [a][b]|[c][d] */ + /* */ + + { + char temp[80]; + int n, col, pop; + int args = CUR.args; + + + sprintf( temp, "%78c\n", ' ' ); + + /* first letter of location */ + switch ( CUR.curRange ) + { + case TT_CodeRange_Glyph: + temp[0] = 'g'; + break; + case TT_CodeRange_Cvt: + temp[0] = 'c'; + break; + default: + temp[0] = 'f'; + } + + /* current IP */ + sprintf( temp+1, "%04lx: %02x %-36.36s", + CUR.IP, + CUR.opcode, + Cur_U_Line(&CUR) ); + + strncpy( temp+46, " (", 2 ); + + args = CUR.top - 1; + pop = Pop_Push_Count[CUR.opcode] >> 4; + col = 48; + for ( n = 6; n > 0; n-- ) + { + if ( pop == 0 ) + temp[col-1] = (temp[col-1] == '(' ? ' ' : ')' ); + + if ( args < CUR.top && args >= 0 ) + sprintf( temp+col, "%04lx", CUR.stack[args] ); + else + sprintf( temp+col, " " ); + + temp[col+4] = ' '; + col += 5; + pop--; + args--; + } + temp[78] = '\n'; + temp[79] = '\0'; + PTRACE0(( temp )); + } + + /* First, check for empty stack and overflow */ + if ( CUR.args < 0 ) + { + PTRACE0(( "ERROR : Too few arguments\n" )); + exc->error = TT_Err_Too_Few_Arguments; + goto LErrorLabel_; + } + + CUR.new_top = CUR.args + (Pop_Push_Count[CUR.opcode] & 15); + + /* new_top is the new top of the stack, after the instruction's */ + /* execution. top will be set to new_top after the 'case' */ + + if ( CUR.new_top > CUR.stackSize ) + { + PTRACE0(( "ERROR : Stack overflow\n" )); + exc->error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + } + else + PTRACE0(( "End of program reached.\n" )); + + key = 0; + do + { + /* read keyboard */ + + ch = getch(); + + switch ( ch ) + { + /* Help - show keybindings */ + case '?': + PTRACE0(( "FDebug Help\n\n" )); + PTRACE0(( "? Show this page\n" )); + PTRACE0(( "q Quit debugger\n" )); + PTRACE0(( "n Skip to next instruction\n" )); + PTRACE0(( "s Step into\n" )); + PTRACE0(( "v Show vector info\n" )); + PTRACE0(( "g Show graphics state\n" )); + PTRACE0(( "p Show points zone\n\n" )); + break; + + /* Show vectors */ + case 'v': + PTRACE0(( "freedom (%04hx,%04hx)\n", exc->GS.freeVector.x, + exc->GS.freeVector.y )); + PTRACE0(( "projection (%04hx,%04hx)\n", exc->GS.projVector.x, + exc->GS.projVector.y )); + PTRACE0(( "dual (%04hx,%04hx)\n\n", exc->GS.dualVector.x, + exc->GS.dualVector.y )); + break; + + /* Show graphics state */ + case 'g': + PTRACE0(( "rounding %s\n", round_str[exc->GS.round_state] )); + PTRACE0(( "min dist %04lx\n", exc->GS.minimum_distance )); + PTRACE0(( "cvt_cutin %04lx\n", exc->GS.control_value_cutin )); + break; + + /* Show points table */ + case 'p': + for ( A = 0; A < exc->pts.n_points; A++ ) + { + PTRACE0(( "%02hx ", A )); + PTRACE0(( "%08lx,%08lx - ", pts.org[A].x, pts.org[A].y )); + PTRACE0(( "%08lx,%08lx\n", pts.cur[A].x, pts.cur[A].y )); + } + PTRACE0(( "\n" )); + break; + + default: + key = 1; + } + } while ( !key ); + + MEM_Copy( save.org, pts.org, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.cur, pts.cur, pts.n_points * sizeof ( TT_Vector ) ); + MEM_Copy( save.touch, pts.touch, pts.n_points ); + + /* a return indicate the last command */ + if (ch == '\r') + ch = oldch; + + switch ( ch ) + { + /* Quit debugger */ + case 'q': + goto LErrorLabel_; + + /* Step over */ + case 'n': + if ( exc->IP < exc->codeSize ) + { + /* `step over' is equivalent to `step into' except if */ + /* the current opcode is a CALL or LOOPCALL */ + if ( CUR.opcode != 0x2a && CUR.opcode != 0x2b ) + goto Step_into; + + /* otherwise, loop execution until we reach the next opcode */ + next_IP = CUR.IP + CUR.length; + while ( exc->IP != next_IP ) + { + if ( ( error = RunIns2( exc ) ) ) + goto LErrorLabel_; + } + } + oldch = ch; + break; + + /* Step into */ + case 's': + if ( exc->IP < exc->codeSize ) + + Step_into: + if ( ( error = RunIns2( exc ) ) ) + goto LErrorLabel_; + oldch = ch; + break; + + default: + PTRACE0(( "unknown command. Press ? for help\n" )); + oldch = '\0'; + } + + for ( A = 0; A < pts.n_points; A++ ) + { + diff = 0; + if ( save.org[A].x != pts.org[A].x ) diff |= 1; + if ( save.org[A].y != pts.org[A].y ) diff |= 2; + if ( save.cur[A].x != pts.cur[A].x ) diff |= 4; + if ( save.cur[A].y != pts.cur[A].y ) diff |= 8; + if ( save.touch[A] != pts.touch[A] ) diff |= 16; + + if ( diff ) + { + PTRACE0(( "%02hx ", A )); + + if ( diff & 16 ) temp = "(%01hx)"; else temp = " %01hx "; + PTRACE0(( temp, save.touch[A] & 7 )); + + if ( diff & 1 ) temp = "(%08lx)"; else temp = " %08lx "; + PTRACE0(( temp, save.org[A].x )); + + if ( diff & 2 ) temp = "(%08lx)"; else temp = " %08lx "; + PTRACE0(( temp, save.org[A].y )); + + if ( diff & 4 ) temp = "(%08lx)"; else temp = " %08lx "; + PTRACE0(( temp, save.cur[A].x )); + + if ( diff & 8 ) temp = "(%08lx)"; else temp = " %08lx "; + PTRACE0(( temp, save.cur[A].y )); + + PTRACE0(( "\n" )); + + PTRACE0(( "%02hx ", A )); + + if ( diff & 16 ) temp = "[%01hx]"; else temp = " %01hx "; + PTRACE0(( temp, pts.touch[A] & 7 )); + + if ( diff & 1 ) temp = "[%08lx]"; else temp = " %08lx "; + PTRACE0(( temp, pts.org[A].x )); + + if ( diff & 2 ) temp = "[%08lx]"; else temp = " %08lx "; + PTRACE0(( temp, pts.org[A].y )); + + if ( diff & 4 ) temp = "[%08lx]"; else temp = " %08lx "; + PTRACE0(( temp, pts.cur[A].x )); + + if ( diff & 8 ) temp = "[%08lx]"; else temp = " %08lx "; + PTRACE0(( temp, pts.cur[A].y )); + + PTRACE0(( "\n\n" )); + } + } + } while ( TRUE ); + + LErrorLabel_: + + return error; + } + +#endif /* DEBUG_INTERPRETER */ + + +#endif /* TT_CONFIG_OPTION_NO_INTERPRETER */ + +/* END */ diff --git a/Build/source/libs/libttf/ttinterp.h b/Build/source/libs/libttf/ttinterp.h new file mode 100644 index 00000000000..d991fa07756 --- /dev/null +++ b/Build/source/libs/libttf/ttinterp.h @@ -0,0 +1,54 @@ +/******************************************************************* + * + * ttinterp.h 2.2 + * + * TrueType bytecode intepreter. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * Changes between 2.2 and 2.1: + * + * - a small bugfix in the Push opcodes + * + * Changes between 2.1 and 2.0: + * + * - created the TTExec component to take care of all execution + * context management. The interpreter has now one single + * function. + * + * - made some changes to support re-entrancy. The re-entrant + * interpreter is smaller! + * + ******************************************************************/ + +#ifndef TTINTERP_H +#define TTINTERP_H + +#include "ttconfig.h" +#include "ttobjs.h" + + +#ifdef __cplusplus + extern "C" { +#endif + + /* Run instructions in current execution context */ + + LOCAL_DEF TT_Error RunIns( PExecution_Context exc ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTINTERP_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttload.c b/Build/source/libs/libttf/ttload.c new file mode 100644 index 00000000000..282828fdeec --- /dev/null +++ b/Build/source/libs/libttf/ttload.c @@ -0,0 +1,1574 @@ + +/******************************************************************* + * + * ttload.c 1.0 + * + * TrueType Tables Loader. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "tttypes.h" +#include "ttdebug.h" +#include "ttcalc.h" +#include "ttfile.h" + +#include "tttables.h" +#include "ttobjs.h" + +#include "ttmemory.h" +#include "tttags.h" +#include "ttload.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_load + +/* In all functions, the stream is taken from the 'face' object */ +#define DEFINE_LOCALS DEFINE_LOAD_LOCALS( face->stream ) +#define DEFINE_LOCALS_WO_FRAME DEFINE_LOAD_LOCALS_WO_FRAME( face->stream ) + + +/******************************************************************* + * + * Function : LookUp_TrueType_Table + * + * Description : Looks for a TrueType table by name. + * + * Input : face face table to look for + * tag searched tag + * + * Output : Index of table if found, -1 otherwise. + * + ******************************************************************/ + + EXPORT_FUNC + Long TT_LookUp_Table( PFace face, + ULong tag ) + { + UShort i; + + + PTRACE4(( "TT_LookUp_Table( %08lx, %c%c%c%c )\n", + (Long)face, + (Char)(tag >> 24), + (Char)(tag >> 16), + (Char)(tag >> 8), + (Char)(tag) )); + + for ( i = 0; i < face->numTables; i++ ) + if ( face->dirTables[i].Tag == tag ) + return i; + + PTRACE4(( " Could not find table!\n" )); + return -1; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Collection + * + * Description : Loads the TTC table directory into face table. + * + * Input : face face record to look for + * + * Output : Error code. + * + ******************************************************************/ + + static TT_Error Load_TrueType_Collection( PFace face ) + { + DEFINE_LOCALS; + + ULong n; + + + PTRACE3(( "Load_TrueType_Collection( %08lx )\n", (long)face )); + + if ( FILE_Seek ( 0L ) || + ACCESS_Frame( 12L ) ) + return error; + + face->ttcHeader.Tag = GET_Tag4(); + face->ttcHeader.version = GET_Long(); + face->ttcHeader.DirCount = GET_Long(); + + FORGET_Frame(); + + if ( face->ttcHeader.Tag != TTAG_ttcf ) + { + face->ttcHeader.Tag = 0; + face->ttcHeader.version = 0; + face->ttcHeader.DirCount = 0; + + face->ttcHeader.TableDirectory = NULL; + + PTRACE3(("skipped.\n")); + + return TT_Err_File_Is_Not_Collection; + } + + if ( ALLOC_ARRAY( face->ttcHeader.TableDirectory, + face->ttcHeader.DirCount, + ULong ) || + ACCESS_Frame( face->ttcHeader.DirCount * 4L ) ) + return error; + + for ( n = 0; n < face->ttcHeader.DirCount; n++ ) + face->ttcHeader.TableDirectory[n] = GET_ULong(); + + FORGET_Frame(); + + PTRACE3(( "collections directory loaded.\n" )); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Directory + * + * Description : Loads the table directory into face table. + * + * Input : face face record to look for + * + * faceIndex the index of the TrueType font, when + * we're opening a collection. + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Directory( PFace face, ULong faceIndex ) + { + DEFINE_LOCALS; + + UShort n, limit; + TTableDir tableDir; + + PTableDirEntry entry; + + + PTRACE2(("Load_TT_Directory( %08lx, %ld )\n", (long)face, faceIndex)); + + error = Load_TrueType_Collection( face ); + + if ( error ) + { + if ( error != TT_Err_File_Is_Not_Collection ) + return error; + + /* the file isn't a collection, exit if we're asking */ + /* for a collected font */ + if ( faceIndex != 0 ) + return error; + + /* Now skip to the beginning of the file */ + if ( FILE_Seek( 0L ) ) + return error; + } + else + { + /* The file is a collection. Check the font index */ + if ( faceIndex >= face->ttcHeader.DirCount ) + return TT_Err_Invalid_Argument; + + /* select a TrueType font in the ttc file */ + if ( FILE_Seek( face->ttcHeader.TableDirectory[faceIndex] ) ) + return error; + } + + if ( ACCESS_Frame( 12L ) ) + return error; + + tableDir.version = GET_Long(); + tableDir.numTables = GET_UShort(); + + tableDir.searchRange = GET_UShort(); + tableDir.entrySelector = GET_UShort(); + tableDir.rangeShift = GET_UShort(); + + FORGET_Frame(); + + PTRACE2(( "-- Tables count : %12u\n", tableDir.numTables )); + PTRACE2(( "-- Format version : %08lx\n", tableDir.version )); + + /* Check that we have a 'sfnt' format there */ + + if ( tableDir.version != 0x00010000 && /* MS fonts */ + tableDir.version != 0x74727565 && /* Mac fonts */ + tableDir.version != 0x00000000 ) /* some Korean fonts */ + { + PERROR(( "!! invalid file format" )); + return TT_Err_Invalid_File_Format; + } + + face->numTables = tableDir.numTables; + + if ( ALLOC_ARRAY( face->dirTables, + face->numTables, + TTableDirEntry ) ) + return error; + + if ( ACCESS_Frame( face->numTables * 16L ) ) + return error; + + limit = face->numTables; + entry = face->dirTables; + + for ( n = 0; n < limit; n++ ) + { /* loop through the tables and get all entries */ + entry->Tag = GET_Tag4(); + entry->CheckSum = GET_ULong(); + entry->Offset = GET_Long(); + entry->Length = GET_Long(); + + PTRACE2(( " %c%c%c%c - %08lx - %08lx\n", + (Char)(entry->Tag >> 24), + (Char)(entry->Tag >> 16), + (Char)(entry->Tag >> 8 ), + (Char)(entry->Tag), + entry->Offset, + entry->Length )); + entry++; + } + + FORGET_Frame(); + + PTRACE2(( "Directory loaded\n\n" )); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_MaxProfile + * + * Description : Loads the maxp table into face table. + * + * Input : face face table to look for + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_MaxProfile( PFace face ) + { + DEFINE_LOCALS; + + Long i; + PMaxProfile maxProfile = &face->maxProfile; + + + PTRACE2(( "Load_TT_MaxProfile( %08lx )\n", (long)face )); + + if ( ( i = TT_LookUp_Table( face, TTAG_maxp ) ) < 0 ) + return TT_Err_Max_Profile_Missing; + + if ( FILE_Seek( face->dirTables[i].Offset ) ) /* seek to maxprofile */ + return error; + + if ( ACCESS_Frame( 32L ) ) /* read into frame */ + return error; + + /* read frame data into face table */ + maxProfile->version = GET_ULong(); + + maxProfile->numGlyphs = GET_UShort(); + + maxProfile->maxPoints = GET_UShort(); + maxProfile->maxContours = GET_UShort(); + maxProfile->maxCompositePoints = GET_UShort(); + maxProfile->maxCompositeContours = GET_UShort(); + + maxProfile->maxZones = GET_UShort(); + maxProfile->maxTwilightPoints = GET_UShort(); + + maxProfile->maxStorage = GET_UShort(); + maxProfile->maxFunctionDefs = GET_UShort(); + maxProfile->maxInstructionDefs = GET_UShort(); + maxProfile->maxStackElements = GET_UShort(); + maxProfile->maxSizeOfInstructions = GET_UShort(); + maxProfile->maxComponentElements = GET_UShort(); + maxProfile->maxComponentDepth = GET_UShort(); + + FORGET_Frame(); + + /* XXX : an adjustement that is necessary to load certain */ + /* broken fonts like "Keystrokes MT" :-( */ + /* */ + /* We allocate 64 function entries by default when */ + /* the maxFunctionDefs field is null. */ + + if (maxProfile->maxFunctionDefs == 0) + maxProfile->maxFunctionDefs = 64; + + face->numGlyphs = maxProfile->numGlyphs; + + face->maxPoints = MAX( maxProfile->maxCompositePoints, + maxProfile->maxPoints ); + face->maxContours = MAX( maxProfile->maxCompositeContours, + maxProfile->maxContours ); + face->maxComponents = maxProfile->maxComponentElements + + maxProfile->maxComponentDepth; + + /* XXX: Some fonts have maxComponents set to 0; we will */ + /* then use 16 of them by default. */ + if ( face->maxComponents == 0 ) + face->maxComponents = 16; + + /* We also increase maxPoints and maxContours in order to support */ + /* some broken fonts. */ + face->maxPoints += 8; + face->maxContours += 4; + + PTRACE2(( "GASP loaded.\n" )); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Gasp + * + * Description : Loads the TrueType Gasp table into the face + * table. + * + * Input : face face table to look for + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Gasp( PFace face ) + { + DEFINE_LOCALS; + + Long i; + UShort j; + TGasp* gas; + GaspRange* gaspranges; + + + PTRACE2(( "Load_TT_Gasp( %08lx )\n", (long)face )); + + if ( ( i = TT_LookUp_Table( face, TTAG_gasp ) ) < 0 ) + return TT_Err_Ok; /* gasp table is not required */ + + if ( FILE_Seek( face->dirTables[i].Offset ) || + ACCESS_Frame( 4L ) ) + return error; + + gas = &face->gasp; + + gas->version = GET_UShort(); + gas->numRanges = GET_UShort(); + + FORGET_Frame(); + + PTRACE3(( "number of ranges = %d\n", gas->numRanges )); + + if ( ALLOC_ARRAY( gaspranges, gas->numRanges, GaspRange ) || + ACCESS_Frame( gas->numRanges * 4L ) ) + goto Fail; + + face->gasp.gaspRanges = gaspranges; + + for ( j = 0; j < gas->numRanges; j++ ) + { + gaspranges[j].maxPPEM = GET_UShort(); + gaspranges[j].gaspFlag = GET_UShort(); + + PTRACE3(( " [max:%d flag:%d]", + gaspranges[j].maxPPEM, + gaspranges[j].gaspFlag )); + } + PTRACE3(("\n")); + + FORGET_Frame(); + + PTRACE2(( "GASP loaded\n" )); + return TT_Err_Ok; + + Fail: + FREE( gaspranges ); + gas->numRanges = 0; + return error; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Header + * + * Description : Loads the TrueType header table into the face + * table. + * + * Input : face face table to look for + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Header( PFace face ) + { + DEFINE_LOCALS; + + Long i; + TT_Header* header; + + + PTRACE2(( "Load_TT_Header( %08lx )\n", (long)face )); + + if ( ( i = TT_LookUp_Table( face, TTAG_head ) ) < 0 ) + { + PTRACE0(( "Font Header is missing !!\n" )); + return TT_Err_Header_Table_Missing; + } + + if ( FILE_Seek( face->dirTables[i].Offset ) || + ACCESS_Frame( 54L ) ) + return error; + + header = &face->fontHeader; + + header->Table_Version = GET_ULong(); + header->Font_Revision = GET_ULong(); + + header->CheckSum_Adjust = GET_Long(); + header->Magic_Number = GET_Long(); + + header->Flags = GET_UShort(); + header->Units_Per_EM = GET_UShort(); + + header->Created [0] = GET_Long(); + header->Created [1] = GET_Long(); + header->Modified[0] = GET_Long(); + header->Modified[1] = GET_Long(); + + header->xMin = GET_Short(); + header->yMin = GET_Short(); + header->xMax = GET_Short(); + header->yMax = GET_Short(); + + header->Mac_Style = GET_UShort(); + header->Lowest_Rec_PPEM = GET_UShort(); + + header->Font_Direction = GET_Short(); + header->Index_To_Loc_Format = GET_Short(); + header->Glyph_Data_Format = GET_Short(); + + FORGET_Frame(); + + PTRACE2(( " Units per EM : %8u\n", header->Units_Per_EM )); + PTRACE2(( " IndexToLoc : %8d\n", header->Index_To_Loc_Format )); + PTRACE2(( "Font Header Loaded.\n" )); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Metrics + * + * Description : Loads the horizontal or vertical metrics table + * into face object. + * + * Input : face + * vertical set to true when loading the vmtx table, + * or false for hmtx + * + * Output : Error code. + * + ******************************************************************/ + + static + TT_Error Load_TrueType_Metrics( PFace face, + Bool vertical ) + { + DEFINE_LOCALS; + + Long n, num_shorts, num_shorts_checked, num_longs; + + PLongMetrics* longs; + PShortMetrics* shorts; + + PLongMetrics long_metric; + + + PTRACE2(( "Load_TT_%s_Metrics( %08lx )\n", + vertical ? "Vertical" : "Horizontal", + (long)face )); + + if ( vertical ) + { + /* The table is optional, quit silently if it wasn't found */ + /* XXX : Some fonts have a valid vertical header with a non-null */ + /* "number_of_VMetrics" fields, but no corresponding */ + /* 'vmtx' table to get the metrics from (e.g. mingliu) */ + /* */ + /* For safety, we set the field to 0 ! */ + /* */ + n = TT_LookUp_Table( face, TTAG_vmtx ); + if ( n < 0 ) + { + /* Set the number_Of_VMetrics to 0! */ + PTRACE2(( " no vertical header in file.\n" )); + face->verticalHeader.number_Of_VMetrics = 0; + return TT_Err_Ok; + } + + num_longs = face->verticalHeader.number_Of_VMetrics; + longs = (PLongMetrics*)&face->verticalHeader.long_metrics; + shorts = (PShortMetrics*)&face->verticalHeader.short_metrics; + } + else + { + if ( ( n = TT_LookUp_Table( face, TTAG_hmtx ) ) < 0 ) + { + PERROR(( "!! No Horizontal metrics in file !!\n" )); + return TT_Err_Hmtx_Table_Missing; + } + + num_longs = face->horizontalHeader.number_Of_HMetrics; + longs = (PLongMetrics*)&face->horizontalHeader.long_metrics; + shorts = (PShortMetrics*)&face->horizontalHeader.short_metrics; + } + + /* never trust derived values! */ + + num_shorts = face->maxProfile.numGlyphs - num_longs; + num_shorts_checked = ( face->dirTables[n].Length - num_longs * 4 ) / 2; + + if ( num_shorts < 0 ) /* sanity check */ + { + PERROR(( "!! more metrics than glyphs!\n" )); + if ( vertical ) + return TT_Err_Invalid_Vert_Metrics; + else + return TT_Err_Invalid_Horiz_Metrics; + } + + if ( ALLOC_ARRAY( *longs, num_longs, TLongMetrics ) || + ALLOC_ARRAY( *shorts, num_shorts, TShortMetrics ) ) + return error; + + if ( FILE_Seek( face->dirTables[n].Offset ) || + ACCESS_Frame( face->dirTables[n].Length ) ) + return error; + + long_metric = *longs; + for ( n = 0; n < num_longs; n++ ) + { + long_metric->advance = GET_UShort(); + long_metric->bearing = GET_Short(); + long_metric++; + } + + /* do we have an inconsistent number of metric values? */ + + if ( num_shorts > num_shorts_checked ) + { + for ( n = 0; n < num_shorts_checked; n++ ) + (*shorts)[n] = GET_Short(); + + /* we fill up the missing left side bearings with the */ + /* last valid value. Since this will occur for buggy CJK */ + /* fonts usually, nothing serious will happen. */ + + for ( n = num_shorts_checked; n < num_shorts; n++ ) + (*shorts)[n] = (*shorts)[num_shorts_checked - 1]; + } + else + { + for ( n = 0; n < num_shorts; n++ ) + (*shorts)[n] = GET_Short(); + } + + FORGET_Frame(); + + PTRACE2(( "loaded\n" )); + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Metrics_Header + * + * Description : Loads either the "hhea" or "vhea" table in memory + * + * Input : face face table to look for + * vertical a boolean. When set, queries the optional + * "vhea" table. Otherwise, load the mandatory + * "hhea" horizontal header. + * + * Output : Error code. + * + * Note : This function now loads the corresponding metrics table + * (either hmtx or vmtx) and attaches it to the header. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Metrics_Header( PFace face, + Bool vertical ) + { + DEFINE_LOCALS; + + Long i; + + TT_Horizontal_Header* header; + + + PTRACE2(( vertical ? "Vertical header" : "Horizontal header " )); + + if ( vertical ) + { + face->verticalInfo = 0; + + /* The vertical header table is optional, so return quietly if */ + /* we don't find it.. */ + if ( ( i = TT_LookUp_Table( face, TTAG_vhea ) ) < 0 ) + return TT_Err_Ok; + + face->verticalInfo = 1; + header = (TT_Horizontal_Header*)&face->verticalHeader; + } + else + { + /* The orizontal header is mandatory, return an error if we */ + /* don't find it. */ + if ( ( i = TT_LookUp_Table( face, TTAG_hhea ) ) < 0 ) + return TT_Err_Horiz_Header_Missing; + + header = &face->horizontalHeader; + } + + if ( FILE_Seek( face->dirTables[i].Offset ) || + ACCESS_Frame( 36L ) ) + return error; + + header->Version = GET_ULong(); + header->Ascender = GET_Short(); + header->Descender = GET_Short(); + header->Line_Gap = GET_Short(); + + header->advance_Width_Max = GET_UShort(); + + header->min_Left_Side_Bearing = GET_Short(); + header->min_Right_Side_Bearing = GET_Short(); + header->xMax_Extent = GET_Short(); + header->caret_Slope_Rise = GET_Short(); + header->caret_Slope_Run = GET_Short(); + + header->Reserved0 = GET_Short(); /* this is caret_Offset for + vertical headers */ + header->Reserved1 = GET_Short(); + header->Reserved2 = GET_Short(); + header->Reserved3 = GET_Short(); + header->Reserved4 = GET_Short(); + + header->metric_Data_Format = GET_Short(); + header->number_Of_HMetrics = GET_UShort(); + + FORGET_Frame(); + + header->long_metrics = NULL; + header->short_metrics = NULL; + + PTRACE2(( "loaded\n" )); + + /* Now try to load the corresponding metrics */ + + return Load_TrueType_Metrics( face, vertical ); + } + + +/******************************************************************* + * + * Function : Load_TrueType_Locations + * + * Description : Loads the location table into face table. + * + * Input : face face table to look for + * + * Output : Error code. + * + * NOTE: + * The Font Header *must* be loaded in the leading segment + * calling this function. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Locations( PFace face ) + { + DEFINE_LOCALS; + + Long n, limit; + Short LongOffsets; + + + PTRACE2(( "Locations " )); + + LongOffsets = face->fontHeader.Index_To_Loc_Format; + + if ( ( n = TT_LookUp_Table( face, TTAG_loca ) ) < 0 ) + return TT_Err_Locations_Missing; + + if ( FILE_Seek( face->dirTables[n].Offset ) ) + return error; + + if ( LongOffsets != 0 ) + { + face->numLocations = face->dirTables[n].Length >> 2; + + PTRACE2(( "(32 bit offsets): %12lu ", + face->numLocations )); + + if ( ALLOC_ARRAY( face->glyphLocations, + face->numLocations, + Long ) ) + return error; + + if ( ACCESS_Frame( face->numLocations * 4L ) ) + return error; + + limit = face->numLocations; + + for ( n = 0; n < limit; n++ ) + face->glyphLocations[n] = GET_Long(); + + FORGET_Frame(); + } + else + { + face->numLocations = face->dirTables[n].Length >> 1; + + PTRACE2(( "(16 bit offsets): %12lu ", + face->numLocations )); + + if ( ALLOC_ARRAY( face->glyphLocations, + face->numLocations, + Long ) ) + return error; + + if ( ACCESS_Frame( face->numLocations * 2L ) ) + return error; + + limit = face->numLocations; + + for ( n = 0; n < limit; n++ ) + face->glyphLocations[n] = + (Long)((ULong)GET_UShort() * 2); + + FORGET_Frame(); + } + + PTRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Names + * + * Description : Loads the name table into face table. + * + * Input : face face table to look for + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Names( PFace face ) + { + DEFINE_LOCALS; + + UShort i, bytes; + Long n; + PByte storage; + + TName_Table* names; + TNameRec* namerec; + + + PTRACE2(( "Names " )); + + if ( ( n = TT_LookUp_Table( face, TTAG_name ) ) < 0 ) + { + /* The name table is required so indicate failure. */ + PTRACE2(( "is missing!\n" )); + + return TT_Err_Name_Table_Missing; + } + + /* Seek to the beginning of the table and check the frame access. */ + /* The names table has a 6 byte header. */ + if ( FILE_Seek( face->dirTables[n].Offset ) || + ACCESS_Frame( 6L ) ) + return error; + + names = &face->nameTable; + + /* Load the initial names data. */ + names->format = GET_UShort(); + names->numNameRecords = GET_UShort(); + names->storageOffset = GET_UShort(); + + FORGET_Frame(); + + /* Allocate the array of name records. */ + if ( ALLOC_ARRAY( names->names, + names->numNameRecords, + TNameRec ) || + ACCESS_Frame( names->numNameRecords * 12L ) ) + { + names->numNameRecords = 0; + goto Fail; + } + + /* Load the name records and determine how much storage is needed */ + /* to hold the strings themselves. */ + + for ( i = bytes = 0; i < names->numNameRecords; i++ ) + { + namerec = names->names + i; + namerec->platformID = GET_UShort(); + namerec->encodingID = GET_UShort(); + namerec->languageID = GET_UShort(); + namerec->nameID = GET_UShort(); + namerec->stringLength = GET_UShort(); + namerec->stringOffset = GET_UShort(); + +#if 0 + /* check the ids */ + if ( namerec->platformID <= 3 ) + { +#endif + /* this test takes care of 'holes' in the names tables, as */ + /* reported by Erwin */ + if ( (namerec->stringOffset + namerec->stringLength) > bytes ) + bytes = namerec->stringOffset + namerec->stringLength; +#if 0 + } +#endif + } + + FORGET_Frame(); + + /* Allocate storage for the strings if they exist. */ + + names->storage = NULL; + + if ( bytes > 0 ) + { + if ( ALLOC( storage, bytes ) || + FILE_Read_At( face->dirTables[n].Offset + names->storageOffset, + (void*)storage, + bytes ) ) + goto Fail_Storage; + + names->storage = storage; + + /* Go through and assign the string pointers to the name records. */ + + for ( i = 0; i < names->numNameRecords; i++ ) + { + namerec = names->names + i; + namerec->string = storage + names->names[i].stringOffset; + +/* It is possible (but rather unlikely) that a new platform ID will be */ +/* added by Apple, so we can't rule out IDs > 3. */ + +#if 0 + if ( namerec->platformID <= 3 ) + namerec->string = storage + names->names[i].stringOffset; + else + { + namerec->string = NULL; + namerec->stringLength = 0; + } +#endif + } + } + +#ifdef DEBUG_LEVEL_TRACE + + for ( i = 0; i < names->numNameRecords; i++ ) + { + int j; + + + PTRACE2(( "%d %d %x %d ", + names->names[i].platformID, + names->names[i].encodingID, + names->names[i].languageID, + names->names[i].nameID )); + + /* I know that M$ encoded strings are Unicode, */ + /* but this works reasonable well for debugging purposes. */ + for ( j = 0; j < names->names[i].stringLength; j++ ) + { + if (names->names[i].string) + { + Char c = *(names->names[i].string + j); + + + if ( (Byte)c < 128 ) + PTRACE2(( "%c", c )); + } + } + + PTRACE2(( "\n" )); + } + +#endif /* DEBUG_LEVEL_TRACE */ + + PTRACE2(( "loaded\n" )); + return TT_Err_Ok; + + Fail_Storage: + FREE( storage ); + + Fail: + Free_TrueType_Names( face ); + return error; + } + + +/******************************************************************* + * + * Function : Free_TrueType_Names + * + * Description : Frees a name table. + * + * Input : face face table to look for + * + * Output : TT_Err_Ok. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Free_TrueType_Names( PFace face ) + { + TName_Table* names = &face->nameTable; + + + /* free strings table */ + FREE( names->names ); + + /* free strings storage */ + FREE( names->storage ); + + names->numNameRecords = 0; + names->format = 0; + names->storageOffset = 0; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_CVT + * + * Description : Loads cvt table into resident table. + * + * Input : face face table to look for + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_CVT( PFace face ) + { + DEFINE_LOCALS; + + Long n, limit; + + + PTRACE2(( "CVT " )); + + if ( ( n = TT_LookUp_Table( face, TTAG_cvt ) ) < 0 ) + { + PTRACE2(( "is missing!\n" )); + + face->cvtSize = 0; + face->cvt = NULL; + return TT_Err_Ok; + } + + face->cvtSize = face->dirTables[n].Length / 2; + + if ( ALLOC_ARRAY( face->cvt, + face->cvtSize, + Short ) ) + return error; + + if ( FILE_Seek( face->dirTables[n].Offset ) || + ACCESS_Frame( face->cvtSize * 2L ) ) + return error; + + limit = face->cvtSize; + + for ( n = 0; n < limit; n++ ) + face->cvt[n] = GET_Short(); + + FORGET_Frame(); + + PTRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_CMap + * + * Description : Loads the cmap directory in memory. + * The cmaps themselves are loaded in ttcmap.c . + * + * Input : face + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_CMap( PFace face ) + { + DEFINE_LOCALS; + + Long off, table_start; + Long n, limit; + + TCMapDir cmap_dir; + TCMapDirEntry entry_; + PCMapTable cmap; + + + PTRACE2(( "CMaps " )); + + if ( ( n = TT_LookUp_Table( face, TTAG_cmap ) ) < 0 ) + return TT_Err_CMap_Table_Missing; + + table_start = face->dirTables[n].Offset; + + if ( ( FILE_Seek( table_start ) ) || + ( ACCESS_Frame( 4L ) ) ) /* 4 bytes cmap header */ + return error; + + cmap_dir.tableVersionNumber = GET_UShort(); + cmap_dir.numCMaps = GET_UShort(); + + FORGET_Frame(); + + off = FILE_Pos(); /* save offset to cmapdir[] which follows */ + + /* save space in face table for cmap tables */ + if ( ALLOC_ARRAY( face->cMaps, + cmap_dir.numCMaps, + TCMapTable ) ) + return error; + + face->numCMaps = cmap_dir.numCMaps; + + limit = face->numCMaps; + cmap = face->cMaps; + + for ( n = 0; n < limit; n++ ) + { + if ( FILE_Seek( off ) || + ACCESS_Frame( 8L ) ) + return error; + + /* extra code using entry_ for platxxx could be cleaned up later */ + cmap->loaded = FALSE; + cmap->platformID = entry_.platformID = GET_UShort(); + cmap->platformEncodingID = entry_.platformEncodingID = GET_UShort(); + + entry_.offset = GET_Long(); + + FORGET_Frame(); + + off = FILE_Pos(); + + if ( FILE_Seek( table_start + entry_.offset ) || + ACCESS_Frame( 6L ) ) + return error; + + cmap->format = GET_UShort(); + cmap->length = GET_UShort(); + cmap->version = GET_UShort(); + + FORGET_Frame(); + + cmap->offset = FILE_Pos(); + + cmap++; + } + + PTRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Programs + * + * Description : Loads the font (fpgm) and cvt programs into the + * face table. + * + * Input : face + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Programs( PFace face ) + { + DEFINE_LOCALS_WO_FRAME; + + Long n; + + + PTRACE2(( "Font program " )); + + /* The font program is optional */ + if ( ( n = TT_LookUp_Table( face, TTAG_fpgm ) ) < 0 ) + { + face->fontProgram = NULL; + face->fontPgmSize = 0; + + PTRACE2(( "is missing!\n" )); + } + else + { + face->fontPgmSize = face->dirTables[n].Length; + + if ( ALLOC( face->fontProgram, + face->fontPgmSize ) || + FILE_Read_At( face->dirTables[n].Offset, + (void*)face->fontProgram, + face->fontPgmSize ) ) + return error; + + PTRACE2(( "loaded, %12d bytes\n", face->fontPgmSize )); + } + + PTRACE2(( "Prep program " )); + + if ( ( n = TT_LookUp_Table( face, TTAG_prep ) ) < 0 ) + { + face->cvtProgram = NULL; + face->cvtPgmSize = 0; + + PTRACE2(( "is missing!\n" )); + } + else + { + face->cvtPgmSize = face->dirTables[n].Length; + + if ( ALLOC( face->cvtProgram, + face->cvtPgmSize ) || + FILE_Read_At( face->dirTables[n].Offset, + (void*)face->cvtProgram, + face->cvtPgmSize ) ) + return error; + + PTRACE2(( "loaded, %12d bytes\n", face->cvtPgmSize )); + } + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_OS2 + * + * Description : Loads the OS2 Table. + * + * Input : face + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_OS2( PFace face ) + { + DEFINE_LOCALS; + + Long i; + TT_OS2* os2; + + + PTRACE2(( "OS/2 Table " )); + + /* We now support old Mac fonts where the OS/2 table doesn't */ + /* exist. Simply put, we set the `version' field to 0xFFFF */ + /* and test this value each time we need to access the table. */ + if ( ( i = TT_LookUp_Table( face, TTAG_OS2 ) ) < 0 ) + { + PTRACE2(( "is missing\n!" )); + face->os2.version = 0xFFFF; + error = TT_Err_Ok; + return TT_Err_Ok; + } + + if ( FILE_Seek( face->dirTables[i].Offset ) || + ACCESS_Frame( 78L ) ) + return error; + + os2 = &face->os2; + + os2->version = GET_UShort(); + os2->xAvgCharWidth = GET_Short(); + os2->usWeightClass = GET_UShort(); + os2->usWidthClass = GET_UShort(); + os2->fsType = GET_Short(); + os2->ySubscriptXSize = GET_Short(); + os2->ySubscriptYSize = GET_Short(); + os2->ySubscriptXOffset = GET_Short(); + os2->ySubscriptYOffset = GET_Short(); + os2->ySuperscriptXSize = GET_Short(); + os2->ySuperscriptYSize = GET_Short(); + os2->ySuperscriptXOffset = GET_Short(); + os2->ySuperscriptYOffset = GET_Short(); + os2->yStrikeoutSize = GET_Short(); + os2->yStrikeoutPosition = GET_Short(); + os2->sFamilyClass = GET_Short(); + + for ( i = 0; i < 10; i++ ) + os2->panose[i] = GET_Byte(); + + os2->ulUnicodeRange1 = GET_ULong(); + os2->ulUnicodeRange2 = GET_ULong(); + os2->ulUnicodeRange3 = GET_ULong(); + os2->ulUnicodeRange4 = GET_ULong(); + + for ( i = 0; i < 4; i++ ) + os2->achVendID[i] = GET_Byte(); + + os2->fsSelection = GET_UShort(); + os2->usFirstCharIndex = GET_UShort(); + os2->usLastCharIndex = GET_UShort(); + os2->sTypoAscender = GET_Short(); + os2->sTypoDescender = GET_Short(); + os2->sTypoLineGap = GET_Short(); + os2->usWinAscent = GET_UShort(); + os2->usWinDescent = GET_UShort(); + + FORGET_Frame(); + + if ( os2->version >= 0x0001 ) + { + /* only version 1 tables */ + + if ( ACCESS_Frame( 8L ) ) /* read into frame */ + return error; + + os2->ulCodePageRange1 = GET_ULong(); + os2->ulCodePageRange2 = GET_ULong(); + + FORGET_Frame(); + } + else + { + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 0; + } + + PTRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_PostScript + * + * Description : Loads the post table into face table. + * + * Input : face face table to look for + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_PostScript( PFace face ) + { + DEFINE_LOCALS; + + Long i; + + TT_Postscript* post = &face->postscript; + + + PTRACE2(( "PostScript " )); + + if ( ( i = TT_LookUp_Table( face, TTAG_post ) ) < 0 ) + return TT_Err_Post_Table_Missing; + + if ( FILE_Seek( face->dirTables[i].Offset ) || + ACCESS_Frame( 32L ) ) + return error; + + /* read frame data into face table */ + + post->FormatType = GET_ULong(); + post->italicAngle = GET_ULong(); + post->underlinePosition = GET_Short(); + post->underlineThickness = GET_Short(); + post->isFixedPitch = GET_ULong(); + post->minMemType42 = GET_ULong(); + post->maxMemType42 = GET_ULong(); + post->minMemType1 = GET_ULong(); + post->maxMemType1 = GET_ULong(); + + FORGET_Frame(); + + /* we don't load the glyph names, we do that in a */ + /* library extension (ftxpost). */ + + PTRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Hdmx + * + * Description : Loads the horizontal device metrics table. + * + * Input : face face object to look for + * + * Output : SUCCESS on success. FAILURE on error. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Hdmx( PFace face ) + { + DEFINE_LOCALS; + + TT_Hdmx_Record* rec; + TT_Hdmx hdmx; + Long table; + UShort n, num_glyphs; + Long record_size; + + + hdmx.version = 0; + hdmx.num_records = 0; + hdmx.records = 0; + + face->hdmx = hdmx; + + if ( ( table = TT_LookUp_Table( face, TTAG_hdmx ) ) < 0 ) + return TT_Err_Ok; + + if ( FILE_Seek( face->dirTables[table].Offset ) || + ACCESS_Frame( 8L ) ) + return error; + + hdmx.version = GET_UShort(); + hdmx.num_records = GET_Short(); + record_size = GET_Long(); + + FORGET_Frame(); + + /* Only recognize format 0 */ + + if ( hdmx.version != 0 ) + return TT_Err_Ok; + + if ( ALLOC( hdmx.records, sizeof ( TT_Hdmx_Record ) * hdmx.num_records ) ) + return error; + + num_glyphs = face->numGlyphs; + record_size -= num_glyphs+2; + rec = hdmx.records; + + for ( n = 0; n < hdmx.num_records; n++ ) + { + /* read record */ + + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + rec->ppem = GET_Byte(); + rec->max_width = GET_Byte(); + + FORGET_Frame(); + + if ( ALLOC( rec->widths, num_glyphs ) || + FILE_Read( rec->widths, num_glyphs ) ) + goto Fail; + + /* skip padding bytes */ + if ( record_size > 0 ) + if ( FILE_Skip( record_size ) ) + goto Fail; + + rec++; + } + + face->hdmx = hdmx; + + return TT_Err_Ok; + + Fail: + for ( n = 0; n < hdmx.num_records; n++ ) + FREE( hdmx.records[n].widths ); + + FREE( hdmx.records ); + return error; + } + + +/******************************************************************* + * + * Function : Free_TrueType_Hdmx + * + * Description : Frees the horizontal device metrics table. + * + * Input : face face object to look for + * + * Output : TT_Err_Ok. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Free_TrueType_Hdmx( PFace face ) + { + UShort n; + + + if ( !face ) + return TT_Err_Ok; + + for ( n = 0; n < face->hdmx.num_records; n++ ) + FREE( face->hdmx.records[n].widths ); + + FREE( face->hdmx.records ); + face->hdmx.num_records = 0; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Load_TrueType_Any + * + * Description : Loads any font table into client memory. Used by + * the TT_Get_Font_Data() API function. + * + * Input : face face object to look for + * + * tag tag of table to load. Use the value 0 if you + * want to access the whole font file, else set + * this parameter to a valid TrueType table tag + * that you can forge with the MAKE_TT_TAG + * macro. + * + * offset starting offset in the table (or the file + * if tag == 0 ) + * + * buffer address of target buffer + * + * length address of decision variable : + * + * if length == NULL : + * load the whole table. returns an + * an error if 'offset' == 0 !! + * + * if *length == 0 : + * exit immediately, returning the + * length of the given table, or of + * the font file, depending on the + * value of 'tag' + * + * if *length != 0 : + * load the next 'length' bytes of + * table or font, starting at offset + * 'offset' (in table or font too). + * + * Output : Error condition + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Load_TrueType_Any( PFace face, + ULong tag, + Long offset, + void* buffer, + Long* length ) + { + TT_Stream stream; + TT_Error error; + Long table; + ULong size; + + + if ( tag != 0 ) + { + /* look for tag in font directory */ + table = TT_LookUp_Table( face, tag ); + if ( table < 0 ) + return TT_Err_Table_Missing; + + offset += face->dirTables[table].Offset; + size = face->dirTables[table].Length; + } + else + /* tag = 0 -- the use want to access the font file directly */ + size = TT_Stream_Size( face->stream ); + + if ( length && *length == 0 ) + { + *length = size; + return TT_Err_Ok; + } + + if ( length ) + size = *length; + + if ( !USE_Stream( face->stream, stream ) ) + (void)FILE_Read_At( offset, buffer, size ); + DONE_Stream( stream ); + + return error; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttload.h b/Build/source/libs/libttf/ttload.h new file mode 100644 index 00000000000..47acae91a2e --- /dev/null +++ b/Build/source/libs/libttf/ttload.h @@ -0,0 +1,217 @@ +/******************************************************************* + * + * ttload.h 1.1 + * + * TrueType Tables Loader. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * Changes between 1.1 and 1.0 : + * + * - add function Load_TrueType_Any used by TT_Get_Font_Data + * + ******************************************************************/ + +#ifndef TTLOAD_H +#define TTLOAD_H + +#include "ttconfig.h" +#include "tttypes.h" +#include "ttobjs.h" + +#ifdef __cplusplus + extern "C" { +#endif + + EXPORT_DEF + Long TT_LookUp_Table( PFace face, ULong tag ); + + LOCAL_DEF TT_Error Load_TrueType_Directory ( PFace face, + ULong faceIndex ); + + LOCAL_DEF TT_Error Load_TrueType_MaxProfile ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Gasp ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Header ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Locations ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Names ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_CVT ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_CMap ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Programs ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_OS2 ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_PostScript ( PFace face ); + LOCAL_DEF TT_Error Load_TrueType_Hdmx ( PFace face ); + + LOCAL_DEF TT_Error Load_TrueType_Metrics_Header( PFace face, + Bool vertical ); + + LOCAL_DEF TT_Error Load_TrueType_Any( PFace face, + ULong tag, + Long offset, + void* buffer, + Long* length ); + + LOCAL_DEF TT_Error Free_TrueType_Names( PFace face ); + LOCAL_DEF TT_Error Free_TrueType_Hdmx ( PFace face ); + + +/* The following macros are defined to simplify the writing of */ +/* the various table and glyph loaders. */ + +/* For examples see the code in ttload.c, ttgload.c etc. */ + +#define USE_Stream( original, duplicate ) \ + ( (error = TT_Use_Stream( original, &duplicate )) != TT_Err_Ok ) + +#define DONE_Stream( _stream ) \ + TT_Done_Stream( &_stream ) + +/* Define a file frame -- use it only when needed */ +#define DEFINE_A_FRAME TFileFrame frame = TT_Null_FileFrame + +/* Define a stream -- use it only when needed */ +#define DEFINE_A_STREAM TT_Stream stream + + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE /* re-entrant implementation */ + +/* The following macros define the necessary local */ +/* variables used to access streams and frames. */ + +/* Define stream locals with frame */ +#define DEFINE_STREAM_LOCALS \ + TT_Error error; \ + DEFINE_A_STREAM; \ + DEFINE_A_FRAME + +/* Define stream locals without frame */ +#define DEFINE_STREAM_LOCALS_WO_FRAME \ + TT_Error error; \ + DEFINE_A_STREAM + +/* Define locals with a predefined stream in reentrant mode -- see ttload.c */ +#define DEFINE_LOAD_LOCALS( STREAM ) \ + TT_Error error; \ + DEFINE_A_STREAM = (STREAM); \ + DEFINE_A_FRAME + +/* Define locals without frame with a predefined stream - see ttload.c */ +#define DEFINE_LOAD_LOCALS_WO_FRAME( STREAM ) \ + TT_Error error; \ + DEFINE_A_STREAM = (STREAM) + +/* Define all locals necessary to access a font file */ +#define DEFINE_ALL_LOCALS \ + TT_Error error; \ + DEFINE_A_STREAM; \ + DEFINE_A_FRAME + + +#define ACCESS_Frame( _size_ ) \ + ( (error = TT_Access_Frame( stream, \ + &frame, \ + (Long)(_size_) )) != TT_Err_Ok ) +#define CHECK_ACCESS_Frame( _size_ ) \ + ( (error = TT_Check_And_Access_Frame( stream, \ + &frame, \ + (Long)(_size_) )) != TT_Err_Ok ) +#define FORGET_Frame() \ + ( (void)TT_Forget_Frame( &frame ) ) + +#define GET_Byte() TT_Get_Byte ( &frame ) +#define GET_Char() TT_Get_Char ( &frame ) +#define GET_UShort() TT_Get_UShort( &frame ) +#define GET_Short() TT_Get_Short ( &frame ) +#define GET_Long() TT_Get_Long ( &frame ) +#define GET_ULong() TT_Get_ULong ( &frame ) +#define GET_Tag4() TT_Get_ULong ( &frame ) + +#define FILE_Pos() TT_File_Pos ( stream ) + +#define FILE_Seek( _position_ ) \ + ( (error = TT_Seek_File( stream, \ + (Long)(_position_) )) != TT_Err_Ok ) +#define FILE_Skip( _distance_ ) \ + ( (error = TT_Skip_File( stream, \ + (Long)(_distance_) )) != TT_Err_Ok ) +#define FILE_Read( buffer, count ) \ + ( (error = TT_Read_File ( stream, \ + buffer, \ + (Long)(count) )) != TT_Err_Ok ) +#define FILE_Read_At( pos, buffer, count ) \ + ( (error = TT_Read_At_File( stream, \ + (Long)(pos), \ + buffer, \ + (Long)(count) )) != TT_Err_Ok ) + +#else /* thread-safe implementation */ + +/* Define stream locals with frame -- nothing in thread-safe mode */ +#define DEFINE_STREAM_LOCALS \ + TT_Error error + +/* Define stream locals without frame -- nothing in thread-safe mode */ +#define DEFINE_STREAM_LOCALS_WO_FRAME \ + TT_Error error + +/* Define locals with a predefined stream in reentrant mode -- see ttload.c */ +#define DEFINE_LOAD_LOCALS( STREAM ) \ + TT_Error error + + +/* Define locals without frame with a predefined stream - see ttload.c */ +#define DEFINE_LOAD_LOCALS_WO_FRAME( STREAM ) \ + TT_Error error + +/* Define all locals necessary to access a font file */ +#define DEFINE_ALL_LOCALS \ + TT_Error error; \ + DEFINE_A_STREAM + + +#define ACCESS_Frame( _size_ ) \ + ( (error = TT_Access_Frame( (Long)(_size_) )) != TT_Err_Ok ) +#define CHECK_ACCESS_Frame( _size_ ) \ + ( (error = TT_Check_And_Access_Frame( (Long)(_size_) )) != TT_Err_Ok ) +#define FORGET_Frame() \ + ( (void)TT_Forget_Frame() ) + +#define GET_Byte() TT_Get_Byte () +#define GET_Char() TT_Get_Char () +#define GET_UShort() TT_Get_UShort() +#define GET_Short() TT_Get_Short () +#define GET_Long() TT_Get_Long () +#define GET_ULong() TT_Get_ULong () +#define GET_Tag4() TT_Get_ULong () + +#define FILE_Pos() TT_File_Pos() + +#define FILE_Seek( _position_ ) \ + ( (error = TT_Seek_File( (Long)(_position_) )) != TT_Err_Ok ) +#define FILE_Skip( _distance_ ) \ + ( (error = TT_Skip_File( (Long)(_distance_) )) != TT_Err_Ok ) +#define FILE_Read( buffer, count ) \ + ( (error = TT_Read_File ( buffer, \ + (Long)(count) )) != TT_Err_Ok ) +#define FILE_Read_At( pos, buffer, count ) \ + ( (error = TT_Read_At_File( (Long)(pos), \ + buffer, \ + (Long)(count) )) != TT_Err_Ok ) + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + +#ifdef __cplusplus + } +#endif + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttmemory.c b/Build/source/libs/libttf/ttmemory.c new file mode 100644 index 00000000000..280c05f22d6 --- /dev/null +++ b/Build/source/libs/libttf/ttmemory.c @@ -0,0 +1,397 @@ +/******************************************************************* + * + * ttmemory.c 1.2 + * + * Memory management component (body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * + * Changes between 1.1 and 1.2: + * + * - the font pool is gone. + * + * - introduced the FREE macro and the Free function for + * future use in destructors. + * + * - Init_FontPool() is now a macro to allow the compilation of + * 'legacy' applications (all four test programs have been updated). + * + ******************************************************************/ + +#include "ttdebug.h" +#include "ttmemory.h" +#include "ttengine.h" + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_memory + + +#ifdef DEBUG_MEMORY + +#include <stdio.h> + +#define MAX_TRACKED_BLOCKS 1024 + + struct TMemRec_ + { + void* base; + Long size; + }; + + typedef struct TMemRec_ TMemRec; + + static TMemRec pointers[MAX_TRACKED_BLOCKS + 1]; + + static Int num_alloc; + static Int num_free; + static Int num_realloc; /* counts only `real' reallocations + (i.e., an existing buffer will be resized + to a value larger than zero */ + + static Int fail_alloc; + static Int fail_realloc; + static Int fail_free; + +#endif /* DEBUG_MEMORY */ + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + Long TTMemory_Allocated; + Long TTMemory_MaxAllocated; +#endif + + +/******************************************************************* + * + * Function : TT_Alloc + * + * Description : Allocates memory from the heap buffer. + * + * Input : Size size of the memory to be allocated + * P pointer to a buffer pointer + * + * Output : Error code. + * + * NOTE : The newly allocated block should _always_ be zeroed + * on return. Many parts of the engine rely on this to + * work properly. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Alloc( ULong Size, void** P ) + { +#ifdef DEBUG_MEMORY + Int i; +#endif + + + if ( !P ) + return TT_Err_Invalid_Argument; + + if ( Size > (size_t)-1 ) + return TT_Err_Out_Of_Memory; + if ( Size > 0 ) + { + *P = (void*)malloc( Size ); + if ( !*P ) + return TT_Err_Out_Of_Memory; + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated += Size; + TTMemory_MaxAllocated += Size; +#endif + +#ifdef DEBUG_MEMORY + + num_alloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != NULL ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_alloc++; + else + { + pointers[i].base = *P; + pointers[i].size = Size; + } + +#endif /* DEBUG_MEMORY */ + + MEM_Set( *P, 0, Size ); + } + else + *P = NULL; + + return TT_Err_Ok; + } + + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + +/******************************************************************* + * + * Function : TT_Realloc + * + * Description : Reallocates memory from the heap buffer. + * + * Input : Size new size of the memory to be allocated; + * if zero, TT_Free() will be called + * P pointer to a buffer pointer; if *P == NULL, + * TT_Alloc() will be called + * + * Output : Error code. + * + * NOTES : It's not necessary to zero the memory in case the + * reallocated buffer is larger than before -- the + * application has to take care of this. + * + * If the memory request fails, TT_Free() will be + * called on *P, and TT_Err_Out_Of_Memory returned. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Realloc( ULong Size, void** P ) + { + void* Q; + +#ifdef DEBUG_MEMORY + Int i; +#endif + + + if ( !P ) + return TT_Err_Invalid_Argument; + + if ( !*P ) + return TT_Alloc( Size, P ); + + if ( Size == 0 ) + return TT_Free( P ); + + if ( Size > (size_t)-1 ) + { + TT_Free( *P ); + return TT_Err_Out_Of_Memory; + } + + Q = (void*)realloc( *P, Size ); + if ( !Q ) + { + TT_Free( *P ); + return TT_Err_Out_Of_Memory; + } + +#ifdef DEBUG_MEMORY + + num_realloc++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_realloc++; + else + { +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated += Size - pointers[i].size; + if ( Size > pointers[i].size ) + TTMemory_MaxAllocated += Size - pointers[i].size; +#endif + + pointers[i].base = Q; + pointers[i].size = size; + } +#endif /* DEBUG_MEMORY */ + + *P = Q; + + return TT_Err_Ok; + } + + +#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE */ + + +/******************************************************************* + * + * Function : TT_Free + * + * Description : Releases a previously allocated block of memory. + * + * Input : P pointer to memory block + * + * Output : Always SUCCESS. + * + * Note : The pointer must _always_ be set to NULL by this function. + * + ******************************************************************/ + + EXPORT_FUNC + TT_Error TT_Free( void** P ) + { +#ifdef DEBUG_MEMORY + Int i; +#endif /* DEBUG_MEMORY */ + + + if ( !P || !*P ) + return TT_Err_Ok; + +#ifdef DEBUG_MEMORY + + num_free++; + + i = 0; + while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P ) + i++; + + if ( i >= MAX_TRACKED_BLOCKS ) + fail_free++; + else + { +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated -= pointers[i].size; +#endif + + pointers[i].base = NULL; + pointers[i].size = 0; + } +#endif /* DEBUG_MEMORY */ + + free( *P ); + + *P = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Init + * + * Description : Initializes the memory. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Init( void ) + { +#ifdef DEBUG_MEMORY + Int i; + + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + pointers[i].base = NULL; + pointers[i].size = 0; + } + + num_alloc = 0; + num_realloc = 0; + num_free = 0; + + fail_alloc = 0; + fail_realloc = 0; + fail_free = 0; +#endif + + +#ifndef TT_CONFIG_OPTION_THREAD_SAFE + TTMemory_Allocated = 0; + TTMemory_MaxAllocated = 0; +#endif + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : TTMemory_Done + * + * Description : Finalizes memory usage. + * + * Output : Always SUCCESS. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTMemory_Done( void ) + { +#ifdef DEBUG_MEMORY + Int i, num_leaked, tot_leaked; + + + num_leaked = 0; + tot_leaked = 0; + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + num_leaked ++; + tot_leaked += pointers[i].size; + } + } + + fprintf( stderr, + "%d memory allocations, of which %d failed\n", + num_alloc, + fail_alloc ); + + fprintf( stderr, + "%d memory reallocations, of which %d failed\n", + num_realloc, + fail_realloc ); + + fprintf( stderr, + "%d memory frees, of which %d failed\n", + num_free, + fail_free ); + + if ( num_leaked > 0 ) + { + fprintf( stderr, + "There are %d leaked memory blocks, totalizing %d bytes\n", + num_leaked, tot_leaked ); + + for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ ) + { + if ( pointers[i].base ) + { + fprintf( stderr, + "index: %4d (base: $%08lx, size: %08ld)\n", + i, + (long)pointers[i].base, + pointers[i].size ); + } + } + } + else + fprintf( stderr, "No memory leaks !\n" ); + +#endif /* DEBUG_MEMORY */ + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttmemory.h b/Build/source/libs/libttf/ttmemory.h new file mode 100644 index 00000000000..8cdae2327d2 --- /dev/null +++ b/Build/source/libs/libttf/ttmemory.h @@ -0,0 +1,125 @@ +/******************************************************************* + * + * ttmemory.h 1.2 + * + * Memory management component (specification). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Changes between 1.2 and 1.1: + * + * - the font pool is gone! All allocations are now performed + * with malloc() and free(). + * + * - introduced the FREE() macro and the Free() function for + * future use in destructors. + * + * - Init_FontPool() is now a macro to allow the compilation of + * 'legacy' applications (all four test programs have been updated). + * + ******************************************************************/ + +#ifndef TTMEMORY_H +#define TTMEMORY_H + +#include "ttconfig.h" +#include "tttypes.h" +#include <string.h> + + +#ifdef __cplusplus + extern "C" { +#endif + +#define MEM_Set( dest, byte, count ) memset( dest, byte, count ) + +#ifdef HAVE_MEMCPY +#define MEM_Copy( dest, source, count ) memcpy( dest, source, count ) +#else +#define MEM_Copy( dest, source, count ) bcopy( source, dest, count ) +#endif + +#ifdef HAVE_MEMMOVE +#define MEM_Move( dest, source, count ) memmove( dest, source, count ) +#else +#define MEM_Move( dest, source, count ) bcopy( source, dest, count ) +#endif + + +#define MEM_Alloc( _pointer_, _size_ ) \ + TT_Alloc( _size_, (void**)&(_pointer_) ) + +#define MEM_Realloc( _pointer_, _size_ ) \ + TT_Realloc( _size_, (void**)&(_pointer_) ) + +#define ALLOC( _pointer_, _size_ ) \ + ( ( error = MEM_Alloc( _pointer_, _size_ ) ) != TT_Err_Ok ) + +#define ALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + ( ( error = MEM_Alloc( _pointer_, \ + (_count_) * sizeof ( _type_ ) ) ) != TT_Err_Ok ) + +#define REALLOC( _pointer_, _size_ ) \ + ( ( error = MEM_Realloc( _pointer_, _size_ ) ) != TT_Err_Ok ) + +#define REALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + ( (error = MEM_Realloc( _pointer_, \ + (_count_) * sizeof ( _type_ ) ) ) != TT_Err_Ok ) + +#define FREE( _pointer_ ) \ + TT_Free( (void**)&(_pointer_) ) + + + /* Allocate a block of memory of 'Size' bytes from the heap, and */ + /* sets the pointer '*P' to its address. If 'Size' is 0, or in */ + /* case of error, the pointer is always set to NULL. */ + + EXPORT_DEF + TT_Error TT_Alloc( ULong Size, void** P ); + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + /* Reallocates a block of memory pointed to by '*P' to 'Size' */ + /* bytes from the heap, possibly changing '*P'. If 'Size' is 0, */ + /* TT_Free() is called, if '*P' is NULL, TT_Alloc() is called. */ + /* '*P' is freed (if it's non-NULL) in case of error. */ + + EXPORT_DEF + TT_Error TT_Realloc( ULong Size, void** P ); + +#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE */ + + /* Releases a block that was previously allocated through Alloc. */ + /* Note that the function returns successfully when P or *P are */ + /* already NULL. The pointer '*P' is set to NULL on exit in */ + /* case of success. */ + + EXPORT_DEF + TT_Error TT_Free( void** P ); + + + /* For "legacy" applications, that should be re-coded. */ + /* Note that this won't release the previously allocated font pool. */ + +#define Init_FontPool( x, y ) while( 0 ) { } + + + LOCAL_DEF TT_Error TTMemory_Init( void ); + LOCAL_DEF TT_Error TTMemory_Done( void ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTMEMORY_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttmutex.c b/Build/source/libs/libttf/ttmutex.c new file mode 100644 index 00000000000..2f4b9204e0c --- /dev/null +++ b/Build/source/libs/libttf/ttmutex.c @@ -0,0 +1,85 @@ +/******************************************************************* + * + * ttmutex.c 1.0 + * + * Mutual exclusion object, single-threaded implementation + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTE: This is a generic non-functional implementation + * that you are welcome to refine for your own system. + * + * Please name your system-specific source with a + * different name (like ttmutex-os2.c or ttmutex-linux.c) + * and change your makefile accordingly. + * + ******************************************************************/ + +#include "ttmutex.h" + + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_mutex + + +/* ANSI C prevents the compilation of empty units. We thus introduce */ +/* a dummy typedef to get rid of compiler warnings/errors. */ +/* Note that gcc's -ansi -pedantic does not report any error here. */ +/* Watcom, VC++ or Borland C++ do however. */ + + typedef void _ttmutex_to_satisfy_ANSI_C_; + + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE + + LOCAL_FUNC + void TT_Mutex_Create ( TMutex* mutex ) + { + *mutex = (void*)-1; + /* Replace this line with your own mutex creation code */ + } + + + LOCAL_FUNC + void TT_Mutex_Delete ( TMutex* mutex ) + { + *mutex = (void*)0; + /* Replace this line with your own mutex destruction code */ + } + + + LOCAL_FUNC + void TT_Mutex_Lock ( TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate. */ + if ( !mutex ) + return; + + ; /* Insert your own mutex locking code here */ + } + + + LOCAL_FUNC + void TT_Mutex_Release( TMutex* mutex ) + { + /* NOTE: It is legal to call this function with a NULL argument */ + /* in which case an immediate return is appropriate */ + if ( !mutex ) + return; + + ; /* Insert your own mutex release code here */ + } + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttmutex.h b/Build/source/libs/libttf/ttmutex.h new file mode 100644 index 00000000000..097385b22a0 --- /dev/null +++ b/Build/source/libs/libttf/ttmutex.h @@ -0,0 +1,59 @@ +/******************************************************************* + * + * ttmutex.h 1.0 + * + * Mutual exclusion object / dummy generic interface. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * Note: This file provides a generic interface. The implementation + * to compile depends on your system and the type of + * library you want to build (either singly-threaded, + * thread-safe or re-entrant). + * + * Please read the technical documentation for more details. + * + ******************************************************************/ + +#ifndef TTMUTEX_H +#define TTMUTEX_H + +#include "ttconfig.h" + + + typedef void* TMutex; /* typeless reference to a mutex */ + +#ifdef TT_CONFIG_OPTION_THREAD_SAFE /* thread-safe and re-entrant builds */ + +#define MUTEX_Create( mutex ) TT_Mutex_Create ( &(mutex) ) +#define MUTEX_Destroy( mutex ) TT_Mutex_Delete ( &(mutex) ) +#define MUTEX_Lock( mutex ) TT_Mutex_Lock ( &(mutex) ) +#define MUTEX_Release( mutex ) TT_Mutex_Release( &(mutex) ) + + LOCAL_DEF void TT_Mutex_Create ( TMutex* mutex ); /* Create a new mutex */ + LOCAL_DEF void TT_Mutex_Delete ( TMutex* mutex ); /* Delete a mutex */ + LOCAL_DEF void TT_Mutex_Lock ( TMutex* mutex ); /* Lock a mutex. */ + LOCAL_DEF void TT_Mutex_Release( TMutex* mutex ); /* Release a mutex */ + +#else /* for the single-thread build */ + +#define MUTEX_Create( mutex ) /* nothing */ +#define MUTEX_Destroy( mutex ) /* nothing */ +#define MUTEX_Lock( mutex ) /* nothing */ +#define MUTEX_Release( mutex ) /* nothing */ + + /* No code will be generated for mutex operations */ + +#endif /* TT_CONFIG_OPTION_THREAD_SAFE */ + +#endif /* TTMUTEX_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttobjs.c b/Build/source/libs/libttf/ttobjs.c new file mode 100644 index 00000000000..9ce11013ae8 --- /dev/null +++ b/Build/source/libs/libttf/ttobjs.c @@ -0,0 +1,1495 @@ +/******************************************************************* + * + * ttobjs.c 1.0 + * + * Objects manager. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#include "ttobjs.h" +#include "ttfile.h" +#include "ttcalc.h" +#include "ttmemory.h" +#include "ttload.h" +#include "ttinterp.h" +#include "ttdebug.h" + + +/* Add extensions definition */ +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE +#include "ttextend.h" +#endif + +/* Required by tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_objs + +/******************************************************************* + * + * Function : New_Context + * + * Description : Creates a new execution context for a given + * face object. + * + ******************************************************************/ + + LOCAL_FUNC + PExecution_Context New_Context( PFace face ) + { + PEngine_Instance engine; + PExecution_Context exec; + + + if ( !face ) + return NULL; + + engine = face->engine; + CACHE_New( engine->objs_exec_cache, exec, face ); + return exec; + } + + +/******************************************************************* + * + * Function : Done_Context + * + * Description : Discards an execution context. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Done_Context( PExecution_Context exec ) + { + PEngine_Instance engine; + + + if ( !exec ) + return TT_Err_Ok; + + engine = exec->face->engine; + return CACHE_Done( engine->objs_exec_cache, exec ); + } + + +#if 0 + +/******************************************************************* + * + * Function : New_Instance + * + * Description : Creates a new instance for a given face object. + * + ******************************************************************/ + + LOCAL_FUNC + PInstance New_Instance( PFace face ) + { + PInstance ins; + + + if ( !face ) + return NULL; + + CACHE_New( &face->instances, ins, face ); + + return ins; + } + + +/******************************************************************* + * + * Function : Done_Instance + * + * Description : Discards an instance. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Done_Instance( PInstance instance ) + { + return CACHE_Done( &instance->owner->instances, instance ); + } + +#endif + + +/******************************************************************* + * * + * GLYPH ZONE FUNCTIONS * + * * + * * + *******************************************************************/ + +/******************************************************************* + * + * Function : New_Glyph_Zone + * + * Description : Allocates a new glyph zone + * + * Input : pts pointer to the target glyph zone record + * maxPoints capacity of glyph zone in points + * maxContours capacity of glyph zone in contours + * + * Return : Error code. + * + *****************************************************************/ + + static + TT_Error New_Glyph_Zone( PGlyph_Zone pts, + UShort maxPoints, + UShort maxContours ) + { + TT_Error error; + + + if ( ALLOC( pts->org, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) || + ALLOC( pts->cur, maxPoints * 2 * sizeof ( TT_F26Dot6 ) ) || + ALLOC( pts->touch, maxPoints * sizeof ( Byte ) ) || + ALLOC( pts->contours, maxContours * sizeof ( Short ) ) ) + return error; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Done_Glyph_Zone + * + * Description : Deallocates a glyph zone + * + * Input : pts pointer to the target glyph zone record + * + * Return : Error code. + * + *****************************************************************/ + + static + TT_Error Done_Glyph_Zone( PGlyph_Zone pts ) + { + FREE( pts->contours ); + FREE( pts->touch ); + FREE( pts->cur ); + FREE( pts->org ); + + return TT_Err_Ok; + } + + + +/******************************************************************* + * * + * CODERANGE FUNCTIONS * + * * + *******************************************************************/ + +/******************************************************************* + * + * Function : Goto_CodeRange + * + * Description : Switch to a new code range (updates Code and IP). + * + * Input : exec target execution context + * range new execution code range + * IP new IP in new code range + * + * Output : SUCCESS on success. FAILURE on error (no code range). + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Goto_CodeRange( PExecution_Context exec, + Int range, + ULong IP ) + { + PCodeRange cr; + + + if ( range < 1 || range > 3 ) + return TT_Err_Bad_Argument; + + cr = &exec->codeRangeTable[range - 1]; + + if ( cr->Base == NULL ) + return TT_Err_Invalid_CodeRange; + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for IP <= Size, instead of IP < Size. */ + + if ( IP > cr->Size ) + return TT_Err_Code_Overflow; + + exec->code = cr->Base; + exec->codeSize = cr->Size; + exec->IP = IP; + exec->curRange = range; + + return TT_Err_Ok; + } + + +#if 0 + +/******************************************************************* + * + * Function : Get_CodeRange + * + * Description : Returns a pointer to a given code range. Should + * be used only by the debugger. Returns NULL if + * 'range' is out of current bounds. + * + * Input : exec target execution context + * range new execution code range + * + * Output : Pointer to the code range record. NULL on failure. + * + *****************************************************************/ + + LOCAL_FUNC + PCodeRange Get_CodeRange( PExecution_Context exec, Int range ) + { + if ( range < 1 || range > 3 ) + return NULL; + else /* arrays start with 1 in Pascal, and with 0 in C */ + return &exec->codeRangeTable[range - 1]; + } + +#endif + + +/******************************************************************* + * + * Function : Set_CodeRange + * + * Description : Sets a code range. + * + * Input : exec target execution context + * range code range index + * base new code base + * length range size in bytes + * + * Output : SUCCESS on success. FAILURE on error. + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Set_CodeRange( PExecution_Context exec, + Int range, + void* base, + ULong length ) + { + if ( range < 1 || range > 3 ) + return TT_Err_Bad_Argument; + + exec->codeRangeTable[range - 1].Base = (Byte*)base; + exec->codeRangeTable[range - 1].Size = length; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Clear_CodeRange + * + * Description : Clears a code range. + * + * Input : exec target execution context + * range code range index + * + * Output : SUCCESS on success. FAILURE on error. + * + * Note : Does not set the Error variable. + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Clear_CodeRange( PExecution_Context exec, Int range ) + { + if ( range < 1 || range > 3 ) + return TT_Err_Bad_Argument; + + exec->codeRangeTable[range - 1].Base = NULL; + exec->codeRangeTable[range - 1].Size = 0; + + return TT_Err_Ok; + } + + + +/******************************************************************* + * * + * EXECUTION CONTEXT ROUTINES * + * * + *******************************************************************/ + +/******************************************************************* + * + * Function : Context_Destroy + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Context_Destroy( void* _context ) + { + PExecution_Context exec = (PExecution_Context)_context; + + if ( !exec ) + return TT_Err_Ok; + + /* free composite load stack */ + FREE( exec->loadStack ); + exec->loadSize = 0; + + /* points zone */ + Done_Glyph_Zone( &exec->pts ); + exec->maxPoints = 0; + exec->maxContours = 0; + + /* free stack */ + FREE( exec->stack ); + exec->stackSize = 0; + + /* free call stack */ + FREE( exec->callStack ); + exec->callSize = 0; + exec->callTop = 0; + + /* free glyph code range */ + FREE( exec->glyphIns ); + exec->glyphSize = 0; + + exec->instance = NULL; + exec->face = NULL; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Context_Create + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Context_Create( void* _context, void* _face ) + { + PExecution_Context exec = (PExecution_Context)_context; + + PFace face = (PFace)_face; + TT_Error error; + + + /* XXX : We don't reserve arrays anymore, this is done automatically */ + /* during a "Context_Load".. */ + + exec->callSize = 32; + if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TCallRecord ) ) + goto Fail_Memory; + + /* all values in the context are set to 0 already, but this is */ + /* here as a remainder */ + exec->maxPoints = 0; + exec->maxContours = 0; + + exec->stackSize = 0; + exec->loadSize = 0; + exec->glyphSize = 0; + + exec->stack = NULL; + exec->loadStack = NULL; + exec->glyphIns = NULL; + + exec->face = face; + exec->instance = NULL; + + return TT_Err_Ok; + + Fail_Memory: + Context_Destroy( exec ); + return error; + } + + +/******************************************************************* + * + * Function : Context_Load + * + *****************************************************************/ + +/****************************************************************/ +/* */ +/* Update_Max : Reallocate a buffer if it needs to */ +/* */ +/* input: size address of buffer's current size */ +/* expressed in elements */ +/* */ +/* multiplier size in bytes of each element in the */ +/* buffer */ +/* */ +/* buff address of the buffer base pointer */ +/* */ +/* new_max new capacity (size) of the buffer */ + + static + TT_Error Update_Max( ULong* size, + ULong multiplier, + void** buff, + ULong new_max ) + { + TT_Error error; + + if ( *size < new_max ) + { + FREE( *buff ); + if ( ALLOC( *buff, new_max * multiplier ) ) + return error; + *size = new_max; + } + return TT_Err_Ok; + } + + +/****************************************************************/ +/* */ +/* Update_Zone: Reallocate a zone if it needs to */ +/* */ +/* input: zone address of the target zone */ +/* */ +/* maxPoints address of the zone's current capacity */ +/* in points */ +/* */ +/* maxContours address of the zone's current capacity */ +/* in contours */ +/* */ +/* newPoints new capacity in points */ +/* */ +/* newContours new capacity in contours */ +/* */ + + static + TT_Error Update_Zone( PGlyph_Zone zone, + UShort* maxPoints, + UShort* maxContours, + UShort newPoints, + UShort newContours ) + { + if ( *maxPoints < newPoints || *maxContours < newContours ) + { + TT_Error error; + + + Done_Glyph_Zone( zone ); + + error = New_Glyph_Zone( zone, newPoints, newContours ); + if ( error ) + return error; + + *maxPoints = newPoints; + *maxContours = newContours; + } + return TT_Err_Ok; + } + + + LOCAL_FUNC + TT_Error Context_Load( PExecution_Context exec, + PFace face, + PInstance ins ) + { + Int i; + TMaxProfile* maxp; + TT_Error error; + + exec->face = face; + maxp = &face->maxProfile; + + exec->instance = ins; + + if ( ins ) + { + exec->numFDefs = ins->numFDefs; + exec->numIDefs = ins->numIDefs; + exec->maxFDefs = ins->maxFDefs; + exec->maxIDefs = ins->maxIDefs; + exec->FDefs = ins->FDefs; + exec->IDefs = ins->IDefs; + exec->metrics = ins->metrics; + + exec->maxFunc = ins->maxFunc; + exec->maxIns = ins->maxIns; + + for ( i = 0; i < MAX_CODE_RANGES; i++ ) + exec->codeRangeTable[i] = ins->codeRangeTable[i]; + + /* set graphics state */ + exec->GS = ins->GS; + + exec->cvtSize = ins->cvtSize; + exec->cvt = ins->cvt; + + exec->storeSize = ins->storeSize; + exec->storage = ins->storage; + + exec->twilight = ins->twilight; + } + + error = Update_Max( &exec->loadSize, + sizeof ( TSubglyph_Record ), + (void**)&exec->loadStack, + face->maxComponents + 1 ); + if ( error ) + return error; + + error = Update_Max( &exec->stackSize, + sizeof ( TT_F26Dot6 ), + (void**)&exec->stack, + maxp->maxStackElements + 32 ); + /* XXX : We reserve a little more elements on the stack to deal safely */ + /* with broken fonts like arialbs, courbs, timesbs... */ + if ( error ) + return error; + + error = Update_Max( &exec->glyphSize, + sizeof ( Byte ), + (void**)&exec->glyphIns, + maxp->maxSizeOfInstructions ); + if ( error ) + return error; + + error = Update_Zone( &exec->pts, + &exec->maxPoints, + &exec->maxContours, + exec->face->maxPoints + 2, + exec->face->maxContours ); + /* XXX : We reserve two positions for the phantom points! */ + if ( error ) + return error; + + exec->pts.n_points = 0; + exec->pts.n_contours = 0; + + exec->instruction_trap = FALSE; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Context_Save + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Context_Save( PExecution_Context exec, + PInstance ins ) + { + Int i; + + /* XXXX : Will probably disappear soon with all the coderange */ + /* management, which is now rather obsolete. */ + + ins->numFDefs = exec->numFDefs; + ins->numIDefs = exec->numIDefs; + ins->maxFunc = exec->maxFunc; + ins->maxIns = exec->maxIns; + + for ( i = 0; i < MAX_CODE_RANGES; i++ ) + ins->codeRangeTable[i] = exec->codeRangeTable[i]; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Context_Run + * + *****************************************************************/ + + LOCAL_FUNC + TT_Error Context_Run( PExecution_Context exec, + Bool debug ) + { + TT_Error error; + + + if ( (error = Goto_CodeRange( exec, + TT_CodeRange_Glyph, 0 )) != TT_Err_Ok ) + return error; + + exec->zp0 = exec->pts; + exec->zp1 = exec->pts; + exec->zp2 = exec->pts; + + exec->GS.gep0 = 1; + exec->GS.gep1 = 1; + exec->GS.gep2 = 1; + + exec->GS.projVector.x = 0x4000; + exec->GS.projVector.y = 0x0000; + + exec->GS.freeVector = exec->GS.projVector; + exec->GS.dualVector = exec->GS.projVector; + + exec->GS.round_state = 1; + exec->GS.loop = 1; + + /* some glyphs leave something on the stack. so we clean it */ + /* before a new execution. */ + exec->top = 0; + exec->callTop = 0; + + if ( !debug ) + return RunIns( exec ); + else + return TT_Err_Ok; + } + + + LOCAL_FUNC + const TGraphicsState Default_GraphicsState = + { + 0, 0, 0, + { 0x4000, 0 }, + { 0x4000, 0 }, + { 0x4000, 0 }, + 1, 64, 1, + TRUE, 68, 0, 0, 9, 3, + 0, FALSE, 2, 1, 1, 1 + }; + + + +/******************************************************************* + * * + * INSTANCE FUNCTIONS * + * * + * * + *******************************************************************/ + +/******************************************************************* + * + * Function : Instance_Destroy + * + * Description : + * + * Input : _instance the instance object to destroy + * + * Output : error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Instance_Destroy( void* _instance ) + { + PInstance ins = (PInstance)_instance; + + + if ( !_instance ) + return TT_Err_Ok; + + if ( ins->debug ) + { + /* the debug context must be deleted by the debugger itself */ + ins->context = NULL; + ins->debug = FALSE; + } + + FREE( ins->cvt ); + ins->cvtSize = 0; + + /* free storage area */ + FREE( ins->storage ); + ins->storeSize = 0; + + /* twilight zone */ + Done_Glyph_Zone( &ins->twilight ); + + FREE( ins->FDefs ); + FREE( ins->IDefs ); + ins->numFDefs = 0; + ins->numIDefs = 0; + ins->maxFDefs = 0; + ins->maxIDefs = 0; + ins->maxFunc = -1; + ins->maxIns = -1; + + ins->owner = NULL; + ins->valid = FALSE; + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Instance_Create + * + * Description : + * + * Input : _instance instance record to initialize + * _face parent face object + * + * Output : Error code. All partially built subtables are + * released on error. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Instance_Create( void* _instance, + void* _face ) + { + PInstance ins = (PInstance)_instance; + PFace face = (PFace)_face; + TT_Error error; + Int i; + UShort n_twilight; + + PMaxProfile maxp = &face->maxProfile; + + + ins->owner = face; + ins->valid = FALSE; + + ins->maxFDefs = maxp->maxFunctionDefs; + ins->maxIDefs = maxp->maxInstructionDefs; + ins->cvtSize = face->cvtSize; + ins->storeSize = maxp->maxStorage; + + /* Set default metrics */ + { + PIns_Metrics metrics = &ins->metrics; + + + metrics->pointSize = 10 * 64; /* default pointsize = 10pts */ + + metrics->x_resolution = 96; /* default resolution = 96dpi */ + metrics->y_resolution = 96; + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + + metrics->rotated = FALSE; + metrics->stretched = FALSE; + + /* set default compensation ( all 0 ) */ + for ( i = 0; i < 4; i++ ) + metrics->compensations[i] = 0; + } + + /* allocate function defs, instruction defs, cvt and storage area */ + if ( ALLOC_ARRAY( ins->FDefs, ins->maxFDefs, TDefRecord ) || + ALLOC_ARRAY( ins->IDefs, ins->maxIDefs, TDefRecord ) || + ALLOC_ARRAY( ins->cvt, ins->cvtSize, Long ) || + ALLOC_ARRAY( ins->storage, ins->storeSize, Long ) ) + goto Fail_Memory; + + /* reserve twilight zone */ + n_twilight = maxp->maxTwilightPoints; + error = New_Glyph_Zone( &ins->twilight, n_twilight, 0 ); + if (error) + goto Fail_Memory; + + ins->twilight.n_points = n_twilight; + + return TT_Err_Ok; + + Fail_Memory: + Instance_Destroy( ins ); + return error; + } + + +/******************************************************************* + * + * Function : Instance_Init + * + * Description : Initialize a fresh new instance. + * Executes the font program if any is found. + * + * Input : _instance the instance object to destroy + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Instance_Init( PInstance ins ) + { + PExecution_Context exec; + + TT_Error error; + PFace face = ins->owner; + + + if ( ins->debug ) + exec = ins->context; + else + exec = New_Context( face ); + /* debugging instances have their own context */ + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + ins->GS = Default_GraphicsState; + + ins->numFDefs = 0; + ins->numIDefs = 0; + ins->maxFunc = -1; + ins->maxIns = -1; + + Context_Load( exec, face, ins ); + + exec->callTop = 0; + exec->top = 0; + + exec->period = 64; + exec->phase = 0; + exec->threshold = 0; + + { + PIns_Metrics metrics = &exec->metrics; + + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + metrics->pointSize = 0; + metrics->x_scale1 = 0; + metrics->x_scale2 = 1; + metrics->y_scale1 = 0; + metrics->y_scale2 = 1; + + metrics->ppem = 0; + metrics->scale1 = 0; + metrics->scale2 = 1; + metrics->ratio = 1L << 16; + } + + exec->instruction_trap = FALSE; + + exec->cvtSize = ins->cvtSize; + exec->cvt = ins->cvt; + + exec->F_dot_P = 0x10000; + + /* allow font program execution */ + Set_CodeRange( exec, + TT_CodeRange_Font, + face->fontProgram, + face->fontPgmSize ); + + /* disable CVT and glyph programs coderange */ + Clear_CodeRange( exec, TT_CodeRange_Cvt ); + Clear_CodeRange( exec, TT_CodeRange_Glyph ); + + if ( face->fontPgmSize > 0 ) + { + error = Goto_CodeRange( exec, TT_CodeRange_Font, 0 ); + if ( error ) + goto Fin; + + error = RunIns( exec ); + } + else + error = TT_Err_Ok; + + Fin: + Context_Save( exec, ins ); + + if ( !ins->debug ) + Done_Context( exec ); + /* debugging instances keep their context */ + + ins->valid = FALSE; + + return error; + } + + +/******************************************************************* + * + * Function : Instance_Reset + * + * Description : Resets an instance to a new pointsize/transform. + * Executes the cvt program if any is found. + * + * Input : _instance the instance object to destroy + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Instance_Reset( PInstance ins ) + { + PExecution_Context exec; + + TT_Error error; + ULong i; + UShort j; + PFace face; + + + if ( !ins ) + return TT_Err_Invalid_Instance_Handle; + + if ( ins->valid ) + return TT_Err_Ok; + + face = ins->owner; + + if ( ins->metrics.x_ppem < 1 || + ins->metrics.y_ppem < 1 ) + return TT_Err_Invalid_PPem; + + /* compute new transformation */ + if ( ins->metrics.x_ppem >= ins->metrics.y_ppem ) + { + ins->metrics.scale1 = ins->metrics.x_scale1; + ins->metrics.scale2 = ins->metrics.x_scale2; + ins->metrics.ppem = ins->metrics.x_ppem; + ins->metrics.x_ratio = 1L << 16; + ins->metrics.y_ratio = TT_MulDiv( ins->metrics.y_ppem, + 0x10000, + ins->metrics.x_ppem ); + } + else + { + ins->metrics.scale1 = ins->metrics.y_scale1; + ins->metrics.scale2 = ins->metrics.y_scale2; + ins->metrics.ppem = ins->metrics.y_ppem; + ins->metrics.x_ratio = TT_MulDiv( ins->metrics.x_ppem, + 0x10000, + ins->metrics.y_ppem ); + ins->metrics.y_ratio = 1L << 16; + } + + /* Scale the cvt values to the new ppem. */ + /* We use by default the y ppem to scale the CVT. */ + + for ( i = 0; i < ins->cvtSize; i++ ) + ins->cvt[i] = TT_MulDiv( face->cvt[i], + ins->metrics.scale1, + ins->metrics.scale2 ); + + /* All twilight points are originally zero */ + for ( j = 0; j < ins->twilight.n_points; j++ ) + { + ins->twilight.org[j].x = 0; + ins->twilight.org[j].y = 0; + ins->twilight.cur[j].x = 0; + ins->twilight.cur[j].y = 0; + } + + /* clear storage area */ + for ( i = 0; i < ins->storeSize; i++ ) + ins->storage[i] = 0; + + ins->GS = Default_GraphicsState; + + /* get execution context and run prep program */ + + if ( ins->debug ) + exec = ins->context; + else + exec = New_Context(face); + /* debugging instances have their own context */ + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + Context_Load( exec, face, ins ); + + Set_CodeRange( exec, + TT_CodeRange_Cvt, + face->cvtProgram, + face->cvtPgmSize ); + + Clear_CodeRange( exec, TT_CodeRange_Glyph ); + + exec->instruction_trap = FALSE; + + exec->top = 0; + exec->callTop = 0; + + if ( face->cvtPgmSize > 0 ) + { + error = Goto_CodeRange( exec, TT_CodeRange_Cvt, 0 ); + if ( error ) + goto Fin; + + if ( !ins->debug ) + error = RunIns( exec ); + } + else + error = TT_Err_Ok; + + ins->GS = exec->GS; + /* save default graphics state */ + + Fin: + Context_Save( exec, ins ); + + if ( !ins->debug ) + Done_Context( exec ); + /* debugging instances keep their context */ + + if ( !error ) + ins->valid = TRUE; + + return error; + } + + + +/******************************************************************* + * * + * FACE FUNCTIONS * + * * + * * + *******************************************************************/ + +/******************************************************************* + * + * Function : Face_Destroy + * + * Description : The face object destructor. + * + * Input : _face typeless pointer to the face object to destroy + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Face_Destroy( void* _face ) + { + PFace face = (PFace)_face; + UShort n; + + + if ( !face ) + return TT_Err_Ok; + + /* well, we assume that no other thread is using the face */ + /* at this moment, but one is never sure enough. */ + MUTEX_Lock( face->lock ); + + /* first of all, destroys the cached sub-objects */ + Cache_Destroy( &face->instances ); + Cache_Destroy( &face->glyphs ); + + /* destroy the extensions */ +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + Extension_Destroy( face ); +#endif + + /* freeing the collection table */ + FREE( face->ttcHeader.TableDirectory ); + face->ttcHeader.DirCount = 0; + + /* freeing table directory */ + FREE( face->dirTables ); + face->numTables = 0; + + /* freeing the locations table */ + FREE( face->glyphLocations ); + face->numLocations = 0; + + /* freeing the character mapping tables */ + for ( n = 0; n < face->numCMaps; n++ ) + CharMap_Free( face->cMaps + n ); + + FREE( face->cMaps ); + face->numCMaps = 0; + + /* freeing the CVT */ + FREE( face->cvt ); + face->cvtSize = 0; + + /* freeing the horizontal metrics */ + FREE( face->horizontalHeader.long_metrics ); + FREE( face->horizontalHeader.short_metrics ); + + /* freeing the vertical ones, if any */ + if (face->verticalInfo) + { + FREE( face->verticalHeader.long_metrics ); + FREE( face->verticalHeader.short_metrics ); + face->verticalInfo = 0; + } + + /* freeing the programs */ + FREE( face->fontProgram ); + FREE( face->cvtProgram ); + face->fontPgmSize = 0; + face->cvtPgmSize = 0; + + /* freeing the gasp table */ + FREE( face->gasp.gaspRanges ); + face->gasp.numRanges = 0; + + /* freeing the name table */ + Free_TrueType_Names( face ); + + /* freeing the hdmx table */ + Free_TrueType_Hdmx( face ); + + /* TT_Close_Stream( &face->stream ); -- this is performed by the API */ + + /* destroy the mutex */ + MUTEX_Destroy(face->lock); + + return TT_Err_Ok; + } + + +/******************************************************************* + * + * Function : Face_Create + * + * Description : The face object constructor. + * + * Input : _face face record to build + * _input input stream where to load font data + * + * Output : Error code. + * + * NOTE : The input stream is kept in the face object. The + * caller shouldn't destroy it after calling Face_Create(). + * + ******************************************************************/ + +#undef LOAD_ +#define LOAD_( table ) \ + (error = Load_TrueType_##table (face)) != TT_Err_Ok + + + LOCAL_FUNC + TT_Error Face_Create( void* _face, + void* _input ) + { + PEngine_Instance engine; + + TFont_Input* input = (TFont_Input*)_input; + PFace face = (PFace)_face; + TT_Error error; + + + face->stream = input->stream; + face->engine = input->engine; + + engine = face->engine; + + MUTEX_Create( face->lock ); + + Cache_Create( engine, + engine->objs_instance_class, + &face->instances, + &face->lock ); + + Cache_Create( engine, + engine->objs_glyph_class, + &face->glyphs, + &face->lock ); + + /* Load collection directory if present, then font directory */ + + error = Load_TrueType_Directory( face, input->fontIndex ); + if ( error ) + goto Fail; + + /* Load tables */ + + if ( LOAD_( Header ) || + LOAD_( MaxProfile ) || + LOAD_( Locations ) || + + (error = Load_TrueType_Metrics_Header( face, 0 )) != TT_Err_Ok || + /* load the 'hhea' & 'hmtx' tables at once */ + + LOAD_( CMap ) || + LOAD_( CVT ) || + LOAD_( Programs ) || + LOAD_( Gasp ) || + LOAD_( Names ) || + LOAD_( OS2 ) || + LOAD_( PostScript ) || + + (error = Load_TrueType_Metrics_Header( face, 1 )) != TT_Err_Ok || + /* try to load the 'vhea' & 'vmtx' at once if present */ + + LOAD_( Hdmx ) ) + + goto Fail; + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + if ( ( error = Extension_Create( face ) ) != TT_Err_Ok ) + return error; +#endif + + return TT_Err_Ok; + + Fail : + Face_Destroy( face ); + return error; + } + +#undef LOAD_ + + +/******************************************************************* + * + * Function : Glyph_Destroy + * + * Description : The glyph object destructor. + * + * Input : _glyph typeless pointer to the glyph record to destroy + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Glyph_Destroy( void* _glyph ) + { + PGlyph glyph = (PGlyph)_glyph; + + + if ( !glyph ) + return TT_Err_Ok; + + glyph->outline.owner = TRUE; + return TT_Done_Outline( &glyph->outline ); + } + + +/******************************************************************* + * + * Function : Glyph_Create + * + * Description : The glyph object constructor. + * + * Input : _glyph glyph record to build. + * _face the glyph's parent face. + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error Glyph_Create( void* _glyph, + void* _face ) + { + PFace face = (PFace)_face; + PGlyph glyph = (PGlyph)_glyph; + + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( !glyph ) + return TT_Err_Invalid_Glyph_Handle; + + glyph->face = face; + + /* XXX: Don't forget the space for the 2 phantom points */ + return TT_New_Outline( glyph->face->maxPoints + 2, + glyph->face->maxContours, + &glyph->outline ); + } + + +/******************************************************************* + * + * Function : Scale_X + * + * Description : scale an horizontal distance from font + * units to 26.6 pixels + * + * Input : metrics pointer to metrics + * x value to scale + * + * Output : scaled value + * + ******************************************************************/ + + LOCAL_FUNC + TT_Pos Scale_X( PIns_Metrics metrics, TT_Pos x ) + { + return TT_MulDiv( x, metrics->x_scale1, metrics->x_scale2 ); + } + + +/******************************************************************* + * + * Function : Scale_Y + * + * Description : scale a vertical distance from font + * units to 26.6 pixels + * + * Input : metrics pointer to metrics + * y value to scale + * + * Output : scaled value + * + ******************************************************************/ + + LOCAL_FUNC + TT_Pos Scale_Y( PIns_Metrics metrics, TT_Pos y ) + { + return TT_MulDiv( y, metrics->y_scale1, metrics->y_scale2 ); + } + + +/******************************************************************* + * + * Function : TTObjs_Init + * + * Description : The TTObjs component initializer. Creates the + * object cache classes, as well as the face record + * cache. + * + * Input : engine engine instance + * + * Output : Error code. + * + ******************************************************************/ + + static + const TCache_Class objs_face_class = + { + sizeof ( TFace ), + -1, + Face_Create, + Face_Destroy, + NULL, + NULL + }; + + static + const TCache_Class objs_instance_class = + { + sizeof ( TInstance ), + -1, + Instance_Create, + Instance_Destroy, + NULL, + NULL + }; + + /* Note that we use a cache size of 1 for the execution context. */ + /* This is to avoid re-creating a new context each time we */ + /* change one instance's attribute (resolution and/or char sizes) */ + /* or when we load a glyph. */ + + static + const TCache_Class objs_exec_class = + { + sizeof ( TExecution_Context ), + 1, + Context_Create, + Context_Destroy, + NULL, + NULL + }; + + static + const TCache_Class objs_glyph_class = + { + sizeof ( TGlyph ), + -1, + Glyph_Create, + Glyph_Destroy, + NULL, + NULL + }; + + + LOCAL_FUNC + TT_Error TTObjs_Init( PEngine_Instance engine ) + { + PCache face_cache, exec_cache; + TT_Error error; + + + face_cache = 0; + exec_cache = 0; + + if ( ALLOC( face_cache, sizeof ( TCache ) ) || + ALLOC( exec_cache, sizeof ( TCache ) ) ) + goto Fail; + + /* create face cache */ + error = Cache_Create( engine, (PCache_Class)&objs_face_class, + face_cache, &engine->lock ); + if ( error ) + goto Fail; + + engine->objs_face_cache = face_cache; + + error = Cache_Create( engine, (PCache_Class)&objs_exec_class, + exec_cache, &engine->lock ); + if ( error ) + goto Fail; + + engine->objs_exec_cache = exec_cache; + + engine->objs_face_class = (PCache_Class)&objs_face_class; + engine->objs_instance_class = (PCache_Class)&objs_instance_class; + engine->objs_execution_class = (PCache_Class)&objs_exec_class; + engine->objs_glyph_class = (PCache_Class)&objs_glyph_class; + + goto Exit; + + Fail: + FREE( face_cache ); + FREE( exec_cache ); + + Exit: + return error; + } + + +/******************************************************************* + * + * Function : TTObjs_Done + * + * Description : The TTObjs component finalizer. + * + * Input : engine engine instance + * + * Output : Error code. + * + ******************************************************************/ + + LOCAL_FUNC + TT_Error TTObjs_Done( PEngine_Instance engine ) + { + /* destroy all active faces and contexts before releasing the */ + /* caches */ + Cache_Destroy( (TCache*)engine->objs_exec_cache ); + Cache_Destroy( (TCache*)engine->objs_face_cache ); + + /* Now frees caches and cache classes */ + FREE( engine->objs_exec_cache ); + FREE( engine->objs_face_cache ); + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttobjs.h b/Build/source/libs/libttf/ttobjs.h new file mode 100644 index 00000000000..a5ba1ff86f7 --- /dev/null +++ b/Build/source/libs/libttf/ttobjs.h @@ -0,0 +1,873 @@ +/******************************************************************* + * + * ttobjs.h 1.0 + * + * Objects definition unit. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef TTOBJS_H +#define TTOBJS_H + +#include "ttconfig.h" +#include "ttengine.h" +#include "ttmutex.h" +#include "ttcache.h" +#include "tttables.h" +#include "ttcmap.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* */ +/* This file contains the definitions and methods of the four */ +/* kinds of objects managed by the FreeType engine. These are: */ +/* */ +/* */ +/* Face objects: */ +/* */ +/* There is always one face object per opened TrueType font */ +/* file, and only one. The face object contains data that is */ +/* independent of current transform/scaling/rotation and */ +/* pointsize, or glyph index. This data is made of several */ +/* critical tables that are loaded on face object creation. */ +/* */ +/* A face object tracks all active and recycled objects of */ +/* the instance and execution context classes. Destroying a face */ +/* object will automatically destroy all associated instances. */ +/* */ +/* */ +/* Instance objects: */ +/* */ +/* An instance object always relates to a given face object, */ +/* known as its 'parent' or 'owner', and contains only the */ +/* data that is specific to one given pointsize/transform of */ +/* the face. You can only create an instance from a face object. */ +/* */ +/* An instance's current transform/pointsize can be changed */ +/* at any time using a single high-level API call, */ +/* TT_Reset_Instance(). */ +/* */ +/* Execution Context objects: */ +/* */ +/* An execution context (or context in short) relates to a face. */ +/* It contains the data and tables that are necessary to load */ +/* and hint (i.e. execute the glyph instructions of) one glyph. */ +/* A context is a transient object that is queried/created on */ +/* the fly: client applications never deal with them directly. */ +/* */ +/* */ +/* Glyph objects: */ +/* */ +/* A glyph object contains only the minimal glyph information */ +/* needed to render one glyph correctly. This means that a glyph */ +/* object really contains tables that are sized to hold the */ +/* contents of _any_ glyph of a given face. A client application */ +/* can usually create one glyph object for a given face, then use */ +/* it for all subsequent loads. */ +/* */ +/* Here is an example of a client application : */ +/* (NOTE: No error checking performed here!) */ +/* */ +/* */ +/* TT_Face face; -- face handle */ +/* TT_Instance ins1, ins2; -- two instance handles */ +/* TT_Glyph glyph; -- glyph handle */ +/* */ +/* TT_Init_FreeType(); */ +/* */ +/* -- Initialize the engine. This must be done prior to _any_ */ +/* operation. */ +/* */ +/* TT_Open_Face( "/some/face/name.ttf", &face ); */ +/* */ +/* -- create the face object. This call opens the font file */ +/* */ +/* TT_New_Instance( face, &ins1 ); */ +/* TT_New_Instance( face, &ins2 ); */ +/* */ +/* TT_Set_Instance_PointSize( ins1, 8 ); */ +/* TT_Set_Instance_PointSize( ins2, 12 ); */ +/* */ +/* -- create two distinct instances of the same face */ +/* -- ins1 is pointsize 8 at resolution 96 dpi */ +/* -- ins2 is pointsize 12 at resolution 96 dpi */ +/* */ +/* TT_New_Glyph( face, &glyph ); */ +/* */ +/* -- create a new glyph object which will receive the contents */ +/* of any glyph of 'face' */ +/* */ +/* TT_Load_Glyph( ins1, glyph, 64, DEFAULT_GLYPH_LOAD ); */ +/* */ +/* -- load glyph indexed 64 at pointsize 8 in the 'glyph' object */ +/* -- NOTE: This call will fail if the instance and the glyph */ +/* do not relate to the same face object. */ +/* */ +/* TT_Get_Outline( glyph, &outline ); */ +/* */ +/* -- extract the glyph outline from the object and copies it */ +/* to the 'outline' record */ +/* */ +/* TT_Get_Metrics( glyph, &metrics ); */ +/* */ +/* -- extract the glyph metrics and put them into the 'metrics' */ +/* record */ +/* */ +/* TT_Load_Glyph( ins2, glyph, 64, DEFAULT_GLYPH_LOAD ); */ +/* */ +/* -- load the same glyph at pointsize 12 in the 'glyph' object */ +/* */ +/* */ +/* TT_Close_Face( &face ); */ +/* */ +/* -- destroy the face object. This will destroy 'ins1' and */ +/* 'ins2'. However, the glyph object will still be available */ +/* */ +/* TT_Done_FreeType(); */ +/* */ +/* -- Finalize the engine. This will also destroy all pending */ +/* glyph objects (here 'glyph'). */ + + struct TFace_; + struct TInstance_; + struct TExecution_Context_; + struct TGlyph_; + + typedef struct TFace_ TFace; + typedef TFace* PFace; + + typedef struct TInstance_ TInstance; + typedef TInstance* PInstance; + + typedef struct TExecution_Context_ TExecution_Context; + typedef TExecution_Context* PExecution_Context; + + typedef struct TGlyph_ TGlyph; + typedef TGlyph* PGlyph; + + + /*************************************************************/ + /* */ + /* ADDITIONAL SUBTABLES */ + /* */ + /* These tables are not precisely defined by the specs */ + /* but their structures is implied by the TrueType font */ + /* file layout. */ + /* */ + /*************************************************************/ + + /* Graphics State */ + /* */ + /* The Graphics State (GS) is managed by the */ + /* instruction field, but does not come from */ + /* the font file. Thus, we can use 'int's */ + /* where needed. */ + + struct TGraphicsState_ + { + UShort rp0; + UShort rp1; + UShort rp2; + + TT_UnitVector dualVector; + TT_UnitVector projVector; + TT_UnitVector freeVector; + + Long loop; + TT_F26Dot6 minimum_distance; + Int round_state; + + Bool auto_flip; + TT_F26Dot6 control_value_cutin; + TT_F26Dot6 single_width_cutin; + TT_F26Dot6 single_width_value; + Short delta_base; + Short delta_shift; + + Byte instruct_control; + Bool scan_control; + Int scan_type; + + UShort gep0; + UShort gep1; + UShort gep2; + }; + + typedef struct TGraphicsState_ TGraphicsState; + + + LOCAL_DEF + const TGraphicsState Default_GraphicsState; + + + /*************************************************************/ + /* */ + /* EXECUTION SUBTABLES */ + /* */ + /* These sub-tables relate to instruction execution. */ + /* */ + /*************************************************************/ + +#define MAX_CODE_RANGES 3 + +/* There can only be 3 active code ranges at once: */ +/* - the Font Program */ +/* - the CVT Program */ +/* - a glyph's instructions set */ + +#define TT_CodeRange_Font 1 +#define TT_CodeRange_Cvt 2 +#define TT_CodeRange_Glyph 3 + + + struct TCodeRange_ + { + PByte Base; + ULong Size; + }; + + typedef struct TCodeRange_ TCodeRange; + typedef TCodeRange* PCodeRange; + + + /* Defintion of a code range */ + /* */ + /* Code ranges can be resident to a glyph (i.e. the Font Program) */ + /* while some others are volatile (Glyph instructions). */ + /* Tracking the state and presence of code ranges allows function */ + /* and instruction definitions within a code range to be forgotten */ + /* when the range is discarded. */ + + typedef TCodeRange TCodeRangeTable[MAX_CODE_RANGES]; + + /* defines a function/instruction definition record */ + + struct TDefRecord_ + { + Int Range; /* in which code range is it located ? */ + ULong Start; /* where does it start ? */ + Int Opc; /* function #, or instruction code */ + Bool Active; /* is it active ? */ + }; + + typedef struct TDefRecord_ TDefRecord; + typedef TDefRecord* PDefRecord; + typedef TDefRecord* PDefArray; + + /* defines a call record, used to manage function calls. */ + + struct TCallRecord_ + { + Int Caller_Range; + ULong Caller_IP; + Long Cur_Count; + ULong Cur_Restart; + }; + + typedef struct TCallRecord_ TCallRecord; + typedef TCallRecord* PCallRecord; + typedef TCallRecord* PCallStack; /* defines a simple call stack */ + + + /* This type defining a set of glyph points will be used to represent */ + /* each zone (regular and twilight) during instructions decoding. */ + struct TGlyph_Zone_ + { + UShort n_points; /* number of points in zone */ + Short n_contours; /* number of contours */ + + TT_Vector* org; /* original points coordinates */ + TT_Vector* cur; /* current points coordinates */ + + Byte* touch; /* current touch flags */ + UShort* contours; /* contour end points */ + }; + + typedef struct TGlyph_Zone_ TGlyph_Zone; + typedef TGlyph_Zone* PGlyph_Zone; + + + +#ifndef TT_STATIC_INTEPRETER /* indirect implementation */ + +#define EXEC_OPS PExecution_Context exc, +#define EXEC_OP PExecution_Context exc +#define EXEC_ARGS exc, +#define EXEC_ARG exc + +#else /* static implementation */ + +#define EXEC_OPS /* void */ +#define EXEC_OP /* void */ +#define EXEC_ARGS /* void */ +#define EXEC_ARG /* void */ + +#endif + + /* Rounding function, as used by the interpreter */ + typedef TT_F26Dot6 (*TRound_Function)( EXEC_OPS TT_F26Dot6 distance, + TT_F26Dot6 compensation ); + + /* Point displacement along the freedom vector routine, as */ + /* used by the interpreter */ + typedef void (*TMove_Function)( EXEC_OPS PGlyph_Zone zone, + UShort point, + TT_F26Dot6 distance ); + + /* Distance projection along one of the proj. vectors, as used */ + /* by the interpreter */ + typedef TT_F26Dot6 (*TProject_Function)( EXEC_OPS TT_Vector* v1, + TT_Vector* v2 ); + + /* reading a cvt value. Take care of non-square pixels when needed */ + typedef TT_F26Dot6 (*TGet_CVT_Function)( EXEC_OPS ULong index ); + + /* setting or moving a cvt value. Take care of non-square pixels */ + /* when needed */ + typedef void (*TSet_CVT_Function)( EXEC_OPS ULong index, + TT_F26Dot6 value ); + + /* subglyph transformation record */ + struct TTransform_ + { + TT_Fixed xx, xy; /* transformation */ + TT_Fixed yx, yy; /* matrix */ + TT_F26Dot6 ox, oy; /* offsets */ + }; + + typedef struct TTransform_ TTransform; + typedef TTransform* PTransform; + + /* subglyph loading record. Used to load composite components */ + struct TSubglyph_Record_ + { + Long index; /* subglyph index; initialized with -1 */ + Bool is_scaled; /* is the subglyph scaled? */ + Bool is_hinted; /* should it be hinted? */ + Bool preserve_pps; /* preserve phantom points? */ + + Long file_offset; + + TT_Big_Glyph_Metrics metrics; + + TGlyph_Zone zone; + + Long arg1; /* first argument */ + Long arg2; /* second argument */ + + UShort element_flag; /* current load element flag */ + + TTransform transform; /* transform */ + + TT_Vector pp1, pp2; /* phantom points */ + + }; + + typedef struct TSubglyph_Record_ TSubglyph_Record; + typedef TSubglyph_Record* PSubglyph_Record; + typedef TSubglyph_Record* PSubglyph_Stack; + + /* A note regarding non-squared pixels: */ + /* */ + /* (This text will probably go into some docs at some time, for */ + /* now, it is kept there to explain some definitions in the */ + /* TIns_Metrics record). */ + /* */ + /* The CVT is a one-dimensional array containing values that */ + /* control certain important characteristics in a font, like */ + /* the height of all capitals, all lowercase letter, default */ + /* spacing or stem width/height. */ + /* */ + /* These values are found in FUnits in the font file, and must be */ + /* scaled to pixel coordinates before being used by the CVT and */ + /* glyph programs. Unfortunately, when using distinct x and y */ + /* resolutions (or distinct x and y pointsizes), there are two */ + /* possible scalings. */ + /* */ + /* A first try was to implement a 'lazy' scheme where all values */ + /* were scaled when first used. However, while some values are always */ + /* used in the same direction, and some other are used in many */ + /* different circumstances and orientations. */ + /* */ + /* I have found a simpler way to do the same, and it even seems to */ + /* work in most of the cases: */ + /* */ + /* - all CVT values are scaled to the maximum ppem size */ + /* */ + /* - when performing a read or write in the CVT, a ratio factor */ + /* is used to perform adequate scaling. Example: */ + /* */ + /* x_ppem = 14 */ + /* y_ppem = 10 */ + /* */ + /* we choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */ + /* entries are scaled to it. */ + /* */ + /* x_ratio = 1.0 */ + /* y_ratio = y_ppem/ppem (< 1.0) */ + /* */ + /* we compute the current ratio like: */ + /* */ + /* - if projVector is horizontal, */ + /* ratio = x_ratio = 1.0 */ + /* - if projVector is vertical, */ + /* ratop = y_ratio */ + /* - else, */ + /* ratio = sqrt((proj.x*x_ratio)^2 + (proj.y*y_ratio)^2) */ + /* */ + /* reading a cvt value returns ratio * cvt[index] */ + /* writing a cvt value in pixels cvt[index] / ratio */ + /* */ + /* the current ppem is simply ratio * ppem */ + /* */ + + /* metrics used by the instance and execution context objects */ + struct TIns_Metrics_ + { + TT_F26Dot6 pointSize; /* point size. 1 point = 1/72 inch. */ + + UShort x_resolution; /* device horizontal resolution in dpi. */ + UShort y_resolution; /* device vertical resolution in dpi. */ + + UShort x_ppem; /* horizontal pixels per EM */ + UShort y_ppem; /* vertical pixels per EM */ + + Long x_scale1; + Long x_scale2; /* used to scale FUnits to fractional pixels */ + + Long y_scale1; + Long y_scale2; /* used to scale FUnits to fractional pixels */ + + /* for non-square pixels */ + Long x_ratio; + Long y_ratio; + + UShort ppem; /* maximum ppem size */ + Long ratio; /* current ratio */ + Long scale1; + Long scale2; /* scale for ppem */ + + TT_F26Dot6 compensations[4]; /* device-specific compensations */ + + Bool rotated; /* `is the glyph rotated?'-flag */ + Bool stretched; /* `is the glyph stretched?'-flag */ + }; + + typedef struct TIns_Metrics_ TIns_Metrics; + typedef TIns_Metrics* PIns_Metrics; + + + + /***********************************************************************/ + /* */ + /* FreeType Face Type */ + /* */ + /***********************************************************************/ + + struct TFace_ + { + /* parent engine instance for the face object */ + PEngine_Instance engine; + + /* i/o stream */ + TT_Stream stream; + + /* used only by the threaded builds of the library */ + TMutex lock; + + /* TrueType collection header, if any was found */ + TTTCHeader ttcHeader; + + /* maximum profile table, as found in the TrueType file */ + TMaxProfile maxProfile; + + /* Note: */ + /* it seems that some maximum values cannot be */ + /* taken directly from this table, but rather by */ + /* combining some of its fields; e.g. the max. */ + /* number of points seems to be given by */ + /* MAX( maxPoints, maxCompositePoints ) */ + /* */ + /* For this reason, we define later our own */ + /* max values that are used to load and allocate */ + /* further tables. */ + + TT_Header fontHeader; /* the font header, as */ + /* found in the TTF file */ + TT_Horizontal_Header horizontalHeader; /* the horizontal header */ + + Bool verticalInfo; /* True when vertical table */ + TT_Vertical_Header verticalHeader; /* is present in the font */ + + TT_OS2 os2; /* 'OS/2' table */ + + TT_Postscript postscript; /* 'Post' table */ + + TT_Hdmx hdmx; /* 'Hdmx' table */ + + TName_Table nameTable; /* name table */ + + TGasp gasp; /* the 'gasp' table */ + + /* The directory of TrueType tables for this typeface */ + UShort numTables; + PTableDirEntry dirTables; + + /* The directory of character mappings table for */ + /* this typeface */ + UShort numCMaps; + PCMapTable cMaps; + + /* The glyph locations table */ + ULong numLocations; /* UShort is not enough */ +#ifndef TT_HUGE_PTR + PStorage glyphLocations; +#else + Storage TT_HUGE_PTR * glyphLocations; +#endif + + /* NOTE : The "hmtx" is now part of the horizontal header */ + + /* the font program, if any */ + ULong fontPgmSize; + PByte fontProgram; + + /* the cvt program, if any */ + ULong cvtPgmSize; + PByte cvtProgram; + + /* the original, unscaled, control value table */ + ULong cvtSize; + PShort cvt; + + /* The following values _must_ be set by the */ + /* maximum profile loader */ + + UShort numGlyphs; /* the face's total number of glyphs */ + UShort maxPoints; /* max glyph points number, simple and composite */ + UShort maxContours; /* max glyph contours numb, simple and composite */ + UShort maxComponents; /* max components in a composite glyph */ + + /* the following are object caches to track active */ + /* and recycled instances and execution contexts */ + /* objects. See 'ttcache.h' */ + + TCache instances; /* current instances for this face */ + TCache glyphs; /* current glyph containers for this face */ + + + /* A typeless pointer to the face object extensions defined */ + /* in the 'ttextend.*' files. */ + void* extension; + Int n_extensions; /* number of extensions */ + + /* Use extensions to provide additional capabilities to the */ + /* engine. Read the developer's guide in the documentation */ + /* directory to know how to do that. */ + + /* a generic pointer for client use - see TT_Set/Get_Face_Pointer */ + void* generic; + }; + + + + /***********************************************************************/ + /* */ + /* FreeType Instance Type */ + /* */ + /***********************************************************************/ + + struct TInstance_ + { + PFace owner; /* face object */ + + Bool valid; + + TIns_Metrics metrics; + + UShort numFDefs; /* number of function definitions */ + UShort maxFDefs; + PDefArray FDefs; /* table of FDefs entries */ + + UShort numIDefs; /* number of instruction definitions */ + UShort maxIDefs; + PDefArray IDefs; /* table of IDefs entries */ + + Int maxFunc; /* maximum function definition id */ + Int maxIns; /* maximum instruction definition id */ + + TCodeRangeTable codeRangeTable; + + TGraphicsState GS; + TGraphicsState default_GS; + + ULong cvtSize; /* the scaled control value table */ + PLong cvt; + + ULong storeSize; /* The storage area is now part of the */ + PLong storage; /* instance */ + + TGlyph_Zone twilight; /* The instance's twilight zone */ + + /* debugging variables */ + + /* When using the debugger, we must keep the */ + /* execution context tied to the instance */ + /* object rather than asking it on demand */ + + Bool debug; + PExecution_Context context; + + /* a generic pointer for client use - see TT_Set/Get_Instance_Pointer */ + void* generic; + }; + + + /***********************************************************************/ + /* */ + /* FreeType Execution Context Type */ + /* */ + /***********************************************************************/ + + struct TExecution_Context_ + { + PFace face; + PInstance instance; + + /* instructions state */ + + TT_Error error; /* last execution error */ + + Long top; /* top of exec. stack */ + + ULong stackSize; /* size of exec. stack */ + PStorage stack; /* current exec. stack */ + + Long args; + ULong new_top; /* new top after exec. */ + + TGlyph_Zone zp0, /* zone records */ + zp1, + zp2, + pts, + twilight; + + TIns_Metrics metrics; /* instance metrics */ + + TGraphicsState GS; /* current graphics state */ + + Int curRange; /* current code range number */ + PByte code; /* current code range */ + ULong IP; /* current instruction pointer */ + ULong codeSize; /* size of current range */ + + Byte opcode; /* current opcode */ + Int length; /* length of current opcode */ + + Bool step_ins; /* true if the interpreter must */ + /* increment IP after ins. exec */ + ULong cvtSize; + PLong cvt; + + ULong glyphSize; /* glyph instructions buffer size */ + PByte glyphIns; /* glyph instructions buffer */ + + UShort numFDefs; /* number of function defs */ + UShort maxFDefs; /* maximum number of function defs */ + PDefRecord FDefs; /* table of FDefs entries */ + + UShort numIDefs; /* number of instruction defs */ + UShort maxIDefs; /* maximum number of instruction defs */ + PDefRecord IDefs; /* table of IDefs entries */ + + Int maxFunc; + Int maxIns; + + Int callTop, /* top of call stack during execution */ + callSize; /* size of call stack */ + PCallStack callStack; /* call stack */ + + UShort maxPoints; /* capacity of this context's "pts" */ + UShort maxContours; /* record, expressed in points and */ + /* contours.. */ + + TCodeRangeTable codeRangeTable; /* table of valid coderanges */ + /* useful for the debugger */ + + ULong storeSize; /* size of current storage */ + PLong storage; /* storage area */ + + TT_F26Dot6 period; /* values used for the */ + TT_F26Dot6 phase; /* 'SuperRounding' */ + TT_F26Dot6 threshold; + + /* this seems to be unused */ +#if 0 + Int cur_ppem; /* ppem along the current proj vector */ +#endif + Long scale1; /* scaling values along the current */ + Long scale2; /* projection vector too.. */ + Bool cached_metrics; /* the ppem is computed lazily. used */ + /* to trigger computation when needed */ + + Bool instruction_trap; /* If True, the interpreter will */ + /* exit after each instruction */ + + TGraphicsState default_GS; /* graphics state resulting from */ + /* the prep program */ + Bool is_composite; /* ture if the glyph is composite */ + + Bool pedantic_hinting; /* if true, read and write array */ + /* bounds faults halt the hinting */ + + /* latest interpreter additions */ + + Long F_dot_P; /* dot product of freedom and projection */ + /* vectors */ + TRound_Function func_round; /* current rounding function */ + + TProject_Function func_project, /* current projection function */ + func_dualproj, /* current dual proj. function */ + func_freeProj; /* current freedom proj. func */ + + TMove_Function func_move; /* current point move function */ + + TGet_CVT_Function func_read_cvt; /* read a cvt entry */ + TSet_CVT_Function func_write_cvt; /* write a cvt entry (in pixels) */ + TSet_CVT_Function func_move_cvt; /* incr a cvt entry (in pixels) */ + + ULong loadSize; + PSubglyph_Stack loadStack; /* loading subglyph stack */ + + }; + + + /***********************************************************************/ + /* */ + /* FreeType Glyph Object Type */ + /* */ + /***********************************************************************/ + + struct TGlyph_ + { + PFace face; + TT_Big_Glyph_Metrics metrics; + TT_Outline outline; + }; + + + /* The following type is used to load a font from a collection. */ + /* See Face_Create in ttobjs.c */ + + struct TFont_Input_ + { + TT_Stream stream; /* input stream */ + ULong fontIndex; /* index of font in collection */ + PEngine_Instance engine; /* parent engine instance */ + + }; + + typedef struct TFont_Input_ TFont_Input; + + + /********************************************************************/ + /* */ + /* Code Range Functions */ + /* */ + /********************************************************************/ + + /* Goto a specified coderange */ + LOCAL_DEF + TT_Error Goto_CodeRange( PExecution_Context exec, + Int range, + ULong IP ); + +#if 0 + /* Return a pointer to a given coderange record. */ + /* Used only by the debugger. */ + LOCAL_DEF + PCodeRange Get_CodeRange( PExecution_Context exec, + Int range ); +#endif + + /* Set a given code range properties */ + LOCAL_DEF + TT_Error Set_CodeRange( PExecution_Context exec, + Int range, + void* base, + ULong length ); + + /* Clear a given coderange */ + LOCAL_DEF + TT_Error Clear_CodeRange( PExecution_Context exec, Int range ); + + + LOCAL_DEF + PExecution_Context New_Context( PFace face ); + + LOCAL_DEF + TT_Error Done_Context( PExecution_Context exec ); + + + LOCAL_DEF + TT_Error Context_Load( PExecution_Context exec, + PFace face, + PInstance ins ); + + LOCAL_DEF + TT_Error Context_Save( PExecution_Context exec, + PInstance ins ); + + LOCAL_DEF + TT_Error Context_Run( PExecution_Context exec, + Bool debug ); + + LOCAL_DEF + TT_Error Instance_Init( PInstance ins ); + + LOCAL_DEF + TT_Error Instance_Reset( PInstance ins ); + + + /********************************************************************/ + /* */ + /* Handy scaling functions */ + /* */ + /********************************************************************/ + + LOCAL_DEF TT_Pos Scale_X( PIns_Metrics metrics, TT_Pos x ); + LOCAL_DEF TT_Pos Scale_Y( PIns_Metrics metrics, TT_Pos y ); + + /********************************************************************/ + /* */ + /* Component Initializer/Finalizer */ + /* */ + /* Called from 'freetype.c' */ + /* The component must create and register the face, instance and */ + /* execution context cache classes before any object can be */ + /* managed. */ + /* */ + /********************************************************************/ + + LOCAL_DEF TT_Error TTObjs_Init( PEngine_Instance engine ); + LOCAL_DEF TT_Error TTObjs_Done( PEngine_Instance engine ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTOBJS_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/ttraster.c b/Build/source/libs/libttf/ttraster.c new file mode 100644 index 00000000000..5daee1439cf --- /dev/null +++ b/Build/source/libs/libttf/ttraster.c @@ -0,0 +1,2729 @@ +/******************************************************************* + * + * ttraster.c 1.5 + * + * The FreeType glyph rasterizer (body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTES: + * + * This version supports the following: + * + * - direct grayscaling + * - sub-banding + * - drop-out modes 4 and 5 + * - second pass for complete drop-out control (bitmap only) + * - variable precision + * + * Changes between 1.5 and 1.4: + * + * Performance tuning. + * + * Changes between 1.4 and 1.3: + * + * Mainly performance tunings: + * + * - Line_Down() and Bezier_Down() now use the functions Line_Up() + * and Bezier_Up() to do their work. + * - optimized Split_Bezier() + * - optimized linked lists used during sweeps + * + ******************************************************************/ + +#include "ttraster.h" +#include "ttdebug.h" +#include "tttypes.h" +#include "ttengine.h" +#include "ttcalc.h" /* for TT_MulDiv only */ + +#include "ttmemory.h" /* only used to allocate memory on engine init */ + +/* required by the tracing mode */ +#undef TT_COMPONENT +#define TT_COMPONENT trace_raster + + +/* The default render pool size */ +#define RASTER_RENDER_POOL 64000 + +/* The size of the two-lines intermediate bitmap used */ +/* for anti-aliasing */ +#define RASTER_GRAY_LINES 2048 + + +#define Raster_Err_None TT_Err_Ok +#define Raster_Err_Not_Ini TT_Err_Raster_Not_Initialized +#define Raster_Err_Overflow TT_Err_Raster_Pool_Overflow +#define Raster_Err_Neg_Height TT_Err_Raster_Negative_Height +#define Raster_Err_Invalid TT_Err_Raster_Invalid_Value +#define Raster_Err_Gray_Unsupported TT_Err_Raster_Gray_Unsupported + + +/* FMulDiv means "Fast MulDiv", it is uses in case where 'b' is typically */ +/* a small value and the result of (a*b) is known to fit in 32 bits. */ +#define FMulDiv( a, b, c ) ( (a) * (b) / (c) ) + +/* On the other hand, SMulDiv is for "Slow MulDiv", and is used typically */ +/* for clipping computations. It simply uses the TT_MulDiv() function */ +/* defined in "ttcalc.h" */ +/* */ +/* So, the following definition fits the bill nicely, and we don't need */ +/* to use the one in 'ttcalc' anymore, even for 16-bit systems... */ +#define SMulDiv TT_MulDiv + + +/* Define DEBUG_RASTER if you want to generate a debug version of the */ +/* rasterizer. This will progressively draw the glyphs while all the */ +/* computation are done directly on the graphics screen (the glyphs */ +/* will be inverted). */ + +/* Note that DEBUG_RASTER should only be used for debugging with b/w */ +/* rendering, not with gray levels. */ + +/* The definition of DEBUG_RASTER should appear in the file */ +/* "ttconfig.h". */ + +#ifdef DEBUG_RASTER + extern Char* Vio; /* A pointer to VRAM or display buffer */ +#endif + + +/* The rasterizer is a very general purpose component, please leave */ +/* the following redefinitions there (you never know your target */ +/* environment). */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */ + /* Setting this constant to more than 32 is a */ + /* pure waste of space. */ + +#define Pixel_Bits 6 /* fractional bits of *input* coordinates */ + + /* States of each line, arc and profile */ + enum TStates_ + { + Unknown, + Ascending, + Descending, + Flat + }; + + typedef enum TStates_ TStates; + + struct TProfile_; + typedef struct TProfile_ TProfile; + typedef TProfile* PProfile; + + struct TProfile_ + { + TT_F26Dot6 X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PStorage offset; /* start of profile's data in render pool */ + Int flow; /* Profile orientation: Asc/Descending */ + Long height; /* profile's height in scanlines */ + Long start; /* profile's starting scanline */ + + UShort countL; /* number of lines to step before this */ + /* profile becomes drawable */ + + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + }; + + typedef PProfile TProfileList; + typedef PProfile* PProfileList; + + + /* I use the classic trick of two dummy records for the head and tail */ + /* of a linked list; this reduces tests in insertion/deletion/sorting. */ + /* NOTE: used during sweeps only. */ + + /* Simple record used to implement a stack of bands, required */ + /* by the sub-banding mechanism */ + + struct TBand_ + { + Short y_min; /* band's minimum */ + Short y_max; /* band's maximum */ + }; + + typedef struct TBand_ TBand; + + +#define AlignProfileSize \ + (( sizeof(TProfile)+sizeof(long)-1 ) / sizeof(long)) + + + /* Left fill bitmask */ + static const Byte LMask[8] = + { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; + + /* Right fill bitmask */ + static const Byte RMask[8] = + { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF }; + + /* prototypes used for sweep function dispatch */ + typedef void Function_Sweep_Init( RAS_ARGS Short* min, + Short* max ); + + typedef void Function_Sweep_Span( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ); + + typedef void Function_Sweep_Step( RAS_ARG ); + + +/* NOTE: These operations are only valid on 2's complement processors */ + +#define FLOOR( x ) ( (x) & -ras.precision ) +#define CEILING( x ) ( ((x) + ras.precision - 1) & -ras.precision ) +#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits ) +#define FRAC( x ) ( (x) & (ras.precision - 1) ) +#define SCALED( x ) ( ((x) << ras.scale_shift) - ras.precision_half ) + +#ifdef DEBUG_RASTER +#define DEBUG_PSET Pset() +#else +#define DEBUG_PSET +#endif + + struct TPoint_ + { + Long x, y; + }; + + typedef struct TPoint_ TPoint; + + + /* Note that I have moved the location of some fields in the */ + /* structure to ensure that the most used variables are used */ + /* at the top. Thus, their offset can be coded with less */ + /* opcodes, and it results in a smaller executable. */ + + struct TRaster_Instance_ + { + Int precision_bits; /* precision related variables */ + Int precision; + Int precision_half; + Long precision_mask; + Int precision_shift; + Int precision_step; + Int precision_jitter; + + Int scale_shift; /* == precision_shift for bitmaps */ + /* == precision_shift+1 for pixmaps */ + + PStorage buff; /* The profiles buffer */ + PStorage sizeBuff; /* Render pool size */ + PStorage maxBuff; /* Profiles buffer size */ + PStorage top; /* Current cursor in buffer */ + + TT_Error error; + + PByte flags; /* current flags table */ + PUShort outs; /* current outlines table */ + + UShort nPoints; /* number of points in current glyph */ + Short nContours; /* number of contours in current glyph */ + Int numTurns; /* number of Y-turns in outline */ + + TPoint* arc; /* current Bezier arc pointer */ + + UShort bWidth; /* target bitmap width */ + PByte bTarget; /* target bitmap buffer */ + PByte gTarget; /* target pixmap buffer */ + + Long lastX, lastY, minY, maxY; + + UShort num_Profs; /* current number of profiles */ + + Bool fresh; /* signals a fresh new profile which */ + /* 'start' field must be completed */ + Bool joint; /* signals that the last arc ended */ + /* exactly on a scanline. Allows */ + /* removal of doublets */ + PProfile cProfile; /* current profile */ + PProfile fProfile; /* head of linked list of profiles */ + PProfile gProfile; /* contour's first profile in case */ + /* of impact */ + TStates state; /* rendering state */ + + TT_Raster_Map target; /* description of target bit/pixmap */ + + Long traceOfs; /* current offset in target bitmap */ + Long traceG; /* current offset in target pixmap */ + + Short traceIncr; /* sweep's increment in target bitmap */ + + Short gray_min_x; /* current min x during gray rendering */ + Short gray_max_x; /* current max x during gray rendering */ + + /* dispatch variables */ + + Function_Sweep_Init* Proc_Sweep_Init; + Function_Sweep_Span* Proc_Sweep_Span; + Function_Sweep_Span* Proc_Sweep_Drop; + Function_Sweep_Step* Proc_Sweep_Step; + + TT_Vector* coords; + + Byte dropOutControl; /* current drop_out control method */ + + Byte grays[5]; /* Palette of gray levels used for render */ + + Byte* gray_lines; /* Intermediate table used to render the */ + /* graylevels pixmaps. */ + /* gray_lines is a buffer holding two */ + /* monochrome scanlines */ + Short gray_width; /* width in bytes of one monochrome */ + /* intermediate scanline of gray_lines. */ + /* Each gray pixel takes 2 bits long there */ + + /* The gray_lines must hold 2 lines, thus with size */ + /* in bytes of at least 'gray_width*2' */ + + Bool second_pass; /* indicates wether a horizontal pass */ + /* should be performed to control drop-out */ + /* accurately when calling Render_Glyph. */ + /* Note that there is no horizontal pass */ + /* during gray rendering. */ + TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */ + + TBand band_stack[16]; /* band stack used for sub-banding */ + Int band_top; /* band stack top */ + + Int count_table[256]; /* Look-up table used to quickly count */ + /* set bits in a gray 2x2 cell */ + }; + + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + + static TRaster_Instance cur_ras; +#define ras cur_ras + +#else + +#define ras (*raster) + +#endif /* TT_STATIC_RASTER */ + + +#ifdef DEBUG_RASTER + + /************************************************/ + /* */ + /* Pset: */ + /* */ + /* Used for debugging only. Plots a point */ + /* in VRAM during rendering (not afterwards). */ + /* */ + /* NOTE: This procedure relies on the value */ + /* of cProfile->start, which may not */ + /* be set when Pset is called sometimes. */ + /* This will usually result in a dot */ + /* plotted on the first screen scanline */ + /* (far away its original position). */ + /* */ + /* This "bug" reflects nothing wrong */ + /* in the current implementation, and */ + /* the bitmap is rendered correctly, */ + /* so don't panic if you see 'flying' */ + /* dots in debugging mode. */ + /* */ + /* - David */ + /* */ + /************************************************/ + + static void Pset( RAS_ARG ) + { + Long o; + Long x; + + + x = ras.top[-1]; + + switch ( ras.cProfile->flow ) + { + case TT_Flow_Up: + o = Vio_ScanLineWidth * + ( ras.top-ras.cProfile->offset + ras.cProfile->start ) + + ( x / (ras.precision*8) ); + break; + + case TT_Flow_Down: + o = Vio_ScanLineWidth * + ( ras.cProfile->start-ras.top + ras.cProfile->offset ) + + ( x / (ras.precision*8) ); + break; + } + + if ( o > 0 ) + Vio[o] |= (unsigned)0x80 >> ( (x/ras.precision) & 7 ); + } + + + static void Clear_Band( RAS_ARGS Int y1, Int y2 ) + { + MEM_Set( Vio + y1*Vio_ScanLineWidth, (y2-y1+1)*Vio_ScanLineWidth, 0 ); + } + +#endif /* DEBUG_RASTER */ + + +/************************************************************************/ +/* */ +/* Function: Set_High_Precision */ +/* */ +/* Description: Sets precision variables according to param flag. */ +/* */ +/* Input: High set to True for high precision (typically for */ +/* ppem < 18), false otherwise. */ +/* */ +/************************************************************************/ + + static void Set_High_Precision( RAS_ARGS Bool High ) + { + if ( High ) + { + ras.precision_bits = 10; + ras.precision_step = 128; + ras.precision_jitter = 24; + } + else + { + ras.precision_bits = 6; + ras.precision_step = 32; + ras.precision_jitter = 2; + } + + PTRACE7(( "Set_High_Precision(%s)\n", High ? "true" : "false" )); + + ras.precision = 1 << ras.precision_bits; + ras.precision_half = ras.precision / 2; + ras.precision_shift = ras.precision_bits - Pixel_Bits; + ras.precision_mask = -ras.precision; + } + + +/****************************************************************************/ +/* */ +/* Function: New_Profile */ +/* */ +/* Description: Creates a new Profile in the render pool. */ +/* */ +/* Input: aState state/orientation of the new Profile */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE in case of overflow or of incoherent Profile. */ +/* */ +/****************************************************************************/ + + static Bool New_Profile( RAS_ARGS TStates aState ) + { + if ( !ras.fProfile ) + { + ras.cProfile = (PProfile)ras.top; + ras.fProfile = ras.cProfile; + ras.top += AlignProfileSize; + } + + if ( ras.top >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + switch ( aState ) + { + case Ascending: + ras.cProfile->flow = TT_Flow_Up; + PTRACE7(( "New ascending profile = %lx\n", (long)ras.cProfile )); + break; + + case Descending: + ras.cProfile->flow = TT_Flow_Down; + PTRACE7(( "New descending profile = %lx\n", (long)ras.cProfile )); + break; + + default: + PTRACE0(( "Invalid profile direction in Raster:New_Profile !!\n" )); + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + ras.cProfile->start = 0; + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + ras.cProfile->link = (PProfile)0; + ras.cProfile->next = (PProfile)0; + + if ( !ras.gProfile ) + ras.gProfile = ras.cProfile; + + ras.state = aState; + ras.fresh = TRUE; + ras.joint = FALSE; + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: End_Profile */ +/* */ +/* Description: Finalizes the current Profile. */ +/* */ +/* Input: None */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE in case of overflow or incoherency. */ +/* */ +/****************************************************************************/ + + static Bool End_Profile( RAS_ARG ) + { + Long h; + PProfile oldProfile; + + + h = ras.top - ras.cProfile->offset; + + if ( h < 0 ) + { + PTRACE0(( "Negative height encountered in End_Profile!\n" )); + ras.error = Raster_Err_Neg_Height; + return FAILURE; + } + + if ( h > 0 ) + { + PTRACE1(( "Ending profile %lx, start = %ld, height = %ld\n", + (long)ras.cProfile, ras.cProfile->start, h )); + + oldProfile = ras.cProfile; + ras.cProfile->height = h; + ras.cProfile = (PProfile)ras.top; + + ras.top += AlignProfileSize; + + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + oldProfile->next = ras.cProfile; + ras.num_Profs++; + } + + if ( ras.top >= ras.maxBuff ) + { + PTRACE1(( "overflow in End_Profile\n" )); + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + ras.joint = FALSE; + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Insert_Y_Turn */ +/* */ +/* Description: Insert a salient into the sorted list placed on top */ +/* of the render pool */ +/* */ +/* Input: New y scanline position */ +/* */ +/****************************************************************************/ + + static + Bool Insert_Y_Turn( RAS_ARGS Int y ) + { + PStorage y_turns; + Int y2, n; + + n = ras.numTurns-1; + y_turns = ras.sizeBuff - ras.numTurns; + + /* look for first y value that is <= */ + while ( n >= 0 && y < y_turns[n] ) + n--; + + /* if it is <, simply insert it, ignore if == */ + if ( n >= 0 && y > y_turns[n] ) + while ( n >= 0 ) + { + y2 = y_turns[n]; + y_turns[n] = y; + y = y2; + n--; + } + + if ( n < 0 ) + { + if (ras.maxBuff <= ras.top) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + ras.maxBuff--; + ras.numTurns++; + ras.sizeBuff[-ras.numTurns] = y; + } + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Finalize_Profile_Table */ +/* */ +/* Description: Adjusts all links in the Profiles list. */ +/* */ +/* Input: None */ +/* */ +/* Returns: None. */ +/* */ +/****************************************************************************/ + + static + Bool Finalize_Profile_Table( RAS_ARG ) + { + Int bottom, top; + UShort n; + PProfile p; + + + n = ras.num_Profs; + + if ( n > 1 ) + { + p = ras.fProfile; + while ( n > 0 ) + { + if ( n > 1 ) + p->link = (PProfile)( p->offset + p->height ); + else + p->link = NULL; + + switch ( p->flow ) + { + case TT_Flow_Down: + bottom = p->start - p->height+1; + top = p->start; + p->start = bottom; + p->offset += p->height-1; + break; + + case TT_Flow_Up: + default: + bottom = p->start; + top = p->start + p->height-1; + } + + if ( Insert_Y_Turn( RAS_VARS bottom ) || + Insert_Y_Turn( RAS_VARS top+1 ) ) + return FAILURE; + + p = p->link; + n--; + } + } + else + ras.fProfile = NULL; + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Split_Bezier */ +/* */ +/* Description: Subdivides one Bezier arc into two joint */ +/* sub-arcs in the Bezier stack. */ +/* */ +/* Input: None (subdivided bezier is taken from the top of the */ +/* stack). */ +/* */ +/* Returns: None. */ +/* */ +/* */ +/* Note: This routine is the 'beef' of this component. It is _the_ */ +/* inner loop that should be optimized to hell to get the */ +/* best performance. */ +/* */ +/****************************************************************************/ + + static void Split_Bezier( TPoint* base ) + { + Long a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + + /* hand optimized. gcc doesn't seem too good at common expression */ + /* substitution and instruction scheduling ;-) */ + } + + +/****************************************************************************/ +/* */ +/* Function: Push_Bezier */ +/* */ +/* Description: Clears the Bezier stack and pushes a new arc on top of it. */ +/* */ +/* Input: x1,y1 x2,y2 x3,y3 new Bezier arc */ +/* */ +/* Returns: None. */ +/* */ +/****************************************************************************/ + + static void Push_Bezier( RAS_ARGS Long x1, Long y1, + Long x2, Long y2, + Long x3, Long y3 ) + { + ras.arc = ras.arcs; + ras.arc[2].x = x1; ras.arc[2].y = y1; + ras.arc[1].x = x2; ras.arc[1].y = y2; + ras.arc[0].x = x3; ras.arc[0].y = y3; + } + + +/****************************************************************************/ +/* */ +/* Function: Line_Up */ +/* */ +/* Description: Computes the x-coordinates of an ascending line segment */ +/* and stores them in the render pool. */ +/* */ +/* Input: x1,y1,x2,y2 Segment start (x1,y1) and end (x2,y2) points */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on Render Pool overflow. */ +/* */ +/****************************************************************************/ + + static Bool Line_Up( RAS_ARGS Long x1, Long y1, + Long x2, Long y2, + Long miny, Long maxy ) + { + Long Dx, Dy; + Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ + Long Ix, Rx, Ax; + + PStorage top; + + + Dx = x2 - x1; + Dy = y2 - y1; + + if ( Dy <= 0 || y2 < miny || y1 > maxy ) + return SUCCESS; + + if ( y1 < miny ) + { + /* Take care : miny-y1 can be a very large value, we use */ + /* a slow MulDiv function to avoid clipping bugs */ + x1 += SMulDiv( Dx, miny - y1, Dy ); + e1 = TRUNC( miny ); + f1 = 0; + } + else + { + e1 = TRUNC( y1 ); + f1 = FRAC( y1 ); + } + + if ( y2 > maxy ) + { + /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ + e2 = TRUNC( maxy ); + f2 = 0; + } + else + { + e2 = TRUNC( y2 ); + f2 = FRAC( y2 ); + } + + if ( f1 > 0 ) + { + if ( e1 == e2 ) return SUCCESS; + else + { + x1 += FMulDiv( Dx, ras.precision - f1, Dy ); + e1 += 1; + } + } + else + if ( ras.joint ) + { + ras.top--; + ras.joint = FALSE; + } + + ras.joint = ( f2 == 0 ); + + if ( ras.fresh ) + { + ras.cProfile->start = e1; + ras.fresh = FALSE; + } + + size = e2 - e1 + 1; + if ( ras.top + size >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + if ( Dx > 0 ) + { + Ix = (ras.precision*Dx) / Dy; + Rx = (ras.precision*Dx) % Dy; + Dx = 1; + } + else + { + Ix = -( (ras.precision*-Dx) / Dy ); + Rx = (ras.precision*-Dx) % Dy; + Dx = -1; + } + + Ax = -Dy; + top = ras.top; + + while ( size > 0 ) + { + *top++ = x1; + + DEBUG_PSET; + + x1 += Ix; + Ax += Rx; + if ( Ax >= 0 ) + { + Ax -= Dy; + x1 += Dx; + } + size--; + } + + ras.top = top; + return SUCCESS; + } + + + static Bool Line_Down( RAS_ARGS Long x1, Long y1, + Long x2, Long y2, + Long miny, Long maxy ) + { + Bool result, fresh; + + + fresh = ras.fresh; + + result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + return result; + } + + +/****************************************************************************/ +/* */ +/* Function: Bezier_Up */ +/* */ +/* Description: Computes thes x-coordinates of an ascending bezier arc */ +/* and stores them in the render pool. */ +/* */ +/* Input: None. The arc is taken from the top of the Bezier stack. */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on Render Pool overflow. */ +/* */ +/****************************************************************************/ + + static Bool Bezier_Up( RAS_ARGS Long miny, Long maxy ) + { + Long y1, y2, e, e2, e0; + Short f1; + + TPoint* arc; + TPoint* start_arc; + + PStorage top; + + + arc = ras.arc; + y1 = arc[2].y; + y2 = arc[0].y; + top = ras.top; + + if ( y2 < miny || y1 > maxy ) + goto Fin; + + e2 = FLOOR( y2 ); + + if ( e2 > maxy ) + e2 = maxy; + + e0 = miny; + + if ( y1 < miny ) + e = miny; + else + { + e = CEILING( y1 ); + f1 = FRAC( y1 ); + e0 = e; + + if ( f1 == 0 ) + { + if ( ras.joint ) + { + top--; + ras.joint = FALSE; + } + + *top++ = arc[2].x; + + DEBUG_PSET; + + e += ras.precision; + } + } + + if ( ras.fresh ) + { + ras.cProfile->start = TRUNC( e0 ); + ras.fresh = FALSE; + } + + if ( e2 < e ) + goto Fin; + + if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) + { + ras.top = top; + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + start_arc = arc; + + while ( arc >= start_arc && e <= e2 ) + { + ras.joint = FALSE; + + y2 = arc[0].y; + + if ( y2 > e ) + { + y1 = arc[2].y; + if ( y2 - y1 >= ras.precision_step ) + { + Split_Bezier( arc ); + arc += 2; + } + else + { + *top++ = arc[2].x + FMulDiv( arc[0].x - arc[2].x, + e - y1, + y2 - y1 ); + DEBUG_PSET; + + arc -= 2; + e += ras.precision; + } + } + else + { + if ( y2 == e ) + { + ras.joint = TRUE; + *top++ = arc[0].x; + + DEBUG_PSET; + + e += ras.precision; + } + arc -= 2; + } + } + + Fin: + ras.top = top; + ras.arc -= 2; + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Bezier_Down */ +/* */ +/* Description: Computes the x-coordinates of a descending bezier arc */ +/* and stores them in the render pool. */ +/* */ +/* Input: None. Arc is taken from the top of the Bezier stack. */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on Render Pool overflow. */ +/* */ +/****************************************************************************/ + + static Bool Bezier_Down( RAS_ARGS Long miny, Long maxy ) + { + TPoint* arc = ras.arc; + Bool result, fresh; + + + arc[0].y = -arc[0].y; + arc[1].y = -arc[1].y; + arc[2].y = -arc[2].y; + + fresh = ras.fresh; + + result = Bezier_Up( RAS_VARS -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + arc[0].y = -arc[0].y; + return result; + } + + +/****************************************************************************/ +/* */ +/* Function: Line_To */ +/* */ +/* Description: Injects a new line segment and adjusts Profiles list. */ +/* */ +/* Input: x, y : segment endpoint (start point in LastX,LastY) */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on Render Pool overflow or Incorrect Profile. */ +/* */ +/****************************************************************************/ + + static Bool Line_To( RAS_ARGS Long x, Long y ) + { + /* First, detect a change of direction */ + + switch ( ras.state ) + { + case Unknown: + if ( y > ras.lastY ) + { + if ( New_Profile( RAS_VARS Ascending ) ) return FAILURE; + } + else + { + if ( y < ras.lastY ) + if ( New_Profile( RAS_VARS Descending ) ) return FAILURE; + } + break; + + case Ascending: + if ( y < ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Descending ) ) return FAILURE; + } + break; + + case Descending: + if ( y > ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Ascending ) ) return FAILURE; + } + break; + + default: + ; + } + + /* Then compute the lines */ + + switch ( ras.state ) + { + case Ascending: + if ( Line_Up ( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + case Descending: + if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + default: + ; + } + + ras.lastX = x; + ras.lastY = y; + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Bezier_To */ +/* */ +/* Description: Injects a new bezier arc and adjusts the profile list. */ +/* */ +/* Input: x, y : arc endpoint (start point in LastX, LastY) */ +/* Cx, Cy : control point */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on Render Pool overflow or Incorrect Profile. */ +/* */ +/****************************************************************************/ + + static Bool Bezier_To( RAS_ARGS Long x, + Long y, + Long cx, + Long cy ) + { + Long y1, y2, y3, x3; + TStates state_bez; + + + Push_Bezier( RAS_VARS ras.lastX, ras.lastY, cx, cy, x, y ); + + do + { + y1 = ras.arc[2].y; + y2 = ras.arc[1].y; + y3 = ras.arc[0].y; + x3 = ras.arc[0].x; + + /* first, categorize the bezier arc */ + + if ( y1 == y2 ) + { + if ( y2 == y3 ) + state_bez = Flat; + else if ( y2 > y3 ) + state_bez = Descending; + else + state_bez = Ascending; + } + else if ( y1 > y2 ) + { + if ( y2 >= y3 ) + state_bez = Descending; + else + state_bez = Unknown; + } + else if ( y2 <= y3 ) + state_bez = Ascending; + else + state_bez = Unknown; + + /* split non-monotonic arcs, ignore flat ones, or */ + /* computes the up and down ones */ + + switch ( state_bez ) + { + case Flat: + ras.arc -= 2; + break; + + case Unknown: + Split_Bezier( ras.arc ); + ras.arc += 2; + break; + + default: + /* detect a change of direction */ + + if ( ras.state != state_bez ) + { + if ( ras.state != Unknown ) + if ( End_Profile( RAS_VAR ) ) return FAILURE; + + if ( New_Profile( RAS_VARS state_bez ) ) return FAILURE; + } + + /* compute */ + + switch ( ras.state ) + { + case Ascending: + if ( Bezier_Up ( RAS_VARS ras.minY, ras.maxY ) ) + return FAILURE; + break; + + case Descending: + if ( Bezier_Down( RAS_VARS ras.minY, ras.maxY ) ) + return FAILURE; + break; + + default: + ; + } + } + } while ( ras.arc >= ras.arcs ); + + ras.lastX = x3; + ras.lastY = y3; + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Decompose_Curve */ +/* */ +/* Description: Scans the outline arays in order to emit individual */ +/* segments and beziers by calling Line_To() and Bezier_To(). */ +/* It handles all weird cases, like when the first point */ +/* is off the curve, or when there are simply no 'on' */ +/* points in the contour! */ +/* */ +/* Input: first, last : indexes of first and last point in */ +/* contour. */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE on error. */ +/* */ +/****************************************************************************/ + +#undef SWAP_ +#define SWAP_(x,y) { Long swap = x; x = y; y = swap; } + + static Bool Decompose_Curve( RAS_ARGS UShort first, + UShort last, + Bool flipped ) + { + Long x, y; /* current point */ + Long cx, cy; /* current Bezier control point */ + Long mx, my; /* current middle point */ + + Long x_first, y_first; /* first point's coordinates */ + Long x_last, y_last; /* last point's coordinates */ + + UShort index; /* current point's index */ + Bool on_curve; /* current point's state */ + + x_first = SCALED( ras.coords[first].x ); + y_first = SCALED( ras.coords[first].y ); + + if ( flipped ) SWAP_( x_first,y_first ); + + x_last = SCALED( ras.coords[last].x ); + y_last = SCALED( ras.coords[last].y ); + + if ( flipped ) SWAP_( x_last,y_last ); + + ras.lastX = cx = x_first; + ras.lastY = cy = y_first; + + on_curve = (ras.flags[first] & 1); + index = first; + + /* check first point to determine origin */ + if ( !on_curve ) + { + /* first point is off the curve. Yes, this happens... */ + if ( ras.flags[last] & 1 ) + { + ras.lastX = x_last; /* start at last point if it */ + ras.lastY = y_last; /* is on the curve */ + } + else + { + /* if both first and last points are off the curve, */ + /* start at their middle and record its position */ + /* for closure */ + ras.lastX = (ras.lastX + x_last)/2; + ras.lastY = (ras.lastY + y_last)/2; + + x_last = ras.lastX; + y_last = ras.lastY; + } + } + + /* now process each contour point individually */ + while ( index < last ) + { + index++; + x = SCALED( ras.coords[index].x ); + y = SCALED( ras.coords[index].y ); + + if ( flipped ) SWAP_( x, y ); + + if ( on_curve ) + { + /* the previous point was on the curve */ + on_curve = ( ras.flags[index] & 1 ); + if ( on_curve ) + { + /* two successive on points => emit segment */ + if ( Line_To( RAS_VARS x, y ) ) return FAILURE; + } + else + { + /* else, keep current control point for next bezier */ + cx = x; + cy = y; + } + } + else + { + /* the previous point was off the curve */ + on_curve = ( ras.flags[index] & 1 ); + if ( on_curve ) + { + /* reaching an `on' point */ + if ( Bezier_To( RAS_VARS x, y, cx, cy ) ) return FAILURE; + } + else + { + /* two successive `off' points => create middle point */ + mx = ( cx + x ) / 2; + my = ( cy + y ) / 2; + + if ( Bezier_To( RAS_VARS mx, my, cx, cy ) ) return FAILURE; + + cx = x; + cy = y; + } + } + } + + /* end of contour, close curve cleanly */ + if ( ras.flags[first] & 1 ) + { + if ( on_curve ) + return Line_To( RAS_VARS x_first, y_first ); + else + return Bezier_To( RAS_VARS x_first, y_first, cx, cy ); + } + else + if ( !on_curve ) + return Bezier_To( RAS_VARS x_last, y_last, cx, cy ); + + return SUCCESS; + } + + +/****************************************************************************/ +/* */ +/* Function: Convert_Glyph */ +/* */ +/* Description: Converts a glyph into a series of segments and arcs */ +/* and makes a Profiles list with them. */ +/* */ +/* Input: _xCoord, _yCoord : coordinates tables. */ +/* */ +/* Uses the 'Flag' table too. */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE if any error was encountered during rendering. */ +/* */ +/****************************************************************************/ + + static Bool Convert_Glyph( RAS_ARGS int flipped ) + { + Short i; + UShort start; + + PProfile lastProfile; + + + ras.fProfile = NULL; + ras.joint = FALSE; + ras.fresh = FALSE; + + ras.maxBuff = ras.sizeBuff - AlignProfileSize; + + ras.numTurns = 0; + + ras.cProfile = (PProfile)ras.top; + ras.cProfile->offset = ras.top; + ras.num_Profs = 0; + + start = 0; + + for ( i = 0; i < ras.nContours; i++ ) + { + ras.state = Unknown; + ras.gProfile = NULL; + + if ( Decompose_Curve( RAS_VARS start, ras.outs[i], flipped ) ) + return FAILURE; + + start = ras.outs[i] + 1; + + /* We must now see if the extreme arcs join or not */ + if ( ( FRAC( ras.lastY ) == 0 && + ras.lastY >= ras.minY && + ras.lastY <= ras.maxY ) ) + if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow ) + ras.top--; + /* Note that ras.gProfile can be nil if the contour was too small */ + /* to be drawn. */ + + lastProfile = ras.cProfile; + if ( End_Profile( RAS_VAR ) ) return FAILURE; + + /* close the 'next profile in contour' linked list */ + if ( ras.gProfile ) + lastProfile->next = ras.gProfile; + } + + if (Finalize_Profile_Table( RAS_VAR )) + return FAILURE; + + return (ras.top < ras.maxBuff ? SUCCESS : FAILURE ); + } + + +/************************************************/ +/* */ +/* Init_Linked */ +/* */ +/* Inits an empty linked list. */ +/* */ +/************************************************/ + + static void Init_Linked( TProfileList* l ) + { + *l = NULL; + } + + +/************************************************/ +/* */ +/* InsNew : */ +/* */ +/* Inserts a new Profile in a linked list. */ +/* */ +/************************************************/ + + static void InsNew( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + Long x; + + + old = list; + current = *old; + x = profile->X; + + while ( current ) + { + if ( x < current->X ) + break; + old = ¤t->link; + current = *old; + } + + profile->link = current; + *old = profile; + } + + +/*************************************************/ +/* */ +/* DelOld : */ +/* */ +/* Removes an old Profile from a linked list. */ +/* */ +/*************************************************/ + + static void DelOld( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + + + old = list; + current = *old; + + while ( current ) + { + if ( current == profile ) + { + *old = current->link; + return; + } + + old = ¤t->link; + current = *old; + } + + /* we should never get there, unless the Profile was not part of */ + /* the list. */ + } + + +/************************************************/ +/* */ +/* Update : */ +/* */ +/* Update all X offsets of a drawing list */ +/* */ +/************************************************/ + + static void Update( PProfile first ) + { + PProfile current = first; + + + while ( current ) + { + current->X = *current->offset; + current->offset += current->flow; + current->height--; + current = current->link; + } + } + + +/************************************************/ +/* */ +/* Sort : */ +/* */ +/* Sorts a trace list. In 95%, the list */ +/* is already sorted. We need an algorithm */ +/* which is fast in this case. Bubble sort */ +/* is enough and simple. */ +/* */ +/************************************************/ + + static void Sort( PProfileList list ) + { + PProfile *old, current, next; + + + /* First, set the new X coordinate of each profile */ + Update( *list ); + + /* Then sort them */ + old = list; + current = *old; + + if ( !current ) + return; + + next = current->link; + + while ( next ) + { + if ( current->X <= next->X ) + { + old = ¤t->link; + current = *old; + + if ( !current ) + return; + } + else + { + *old = next; + current->link = next->link; + next->link = current; + + old = list; + current = *old; + } + + next = current->link; + } + } + + +/***********************************************************************/ +/* */ +/* Vertical Sweep Procedure Set : */ +/* */ +/* These three routines are used during the vertical black/white */ +/* sweep phase by the generic Draw_Sweep() function. */ +/* */ +/***********************************************************************/ + + static void Vertical_Sweep_Init( RAS_ARGS Short* min, Short* max ) + { + switch ( ras.target.flow ) + { + case TT_Flow_Up: + ras.traceOfs = *min * ras.target.cols; + ras.traceIncr = ras.target.cols; + break; + + default: + ras.traceOfs = ( ras.target.rows - 1 - *min ) * ras.target.cols; + ras.traceIncr = -ras.target.cols; + } + + ras.gray_min_x = 0; + ras.gray_max_x = 0; + } + + + static void Vertical_Sweep_Span( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + Short c1, c2; + Short f1, f2; + Byte* target; + + + /* Drop-out control */ + + e1 = TRUNC( CEILING( x1 ) ); + + if ( x2-x1-ras.precision <= ras.precision_jitter ) + e2 = e1; + else + e2 = TRUNC( FLOOR( x2 ) ); + + if ( e2 >= 0 && e1 < ras.bWidth ) + { + if ( e1 < 0 ) e1 = 0; + if ( e2 >= ras.bWidth ) e2 = ras.bWidth-1; + + c1 = (Short)(e1 >> 3); + c2 = (Short)(e2 >> 3); + + f1 = e1 & 7; + f2 = e2 & 7; + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2; + + target = ras.bTarget + ras.traceOfs + c1; + + if ( c1 != c2 ) + { + *target |= LMask[f1]; + + if ( c2 > c1 + 1 ) + MEM_Set( target + 1, 0xFF, c2 - c1 - 1 ); + + target[c2 - c1] |= RMask[f2]; + } + else + *target |= ( LMask[f1] & RMask[f2] ); + } + } + + + static void Vertical_Sweep_Drop( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + Short c1, f1; + + + /* Drop-out control */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( (x1 + x2 + 1) / 2 ); + break; + + case 2: + case 5: + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of 'stubs'. */ + /* */ + /* Here, we only get rid of stubs recognized when: */ + /* */ + /* upper stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Right is the successor of P_Left in that contour */ + /* - y is the top of P_Left and P_Right */ + /* */ + /* lower stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Left is the successor of P_Right in that contour */ + /* - y is the bottom of P_Left */ + /* */ + + /* FIXXXME : uncommenting this line solves the disappearing */ + /* bit problem in the '7' of verdana 10pts, but */ + /* makes a new one in the 'C' of arial 14pts */ + + /* if ( x2-x1 < ras.precision_half ) */ + { + /* upper stub test */ + + if ( left->next == right && left->height <= 0 ) return; + + /* lower stub test */ + + if ( right->next == left && left->start == y ) return; + } + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + c1 = (Short)(e1 >> 3); + f1 = e1 & 7; + + if ( e1 >= 0 && e1 < ras.bWidth && + ras.bTarget[ras.traceOfs + c1] & (0x80 >> f1) ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( (x1 + x2 + 1) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.bWidth ) + { + c1 = (Short)(e1 >> 3); + f1 = e1 & 7; + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1; + + ras.bTarget[ras.traceOfs + c1] |= (Char)(0x80 >> f1); + } + } + + + static void Vertical_Sweep_Step( RAS_ARG ) + { + ras.traceOfs += ras.traceIncr; + } + + +/***********************************************************************/ +/* */ +/* Horizontal Sweep Procedure Set : */ +/* */ +/* These three routines are used during the horizontal black/white */ +/* sweep phase by the generic Draw_Sweep() function. */ +/* */ +/***********************************************************************/ + + static void Horizontal_Sweep_Init( RAS_ARGS Short* min, Short* max ) + { + /* nothing, really */ + } + + + static void Horizontal_Sweep_Span( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + + if ( x2-x1 < ras.precision ) + { + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 == e2 ) + { + bits = ras.bTarget + (y >> 3); + f1 = (Byte)(0x80 >> (y & 7)); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + if ( ras.target.flow == TT_Flow_Down ) + bits[(ras.target.rows-1 - e1) * ras.target.cols] |= f1; + else + bits[e1 * ras.target.cols] |= f1; + } + } + } +#if 0 + e2 = TRUNC( e2 ); + + if ( e2 >= 0 && e2 < ras.target.rows ) + if ( ras.target.flow == TT_Flow_Down ) + bits[(ras.target.rows-1-e2) * ras.target.cols] |= f1; + else + bits[e2 * ras.target.cols] |= f1; +#endif + } + + + static void Horizontal_Sweep_Drop( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + + /* During the horizontal sweep, we only take care of drop-outs */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( (x1 + x2 + 1) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of 'stubs'. */ + /* */ + + /* rightmost stub test */ + + if ( left->next == right && left->height <= 0 ) return; + + /* leftmost stub test */ + + if ( right->next == left && left->start == y ) return; + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + bits = ras.bTarget + (y >> 3); + f1 = (Byte)(0x80 >> (y & 7)); + + if ( ras.target.flow == TT_Flow_Down ) + bits += (ras.target.rows-1-e1) * ras.target.cols; + else + bits += e1 * ras.target.cols; + + if ( e1 >= 0 && + e1 < ras.target.rows && + *bits & f1 ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( (x1 + x2 + 1) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + bits = ras.bTarget + (y >> 3); + f1 = (Byte)(0x80 >> (y & 7)); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + if (ras.target.flow==TT_Flow_Down) + bits[(ras.target.rows-1-e1) * ras.target.cols] |= f1; + else + bits[e1 * ras.target.cols] |= f1; + } + } + + + static void Horizontal_Sweep_Step( RAS_ARG ) + { + /* Nothing, really */ + } + + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + +/***********************************************************************/ +/* */ +/* Vertical Gray Sweep Procedure Set: */ +/* */ +/* These two routines are used during the vertical gray-levels */ +/* sweep phase by the generic Draw_Sweep() function. */ +/* */ +/* */ +/* NOTES: */ +/* */ +/* - The target pixmap's width *must* be a multiple of 4. */ +/* */ +/* - you have to use the function Vertical_Sweep_Span() for */ +/* the gray span call. */ +/* */ +/***********************************************************************/ + + static void Vertical_Gray_Sweep_Init( RAS_ARGS Short* min, Short* max ) + { + *min = *min & -2; + *max = ( *max + 3 ) & -2; + + ras.traceOfs = 0; + + switch ( ras.target.flow ) + { + case TT_Flow_Up: + ras.traceG = (*min / 2) * ras.target.cols; + ras.traceIncr = ras.target.cols; + break; + + default: + ras.traceG = (ras.target.rows-1 - *min/2) * ras.target.cols; + ras.traceIncr = -ras.target.cols; + } + + ras.gray_min_x = ras.target.cols; + ras.gray_max_x = -ras.target.cols; + } + + + static void Vertical_Gray_Sweep_Step( RAS_ARG ) + { + Int c1, c2; + PByte pix, bit, bit2; + Int* count = ras.count_table; + Byte* grays; + + + ras.traceOfs += ras.gray_width; + + if ( ras.traceOfs > ras.gray_width ) + { + pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4; + grays = ras.grays; + + if ( ras.gray_max_x >= 0 ) + { + if ( ras.gray_max_x >= ras.target.width ) + ras.gray_max_x = ras.target.width-1; + + if ( ras.gray_min_x < 0 ) + ras.gray_min_x = 0; + + bit = ras.bTarget + ras.gray_min_x; + bit2 = bit + ras.gray_width; + + c1 = ras.gray_max_x - ras.gray_min_x; + + while ( c1 >= 0 ) + { + c2 = count[*bit] + count[*bit2]; + + if ( c2 ) + { + pix[0] = grays[(c2 & 0xF000) >> 12]; + pix[1] = grays[(c2 & 0x0F00) >> 8]; + pix[2] = grays[(c2 & 0x00F0) >> 4]; + pix[3] = grays[(c2 & 0x000F) ]; + + *bit = 0; + *bit2 = 0; + } + + bit ++; + bit2++; + pix += 4; + c1 --; + } + } + + ras.traceOfs = 0; + ras.traceG += ras.traceIncr; + + ras.gray_min_x = ras.target.cols; + ras.gray_max_x = -ras.target.cols; + } + } + + + static void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + /* nothing, really */ + } + + static void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y, + TT_F26Dot6 x1, + TT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte pixel; + Byte color; + + + /* During the horizontal sweep, we only take care of drop-outs */ + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( (x1 + x2 + 1) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of 'stubs'. */ + /* */ + + /* rightmost stub test */ + if ( left->next == right && left->height <= 0 ) return; + + /* leftmost stub test */ + if ( right->next == left && left->start == y ) return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( (x1 + x2 + 1) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + if ( e1 >= 0 ) + { + if ( x2 - x1 >= ras.precision_half ) + color = ras.grays[2]; + else + color = ras.grays[1]; + + e1 = TRUNC( e1 ) / 2; + if ( e1 < ras.target.rows ) + { + if ( ras.target.flow == TT_Flow_Down ) + pixel = ras.gTarget + + (ras.target.rows - 1 - e1) * ras.target.cols + y / 2; + else + pixel = ras.gTarget + + e1 * ras.target.cols + y / 2; + + if (pixel[0] == ras.grays[0]) + pixel[0] = color; + } + } + } + +#endif /* TT_CONFIG_OPTION_GRAY_SCALING */ + + +/********************************************************************/ +/* */ +/* Generic Sweep Drawing routine */ +/* */ +/********************************************************************/ + + static Bool Draw_Sweep( RAS_ARG ) + { + Short y, y_change, y_height; + + PProfile P, Q, P_Left, P_Right; + + Short min_Y, max_Y, top, bottom, dropouts; + + Long x1, x2, xs, e1, e2; + + TProfileList wait; + TProfileList draw_left, draw_right; + + + /* Init empty linked lists */ + + Init_Linked( &wait ); + + Init_Linked( &draw_left ); + Init_Linked( &draw_right ); + + /* first, compute min and max Y */ + + P = ras.fProfile; + max_Y = (short)TRUNC( ras.minY ); + min_Y = (short)TRUNC( ras.maxY ); + + while ( P ) + { + Q = P->link; + + bottom = P->start; + top = P->start + P->height-1; + + if ( min_Y > bottom ) min_Y = bottom; + if ( max_Y < top ) max_Y = top; + + P->X = 0; + InsNew( &wait, P ); + + P = Q; + } + + /* Check the Y-turns */ + if ( ras.numTurns == 0 ) + { + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + /* Now inits the sweep */ + + ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y ); + + /* Then compute the distance of each profile from min_Y */ + + P = wait; + + while ( P ) + { + P->countL = P->start - min_Y; + P = P->link; + } + + /* Let's go */ + + y = min_Y; + y_height = 0; + + if ( ras.numTurns > 0 && + ras.sizeBuff[-ras.numTurns] == min_Y ) + ras.numTurns--; + + while ( ras.numTurns > 0 ) + { + /* look in the wait list for new activations */ + + P = wait; + + while ( P ) + { + Q = P->link; + P->countL -= y_height; + if ( P->countL == 0 ) + { + DelOld( &wait, P ); + + switch ( P->flow ) + { + case TT_Flow_Up: InsNew( &draw_left, P ); break; + case TT_Flow_Down: InsNew( &draw_right, P ); break; + } + } + + P = Q; + } + + /* Sort the drawing lists */ + + Sort( &draw_left ); + Sort( &draw_right ); + + y_change = (Short)ras.sizeBuff[-ras.numTurns--]; + y_height = y_change - y; + + while ( y < y_change ) + { + + /* Let's trace */ + + dropouts = 0; + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + x1 = P_Left ->X; + x2 = P_Right->X; + + if ( x1 > x2 ) + { + xs = x1; + x1 = x2; + x2 = xs; + } + + if ( x2-x1 <= ras.precision ) + { + e1 = FLOOR( x1 ); + e2 = CEILING( x2 ); + + if ( ras.dropOutControl != 0 && + (e1 > e2 || e2 == e1 + ras.precision) ) + { + /* a drop out was detected */ + + P_Left ->X = x1; + P_Right->X = x2; + + /* mark profile for drop-out processing */ + P_Left->countL = 1; + dropouts++; + + goto Skip_To_Next; + } + } + + ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right ); + + Skip_To_Next: + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + /* now perform the dropouts _after_ the span drawing */ + /* drop-outs processing has been moved out of the loop */ + /* for performance tuning */ + if (dropouts > 0) + goto Scan_DropOuts; + + Next_Line: + + ras.Proc_Sweep_Step( RAS_VAR ); + + y++; + + if ( y < y_change ) + { + Sort( &draw_left ); + Sort( &draw_right ); + } + + } + + /* Now finalize the profiles that needs it */ + + { + PProfile Q, P; + P = draw_left; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_left, P ); + P = Q; + } + } + + { + PProfile Q, P = draw_right; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_right, P ); + P = Q; + } + } + } + + /* for gray-scaling, flushes the bitmap scanline cache */ + while ( y <= max_Y ) + { + ras.Proc_Sweep_Step( RAS_VAR ); + y++; + } + + return SUCCESS; + +Scan_DropOuts : + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + if ( P_Left->countL ) + { + P_Left->countL = 0; + /* dropouts--; -- this is useful when debugging only */ + ras.Proc_Sweep_Drop( RAS_VARS y, + P_Left->X, + P_Right->X, + P_Left, + P_Right ); + } + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + goto Next_Line; + } + + +/****************************************************************************/ +/* */ +/* Function: Render_Single_Pass */ +/* */ +/* Description: Performs one sweep with sub-banding. */ +/* */ +/* Input: _XCoord, _YCoord : x and y coordinates arrays */ +/* */ +/* Returns: SUCCESS on success */ +/* FAILURE if any error was encountered during render. */ +/* */ +/****************************************************************************/ + + static TT_Error Render_Single_Pass( RAS_ARGS Bool flipped ) + { + Short i, j, k; + + + while ( ras.band_top >= 0 ) + { + ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision; + ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision; + + ras.top = ras.buff; + + ras.error = Raster_Err_None; + + if ( Convert_Glyph( RAS_VARS flipped ) ) + { + if ( ras.error != Raster_Err_Overflow ) return FAILURE; + + ras.error = Raster_Err_None; + + /* sub-banding */ + +#ifdef DEBUG_RASTER + ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) ); +#endif + + i = ras.band_stack[ras.band_top].y_min; + j = ras.band_stack[ras.band_top].y_max; + + k = ( i + j ) / 2; + + if ( ras.band_top >= 7 || k < i ) + { + ras.band_top = 0; + ras.error = Raster_Err_Invalid; + return ras.error; + } + + ras.band_stack[ras.band_top+1].y_min = k; + ras.band_stack[ras.band_top+1].y_max = j; + + ras.band_stack[ras.band_top].y_max = k - 1; + + ras.band_top++; + } + else + { + if ( ras.fProfile ) + if ( Draw_Sweep( RAS_VAR ) ) return ras.error; + ras.band_top--; + } + } + + return TT_Err_Ok; + } + + +/****************************************************************************/ +/* */ +/* Function: Render_Glyph */ +/* */ +/* Description: Renders a glyph in a bitmap. Sub-banding if needed. */ +/* */ +/* Input: AGlyph Glyph record */ +/* */ +/* Returns: SUCCESS on success. */ +/* FAILURE if any error was encountered during rendering. */ +/* */ +/****************************************************************************/ + + LOCAL_FUNC + TT_Error Render_Glyph( RAS_ARGS TT_Outline* glyph, + TT_Raster_Map* target_map ) + { + TT_Error error; + + + if ( glyph->n_points == 0 || glyph->n_contours <= 0 ) + return TT_Err_Ok; + + if ( !ras.buff ) + { + ras.error = Raster_Err_Not_Ini; + return ras.error; + } + + if ( glyph->n_points < glyph->contours[glyph->n_contours - 1] ) + { + ras.error = TT_Err_Too_Many_Points; + return ras.error; + } + + if ( target_map ) + ras.target = *target_map; + + ras.outs = glyph->contours; + ras.flags = glyph->flags; + ras.nPoints = glyph->n_points; + ras.nContours = glyph->n_contours; + ras.coords = glyph->points; + + Set_High_Precision( RAS_VARS glyph->high_precision ); + ras.scale_shift = ras.precision_shift; + ras.dropOutControl = glyph->dropout_mode; + ras.second_pass = glyph->second_pass; + + + /* Vertical Sweep */ + ras.Proc_Sweep_Init = Vertical_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.rows - 1; + + ras.bWidth = ras.target.width; + ras.bTarget = (Byte*)ras.target.bitmap; + + if ( (error = Render_Single_Pass( RAS_VARS 0 )) != 0 ) + return error; + + /* Horizontal Sweep */ + + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width - 1; + + if ( (error = Render_Single_Pass( RAS_VARS 1 )) != 0 ) + return error; + } + + return TT_Err_Ok; + } + + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + +/****************************************************************************/ +/* */ +/* Function: Render_Gray_Glyph */ +/* */ +/* Description: Renders a glyph with grayscaling. Sub-banding if needed. */ +/* */ +/* Input: AGlyph Glyph record */ +/* */ +/* Returns: SUCCESS on success */ +/* FAILURE if any error was encountered during rendering. */ +/* */ +/****************************************************************************/ + + LOCAL_FUNC + TT_Error Render_Gray_Glyph( RAS_ARGS TT_Outline* glyph, + TT_Raster_Map* target_map, + Byte* palette ) + { + Int i; + TT_Error error; + + if ( !ras.buff ) + { + ras.error = Raster_Err_Not_Ini; + return ras.error; + } + + if ( glyph->n_points == 0 || glyph->n_contours <= 0 ) + return TT_Err_Ok; + + if ( glyph->n_points < glyph->contours[glyph->n_contours - 1] ) + { + ras.error = TT_Err_Too_Many_Points; + return ras.error; + } + + if ( palette ) + { + for ( i = 0; i < 5; i++ ) + ras.grays[i] = palette[i]; + } + + if ( target_map ) + ras.target = *target_map; + + ras.outs = glyph->contours; + ras.flags = glyph->flags; + ras.nPoints = glyph->n_points; + ras.nContours = glyph->n_contours; + ras.coords = glyph->points; + + Set_High_Precision( RAS_VARS glyph->high_precision ); + ras.scale_shift = ras.precision_shift+1; + ras.dropOutControl = glyph->dropout_mode; + ras.second_pass = glyph->second_pass; + + + /* Vertical Sweep */ + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = 2 * ras.target.rows - 1; + + ras.bWidth = ras.gray_width; + if ( ras.bWidth > ras.target.cols/4 ) + ras.bWidth = ras.target.cols/4; + + ras.bWidth = ras.bWidth * 8; + ras.bTarget = (Byte*)ras.gray_lines; + ras.gTarget = (Byte*)ras.target.bitmap; + + ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step; + + error = Render_Single_Pass( RAS_VARS 0 ); + if (error) + return error; + + /* Horizontal Sweep */ + + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width * 2 - 1; + + error = Render_Single_Pass( RAS_VARS 1 ); + if (error) + return error; + } + + return TT_Err_Ok; + } + +#endif /* TT_CONFIG_OPTION_GRAY_SCALING */ + + +/************************************************/ +/* */ +/* InitRasterizer */ +/* */ +/* Raster Initialization. */ +/* Gets the bitmap description and render pool */ +/* addresses. */ +/* */ +/************************************************/ + +#undef ras + + LOCAL_FUNC + TT_Error TTRaster_Done( PEngine_Instance engine ) + { + TRaster_Instance* ras = (TRaster_Instance*)engine->raster_component; + + + if ( !ras ) + return TT_Err_Ok; + + FREE( ras->buff ); + FREE( ras->gray_lines ); + +#ifndef TT_CONFIG_OPTION_STATIC_RASTER + FREE( engine->raster_component ); +#endif + + return TT_Err_Ok; + } + + + LOCAL_FUNC + TT_Error TTRaster_Init( PEngine_Instance engine ) + { + TT_Error error; + + Int i, l, j, c; + + TRaster_Instance* ras; + + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + ras = engine->raster_component = &cur_ras; +#else + if ( ALLOC( engine->raster_component, sizeof ( TRaster_Instance ) ) ) + return error; + + ras = (TRaster_Instance*)engine->raster_component; +#endif + + if ( ALLOC( ras->buff, RASTER_RENDER_POOL ) || + ALLOC( ras->gray_lines, RASTER_GRAY_LINES ) ) + return error; + + ras->sizeBuff = ras->buff + ( RASTER_RENDER_POOL/sizeof(long) ); + ras->gray_width = RASTER_GRAY_LINES/2; + + MUTEX_Create( engine->raster_lock ); + + /* Initialization of Count_Table */ + + for ( i = 0; i < 256; i++ ) + { + l = 0; + j = i; + + for ( c = 0; c < 4; c++ ) + { + l <<= 4; + + if ( j & 0x80 ) l++; + if ( j & 0x40 ) l++; + + j = ( j << 2 ) & 0xFF; + } + + ras->count_table[i] = l; + } + + ras->dropOutControl = 2; + ras->error = Raster_Err_None; + + return TT_Err_Ok; + } + + +/* END */ diff --git a/Build/source/libs/libttf/ttraster.h b/Build/source/libs/libttf/ttraster.h new file mode 100644 index 00000000000..66c8fef6e73 --- /dev/null +++ b/Build/source/libs/libttf/ttraster.h @@ -0,0 +1,127 @@ +/******************************************************************* + * + * ttraster.h v 1.4 + * + * The FreeType glyph rasterizer. + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTES: + * + * This version supports the following: + * + * - direct grayscaling + * - sub-banding + * - drop-out modes 4 and 5 + * - second pass for complete drop-out control (bitmap only) + * - variable precision + * + * + * Changes between 1.4 and 1.3: + * + * Mainly performance tunings: + * + * - Line_Down() and Bezier_Down() now use the functions Line_Up() + * and Bezier_Up() to do their work. + * - optimized Split_Bezier() + * - optimized linked lists used during sweeps + * + * Changes between 1.2 and 1.3: + * + * - made the engine optionaly re-entrant. Saves a lot + * of code for a moderate performance hit. + * + ******************************************************************/ + +#ifndef TTRASTER_H +#define TTRASTER_H + +#include "ttconfig.h" +#include "freetype.h" /* for TT_Outline */ +#include "ttengine.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* We provide two different builds of the scan-line converter */ + /* The static build uses global variables and isn't */ + /* re-entrant. */ + /* The indirect build is re-entrant but accesses all variables */ + /* indirectly. */ + /* */ + /* As a consequence, the indirect build is about 10% slower */ + /* than the static one on a _Pentium_ (this could get worse */ + /* on older processors), but the code size is reduced by */ + /* more than 30% ! */ + /* */ + /* The indirect build is now the default, defined in */ + /* ttconfig.h. Be careful if you experiment with this. */ + + /* Note also that, though its code can be re-entrant, the */ + /* component is always used in thread-safe mode. This is */ + /* simply due to the fact that we want to use a single */ + /* render pool (of 64 Kb), and not to waste memory. */ + +#ifdef TT_STATIC_RASTER + +#define RAS_ARGS /* void */ +#define RAS_ARG /* void */ + +#define RAS_VARS /* void */ +#define RAS_VAR /* void */ + +#else + +#define RAS_ARGS TRaster_Instance* raster, +#define RAS_ARG TRaster_Instance* raster + +#define RAS_VARS raster, +#define RAS_VAR raster + +#endif + + + struct TRaster_Instance_; + typedef struct TRaster_Instance_ TRaster_Instance; + + /* Render one glyph in the target bitmap, using drop-out control */ + /* mode 'scan'. */ + LOCAL_DEF + TT_Error Render_Glyph( RAS_ARGS TT_Outline* glyph, + TT_Raster_Map* target ); + +#ifdef TT_CONFIG_OPTION_GRAY_SCALING + /* Render one gray-level glyph in the target pixmap. */ + /* Palette points to an array of 5 colors used for the rendering. */ + /* Use NULL to reuse the last palette. Default is VGA graylevels. */ + LOCAL_DEF + TT_Error Render_Gray_Glyph( RAS_ARGS TT_Outline* glyph, + TT_Raster_Map* target, + Byte* palette ); +#endif + + /* Initialize rasterizer */ + LOCAL_DEF + TT_Error TTRaster_Init( PEngine_Instance engine ); + + /* Finalize it */ + LOCAL_DEF + TT_Error TTRaster_Done( PEngine_Instance engine ); + + +#ifdef __cplusplus +} +#endif + +#endif /* TTRASTER_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/tttables.h b/Build/source/libs/libttf/tttables.h new file mode 100644 index 00000000000..e3556fc18a2 --- /dev/null +++ b/Build/source/libs/libttf/tttables.h @@ -0,0 +1,215 @@ +/******************************************************************* + * + * tttables.h 1.1 + * + * TrueType Tables structures and handling (specification). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef TTTABLES_H +#define TTTABLES_H + +#include "ttconfig.h" +#include "tttypes.h" + +#ifdef __cplusplus + extern "C" { +#endif + + /***********************************************************************/ + /* */ + /* TrueType Table Types */ + /* */ + /***********************************************************************/ + + /* TrueType Collection Header */ + + struct TTTCHeader_ + { + ULong Tag; + TT_Fixed version; + ULong DirCount; + PULong TableDirectory; + }; + + typedef struct TTTCHeader_ TTTCHeader; + typedef TTTCHeader* PTTCHeader; + + + /* TrueType Table Directory type */ + + struct TTableDir_ + { + TT_Fixed version; /* should be 0x10000 */ + UShort numTables; /* number of tables */ + + UShort searchRange; /* These parameters are only used */ + UShort entrySelector; /* for a dichotomy search in the */ + UShort rangeShift; /* directory. We ignore them. */ + }; + + typedef struct TTableDir_ TTableDir; + typedef TTableDir* PTableDir; + + + /* The 'TableDir' is followed by 'numTables' TableDirEntries */ + + struct TTableDirEntry_ + { + ULong Tag; /* table type */ + ULong CheckSum; /* table checksum */ + ULong Offset; /* table file offset */ + ULong Length; /* table length */ + }; + + typedef struct TTableDirEntry_ TTableDirEntry; + typedef TTableDirEntry* PTableDirEntry; + + + /* 'cmap' tables */ + + struct TCMapDir_ + { + UShort tableVersionNumber; + UShort numCMaps; + }; + + typedef struct TCMapDir_ TCMapDir; + typedef TCMapDir* PCMapDir; + + struct TCMapDirEntry_ + { + UShort platformID; + UShort platformEncodingID; + Long offset; + }; + + typedef struct TCMapDirEntry_ TCMapDirEntry; + typedef TCMapDirEntry* PCMapDirEntries; + + + /* 'maxp' Maximum Profiles table */ + + struct TMaxProfile_ + { + TT_Fixed version; + UShort numGlyphs, + maxPoints, + maxContours, + maxCompositePoints, + maxCompositeContours, + maxZones, + maxTwilightPoints, + maxStorage, + maxFunctionDefs, + maxInstructionDefs, + maxStackElements, + maxSizeOfInstructions, + maxComponentElements, + maxComponentDepth; + }; + + typedef struct TMaxProfile_ TMaxProfile; + typedef TMaxProfile* PMaxProfile; + + + /* table "gasp" */ + +#define GASP_GRIDFIT 0x01 +#define GASP_DOGRAY 0x02 + + struct GaspRange_ + { + UShort maxPPEM; + UShort gaspFlag; + }; + + typedef struct GaspRange_ GaspRange; + + + struct TGasp_ + { + UShort version; + UShort numRanges; + GaspRange* gaspRanges; + }; + + typedef struct TGasp_ TGasp; + + + /* table "head" - now defined in freetype.h */ + /* table "hhea" - now defined in freetype.h */ + + + /* tables "HMTX" and "VMTX" */ + + struct TLongMetrics_ + { + UShort advance; + Short bearing; + }; + + typedef struct TLongMetrics_ TLongMetrics, *PLongMetrics; + + typedef Short TShortMetrics, *PShortMetrics; + + /* 'loca' location table type */ + + struct TLoca_ + { + UShort Size; + PStorage Table; + }; + + typedef struct TLoca_ TLoca; + + + /* table "name" */ + + struct TNameRec_ + { + UShort platformID; + UShort encodingID; + UShort languageID; + UShort nameID; + UShort stringLength; + UShort stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + PByte string; + }; + + typedef struct TNameRec_ TNameRec; + + + struct TName_Table_ + { + UShort format; + UShort numNameRecords; + UShort storageOffset; + TNameRec* names; + PByte storage; + }; + + typedef struct TName_Table_ TName_Table; + + +#ifdef __cplusplus + } +#endif + +#endif /* TTTABLES_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/tttags.h b/Build/source/libs/libttf/tttags.h new file mode 100644 index 00000000000..95347d1db43 --- /dev/null +++ b/Build/source/libs/libttf/tttags.h @@ -0,0 +1,61 @@ +/******************************************************************* + * + * tttags.h + * + * tags for TrueType tables (specification only). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + ******************************************************************/ + +#ifndef TTAGS_H +#define TTAGS_H + +#include "ttconfig.h" +#include "freetype.h" /* for MAKE_TT_TAG() */ + +#define TTAG_BASE MAKE_TT_TAG( 'B', 'A', 'S', 'E' ) +#define TTAG_bloc MAKE_TT_TAG( 'b', 'l', 'o', 'c' ) +#define TTAG_bdat MAKE_TT_TAG( 'b', 'd', 'a', 't' ) +#define TTAG_cmap MAKE_TT_TAG( 'c', 'm', 'a', 'p' ) +#define TTAG_cvt MAKE_TT_TAG( 'c', 'v', 't', ' ' ) +#define TTAG_EBDT MAKE_TT_TAG( 'E', 'B', 'D', 'T' ) +#define TTAG_EBLC MAKE_TT_TAG( 'E', 'B', 'L', 'C' ) +#define TTAG_EBSC MAKE_TT_TAG( 'E', 'B', 'S', 'C' ) +#define TTAG_fpgm MAKE_TT_TAG( 'f', 'p', 'g', 'm' ) +#define TTAG_gasp MAKE_TT_TAG( 'g', 'a', 's', 'p' ) +#define TTAG_glyf MAKE_TT_TAG( 'g', 'l', 'y', 'f' ) +#define TTAG_GDEF MAKE_TT_TAG( 'G', 'D', 'E', 'F' ) +#define TTAG_GPOS MAKE_TT_TAG( 'G', 'P', 'O', 'S' ) +#define TTAG_GSUB MAKE_TT_TAG( 'G', 'S', 'U', 'B' ) +#define TTAG_hdmx MAKE_TT_TAG( 'h', 'd', 'm', 'x' ) +#define TTAG_head MAKE_TT_TAG( 'h', 'e', 'a', 'd' ) +#define TTAG_hhea MAKE_TT_TAG( 'h', 'h', 'e', 'a' ) +#define TTAG_hmtx MAKE_TT_TAG( 'h', 'm', 't', 'x' ) +#define TTAG_JSTF MAKE_TT_TAG( 'J', 'S', 'T', 'F' ) +#define TTAG_kern MAKE_TT_TAG( 'k', 'e', 'r', 'n' ) +#define TTAG_loca MAKE_TT_TAG( 'l', 'o', 'c', 'a' ) +#define TTAG_LTSH MAKE_TT_TAG( 'L', 'T', 'S', 'H' ) +#define TTAG_maxp MAKE_TT_TAG( 'm', 'a', 'x', 'p' ) +#define TTAG_name MAKE_TT_TAG( 'n', 'a', 'm', 'e' ) +#define TTAG_OS2 MAKE_TT_TAG( 'O', 'S', '/', '2' ) +#define TTAG_PCLT MAKE_TT_TAG( 'P', 'C', 'L', 'T' ) +#define TTAG_post MAKE_TT_TAG( 'p', 'o', 's', 't' ) +#define TTAG_prep MAKE_TT_TAG( 'p', 'r', 'e', 'p' ) +#define TTAG_ttc MAKE_TT_TAG( 't', 't', 'c', ' ' ) +#define TTAG_ttcf MAKE_TT_TAG( 't', 't', 'c', 'f' ) +#define TTAG_VDMX MAKE_TT_TAG( 'V', 'D', 'M', 'X' ) +#define TTAG_vhea MAKE_TT_TAG( 'v', 'h', 'e', 'a' ) +#define TTAG_vmtx MAKE_TT_TAG( 'v', 'm', 't', 'x' ) + +#endif /* TTAGS_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/tttypes.h b/Build/source/libs/libttf/tttypes.h new file mode 100644 index 00000000000..b324013e874 --- /dev/null +++ b/Build/source/libs/libttf/tttypes.h @@ -0,0 +1,150 @@ +/******************************************************************* + * + * tttypes.h + * + * Freetype engine's common types specification + * (this spec has no associated body). + * + * Copyright 1996-1999 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used + * modified and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + * NOTE: + * + * All these declarations are library internals, and *not* part + * of the high-level interface. See also 'freetype.h'. + * + ******************************************************************/ + +#ifndef TTTYPES_H +#define TTTYPES_H + +#include "ttconfig.h" +#include "freetype.h" + +#ifdef __MACTYPES__ +#error "<MacTypes.h> have been included, and this prevents the proper\ + compilation of this library. Please remove the precompiled headers." +#endif + + typedef char String; + typedef signed char Char; + typedef unsigned char Byte; + + typedef unsigned short UShort; + typedef signed short Short; + + typedef unsigned long ULong; + typedef signed long Long; + + typedef TT_Int32 Fixed; + + typedef int Int; + + /* Simple access types: pointers and tables */ + + typedef Byte* PByte; + typedef UShort* PUShort; + typedef Short* PShort; + typedef ULong* PULong; + typedef Long* PLong; + + typedef Fixed* PFixed; + + typedef Int* PInt; + + typedef void* Pointer; + + typedef TT_F26Dot6* PCoordinates; + typedef unsigned char* PTouchTable; + + +#ifndef Bool + typedef int Bool; /* No boolean type in C */ +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + + typedef Long Storage; + typedef Storage* PStorage; + + +/* Rounding mode constants */ + +#define TT_Round_Off 5 +#define TT_Round_To_Half_Grid 0 +#define TT_Round_To_Grid 1 +#define TT_Round_To_Double_Grid 2 +#define TT_Round_Up_To_Grid 4 +#define TT_Round_Down_To_Grid 3 +#define TT_Round_Super 6 +#define TT_Round_Super_45 7 + + +/* Touch flag masks */ + +#define TT_Flag_On_Curve 1 +#define TT_Flag_Touched_X 2 +#define TT_Flag_Touched_Y 4 +#define TT_Flag_Touched_Both 6 + + +/* Error management constants :) */ + +#define SUCCESS 0 +#define FAILURE -1 + + +/* The min and max functions missing in C. As usual, be careful not to */ +/* write things like MIN( a++, b++ ) to avoid side effects. */ + +#ifndef MIN +#define MIN( a, b ) ( (a) < (b) ? (a) : (b) ) +#endif + +#ifndef MAX +#define MAX( a, b ) ( (a) > (b) ? (a) : (b) ) +#endif + +#ifndef ABS +#define ABS( a ) ( (a) < 0 ? -(a) : (a) ) +#endif + +/* conversion macros for the handles defined in freetype.h */ + +#define HANDLE_Val( handle ) ((handle).z) + +#define HANDLE_Engine( handle ) ((PEngine_Instance)HANDLE_Val( handle )) + +#define HANDLE_Face( handle ) ((PFace)HANDLE_Val( handle )) + +#define HANDLE_Instance( handle ) ((PInstance)HANDLE_Val( handle )) + +/* HANDLE_Stream( handle ) must be defined in ttfile.c */ + +#define HANDLE_Glyph( handle ) ((PGlyph)HANDLE_Val( handle )) + +#define HANDLE_CharMap( handle ) ((PCMapTable)HANDLE_Val( handle )) + +#define HANDLE_Set( handle, val ) ((handle).z = (void*)(val)) + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/Build/source/libs/libttf/win32.mak b/Build/source/libs/libttf/win32.mak new file mode 100644 index 00000000000..1eb8daa6e26 --- /dev/null +++ b/Build/source/libs/libttf/win32.mak @@ -0,0 +1,111 @@ +################################################################################ +# +# Makefile : libttf, MSVC +# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr> +# Time-stamp: <02/09/23 17:40:42 popineau> +# +################################################################################ +root_srcdir = ..\.. +INCLUDE=$(INCLUDE);$(root_srcdir)\texk + +# Makefile for freetype library +# The library already compiles under win32. +# This Makefile for accomodating the needs of fpTeX. +# (maybe building a .dll later) + +USE_GNUW32 = 1 +USE_TTF = 1 +MAKE_TTF = 1 + +!include <msvc/common.mak> + +programs = $(ttfdll) +libfiles = $(ttflib) +includefiles = freetype.h fterrid.h ftnameid.h +objects = \ +$(objdir)\ttapi.obj \ +$(objdir)\ttcache.obj \ +$(objdir)\ttcalc.obj \ +$(objdir)\ttcmap.obj \ +$(objdir)\ttdebug.obj \ +$(objdir)\ttextend.obj \ +$(objdir)\ttfile.obj \ +$(objdir)\ttgload.obj \ +$(objdir)\ttinterp.obj \ +$(objdir)\ttload.obj \ +$(objdir)\ttmemory.obj \ +$(objdir)\ttmutex.obj \ +$(objdir)\ttobjs.obj \ +$(objdir)\ttraster.obj \ +$(objdir)\ftxkern.obj \ +$(objdir)\ftxpost.obj \ +$(objdir)\ftxerr18.obj \ +$(objdir)\ftxcmap.obj \ +$(objdir)\ftxwidth.obj \ +$(objdir)\ftxgsub.obj \ +$(objdir)\ftxgdef.obj \ +$(objdir)\ftxgpos.obj \ +$(objdir)\ftxopen.obj \ +$(objdir)\ftxgasp.obj + + +default: all + +all: $(objdir) $(ttf) + +lib: $(objdir) $(ttflib) + +!ifdef TTF_DLL +DEFS = -DMAKE_TTF_DLL $(DEFS) + +$(ttflib): $(objdir) $(objects) + $(archive) /DEF $(objects) + +$(ttfdll): $(objects) $(objdir)\libttf.res $(gnuw32lib) + $(link_dll) $(**) $(ttflib:.lib=.exp) $(conlibs) +!else +$(ttflib): $(objdir) $(objects) + $(archive) $(objects) +!endif + +ft_conf.h: arch\win32\ft_conf.h + copy $** $@ + +$(objdir)\ftxkern.obj: extend\ftxkern.c + $(compile) $** +$(objdir)\ftxwidth.obj: extend\ftxwidth.c + $(compile) $** +$(objdir)\ftxpost.obj: extend\ftxpost.c + $(compile) $** +$(objdir)\ftxerr18.obj: extend\ftxerr18.c + $(compile) $** +$(objdir)\ftxcmap.obj: extend\ftxcmap.c + $(compile) $** +$(objdir)\freetype.obj: arch\win32\freetype.c + $(compile) $** +$(objdir)\ftxgasp.obj: extend\ftxgasp.c + $(compile) $** +$(objdir)\ftxgsub.obj: extend\ftxgsub.c + $(compile) $** +$(objdir)\ftxgpos.obj: extend\ftxgpos.c + $(compile) $** +$(objdir)\ftxgdef.obj: extend\ftxgdef.c + $(compile) $** +$(objdir)\ftxopen.obj: extend\ftxopen.c + $(compile) $** + +!include <msvc/config.mak> +!include <msvc/install.mak> + +install:: install-exec install-include install-lib + +!include <msvc/clean.mak> + +!include <msvc/rdepend.mak> +!include "./depend.mak" + +# +# Local Variables: +# mode: makefile +# End: + |