[DO NOT MERGE] Update FreeType to 2.6.2+update from 2.4.12
am: 42a6868914
* commit '42a68689140022fd8c067ff75fc5d573fe8f02d0':
[DO NOT MERGE] Update FreeType to 2.6.2+update from 2.4.12
Change-Id: Id7957d2368e2e14df391316eeb447f8f30e882a3
diff --git a/Android.mk b/Android.mk
index e357397..138ac69 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,10 +1,10 @@
# this is now the default FreeType build for Android
#
ifndef USE_FREETYPE
-USE_FREETYPE := 2.4.2
+USE_FREETYPE := 2.6.2
endif
-ifeq ($(USE_FREETYPE),2.4.2)
+ifeq ($(USE_FREETYPE),2.6.2)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -14,32 +14,33 @@
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES:= \
- src/base/ftbbox.c \
- src/base/ftbitmap.c \
- src/base/ftfstype.c \
- src/base/ftglyph.c \
- src/base/ftlcdfil.c \
- src/base/ftstroke.c \
- src/base/fttype1.c \
- src/base/ftxf86.c \
- src/base/ftbase.c \
- src/base/ftsystem.c \
- src/base/ftinit.c \
- src/base/ftgasp.c \
- src/raster/raster.c \
- src/sfnt/sfnt.c \
- src/smooth/smooth.c \
- src/autofit/autofit.c \
- src/truetype/truetype.c \
- src/cff/cff.c \
- src/psnames/psnames.c \
- src/pshinter/pshinter.c
+ src/base/ftbbox.c \
+ src/base/ftbitmap.c \
+ src/base/ftfntfmt.c \
+ src/base/ftfstype.c \
+ src/base/ftglyph.c \
+ src/base/ftlcdfil.c \
+ src/base/ftstroke.c \
+ src/base/fttype1.c \
+ src/base/ftbase.c \
+ src/base/ftsystem.c \
+ src/base/ftinit.c \
+ src/base/ftgasp.c \
+ src/base/ftmm.c \
+ src/gzip/ftgzip.c \
+ src/raster/raster.c \
+ src/sfnt/sfnt.c \
+ src/smooth/smooth.c \
+ src/autofit/autofit.c \
+ src/truetype/truetype.c \
+ src/cff/cff.c \
+ src/psnames/psnames.c \
+ src/pshinter/pshinter.c
LOCAL_C_INCLUDES += \
- $(LOCAL_PATH)/builds \
- $(LOCAL_PATH)/include \
- external/libpng \
- external/zlib
+ $(LOCAL_PATH)/include \
+ external/libpng \
+ external/zlib
LOCAL_CFLAGS += -W -Wall
LOCAL_CFLAGS += -fPIC -DPIC
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b6..b9cafef 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -47,3 +47,5 @@
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libft2_*)
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..c3139d5
--- /dev/null
+++ b/README.android
@@ -0,0 +1,16 @@
+Name: FreeType
+Version: 2.6.2 + update
+Revision: a512b0fe7a8d9db0e5aa9c0a4db1e92cb861722d
+
+Local modifications:
+
+1. Drop unused build files (Jamfiles, {module,rules}.mk)
+2. Drop src directories for unused modules:
+ bdf, cid, pcf, pfr, type1, type42, winfonts
+3. Drop src/{bzip2,tools,lzw,otvalid,gxvalid}
+4. Customize include/freetype/config/{ftmodule,ftoption}.h by applying
+ module_option.diff
+
+To faciliate an easier update, all the files in src/{base,autofit} are kept
+even if some of them are for dropped modules/options. Android.mk can be used
+to control exactly what's built.
diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h
index 5dce30e..d4d7993 100644
--- a/include/freetype/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
/* */
/* ANSI-specific configuration file (specification only). */
/* */
-/* Copyright 1996-2004, 2006-2008, 2010-2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,11 +27,11 @@
/* Note however that if some specific modifications are needed, we */
/* advise you to place a modified copy in your build directory. */
/* */
- /* The build directory is usually `freetype/builds/<system>', and */
- /* contains system-specific files that are always included first when */
- /* building the library. */
+ /* The build directory is usually `builds/<system>', and contains */
+ /* system-specific files that are always included first when building */
+ /* the library. */
/* */
- /* This ANSI version should stay in `include/freetype/config'. */
+ /* This ANSI version should stay in `include/config/'. */
/* */
/*************************************************************************/
@@ -53,7 +53,7 @@
/* These macros can be toggled to suit a specific system. The current */
/* ones are defaults used to compile FreeType in an ANSI C environment */
/* (16bit compilers are also supported). Copy this file to your own */
- /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+ /* `builds/<system>' directory, and edit it to port the engine. */
/* */
/*************************************************************************/
@@ -266,7 +266,16 @@
#define FT_INT64 long
#define FT_UINT64 unsigned long
-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+ /*************************************************************************/
+ /* */
+ /* A 64-bit data type may create compilation problems if you compile */
+ /* in strict ANSI mode. To avoid them, we disable other 64-bit data */
+ /* types if __STDC__ is defined. You can however ignore this rule */
+ /* by defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
+ /* */
+#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
+
+#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
/* this compiler provides the __int64 type */
#define FT_LONG64
@@ -300,178 +309,35 @@
#define FT_INT64 long long int
#define FT_UINT64 unsigned long long int
+#endif /* _MSC_VER */
+
#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
-
- /*************************************************************************/
- /* */
- /* A 64-bit data type will create compilation problems if you compile */
- /* in strict ANSI mode. To avoid them, we disable its use if __STDC__ */
- /* is defined. You can however ignore this rule by defining the */
- /* FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */
- /* */
-#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
-
-#ifdef __STDC__
-
- /* undefine the 64-bit macros in strict ANSI compilation mode */
-#undef FT_LONG64
-#undef FT_INT64
-
-#endif /* __STDC__ */
-
-#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
-
#ifdef FT_LONG64
typedef FT_INT64 FT_Int64;
typedef FT_UINT64 FT_UInt64;
#endif
+ /*************************************************************************/
+ /* */
+ /* miscellaneous */
+ /* */
+ /*************************************************************************/
+
+
#define FT_BEGIN_STMNT do {
#define FT_END_STMNT } while ( 0 )
#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
-#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
- /* Provide assembler fragments for performance-critical functions. */
- /* These must be defined `static __inline__' with GCC. */
-
-#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
-
- /* documentation is in freetype.h */
-
- static __inline FT_Int32
- FT_MulFix_arm( FT_Int32 a,
- FT_Int32 b )
- {
- register FT_Int32 t, t2;
-
-
- __asm
- {
- smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
- mov a, t, asr #31 /* a = (hi >> 31) */
- add a, a, #0x8000 /* a += 0x8000 */
- adds t2, t2, a /* t2 += a */
- adc t, t, #0 /* t += carry */
- mov a, t2, lsr #16 /* a = t2 >> 16 */
- orr a, a, t, lsl #16 /* a |= t << 16 */
- }
- return a;
- }
-
-#endif /* __CC_ARM || __ARMCC__ */
-
-
-#ifdef __GNUC__
-
-#if defined( __arm__ ) && !defined( __thumb__ ) && \
- !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
-#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
-
- /* documentation is in freetype.h */
-
- static __inline__ FT_Int32
- FT_MulFix_arm( FT_Int32 a,
- FT_Int32 b )
- {
- register FT_Int32 t, t2;
-
-
- __asm__ __volatile__ (
- "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
- "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
- "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
- "adds %1, %1, %0\n\t" /* %1 += %0 */
- "adc %2, %2, #0\n\t" /* %2 += carry */
- "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
- "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
- : "=r"(a), "=&r"(t2), "=&r"(t)
- : "r"(a), "r"(b)
- : "cc" );
- return a;
- }
-
-#endif /* __arm__ && !__thumb__ && !( __CC_ARM || __ARMCC__ ) */
-
-#if defined( __i386__ )
-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
-
- /* documentation is in freetype.h */
-
- static __inline__ FT_Int32
- FT_MulFix_i386( FT_Int32 a,
- FT_Int32 b )
- {
- register FT_Int32 result;
-
-
- __asm__ __volatile__ (
- "imul %%edx\n"
- "movl %%edx, %%ecx\n"
- "sarl $31, %%ecx\n"
- "addl $0x8000, %%ecx\n"
- "addl %%ecx, %%eax\n"
- "adcl $0, %%edx\n"
- "shrl $16, %%eax\n"
- "shll $16, %%edx\n"
- "addl %%edx, %%eax\n"
- : "=a"(result), "=d"(b)
- : "a"(a), "d"(b)
- : "%ecx", "cc" );
- return result;
- }
-
-#endif /* i386 */
-
-#endif /* __GNUC__ */
-
-
-#ifdef _MSC_VER /* Visual C++ */
-
-#ifdef _M_IX86
-
-#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
-
- /* documentation is in freetype.h */
-
- static __inline FT_Int32
- FT_MulFix_i386( FT_Int32 a,
- FT_Int32 b )
- {
- register FT_Int32 result;
-
- __asm
- {
- mov eax, a
- mov edx, b
- imul edx
- mov ecx, edx
- sar ecx, 31
- add ecx, 8000h
- add eax, ecx
- adc edx, 0
- shr eax, 16
- shl edx, 16
- add eax, edx
- mov result, eax
- }
- return result;
- }
-
-#endif /* _M_IX86 */
-
-#endif /* _MSC_VER */
-
-#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
-
-
-#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
-#ifdef FT_MULFIX_ASSEMBLER
-#define FT_MULFIX_INLINED FT_MULFIX_ASSEMBLER
-#endif
+ /* typeof condition taken from gnulib's `intprops.h' header file */
+#if ( __GNUC__ >= 2 || \
+ defined( __IBM__TYPEOF__ ) || \
+ ( __SUNPRO_C >= 0x5110 && !__STDC__ ) )
+#define FT_TYPEOF( type ) (__typeof__ (type))
+#else
+#define FT_TYPEOF( type ) /* empty */
#endif
@@ -492,6 +358,9 @@
#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
+#define FT_LOCAL_ARRAY( x ) extern const x
+#define FT_LOCAL_ARRAY_DEF( x ) const x
+
#ifndef FT_BASE
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index 8371a31..55f833d 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
/* */
/* Build macros of the FreeType 2 library. */
/* */
-/* Copyright 1996-2008, 2010, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -710,14 +710,16 @@
/*************************************************************************
*
* @macro:
- * FT_XFREE86_H
+ * FT_FONT_FORMATS_H
*
* @description:
* A macro used in #include statements to name the file containing the
- * FreeType~2 API which provides functions specific to the XFree86 and
- * X.Org X11 servers.
+ * FreeType~2 API which provides functions specific to font formats.
*/
-#define FT_XFREE86_H <freetype/ftxf86.h>
+#define FT_FONT_FORMATS_H <freetype/ftfntfmt.h>
+
+ /* deprecated */
+#define FT_XFREE86_H FT_FONT_FORMATS_H
/*************************************************************************
@@ -817,7 +819,7 @@
/*
- * Include internal headers definitions from <freetype/internal/...>
+ * Include internal headers definitions from <internal/...>
* only when building the library.
*/
#ifdef FT2_BUILD_LIBRARY
diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h
index 8a91d17..e145790 100644
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -21,16 +21,4 @@
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class )
-/*
- * New modules in 2.4.7:
-FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
-FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
-FT_USE_MODULE( FT_Module_Class, psaux_module_class )
-FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
- */
-
/* EOF */
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index bc239bf..3819586 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
/* */
/* User-selectable configuration macros (specification only). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -61,7 +61,7 @@
/* that are statically linked to the library at compile time. By */
/* default, this file is <freetype/config/ftmodule.h>. */
/* */
- /* We highly recommend using the third method whenever possible. */
+ /* We highly recommend using the third method whenever possible. */
/* */
/*************************************************************************/
@@ -216,7 +216,7 @@
/*************************************************************************/
/* */
- /* PNG bitmap support. */
+ /* PNG bitmap support. */
/* */
/* FreeType now handles loading color bitmap glyphs in the PNG format. */
/* This requires help from the external libpng library. Uncompressed */
@@ -230,6 +230,19 @@
/*************************************************************************/
/* */
+ /* HarfBuzz support. */
+ /* */
+ /* FreeType uses the HarfBuzz library to improve auto-hinting of */
+ /* OpenType fonts. If available, many glyphs not directly addressable */
+ /* by a font's character map will be hinted also. */
+ /* */
+ /* Define this macro if you want to enable this `feature'. */
+ /* */
+/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+ /*************************************************************************/
+ /* */
/* DLL export compilation */
/* */
/* When compiling FreeType as a DLL, some systems/compilers need a */
@@ -365,10 +378,6 @@
/* The size in bytes of the render pool used by the scan-line converter */
/* to do all of its work. */
/* */
- /* This must be greater than 4KByte if you use FreeType to rasterize */
- /* glyphs; otherwise, you may set it to zero to avoid unnecessary */
- /* allocation of the render pool. */
- /* */
#define FT_RENDER_POOL_SIZE 16384L
@@ -422,6 +431,8 @@
/* af_glyph_hints_dump_points */
/* af_glyph_hints_dump_segments */
/* af_glyph_hints_dump_edges */
+ /* af_glyph_hints_get_num_segments */
+ /* af_glyph_hints_get_segment_offset */
/* */
/* As an argument, they use another global variable: */
/* */
@@ -528,7 +539,7 @@
/* does not contain any glyph name though. */
/* */
/* Accessing SFNT names is done through the functions declared in */
- /* `freetype/ftsnames.h'. */
+ /* `ftsnames.h'. */
/* */
#define TT_CONFIG_OPTION_SFNT_NAMES
@@ -569,7 +580,7 @@
/* Do not #undef this macro here, since the build system might */
/* define it for certain configurations only. */
/* */
-/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
/*************************************************************************/
@@ -641,20 +652,7 @@
/* ... */
/* } */
/* */
-#define TT_CONFIG_OPTION_UNPATENTED_HINTING
-
-
- /*************************************************************************/
- /* */
- /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */
- /* bytecode interpreter with a huge switch statement, rather than a call */
- /* table. This results in smaller and faster code for a number of */
- /* architectures. */
- /* */
- /* Note however that on some compiler/processor combinations, undefining */
- /* this macro will generate faster, though larger, code. */
- /* */
-#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+/* #define TT_CONFIG_OPTION_UNPATENTED_HINTING */
/*************************************************************************/
@@ -671,7 +669,7 @@
/* fonts will not have them. */
/* */
/* http://www.microsoft.com/typography/otspec/glyf.htm */
- /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
+ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */
/* */
#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -695,6 +693,24 @@
/*************************************************************************/
+ /* */
+ /* Option TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES controls the maximum */
+ /* number of bytecode instructions executed for a single run of the */
+ /* bytecode interpreter, needed to prevent infinite loops. You don't */
+ /* want to change this except for very special situations (e.g., making */
+ /* a library fuzzer spend less time to handle broken fonts). */
+ /* */
+ /* It is not expected that this value is ever modified by a configuring */
+ /* script; instead, it gets surrounded with #ifndef ... #endif so that */
+ /* the value can be set as a preprocessor option on the compiler's */
+ /* command line. */
+ /* */
+#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES
+#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L
+#endif
+
+
+ /*************************************************************************/
/*************************************************************************/
/**** ****/
/**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/
@@ -760,6 +776,30 @@
/*************************************************************************/
/* */
+ /* Using CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4} it is */
+ /* possible to set up the default values of the four control points that */
+ /* define the stem darkening behaviour of the (new) CFF engine. For */
+ /* more details please read the documentation of the */
+ /* `darkening-parameters' property of the cff driver module (file */
+ /* `ftcffdrv.h'), which allows the control at run-time. */
+ /* */
+ /* Do *not* undefine these macros! */
+ /* */
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 1000
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 1667
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 2333
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0
+
+
+ /*************************************************************************/
+ /* */
/* CFF_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe CFF */
/* engine gets compiled into FreeType. If defined, it is possible to */
/* switch between the two engines using the `hinting-engine' property of */
@@ -798,8 +838,10 @@
/* grid. To find out the optimal scaling and shifting value, various */
/* parameter combinations are tried and scored. */
/* */
- /* This experimental option is only active if the render mode is */
- /* FT_RENDER_MODE_LIGHT. */
+ /* This experimental option is active only if the rendering mode is */
+ /* FT_RENDER_MODE_LIGHT; you can switch warping on and off with the */
+ /* `warping' property of the auto-hinter (see file `ftautoh.h' for more */
+ /* information; by default it is switched off). */
/* */
/* #define AF_CONFIG_OPTION_USE_WARPER */
@@ -807,8 +849,8 @@
/*
- * This macro is obsolete. Support has been removed in FreeType
- * version 2.5.
+ * This macro is obsolete. Support has been removed in FreeType
+ * version 2.5.
*/
/* #define FT_CONFIG_OPTION_OLD_INTERNALS */
@@ -824,6 +866,35 @@
#define TT_USE_BYTECODE_INTERPRETER
#endif
+
+ /*
+ * Check CFF darkening parameters. The checks are the same as in function
+ * `cff_property_set' in file `cffdrivr.c'.
+ */
+#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500
+#error "Invalid CFF darkening parameters!"
+#endif
+
FT_END_HEADER
diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index b940efc..4b471d4 100644
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
/* ANSI-specific library and header configuration file (specification */
/* only). */
/* */
-/* Copyright 2002-2007, 2009, 2011-2012 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -64,6 +64,7 @@
#define FT_INT_MAX INT_MAX
#define FT_INT_MIN INT_MIN
#define FT_UINT_MAX UINT_MAX
+#define FT_LONG_MAX LONG_MAX
#define FT_ULONG_MAX ULONG_MAX
@@ -141,8 +142,7 @@
/**********************************************************************/
-#define ft_atol atol
-#define ft_labs labs
+#define ft_atol atol
/**********************************************************************/
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 0d5680b..f68718d 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,7 +4,7 @@
/* */
/* FreeType high-level API and common types (specification only). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -42,6 +42,38 @@
/*************************************************************************/
/* */
/* <Section> */
+ /* header_inclusion */
+ /* */
+ /* <Title> */
+ /* FreeType's header inclusion scheme */
+ /* */
+ /* <Abstract> */
+ /* How client applications should include FreeType header files. */
+ /* */
+ /* <Description> */
+ /* To be as flexible as possible (and for historical reasons), */
+ /* FreeType uses a very special inclusion scheme to load header */
+ /* files, for example */
+ /* */
+ /* { */
+ /* #include <ft2build.h> */
+ /* */
+ /* #include FT_FREETYPE_H */
+ /* #include FT_OUTLINE_H */
+ /* } */
+ /* */
+ /* A compiler and its preprocessor only needs an include path to find */
+ /* the file `ft2build.h'; the exact locations and names of the other */
+ /* FreeType header files are hidden by preprocessor macro names, */
+ /* loaded by `ft2build.h'. The API documentation always gives the */
+ /* header macro name needed for a particular function. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
/* user_allocation */
/* */
/* <Title> */
@@ -81,7 +113,8 @@
/* The FreeType~2 base font interface. */
/* */
/* <Description> */
- /* This section describes the public high-level API of FreeType~2. */
+ /* This section describes the most important public high-level API */
+ /* functions of FreeType~2. */
/* */
/* <Order> */
/* FT_Library */
@@ -90,6 +123,7 @@
/* FT_GlyphSlot */
/* FT_CharMap */
/* FT_Encoding */
+ /* FT_ENC_TAG */
/* */
/* FT_FaceRec */
/* */
@@ -98,13 +132,30 @@
/* FT_FACE_FLAG_FIXED_WIDTH */
/* FT_FACE_FLAG_HORIZONTAL */
/* FT_FACE_FLAG_VERTICAL */
+ /* FT_FACE_FLAG_COLOR */
/* FT_FACE_FLAG_SFNT */
+ /* FT_FACE_FLAG_CID_KEYED */
+ /* FT_FACE_FLAG_TRICKY */
/* FT_FACE_FLAG_KERNING */
/* FT_FACE_FLAG_MULTIPLE_MASTERS */
/* FT_FACE_FLAG_GLYPH_NAMES */
/* FT_FACE_FLAG_EXTERNAL_STREAM */
- /* FT_FACE_FLAG_FAST_GLYPHS */
/* FT_FACE_FLAG_HINTER */
+ /* FT_FACE_FLAG_TRICKY */
+ /* */
+ /* FT_HAS_HORIZONTAL */
+ /* FT_HAS_VERTICAL */
+ /* FT_HAS_KERNING */
+ /* FT_HAS_FIXED_SIZES */
+ /* FT_HAS_GLYPH_NAMES */
+ /* FT_HAS_MULTIPLE_MASTERS */
+ /* FT_HAS_COLOR */
+ /* */
+ /* FT_IS_SFNT */
+ /* FT_IS_SCALABLE */
+ /* FT_IS_FIXED_WIDTH */
+ /* FT_IS_CID_KEYED */
+ /* FT_IS_TRICKY */
/* */
/* FT_STYLE_FLAG_BOLD */
/* FT_STYLE_FLAG_ITALIC */
@@ -123,6 +174,7 @@
/* */
/* FT_New_Face */
/* FT_Done_Face */
+ /* FT_Reference_Face */
/* FT_New_Memory_Face */
/* FT_Open_Face */
/* FT_Open_Args */
@@ -135,10 +187,13 @@
/* FT_Request_Size */
/* FT_Select_Size */
/* FT_Size_Request_Type */
+ /* FT_Size_RequestRec */
/* FT_Size_Request */
/* FT_Set_Transform */
/* FT_Load_Glyph */
/* FT_Get_Char_Index */
+ /* FT_Get_First_Char */
+ /* FT_Get_Next_Char */
/* FT_Get_Name_Index */
/* FT_Load_Char */
/* */
@@ -155,11 +210,11 @@
/* FT_LOAD_NO_SCALE */
/* FT_LOAD_NO_HINTING */
/* FT_LOAD_NO_BITMAP */
- /* FT_LOAD_CROP_BITMAP */
+ /* FT_LOAD_NO_AUTOHINT */
+ /* FT_LOAD_COLOR */
/* */
/* FT_LOAD_VERTICAL_LAYOUT */
/* FT_LOAD_IGNORE_TRANSFORM */
- /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
/* FT_LOAD_FORCE_AUTOHINT */
/* FT_LOAD_NO_RECURSE */
/* FT_LOAD_PEDANTIC */
@@ -170,6 +225,8 @@
/* FT_LOAD_TARGET_LCD */
/* FT_LOAD_TARGET_LCD_V */
/* */
+ /* FT_LOAD_TARGET_MODE */
+ /* */
/* FT_Render_Glyph */
/* FT_Render_Mode */
/* FT_Get_Kerning */
@@ -183,14 +240,22 @@
/* FT_Set_Charmap */
/* FT_Get_Charmap_Index */
/* */
- /* FT_FSTYPE_INSTALLABLE_EMBEDDING */
- /* FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING */
- /* FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING */
- /* FT_FSTYPE_EDITABLE_EMBEDDING */
- /* FT_FSTYPE_NO_SUBSETTING */
- /* FT_FSTYPE_BITMAP_EMBEDDING_ONLY */
- /* */
/* FT_Get_FSType_Flags */
+ /* FT_Get_SubGlyph_Info */
+ /* */
+ /* FT_Face_Internal */
+ /* FT_Size_Internal */
+ /* FT_Slot_Internal */
+ /* */
+ /* FT_FACE_FLAG_XXX */
+ /* FT_STYLE_FLAG_XXX */
+ /* FT_OPEN_XXX */
+ /* FT_LOAD_XXX */
+ /* FT_LOAD_TARGET_XXX */
+ /* FT_SUBGLYPH_FLAG_XXX */
+ /* FT_FSTYPE_XXX */
+ /* */
+ /* FT_HAS_FAST_GLYPHS */
/* */
/*************************************************************************/
@@ -329,18 +394,30 @@
/* It also embeds a memory manager (see @FT_Memory), as well as a */
/* scan-line converter object (see @FT_Raster). */
/* */
- /* For multi-threading applications each thread should have its own */
- /* FT_Library object. */
+ /* In multi-threaded applications it is easiest to use one */
+ /* `FT_Library' object per thread. In case this is too cumbersome, */
+ /* a single `FT_Library' object across threads is possible also */
+ /* (since FreeType version 2.5.6), as long as a mutex lock is used */
+ /* around @FT_New_Face and @FT_Done_Face. */
/* */
/* <Note> */
/* Library objects are normally created by @FT_Init_FreeType, and */
- /* destroyed with @FT_Done_FreeType. */
+ /* destroyed with @FT_Done_FreeType. If you need reference-counting */
+ /* (cf. @FT_Reference_Library), use @FT_New_Library and */
+ /* @FT_Done_Library. */
/* */
typedef struct FT_LibraryRec_ *FT_Library;
/*************************************************************************/
/* */
+ /* <Section> */
+ /* module_management */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
/* <Type> */
/* FT_Module */
/* */
@@ -380,6 +457,13 @@
/*************************************************************************/
/* */
+ /* <Section> */
+ /* base_interface */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
/* <Type> */
/* FT_Face */
/* */
@@ -396,6 +480,14 @@
/* */
/* Use @FT_Done_Face to destroy it (along with its slot and sizes). */
/* */
+ /* An `FT_Face' object can only be safely used from one thread at a */
+ /* time. Similarly, creation and destruction of `FT_Face' with the */
+ /* same @FT_Library object can only be done from one thread at a */
+ /* time. On the other hand, functions like @FT_Load_Glyph and its */
+ /* siblings are thread-safe and do not need the lock to be held as */
+ /* long as the same `FT_Face' object is not used from multiple */
+ /* threads at the same time. */
+ /* */
/* <Also> */
/* See @FT_FaceRec for the publicly accessible fields of a given face */
/* object. */
@@ -415,7 +507,8 @@
/* <Note> */
/* Each @FT_Face has an _active_ @FT_Size object that is used by */
/* functions like @FT_Load_Glyph to determine the scaling */
- /* transformation which is used to load and hint glyphs and metrics. */
+ /* transformation that in turn is used to load and hint glyphs and */
+ /* metrics. */
/* */
/* You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, */
/* @FT_Request_Size or even @FT_Select_Size to change the content */
@@ -549,12 +642,17 @@
/* */
/* FT_ENCODING_MS_SYMBOL :: */
/* Corresponds to the Microsoft Symbol encoding, used to encode */
- /* mathematical symbols in the 32..255 character code range. For */
- /* more information, see `http://www.ceviz.net/symbol.htm'. */
+ /* mathematical symbols and wingdings. For more information, see */
+ /* `http://www.microsoft.com/typography/otspec/recom.htm', */
+ /* `http://www.kostis.net/charsets/symbol.htm', and */
+ /* `http://www.kostis.net/charsets/wingding.htm'. */
+ /* */
+ /* This encoding uses character codes from the PUA (Private Unicode */
+ /* Area) in the range U+F020-U+F0FF. */
/* */
/* FT_ENCODING_SJIS :: */
/* Corresponds to Japanese SJIS encoding. More info at */
- /* at `http://langsupport.japanreference.com/encoding.shtml'. */
+ /* at `http://en.wikipedia.org/wiki/Shift_JIS'. */
/* See note on multi-byte encodings below. */
/* */
/* FT_ENCODING_GB2312 :: */
@@ -568,7 +666,7 @@
/* FT_ENCODING_WANSUNG :: */
/* Corresponds to the Korean encoding system known as Wansung. */
/* For more information see */
- /* `http://www.microsoft.com/typography/unicode/949.txt'. */
+ /* `https://msdn.microsoft.com/en-US/goglobal/cc305154'. */
/* */
/* FT_ENCODING_JOHAB :: */
/* The Korean standard character set (KS~C 5601-1992), which */
@@ -643,10 +741,10 @@
/* FT_ENCODING_APPLE_ROMAN). */
/* */
/* If `platform_id' is @TT_PLATFORM_MACINTOSH, use the function */
- /* @FT_Get_CMap_Language_ID to query the Mac language ID which may */
+ /* @FT_Get_CMap_Language_ID to query the Mac language ID that may */
/* be needed to be able to distinguish Apple encoding variants. See */
/* */
- /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */
+ /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt */
/* */
/* to get an idea how to do that. Basically, if the language ID */
/* is~0, don't use it, otherwise subtract 1 from the language ID. */
@@ -688,15 +786,8 @@
} FT_Encoding;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* ft_encoding_xxx */
- /* */
- /* <Description> */
- /* These constants are deprecated; use the corresponding @FT_Encoding */
- /* values instead. */
- /* */
+ /* these constants are deprecated; use the corresponding `FT_Encoding' */
+ /* values instead */
#define ft_encoding_none FT_ENCODING_NONE
#define ft_encoding_unicode FT_ENCODING_UNICODE
#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL
@@ -785,17 +876,36 @@
/* font formats can have multiple faces in */
/* a font file. */
/* */
- /* face_index :: The index of the face in the font file. It */
- /* is set to~0 if there is only one face in */
+ /* face_index :: This field holds two different values. */
+ /* Bits 0-15 are the index of the face in the */
+ /* font file (starting with value~0). They */
+ /* are set to~0 if there is only one face in */
/* the font file. */
/* */
+ /* Bits 16-30 are relevant to GX variation */
+ /* fonts only, holding the named instance */
+ /* index for the current face index (starting */
+ /* with value~1; value~0 indicates font access */
+ /* without GX variation data). For non-GX */
+ /* fonts, bits 16-30 are ignored. If we have */
+ /* the third named instance of face~4, say, */
+ /* `face_index' is set to 0x00030004. */
+ /* */
+ /* Bit 31 is always zero (this is, */
+ /* `face_index' is always a positive value). */
+ /* */
/* face_flags :: A set of bit flags that give important */
/* information about the face; see */
/* @FT_FACE_FLAG_XXX for the details. */
/* */
- /* style_flags :: A set of bit flags indicating the style of */
- /* the face; see @FT_STYLE_FLAG_XXX for the */
- /* details. */
+ /* style_flags :: The lower 16~bits contain a set of bit */
+ /* flags indicating the style of the face; see */
+ /* @FT_STYLE_FLAG_XXX for the details. Bits */
+ /* 16-30 hold the number of named instances */
+ /* available for the current face if we have a */
+ /* GX variation (sub)font. Bit 31 is always */
+ /* zero (this is, `style_flags' is always a */
+ /* positive value). */
/* */
/* num_glyphs :: The number of glyphs in the face. If the */
/* face is scalable and has sbits (see */
@@ -806,7 +916,7 @@
/* highest CID used in the font. */
/* */
/* family_name :: The face's family name. This is an ASCII */
- /* string, usually in English, which describes */
+ /* string, usually in English, that describes */
/* the typeface's family (like `Times New */
/* Roman', `Bodoni', `Garamond', etc). This */
/* is a least common denominator used to list */
@@ -817,8 +927,13 @@
/* Can be NULL (e.g., in fonts embedded in a */
/* PDF file). */
/* */
+ /* In case the font doesn't provide a specific */
+ /* family name entry, FreeType tries to */
+ /* synthesize one, deriving it from other name */
+ /* entries. */
+ /* */
/* style_name :: The face's style name. This is an ASCII */
- /* string, usually in English, which describes */
+ /* string, usually in English, that describes */
/* the typeface's style (like `Italic', */
/* `Bold', `Condensed', etc). Not all font */
/* formats provide a style name, so this field */
@@ -1052,7 +1167,7 @@
/* exist make FT_Load_Glyph return successfully; in all other cases */
/* you get an `FT_Err_Invalid_Argument' error. */
/* */
- /* Note that CID-keyed fonts which are in an SFNT wrapper don't */
+ /* Note that CID-keyed fonts that are in an SFNT wrapper don't */
/* have this flag set since the glyphs are accessed in the normal */
/* way (using contiguous indices); the `CID-ness' isn't visible to */
/* the application. */
@@ -1060,11 +1175,11 @@
/* FT_FACE_FLAG_TRICKY :: */
/* Set if the font is `tricky', this is, it always needs the */
/* font format's native hinting engine to get a reasonable result. */
- /* A typical example is the Chinese font `mingli.ttf' which uses */
+ /* A typical example is the Chinese font `mingli.ttf' that uses */
/* TrueType bytecode instructions to move and scale all of its */
/* subglyphs. */
/* */
- /* It is not possible to autohint such fonts using */
+ /* It is not possible to auto-hint such fonts using */
/* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */
/* @FT_LOAD_NO_HINTING. You have to set both @FT_LOAD_NO_HINTING */
/* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
@@ -1073,6 +1188,10 @@
/* Currently, there are about a dozen TrueType fonts in the list of */
/* tricky fonts; they are hard-coded in file `ttobjs.c'. */
/* */
+ /* FT_FACE_FLAG_COLOR :: */
+ /* Set if the font has color glyph tables. To access color glyphs */
+ /* use @FT_LOAD_COLOR. */
+ /* */
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
@@ -1087,6 +1206,7 @@
#define FT_FACE_FLAG_HINTER ( 1L << 11 )
#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )
#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
+#define FT_FACE_FLAG_COLOR ( 1L << 14 )
/*************************************************************************
@@ -1271,13 +1391,27 @@
( face->face_flags & FT_FACE_FLAG_TRICKY )
+ /*************************************************************************
+ *
+ * @macro:
+ * FT_HAS_COLOR( face )
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains
+ * tables for color glyphs.
+ *
+ */
+#define FT_HAS_COLOR( face ) \
+ ( face->face_flags & FT_FACE_FLAG_COLOR )
+
+
/*************************************************************************/
/* */
/* <Const> */
/* FT_STYLE_FLAG_XXX */
/* */
/* <Description> */
- /* A list of bit-flags used to indicate the style of a given face. */
+ /* A list of bit flags used to indicate the style of a given face. */
/* These are used in the `style_flags' field of @FT_FaceRec. */
/* */
/* <Values> */
@@ -1392,9 +1526,9 @@
/* <Fields> */
/* face :: Handle to the parent face object. */
/* */
- /* generic :: A typeless pointer, which is unused by the FreeType */
- /* library or any of its drivers. It can be used by */
- /* client applications to link their own data to each size */
+ /* generic :: A typeless pointer, unused by the FreeType library or */
+ /* any of its drivers. It can be used by client */
+ /* applications to link their own data to each size */
/* object. */
/* */
/* metrics :: Metrics for this size object. This field is read-only. */
@@ -1462,10 +1596,10 @@
/* listed through a direct, single-linked list */
/* using its `next' field. */
/* */
- /* generic :: A typeless pointer which is unused by the */
- /* FreeType library or any of its drivers. It */
- /* can be used by client applications to link */
- /* their own data to each glyph slot object. */
+ /* generic :: A typeless pointer unused by the FreeType */
+ /* library or any of its drivers. It can be */
+ /* used by client applications to link their own */
+ /* data to each glyph slot object. */
/* */
/* metrics :: The metrics of the last loaded glyph in the */
/* slot. The returned values depend on the last */
@@ -1492,8 +1626,8 @@
/* */
/* advance :: This shorthand is, depending on */
/* @FT_LOAD_IGNORE_TRANSFORM, the transformed */
- /* advance width for the glyph (in 26.6 */
- /* fractional pixel format). As specified with */
+ /* (hinted) advance width for the glyph, in 26.6 */
+ /* fractional pixel format. As specified with */
/* @FT_LOAD_VERTICAL_LAYOUT, it uses either the */
/* `horiAdvance' or the `vertAdvance' value of */
/* `metrics' field. */
@@ -1512,15 +1646,15 @@
/* change between calls of @FT_Load_Glyph and a */
/* few other functions. */
/* */
- /* bitmap_left :: This is the bitmap's left bearing expressed */
- /* in integer pixels. Of course, this is only */
- /* valid if the format is */
- /* @FT_GLYPH_FORMAT_BITMAP. */
+ /* bitmap_left :: The bitmap's left bearing expressed in */
+ /* integer pixels. Only valid if the format is */
+ /* @FT_GLYPH_FORMAT_BITMAP, this is, if the */
+ /* glyph slot contains a bitmap. */
/* */
- /* bitmap_top :: This is the bitmap's top bearing expressed in */
- /* integer pixels. Remember that this is the */
- /* distance from the baseline to the top-most */
- /* glyph scanline, upwards y~coordinates being */
+ /* bitmap_top :: The bitmap's top bearing expressed in integer */
+ /* pixels. Remember that this is the distance */
+ /* from the baseline to the top-most glyph */
+ /* scanline, upwards y~coordinates being */
/* *positive*. */
/* */
/* outline :: The outline descriptor for the current glyph */
@@ -1534,7 +1668,6 @@
/* This field is only valid for the composite */
/* glyph format that should normally only be */
/* loaded with the @FT_LOAD_NO_RECURSE flag. */
- /* For now this is internal to FreeType. */
/* */
/* subglyphs :: An array of subglyph descriptors for */
/* composite glyphs. There are `num_subglyphs' */
@@ -1555,11 +1688,11 @@
/* needs to know about the image format. */
/* */
/* lsb_delta :: The difference between hinted and unhinted */
- /* left side bearing while autohinting is */
+ /* left side bearing while auto-hinting is */
/* active. Zero otherwise. */
/* */
/* rsb_delta :: The difference between hinted and unhinted */
- /* right side bearing while autohinting is */
+ /* right side bearing while auto-hinting is */
/* active. Zero otherwise. */
/* */
/* <Note> */
@@ -1582,7 +1715,7 @@
/* `slot->format' is also changed to @FT_GLYPH_FORMAT_BITMAP. */
/* */
/* <Note> */
- /* Here a small pseudo code fragment which shows how to use */
+ /* Here is a small pseudo code fragment that shows how to use */
/* `lsb_delta' and `rsb_delta': */
/* */
/* { */
@@ -1675,8 +1808,11 @@
/* use @FT_New_Library instead, followed by a call to */
/* @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module). */
/* */
- /* For multi-threading applications each thread should have its own */
- /* FT_Library object. */
+ /* See the documentation of @FT_Library and @FT_Face for */
+ /* multi-threading issues. */
+ /* */
+ /* If you need reference-counting (cf. @FT_Reference_Library), use */
+ /* @FT_New_Library and @FT_Done_Library. */
/* */
FT_EXPORT( FT_Error )
FT_Init_FreeType( FT_Library *alibrary );
@@ -1707,7 +1843,7 @@
/* FT_OPEN_XXX */
/* */
/* <Description> */
- /* A list of bit-field constants used within the `flags' field of the */
+ /* A list of bit field constants used within the `flags' field of the */
/* @FT_Open_Args structure. */
/* */
/* <Values> */
@@ -1722,16 +1858,6 @@
/* */
/* FT_OPEN_PARAMS :: Use the `num_params' and `params' fields. */
/* */
- /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */
- /* */
- /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */
- /* */
- /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */
- /* */
- /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */
- /* */
- /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */
- /* */
/* <Note> */
/* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */
/* flags are mutually exclusive. */
@@ -1742,11 +1868,14 @@
#define FT_OPEN_DRIVER 0x8
#define FT_OPEN_PARAMS 0x10
-#define ft_open_memory FT_OPEN_MEMORY /* deprecated */
-#define ft_open_stream FT_OPEN_STREAM /* deprecated */
-#define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */
-#define ft_open_driver FT_OPEN_DRIVER /* deprecated */
-#define ft_open_params FT_OPEN_PARAMS /* deprecated */
+
+ /* these constants are deprecated; use the corresponding `FT_OPEN_XXX' */
+ /* values instead */
+#define ft_open_memory FT_OPEN_MEMORY
+#define ft_open_stream FT_OPEN_STREAM
+#define ft_open_pathname FT_OPEN_PATHNAME
+#define ft_open_driver FT_OPEN_DRIVER
+#define ft_open_params FT_OPEN_PARAMS
/*************************************************************************/
@@ -1808,25 +1937,25 @@
/* opening a new face. */
/* */
/* <Note> */
- /* The stream type is determined by the contents of `flags' which */
+ /* The stream type is determined by the contents of `flags' that */
/* are tested in the following order by @FT_Open_Face: */
/* */
- /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */
+ /* If the @FT_OPEN_MEMORY bit is set, assume that this is a */
/* memory file of `memory_size' bytes, located at `memory_address'. */
/* The data are are not copied, and the client is responsible for */
/* releasing and destroying them _after_ the corresponding call to */
/* @FT_Done_Face. */
/* */
- /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */
+ /* Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a */
/* custom input stream `stream' is used. */
/* */
- /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */
+ /* Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this */
/* is a normal file and use `pathname' to open it. */
/* */
- /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face only tries to */
+ /* If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to */
/* open the file with the driver whose handler is in `driver'. */
/* */
- /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */
+ /* If the @FT_OPEN_PARAMS bit is set, the parameters given by */
/* `num_params' and `params' is used. They are ignored otherwise. */
/* */
/* Ideally, both the `pathname' and `params' fields should be tagged */
@@ -1861,17 +1990,20 @@
/* <Input> */
/* pathname :: A path to the font file. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: See @FT_Open_Face for a detailed description of this */
+ /* parameter. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See @FT_Open_Face for more details. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* Use @FT_Done_Face to destroy the created @FT_Face object (along */
+ /* with its slot and sizes). */
+ /* */
FT_EXPORT( FT_Error )
FT_New_Face( FT_Library library,
const char* filepathname,
@@ -1885,7 +2017,7 @@
/* FT_New_Memory_Face */
/* */
/* <Description> */
- /* This function calls @FT_Open_Face to open a font which has been */
+ /* This function calls @FT_Open_Face to open a font that has been */
/* loaded into memory. */
/* */
/* <InOut> */
@@ -1896,13 +2028,12 @@
/* */
/* file_size :: The size of the memory chunk used by the font data. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: See @FT_Open_Face for a detailed description of this */
+ /* parameter. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See @FT_Open_Face for more details. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -1931,35 +2062,55 @@
/* library :: A handle to the library resource. */
/* */
/* <Input> */
- /* args :: A pointer to an `FT_Open_Args' structure which must */
+ /* args :: A pointer to an `FT_Open_Args' structure that must */
/* be filled by the caller. */
/* */
- /* face_index :: The index of the face within the font. The first */
- /* face has index~0. */
+ /* face_index :: This field holds two different values. Bits 0-15 */
+ /* are the index of the face in the font file (starting */
+ /* with value~0). Set it to~0 if there is only one */
+ /* face in the font file. */
+ /* */
+ /* Bits 16-30 are relevant to GX variation fonts only, */
+ /* specifying the named instance index for the current */
+ /* face index (starting with value~1; value~0 makes */
+ /* FreeType ignore named instances). For non-GX fonts, */
+ /* bits 16-30 are ignored. Assuming that you want to */
+ /* access the third named instance in face~4, */
+ /* `face_index' should be set to 0x00030004. If you */
+ /* want to access face~4 without GX variation handling, */
+ /* simply set `face_index' to value~4. */
+ /* */
+ /* FT_Open_Face and its siblings can be used to quickly */
+ /* check whether the font format of a given font */
+ /* resource is supported by FreeType. In general, if */
+ /* the `face_index' argument is negative, the */
+ /* function's return value is~0 if the font format is */
+ /* recognized, or non-zero otherwise. The function */
+ /* allocates a more or less empty face handle in */
+ /* `*aface' (if `aface' isn't NULL); the only two */
+ /* useful fields in this special case are */
+ /* `face->num_faces' and `face->style_flags'. For any */
+ /* negative value of `face_index', `face->num_faces' */
+ /* gives the number of faces within the font file. For */
+ /* the negative value `-(N+1)' (with `N' a 16-bit */
+ /* value), bits 16-30 in `face->style_flags' give the */
+ /* number of named instances in face `N' if we have a */
+ /* GX variation font (or zero otherwise). After */
+ /* examination, the returned @FT_Face structure should */
+ /* be deallocated with a call to @FT_Done_Face. */
/* */
/* <Output> */
/* aface :: A handle to a new face object. If `face_index' is */
/* greater than or equal to zero, it must be non-NULL. */
- /* See note below. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
/* <Note> */
/* Unlike FreeType 1.x, this function automatically creates a glyph */
- /* slot for the face object which can be accessed directly through */
+ /* slot for the face object that can be accessed directly through */
/* `face->glyph'. */
/* */
- /* FT_Open_Face can be used to quickly check whether the font */
- /* format of a given font resource is supported by FreeType. If the */
- /* `face_index' field is negative, the function's return value is~0 */
- /* if the font format is recognized, or non-zero otherwise; */
- /* the function returns a more or less empty face handle in `*aface' */
- /* (if `aface' isn't NULL). The only useful field in this special */
- /* case is `face->num_faces' which gives the number of faces within */
- /* the font file. After examination, the returned @FT_Face structure */
- /* should be deallocated with a call to @FT_Done_Face. */
- /* */
/* Each new face object created with this function also owns a */
/* default @FT_Size object, accessible as `face->size'. */
/* */
@@ -1970,6 +2121,74 @@
/* See the discussion of reference counters in the description of */
/* @FT_Reference_Face. */
/* */
+ /* To loop over all faces, use code similar to the following snippet */
+ /* (omitting the error handling). */
+ /* */
+ /* { */
+ /* ... */
+ /* FT_Face face; */
+ /* FT_Long i, num_faces; */
+ /* */
+ /* */
+ /* error = FT_Open_Face( library, args, -1, &face ); */
+ /* if ( error ) { ... } */
+ /* */
+ /* num_faces = face->num_faces; */
+ /* FT_Done_Face( face ); */
+ /* */
+ /* for ( i = 0; i < num_faces; i++ ) */
+ /* { */
+ /* ... */
+ /* error = FT_Open_Face( library, args, i, &face ); */
+ /* ... */
+ /* FT_Done_Face( face ); */
+ /* ... */
+ /* } */
+ /* } */
+ /* */
+ /* To loop over all valid values for `face_index', use something */
+ /* similar to the following snippet, again without error handling. */
+ /* The code accesses all faces immediately (thus only a single call */
+ /* of `FT_Open_Face' within the do-loop), with and without named */
+ /* instances. */
+ /* */
+ /* { */
+ /* ... */
+ /* FT_Face face; */
+ /* */
+ /* FT_Long num_faces = 0; */
+ /* FT_Long num_instances = 0; */
+ /* */
+ /* FT_Long face_idx = 0; */
+ /* FT_Long instance_idx = 0; */
+ /* */
+ /* */
+ /* do */
+ /* { */
+ /* FT_Long id = ( instance_idx << 16 ) + face_idx; */
+ /* */
+ /* */
+ /* error = FT_Open_Face( library, args, id, &face ); */
+ /* if ( error ) { ... } */
+ /* */
+ /* num_faces = face->num_faces; */
+ /* num_instances = face->style_flags >> 16; */
+ /* */
+ /* ... */
+ /* */
+ /* FT_Done_Face( face ); */
+ /* */
+ /* if ( instance_idx < num_instances ) */
+ /* instance_idx++; */
+ /* else */
+ /* { */
+ /* face_idx++; */
+ /* instance_idx = 0; */
+ /* } */
+ /* */
+ /* } while ( face_idx < num_faces ) */
+ /* } */
+ /* */
FT_EXPORT( FT_Error )
FT_Open_Face( FT_Library library,
const FT_Open_Args* args,
@@ -2014,7 +2233,7 @@
/* face :: The target face object. */
/* */
/* <Input> */
- /* parameters :: A pointer to @FT_Open_Args which must be filled by */
+ /* parameters :: A pointer to @FT_Open_Args that must be filled by */
/* the caller. */
/* */
/* <Return> */
@@ -2045,7 +2264,7 @@
/* then only destroys a face if the counter is~1, otherwise it simply */
/* decrements the counter. */
/* */
- /* This function helps in managing life-cycles of structures which */
+ /* This function helps in managing life-cycles of structures that */
/* reference @FT_Face objects. */
/* */
/* <Input> */
@@ -2240,6 +2459,8 @@
/* glyph relative to this size. For more information refer to */
/* `http://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html' */
/* */
+ /* Don't use this function if you are using the FreeType cache API. */
+ /* */
FT_EXPORT( FT_Error )
FT_Request_Size( FT_Face face,
FT_Size_Request req );
@@ -2314,6 +2535,8 @@
/* constrained, to this pixel size. Refer to @FT_Request_Size to */
/* understand how requested sizes relate to actual sizes. */
/* */
+ /* Don't use this function if you are using the FreeType cache API. */
+ /* */
FT_EXPORT( FT_Error )
FT_Set_Pixel_Sizes( FT_Face face,
FT_UInt pixel_width,
@@ -2352,7 +2575,7 @@
/* the details. */
/* */
/* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument' is */
- /* returned for invalid CID values (this is, for CID values which */
+ /* returned for invalid CID values (this is, for CID values that */
/* don't have a corresponding glyph in the font). See the discussion */
/* of the @FT_FACE_FLAG_CID_KEYED flag for more details. */
/* */
@@ -2403,7 +2626,7 @@
* FT_LOAD_XXX
*
* @description:
- * A list of bit-field constants used with @FT_Load_Glyph to indicate
+ * A list of bit field constants used with @FT_Load_Glyph to indicate
* what kind of operations to perform during glyph loading.
*
* @values:
@@ -2472,11 +2695,6 @@
* Indicates that the auto-hinter is preferred over the font's native
* hinter. See also the note below.
*
- * FT_LOAD_CROP_BITMAP ::
- * Indicates that the font driver should crop the loaded bitmap glyph
- * (i.e., remove all space around its black bits). Not all drivers
- * implement this.
- *
* FT_LOAD_PEDANTIC ::
* Indicates that the font driver should perform pedantic verifications
* during glyph loading. This is mostly used to detect broken glyphs
@@ -2487,18 +2705,12 @@
* result in partially hinted or distorted glyphs in case a glyph's
* bytecode is buggy.
*
- * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
- * Ignored. Deprecated.
- *
* FT_LOAD_NO_RECURSE ::
- * This flag is only used internally. It merely indicates that the
- * font driver should not load composite glyphs recursively. Instead,
- * it should set the `num_subglyph' and `subglyphs' values of the
- * glyph slot accordingly, and set `glyph->format' to
- * @FT_GLYPH_FORMAT_COMPOSITE.
- *
- * The description of sub-glyphs is not available to client
- * applications for now.
+ * Indicate that the font driver should not load composite glyphs
+ * recursively. Instead, it should set the `num_subglyph' and
+ * `subglyphs' values of the glyph slot accordingly, and set
+ * `glyph->format' to @FT_GLYPH_FORMAT_COMPOSITE. The description of
+ * subglyphs can then be accessed with @FT_Get_SubGlyph_Info.
*
* This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
*
@@ -2531,6 +2743,22 @@
* bitmaps transparently. Those bitmaps will be in the
* @FT_PIXEL_MODE_GRAY format.
*
+ * FT_LOAD_COMPUTE_METRICS ::
+ * This flag sets computing glyph metrics without the use of bundled
+ * metrics tables (for example, the `hdmx' table in TrueType fonts).
+ * Well-behaving fonts have optimized bundled metrics and these should
+ * be used. This flag is mainly used by font validating or font
+ * editing applications, which need to ignore, verify, or edit those
+ * tables.
+ *
+ * Currently, this flag is only implemented for TrueType fonts.
+ *
+ * FT_LOAD_CROP_BITMAP ::
+ * Ignored. Deprecated.
+ *
+ * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+ * Ignored. Deprecated.
+ *
* @note:
* By default, hinting is enabled and the font's native hinter (see
* @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can
@@ -2570,6 +2798,7 @@
#define FT_LOAD_NO_AUTOHINT ( 1L << 15 )
/* Bits 16..19 are used by `FT_LOAD_TARGET_' */
#define FT_LOAD_COLOR ( 1L << 20 )
+#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 )
/* */
@@ -2592,9 +2821,6 @@
* have specified (e.g., the TrueType bytecode interpreter). You can set
* @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
*
- * Also note that @FT_LOAD_TARGET_LIGHT is an exception, in that it
- * always implies @FT_LOAD_FORCE_AUTOHINT.
- *
* @values:
* FT_LOAD_TARGET_NORMAL ::
* This corresponds to the default hinting algorithm, optimized for
@@ -2602,11 +2828,14 @@
* @FT_LOAD_TARGET_MONO instead.
*
* FT_LOAD_TARGET_LIGHT ::
- * A lighter hinting algorithm for non-monochrome modes. Many
- * generated glyphs are more fuzzy but better resemble its original
- * shape. A bit like rendering on Mac OS~X.
- *
- * As a special exception, this target implies @FT_LOAD_FORCE_AUTOHINT.
+ * A lighter hinting algorithm for gray-level modes. Many generated
+ * glyphs are fuzzier but better resemble their original shape. This
+ * is achieved by snapping glyphs to the pixel grid only vertically
+ * (Y-axis), as is done by Microsoft's ClearType and Adobe's
+ * proprietary font renderer. This preserves inter-glyph spacing in
+ * horizontal text. The snapping is done either by the native font
+ * driver if the driver itself and the font support it or by the
+ * auto-hinter.
*
* FT_LOAD_TARGET_MONO ::
* Strong hinting algorithm that should only be used for monochrome
@@ -2626,7 +2855,7 @@
* `load_flags'. They can't be ORed.
*
* If @FT_LOAD_RENDER is also set, the glyph is rendered in the
- * corresponding mode (i.e., the mode which matches the used algorithm
+ * corresponding mode (i.e., the mode that matches the used algorithm
* best). An exeption is FT_LOAD_TARGET_MONO since it implies
* @FT_LOAD_MONOCHROME.
*
@@ -2713,7 +2942,10 @@
/* field in the @FT_GlyphSlotRec structure gives the format of the */
/* returned bitmap. */
/* */
- /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity. */
+ /* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity, */
+ /* indicating pixel coverage. Use linear alpha blending and gamma */
+ /* correction to correctly render non-monochrome glyph bitmaps onto a */
+ /* surface; see @FT_Render_Glyph. */
/* */
/* <Values> */
/* FT_RENDER_MODE_NORMAL :: */
@@ -2767,19 +2999,8 @@
} FT_Render_Mode;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* ft_render_mode_xxx */
- /* */
- /* <Description> */
- /* These constants are deprecated. Use the corresponding */
- /* @FT_Render_Mode values instead. */
- /* */
- /* <Values> */
- /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */
- /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */
- /* */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Render_Mode' values instead */
#define ft_render_mode_normal FT_RENDER_MODE_NORMAL
#define ft_render_mode_mono FT_RENDER_MODE_MONO
@@ -2806,6 +3027,87 @@
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* To get meaningful results, font scaling values must be set with */
+ /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */
+ /* */
+ /* When FreeType outputs a bitmap of a glyph, it really outputs an */
+ /* alpha coverage map. If a pixel is completely covered by a */
+ /* filled-in outline, the bitmap contains 0xFF at that pixel, meaning */
+ /* that 0xFF/0xFF fraction of that pixel is covered, meaning the */
+ /* pixel is 100% black (or 0% bright). If a pixel is only 50% */
+ /* covered (value 0x80), the pixel is made 50% black (50% bright or a */
+ /* middle shade of grey). 0% covered means 0% black (100% bright or */
+ /* white). */
+ /* */
+ /* On high-DPI screens like on smartphones and tablets, the pixels */
+ /* are so small that their chance of being completely covered and */
+ /* therefore completely black are fairly good. On the low-DPI */
+ /* screens, however, the situation is different. The pixels are too */
+ /* large for most of the details of a glyph and shades of gray are */
+ /* the norm rather than the exception. */
+ /* */
+ /* This is relevant because all our screens have a second problem: */
+ /* they are not linear. 1~+~1 is not~2. Twice the value does not */
+ /* result in twice the brightness. When a pixel is only 50% covered, */
+ /* the coverage map says 50% black, and this translates to a pixel */
+ /* value of 128 when you use 8~bits per channel (0-255). However, */
+ /* this does not translate to 50% brightness for that pixel on our */
+ /* sRGB and gamma~2.2 screens. Due to their non-linearity, they */
+ /* dwell longer in the darks and only a pixel value of about 186 */
+ /* results in 50% brightness – 128 ends up too dark on both bright */
+ /* and dark backgrounds. The net result is that dark text looks */
+ /* burnt-out, pixely and blotchy on bright background, bright text */
+ /* too frail on dark backgrounds, and colored text on colored */
+ /* background (for example, red on green) seems to have dark halos or */
+ /* `dirt' around it. The situation is especially ugly for diagonal */
+ /* stems like in `w' glyph shapes where the quality of FreeType's */
+ /* anti-aliasing depends on the correct display of grays. On */
+ /* high-DPI screens where smaller, fully black pixels reign supreme, */
+ /* this doesn't matter, but on our low-DPI screens with all the gray */
+ /* shades, it does. 0% and 100% brightness are the same things in */
+ /* linear and non-linear space, just all the shades in-between */
+ /* aren't. */
+ /* */
+ /* The blending function for placing text over a background is */
+ /* */
+ /* { */
+ /* dst = alpha * src + (1 - alpha) * dst , */
+ /* } */
+ /* */
+ /* which is known as the OVER operator. */
+ /* */
+ /* To correctly composite an antialiased pixel of a glyph onto a */
+ /* surface, */
+ /* */
+ /* 1. take the foreground and background colors (e.g., in sRGB space) */
+ /* and apply gamma to get them in a linear space, */
+ /* */
+ /* 2. use OVER to blend the two linear colors using the glyph pixel */
+ /* as the alpha value (remember, the glyph bitmap is an alpha */
+ /* coverage bitmap), and */
+ /* */
+ /* 3. apply inverse gamma to the blended pixel and write it back to */
+ /* the image. */
+ /* */
+ /* Internal testing at Adobe found that a target inverse gamma of~1.8 */
+ /* for step~3 gives good results across a wide range of displays with */
+ /* an sRGB gamma curve or a similar one. */
+ /* */
+ /* This process can cost performance. There is an approximation that */
+ /* does not need to know about the background color; see */
+ /* https://bel.fi/alankila/lcd/ and */
+ /* https://bel.fi/alankila/lcd/alpcor.html for details. */
+ /* */
+ /* *ATTENTION*: Linear blending is even more important when dealing */
+ /* with subpixel-rendered glyphs to prevent color-fringing! A */
+ /* subpixel-rendered glyph must first be filtered with a filter that */
+ /* gives equal weight to the three color primaries and does not */
+ /* exceed a sum of 0x100, see section @lcd_filtering. Then the */
+ /* only difference to gray linear blending is that subpixel-rendered */
+ /* linear blending is done 3~times per pixel: red foreground subpixel */
+ /* to red background subpixel and so on for green and blue. */
+ /* */
FT_EXPORT( FT_Error )
FT_Render_Glyph( FT_GlyphSlot slot,
FT_Render_Mode render_mode );
@@ -2821,15 +3123,22 @@
/* @FT_Get_Kerning. */
/* */
/* <Values> */
- /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */
- /* distances (value is~0). */
+ /* FT_KERNING_DEFAULT :: Return grid-fitted kerning distances in */
+ /* pixels (value is~0). Whether they are */
+ /* scaled depends on @FT_LOAD_NO_SCALE. */
/* */
- /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */
- /* distances. */
+ /* FT_KERNING_UNFITTED :: Return un-grid-fitted kerning distances in */
+ /* 26.6 fractional pixels. Whether they are */
+ /* scaled depends on @FT_LOAD_NO_SCALE. */
/* */
/* FT_KERNING_UNSCALED :: Return the kerning vector in original font */
/* units. */
/* */
+ /* <Note> */
+ /* FT_KERNING_DEFAULT returns full pixel values; it also makes */
+ /* FreeType heuristically scale down kerning distances at small ppem */
+ /* values so that they don't become too big. */
+ /* */
typedef enum FT_Kerning_Mode_
{
FT_KERNING_DEFAULT = 0,
@@ -2839,39 +3148,10 @@
} FT_Kerning_Mode;
- /*************************************************************************/
- /* */
- /* <Const> */
- /* ft_kerning_default */
- /* */
- /* <Description> */
- /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */
- /* instead. */
- /* */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Kerning_Mode' values instead */
#define ft_kerning_default FT_KERNING_DEFAULT
-
-
- /*************************************************************************/
- /* */
- /* <Const> */
- /* ft_kerning_unfitted */
- /* */
- /* <Description> */
- /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */
- /* instead. */
- /* */
#define ft_kerning_unfitted FT_KERNING_UNFITTED
-
-
- /*************************************************************************/
- /* */
- /* <Const> */
- /* ft_kerning_unscaled */
- /* */
- /* <Description> */
- /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */
- /* instead. */
- /* */
#define ft_kerning_unscaled FT_KERNING_UNSCALED
@@ -2895,9 +3175,10 @@
/* kerning vector. */
/* */
/* <Output> */
- /* akerning :: The kerning vector. This is either in font units */
- /* or in pixels (26.6 format) for scalable formats, */
- /* and in pixels for fixed-sizes formats. */
+ /* akerning :: The kerning vector. This is either in font units, */
+ /* fractional pixels (26.6 format), or pixels for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -2992,9 +3273,8 @@
/* glyph index~0 always corresponds to the `missing glyph' (called */
/* `.notdef'). */
/* */
- /* This function is not compiled within the library if the config */
- /* macro `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is defined in */
- /* `include/freetype/config/ftoptions.h'. */
+ /* This function always returns an error if the config macro */
+ /* `FT_CONFIG_OPTION_NO_GLYPH_NAMES' is not defined in `ftoptions.h'. */
/* */
FT_EXPORT( FT_Error )
FT_Get_Glyph_Name( FT_Face face,
@@ -3050,8 +3330,8 @@
/* */
/* Because many fonts contain more than a single cmap for Unicode */
/* encoding, this function has some special code to select the one */
- /* which covers Unicode best (`best' in the sense that a UCS-4 cmap */
- /* is preferred to a UCS-2 cmap). It is thus preferable to */
+ /* that covers Unicode best (`best' in the sense that a UCS-4 cmap is */
+ /* preferred to a UCS-2 cmap). It is thus preferable to */
/* @FT_Set_Charmap in this case. */
/* */
FT_EXPORT( FT_Error )
@@ -3183,6 +3463,13 @@
/* } */
/* } */
/* */
+ /* Be aware that character codes can have values up to 0xFFFFFFFF; */
+ /* this might happen for non-Unicode or malformed cmaps. However, */
+ /* even with regular Unicode encoding, so-called `last resort fonts' */
+ /* (using SFNT cmap format 13, see function @FT_Get_CMap_Format) */
+ /* normally have entries for all Unicode characters up to 0x1FFFFF, */
+ /* which can cause *a lot* of iterations. */
+ /* */
/* Note that `*agindex' is set to~0 if the charmap is empty. The */
/* result itself can be~0 in two cases: if the charmap is empty or */
/* if the value~0 is the first valid character code. */
@@ -3342,8 +3629,9 @@
/* @FT_Get_FSType_Flags; they inform client applications of embedding */
/* and subsetting restrictions associated with a font. */
/* */
- /* See http://www.adobe.com/devnet/acrobat/pdfs/FontPolicies.pdf for */
- /* more details. */
+ /* See */
+ /* http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf */
+ /* for more details. */
/* */
/* <Values> */
/* FT_FSTYPE_INSTALLABLE_EMBEDDING :: */
@@ -3377,6 +3665,9 @@
/* bitmaps available in the font, then the font is unembeddable. */
/* */
/* <Note> */
+ /* The flags are ORed together, thus more than a single value can be */
+ /* returned. */
+ /* */
/* While the fsType flags can indicate that a font may be embedded, a */
/* license with the font vendor may be separately required to use the */
/* font in this way. */
@@ -3405,7 +3696,7 @@
/* */
/* <Note> */
/* Use this function rather than directly reading the `fs_type' field */
- /* in the @PS_FontInfoRec structure which is only guaranteed to */
+ /* in the @PS_FontInfoRec structure, which is only guaranteed to */
/* return the correct results for Type~1 fonts. */
/* */
/* <Since> */
@@ -3442,8 +3733,8 @@
/* */
/* http://www.unicode.org/reports/tr37/ */
/* */
- /* To date (November 2012), the character with the most variants is */
- /* U+9089, having 31 such IVS. */
+ /* To date (November 2014), the character with the most variants is */
+ /* U+9089, having 32 such IVS. */
/* */
/* Adobe and MS decided to support IVS with a new cmap subtable */
/* (format~14). It is an odd subtable because it is not a mapping of */
@@ -3585,7 +3876,7 @@
/* The character codepoint in Unicode. */
/* */
/* <Return> */
- /* A pointer to an array of variant selector code points which are */
+ /* A pointer to an array of variant selector code points that are */
/* active for the given character, or NULL if the corresponding list */
/* is empty. */
/* */
@@ -3619,7 +3910,7 @@
/* The variant selector code point in Unicode. */
/* */
/* <Return> */
- /* A list of all the code points which are specified by this selector */
+ /* A list of all the code points that are specified by this selector */
/* (both default and non-default codes are returned) or NULL if there */
/* is no valid cmap or the variant selector is invalid. */
/* */
@@ -3694,12 +3985,6 @@
FT_Long c );
- /* */
-
- /* The following #if 0 ... #endif is for the documentation formatter, */
- /* hiding the internal `FT_MULFIX_INLINED' macro. */
-
-#if 0
/*************************************************************************/
/* */
/* <Function> */
@@ -3733,17 +4018,6 @@
FT_MulFix( FT_Long a,
FT_Long b );
- /* */
-#endif
-
-#ifdef FT_MULFIX_INLINED
-#define FT_MulFix( a, b ) FT_MULFIX_INLINED( a, b )
-#else
- FT_EXPORT( FT_Long )
- FT_MulFix( FT_Long a,
- FT_Long b );
-#endif
-
/*************************************************************************/
/* */
@@ -3756,18 +4030,12 @@
/* used to divide a given value by a 16.16 fixed-point factor. */
/* */
/* <Input> */
- /* a :: The first multiplier. */
- /* b :: The second multiplier. Use a 16.16 factor here whenever */
- /* possible (see note below). */
+ /* a :: The numerator. */
+ /* b :: The denominator. Use a 16.16 factor here. */
/* */
/* <Return> */
/* The result of `(a*0x10000)/b'. */
/* */
- /* <Note> */
- /* The optimization for FT_DivFix() is simple: If (a~<<~16) fits in */
- /* 32~bits, then the division is computed directly. Otherwise, we */
- /* use a specialized version of @FT_MulDiv. */
- /* */
FT_EXPORT( FT_Long )
FT_DivFix( FT_Long a,
FT_Long b );
@@ -3785,7 +4053,8 @@
/* a :: The number to be rounded. */
/* */
/* <Return> */
- /* The result of `(a + 0x8000) & -0x10000'. */
+ /* `a' rounded to nearest 16.16 fixed integer, halfway cases away */
+ /* from zero. */
/* */
FT_EXPORT( FT_Fixed )
FT_RoundFix( FT_Fixed a );
@@ -3804,7 +4073,7 @@
/* a :: The number for which the ceiling function is to be computed. */
/* */
/* <Return> */
- /* The result of `(a + 0x10000 - 1) & -0x10000'. */
+ /* `a' rounded towards plus infinity. */
/* */
FT_EXPORT( FT_Fixed )
FT_CeilFix( FT_Fixed a );
@@ -3823,7 +4092,7 @@
/* a :: The number for which the floor function is to be computed. */
/* */
/* <Return> */
- /* The result of `a & -0x10000'. */
+ /* `a' rounded towards minus infinity. */
/* */
FT_EXPORT( FT_Fixed )
FT_FloorFix( FT_Fixed a );
@@ -3867,6 +4136,18 @@
/* even a new release of FreeType with only documentation changes */
/* increases the version number. */
/* */
+ /* <Order> */
+ /* FT_Library_Version */
+ /* */
+ /* FREETYPE_MAJOR */
+ /* FREETYPE_MINOR */
+ /* FREETYPE_PATCH */
+ /* */
+ /* FT_Face_CheckTrueTypePatents */
+ /* FT_Face_SetUnpatentedHinting */
+ /* */
+ /* FREETYPE_XXX */
+ /* */
/*************************************************************************/
@@ -3891,8 +4172,8 @@
*
*/
#define FREETYPE_MAJOR 2
-#define FREETYPE_MINOR 4
-#define FREETYPE_PATCH 12
+#define FREETYPE_MINOR 6
+#define FREETYPE_PATCH 2
/*************************************************************************/
diff --git a/include/freetype/ftadvanc.h b/include/freetype/ftadvanc.h
index 012b74b..b4d2aed 100644
--- a/include/freetype/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
/* */
/* Quick computation of advance widths (specification only). */
/* */
-/* Copyright 2008, 2013 by */
+/* Copyright 2008-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,6 +48,11 @@
* @description:
* This section contains functions to quickly extract advance values
* without handling glyph outlines, if possible.
+ *
+ * @order:
+ * FT_Get_Advance
+ * FT_Get_Advances
+ *
*/
@@ -64,15 +69,15 @@
/* corresponding hinting mode or font driver doesn't allow for very */
/* quick advance computation. */
/* */
- /* Typically, glyphs which are either unscaled, unhinted, bitmapped, */
+ /* Typically, glyphs that are either unscaled, unhinted, bitmapped, */
/* or light-hinted can have their advance width computed very */
/* quickly. */
/* */
- /* Normal and bytecode hinted modes, which require loading, scaling, */
+ /* Normal and bytecode hinted modes that require loading, scaling, */
/* and hinting of the glyph outline, are extremely slow by */
/* comparison. */
/* */
-#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000UL
+#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L
/*************************************************************************/
@@ -171,7 +176,7 @@
FT_Int32 load_flags,
FT_Fixed *padvances );
-/* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftautoh.h b/include/freetype/ftautoh.h
index 62ce96d..d0f6445 100644
--- a/include/freetype/ftautoh.h
+++ b/include/freetype/ftautoh.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for controlling the auto-hinter (specification only). */
/* */
-/* Copyright 2012 by */
+/* Copyright 2012-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -61,6 +61,8 @@
* glyph-to-script-map
*
* @description:
+ * *Experimental* *only*
+ *
* The auto-hinter provides various script modules to hint glyphs.
* Examples of supported scripts are Latin or CJK. Before a glyph is
* auto-hinted, the Unicode character map of the font gets examined, and
@@ -77,7 +79,7 @@
* sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an
* array with `num_glyphs' elements, as found in the font's @FT_Face
* structure. The `glyph-to-script-map' property returns a pointer to
- * this array which can be modified as needed. Note that the
+ * this array, which can be modified as needed. Note that the
* modification should happen before the first glyph gets processed by
* the auto-hinter so that the global analysis of the font shapes
* actually uses the modified mapping.
@@ -113,6 +115,8 @@
* FT_AUTOHINTER_SCRIPT_XXX
*
* @description:
+ * *Experimental* *only*
+ *
* A list of constants used for the @glyph-to-script-map property to
* specify the script submodule the auto-hinter should use for hinting a
* particular glyph.
@@ -236,15 +240,17 @@
* FT_Prop_GlyphToScriptMap
*
* @description:
+ * *Experimental* *only*
+ *
* The data exchange structure for the @glyph-to-script-map property.
*
*/
- typedef struct FT_Prop_GlyphToScriptMap_
- {
- FT_Face face;
- FT_Byte* map;
+ typedef struct FT_Prop_GlyphToScriptMap_
+ {
+ FT_Face face;
+ FT_UShort* map;
- } FT_Prop_GlyphToScriptMap;
+ } FT_Prop_GlyphToScriptMap;
/**************************************************************************
@@ -253,6 +259,8 @@
* fallback-script
*
* @description:
+ * *Experimental* *only*
+ *
* If no auto-hinter script module can be assigned to a glyph, a
* fallback script gets assigned to it (see also the
* @glyph-to-script-map property). By default, this is
@@ -274,12 +282,57 @@
* This property can be used with @FT_Property_Get also.
*
* It's important to use the right timing for changing this value: The
- * creation of the glyph-to-script map which eventually uses the
+ * creation of the glyph-to-script map that eventually uses the
* fallback script value gets triggered either by setting or reading a
* face-specific property like @glyph-to-script-map, or by auto-hinting
* any glyph from that face. In particular, if you have already created
* an @FT_Face structure but not loaded any glyph (using the
- * auto-hinter), a change of the fallback glyph will affect this face.
+ * auto-hinter), a change of the fallback script will affect this face.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * default-script
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * If FreeType gets compiled with FT_CONFIG_OPTION_USE_HARFBUZZ to make
+ * the HarfBuzz library access OpenType features for getting better
+ * glyph coverages, this property sets the (auto-fitter) script to be
+ * used for the default (OpenType) script data of a font's GSUB table.
+ * Features for the default script are intended for all scripts not
+ * explicitly handled in GSUB; an example is a `dlig' feature,
+ * containing the combination of the characters `T', `E', and `L' to
+ * form a `TEL' ligature.
+ *
+ * By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the
+ * `default-script' property, this default value can be changed.
+ *
+ * {
+ * FT_Library library;
+ * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "default-script", &default_script );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * It's important to use the right timing for changing this value: The
+ * creation of the glyph-to-script map that eventually uses the
+ * default script value gets triggered either by setting or reading a
+ * face-specific property like @glyph-to-script-map, or by auto-hinting
+ * any glyph from that face. In particular, if you have already created
+ * an @FT_Face structure but not loaded any glyph (using the
+ * auto-hinter), a change of the default script will affect this face.
*
*/
@@ -331,15 +384,116 @@
* The data exchange structure for the @increase-x-height property.
*
*/
- typedef struct FT_Prop_IncreaseXHeight_
- {
- FT_Face face;
- FT_UInt limit;
+ typedef struct FT_Prop_IncreaseXHeight_
+ {
+ FT_Face face;
+ FT_UInt limit;
- } FT_Prop_IncreaseXHeight;
+ } FT_Prop_IncreaseXHeight;
- /* */
+ /**************************************************************************
+ *
+ * @property:
+ * warping
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * If FreeType gets compiled with option AF_CONFIG_OPTION_USE_WARPER to
+ * activate the warp hinting code in the auto-hinter, this property
+ * switches warping on and off.
+ *
+ * Warping only works in `light' auto-hinting mode. The idea of the
+ * code is to slightly scale and shift a glyph along the non-hinted
+ * dimension (which is usually the horizontal axis) so that as much of
+ * its segments are aligned (more or less) to the grid. To find out a
+ * glyph's optimal scaling and shifting value, various parameter
+ * combinations are tried and scored.
+ *
+ * By default, warping is off. The example below shows how to switch on
+ * warping (omitting the error handling).
+ *
+ * {
+ * FT_Library library;
+ * FT_Bool warping = 1;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "warping", &warping );
+ * }
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * The warping code can also change advance widths. Have a look at the
+ * `lsb_delta' and `rsb_delta' fields in the @FT_GlyphSlotRec structure
+ * for details on improving inter-glyph distances while rendering.
+ *
+ * Since warping is a global property of the auto-hinter it is best to
+ * change its value before rendering any face. Otherwise, you should
+ * reload all faces that get auto-hinted in `light' hinting mode.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * no-stem-darkening[autofit]
+ *
+ * @description:
+ * *Experimental* *only,* *requires* *linear* *alpha* *blending* *and*
+ * *gamma* *correction*
+ *
+ * Stem darkening emboldens glyphs at smaller sizes to make them more
+ * readable on common low-DPI screens when using linear alpha blending
+ * and gamma correction, see @FT_Render_Glyph. When not using linear
+ * alpha blending and gamma correction, glyphs will appear heavy and
+ * fuzzy!
+ *
+ * Gamma correction essentially lightens fonts since shades of grey are
+ * shifted to higher pixel values (=~higher brightness) to match the
+ * original intention to the reality of our screens. The side-effect is
+ * that glyphs `thin out'. Mac OS~X and Adobe's proprietary font
+ * rendering library implement a counter-measure: stem darkening at
+ * smaller sizes where shades of gray dominate. By emboldening a glyph
+ * slightly in relation to its pixel size, individual pixels get higher
+ * coverage of filled-in outlines and are therefore `blacker'. This
+ * counteracts the `thinning out' of glyphs, making text remain readable
+ * at smaller sizes. All glyphs that pass through the auto-hinter will
+ * be emboldened unless this property is set to TRUE.
+ *
+ * See the description of the CFF driver for algorithmic details. Total
+ * consistency with the CFF driver is currently not achieved because the
+ * emboldening method differs and glyphs must be scaled down on the
+ * Y-axis to keep outline points inside their precomputed blue zones.
+ * The smaller the size (especially 9ppem and down), the higher the loss
+ * of emboldening versus the CFF driver.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * darkening-parameters[autofit]
+ *
+ * @description:
+ * *Experimental* *only*
+ *
+ * See the description of the CFF driver for details. This
+ * implementation appropriates the
+ * CFF_CONFIG_OPTION_DARKENING_PARAMETER_* #defines for consistency.
+ * Note the differences described in @no-stem-darkening[autofit].
+ *
+ */
+
+
+ /* */
+
FT_END_HEADER
diff --git a/include/freetype/ftbbox.h b/include/freetype/ftbbox.h
index 9766919..9d9d040 100644
--- a/include/freetype/ftbbox.h
+++ b/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
/* */
/* FreeType exact bbox computation (specification). */
/* */
-/* Copyright 1996-2001, 2003, 2007, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -60,7 +60,7 @@
/* <Description> */
/* Compute the exact bounding box of an outline. This is slower */
/* than computing the control box. However, it uses an advanced */
- /* algorithm which returns _very_ quickly when the two boxes */
+ /* algorithm that returns _very_ quickly when the two boxes */
/* coincide. Otherwise, the outline Bézier arcs are traversed to */
/* extract their extrema. */
/* */
@@ -78,14 +78,13 @@
/* @FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get */
/* reasonable values for the BBox it is necessary to load the glyph */
/* at a large ppem value (so that the hinting instructions can */
- /* properly shift and scale the subglyphs), then extracting the BBox */
+ /* properly shift and scale the subglyphs), then extracting the BBox, */
/* which can be eventually converted back to font units. */
/* */
FT_EXPORT( FT_Error )
FT_Outline_Get_BBox( FT_Outline* outline,
FT_BBox *abbox );
-
/* */
diff --git a/include/freetype/ftbdf.h b/include/freetype/ftbdf.h
index 4f8baf8..0bdabf4 100644
--- a/include/freetype/ftbdf.h
+++ b/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing BDF-specific strings (specification). */
/* */
-/* Copyright 2002, 2003, 2004, 2006, 2009 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -53,7 +53,7 @@
/**********************************************************************
*
* @enum:
- * FT_PropertyType
+ * BDF_PropertyType
*
* @description:
* A list of BDF property types.
@@ -106,7 +106,8 @@
* The property type.
*
* u.atom ::
- * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM.
+ * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. May be
+ * NULL, indicating an empty string.
*
* u.integer ::
* A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.
@@ -199,7 +200,7 @@
const char* prop_name,
BDF_PropertyRec *aproperty );
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftbitmap.h b/include/freetype/ftbitmap.h
index 7dbf5ba..46cc47b 100644
--- a/include/freetype/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
/* */
/* FreeType utility functions for bitmaps (specification). */
/* */
-/* Copyright 2004-2006, 2008, 2013 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -45,7 +45,9 @@
/* Handling FT_Bitmap objects. */
/* */
/* <Description> */
- /* This section contains functions for converting FT_Bitmap objects. */
+ /* This section contains functions for handling @FT_Bitmap objects. */
+ /* Note that none of the functions changes the bitmap's `flow' (as */
+ /* indicated by the sign of the `pitch' field in `FT_Bitmap'). */
/* */
/*************************************************************************/
@@ -53,7 +55,7 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Bitmap_New */
+ /* FT_Bitmap_Init */
/* */
/* <Description> */
/* Initialize a pointer to an @FT_Bitmap structure. */
@@ -61,6 +63,14 @@
/* <InOut> */
/* abitmap :: A pointer to the bitmap structure. */
/* */
+ /* <Note> */
+ /* A deprecated name for the same function is `FT_Bitmap_New'. */
+ /* */
+ FT_EXPORT( void )
+ FT_Bitmap_Init( FT_Bitmap *abitmap );
+
+
+ /* deprecated */
FT_EXPORT( void )
FT_Bitmap_New( FT_Bitmap *abitmap );
@@ -122,6 +132,9 @@
/* If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, */
/* you should call @FT_GlyphSlot_Own_Bitmap on the slot first. */
/* */
+ /* Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format */
+ /* are converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp). */
+ /* */
FT_EXPORT( FT_Error )
FT_Bitmap_Embolden( FT_Library library,
FT_Bitmap* bitmap,
@@ -197,7 +210,7 @@
/* FT_Bitmap_Done */
/* */
/* <Description> */
- /* Destroy a bitmap object created with @FT_Bitmap_New. */
+ /* Destroy a bitmap object initialized with @FT_Bitmap_Init. */
/* */
/* <Input> */
/* library :: A handle to a library object. */
diff --git a/include/freetype/ftbzip2.h b/include/freetype/ftbzip2.h
new file mode 100644
index 0000000..c25f946
--- /dev/null
+++ b/include/freetype/ftbzip2.h
@@ -0,0 +1,102 @@
+/***************************************************************************/
+/* */
+/* ftbzip2.h */
+/* */
+/* Bzip2-compressed stream support. */
+/* */
+/* Copyright 2010-2015 by */
+/* Joel Klinghed. */
+/* */
+/* 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 __FTBZIP2_H__
+#define __FTBZIP2_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* bzip2 */
+ /* */
+ /* <Title> */
+ /* BZIP2 Streams */
+ /* */
+ /* <Abstract> */
+ /* Using bzip2-compressed font files. */
+ /* */
+ /* <Description> */
+ /* This section contains the declaration of Bzip2-specific functions. */
+ /* */
+ /*************************************************************************/
+
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenBzip2
+ *
+ * @description:
+ * Open a new stream to parse bzip2-compressed font files. This is
+ * mainly used to support the compressed `*.pcf.bz2' fonts that come
+ * with XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close' on the new stream will
+ * *not* call `FT_Stream_Close' on the source stream. None of the stream
+ * objects will be released to the heap.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream.
+ *
+ * In certain builds of the library, bzip2 compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a bzip2 compressed stream
+ * from it and re-open the face with it.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature' if your build
+ * of FreeType was not compiled with bzip2 support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenBzip2( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTBZIP2_H__ */
+
+
+/* END */
diff --git a/include/freetype/ftcache.h b/include/freetype/ftcache.h
index 4ec9587..68525bb 100644
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache subsystem (specification). */
/* */
-/* Copyright 1996-2008, 2010, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -156,7 +156,7 @@
* @note:
* Never use NULL as a valid @FTC_FaceID.
*
- * Face IDs are passed by the client to the cache manager, which calls,
+ * Face IDs are passed by the client to the cache manager that calls,
* when needed, the @FTC_Face_Requester to translate them into new
* @FT_Face objects.
*
@@ -209,10 +209,10 @@
typedef FT_Error
(*FTC_Face_Requester)( FTC_FaceID face_id,
FT_Library library,
- FT_Pointer request_data,
+ FT_Pointer req_data,
FT_Face* aface );
- /* */
+ /* */
/*************************************************************************/
@@ -667,8 +667,8 @@
typedef struct FTC_ImageTypeRec_
{
FTC_FaceID face_id;
- FT_Int width;
- FT_Int height;
+ FT_UInt width;
+ FT_UInt height;
FT_Int32 flags;
} FTC_ImageTypeRec;
@@ -1046,8 +1046,8 @@
FTC_SBit *sbit,
FTC_Node *anode );
+ /* */
- /* */
FT_END_HEADER
diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h
index ccbcbcc..8500346 100644
--- a/include/freetype/ftcffdrv.h
+++ b/include/freetype/ftcffdrv.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for controlling the CFF driver (specification only). */
/* */
-/* Copyright 2013 by */
+/* Copyright 2013-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -46,11 +46,74 @@
* @description:
* While FreeType's CFF driver doesn't expose API functions by itself,
* it is possible to control its behaviour with @FT_Property_Set and
- * @FT_Property_Get. The following lists the available properties
+ * @FT_Property_Get. The list below gives the available properties
* together with the necessary macros and structures.
*
* The CFF driver's module name is `cff'.
*
+ * *Hinting* *and* *antialiasing* *principles* *of* *the* *new* *engine*
+ *
+ * The rasterizer is positioning horizontal features (e.g., ascender
+ * height & x-height, or crossbars) on the pixel grid and minimizing the
+ * amount of antialiasing applied to them, while placing vertical
+ * features (vertical stems) on the pixel grid without hinting, thus
+ * representing the stem position and weight accurately. Sometimes the
+ * vertical stems may be only partially black. In this context,
+ * `antialiasing' means that stems are not positioned exactly on pixel
+ * borders, causing a fuzzy appearance.
+ *
+ * There are two principles behind this approach.
+ *
+ * 1) No hinting in the horizontal direction: Unlike `superhinted'
+ * TrueType, which changes glyph widths to accommodate regular
+ * inter-glyph spacing, Adobe's approach is `faithful to the design' in
+ * representing both the glyph width and the inter-glyph spacing
+ * designed for the font. This makes the screen display as close as it
+ * can be to the result one would get with infinite resolution, while
+ * preserving what is considered the key characteristics of each glyph.
+ * Note that the distances between unhinted and grid-fitted positions at
+ * small sizes are comparable to kerning values and thus would be
+ * noticeable (and distracting) while reading if hinting were applied.
+ *
+ * One of the reasons to not hint horizontally is antialiasing for LCD
+ * screens: The pixel geometry of modern displays supplies three
+ * vertical sub-pixels as the eye moves horizontally across each visible
+ * pixel. On devices where we can be certain this characteristic is
+ * present a rasterizer can take advantage of the sub-pixels to add
+ * increments of weight. In Western writing systems this turns out to
+ * be the more critical direction anyway; the weights and spacing of
+ * vertical stems (see above) are central to Armenian, Cyrillic, Greek,
+ * and Latin type designs. Even when the rasterizer uses greyscale
+ * antialiasing instead of color (a necessary compromise when one
+ * doesn't know the screen characteristics), the unhinted vertical
+ * features preserve the design's weight and spacing much better than
+ * aliased type would.
+ *
+ * 2) Aligment in the vertical direction: Weights and spacing along the
+ * y~axis are less critical; what is much more important is the visual
+ * alignment of related features (like cap-height and x-height). The
+ * sense of alignment for these is enhanced by the sharpness of grid-fit
+ * edges, while the cruder vertical resolution (full pixels instead of
+ * 1/3 pixels) is less of a problem.
+ *
+ * On the technical side, horizontal alignment zones for ascender,
+ * x-height, and other important height values (traditionally called
+ * `blue zones') as defined in the font are positioned independently,
+ * each being rounded to the nearest pixel edge, taking care of
+ * overshoot suppression at small sizes, stem darkening, and scaling.
+ *
+ * Hstems (this is, hint values defined in the font to help align
+ * horizontal features) that fall within a blue zone are said to be
+ * `captured' and are aligned to that zone. Uncaptured stems are moved
+ * in one of four ways, top edge up or down, bottom edge up or down.
+ * Unless there are conflicting hstems, the smallest movement is taken
+ * to minimize distortion.
+ *
+ * @order:
+ * hinting-engine
+ * no-stem-darkening[cff]
+ * darkening-parameters[cff]
+ *
*/
@@ -73,7 +136,6 @@
*
* {
* FT_Library library;
- * FT_Face face;
* FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE;
*
*
@@ -113,18 +175,18 @@
/**************************************************************************
*
* @property:
- * no-stem-darkening
+ * no-stem-darkening[cff]
*
* @description:
* By default, the Adobe CFF engine darkens stems at smaller sizes,
- * regardless of hinting, to enhance contrast. Setting this property,
- * stem darkening gets switched off.
+ * regardless of hinting, to enhance contrast. This feature requires
+ * a rendering system with proper gamma correction. Setting this
+ * property, stem darkening gets switched off.
*
* Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set.
*
* {
* FT_Library library;
- * FT_Face face;
* FT_Bool no_stem_darkening = TRUE;
*
*
@@ -140,7 +202,56 @@
*/
- /* */
+ /**************************************************************************
+ *
+ * @property:
+ * darkening-parameters[cff]
+ *
+ * @description:
+ * By default, the Adobe CFF engine darkens stems as follows (if the
+ * `no-stem-darkening' property isn't set):
+ *
+ * {
+ * stem width <= 0.5px: darkening amount = 0.4px
+ * stem width = 1px: darkening amount = 0.275px
+ * stem width = 1.667px: darkening amount = 0.275px
+ * stem width >= 2.333px: darkening amount = 0px
+ * }
+ *
+ * and piecewise linear in-between. At configuration time, these four
+ * control points can be set with the macro
+ * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS'. At runtime, the control
+ * points can be changed using the `darkening-parameters' property, as
+ * the following example demonstrates.
+ *
+ * {
+ * FT_Library library;
+ * FT_Int darken_params[8] = { 500, 300, // x1, y1
+ * 1000, 200, // x2, y2
+ * 1500, 100, // x3, y3
+ * 2000, 0 }; // x4, y4
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "cff",
+ * "darkening-parameters", darken_params );
+ * }
+ *
+ * The x~values give the stem width, and the y~values the darkening
+ * amount. The unit is 1000th of pixels. All coordinate values must be
+ * positive; the x~values must be monotonically increasing; the
+ * y~values must be monotonically decreasing and smaller than or
+ * equal to 500 (corresponding to half a pixel); the slope of each
+ * linear piece must be shallower than -1 (e.g., -.4).
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ */
+
+ /* */
+
FT_END_HEADER
diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h
index c55670d..ab43895 100644
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -1,7 +1,7 @@
/***************************************************************************/
/* */
/* This file defines the structure of the FreeType reference. */
-/* It is used by the python script which generates the HTML files. */
+/* It is used by the python script that generates the HTML files. */
/* */
/***************************************************************************/
@@ -15,6 +15,7 @@
/* General Remarks */
/* */
/* <Sections> */
+/* header_inclusion */
/* user_allocation */
/* */
/***************************************************************************/
@@ -118,3 +119,17 @@
/* lcd_filtering */
/* */
/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* <Chapter> */
+/* error_codes */
+/* */
+/* <Title> */
+/* Error Codes */
+/* */
+/* <Sections> */
+/* error_enumerations */
+/* error_code_values */
+/* */
+/***************************************************************************/
diff --git a/include/freetype/ftcid.h b/include/freetype/ftcid.h
index 203a30c..05741c8 100644
--- a/include/freetype/ftcid.h
+++ b/include/freetype/ftcid.h
@@ -4,7 +4,8 @@
/* */
/* FreeType API for accessing CID font information (specification). */
/* */
-/* Copyright 2007, 2009 by Dereg Clegg, Michael Toftdal. */
+/* Copyright 2007-2015 by */
+/* Dereg Clegg and Michael Toftdal. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
@@ -156,7 +157,8 @@
FT_UInt glyph_index,
FT_UInt *cid );
- /* */
+ /* */
+
FT_END_HEADER
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index 76c7b9e..3bf4e63 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
/* */
/* FreeType error codes (specification). */
/* */
-/* Copyright 2002, 2004, 2006, 2007, 2010-2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,234 +16,261 @@
/***************************************************************************/
- /*******************************************************************/
- /*******************************************************************/
- /***** *****/
- /***** LIST OF ERROR CODES/MESSAGES *****/
- /***** *****/
- /*******************************************************************/
- /*******************************************************************/
+ /*************************************************************************/
+ /* */
+ /* <Section> */
+ /* error_code_values */
+ /* */
+ /* <Title> */
+ /* Error Code Values */
+ /* */
+ /* <Abstract> */
+ /* All possible error codes returned by FreeType functions. */
+ /* */
+ /* <Description> */
+ /* The list below is taken verbatim from the file `fterrdef.h' */
+ /* (loaded automatically by including `FT_FREETYPE_H'). The first */
+ /* argument of the `FT_ERROR_DEF_' macro is the error label; by */
+ /* default, the prefix `FT_Err_' gets added so that you get error */
+ /* names like `FT_Err_Cannot_Open_Resource'. The second argument is */
+ /* the error code, and the last argument an error string, which is not */
+ /* used by FreeType. */
+ /* */
+ /* Within your application you should *only* use error names and */
+ /* *never* its numeric values! The latter might (and actually do) */
+ /* change in forthcoming FreeType versions. */
+ /* */
+ /* Macro `FT_NOERRORDEF_' defines `FT_Err_Ok', which is always zero. */
+ /* See the `Error Enumerations' subsection how to automatically */
+ /* generate a list of error strings. */
+ /* */
+ /*************************************************************************/
- /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */
- /* including this file. */
-
+ /*************************************************************************/
+ /* */
+ /* <Enum> */
+ /* FT_Err_XXX */
+ /* */
+ /*************************************************************************/
/* generic errors */
- FT_NOERRORDEF_( Ok, 0x00, \
+ FT_NOERRORDEF_( Ok, 0x00,
"no error" )
- FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \
+ FT_ERRORDEF_( Cannot_Open_Resource, 0x01,
"cannot open resource" )
- FT_ERRORDEF_( Unknown_File_Format, 0x02, \
+ FT_ERRORDEF_( Unknown_File_Format, 0x02,
"unknown file format" )
- FT_ERRORDEF_( Invalid_File_Format, 0x03, \
+ FT_ERRORDEF_( Invalid_File_Format, 0x03,
"broken file" )
- FT_ERRORDEF_( Invalid_Version, 0x04, \
+ FT_ERRORDEF_( Invalid_Version, 0x04,
"invalid FreeType version" )
- FT_ERRORDEF_( Lower_Module_Version, 0x05, \
+ FT_ERRORDEF_( Lower_Module_Version, 0x05,
"module version is too low" )
- FT_ERRORDEF_( Invalid_Argument, 0x06, \
+ FT_ERRORDEF_( Invalid_Argument, 0x06,
"invalid argument" )
- FT_ERRORDEF_( Unimplemented_Feature, 0x07, \
+ FT_ERRORDEF_( Unimplemented_Feature, 0x07,
"unimplemented feature" )
- FT_ERRORDEF_( Invalid_Table, 0x08, \
+ FT_ERRORDEF_( Invalid_Table, 0x08,
"broken table" )
- FT_ERRORDEF_( Invalid_Offset, 0x09, \
+ FT_ERRORDEF_( Invalid_Offset, 0x09,
"broken offset within table" )
- FT_ERRORDEF_( Array_Too_Large, 0x0A, \
+ FT_ERRORDEF_( Array_Too_Large, 0x0A,
"array allocation size too large" )
- FT_ERRORDEF_( Missing_Module, 0x0B, \
+ FT_ERRORDEF_( Missing_Module, 0x0B,
"missing module" )
- FT_ERRORDEF_( Missing_Property, 0x0C, \
+ FT_ERRORDEF_( Missing_Property, 0x0C,
"missing property" )
/* glyph/character errors */
- FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \
+ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10,
"invalid glyph index" )
- FT_ERRORDEF_( Invalid_Character_Code, 0x11, \
+ FT_ERRORDEF_( Invalid_Character_Code, 0x11,
"invalid character code" )
- FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \
+ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12,
"unsupported glyph image format" )
- FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \
+ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13,
"cannot render this glyph format" )
- FT_ERRORDEF_( Invalid_Outline, 0x14, \
+ FT_ERRORDEF_( Invalid_Outline, 0x14,
"invalid outline" )
- FT_ERRORDEF_( Invalid_Composite, 0x15, \
+ FT_ERRORDEF_( Invalid_Composite, 0x15,
"invalid composite glyph" )
- FT_ERRORDEF_( Too_Many_Hints, 0x16, \
+ FT_ERRORDEF_( Too_Many_Hints, 0x16,
"too many hints" )
- FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \
+ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17,
"invalid pixel size" )
/* handle errors */
- FT_ERRORDEF_( Invalid_Handle, 0x20, \
+ FT_ERRORDEF_( Invalid_Handle, 0x20,
"invalid object handle" )
- FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \
+ FT_ERRORDEF_( Invalid_Library_Handle, 0x21,
"invalid library handle" )
- FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \
+ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22,
"invalid module handle" )
- FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \
+ FT_ERRORDEF_( Invalid_Face_Handle, 0x23,
"invalid face handle" )
- FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \
+ FT_ERRORDEF_( Invalid_Size_Handle, 0x24,
"invalid size handle" )
- FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \
+ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25,
"invalid glyph slot handle" )
- FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \
+ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26,
"invalid charmap handle" )
- FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \
+ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27,
"invalid cache manager handle" )
- FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \
+ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28,
"invalid stream handle" )
/* driver errors */
- FT_ERRORDEF_( Too_Many_Drivers, 0x30, \
+ FT_ERRORDEF_( Too_Many_Drivers, 0x30,
"too many modules" )
- FT_ERRORDEF_( Too_Many_Extensions, 0x31, \
+ FT_ERRORDEF_( Too_Many_Extensions, 0x31,
"too many extensions" )
/* memory errors */
- FT_ERRORDEF_( Out_Of_Memory, 0x40, \
+ FT_ERRORDEF_( Out_Of_Memory, 0x40,
"out of memory" )
- FT_ERRORDEF_( Unlisted_Object, 0x41, \
+ FT_ERRORDEF_( Unlisted_Object, 0x41,
"unlisted object" )
/* stream errors */
- FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \
+ FT_ERRORDEF_( Cannot_Open_Stream, 0x51,
"cannot open stream" )
- FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \
+ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52,
"invalid stream seek" )
- FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \
+ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53,
"invalid stream skip" )
- FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \
+ FT_ERRORDEF_( Invalid_Stream_Read, 0x54,
"invalid stream read" )
- FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \
+ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55,
"invalid stream operation" )
- FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \
+ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56,
"invalid frame operation" )
- FT_ERRORDEF_( Nested_Frame_Access, 0x57, \
+ FT_ERRORDEF_( Nested_Frame_Access, 0x57,
"nested frame access" )
- FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \
+ FT_ERRORDEF_( Invalid_Frame_Read, 0x58,
"invalid frame read" )
/* raster errors */
- FT_ERRORDEF_( Raster_Uninitialized, 0x60, \
+ FT_ERRORDEF_( Raster_Uninitialized, 0x60,
"raster uninitialized" )
- FT_ERRORDEF_( Raster_Corrupted, 0x61, \
+ FT_ERRORDEF_( Raster_Corrupted, 0x61,
"raster corrupted" )
- FT_ERRORDEF_( Raster_Overflow, 0x62, \
+ FT_ERRORDEF_( Raster_Overflow, 0x62,
"raster overflow" )
- FT_ERRORDEF_( Raster_Negative_Height, 0x63, \
+ FT_ERRORDEF_( Raster_Negative_Height, 0x63,
"negative height while rastering" )
/* cache errors */
- FT_ERRORDEF_( Too_Many_Caches, 0x70, \
+ FT_ERRORDEF_( Too_Many_Caches, 0x70,
"too many registered caches" )
/* TrueType and SFNT errors */
- FT_ERRORDEF_( Invalid_Opcode, 0x80, \
+ FT_ERRORDEF_( Invalid_Opcode, 0x80,
"invalid opcode" )
- FT_ERRORDEF_( Too_Few_Arguments, 0x81, \
+ FT_ERRORDEF_( Too_Few_Arguments, 0x81,
"too few arguments" )
- FT_ERRORDEF_( Stack_Overflow, 0x82, \
+ FT_ERRORDEF_( Stack_Overflow, 0x82,
"stack overflow" )
- FT_ERRORDEF_( Code_Overflow, 0x83, \
+ FT_ERRORDEF_( Code_Overflow, 0x83,
"code overflow" )
- FT_ERRORDEF_( Bad_Argument, 0x84, \
+ FT_ERRORDEF_( Bad_Argument, 0x84,
"bad argument" )
- FT_ERRORDEF_( Divide_By_Zero, 0x85, \
+ FT_ERRORDEF_( Divide_By_Zero, 0x85,
"division by zero" )
- FT_ERRORDEF_( Invalid_Reference, 0x86, \
+ FT_ERRORDEF_( Invalid_Reference, 0x86,
"invalid reference" )
- FT_ERRORDEF_( Debug_OpCode, 0x87, \
+ FT_ERRORDEF_( Debug_OpCode, 0x87,
"found debug opcode" )
- FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \
+ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88,
"found ENDF opcode in execution stream" )
- FT_ERRORDEF_( Nested_DEFS, 0x89, \
+ FT_ERRORDEF_( Nested_DEFS, 0x89,
"nested DEFS" )
- FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \
+ FT_ERRORDEF_( Invalid_CodeRange, 0x8A,
"invalid code range" )
- FT_ERRORDEF_( Execution_Too_Long, 0x8B, \
+ FT_ERRORDEF_( Execution_Too_Long, 0x8B,
"execution context too long" )
- FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \
+ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C,
"too many function definitions" )
- FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \
+ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D,
"too many instruction definitions" )
- FT_ERRORDEF_( Table_Missing, 0x8E, \
+ FT_ERRORDEF_( Table_Missing, 0x8E,
"SFNT font table missing" )
- FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \
+ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F,
"horizontal header (hhea) table missing" )
- FT_ERRORDEF_( Locations_Missing, 0x90, \
+ FT_ERRORDEF_( Locations_Missing, 0x90,
"locations (loca) table missing" )
- FT_ERRORDEF_( Name_Table_Missing, 0x91, \
+ FT_ERRORDEF_( Name_Table_Missing, 0x91,
"name table missing" )
- FT_ERRORDEF_( CMap_Table_Missing, 0x92, \
+ FT_ERRORDEF_( CMap_Table_Missing, 0x92,
"character map (cmap) table missing" )
- FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \
+ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93,
"horizontal metrics (hmtx) table missing" )
- FT_ERRORDEF_( Post_Table_Missing, 0x94, \
+ FT_ERRORDEF_( Post_Table_Missing, 0x94,
"PostScript (post) table missing" )
- FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \
+ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95,
"invalid horizontal metrics" )
- FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \
+ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96,
"invalid character map (cmap) format" )
- FT_ERRORDEF_( Invalid_PPem, 0x97, \
+ FT_ERRORDEF_( Invalid_PPem, 0x97,
"invalid ppem value" )
- FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \
+ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98,
"invalid vertical metrics" )
- FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \
+ FT_ERRORDEF_( Could_Not_Find_Context, 0x99,
"could not find context" )
- FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \
+ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A,
"invalid PostScript (post) table format" )
- FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \
+ FT_ERRORDEF_( Invalid_Post_Table, 0x9B,
"invalid PostScript (post) table" )
/* CFF, CID, and Type 1 errors */
- FT_ERRORDEF_( Syntax_Error, 0xA0, \
+ FT_ERRORDEF_( Syntax_Error, 0xA0,
"opcode syntax error" )
- FT_ERRORDEF_( Stack_Underflow, 0xA1, \
+ FT_ERRORDEF_( Stack_Underflow, 0xA1,
"argument stack underflow" )
- FT_ERRORDEF_( Ignore, 0xA2, \
+ FT_ERRORDEF_( Ignore, 0xA2,
"ignore" )
- FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \
+ FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3,
"no Unicode glyph name found" )
- FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \
- "glyph to big for hinting" )
+ FT_ERRORDEF_( Glyph_Too_Big, 0xA4,
+ "glyph too big for hinting" )
/* BDF errors */
- FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \
+ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0,
"`STARTFONT' field missing" )
- FT_ERRORDEF_( Missing_Font_Field, 0xB1, \
+ FT_ERRORDEF_( Missing_Font_Field, 0xB1,
"`FONT' field missing" )
- FT_ERRORDEF_( Missing_Size_Field, 0xB2, \
+ FT_ERRORDEF_( Missing_Size_Field, 0xB2,
"`SIZE' field missing" )
- FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3, \
+ FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3,
"`FONTBOUNDINGBOX' field missing" )
- FT_ERRORDEF_( Missing_Chars_Field, 0xB4, \
+ FT_ERRORDEF_( Missing_Chars_Field, 0xB4,
"`CHARS' field missing" )
- FT_ERRORDEF_( Missing_Startchar_Field, 0xB5, \
+ FT_ERRORDEF_( Missing_Startchar_Field, 0xB5,
"`STARTCHAR' field missing" )
- FT_ERRORDEF_( Missing_Encoding_Field, 0xB6, \
+ FT_ERRORDEF_( Missing_Encoding_Field, 0xB6,
"`ENCODING' field missing" )
- FT_ERRORDEF_( Missing_Bbx_Field, 0xB7, \
+ FT_ERRORDEF_( Missing_Bbx_Field, 0xB7,
"`BBX' field missing" )
- FT_ERRORDEF_( Bbx_Too_Big, 0xB8, \
+ FT_ERRORDEF_( Bbx_Too_Big, 0xB8,
"`BBX' too big" )
- FT_ERRORDEF_( Corrupted_Font_Header, 0xB9, \
+ FT_ERRORDEF_( Corrupted_Font_Header, 0xB9,
"Font header corrupted or missing fields" )
- FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA, \
+ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA,
"Font glyphs corrupted or missing fields" )
+ /* */
+
/* END */
diff --git a/include/freetype/fterrors.h b/include/freetype/fterrors.h
index 0fa3e4d..0507b9a 100644
--- a/include/freetype/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
/* */
/* FreeType error code handling (specification). */
/* */
-/* Copyright 1996-2002, 2004, 2007, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,68 +18,86 @@
/*************************************************************************/
/* */
- /* This special header file is used to define the handling of FT2 */
- /* enumeration constants. It can also be used to generate error message */
- /* strings with a small macro trick explained below. */
+ /* <Section> */
+ /* error_enumerations */
/* */
- /* I - Error Formats */
- /* ----------------- */
+ /* <Title> */
+ /* Error Enumerations */
+ /* */
+ /* <Abstract> */
+ /* How to handle errors and error strings. */
+ /* */
+ /* <Description> */
+ /* The header file `fterrors.h' (which is automatically included by */
+ /* `freetype.h' defines the handling of FreeType's enumeration */
+ /* constants. It can also be used to generate error message strings */
+ /* with a small macro trick explained below. */
+ /* */
+ /* *Error* *Formats* */
/* */
/* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */
- /* defined in ftoption.h in order to make the higher byte indicate */
+ /* defined in `ftoption.h' in order to make the higher byte indicate */
/* the module where the error has happened (this is not compatible */
- /* with standard builds of FreeType 2). See the file `ftmoderr.h' for */
- /* more details. */
+ /* with standard builds of FreeType 2, however). See the file */
+ /* `ftmoderr.h' for more details. */
/* */
+ /* *Error* *Message* *Strings* */
/* */
- /* II - Error Message strings */
- /* -------------------------- */
- /* */
- /* The error definitions below are made through special macros that */
- /* allow client applications to build a table of error message strings */
- /* if they need it. The strings are not included in a normal build of */
- /* FreeType 2 to save space (most client applications do not use */
- /* them). */
+ /* Error definitions are set up with special macros that allow client */
+ /* applications to build a table of error message strings. The */
+ /* strings are not included in a normal build of FreeType 2 to */
+ /* save space (most client applications do not use them). */
/* */
/* To do so, you have to define the following macros before including */
- /* this file: */
- /* */
- /* FT_ERROR_START_LIST :: */
- /* This macro is called before anything else to define the start of */
- /* the error list. It is followed by several FT_ERROR_DEF calls */
- /* (see below). */
- /* */
- /* FT_ERROR_DEF( e, v, s ) :: */
- /* This macro is called to define one single error. */
- /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */
- /* `v' is the error numerical value. */
- /* `s' is the corresponding error string. */
- /* */
- /* FT_ERROR_END_LIST :: */
- /* This macro ends the list. */
- /* */
- /* Additionally, you have to undefine __FTERRORS_H__ before #including */
/* this file. */
/* */
- /* Here is a simple example: */
+ /* { */
+ /* FT_ERROR_START_LIST */
+ /* } */
/* */
+ /* This macro is called before anything else to define the start of */
+ /* the error list. It is followed by several FT_ERROR_DEF calls. */
+ /* */
+ /* { */
+ /* FT_ERROR_DEF( e, v, s ) */
+ /* } */
+ /* */
+ /* This macro is called to define one single error. `e' is the error */
+ /* code identifier (e.g., `Invalid_Argument'), `v' is the error's */
+ /* numerical value, and `s' is the corresponding error string. */
+ /* */
+ /* { */
+ /* FT_ERROR_END_LIST */
+ /* } */
+ /* */
+ /* This macro ends the list. */
+ /* */
+ /* Additionally, you have to undefine `__FTERRORS_H__' before */
+ /* #including this file. */
+ /* */
+ /* Here is a simple example. */
+ /* */
+ /* { */
+ /* #undef __FTERRORS_H__ */
+ /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
+ /* #define FT_ERROR_START_LIST { */
+ /* #define FT_ERROR_END_LIST { 0, NULL } }; */
+ /* */
+ /* const struct */
/* { */
- /* #undef __FTERRORS_H__ */
- /* #define FT_ERRORDEF( e, v, s ) { e, s }, */
- /* #define FT_ERROR_START_LIST { */
- /* #define FT_ERROR_END_LIST { 0, 0 } }; */
+ /* int err_code; */
+ /* const char* err_msg; */
+ /* } ft_errors[] = */
/* */
- /* const struct */
- /* { */
- /* int err_code; */
- /* const char* err_msg; */
- /* } ft_errors[] = */
+ /* #include FT_ERRORS_H */
+ /* } */
/* */
- /* #include FT_ERRORS_H */
- /* } */
+ /* Note that `FT_Err_Ok' is _not_ defined with `FT_ERRORDEF' but with */
+ /* `FT_NOERRORDEF'; it is always zero. */
/* */
/*************************************************************************/
+ /* */
#ifndef __FTERRORS_H__
#define __FTERRORS_H__
diff --git a/include/freetype/ftxf86.h b/include/freetype/ftfntfmt.h
similarity index 79%
rename from include/freetype/ftxf86.h
rename to include/freetype/ftfntfmt.h
index 8c68afd..1f8ff28 100644
--- a/include/freetype/ftxf86.h
+++ b/include/freetype/ftfntfmt.h
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* ftxf86.h */
+/* ftfntfmt.h */
/* */
-/* Support functions for X11. */
+/* Support functions for font formats. */
/* */
-/* Copyright 2002, 2003, 2004, 2006, 2007 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __FTXF86_H__
-#define __FTXF86_H__
+#ifndef __FTFNTFMT_H__
+#define __FTFNTFMT_H__
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -49,22 +49,20 @@
/* however, there are special cases (like in PDF devices) where it is */
/* important to differentiate, in spite of FreeType's uniform API. */
/* */
- /* This function is in the X11/xf86 namespace for historical reasons */
- /* and in no way depends on that windowing system. */
- /* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Get_X11_Font_Format */
+ /* FT_Get_Font_Format */
/* */
/* <Description> */
- /* Return a string describing the format of a given face, using values */
- /* which can be used as an X11 FONT_PROPERTY. Possible values are */
- /* `TrueType', `Type~1', `BDF', `PCF', `Type~42', `CID~Type~1', `CFF', */
- /* `PFR', and `Windows~FNT'. */
+ /* Return a string describing the format of a given face. Possible */
+ /* values are `TrueType', `Type~1', `BDF', `PCF', `Type~42', */
+ /* `CID~Type~1', `CFF', `PFR', and `Windows~FNT'. */
+ /* */
+ /* The return value is suitable to be used as an X11 FONT_PROPERTY. */
/* */
/* <Input> */
/* face :: */
@@ -73,11 +71,22 @@
/* <Return> */
/* Font format string. NULL in case of error. */
/* */
+ /* <Note> */
+ /* A deprecated name for the same function is */
+ /* `FT_Get_X11_Font_Format'. */
+ /* */
+ FT_EXPORT( const char* )
+ FT_Get_Font_Format( FT_Face face );
+
+
+ /* deprecated */
FT_EXPORT( const char* )
FT_Get_X11_Font_Format( FT_Face face );
- /* */
+
+ /* */
+
FT_END_HEADER
-#endif /* __FTXF86_H__ */
+#endif /* __FTFNTFMT_H__ */
diff --git a/include/freetype/ftgasp.h b/include/freetype/ftgasp.h
index 453d4fa..9a9b632 100644
--- a/include/freetype/ftgasp.h
+++ b/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
/* */
/* Access of TrueType's `gasp' table (specification). */
/* */
-/* Copyright 2007, 2008, 2011 by */
+/* Copyright 2007-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -120,7 +120,8 @@
FT_Get_Gasp( FT_Face face,
FT_UInt ppem );
-/* */
+ /* */
+
#endif /* _FT_GASP_H_ */
diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index 31dc331..803ad39 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (specification). */
/* */
-/* Copyright 1996-2003, 2006, 2008, 2009, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -325,22 +325,8 @@
} FT_Glyph_BBox_Mode;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* ft_glyph_bbox_xxx */
- /* */
- /* <Description> */
- /* These constants are deprecated. Use the corresponding */
- /* @FT_Glyph_BBox_Mode values instead. */
- /* */
- /* <Values> */
- /* ft_glyph_bbox_unscaled :: See @FT_GLYPH_BBOX_UNSCALED. */
- /* ft_glyph_bbox_subpixels :: See @FT_GLYPH_BBOX_SUBPIXELS. */
- /* ft_glyph_bbox_gridfit :: See @FT_GLYPH_BBOX_GRIDFIT. */
- /* ft_glyph_bbox_truncate :: See @FT_GLYPH_BBOX_TRUNCATE. */
- /* ft_glyph_bbox_pixels :: See @FT_GLYPH_BBOX_PIXELS. */
- /* */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Glyph_BBox_Mode' values instead */
#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED
#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS
#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT
@@ -358,17 +344,17 @@
/* outline's points, including Bézier control points. Though it */
/* coincides with the exact bounding box for most glyphs, it can be */
/* slightly larger in some situations (like when rotating an outline */
- /* which contains Bézier outside arcs). */
+ /* that contains Bézier outside arcs). */
/* */
/* Computing the control box is very fast, while getting the bounding */
/* box can take much more time as it needs to walk over all segments */
/* and arcs in the outline. To get the latter, you can use the */
- /* `ftbbox' component which is dedicated to this single task. */
+ /* `ftbbox' component, which is dedicated to this single task. */
/* */
/* <Input> */
/* glyph :: A handle to the source glyph object. */
/* */
- /* mode :: The mode which indicates how to interpret the returned */
+ /* mode :: The mode that indicates how to interpret the returned */
/* bounding box values. */
/* */
/* <Output> */
@@ -388,7 +374,7 @@
/* @FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get */
/* reasonable values for the CBox it is necessary to load the glyph */
/* at a large ppem value (so that the hinting instructions can */
- /* properly shift and scale the subglyphs), then extracting the CBox */
+ /* properly shift and scale the subglyphs), then extracting the CBox, */
/* which can be eventually converted back to font units. */
/* */
/* Note that the maximum coordinates are exclusive, which means that */
@@ -603,7 +589,6 @@
FT_EXPORT( FT_Error )
FT_Matrix_Invert( FT_Matrix* matrix );
-
/* */
diff --git a/include/freetype/ftgxval.h b/include/freetype/ftgxval.h
index 497015c..0e9ac1d 100644
--- a/include/freetype/ftgxval.h
+++ b/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
/* */
-/* Copyright 2004, 2005, 2006 by */
+/* Copyright 2004-2015 by */
/* Masatake YAMATO, Redhat K.K, */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
@@ -57,9 +57,19 @@
/* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */
/* trak, prop, lcar). */
/* */
+ /* <Order> */
+ /* FT_TrueTypeGX_Validate */
+ /* FT_TrueTypeGX_Free */
+ /* */
+ /* FT_ClassicKern_Validate */
+ /* FT_ClassicKern_Free */
+ /* */
+ /* FT_VALIDATE_GX_LENGTH */
+ /* FT_VALIDATE_GXXXX */
+ /* FT_VALIDATE_CKERNXXX */
+ /* */
/*************************************************************************/
-
/*************************************************************************/
/* */
/* */
@@ -171,8 +181,6 @@
FT_VALIDATE_lcar )
- /* */
-
/**********************************************************************
*
* @function:
@@ -180,7 +188,7 @@
*
* @description:
* Validate various TrueTypeGX tables to assure that all offsets and
- * indices are valid. The idea is that a higher-level library which
+ * indices are valid. The idea is that a higher-level library that
* actually does the text layout can access those tables without
* error checking (which can be quite time consuming).
*
@@ -189,7 +197,7 @@
* A handle to the input face.
*
* validation_flags ::
- * A bit field which specifies the tables to be validated. See
+ * A bit field that specifies the tables to be validated. See
* @FT_VALIDATE_GXXXX for possible values.
*
* table_length ::
@@ -221,8 +229,6 @@
FT_UInt table_length );
- /* */
-
/**********************************************************************
*
* @function:
@@ -248,8 +254,6 @@
FT_Bytes table );
- /* */
-
/**********************************************************************
*
* @enum:
@@ -277,8 +281,6 @@
#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
- /* */
-
/**********************************************************************
*
* @function:
@@ -286,7 +288,7 @@
*
* @description:
* Validate classic (16-bit format) kern table to assure that the offsets
- * and indices are valid. The idea is that a higher-level library which
+ * and indices are valid. The idea is that a higher-level library that
* actually does the text layout can access those tables without error
* checking (which can be quite time consuming).
*
@@ -299,7 +301,7 @@
* A handle to the input face.
*
* validation_flags ::
- * A bit field which specifies the dialect to be validated. See
+ * A bit field that specifies the dialect to be validated. See
* @FT_VALIDATE_CKERNXXX for possible values.
*
* @output:
@@ -320,8 +322,6 @@
FT_Bytes *ckern_table );
- /* */
-
/**********************************************************************
*
* @function:
@@ -346,8 +346,7 @@
FT_ClassicKern_Free( FT_Face face,
FT_Bytes table );
-
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftgzip.h b/include/freetype/ftgzip.h
index acbc4f0..b3a532d 100644
--- a/include/freetype/ftgzip.h
+++ b/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
/* */
/* Gzip-compressed stream support. */
/* */
-/* Copyright 2002, 2003, 2004, 2006 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -91,7 +91,53 @@
FT_Stream_OpenGzip( FT_Stream stream,
FT_Stream source );
- /* */
+
+ /************************************************************************
+ *
+ * @function:
+ * FT_Gzip_Uncompress
+ *
+ * @description:
+ * Decompress a zipped input buffer into an output buffer. This function
+ * is modeled after zlib's `uncompress' function.
+ *
+ * @input:
+ * memory ::
+ * A FreeType memory handle.
+ *
+ * input ::
+ * The input buffer.
+ *
+ * input_len ::
+ * The length of the input buffer.
+ *
+ * @output:
+ * output::
+ * The output buffer.
+ *
+ * @inout:
+ * output_len ::
+ * Before calling the function, this is the the total size of the
+ * output buffer, which must be large enough to hold the entire
+ * uncompressed data (so the size of the uncompressed data must be
+ * known in advance). After calling the function, `output_len' is the
+ * size of the used data in `output'.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function may return `FT_Err_Unimplemented_Feature' if your build
+ * of FreeType was not compiled with zlib support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Gzip_Uncompress( FT_Memory memory,
+ FT_Byte* output,
+ FT_ULong* output_len,
+ const FT_Byte* input,
+ FT_ULong input_len );
+
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 3b826b1..82f284c 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
/* FreeType glyph image formats and default raster interface */
/* (specification). */
/* */
-/* Copyright 1996-2010, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -193,67 +193,14 @@
} FT_Pixel_Mode;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* ft_pixel_mode_xxx */
- /* */
- /* <Description> */
- /* A list of deprecated constants. Use the corresponding */
- /* @FT_Pixel_Mode values instead. */
- /* */
- /* <Values> */
- /* ft_pixel_mode_none :: See @FT_PIXEL_MODE_NONE. */
- /* ft_pixel_mode_mono :: See @FT_PIXEL_MODE_MONO. */
- /* ft_pixel_mode_grays :: See @FT_PIXEL_MODE_GRAY. */
- /* ft_pixel_mode_pal2 :: See @FT_PIXEL_MODE_GRAY2. */
- /* ft_pixel_mode_pal4 :: See @FT_PIXEL_MODE_GRAY4. */
- /* */
+ /* these constants are deprecated; use the corresponding `FT_Pixel_Mode' */
+ /* values instead. */
#define ft_pixel_mode_none FT_PIXEL_MODE_NONE
#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO
#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY
#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2
#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4
- /* */
-
-#if 0
-
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* FT_Palette_Mode */
- /* */
- /* <Description> */
- /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */
- /* */
- /* An enumeration type to describe the format of a bitmap palette, */
- /* used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */
- /* */
- /* <Values> */
- /* ft_palette_mode_rgb :: The palette is an array of 3-byte RGB */
- /* records. */
- /* */
- /* ft_palette_mode_rgba :: The palette is an array of 4-byte RGBA */
- /* records. */
- /* */
- /* <Note> */
- /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */
- /* FreeType, these types are not handled by the library itself. */
- /* */
- typedef enum FT_Palette_Mode_
- {
- ft_palette_mode_rgb = 0,
- ft_palette_mode_rgba,
-
- ft_palette_mode_max /* do not remove */
-
- } FT_Palette_Mode;
-
- /* */
-
-#endif
-
/*************************************************************************/
/* */
@@ -311,20 +258,15 @@
/* field is intended for paletted pixel modes. Not */
/* used currently. */
/* */
- /* <Note> */
- /* For now, the only pixel modes supported by FreeType are mono and */
- /* grays. However, drivers might be added in the future to support */
- /* more `colorful' options. */
- /* */
typedef struct FT_Bitmap_
{
- int rows;
- int width;
+ unsigned int rows;
+ unsigned int width;
int pitch;
unsigned char* buffer;
- short num_grays;
- char pixel_mode;
- char palette_mode;
+ unsigned short num_grays;
+ unsigned char pixel_mode;
+ unsigned char palette_mode;
void* palette;
} FT_Bitmap;
@@ -381,7 +323,7 @@
/* */
/* flags :: A set of bit flags used to characterize the outline */
/* and give hints to the scan-converter and hinter on */
- /* how to convert/grid-fit it. See @FT_OUTLINE_FLAGS. */
+ /* how to convert/grid-fit it. See @FT_OUTLINE_XXX. */
/* */
/* <Note> */
/* The B/W rasterizer only checks bit~2 in the `tags' array for the */
@@ -402,6 +344,8 @@
} FT_Outline;
+ /* */
+
/* Following limits must be consistent with */
/* FT_Outline.{n_contours,n_points} */
#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX
@@ -411,7 +355,7 @@
/*************************************************************************/
/* */
/* <Enum> */
- /* FT_OUTLINE_FLAGS */
+ /* FT_OUTLINE_XXX */
/* */
/* <Description> */
/* A list of bit-field constants use for the flags in an outline's */
@@ -492,24 +436,8 @@
#define FT_OUTLINE_SINGLE_PASS 0x200
- /*************************************************************************
- *
- * @enum:
- * ft_outline_flags
- *
- * @description:
- * These constants are deprecated. Please use the corresponding
- * @FT_OUTLINE_FLAGS values.
- *
- * @values:
- * ft_outline_none :: See @FT_OUTLINE_NONE.
- * ft_outline_owner :: See @FT_OUTLINE_OWNER.
- * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL.
- * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL.
- * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS.
- * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION.
- * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS.
- */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_OUTLINE_XXX' values instead */
#define ft_outline_none FT_OUTLINE_NONE
#define ft_outline_owner FT_OUTLINE_OWNER
#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL
@@ -555,7 +483,7 @@
/* <Input> */
/* to :: A pointer to the target point of the `move to'. */
/* */
- /* user :: A typeless pointer which is passed from the caller of the */
+ /* user :: A typeless pointer, which is passed from the caller of the */
/* decomposition function. */
/* */
/* <Return> */
@@ -582,7 +510,7 @@
/* <Input> */
/* to :: A pointer to the target point of the `line to'. */
/* */
- /* user :: A typeless pointer which is passed from the caller of the */
+ /* user :: A typeless pointer, which is passed from the caller of the */
/* decomposition function. */
/* */
/* <Return> */
@@ -613,7 +541,7 @@
/* */
/* to :: A pointer to the target end point of the conic arc. */
/* */
- /* user :: A typeless pointer which is passed from the caller of */
+ /* user :: A typeless pointer, which is passed from the caller of */
/* the decomposition function. */
/* */
/* <Return> */
@@ -645,7 +573,7 @@
/* */
/* to :: A pointer to the target end point. */
/* */
- /* user :: A typeless pointer which is passed from the caller of */
+ /* user :: A typeless pointer, which is passed from the caller of */
/* the decomposition function. */
/* */
/* <Return> */
@@ -796,22 +724,8 @@
} FT_Glyph_Format;
- /*************************************************************************/
- /* */
- /* <Enum> */
- /* ft_glyph_format_xxx */
- /* */
- /* <Description> */
- /* A list of deprecated constants. Use the corresponding */
- /* @FT_Glyph_Format values instead. */
- /* */
- /* <Values> */
- /* ft_glyph_format_none :: See @FT_GLYPH_FORMAT_NONE. */
- /* ft_glyph_format_composite :: See @FT_GLYPH_FORMAT_COMPOSITE. */
- /* ft_glyph_format_bitmap :: See @FT_GLYPH_FORMAT_BITMAP. */
- /* ft_glyph_format_outline :: See @FT_GLYPH_FORMAT_OUTLINE. */
- /* ft_glyph_format_plotter :: See @FT_GLYPH_FORMAT_PLOTTER. */
- /* */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Glyph_Format' values instead. */
#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE
#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE
#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
@@ -836,8 +750,8 @@
/* a a bitmap. This section contains the public API for rasters. */
/* */
/* Note that in FreeType 2, all rasters are now encapsulated within */
- /* specific modules called `renderers'. See `freetype/ftrender.h' for */
- /* more details on renderers. */
+ /* specific modules called `renderers'. See `ftrender.h' for more */
+ /* details on renderers. */
/* */
/*************************************************************************/
@@ -856,6 +770,21 @@
/* <Description> */
/* This section contains technical definitions. */
/* */
+ /* <Order> */
+ /* FT_Raster */
+ /* FT_Span */
+ /* FT_SpanFunc */
+ /* */
+ /* FT_Raster_Params */
+ /* FT_RASTER_FLAG_XXX */
+ /* */
+ /* FT_Raster_NewFunc */
+ /* FT_Raster_DoneFunc */
+ /* FT_Raster_ResetFunc */
+ /* FT_Raster_SetModeFunc */
+ /* FT_Raster_RenderFunc */
+ /* FT_Raster_Funcs */
+ /* */
/*************************************************************************/
@@ -865,8 +794,8 @@
/* FT_Raster */
/* */
/* <Description> */
- /* A handle (pointer) to a raster object. Each object can be used */
- /* independently to convert an outline into a bitmap or pixmap. */
+ /* An opaque handle (pointer) to a raster object. Each object can be */
+ /* used independently to convert an outline into a bitmap or pixmap. */
/* */
typedef struct FT_RasterRec_* FT_Raster;
@@ -877,8 +806,8 @@
/* FT_Span */
/* */
/* <Description> */
- /* A structure used to model a single span of gray (or black) pixels */
- /* when rendering a monochrome or anti-aliased bitmap. */
+ /* A structure used to model a single span of gray pixels when */
+ /* rendering an anti-aliased bitmap. */
/* */
/* <Fields> */
/* x :: The span's horizontal start position. */
@@ -886,13 +815,12 @@
/* len :: The span's length in pixels. */
/* */
/* coverage :: The span color/coverage, ranging from 0 (background) */
- /* to 255 (foreground). Only used for anti-aliased */
- /* rendering. */
+ /* to 255 (foreground). */
/* */
/* <Note> */
/* This structure is used by the span drawing callback type named */
- /* @FT_SpanFunc which takes the y~coordinate of the span as a */
- /* a parameter. */
+ /* @FT_SpanFunc that takes the y~coordinate of the span as a */
+ /* parameter. */
/* */
/* The coverage value is always between 0 and 255. If you want less */
/* gray values, the callback function has to reduce them. */
@@ -957,22 +885,7 @@
/* FT_Raster_BitTest_Func */
/* */
/* <Description> */
- /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */
- /* */
- /* A function used as a call-back by the monochrome scan-converter */
- /* to test whether a given target pixel is already set to the drawing */
- /* `color'. These tests are crucial to implement drop-out control */
- /* per-se the TrueType spec. */
- /* */
- /* <Input> */
- /* y :: The pixel's y~coordinate. */
- /* */
- /* x :: The pixel's x~coordinate. */
- /* */
- /* user :: User-supplied data that is passed to the callback. */
- /* */
- /* <Return> */
- /* 1~if the pixel is `set', 0~otherwise. */
+ /* Deprecated, unimplemented. */
/* */
typedef int
(*FT_Raster_BitTest_Func)( int y,
@@ -986,21 +899,7 @@
/* FT_Raster_BitSet_Func */
/* */
/* <Description> */
- /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */
- /* */
- /* A function used as a call-back by the monochrome scan-converter */
- /* to set an individual target pixel. This is crucial to implement */
- /* drop-out control according to the TrueType specification. */
- /* */
- /* <Input> */
- /* y :: The pixel's y~coordinate. */
- /* */
- /* x :: The pixel's x~coordinate. */
- /* */
- /* user :: User-supplied data that is passed to the callback. */
- /* */
- /* <Return> */
- /* 1~if the pixel is `set', 0~otherwise. */
+ /* Deprecated, unimplemented. */
/* */
typedef void
(*FT_Raster_BitSet_Func)( int y,
@@ -1034,8 +933,8 @@
/* pixmap's buffer _must_ be zeroed before */
/* rendering. */
/* */
- /* Note that for now, direct rendering is */
- /* only possible with anti-aliased glyphs. */
+ /* Direct rendering is only possible with */
+ /* anti-aliased glyphs. */
/* */
/* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */
/* rendering mode. If set, the output will */
@@ -1053,7 +952,8 @@
#define FT_RASTER_FLAG_DIRECT 0x2
#define FT_RASTER_FLAG_CLIP 0x4
- /* deprecated */
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_RASTER_FLAG_XXX' values instead */
#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT
#define ft_raster_flag_aa FT_RASTER_FLAG_AA
#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT
@@ -1079,11 +979,11 @@
/* */
/* gray_spans :: The gray span drawing callback. */
/* */
- /* black_spans :: The black span drawing callback. UNIMPLEMENTED! */
+ /* black_spans :: Unused. */
/* */
- /* bit_test :: The bit test callback. UNIMPLEMENTED! */
+ /* bit_test :: Unused. */
/* */
- /* bit_set :: The bit set callback. UNIMPLEMENTED! */
+ /* bit_set :: Unused. */
/* */
/* user :: User-supplied data that is passed to each drawing */
/* callback. */
@@ -1100,15 +1000,9 @@
/* */
/* If the @FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */
/* raster will call the `gray_spans' callback to draw gray pixel */
- /* spans, in the case of an aa glyph bitmap, it will call */
- /* `black_spans', and `bit_test' and `bit_set' in the case of a */
- /* monochrome bitmap. This allows direct composition over a */
- /* pre-existing bitmap through user-provided callbacks to perform the */
- /* span drawing/composition. */
- /* */
- /* Note that the `bit_test' and `bit_set' callbacks are required when */
- /* rendering a monochrome bitmap, as they are crucial to implement */
- /* correct drop-out control as defined in the TrueType specification. */
+ /* spans. This allows direct composition over a pre-existing bitmap */
+ /* through user-provided callbacks to perform the span drawing and */
+ /* composition. Not supported by the monochrome rasterizer. */
/* */
typedef struct FT_Raster_Params_
{
@@ -1116,9 +1010,9 @@
const void* source;
int flags;
FT_SpanFunc gray_spans;
- FT_SpanFunc black_spans; /* doesn't work! */
- FT_Raster_BitTest_Func bit_test; /* doesn't work! */
- FT_Raster_BitSet_Func bit_set; /* doesn't work! */
+ FT_SpanFunc black_spans; /* unused */
+ FT_Raster_BitTest_Func bit_test; /* unused */
+ FT_Raster_BitSet_Func bit_set; /* unused */
void* user;
FT_BBox clip_box;
@@ -1179,10 +1073,10 @@
/* FT_Raster_ResetFunc */
/* */
/* <Description> */
- /* FreeType provides an area of memory called the `render pool', */
- /* available to all registered rasters. This pool can be freely used */
- /* during a given scan-conversion but is shared by all rasters. Its */
- /* content is thus transient. */
+ /* FreeType used to provide an area of memory called the `render */
+ /* pool' available to all registered rasters. This was not thread */
+ /* safe however and now FreeType never allocates this pool. NULL */
+ /* is always passed in as pool_base. */
/* */
/* This function is called each time the render pool changes, or just */
/* after a new raster object is created. */
@@ -1195,10 +1089,9 @@
/* pool_size :: The size in bytes of the render pool. */
/* */
/* <Note> */
- /* Rasters can ignore the render pool and rely on dynamic memory */
+ /* Rasters should ignore the render pool and rely on dynamic or stack */
/* allocation if they want to (a handle to the memory allocator is */
- /* passed to the raster constructor). However, this is not */
- /* recommended for efficiency purposes. */
+ /* passed to the raster constructor). */
/* */
typedef void
(*FT_Raster_ResetFunc)( FT_Raster raster,
@@ -1265,7 +1158,7 @@
/* XXX: For now, the standard raster doesn't support direct */
/* composition but this should change for the final release (see */
/* the files `demos/src/ftgrays.c' and `demos/src/ftgrays2.c' */
- /* for examples of distinct implementations which support direct */
+ /* for examples of distinct implementations that support direct */
/* composition). */
/* */
typedef int
@@ -1305,7 +1198,6 @@
} FT_Raster_Funcs;
-
/* */
diff --git a/include/freetype/ftincrem.h b/include/freetype/ftincrem.h
index aaf689f..840af25 100644
--- a/include/freetype/ftincrem.h
+++ b/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
/* */
/* FreeType incremental loading (specification). */
/* */
-/* Copyright 2002, 2003, 2006, 2007, 2008, 2010 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -45,7 +45,7 @@
* @description:
* This section contains various functions used to perform so-called
* `incremental' glyph loading. This is a mode where all glyphs loaded
- * from a given @FT_Face are provided by the client application,
+ * from a given @FT_Face are provided by the client application.
*
* Apart from that, all other tables are loaded normally from the font
* file. This mode is useful when FreeType is used within another
@@ -345,6 +345,7 @@
/* */
+
FT_END_HEADER
#endif /* __FTINCREM_H__ */
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 8b253f1..a9dd3ea 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
/* FreeType API for color filtering of subpixel bitmap glyphs */
/* (specification). */
/* */
-/* Copyright 2006, 2007, 2008, 2010 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -41,56 +41,78 @@
* LCD Filtering
*
* @abstract:
- * Reduce color fringes of LCD-optimized bitmaps.
+ * Reduce color fringes of subpixel-rendered bitmaps.
*
* @description:
- * The @FT_Library_SetLcdFilter API can be used to specify a low-pass
- * filter which is then applied to LCD-optimized bitmaps generated
- * through @FT_Render_Glyph. This is useful to reduce color fringes
- * which would occur with unfiltered rendering.
+ * Subpixel rendering exploits the color-striped structure of LCD
+ * pixels, increasing the available resolution in the direction of the
+ * stripe (usually horizontal RGB) by a factor of~3. Since these
+ * subpixels are color pixels, using them unfiltered creates severe
+ * color fringes. Use the @FT_Library_SetLcdFilter API to specify a
+ * low-pass filter, which is then applied to subpixel-rendered bitmaps
+ * generated through @FT_Render_Glyph. The filter sacrifices some of
+ * the higher resolution to reduce color fringes, making the glyph image
+ * slightly blurrier. Positional improvements will remain.
*
* Note that no filter is active by default, and that this function is
* *not* implemented in default builds of the library. You need to
* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
* in order to activate it.
*
- * FreeType generates alpha coverage maps, which are linear by nature.
- * For instance, the value 0x80 in bitmap representation means that
- * (within numerical precision) 0x80/0xff fraction of that pixel is
- * covered by the glyph's outline. The blending function for placing
- * text over a background is
+ * A filter should have two properties:
*
- * {
- * dst = alpha * src + (1 - alpha) * dst ,
- * }
+ * 1) It should be normalized, meaning the sum of the 5~components
+ * should be 256 (0x100). It is possible to go above or under this
+ * target sum, however: going under means tossing out contrast, going
+ * over means invoking clamping and thereby non-linearities that
+ * increase contrast somewhat at the expense of greater distortion
+ * and color-fringing. Contrast is better enhanced through stem
+ * darkening.
*
- * which is known as OVER. However, when calculating the output of the
- * OVER operator, the source colors should first be transformed to a
- * linear color space, then alpha blended in that space, and transformed
- * back to the output color space.
+ * 2) It should be color-balanced, meaning a filter `{~a, b, c, b, a~}'
+ * where a~+ b~=~c. It distributes the computed coverage for one
+ * subpixel to all subpixels equally, sacrificing some won resolution
+ * but drastically reducing color-fringing. Positioning improvements
+ * remain! Note that color-fringing can only really be minimized
+ * when using a color-balanced filter and alpha-blending the glyph
+ * onto a surface in linear space; see @FT_Render_Glyph.
*
- * When linear light blending is used, the default FIR5 filtering
- * weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as
- * they have been designed for black on white rendering while lacking
- * gamma correction. To preserve color neutrality, weights for a FIR5
- * filter should be chosen according to two free parameters `a' and `c',
- * and the FIR weights should be
+ * Regarding the form, a filter can be a `boxy' filter or a `beveled'
+ * filter. Boxy filters are sharper but are less forgiving of non-ideal
+ * gamma curves of a screen (viewing angles!), beveled filters are
+ * fuzzier but more tolerant.
*
- * {
- * [a - c, a + c, 2 * a, a + c, a - c] .
- * }
+ * Examples:
*
- * This formula generates equal weights for all the color primaries
- * across the filter kernel, which makes it colorless. One suggested
- * set of weights is
+ * - [0x10 0x40 0x70 0x40 0x10] is beveled and neither balanced nor
+ * normalized.
*
- * {
- * [0x10, 0x50, 0x60, 0x50, 0x10] ,
- * }
+ * - [0x1A 0x33 0x4D 0x33 0x1A] is beveled and balanced but not
+ * normalized.
*
- * where `a' has value 0x30 and `b' value 0x20. The weights in filter
- * may have a sum larger than 0x100, which increases coloration slightly
- * but also improves contrast.
+ * - [0x19 0x33 0x66 0x4c 0x19] is beveled and normalized but not
+ * balanced.
+ *
+ * - [0x00 0x4c 0x66 0x4c 0x00] is boxily beveled and normalized but not
+ * balanced.
+ *
+ * - [0x00 0x55 0x56 0x55 0x00] is boxy, normalized, and almost
+ * balanced.
+ *
+ * - [0x08 0x4D 0x56 0x4D 0x08] is beveled, normalized and, almost
+ * balanced.
+ *
+ * It is important to understand that linear alpha blending and gamma
+ * correction is critical for correctly rendering glyphs onto surfaces
+ * without artifacts and even more critical when subpixel rendering is
+ * involved.
+ *
+ * Each of the 3~alpha values (subpixels) is independently used to blend
+ * one color channel. That is, red alpha blends the red channel of the
+ * text color with the red channel of the background pixel. The
+ * distribution of density values by the color-balanced filter assumes
+ * alpha blending is done in linear space; only then color artifacts
+ * cancel out.
*/
@@ -111,10 +133,21 @@
* The default filter reduces color fringes considerably, at the cost
* of a slight blurriness in the output.
*
+ * It is a beveled, normalized, and color-balanced five-tap filter
+ * that is more forgiving to screens with non-ideal gamma curves and
+ * viewing angles. Note that while color-fringing is reduced, it can
+ * only be minimized by using linear alpha blending and gamma
+ * correction to render glyphs onto surfaces.
+ *
* FT_LCD_FILTER_LIGHT ::
- * The light filter is a variant that produces less blurriness at the
- * cost of slightly more color fringes than the default one. It might
- * be better, depending on taste, your monitor, or your personal vision.
+ * The light filter is a variant that is sharper at the cost of
+ * slightly more color fringes than the default one.
+ *
+ * It is a boxy, normalized, and color-balanced three-tap filter that
+ * is less forgiving to screens with non-ideal gamma curves and
+ * viewing angles. This filter works best when the rendering system
+ * uses linear alpha blending and gamma correction to render glyphs
+ * onto surfaces.
*
* FT_LCD_FILTER_LEGACY ::
* This filter corresponds to the original libXft color filter. It
@@ -126,14 +159,23 @@
* This filter is only provided for comparison purposes, and might be
* disabled or stay unsupported in the future.
*
+ * FT_LCD_FILTER_LEGACY1 ::
+ * For historical reasons, the FontConfig library returns a different
+ * enumeration value for legacy LCD filtering. To make code work that
+ * (incorrectly) forwards FontConfig's enumeration value to
+ * @FT_Library_SetLcdFilter without proper mapping, it is thus easiest
+ * to have another enumeration value, which is completely equal to
+ * `FT_LCD_FILTER_LEGACY'.
+ *
* @since:
- * 2.3.0
+ * 2.3.0 (`FT_LCD_FILTER_LEGACY1' since 2.6.2)
*/
typedef enum FT_LcdFilter_
{
FT_LCD_FILTER_NONE = 0,
FT_LCD_FILTER_DEFAULT = 1,
FT_LCD_FILTER_LIGHT = 2,
+ FT_LCD_FILTER_LEGACY1 = 3,
FT_LCD_FILTER_LEGACY = 16,
FT_LCD_FILTER_MAX /* do not remove */
@@ -208,9 +250,8 @@
* @description:
* Use this function to override the filter weights selected by
* @FT_Library_SetLcdFilter. By default, FreeType uses the quintuple
- * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x10,
- * 0x40, 0x70, 0x40, 0x10) for FT_LCD_FILTER_DEFAULT and
- * FT_LCD_FILTER_LEGACY.
+ * (0x00, 0x55, 0x56, 0x55, 0x00) for FT_LCD_FILTER_LIGHT, and (0x08,
+ * 0x4D, 0x56, 0x4D, 0x08) for FT_LCD_FILTER_DEFAULT.
*
* @input:
* library ::
diff --git a/include/freetype/ftlist.h b/include/freetype/ftlist.h
index bb6f7f1..12b48c7 100644
--- a/include/freetype/ftlist.h
+++ b/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
/* */
/* Generic list support for FreeType (specification). */
/* */
-/* Copyright 1996-2001, 2003, 2007, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -173,7 +173,7 @@
/* FT_List_Iterator */
/* */
/* <Description> */
- /* An FT_List iterator function which is called during a list parse */
+ /* An FT_List iterator function that is called during a list parse */
/* by @FT_List_Iterate. */
/* */
/* <Input> */
@@ -200,7 +200,7 @@
/* <Input> */
/* list :: A handle to the list. */
/* iterator :: An iterator function, called on each node of the list. */
- /* user :: A user-supplied field which is passed as the second */
+ /* user :: A user-supplied field that is passed as the second */
/* argument to the iterator. */
/* */
/* <Return> */
@@ -218,7 +218,7 @@
/* FT_List_Destructor */
/* */
/* <Description> */
- /* An @FT_List iterator function which is called during a list */
+ /* An @FT_List iterator function that is called during a list */
/* finalization by @FT_List_Finalize to destroy all elements in a */
/* given list. */
/* */
@@ -248,11 +248,11 @@
/* list :: A handle to the list. */
/* */
/* destroy :: A list destructor that will be applied to each element */
- /* of the list. */
+ /* of the list. Set this to NULL if not needed. */
/* */
- /* memory :: The current memory object which handles deallocation. */
+ /* memory :: The current memory object that handles deallocation. */
/* */
- /* user :: A user-supplied field which is passed as the last */
+ /* user :: A user-supplied field that is passed as the last */
/* argument to the destructor. */
/* */
/* <Note> */
@@ -265,7 +265,6 @@
FT_Memory memory,
void* user );
-
/* */
diff --git a/include/freetype/ftlzw.h b/include/freetype/ftlzw.h
index 00d4016..d3ec28e 100644
--- a/include/freetype/ftlzw.h
+++ b/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
/* */
/* LZW-compressed stream support. */
/* */
-/* Copyright 2004, 2006 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -88,7 +88,7 @@
FT_Stream_OpenLZW( FT_Stream stream,
FT_Stream source );
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftmac.h b/include/freetype/ftmac.h
index ab5bab5..14c55cf 100644
--- a/include/freetype/ftmac.h
+++ b/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
/* */
/* Additional Mac-specific API. */
/* */
-/* Copyright 1996-2001, 2004, 2006, 2007 by */
+/* Copyright 1996-2015 by */
/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,7 +18,7 @@
/***************************************************************************/
/* */
-/* NOTE: Include this file after <freetype/freetype.h> and after any */
+/* NOTE: Include this file after FT_FREETYPE_H and after any */
/* Mac-specific headers (because this header uses Mac types such as */
/* Handle, FSSpec, FSRef, etc.) */
/* */
@@ -168,7 +168,7 @@
/* */
/* <Description> */
/* Return a pathname of the disk file and face index for given font */
- /* name which is handled by ATS framework. */
+ /* name that is handled by ATS framework. */
/* */
/* <Input> */
/* fontName :: Mac OS name of the font in ATS framework. */
diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h
index 3aefb9e..96dd66e 100644
--- a/include/freetype/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Multiple Master font interface (specification). */
/* */
-/* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -95,8 +95,8 @@
/* */
/* num_designs :: Number of designs; should be normally 2^num_axis */
/* even though the Type~1 specification strangely */
- /* allows for intermediate designs to be present. This */
- /* number cannot exceed~16. */
+ /* allows for intermediate designs to be present. */
+ /* This number cannot exceed~16. */
/* */
/* axis :: A table of axis descriptors. */
/* */
@@ -196,16 +196,20 @@
/* number of designs). */
/* */
/* num_namedstyles :: The number of named styles; only meaningful for */
- /* GX which allows certain design coordinates to */
+ /* GX that allows certain design coordinates to */
/* have a string ID (in the `name' table) */
/* associated with them. The font can tell the */
/* user that, for example, Weight=1.5 is `Bold'. */
/* */
- /* axis :: A table of axis descriptors. */
+ /* axis :: An axis descriptor table. */
/* GX fonts contain slightly more data than MM. */
+ /* Memory management of this pointer is done */
+ /* internally by FreeType. */
/* */
- /* namedstyles :: A table of named styles. */
+ /* namedstyle :: A named style table. */
/* Only meaningful with GX. */
+ /* Memory management of this pointer is done */
+ /* internally by FreeType. */
/* */
typedef struct FT_MM_Var_
{
@@ -218,9 +222,6 @@
} FT_MM_Var;
- /* */
-
-
/*************************************************************************/
/* */
/* <Function> */
@@ -258,8 +259,8 @@
/* */
/* <Output> */
/* amaster :: The Multiple Masters/GX var descriptor. */
- /* Allocates a data structure, which the user must free */
- /* (a single call to FT_FREE will do it). */
+ /* Allocates a data structure, which the user must */
+ /* deallocate with `free' after use. */
/* */
/* <Return> */
/* FreeType error code. 0~means success. */
@@ -284,8 +285,10 @@
/* face :: A handle to the source face. */
/* */
/* <Input> */
- /* num_coords :: The number of design coordinates (must be equal to */
- /* the number of axes in the font). */
+ /* num_coords :: The number of available design coordinates. If it */
+ /* is larger than the number of axes, ignore the excess */
+ /* values. If it is smaller than the number of axes, */
+ /* use default values for the remaining axes. */
/* */
/* coords :: An array of design coordinates. */
/* */
@@ -311,8 +314,10 @@
/* face :: A handle to the source face. */
/* */
/* <Input> */
- /* num_coords :: The number of design coordinates (must be equal to */
- /* the number of axes in the font). */
+ /* num_coords :: The number of available design coordinates. If it */
+ /* is larger than the number of axes, ignore the excess */
+ /* values. If it is smaller than the number of axes, */
+ /* use default values for the remaining axes. */
/* */
/* coords :: An array of design coordinates. */
/* */
@@ -338,8 +343,10 @@
/* face :: A handle to the source face. */
/* */
/* <Input> */
- /* num_coords :: The number of design coordinates (must be equal to */
- /* the number of axes in the font). */
+ /* num_coords :: The number of available design coordinates. If it */
+ /* is larger than the number of axes, ignore the excess */
+ /* values. If it is smaller than the number of axes, */
+ /* use default values for the remaining axes. */
/* */
/* coords :: The design coordinates array (each element must be */
/* between 0 and 1.0). */
@@ -366,7 +373,6 @@
FT_UInt num_coords,
FT_Fixed* coords );
-
/* */
diff --git a/include/freetype/ftmodapi.h b/include/freetype/ftmodapi.h
index 8abffb5..89d9347 100644
--- a/include/freetype/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
/* */
/* FreeType modules public interface (specification). */
/* */
-/* Copyright 1996-2003, 2006, 2008-2010, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -63,7 +63,7 @@
/* psaux */
/* pshinter */
/* psnames */
- /* raster1, raster5 */
+ /* raster1 */
/* sfnt */
/* smooth, smooth-lcd, smooth-lcdv */
/* truetype */
@@ -75,6 +75,33 @@
/* */
/* Note that the FreeType Cache sub-system is not a FreeType module. */
/* */
+ /* <Order> */
+ /* FT_Module */
+ /* FT_Module_Constructor */
+ /* FT_Module_Destructor */
+ /* FT_Module_Requester */
+ /* FT_Module_Class */
+ /* */
+ /* FT_Add_Module */
+ /* FT_Get_Module */
+ /* FT_Remove_Module */
+ /* FT_Add_Default_Modules */
+ /* */
+ /* FT_Property_Set */
+ /* FT_Property_Get */
+ /* */
+ /* FT_New_Library */
+ /* FT_Done_Library */
+ /* FT_Reference_Library */
+ /* */
+ /* FT_Renderer */
+ /* FT_Renderer_Class */
+ /* */
+ /* FT_Get_Renderer */
+ /* FT_Set_Renderer */
+ /* */
+ /* FT_Set_Debug_Hook */
+ /* */
/*************************************************************************/
@@ -84,12 +111,14 @@
#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */
#define FT_MODULE_STYLER 8 /* this module is a styler */
-#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
+#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
/* scalable fonts */
-#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
+#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
/* support vector outlines */
-#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
+#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
/* own hinter */
+#define FT_MODULE_DRIVER_HINTS_LIGHTLY 0x800 /* the driver's hinter */
+ /* produces LIGHT hints */
/* deprecated values */
@@ -98,9 +127,10 @@
#define ft_module_hinter FT_MODULE_HINTER
#define ft_module_styler FT_MODULE_STYLER
-#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
-#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
-#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
+#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
+#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_hints_lightly FT_MODULE_DRIVER_HINTS_LIGHTLY
typedef FT_Pointer FT_Module_Interface;
@@ -298,7 +328,7 @@
* Note that only a few modules have properties.
*
* value ::
- * A generic pointer to a variable or structure which gives the new
+ * A generic pointer to a variable or structure that gives the new
* value of the property. The exact definition of `value' is
* dependent on the property; see the `Synopsis' subsection of the
* module's documentation.
@@ -364,7 +394,7 @@
*
* @inout:
* value ::
- * A generic pointer to a variable or structure which gives the
+ * A generic pointer to a variable or structure that gives the
* value of the property. The exact definition of `value' is
* dependent on the property; see the `Synopsis' subsection of the
* module's documentation.
@@ -418,7 +448,7 @@
/* @FT_Done_Library then only destroys a library if the counter is~1, */
/* otherwise it simply decrements the counter. */
/* */
- /* This function helps in managing life-cycles of structures which */
+ /* This function helps in managing life-cycles of structures that */
/* reference @FT_Library objects. */
/* */
/* <Input> */
@@ -442,7 +472,9 @@
/* <Description> */
/* This function is used to create a new FreeType library instance */
/* from a given memory object. It is thus possible to use libraries */
- /* with distinct memory allocators within the same program. */
+ /* with distinct memory allocators within the same program. Note, */
+ /* however, that the used @FT_Memory structure is expected to remain */
+ /* valid for the life of the @FT_Library object. */
/* */
/* Normally, you would call this function (followed by a call to */
/* @FT_Add_Default_Modules or a series of calls to @FT_Add_Module) */
@@ -491,7 +523,7 @@
FT_EXPORT( FT_Error )
FT_Done_Library( FT_Library library );
-/* */
+ /* */
typedef void
(*FT_DebugHook_Func)( void* arg );
@@ -584,7 +616,7 @@
* The library implements a bytecode interpreter that doesn't
* support the patented operations of the TrueType virtual machine.
*
- * Its main use is to load certain Asian fonts which position and
+ * Its main use is to load certain Asian fonts that position and
* scale glyph components with bytecode instructions. It produces
* bad output for most other fonts.
*
@@ -629,7 +661,6 @@
FT_EXPORT( FT_TrueTypeEngineType )
FT_Get_TrueType_Engine_Type( FT_Library library );
-
/* */
diff --git a/include/freetype/ftmoderr.h b/include/freetype/ftmoderr.h
index 5a27db1..9d7f981 100644
--- a/include/freetype/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
/* */
/* FreeType module error offsets (specification). */
/* */
-/* Copyright 2001-2005, 2010, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/ftotval.h b/include/freetype/ftotval.h
index 027f2e8..e744b71 100644
--- a/include/freetype/ftotval.h
+++ b/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating OpenType tables (specification). */
/* */
-/* Copyright 2004, 2005, 2006, 2007 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -58,6 +58,12 @@
/* This section contains the declaration of functions to validate */
/* some OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH). */
/* */
+ /* <Order> */
+ /* FT_OpenType_Validate */
+ /* FT_OpenType_Free */
+ /* */
+ /* FT_VALIDATE_OTXXX */
+ /* */
/*************************************************************************/
@@ -107,8 +113,6 @@
FT_VALIDATE_JSTF | \
FT_VALIDATE_MATH
- /* */
-
/**********************************************************************
*
* @function:
@@ -116,7 +120,7 @@
*
* @description:
* Validate various OpenType tables to assure that all offsets and
- * indices are valid. The idea is that a higher-level library which
+ * indices are valid. The idea is that a higher-level library that
* actually does the text layout can access those tables without
* error checking (which can be quite time consuming).
*
@@ -125,7 +129,7 @@
* A handle to the input face.
*
* validation_flags ::
- * A bit field which specifies the tables to be validated. See
+ * A bit field that specifies the tables to be validated. See
* @FT_VALIDATE_OTXXX for possible values.
*
* @output:
@@ -165,8 +169,6 @@
FT_Bytes *GSUB_table,
FT_Bytes *JSTF_table );
- /* */
-
/**********************************************************************
*
* @function:
@@ -191,8 +193,7 @@
FT_OpenType_Free( FT_Face face,
FT_Bytes table );
-
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h
index fd69f28..b6ec70d 100644
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
/* Support for the FT_Outline type used to store glyph shapes of */
/* most scalable font formats (specification). */
/* */
-/* Copyright 1996-2003, 2005-2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,7 +52,6 @@
/* */
/* <Order> */
/* FT_Outline */
- /* FT_OUTLINE_FLAGS */
/* FT_Outline_New */
/* FT_Outline_Done */
/* FT_Outline_Copy */
@@ -68,13 +67,17 @@
/* */
/* FT_Outline_Get_Bitmap */
/* FT_Outline_Render */
- /* */
/* FT_Outline_Decompose */
/* FT_Outline_Funcs */
- /* FT_Outline_MoveTo_Func */
- /* FT_Outline_LineTo_Func */
- /* FT_Outline_ConicTo_Func */
- /* FT_Outline_CubicTo_Func */
+ /* FT_Outline_MoveToFunc */
+ /* FT_Outline_LineToFunc */
+ /* FT_Outline_ConicToFunc */
+ /* FT_Outline_CubicToFunc */
+ /* */
+ /* FT_Orientation */
+ /* FT_Outline_Get_Orientation */
+ /* */
+ /* FT_OUTLINE_XXX */
/* */
/*************************************************************************/
@@ -97,7 +100,7 @@
/* operations. */
/* */
/* <InOut> */
- /* user :: A typeless pointer which is passed to each */
+ /* user :: A typeless pointer that is passed to each */
/* emitter during the decomposition. It can be */
/* used to store the state during the */
/* decomposition. */
@@ -105,6 +108,13 @@
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* A contour that contains a single point only is represented by a */
+ /* `move to' operation followed by `line to' to the same point. In */
+ /* most cases, it is best to filter this out before using the */
+ /* outline for stroking purposes (otherwise it would result in a */
+ /* visible dot when round caps are used). */
+ /* */
FT_EXPORT( FT_Error )
FT_Outline_Decompose( FT_Outline* outline,
const FT_Outline_Funcs* func_interface,
@@ -217,12 +227,12 @@
/* the outline's points, including Bézier control points. Though it */
/* coincides with the exact bounding box for most glyphs, it can be */
/* slightly larger in some situations (like when rotating an outline */
- /* which contains Bézier outside arcs). */
+ /* that contains Bézier outside arcs). */
/* */
/* Computing the control box is very fast, while getting the bounding */
/* box can take much more time as it needs to walk over all segments */
/* and arcs in the outline. To get the latter, you can use the */
- /* `ftbbox' component which is dedicated to this single task. */
+ /* `ftbbox' component, which is dedicated to this single task. */
/* */
/* <Input> */
/* outline :: A pointer to the source outline descriptor. */
@@ -344,10 +354,13 @@
/* */
/* { */
/* FT_Load_Glyph( face, index, FT_LOAD_DEFAULT ); */
- /* if ( face->slot->format == FT_GLYPH_FORMAT_OUTLINE ) */
- /* FT_Outline_Embolden( &face->slot->outline, strength ); */
+ /* if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) */
+ /* FT_Outline_Embolden( &face->glyph->outline, strength ); */
/* } */
/* */
+ /* To get meaningful results, font scaling values must be set with */
+ /* functions like @FT_Set_Char_Size before calling FT_Render_Glyph. */
+ /* */
FT_EXPORT( FT_Error )
FT_Outline_Embolden( FT_Outline* outline,
FT_Pos strength );
@@ -525,9 +538,11 @@
*
* @description:
* This function analyzes a glyph outline and tries to compute its
- * fill orientation (see @FT_Orientation). This is done by computing
- * the direction of each global horizontal and/or vertical extrema
- * within the outline.
+ * fill orientation (see @FT_Orientation). This is done by integrating
+ * the total area covered by the outline. The positive integral
+ * corresponds to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT
+ * is returned. The negative integral corresponds to the counter-clockwise
+ * orientation and @FT_ORIENTATION_TRUETYPE is returned.
*
* Note that this will return @FT_ORIENTATION_TRUETYPE for empty
* outlines.
@@ -543,7 +558,6 @@
FT_EXPORT( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline );
-
/* */
diff --git a/include/freetype/ftpfr.h b/include/freetype/ftpfr.h
index 0b7b7d4..a1c02a2 100644
--- a/include/freetype/ftpfr.h
+++ b/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing PFR-specific data (specification only). */
/* */
-/* Copyright 2002, 2003, 2004, 2006, 2008, 2009 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -161,7 +161,7 @@
FT_UInt gindex,
FT_Pos *aadvance );
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftrender.h b/include/freetype/ftrender.h
index dd0229b..ec8da70 100644
--- a/include/freetype/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
/* */
/* FreeType renderer modules public interface (specification). */
/* */
-/* Copyright 1996-2001, 2005, 2006, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -212,13 +212,8 @@
/* */
/* This doesn't change the current renderer for other formats. */
/* */
- /* Currently, only the B/W renderer, if compiled with */
- /* FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels */
- /* anti-aliasing mode; this option must be set directly in */
- /* `ftraster.c' and is undefined by default) accepts a single tag */
- /* `pal5' to set its gray palette as a character string with */
- /* 5~elements. Consequently, the third and fourth argument are zero */
- /* normally. */
+ /* Currently, no FreeType renderer module uses `parameters'; you */
+ /* should thus always pass NULL as the value. */
/* */
FT_EXPORT( FT_Error )
FT_Set_Renderer( FT_Library library,
@@ -226,7 +221,6 @@
FT_UInt num_params,
FT_Parameter* parameters );
-
/* */
diff --git a/include/freetype/ftsizes.h b/include/freetype/ftsizes.h
index 3e548cc..bef8424 100644
--- a/include/freetype/ftsizes.h
+++ b/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
/* */
/* FreeType size objects management (specification). */
/* */
-/* Copyright 1996-2001, 2003, 2004, 2006, 2009 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -129,7 +129,7 @@
/* <Description> */
/* Even though it is possible to create several size objects for a */
/* given face (see @FT_New_Size for details), functions like */
- /* @FT_Load_Glyph or @FT_Load_Char only use the one which has been */
+ /* @FT_Load_Glyph or @FT_Load_Char only use the one that has been */
/* activated last to determine the `current character pixel size'. */
/* */
/* This function can be used to `activate' a previously created size */
diff --git a/include/freetype/ftsnames.h b/include/freetype/ftsnames.h
index 485e4e1..0f7fbe1 100644
--- a/include/freetype/ftsnames.h
+++ b/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
/* */
/* This is _not_ used to retrieve glyph names! */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2006, 2009, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -169,7 +169,7 @@
* A constant used as the tag of @FT_Parameter structures to make
* FT_Open_Face() ignore preferred family subfamily names in `name'
* table since OpenType version 1.4. For backwards compatibility with
- * legacy systems which has 4-face-per-family restriction.
+ * legacy systems that have a 4-face-per-family restriction.
*
*/
#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
@@ -184,7 +184,7 @@
* A constant used as the tag of @FT_Parameter structures to make
* FT_Open_Face() ignore preferred subfamily names in `name' table since
* OpenType version 1.4. For backwards compatibility with legacy
- * systems which has 4-face-per-family restriction.
+ * systems that have a 4-face-per-family restriction.
*
*/
#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY FT_MAKE_TAG( 'i', 'g', 'p', 's' )
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index a498e4a..7ebb1e7 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (specification). */
/* */
-/* Copyright 2002-2006, 2008, 2009, 2011-2012 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -46,6 +46,38 @@
* This can be useful to generate `bordered' glyph, i.e., glyphs
* displayed with a coloured (and anti-aliased) border around their
* shape.
+ *
+ * @order:
+ * FT_Stroker
+ *
+ * FT_Stroker_LineJoin
+ * FT_Stroker_LineCap
+ * FT_StrokerBorder
+ *
+ * FT_Outline_GetInsideBorder
+ * FT_Outline_GetOutsideBorder
+ *
+ * FT_Glyph_Stroke
+ * FT_Glyph_StrokeBorder
+ *
+ * FT_Stroker_New
+ * FT_Stroker_Set
+ * FT_Stroker_Rewind
+ * FT_Stroker_ParseOutline
+ * FT_Stroker_Done
+ *
+ * FT_Stroker_BeginSubPath
+ * FT_Stroker_EndSubPath
+ *
+ * FT_Stroker_LineTo
+ * FT_Stroker_ConicTo
+ * FT_Stroker_CubicTo
+ *
+ * FT_Stroker_GetBorderCounts
+ * FT_Stroker_ExportBorder
+ * FT_Stroker_GetCounts
+ * FT_Stroker_Export
+ *
*/
@@ -55,7 +87,7 @@
* FT_Stroker
*
* @description:
- * Opaque handler to a path stroker object.
+ * Opaque handle to a path stroker object.
*/
typedef struct FT_StrokerRec_* FT_Stroker;
@@ -276,6 +308,8 @@
* @note:
* The radius is expressed in the same units as the outline
* coordinates.
+ *
+ * This function calls @FT_Stroker_Rewind automatically.
*/
FT_EXPORT( void )
FT_Stroker_Set( FT_Stroker stroker,
@@ -570,10 +604,10 @@
* receive all new data.
*
* When an outline, or a sub-path, is `closed', the stroker generates
- * two independent `border' outlines, named `left' and `right'
+ * two independent `border' outlines, named `left' and `right'.
*
* When the outline, or a sub-path, is `opened', the stroker merges
- * the `border' outlines with caps. The `left' border receives all
+ * the `border' outlines with caps. The `left' border receives all
* points, while the `right' border becomes empty.
*
* Use the function @FT_Stroker_Export instead if you want to
@@ -736,7 +770,7 @@
FT_Bool inside,
FT_Bool destroy );
- /* */
+ /* */
FT_END_HEADER
diff --git a/include/freetype/ftsynth.h b/include/freetype/ftsynth.h
index 2074503..fbcbad8 100644
--- a/include/freetype/ftsynth.h
+++ b/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
/* FreeType synthesizing code for emboldening and slanting */
/* (specification). */
/* */
-/* Copyright 2000-2001, 2003, 2006, 2008, 2012 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -37,7 +37,7 @@
/* Main reason for not lifting the functions in this module to a */
/* `standard' API is that the used parameters for emboldening and */
/* slanting are not configurable. Consider the functions as a */
- /* code resource which should be copied into the application and */
+ /* code resource that should be copied into the application and */
/* adapted to the particular needs. */
@@ -62,8 +62,10 @@
/* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */
/* */
/* For emboldened outlines the height, width, and advance metrics are */
- /* increased by the strength of the emboldening. You can also call */
- /* @FT_Outline_Get_CBox to get precise values. */
+ /* increased by the strength of the emboldening -- this even affects */
+ /* mono-width fonts! */
+ /* */
+ /* You can also call @FT_Outline_Get_CBox to get precise values. */
FT_EXPORT( void )
FT_GlyphSlot_Embolden( FT_GlyphSlot slot );
@@ -73,6 +75,7 @@
/* */
+
FT_END_HEADER
#endif /* __FTSYNTH_H__ */
diff --git a/include/freetype/ftsystem.h b/include/freetype/ftsystem.h
index e07460c..2bc9999 100644
--- a/include/freetype/ftsystem.h
+++ b/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
/* */
/* FreeType low-level system interface definition (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2005, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -192,6 +192,10 @@
* @description:
* A handle to an input stream.
*
+ * @also:
+ * See @FT_StreamRec for the publicly accessible fields of a given
+ * stream object.
+ *
*/
typedef struct FT_StreamRec_* FT_Stream;
@@ -285,6 +289,11 @@
* size ::
* The stream size in bytes.
*
+ * In case of compressed streams where the size is unknown before
+ * actually doing the decompression, the value is set to 0x7FFFFFFF.
+ * (Note that this size value can occur for normal streams also; it is
+ * thus just a hint.)
+ *
* pos ::
* The current position within the stream.
*
@@ -335,7 +344,6 @@
} FT_StreamRec;
-
/* */
diff --git a/include/freetype/fttrigon.h b/include/freetype/fttrigon.h
index 65143cb..485ec51 100644
--- a/include/freetype/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
/* */
/* FreeType trigonometric functions (specification). */
/* */
-/* Copyright 2001, 2003, 2005, 2007, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -225,8 +225,8 @@
*
* @description:
* Return the unit vector corresponding to a given angle. After the
- * call, the value of `vec.x' will be `sin(angle)', and the value of
- * `vec.y' will be `cos(angle)'.
+ * call, the value of `vec.x' will be `cos(angle)', and the value of
+ * `vec.y' will be `sin(angle)'.
*
* This function is useful to retrieve both the sinus and cosinus of a
* given angle quickly.
@@ -237,7 +237,7 @@
*
* @input:
* angle ::
- * The address of angle.
+ * The input angle.
*
*/
FT_EXPORT( void )
@@ -259,7 +259,7 @@
*
* @input:
* angle ::
- * The address of angle.
+ * The input angle.
*
*/
FT_EXPORT( void )
diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h
index d5d3f1c..dc0081a 100644
--- a/include/freetype/ftttdrv.h
+++ b/include/freetype/ftttdrv.h
@@ -5,7 +5,7 @@
/* FreeType API for controlling the TrueType driver */
/* (specification only). */
/* */
-/* Copyright 2013 by */
+/* Copyright 2013-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,6 +52,83 @@
*
* The TrueType driver's module name is `truetype'.
*
+ * We start with a list of definitions, kindly provided by Greg
+ * Hitchcock.
+ *
+ * _Bi-Level_ _Rendering_
+ *
+ * Monochromatic rendering, exclusively used in the early days of
+ * TrueType by both Apple and Microsoft. Microsoft's GDI interface
+ * supported hinting of the right-side bearing point, such that the
+ * advance width could be non-linear. Most often this was done to
+ * achieve some level of glyph symmetry. To enable reasonable
+ * performance (e.g., not having to run hinting on all glyphs just to
+ * get the widths) there was a bit in the head table indicating if the
+ * side bearing was hinted, and additional tables, `hdmx' and `LTSH', to
+ * cache hinting widths across multiple sizes and device aspect ratios.
+ *
+ * _Font_ _Smoothing_
+ *
+ * Microsoft's GDI implementation of anti-aliasing. Not traditional
+ * anti-aliasing as the outlines were hinted before the sampling. The
+ * widths matched the bi-level rendering.
+ *
+ * _ClearType_ _Rendering_
+ *
+ * Technique that uses physical subpixels to improve rendering on LCD
+ * (and other) displays. Because of the higher resolution, many methods
+ * of improving symmetry in glyphs through hinting the right-side
+ * bearing were no longer necessary. This lead to what GDI calls
+ * `natural widths' ClearType, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec21. Since hinting
+ * has extra resolution, most non-linearity went away, but it is still
+ * possible for hints to change the advance widths in this mode.
+ *
+ * _ClearType_ _Compatible_ _Widths_
+ *
+ * One of the earliest challenges with ClearType was allowing the
+ * implementation in GDI to be selected without requiring all UI and
+ * documents to reflow. To address this, a compatible method of
+ * rendering ClearType was added where the font hints are executed once
+ * to determine the width in bi-level rendering, and then re-run in
+ * ClearType, with the difference in widths being absorbed in the font
+ * hints for ClearType (mostly in the white space of hints); see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec20. Somewhat by
+ * definition, compatible width ClearType allows for non-linear widths,
+ * but only when the bi-level version has non-linear widths.
+ *
+ * _ClearType_ _Subpixel_ _Positioning_
+ *
+ * One of the nice benefits of ClearType is the ability to more crisply
+ * display fractional widths; unfortunately, the GDI model of integer
+ * bitmaps did not support this. However, the WPF and Direct Write
+ * frameworks do support fractional widths. DWrite calls this `natural
+ * mode', not to be confused with GDI's `natural widths'. Subpixel
+ * positioning, in the current implementation of Direct Write,
+ * unfortunately does not support hinted advance widths, see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec22. Note that the
+ * TrueType interpreter fully allows the advance width to be adjusted in
+ * this mode, just the DWrite client will ignore those changes.
+ *
+ * _ClearType_ _Backwards_ _Compatibility_
+ *
+ * This is a set of exceptions made in the TrueType interpreter to
+ * minimize hinting techniques that were problematic with the extra
+ * resolution of ClearType; see
+ * http://www.beatstamm.com/typography/RTRCh4.htm#Sec1 and
+ * http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
+ * This technique is not to be confused with ClearType compatible
+ * widths. ClearType backwards compatibility has no direct impact on
+ * changing advance widths, but there might be an indirect impact on
+ * disabling some deltas. This could be worked around in backwards
+ * compatibility mode.
+ *
+ * _Native_ _ClearType_ _Mode_
+ *
+ * (Not to be confused with `natural widths'.) This mode removes all
+ * the exceptions in the TrueType interpreter when running with
+ * ClearType. Any issues on widths would still apply, though.
+ *
*/
@@ -61,19 +138,19 @@
* interpreter-version
*
* @description:
- * Currently, two versions are available which represent the bytecode
+ * Currently, two versions are available, representing the bytecode
* interpreter with and without subpixel hinting support,
* respectively. The default is subpixel support if
* TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel
* support otherwise (since it isn't available then).
*
- * If subpixel hinting is on, many TrueType bytecode instructions
- * behave differently compared to B/W or grayscale rendering. The
- * main idea is to render at a much increased horizontal resolution,
- * then sampling down the created output to subpixel precision.
- * However, many older fonts are not suited to this and must be
- * specially taken care of by applying (hardcoded) font-specific
- * tweaks.
+ * If subpixel hinting is on, many TrueType bytecode instructions behave
+ * differently compared to B/W or grayscale rendering (except if `native
+ * ClearType' is selected by the font). The main idea is to render at a
+ * much increased horizontal resolution, then sampling down the created
+ * output to subpixel precision. However, many older fonts are not
+ * suited to this and must be specially taken care of by applying
+ * (hardcoded) font-specific tweaks.
*
* Details on subpixel hinting and some of the necessary tweaks can be
* found in Greg Hitchcock's whitepaper at
@@ -134,13 +211,96 @@
* FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
* `FT_Err_Unimplemented_Feature' error.
*
+ * Depending on the graphics framework, Microsoft uses different
+ * bytecode and rendering engines. As a consequence, the version
+ * numbers returned by a call to the `GETINFO' bytecode instruction are
+ * more convoluted than desired.
+ *
+ * Here are two tables that try to shed some light on the possible
+ * values for the MS rasterizer engine, together with the additional
+ * features introduced by it.
+ *
+ * {
+ * GETINFO framework version feature
+ * -------------------------------------------------------------------
+ * 3 GDI (Win 3.1), v1.0 16-bit, first version
+ * TrueImage
+ * 33 GDI (Win NT 3.1), v1.5 32-bit
+ * HP Laserjet
+ * 34 GDI (Win 95) v1.6 font smoothing,
+ * new SCANTYPE opcode
+ * 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET
+ * bits in composite glyphs
+ * 36 MGDI (Win CE 2) v1.6+ classic ClearType
+ * 37 GDI (XP and later), v1.8 ClearType
+ * GDI+ old (before Vista)
+ * 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType,
+ * WPF Y-direction ClearType,
+ * additional error checking
+ * 39 DWrite (before Win 8) v2.0 subpixel ClearType flags
+ * in GETINFO opcode,
+ * bug fixes
+ * 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag
+ * DWrite (Win 8) in GETINFO opcode,
+ * Gray ClearType
+ * }
+ *
+ * The `version' field gives a rough orientation only, since some
+ * applications provided certain features much earlier (as an example,
+ * Microsoft Reader used subpixel and Y-direction ClearType already in
+ * Windows 2000). Similarly, updates to a given framework might include
+ * improved hinting support.
+ *
+ * {
+ * version sampling rendering comment
+ * x y x y
+ * --------------------------------------------------------------
+ * v1.0 normal normal B/W B/W bi-level
+ * v1.6 high high gray gray grayscale
+ * v1.8 high normal color-filter B/W (GDI) ClearType
+ * v1.9 high high color-filter gray Color ClearType
+ * v2.1 high normal gray B/W Gray ClearType
+ * v2.1 high high gray gray Gray ClearType
+ * }
+ *
+ * Color and Gray ClearType are the two available variants of
+ * `Y-direction ClearType', meaning grayscale rasterization along the
+ * Y-direction; the name used in the TrueType specification for this
+ * feature is `symmetric smoothing'. `Classic ClearType' is the
+ * original algorithm used before introducing a modified version in
+ * Win~XP. Another name for v1.6's grayscale rendering is `font
+ * smoothing', and `Color ClearType' is sometimes also called `DWrite
+ * ClearType'. To differentiate between today's Color ClearType and the
+ * earlier ClearType variant with B/W rendering along the vertical axis,
+ * the latter is sometimes called `GDI ClearType'.
+ *
+ * `Normal' and `high' sampling describe the (virtual) resolution to
+ * access the rasterized outline after the hinting process. `Normal'
+ * means 1 sample per grid line (i.e., B/W). In the current Microsoft
+ * implementation, `high' means an extra virtual resolution of 16x16 (or
+ * 16x1) grid lines per pixel for bytecode instructions like `MIRP'.
+ * After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
+ * lines for color filtering if Color ClearType is activated.
+ *
+ * Note that `Gray ClearType' is essentially the same as v1.6's
+ * grayscale rendering. However, the GETINFO instruction handles it
+ * differently: v1.6 returns bit~12 (hinting for grayscale), while v2.1
+ * returns bits~13 (hinting for ClearType), 18 (symmetrical smoothing),
+ * and~19 (Gray ClearType). Also, this mode respects bits 2 and~3 for
+ * the version~1 gasp table exclusively (like Color ClearType), while
+ * v1.6 only respects the values of version~0 (bits 0 and~1).
+ *
+ * FreeType doesn't provide all capabilities of the most recent
+ * ClearType incarnation, thus we identify our subpixel support as
+ * version~38.
+ *
*/
#define TT_INTERPRETER_VERSION_35 35
#define TT_INTERPRETER_VERSION_38 38
-
/* */
+
FT_END_HEADER
diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h
index 027e59c..706a1be 100644
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
/* */
/* FreeType simple types definitions (specification only). */
/* */
-/* Copyright 1996-2002, 2004, 2006-2009, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -57,6 +57,8 @@
/* FT_UInt16 */
/* FT_Int32 */
/* FT_UInt32 */
+ /* FT_Int64 */
+ /* FT_UInt64 */
/* FT_Short */
/* FT_UShort */
/* FT_Long */
@@ -78,7 +80,9 @@
/* FT_F2Dot14 */
/* FT_UnitVector */
/* FT_F26Dot6 */
+ /* FT_Data */
/* */
+ /* FT_MAKE_TAG */
/* */
/* FT_Generic */
/* FT_Generic_Finalizer */
@@ -418,7 +422,7 @@
/* details of usage. */
/* */
/* <Input> */
- /* The address of the FreeType object which is under finalization. */
+ /* The address of the FreeType object that is under finalization. */
/* Its client data is accessed through its `generic' field. */
/* */
typedef void (*FT_Generic_Finalizer)(void* object);
@@ -466,8 +470,8 @@
/* FT_MAKE_TAG */
/* */
/* <Description> */
- /* This macro converts four-letter tags which are used to label */
- /* TrueType tables into an unsigned long to be used within FreeType. */
+ /* This macro converts four-letter tags that are used to label */
+ /* TrueType tables into an unsigned long, to be used within FreeType. */
/* */
/* <Note> */
/* The produced values *must* be 32-bit integers. Don't redefine */
@@ -567,9 +571,9 @@
} FT_ListRec;
-
/* */
+
#define FT_IS_EMPTY( list ) ( (list).head == 0 )
#define FT_BOOL( x ) ( (FT_Bool)( x ) )
diff --git a/include/freetype/ftwinfnt.h b/include/freetype/ftwinfnt.h
index ea33353..caedaa1 100644
--- a/include/freetype/ftwinfnt.h
+++ b/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing Windows fnt-specific data. */
/* */
-/* Copyright 2003, 2004, 2008 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -58,9 +58,10 @@
* @description:
* A list of valid values for the `charset' byte in
* @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX
- * encodings (except for cp1361) can be found at ftp://ftp.unicode.org
- * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is
- * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
+ * encodings (except for cp1361) can be found at
+ * ftp://ftp.unicode.org/Public in the MAPPINGS/VENDORS/MICSFT/WINDOWS
+ * subdirectory. cp1361 is roughly a superset of
+ * MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT.
*
* @values:
* FT_WinFNT_ID_DEFAULT ::
@@ -94,7 +95,7 @@
* second default codepage that most international versions of
* Windows have. It is one of the OEM codepages from
*
- * http://www.microsoft.com/globaldev/reference/cphome.mspx,
+ * https://msdn.microsoft.com/en-us/goglobal/bb964655,
*
* and is used for the `DOS boxes', to support legacy applications.
* A German Windows version for example usually uses ANSI codepage
@@ -258,9 +259,9 @@
FT_Get_WinFNT_Header( FT_Face face,
FT_WinFNT_HeaderRec *aheader );
-
/* */
+
FT_END_HEADER
#endif /* __FTWINFNT_H__ */
diff --git a/include/freetype/internal/autohint.h b/include/freetype/internal/autohint.h
index 545de93..8d5a977 100644
--- a/include/freetype/internal/autohint.h
+++ b/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
/* */
/* High-level `autohint' module-specific interface (specification). */
/* */
-/* Copyright 1996-2002, 2007, 2009, 2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
index faac3a3..a76682b 100644
--- a/include/freetype/internal/ftcalc.h
+++ b/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
/* */
/* Arithmetic computations (specification). */
/* */
-/* Copyright 1996-2006, 2008, 2009, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,31 +29,222 @@
/*************************************************************************/
/* */
- /* <Function> */
- /* FT_FixedSqrt */
- /* */
- /* <Description> */
- /* Computes the square root of a 16.16 fixed-point value. */
- /* */
- /* <Input> */
- /* x :: The value to compute the root for. */
- /* */
- /* <Return> */
- /* The result of `sqrt(x)'. */
- /* */
- /* <Note> */
- /* This function is not very fast. */
- /* */
- FT_BASE( FT_Int32 )
- FT_SqrtFixed( FT_Int32 x );
-
-
- /*************************************************************************/
- /* */
/* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */
/* */
/*************************************************************************/
+#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+ /* Provide assembler fragments for performance-critical functions. */
+ /* These must be defined `static __inline__' with GCC. */
+
+#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
+
+#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+
+ /* documentation is in freetype.h */
+
+ static __inline FT_Int32
+ FT_MulFix_arm( FT_Int32 a,
+ FT_Int32 b )
+ {
+ FT_Int32 t, t2;
+
+
+ __asm
+ {
+ smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
+ mov a, t, asr #31 /* a = (hi >> 31) */
+ add a, a, #0x8000 /* a += 0x8000 */
+ adds t2, t2, a /* t2 += a */
+ adc t, t, #0 /* t += carry */
+ mov a, t2, lsr #16 /* a = t2 >> 16 */
+ orr a, a, t, lsl #16 /* a |= t << 16 */
+ }
+ return a;
+ }
+
+#endif /* __CC_ARM || __ARMCC__ */
+
+
+#ifdef __GNUC__
+
+#if defined( __arm__ ) && \
+ ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
+ !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
+
+#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
+
+ /* documentation is in freetype.h */
+
+ static __inline__ FT_Int32
+ FT_MulFix_arm( FT_Int32 a,
+ FT_Int32 b )
+ {
+ FT_Int32 t, t2;
+
+
+ __asm__ __volatile__ (
+ "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
+ "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
+#if defined( __clang__ ) && defined( __thumb2__ )
+ "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+#else
+ "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
+#endif
+ "adds %1, %1, %0\n\t" /* %1 += %0 */
+ "adc %2, %2, #0\n\t" /* %2 += carry */
+ "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
+ "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
+ : "=r"(a), "=&r"(t2), "=&r"(t)
+ : "r"(a), "r"(b)
+ : "cc" );
+ return a;
+ }
+
+#endif /* __arm__ && */
+ /* ( __thumb2__ || !__thumb__ ) && */
+ /* !( __CC_ARM || __ARMCC__ ) */
+
+
+#if defined( __i386__ )
+
+#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+
+ /* documentation is in freetype.h */
+
+ static __inline__ FT_Int32
+ FT_MulFix_i386( FT_Int32 a,
+ FT_Int32 b )
+ {
+ FT_Int32 result;
+
+
+ __asm__ __volatile__ (
+ "imul %%edx\n"
+ "movl %%edx, %%ecx\n"
+ "sarl $31, %%ecx\n"
+ "addl $0x8000, %%ecx\n"
+ "addl %%ecx, %%eax\n"
+ "adcl $0, %%edx\n"
+ "shrl $16, %%eax\n"
+ "shll $16, %%edx\n"
+ "addl %%edx, %%eax\n"
+ : "=a"(result), "=d"(b)
+ : "a"(a), "d"(b)
+ : "%ecx", "cc" );
+ return result;
+ }
+
+#endif /* i386 */
+
+#endif /* __GNUC__ */
+
+
+#ifdef _MSC_VER /* Visual C++ */
+
+#ifdef _M_IX86
+
+#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
+
+ /* documentation is in freetype.h */
+
+ static __inline FT_Int32
+ FT_MulFix_i386( FT_Int32 a,
+ FT_Int32 b )
+ {
+ FT_Int32 result;
+
+ __asm
+ {
+ mov eax, a
+ mov edx, b
+ imul edx
+ mov ecx, edx
+ sar ecx, 31
+ add ecx, 8000h
+ add eax, ecx
+ adc edx, 0
+ shr eax, 16
+ shl edx, 16
+ add eax, edx
+ mov result, eax
+ }
+ return result;
+ }
+
+#endif /* _M_IX86 */
+
+#endif /* _MSC_VER */
+
+
+#if defined( __GNUC__ ) && defined( __x86_64__ )
+
+#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64
+
+ static __inline__ FT_Int32
+ FT_MulFix_x86_64( FT_Int32 a,
+ FT_Int32 b )
+ {
+ /* Temporarily disable the warning that C90 doesn't support */
+ /* `long long'. */
+#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlong-long"
+#endif
+
+#if 1
+ /* Technically not an assembly fragment, but GCC does a really good */
+ /* job at inlining it and generating good machine code for it. */
+ long long ret, tmp;
+
+
+ ret = (long long)a * b;
+ tmp = ret >> 63;
+ ret += 0x8000 + tmp;
+
+ return (FT_Int32)( ret >> 16 );
+#else
+
+ /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */
+ /* code from the lines below. The main issue is that `wide_a' is not */
+ /* properly initialized by sign-extending `a'. Instead, the generated */
+ /* machine code assumes that the register that contains `a' on input */
+ /* can be used directly as a 64-bit value, which is wrong most of the */
+ /* time. */
+ long long wide_a = (long long)a;
+ long long wide_b = (long long)b;
+ long long result;
+
+
+ __asm__ __volatile__ (
+ "imul %2, %1\n"
+ "mov %1, %0\n"
+ "sar $63, %0\n"
+ "lea 0x8000(%1, %0), %0\n"
+ "sar $16, %0\n"
+ : "=&r"(result), "=&r"(wide_a)
+ : "r"(wide_b)
+ : "cc" );
+
+ return (FT_Int32)result;
+#endif
+
+#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
+#pragma GCC diagnostic pop
+#endif
+ }
+
+#endif /* __GNUC__ && __x86_64__ */
+
+#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+
+#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
+#ifdef FT_MULFIX_ASSEMBLER
+#define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) )
+#endif
+#endif
+
/*************************************************************************/
/* */
@@ -109,6 +300,18 @@
/*
+ * This function normalizes a vector and returns its original length.
+ * The normalized vector is a 16.16 fixed-point unit vector with length
+ * close to 0x10000. The accuracy of the returned length is limited to
+ * 16 bits also. The function utilizes quick inverse square root
+ * approximation without divisions and square roots relying on Newton's
+ * iterations instead.
+ */
+ FT_BASE( FT_UInt32 )
+ FT_Vector_NormLen( FT_Vector* vector );
+
+
+ /*
* Return -1, 0, or +1, depending on the orientation of a given corner.
* We use the Cartesian coordinate system, with positive vertical values
* going upwards. The function returns +1 if the corner turns to the
@@ -120,10 +323,11 @@
FT_Pos out_x,
FT_Pos out_y );
+
/*
* Return TRUE if a corner is flat or nearly flat. This is equivalent to
- * saying that the angle difference between the `in' and `out' vectors is
- * very small.
+ * saying that the corner point is close to its neighbors, or inside an
+ * ellipse defined by the neighbor focal points to be more precise.
*/
FT_BASE( FT_Int )
ft_corner_is_flat( FT_Pos in_x,
@@ -135,9 +339,31 @@
/*
* Return the most significant bit index.
*/
+
+#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+#if defined( __GNUC__ ) && \
+ ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
+
+#if FT_SIZEOF_INT == 4
+
+#define FT_MSB( x ) ( 31 - __builtin_clz( x ) )
+
+#elif FT_SIZEOF_LONG == 4
+
+#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) )
+
+#endif
+
+#endif /* __GNUC__ */
+#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+#ifndef FT_MSB
+
FT_BASE( FT_Int )
FT_MSB( FT_UInt32 z );
+#endif
+
/*
* Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
@@ -148,6 +374,31 @@
FT_Fixed y );
+#if 0
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_SqrtFixed */
+ /* */
+ /* <Description> */
+ /* Computes the square root of a 16.16 fixed-point value. */
+ /* */
+ /* <Input> */
+ /* x :: The value to compute the root for. */
+ /* */
+ /* <Return> */
+ /* The result of `sqrt(x)'. */
+ /* */
+ /* <Note> */
+ /* This function is not very fast. */
+ /* */
+ FT_BASE( FT_Int32 )
+ FT_SqrtFixed( FT_Int32 x );
+
+#endif /* 0 */
+
+
#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 )
#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 )
#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 )
diff --git a/include/freetype/internal/ftdebug.h b/include/freetype/internal/ftdebug.h
index 1ee120f..216c730 100644
--- a/include/freetype/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
/* */
/* Debugging and logging component (specification). */
/* */
-/* Copyright 1996-2002, 2004, 2006-2009, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -140,7 +140,7 @@
/* This function may be useful if you want to control FreeType 2's */
/* debug level in your application. */
/* */
- FT_BASE( const char * )
+ FT_BASE( const char* )
FT_Trace_Get_Name( FT_Int idx );
@@ -247,7 +247,6 @@
FT_BASE( void )
ft_debug_init( void );
-
FT_END_HEADER
#endif /* __FTDEBUG_H__ */
diff --git a/include/freetype/internal/ftdriver.h b/include/freetype/internal/ftdriver.h
index 940218e..16856d3 100644
--- a/include/freetype/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
@@ -4,7 +4,7 @@
/* */
/* FreeType font driver interface (specification). */
/* */
-/* Copyright 1996-2003, 2006, 2008, 2011-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/ftgloadr.h b/include/freetype/internal/ftgloadr.h
index ce4dc6c..970dd70 100644
--- a/include/freetype/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph loader (specification). */
/* */
-/* Copyright 2002, 2003, 2005, 2006 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -121,21 +121,25 @@
FT_UInt n_contours );
-#define FT_GLYPHLOADER_CHECK_P( _loader, _count ) \
- ( (_count) == 0 || ((_loader)->base.outline.n_points + \
- (_loader)->current.outline.n_points + \
- (unsigned long)(_count)) <= (_loader)->max_points )
+#define FT_GLYPHLOADER_CHECK_P( _loader, _count ) \
+ ( (_count) == 0 || \
+ ( (FT_UInt)(_loader)->base.outline.n_points + \
+ (FT_UInt)(_loader)->current.outline.n_points + \
+ (FT_UInt)(_count) ) <= (_loader)->max_points )
-#define FT_GLYPHLOADER_CHECK_C( _loader, _count ) \
- ( (_count) == 0 || ((_loader)->base.outline.n_contours + \
- (_loader)->current.outline.n_contours + \
- (unsigned long)(_count)) <= (_loader)->max_contours )
+#define FT_GLYPHLOADER_CHECK_C( _loader, _count ) \
+ ( (_count) == 0 || \
+ ( (FT_UInt)(_loader)->base.outline.n_contours + \
+ (FT_UInt)(_loader)->current.outline.n_contours + \
+ (FT_UInt)(_count) ) <= (_loader)->max_contours )
-#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points,_contours ) \
- ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points ) && \
- FT_GLYPHLOADER_CHECK_C( _loader, _contours ) ) \
- ? 0 \
- : FT_GlyphLoader_CheckPoints( (_loader), (_points), (_contours) ) )
+#define FT_GLYPHLOADER_CHECK_POINTS( _loader, _points, _contours ) \
+ ( ( FT_GLYPHLOADER_CHECK_P( _loader, _points ) && \
+ FT_GLYPHLOADER_CHECK_C( _loader, _contours ) ) \
+ ? 0 \
+ : FT_GlyphLoader_CheckPoints( (_loader), \
+ (FT_UInt)(_points), \
+ (FT_UInt)(_contours) ) )
/* check that there is enough space to add `n_subs' sub-glyphs to */
diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h
index 3d51aee..c0c553b 100644
--- a/include/freetype/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType memory management macros (specification). */
/* */
-/* Copyright 1996-2002, 2004-2007, 2010, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -215,11 +215,14 @@
#define FT_MEM_SET_ERROR( cond ) ( (cond), error != 0 )
-#define FT_MEM_SET( dest, byte, count ) ft_memset( dest, byte, count )
+#define FT_MEM_SET( dest, byte, count ) \
+ ft_memset( dest, byte, (FT_Offset)(count) )
-#define FT_MEM_COPY( dest, source, count ) ft_memcpy( dest, source, count )
+#define FT_MEM_COPY( dest, source, count ) \
+ ft_memcpy( dest, source, (FT_Offset)(count) )
-#define FT_MEM_MOVE( dest, source, count ) ft_memmove( dest, source, count )
+#define FT_MEM_MOVE( dest, source, count ) \
+ ft_memmove( dest, source, (FT_Offset)(count) )
#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
@@ -227,14 +230,19 @@
#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )
-#define FT_ARRAY_ZERO( dest, count ) \
- FT_MEM_ZERO( dest, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_ZERO( dest, count ) \
+ FT_MEM_ZERO( dest, \
+ (FT_Offset)(count) * sizeof ( *(dest) ) )
-#define FT_ARRAY_COPY( dest, source, count ) \
- FT_MEM_COPY( dest, source, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_COPY( dest, source, count ) \
+ FT_MEM_COPY( dest, \
+ source, \
+ (FT_Offset)(count) * sizeof ( *(dest) ) )
-#define FT_ARRAY_MOVE( dest, source, count ) \
- FT_MEM_MOVE( dest, source, (count) * sizeof ( *(dest) ) )
+#define FT_ARRAY_MOVE( dest, source, count ) \
+ FT_MEM_MOVE( dest, \
+ source, \
+ (FT_Offset)(count) * sizeof ( *(dest) ) )
/*
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 8a309b8..9a333fc 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType private base classes (specification). */
/* */
-/* Copyright 1996-2006, 2008, 2010, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -72,25 +72,28 @@
#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
+ /*
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+ * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
+ * largest error less than 7% compared to the exact value.
+ */
+#define FT_HYPOT( x, y ) \
+ ( x = FT_ABS( x ), \
+ y = FT_ABS( y ), \
+ x > y ? x + ( 3 * y >> 3 ) \
+ : y + ( 3 * x >> 3 ) )
-#define FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) )
+ /* we use FT_TYPEOF to suppress signedness compilation warnings */
+#define FT_PAD_FLOOR( x, n ) ( (x) & ~FT_TYPEOF( x )( (n)-1 ) )
#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n )
#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n )
-#define FT_PIX_FLOOR( x ) ( (x) & ~63 )
+#define FT_PIX_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 )
#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 )
/*
- * Return the highest power of 2 that is <= value; this correspond to
- * the highest bit in a given 32-bit value.
- */
- FT_BASE( FT_UInt32 )
- ft_highpow2( FT_UInt32 value );
-
-
- /*
* character classification functions -- since these are used to parse
* font files, we must not use those in <ctypes.h> which are
* locale-dependent
@@ -363,7 +366,7 @@
#endif
FT_Bool ignore_unpatented_hinter;
- FT_UInt refcount;
+ FT_Int refcount;
} FT_Face_InternalRec;
@@ -402,7 +405,7 @@
/* glyph_hints :: Format-specific glyph hints management. */
/* */
-#define FT_GLYPH_OWN_BITMAP 0x1
+#define FT_GLYPH_OWN_BITMAP 0x1U
typedef struct FT_Slot_InternalRec_
{
@@ -503,6 +506,9 @@
#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \
FT_MODULE_DRIVER_HAS_HINTER )
+#define FT_DRIVER_HINTS_LIGHTLY( x ) ( FT_MODULE_CLASS( x )->module_flags & \
+ FT_MODULE_DRIVER_HINTS_LIGHTLY )
+
/*************************************************************************/
/* */
@@ -611,12 +617,12 @@
#define FT_REQUEST_WIDTH( req ) \
( (req)->horiResolution \
- ? (FT_Pos)( (req)->width * (req)->horiResolution + 36 ) / 72 \
+ ? ( (req)->width * (FT_Pos)(req)->horiResolution + 36 ) / 72 \
: (req)->width )
#define FT_REQUEST_HEIGHT( req ) \
( (req)->vertResolution \
- ? (FT_Pos)( (req)->height * (req)->vertResolution + 36 ) / 72 \
+ ? ( (req)->height * (FT_Pos)(req)->vertResolution + 36 ) / 72 \
: (req)->height )
@@ -738,9 +744,8 @@
/* faces_list :: The list of faces currently opened by this */
/* driver. */
/* */
- /* glyph_loader :: The glyph loader for all faces managed by this */
- /* driver. This object isn't defined for unscalable */
- /* formats. */
+ /* glyph_loader :: Unused. Used to be glyph loader for all faces */
+ /* managed by this driver. */
/* */
typedef struct FT_DriverRec_
{
@@ -883,7 +888,7 @@
FT_PIC_Container pic_container;
#endif
- FT_UInt refcount;
+ FT_Int refcount;
} FT_LibraryRec;
diff --git a/include/freetype/internal/ftpic.h b/include/freetype/internal/ftpic.h
index 485ce7a..7f9154f 100644
--- a/include/freetype/internal/ftpic.h
+++ b/include/freetype/internal/ftpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services (declaration). */
/* */
-/* Copyright 2009, 2012 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/ftrfork.h b/include/freetype/internal/ftrfork.h
index 6307f2d..da61ca7 100644
--- a/include/freetype/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
/* */
/* Embedded resource forks accessor (specification). */
/* */
-/* Copyright 2004, 2006, 2007, 2012 by */
+/* Copyright 2004-2015 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -44,7 +44,7 @@
typedef struct FT_RFork_Ref_
{
FT_UShort res_id;
- FT_ULong offset;
+ FT_Long offset;
} FT_RFork_Ref;
@@ -83,7 +83,7 @@
/* this array is a storage in non-PIC mode, so ; is needed in END */
#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
- const type name[] = {
+ static const type name[] = {
#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \
{ raccess_guess_ ## func_suffix, \
FT_RFork_Rule_ ## type_suffix },
@@ -94,7 +94,7 @@
/* this array is a function in PIC mode, so no ; is needed in END */
#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
void \
- FT_Init_ ## name( type* storage ) \
+ FT_Init_Table_ ## name( type* storage ) \
{ \
type* local = storage; \
\
@@ -224,6 +224,13 @@
/* tag :: */
/* The resource tag. */
/* */
+ /* sort_by_res_id :: */
+ /* A Boolean to sort the fragmented resource by their ids. */
+ /* The fragmented resources for `POST' resource should be sorted */
+ /* to restore Type1 font properly. For `snft' resources, sorting */
+ /* may induce a different order of the faces in comparison to that */
+ /* by QuickDraw API. */
+ /* */
/* <Output> */
/* offsets :: */
/* The stream offsets for the resource data specified by `tag'. */
@@ -246,6 +253,7 @@
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
+ FT_Bool sort_by_res_id,
FT_Long **offsets,
FT_Long *count );
diff --git a/include/freetype/internal/ftserv.h b/include/freetype/internal/ftserv.h
index 4ac988b..11a0c7f 100644
--- a/include/freetype/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType services (specification only). */
/* */
-/* Copyright 2003-2007, 2009, 2012, 2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -34,14 +34,6 @@
FT_BEGIN_HEADER
-#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
- /* We disable the warning `conditional expression is */
- /* constant' in order to compile cleanly with the maximum */
- /* level of warnings. */
-#pragma warning( push )
-#pragma warning( disable : 4127 )
-#endif /* _MSC_VER */
-
/*
* @macro:
* FT_FACE_FIND_SERVICE
@@ -758,15 +750,11 @@
#define FT_SERVICE_TRUETYPE_ENGINE_H <freetype/internal/services/svtteng.h>
#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
-#define FT_SERVICE_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h>
+#define FT_SERVICE_FONT_FORMAT_H <freetype/internal/services/svfntfmt.h>
#define FT_SERVICE_TRUETYPE_GLYF_H <freetype/internal/services/svttglyf.h>
/* */
-#if defined( _MSC_VER )
-#pragma warning( pop )
-#endif
-
FT_END_HEADER
#endif /* __FTSERV_H__ */
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index 2661858..384e5df 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
/* */
/* Stream handling (specification). */
/* */
-/* Copyright 1996-2002, 2004-2006, 2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -361,7 +361,7 @@
FT_Long distance );
/* return current stream position */
- FT_BASE( FT_Long )
+ FT_BASE( FT_ULong )
FT_Stream_Pos( FT_Stream stream );
/* read bytes from a stream into a user-allocated buffer, returns an */
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index a9d98b6..2b0bf9d 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
/* */
/* Tracing handling (specification only). */
/* */
-/* Copyright 2002, 2004-2007, 2009, 2011-2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -148,5 +148,7 @@
FT_TRACE_DEF( aflatin )
FT_TRACE_DEF( aflatin2 )
FT_TRACE_DEF( afwarp )
+FT_TRACE_DEF( afshaper )
+FT_TRACE_DEF( afglobal )
/* END */
diff --git a/include/freetype/internal/ftvalid.h b/include/freetype/internal/ftvalid.h
index 12ad036..9cda6ee 100644
--- a/include/freetype/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
/* */
/* FreeType validation support (specification). */
/* */
-/* Copyright 2004, 2013 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -87,13 +87,13 @@
/* validator structure */
typedef struct FT_ValidatorRec_
{
+ ft_jmp_buf jump_buffer; /* used for exception handling */
+
const FT_Byte* base; /* address of table in memory */
const FT_Byte* limit; /* `base' + sizeof(table) in memory */
FT_ValidationLevel level; /* validation level */
FT_Error error; /* error returned. 0 means success */
- ft_jmp_buf jump_buffer; /* used for exception handling */
-
} FT_ValidatorRec;
#if defined( _MSC_VER )
@@ -126,31 +126,29 @@
/* Calls ft_validate_error. Assumes that the `valid' local variable */
/* holds a pointer to the current validator object. */
/* */
- /* Use preprocessor prescan to pass FT_ERR_PREFIX. */
- /* */
-#define FT_INVALID( _prefix, _error ) FT_INVALID_( _prefix, _error )
-#define FT_INVALID_( _prefix, _error ) \
- ft_validator_error( valid, _prefix ## _error )
+#define FT_INVALID( _error ) FT_INVALID_( _error )
+#define FT_INVALID_( _error ) \
+ ft_validator_error( valid, FT_THROW( _error ) )
/* called when a broken table is detected */
#define FT_INVALID_TOO_SHORT \
- FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+ FT_INVALID( Invalid_Table )
/* called when an invalid offset is detected */
#define FT_INVALID_OFFSET \
- FT_INVALID( FT_ERR_PREFIX, Invalid_Offset )
+ FT_INVALID( Invalid_Offset )
/* called when an invalid format/value is detected */
#define FT_INVALID_FORMAT \
- FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+ FT_INVALID( Invalid_Table )
/* called when an invalid glyph index is detected */
#define FT_INVALID_GLYPH_ID \
- FT_INVALID( FT_ERR_PREFIX, Invalid_Glyph_Index )
+ FT_INVALID( Invalid_Glyph_Index )
/* called when an invalid field value is detected */
#define FT_INVALID_DATA \
- FT_INVALID( FT_ERR_PREFIX, Invalid_Table )
+ FT_INVALID( Invalid_Table )
FT_END_HEADER
diff --git a/include/freetype/internal/internal.h b/include/freetype/internal/internal.h
index f500a65..809ce59 100644
--- a/include/freetype/internal/internal.h
+++ b/include/freetype/internal/internal.h
@@ -4,7 +4,7 @@
/* */
/* Internal header files (specification only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,4 +48,16 @@
#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h>
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+
+ /* We disable the warning `conditional expression is constant' here */
+ /* in order to compile cleanly with the maximum level of warnings. */
+ /* In particular, the warning complains about stuff like `while(0)' */
+ /* which is very useful in macro definitions. There is no benefit */
+ /* in having it enabled. */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+
+
/* END */
diff --git a/include/freetype/internal/pcftypes.h b/include/freetype/internal/pcftypes.h
deleted file mode 100644
index 382796f..0000000
--- a/include/freetype/internal/pcftypes.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* pcftypes.h
-
- FreeType font driver for pcf fonts
-
- Copyright (C) 2000, 2001, 2002 by
- Francesco Zappa Nardelli
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-
-#ifndef __PCFTYPES_H__
-#define __PCFTYPES_H__
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-
-FT_BEGIN_HEADER
-
-
- typedef struct PCF_Public_FaceRec_
- {
- FT_FaceRec root;
- FT_StreamRec gzip_stream;
- FT_Stream gzip_source;
-
- char* charset_encoding;
- char* charset_registry;
-
- } PCF_Public_FaceRec, *PCF_Public_Face;
-
-
-FT_END_HEADER
-
-#endif /* __PCFTYPES_H__ */
-
-
-/* END */
diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h
index e903114..1c5f784 100644
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
/* Auxiliary functions and data structures related to PostScript fonts */
/* (specification). */
/* */
-/* Copyright 1996-2004, 2006, 2008, 2009, 2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -71,10 +71,10 @@
(*done)( PS_Table table );
FT_Error
- (*add)( PS_Table table,
- FT_Int idx,
- void* object,
- FT_PtrDist length );
+ (*add)( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_UInt length );
void
(*release)( PS_Table table );
@@ -122,12 +122,12 @@
FT_Byte* block; /* current memory block */
FT_Offset cursor; /* current cursor in memory block */
FT_Offset capacity; /* current size of memory block */
- FT_Long init;
+ FT_ULong init;
FT_Int max_elems;
FT_Int num_elems;
FT_Byte** elements; /* addresses of table elements */
- FT_PtrDist* lengths; /* lengths of table elements */
+ FT_UInt* lengths; /* lengths of table elements */
FT_Memory memory;
PS_Table_FuncsRec funcs;
@@ -365,7 +365,7 @@
(*to_bytes)( PS_Parser parser,
FT_Byte* bytes,
FT_Offset max_bytes,
- FT_Long* pnum_bytes,
+ FT_ULong* pnum_bytes,
FT_Bool delimiters );
FT_Int
@@ -675,9 +675,9 @@
FT_Byte** glyph_names;
FT_Int lenIV; /* internal for sub routine calls */
- FT_UInt num_subrs;
+ FT_Int num_subrs;
FT_Byte** subrs;
- FT_PtrDist* subrs_len; /* array of subrs length (optional) */
+ FT_UInt* subrs_len; /* array of subrs length (optional) */
FT_Matrix font_matrix;
FT_Vector font_offset;
diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h
index 3fb18dc..12aaaba 100644
--- a/include/freetype/internal/pshints.h
+++ b/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
/* recorders (specification only). These are used to support native */
/* T1/T2 hints in the `type1', `cid', and `cff' font drivers. */
/* */
-/* Copyright 2001-2003, 2005-2007, 2009, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -45,7 +45,7 @@
T1_Private* private_dict,
PSH_Globals* aglobals );
- typedef FT_Error
+ typedef void
(*PSH_Globals_SetScaleFunc)( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed y_scale,
@@ -465,7 +465,7 @@
typedef void
(*T2_Hints_StemsFunc)( T2_Hints hints,
FT_UInt dimension,
- FT_UInt count,
+ FT_Int count,
FT_Fixed* coordinates );
diff --git a/include/freetype/internal/services/svbdf.h b/include/freetype/internal/services/svbdf.h
index 0974752..865b536 100644
--- a/include/freetype/internal/services/svbdf.h
+++ b/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType BDF services (specification). */
/* */
-/* Copyright 2003, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svcid.h b/include/freetype/internal/services/svcid.h
index 6be3f93..4a535a6 100644
--- a/include/freetype/internal/services/svcid.h
+++ b/include/freetype/internal/services/svcid.h
@@ -4,7 +4,8 @@
/* */
/* The FreeType CID font services (specification). */
/* */
-/* Copyright 2007, 2009, 2012 by Derek Clegg, Michael Toftdal. */
+/* Copyright 2007-2015 by */
+/* Derek Clegg and Michael Toftdal. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
diff --git a/include/freetype/internal/services/svxf86nm.h b/include/freetype/internal/services/svfntfmt.h
similarity index 65%
rename from include/freetype/internal/services/svxf86nm.h
rename to include/freetype/internal/services/svfntfmt.h
index ca5d884..f8b3617 100644
--- a/include/freetype/internal/services/svxf86nm.h
+++ b/include/freetype/internal/services/svfntfmt.h
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* svxf86nm.h */
+/* svfntfmt.h */
/* */
-/* The FreeType XFree86 services (specification only). */
+/* The FreeType font format service (specification only). */
/* */
-/* Copyright 2003 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __SVXF86NM_H__
-#define __SVXF86NM_H__
+#ifndef __SVFNTFMT_H__
+#define __SVFNTFMT_H__
#include FT_INTERNAL_SERVICE_H
@@ -31,17 +31,17 @@
* is a simple constant string pointer.
*/
-#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name"
+#define FT_SERVICE_ID_FONT_FORMAT "font-format"
-#define FT_XF86_FORMAT_TRUETYPE "TrueType"
-#define FT_XF86_FORMAT_TYPE_1 "Type 1"
-#define FT_XF86_FORMAT_BDF "BDF"
-#define FT_XF86_FORMAT_PCF "PCF"
-#define FT_XF86_FORMAT_TYPE_42 "Type 42"
-#define FT_XF86_FORMAT_CID "CID Type 1"
-#define FT_XF86_FORMAT_CFF "CFF"
-#define FT_XF86_FORMAT_PFR "PFR"
-#define FT_XF86_FORMAT_WINFNT "Windows FNT"
+#define FT_FONT_FORMAT_TRUETYPE "TrueType"
+#define FT_FONT_FORMAT_TYPE_1 "Type 1"
+#define FT_FONT_FORMAT_BDF "BDF"
+#define FT_FONT_FORMAT_PCF "PCF"
+#define FT_FONT_FORMAT_TYPE_42 "Type 42"
+#define FT_FONT_FORMAT_CID "CID Type 1"
+#define FT_FONT_FORMAT_CFF "CFF"
+#define FT_FONT_FORMAT_PFR "PFR"
+#define FT_FONT_FORMAT_WINFNT "Windows FNT"
/* */
@@ -49,7 +49,7 @@
FT_END_HEADER
-#endif /* __SVXF86NM_H__ */
+#endif /* __SVFNTFMT_H__ */
/* END */
diff --git a/include/freetype/internal/services/svgldict.h b/include/freetype/internal/services/svgldict.h
index 1d12534..f78bca5 100644
--- a/include/freetype/internal/services/svgldict.h
+++ b/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph dictionary services (specification). */
/* */
-/* Copyright 2003, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svgxval.h b/include/freetype/internal/services/svgxval.h
index 2cdab50..59cc3b7 100644
--- a/include/freetype/internal/services/svgxval.h
+++ b/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
/* */
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
/* */
-/* Copyright 2004, 2005 by */
+/* Copyright 2004-2015 by */
/* Masatake YAMATO, Red Hat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
diff --git a/include/freetype/internal/services/svkern.h b/include/freetype/internal/services/svkern.h
index 1488adf..bc26f15 100644
--- a/include/freetype/internal/services/svkern.h
+++ b/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Kerning service (specification). */
/* */
-/* Copyright 2006 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svmm.h b/include/freetype/internal/services/svmm.h
index b08a663..f2cecfb 100644
--- a/include/freetype/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Multiple Masters and GX var services (specification). */
/* */
-/* Copyright 2003, 2004, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svotval.h b/include/freetype/internal/services/svotval.h
index 970bbd5..a82a642 100644
--- a/include/freetype/internal/services/svotval.h
+++ b/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType OpenType validation service (specification). */
/* */
-/* Copyright 2004, 2006 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svpfr.h b/include/freetype/internal/services/svpfr.h
index 462786f..d4eb169 100644
--- a/include/freetype/internal/services/svpfr.h
+++ b/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
/* */
/* Internal PFR service functions (specification). */
/* */
-/* Copyright 2003, 2006 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svpostnm.h b/include/freetype/internal/services/svpostnm.h
index a76b4fe..a89f79e 100644
--- a/include/freetype/internal/services/svpostnm.h
+++ b/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript name services (specification). */
/* */
-/* Copyright 2003, 2007, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svprop.h b/include/freetype/internal/services/svprop.h
index 22da0bb..c9f07ce 100644
--- a/include/freetype/internal/services/svprop.h
+++ b/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType property service (specification). */
/* */
-/* Copyright 2012 by */
+/* Copyright 2012-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svpscmap.h b/include/freetype/internal/services/svpscmap.h
index 030948e..66da6e1 100644
--- a/include/freetype/internal/services/svpscmap.h
+++ b/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript charmap service (specification). */
/* */
-/* Copyright 2003, 2006, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svpsinfo.h b/include/freetype/internal/services/svpsinfo.h
index 4bfb506..752a266 100644
--- a/include/freetype/internal/services/svpsinfo.h
+++ b/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType PostScript info service (specification). */
/* */
-/* Copyright 2003, 2004, 2009, 2011, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svsfnt.h b/include/freetype/internal/services/svsfnt.h
index d3835aa..252ae1c 100644
--- a/include/freetype/internal/services/svsfnt.h
+++ b/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType SFNT table loading service (specification). */
/* */
-/* Copyright 2003, 2004, 2009, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svttcmap.h b/include/freetype/internal/services/svttcmap.h
index 83994aa..cd95b9a 100644
--- a/include/freetype/internal/services/svttcmap.h
+++ b/include/freetype/internal/services/svttcmap.h
@@ -4,10 +4,8 @@
/* */
/* The FreeType TrueType/sfnt cmap extra information service. */
/* */
-/* Copyright 2003 by */
-/* Masatake YAMATO, Redhat K.K. */
-/* */
-/* Copyright 2003, 2008, 2009, 2012 by */
+/* Copyright 2003-2015 by */
+/* Masatake YAMATO, Redhat K.K., */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -47,14 +45,15 @@
/* <Fields> */
/* language :: */
/* The language ID used in Mac fonts. Definitions of values are in */
- /* freetype/ttnameid.h. */
+ /* `ttnameid.h'. */
/* */
/* format :: */
- /* The cmap format. OpenType 1.5 defines the formats 0 (byte */
+ /* The cmap format. OpenType 1.6 defines the formats 0 (byte */
/* encoding table), 2~(high-byte mapping through table), 4~(segment */
/* mapping to delta values), 6~(trimmed table mapping), 8~(mixed */
/* 16-bit and 32-bit coverage), 10~(trimmed array), 12~(segmented */
- /* coverage), and 14 (Unicode Variation Sequences). */
+ /* coverage), 13~(last resort font), and 14 (Unicode Variation */
+ /* Sequences). */
/* */
typedef struct TT_CMapInfo_
{
diff --git a/include/freetype/internal/services/svtteng.h b/include/freetype/internal/services/svtteng.h
index 58e02a6..272ee8c 100644
--- a/include/freetype/internal/services/svtteng.h
+++ b/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType TrueType engine query service (specification). */
/* */
-/* Copyright 2006 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/services/svttglyf.h b/include/freetype/internal/services/svttglyf.h
index 369eb84..f5cb76a 100644
--- a/include/freetype/internal/services/svttglyf.h
+++ b/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,8 @@
/* */
/* The FreeType TrueType glyph service. */
/* */
-/* Copyright 2007, 2009, 2012 by David Turner. */
+/* Copyright 2007-2015 by */
+/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
diff --git a/include/freetype/internal/services/svwinfnt.h b/include/freetype/internal/services/svwinfnt.h
index 57f7765..0036929 100644
--- a/include/freetype/internal/services/svwinfnt.h
+++ b/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType Windows FNT/FONT service (specification). */
/* */
-/* Copyright 2003 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h
index 6b5e41f..30f53bf 100644
--- a/include/freetype/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
/* */
/* High-level `sfnt' driver interface (specification). */
/* */
-/* Copyright 1996-2006, 2009, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -44,7 +44,9 @@
/* face :: A handle to the target face object. */
/* */
/* face_index :: The index of the TrueType font, if we are opening a */
- /* collection. */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: The number of additional parameters. */
/* */
@@ -87,7 +89,9 @@
/* face :: A handle to the target face object. */
/* */
/* face_index :: The index of the TrueType font, if we are opening a */
- /* collection. */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: The number of additional parameters. */
/* */
@@ -405,14 +409,18 @@
/* <Input> */
/* face :: A handle to the target face object. */
/* */
- /* stream :: The input stream. */
- /* */
/* vertical :: A boolean flag. If set, load vertical metrics. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
+ /* gindex :: The glyph index. */
/* */
- typedef FT_Error
+ /* <Output> */
+ /* abearing :: The horizontal (or vertical) bearing. Set to zero in */
+ /* case of error. */
+ /* */
+ /* aadvance :: The horizontal (or vertical) advance. Set to zero in */
+ /* case of error. */
+ /* */
+ typedef void
(*TT_Get_Metrics_Func)( TT_Face face,
FT_Bool vertical,
FT_UInt gindex,
@@ -423,6 +431,33 @@
/*************************************************************************/
/* */
/* <FuncType> */
+ /* TT_Get_Name_Func */
+ /* */
+ /* <Description> */
+ /* From the `name' table, return a given ENGLISH name record in */
+ /* ASCII. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* nameid :: The name id of the name record to return. */
+ /* */
+ /* <InOut> */
+ /* name :: The address of an allocated string pointer. NULL if */
+ /* no name is present. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ typedef FT_Error
+ (*TT_Get_Name_Func)( TT_Face face,
+ FT_UShort nameid,
+ FT_String** name );
+
+
+ /*************************************************************************/
+ /* */
+ /* <FuncType> */
/* TT_Load_Table_Func */
/* */
/* <Description> */
@@ -552,6 +587,8 @@
TT_Get_Metrics_Func get_metrics;
+ TT_Get_Name_Func get_name;
+
} SFNT_Interface;
@@ -590,7 +627,8 @@
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
- get_metrics_ ) \
+ get_metrics_, \
+ get_name_ ) \
static const SFNT_Interface class_ = \
{ \
goto_table_, \
@@ -622,6 +660,7 @@
set_sbit_strike_, \
load_strike_metrics_, \
get_metrics_, \
+ get_name_, \
};
#else /* FT_CONFIG_OPTION_PIC */
@@ -659,7 +698,8 @@
free_eblc_, \
set_sbit_strike_, \
load_strike_metrics_, \
- get_metrics_ ) \
+ get_metrics_, \
+ get_name_ ) \
void \
FT_Init_Class_ ## class_( FT_Library library, \
SFNT_Interface* clazz ) \
@@ -695,6 +735,7 @@
clazz->set_sbit_strike = set_sbit_strike_; \
clazz->load_strike_metrics = load_strike_metrics_; \
clazz->get_metrics = get_metrics_; \
+ clazz->get_name = get_name_; \
}
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h
index e20237c..029acc4 100644
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
/* Basic Type1/Type2 type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2004, 2006, 2008, 2009, 2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -106,12 +106,12 @@
FT_Int num_subrs;
FT_Byte** subrs;
- FT_PtrDist* subrs_len;
+ FT_UInt* subrs_len;
FT_Int num_glyphs;
FT_String** glyph_names; /* array of glyph names */
FT_Byte** charstrings; /* array of glyph charstrings */
- FT_PtrDist* charstrings_len;
+ FT_UInt* charstrings_len;
FT_Byte paint_type;
FT_Byte font_type;
@@ -127,7 +127,7 @@
typedef struct CID_SubrsRec_
{
- FT_UInt num_subrs;
+ FT_Int num_subrs;
FT_Byte** code;
} CID_SubrsRec, *CID_Subrs;
@@ -157,10 +157,10 @@
typedef struct AFM_KernPairRec_
{
- FT_Int index1;
- FT_Int index2;
- FT_Int x;
- FT_Int y;
+ FT_UInt index1;
+ FT_UInt index2;
+ FT_Int x;
+ FT_Int y;
} AFM_KernPairRec, *AFM_KernPair;
@@ -171,9 +171,9 @@
FT_Fixed Ascender;
FT_Fixed Descender;
AFM_TrackKern TrackKerns; /* free if non-NULL */
- FT_Int NumTrackKern;
+ FT_UInt NumTrackKern;
AFM_KernPair KernPairs; /* free if non-NULL */
- FT_Int NumKernPair;
+ FT_UInt NumKernPair;
} AFM_FontInfoRec, *AFM_FontInfo;
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 1bbfe49..000c5a8 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
/* Basic SFNT/TrueType type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2002, 2004-2008, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -140,6 +140,75 @@
/*************************************************************************/
/* */
/* <Struct> */
+ /* WOFF_HeaderRec */
+ /* */
+ /* <Description> */
+ /* WOFF file format header. */
+ /* */
+ /* <Fields> */
+ /* See */
+ /* */
+ /* http://www.w3.org/TR/WOFF/#WOFFHeader */
+ /* */
+ typedef struct WOFF_HeaderRec_
+ {
+ FT_ULong signature;
+ FT_ULong flavor;
+ FT_ULong length;
+ FT_UShort num_tables;
+ FT_UShort reserved;
+ FT_ULong totalSfntSize;
+ FT_UShort majorVersion;
+ FT_UShort minorVersion;
+ FT_ULong metaOffset;
+ FT_ULong metaLength;
+ FT_ULong metaOrigLength;
+ FT_ULong privOffset;
+ FT_ULong privLength;
+
+ } WOFF_HeaderRec, *WOFF_Header;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* WOFF_TableRec */
+ /* */
+ /* <Description> */
+ /* This structure describes a given table of a WOFF font. */
+ /* */
+ /* <Fields> */
+ /* Tag :: A four-bytes tag describing the table. */
+ /* */
+ /* Offset :: The offset of the table from the start of the WOFF */
+ /* font in its resource. */
+ /* */
+ /* CompLength :: Compressed table length (in bytes). */
+ /* */
+ /* OrigLength :: Unompressed table length (in bytes). */
+ /* */
+ /* CheckSum :: The table checksum. This value can be ignored. */
+ /* */
+ /* OrigOffset :: The uncompressed table file offset. This value gets */
+ /* computed while constructing the (uncompressed) SFNT */
+ /* header. It is not contained in the WOFF file. */
+ /* */
+ typedef struct WOFF_TableRec_
+ {
+ FT_ULong Tag; /* table ID */
+ FT_ULong Offset; /* table file offset */
+ FT_ULong CompLength; /* compressed table length */
+ FT_ULong OrigLength; /* uncompressed table length */
+ FT_ULong CheckSum; /* uncompressed checksum */
+
+ FT_ULong OrigOffset; /* uncompressed table file offset */
+ /* (not in the WOFF file) */
+ } WOFF_TableRec, *WOFF_Table;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
/* TT_LongMetricsRec */
/* */
/* <Description> */
@@ -353,16 +422,16 @@
/* */
typedef struct TT_SBit_MetricsRec_
{
- FT_Byte height;
- FT_Byte width;
+ FT_UShort height;
+ FT_UShort width;
- FT_Char horiBearingX;
- FT_Char horiBearingY;
- FT_Byte horiAdvance;
+ FT_Short horiBearingX;
+ FT_Short horiBearingY;
+ FT_UShort horiAdvance;
- FT_Char vertBearingX;
- FT_Char vertBearingY;
- FT_Byte vertAdvance;
+ FT_Short vertBearingX;
+ FT_Short vertBearingY;
+ FT_UShort vertAdvance;
} TT_SBit_MetricsRec, *TT_SBit_Metrics;
@@ -545,8 +614,7 @@
/* in use by other platforms (e.g. Newton). */
/* For details, please see */
/* */
- /* http://fonts.apple.com/ */
- /* TTRefMan/RM06/Chap6bloc.html */
+ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
/* */
/* hori :: The line metrics for horizontal layouts. */
/* */
@@ -566,8 +634,7 @@
/* flags :: Is this a vertical or horizontal strike? For */
/* details, please see */
/* */
- /* http://fonts.apple.com/ */
- /* TTRefMan/RM06/Chap6bloc.html */
+ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bloc.html */
/* */
typedef struct TT_SBit_StrikeRec_
{
@@ -979,6 +1046,20 @@
(*TT_Loader_EndGlyphFunc)( TT_Loader loader );
+ typedef enum TT_SbitTableType_
+ {
+ TT_SBIT_TABLE_TYPE_NONE = 0,
+ TT_SBIT_TABLE_TYPE_EBLC, /* `EBLC' (Microsoft), */
+ /* `bloc' (Apple) */
+ TT_SBIT_TABLE_TYPE_CBLC, /* `CBLC' (Google) */
+ TT_SBIT_TABLE_TYPE_SBIX, /* `sbix' (Apple) */
+
+ /* do not remove */
+ TT_SBIT_TABLE_TYPE_MAX
+
+ } TT_SbitTableType;
+
+
/*************************************************************************/
/* */
/* TrueType Face Type */
@@ -1030,7 +1111,7 @@
/* This field also contains the associated */
/* vertical metrics table (`vmtx'), if found. */
/* IMPORTANT: The contents of this field is */
- /* undefined if the `verticalInfo' field is */
+ /* undefined if the `vertical_info' field is */
/* unset. */
/* */
/* num_names :: The number of name records within this */
@@ -1090,13 +1171,6 @@
/* */
/* pclt :: The `pclt' SFNT table. */
/* */
- /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */
- /* sizes, embedded in this font. */
- /* */
- /* sbit_strikes :: An array of sbit strikes embedded in this */
- /* font. This table is optional in a */
- /* TrueType/OpenType font. */
- /* */
/* num_sbit_scales :: The number of sbit scales for this font. */
/* */
/* sbit_scales :: Array of sbit scales embedded in this */
@@ -1302,6 +1376,7 @@
FT_Byte* sbit_table;
FT_ULong sbit_table_size;
+ TT_SbitTableType sbit_table_type;
FT_UInt sbit_num_strikes;
FT_Byte* kern_table;
@@ -1363,7 +1438,7 @@
{
FT_Memory memory;
FT_UShort max_points;
- FT_UShort max_contours;
+ FT_Short max_contours;
FT_UShort n_points; /* number of points in zone */
FT_Short n_contours; /* number of contours */
@@ -1382,11 +1457,23 @@
/* handle to execution context */
typedef struct TT_ExecContextRec_* TT_ExecContext;
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* TT_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a TrueType size object. */
+ /* */
+ typedef struct TT_SizeRec_* TT_Size;
+
+
/* glyph loader structure */
typedef struct TT_LoaderRec_
{
- FT_Face face;
- FT_Size size;
+ TT_Face face;
+ TT_Size size;
FT_GlyphSlot glyph;
FT_GlyphLoader gloader;
@@ -1402,7 +1489,6 @@
FT_Int advance;
FT_Int linear;
FT_Bool linear_def;
- FT_Bool preserve_pps;
FT_Vector pp1;
FT_Vector pp2;
@@ -1429,6 +1515,9 @@
FT_Byte* cursor;
FT_Byte* limit;
+ /* since version 2.6.2 */
+ FT_ListRec composites;
+
} TT_LoaderRec;
diff --git a/include/freetype/t1tables.h b/include/freetype/t1tables.h
index a14255e..a6ea415 100644
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
/* Basic Type 1/Type 2 tables definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2004, 2006, 2008, 2009, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -49,6 +49,26 @@
/* This section contains the definition of Type 1-specific tables, */
/* including structures related to other PostScript font formats. */
/* */
+ /* <Order> */
+ /* PS_FontInfoRec */
+ /* PS_FontInfo */
+ /* PS_PrivateRec */
+ /* PS_Private */
+ /* */
+ /* CID_FaceDictRec */
+ /* CID_FaceDict */
+ /* CID_FaceInfoRec */
+ /* CID_FaceInfo */
+ /* */
+ /* FT_Has_PS_Glyph_Names */
+ /* FT_Get_PS_Font_Info */
+ /* FT_Get_PS_Font_Private */
+ /* FT_Get_PS_Font_Value */
+ /* */
+ /* T1_Blend_Flags */
+ /* T1_EncodingType */
+ /* PS_Dict_Keys */
+ /* */
/*************************************************************************/
@@ -190,14 +210,30 @@
/* given blend dictionary (font info or private). Used to support */
/* Multiple Masters fonts. */
/* */
+ /* <Values> */
+ /* T1_BLEND_UNDERLINE_POSITION :: */
+ /* T1_BLEND_UNDERLINE_THICKNESS :: */
+ /* T1_BLEND_ITALIC_ANGLE :: */
+ /* T1_BLEND_BLUE_VALUES :: */
+ /* T1_BLEND_OTHER_BLUES :: */
+ /* T1_BLEND_STANDARD_WIDTH :: */
+ /* T1_BLEND_STANDARD_HEIGHT :: */
+ /* T1_BLEND_STEM_SNAP_WIDTHS :: */
+ /* T1_BLEND_STEM_SNAP_HEIGHTS :: */
+ /* T1_BLEND_BLUE_SCALE :: */
+ /* T1_BLEND_BLUE_SHIFT :: */
+ /* T1_BLEND_FAMILY_BLUES :: */
+ /* T1_BLEND_FAMILY_OTHER_BLUES :: */
+ /* T1_BLEND_FORCE_BOLD :: */
+ /* */
typedef enum T1_Blend_Flags_
{
- /*# required fields in a FontInfo blend dictionary */
+ /* required fields in a FontInfo blend dictionary */
T1_BLEND_UNDERLINE_POSITION = 0,
T1_BLEND_UNDERLINE_THICKNESS,
T1_BLEND_ITALIC_ANGLE,
- /*# required fields in a Private blend dictionary */
+ /* required fields in a Private blend dictionary */
T1_BLEND_BLUE_VALUES,
T1_BLEND_OTHER_BLUES,
T1_BLEND_STANDARD_WIDTH,
@@ -210,15 +246,13 @@
T1_BLEND_FAMILY_OTHER_BLUES,
T1_BLEND_FORCE_BOLD,
- /*# never remove */
- T1_BLEND_MAX
+ T1_BLEND_MAX /* do not remove */
} T1_Blend_Flags;
- /* */
-
- /*# backwards compatible definitions */
+ /* these constants are deprecated; use the corresponding */
+ /* `T1_Blend_Flags' values instead */
#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION
#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS
#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE
@@ -235,6 +269,8 @@
#define t1_blend_force_bold T1_BLEND_FORCE_BOLD
#define t1_blend_max T1_BLEND_MAX
+ /* */
+
/* maximum number of Multiple Masters designs, as defined in the spec */
#define T1_MAX_MM_DESIGNS 16
@@ -333,10 +369,17 @@
/* */
typedef struct CID_FaceDictRec_* CID_FaceDict;
- /* */
-
- /* backwards-compatible definition */
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* CID_FontDict */
+ /* */
+ /* <Description> */
+ /* This type is equivalent to @CID_FaceDictRec. It is deprecated but */
+ /* kept to maintain source compatibility between various versions of */
+ /* FreeType. */
+ /* */
typedef CID_FaceDictRec CID_FontDict;
@@ -449,8 +492,9 @@
* FreeType error code. 0~means success.
*
* @note:
- * The string pointers within the font info structure are owned by
- * the face and don't need to be freed by the caller.
+ * String pointers within the @PS_FontInfoRec structure are owned by
+ * the face and don't need to be freed by the caller. Missing entries
+ * in the font's FontInfo dictionary are represented by NULL pointers.
*
* If the font's format is not PostScript-based, this function will
* return the `FT_Err_Invalid_Argument' error code.
@@ -503,6 +547,13 @@
/* An enumeration describing the `Encoding' entry in a Type 1 */
/* dictionary. */
/* */
+ /* <Values> */
+ /* T1_ENCODING_TYPE_NONE :: */
+ /* T1_ENCODING_TYPE_ARRAY :: */
+ /* T1_ENCODING_TYPE_STANDARD :: */
+ /* T1_ENCODING_TYPE_ISOLATIN1 :: */
+ /* T1_ENCODING_TYPE_EXPERT :: */
+ /* */
typedef enum T1_EncodingType_
{
T1_ENCODING_TYPE_NONE = 0,
@@ -523,6 +574,54 @@
/* An enumeration used in calls to @FT_Get_PS_Font_Value to identify */
/* the Type~1 dictionary entry to retrieve. */
/* */
+ /* <Values> */
+ /* PS_DICT_FONT_TYPE :: */
+ /* PS_DICT_FONT_MATRIX :: */
+ /* PS_DICT_FONT_BBOX :: */
+ /* PS_DICT_PAINT_TYPE :: */
+ /* PS_DICT_FONT_NAME :: */
+ /* PS_DICT_UNIQUE_ID :: */
+ /* PS_DICT_NUM_CHAR_STRINGS :: */
+ /* PS_DICT_CHAR_STRING_KEY :: */
+ /* PS_DICT_CHAR_STRING :: */
+ /* PS_DICT_ENCODING_TYPE :: */
+ /* PS_DICT_ENCODING_ENTRY :: */
+ /* PS_DICT_NUM_SUBRS :: */
+ /* PS_DICT_SUBR :: */
+ /* PS_DICT_STD_HW :: */
+ /* PS_DICT_STD_VW :: */
+ /* PS_DICT_NUM_BLUE_VALUES :: */
+ /* PS_DICT_BLUE_VALUE :: */
+ /* PS_DICT_BLUE_FUZZ :: */
+ /* PS_DICT_NUM_OTHER_BLUES :: */
+ /* PS_DICT_OTHER_BLUE :: */
+ /* PS_DICT_NUM_FAMILY_BLUES :: */
+ /* PS_DICT_FAMILY_BLUE :: */
+ /* PS_DICT_NUM_FAMILY_OTHER_BLUES :: */
+ /* PS_DICT_FAMILY_OTHER_BLUE :: */
+ /* PS_DICT_BLUE_SCALE :: */
+ /* PS_DICT_BLUE_SHIFT :: */
+ /* PS_DICT_NUM_STEM_SNAP_H :: */
+ /* PS_DICT_STEM_SNAP_H :: */
+ /* PS_DICT_NUM_STEM_SNAP_V :: */
+ /* PS_DICT_STEM_SNAP_V :: */
+ /* PS_DICT_FORCE_BOLD :: */
+ /* PS_DICT_RND_STEM_UP :: */
+ /* PS_DICT_MIN_FEATURE :: */
+ /* PS_DICT_LEN_IV :: */
+ /* PS_DICT_PASSWORD :: */
+ /* PS_DICT_LANGUAGE_GROUP :: */
+ /* PS_DICT_VERSION :: */
+ /* PS_DICT_NOTICE :: */
+ /* PS_DICT_FULL_NAME :: */
+ /* PS_DICT_FAMILY_NAME :: */
+ /* PS_DICT_WEIGHT :: */
+ /* PS_DICT_IS_FIXED_PITCH :: */
+ /* PS_DICT_UNDERLINE_POSITION :: */
+ /* PS_DICT_UNDERLINE_THICKNESS :: */
+ /* PS_DICT_FS_TYPE :: */
+ /* PS_DICT_ITALIC_ANGLE :: */
+ /* */
typedef enum PS_Dict_Keys_
{
/* conventionally in the font dictionary */
diff --git a/include/freetype/ttnameid.h b/include/freetype/ttnameid.h
index 173f88c..c9585f2 100644
--- a/include/freetype/ttnameid.h
+++ b/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
/* */
/* TrueType name ID definitions (specification only). */
/* */
-/* Copyright 1996-2004, 2006-2008, 2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -321,7 +321,7 @@
/* */
/* The canonical source for the Apple assigned Language ID's is at */
/* */
- /* https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html */
+ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html */
/* */
#define TT_MAC_LANGID_ENGLISH 0
#define TT_MAC_LANGID_FRENCH 1
@@ -470,26 +470,26 @@
#define TT_MS_LANGID_ARABIC_GENERAL 0x0001
#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_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_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_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_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_GENERAL 0x0004
#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_HONG_KONG 0x0C04
#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004
#if 1 /* this looks like the correct value */
@@ -507,7 +507,7 @@
#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_AUSTRIA 0x0C07
#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007
#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407
#define TT_MS_LANGID_GREEK_GREECE 0x0408
@@ -520,69 +520,69 @@
#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009
#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_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_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_TRINIDAD 0x2C09
#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009
#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409
#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809
-#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09
+#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3C09
#define TT_MS_LANGID_ENGLISH_INDIA 0x4009
#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409
#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809
-#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_SPANISH_UNITED_STATES 0x540a
+#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_SPANISH_UNITED_STATES 0x540A
/* The following ID blatantly violate MS specs by using a */
/* sublanguage > 0x1F. */
-#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU
-#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_FRENCH_WEST_INDIES 0x1c0c
-#define TT_MS_LANGID_FRENCH_REUNION 0x200c
-#define TT_MS_LANGID_FRENCH_CONGO 0x240c
+#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40AU
+#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_FRENCH_WEST_INDIES 0x1C0C
+#define TT_MS_LANGID_FRENCH_REUNION 0x200C
+#define TT_MS_LANGID_FRENCH_CONGO 0x240C
/* which was formerly: */
#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO
-#define TT_MS_LANGID_FRENCH_SENEGAL 0x280c
-#define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c
-#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c
-#define TT_MS_LANGID_FRENCH_MALI 0x340c
-#define TT_MS_LANGID_FRENCH_MOROCCO 0x380c
-#define TT_MS_LANGID_FRENCH_HAITI 0x3c0c
- /* and another violation of the spec (see 0xE40aU) */
-#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU
-#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_FRENCH_SENEGAL 0x280C
+#define TT_MS_LANGID_FRENCH_CAMEROON 0x2C0C
+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300C
+#define TT_MS_LANGID_FRENCH_MALI 0x340C
+#define TT_MS_LANGID_FRENCH_MOROCCO 0x380C
+#define TT_MS_LANGID_FRENCH_HAITI 0x3C0C
+ /* and another violation of the spec (see 0xE40AU) */
+#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40CU
+#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
@@ -600,27 +600,27 @@
#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_CROATIAN_CROATIA 0x041A
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A
#if 0 /* this used to be this value, but it looks like we were wrong */
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101A
#else /* current sources say */
-#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101a
-#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141a
+#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A
/* and XPsp2 Platform SDK added (2004-07-26) */
/* Names are shortened to be significant within 40 chars. */
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181a
-#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181a
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x181A
#endif
-#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_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_URDU_INDIA 0x0820
#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421
@@ -633,13 +633,13 @@
#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827
#define TT_MS_LANGID_TAJIK_TAJIKISTAN 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_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
@@ -650,32 +650,32 @@
#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_MALTESE_MALTA 0x043A
/* Added by XPsp2 Platform SDK (2004-07-26) */
-#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043b
-#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083b
-#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3b
-#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103b
-#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143b
-#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183b
-#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3b
-#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203b
-#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243b
+#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B
+#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B
+#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B
+#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103B
+#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143B
+#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183B
+#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B
+#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B
+#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B
/* ... and we also keep our old identifier... */
-#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b
+#define TT_MS_LANGID_SAAMI_LAPONIA 0x043B
#if 0 /* this seems to be a previous inversion */
-#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c
-#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C
#else
-#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c
-#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C
#endif
-#define TT_MS_LANGID_YIDDISH_GERMANY 0x043d
-#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_YIDDISH_GERMANY 0x043D
+#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_KIRGHIZ_KIRGHIZSTAN /* Cyrillic*/ 0x0440
/* alias declared in Windows 2000 */
#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \
@@ -693,12 +693,12 @@
#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_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_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450
#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850
#define TT_MS_LANGID_TIBETAN_CHINA 0x0451
@@ -732,13 +732,13 @@
#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459
#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859
/* Missing a LCID for Sindhi in Devanagari script */
-#define TT_MS_LANGID_SYRIAC_SYRIA 0x045a
-#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b
-#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c
-#define TT_MS_LANGID_INUKTITUT_CANADA 0x045d
-#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e
-#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045f
-#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f
+#define TT_MS_LANGID_SYRIAC_SYRIA 0x045A
+#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045B
+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045C
+#define TT_MS_LANGID_INUKTITUT_CANADA 0x045D
+#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045F
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085F
/* Missing a LCID for Tifinagh script */
#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460
/* Spelled this way by XPsp2 Platform SDK (2004-07-26) */
@@ -758,15 +758,15 @@
#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467
#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468
#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469
-#define TT_MS_LANGID_YORUBA_NIGERIA 0x046a
-#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046b
-#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086b
-#define TT_MS_LANGID_QUECHUA_PERU 0x0c6b
-#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046c
+#define TT_MS_LANGID_YORUBA_NIGERIA 0x046A
+#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B
+#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B
+#define TT_MS_LANGID_QUECHUA_PERU 0x0C6B
+#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA 0x046C
/* Also spelled by XPsp2 Platform SDK (2004-07-26) */
#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \
TT_MS_LANGID_SEPEDI_SOUTH_AFRICA
- /* language codes 0x046d, 0x046e and 0x046f are (still) unknown. */
+ /* language codes 0x046D, 0x046E and 0x046F are (still) unknown. */
#define TT_MS_LANGID_IGBO_NIGERIA 0x0470
#define TT_MS_LANGID_KANURI_NIGERIA 0x0471
#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472
@@ -783,12 +783,12 @@
/* studying). */
#define TT_MS_LANGID_YI_CHINA 0x0478
#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479
- /* language codes from 0x047a to 0x047f are (still) unknown. */
+ /* language codes from 0x047A to 0x047F are (still) unknown. */
#define TT_MS_LANGID_UIGHUR_CHINA 0x0480
#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481
#if 0 /* not deemed useful for fonts */
-#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04ff
+#define TT_MS_LANGID_HUMAN_INTERFACE_DEVICE 0x04FF
#endif
@@ -1208,7 +1208,7 @@
/* */
/* Here some alias #defines in order to be clearer. */
/* */
- /* These are not always #defined to stay within the 31~character limit */
+ /* 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 */
diff --git a/include/freetype/tttables.h b/include/freetype/tttables.h
index fe07117..1568f40 100644
--- a/include/freetype/tttables.h
+++ b/include/freetype/tttables.h
@@ -5,7 +5,7 @@
/* Basic SFNT/TrueType tables definitions and interface */
/* (specification only). */
/* */
-/* Copyright 1996-2005, 2008-2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,6 +48,25 @@
/* This section contains the definition of TrueType-specific tables */
/* as well as some routines used to access and process them. */
/* */
+ /* <Order> */
+ /* TT_Header */
+ /* TT_HoriHeader */
+ /* TT_VertHeader */
+ /* TT_OS2 */
+ /* TT_Postscript */
+ /* TT_PCLT */
+ /* TT_MaxProfile */
+ /* */
+ /* FT_Sfnt_Tag */
+ /* FT_Get_Sfnt_Table */
+ /* FT_Load_Sfnt_Table */
+ /* FT_Sfnt_Table_Info */
+ /* */
+ /* FT_Get_CMap_Language_ID */
+ /* FT_Get_CMap_Format */
+ /* */
+ /* FT_PARAM_TAG_UNPATENTED_HINTING */
+ /* */
/*************************************************************************/
@@ -170,8 +189,8 @@
/* */
/* <Note> */
/* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
- /* be identical except for the names of their fields which */
- /* are different. */
+ /* be identical except for the names of their fields, */
+ /* which are different. */
/* */
/* This ensures that a single function in the `ttload' */
/* module is able to read both the horizontal and vertical */
@@ -296,8 +315,8 @@
/* */
/* <Note> */
/* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */
- /* be identical except for the names of their fields which */
- /* are different. */
+ /* be identical except for the names of their fields, */
+ /* which are different. */
/* */
/* This ensures that a single function in the `ttload' */
/* module is able to read both the horizontal and vertical */
@@ -340,12 +359,11 @@
/* TT_OS2 */
/* */
/* <Description> */
- /* A structure used to model a TrueType OS/2 table. This is the long */
- /* table version. All fields comply to the TrueType specification. */
+ /* A structure used to model a TrueType OS/2 table. All fields */
+ /* comply to the OpenType specification. */
/* */
- /* Note that we now support old Mac fonts which do not include an */
- /* OS/2 table. In this case, the `version' field is always set to */
- /* 0xFFFF. */
+ /* Note that we now support old Mac fonts that do not include an OS/2 */
+ /* table. In this case, the `version' field is always set to 0xFFFF. */
/* */
typedef struct TT_OS2_
{
@@ -353,7 +371,7 @@
FT_Short xAvgCharWidth;
FT_UShort usWeightClass;
FT_UShort usWidthClass;
- FT_Short fsType;
+ FT_UShort fsType;
FT_Short ySubscriptXSize;
FT_Short ySubscriptYSize;
FT_Short ySubscriptXOffset;
@@ -384,12 +402,12 @@
FT_UShort usWinAscent;
FT_UShort usWinDescent;
- /* only version 1 tables: */
+ /* only version 1 and higher: */
FT_ULong ulCodePageRange1; /* Bits 0-31 */
FT_ULong ulCodePageRange2; /* Bits 32-63 */
- /* only version 2 tables: */
+ /* only version 2 and higher: */
FT_Short sxHeight;
FT_Short sCapHeight;
@@ -397,6 +415,11 @@
FT_UShort usBreakChar;
FT_UShort usMaxContext;
+ /* only version 5 and higher: */
+
+ FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */
+ FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */
+
} TT_OS2;
@@ -465,7 +488,7 @@
/* TT_MaxProfile */
/* */
/* <Description> */
- /* The maximum profile is a table containing many max values which */
+ /* The maximum profile is a table containing many max values, which */
/* can be used to pre-allocate arrays. This ensures that no memory */
/* allocation occurs during a glyph load. */
/* */
@@ -555,21 +578,44 @@
/* An enumeration used to specify the index of an SFNT table. */
/* Used in the @FT_Get_Sfnt_Table API function. */
/* */
+ /* <Values> */
+ /* FT_SFNT_HEAD :: To access the font's @TT_Header structure. */
+ /* */
+ /* FT_SFNT_MAXP :: To access the font's @TT_MaxProfile structure. */
+ /* */
+ /* FT_SFNT_OS2 :: To access the font's @TT_OS2 structure. */
+ /* */
+ /* FT_SFNT_HHEA :: To access the font's @TT_HoriHeader structure. */
+ /* */
+ /* FT_SFNT_VHEA :: To access the font's @TT_VertHeader struture. */
+ /* */
+ /* FT_SFNT_POST :: To access the font's @TT_Postscript structure. */
+ /* */
+ /* FT_SFNT_PCLT :: To access the font's @TT_PCLT structure. */
+ /* */
typedef enum FT_Sfnt_Tag_
{
- ft_sfnt_head = 0, /* TT_Header */
- ft_sfnt_maxp = 1, /* TT_MaxProfile */
- ft_sfnt_os2 = 2, /* TT_OS2 */
- ft_sfnt_hhea = 3, /* TT_HoriHeader */
- ft_sfnt_vhea = 4, /* TT_VertHeader */
- ft_sfnt_post = 5, /* TT_Postscript */
- ft_sfnt_pclt = 6, /* TT_PCLT */
+ FT_SFNT_HEAD,
+ FT_SFNT_MAXP,
+ FT_SFNT_OS2,
+ FT_SFNT_HHEA,
+ FT_SFNT_VHEA,
+ FT_SFNT_POST,
+ FT_SFNT_PCLT,
- sfnt_max /* internal end mark */
+ FT_SFNT_MAX
} FT_Sfnt_Tag;
- /* */
+ /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag' */
+ /* values instead */
+#define ft_sfnt_head FT_SFNT_HEAD
+#define ft_sfnt_maxp FT_SFNT_MAXP
+#define ft_sfnt_os2 FT_SFNT_OS2
+#define ft_sfnt_hhea FT_SFNT_HHEA
+#define ft_sfnt_vhea FT_SFNT_VHEA
+#define ft_sfnt_post FT_SFNT_POST
+#define ft_sfnt_pclt FT_SFNT_PCLT
/*************************************************************************/
@@ -607,7 +653,7 @@
/* */
/* */
/* vert_header = */
- /* (TT_VertHeader*)FT_Get_Sfnt_Table( face, ft_sfnt_vhea ); */
+ /* (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA ); */
/* } */
/* */
FT_EXPORT( void* )
@@ -672,6 +718,12 @@
* error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
* if ( error ) { ... could not load table ... }
* }
+ *
+ * Note that structures like @TT_Header or @TT_OS2 can't be used with
+ * this function; they are limited to @FT_Get_Sfnt_Table. Reason is that
+ * those structures depend on the processor architecture, with varying
+ * size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian).
+ *
*/
FT_EXPORT( FT_Error )
FT_Load_Sfnt_Table( FT_Face face,
@@ -730,7 +782,7 @@
/* */
/* <Description> */
/* Return TrueType/sfnt specific cmap language ID. Definitions of */
- /* language ID values are in `freetype/ttnameid.h'. */
+ /* language ID values are in `ttnameid.h'. */
/* */
/* <Input> */
/* charmap :: */
diff --git a/include/freetype/tttags.h b/include/freetype/tttags.h
index be8c524..3836c7b 100644
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -4,7 +4,7 @@
/* */
/* Tags for TrueType and OpenType tables (specification only). */
/* */
-/* Copyright 1996-2001, 2004, 2005, 2007, 2008, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -88,6 +88,7 @@
#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
+#define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' )
#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' )
#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )
@@ -99,6 +100,7 @@
#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+#define TTAG_wOFF FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
FT_END_HEADER
diff --git a/include/freetype/ttunpat.h b/include/freetype/ttunpat.h
index a016275..8ea5568 100644
--- a/include/freetype/ttunpat.h
+++ b/include/freetype/ttunpat.h
@@ -4,7 +4,7 @@
/* */
/* Definitions for the unpatented TrueType hinting system */
/* */
-/* Copyright 2003, 2006 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* Written by Graham Asher <graham.asher@btinternet.com> */
@@ -48,7 +48,8 @@
*/
#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
- /* */
+ /* */
+
FT_END_HEADER
diff --git a/include/ft2build.h b/include/ft2build.h
index 923d887..419b80a 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -3,9 +3,8 @@
/* ft2build.h */
/* */
/* FreeType 2 build and setup macros. */
-/* (Generic version) */
/* */
-/* Copyright 1996-2001, 2006 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,21 +18,25 @@
/*************************************************************************/
/* */
- /* This file corresponds to the default `ft2build.h' file for */
- /* FreeType 2. It uses the `freetype' include root. */
+ /* This is the `entry point' for FreeType header file inclusions. It is */
+ /* the only header file which should be included directly; all other */
+ /* FreeType header files should be accessed with macro names (after */
+ /* including `ft2build.h'). */
/* */
- /* Note that specific platforms might use a different configuration. */
- /* See builds/unix/ft2unix.h for an example. */
+ /* A typical example is */
+ /* */
+ /* #include <ft2build.h> */
+ /* #include FT_FREETYPE_H */
/* */
/*************************************************************************/
-#ifndef __FT2_BUILD_GENERIC_H__
-#define __FT2_BUILD_GENERIC_H__
+#ifndef __FT2BUILD_H__
+#define __FT2BUILD_H__
#include <freetype/config/ftheader.h>
-#endif /* __FT2_BUILD_GENERIC_H__ */
+#endif /* __FT2BUILD_H__ */
/* END */
diff --git a/module_option.diff b/module_option.diff
new file mode 100644
index 0000000..75079ce
--- /dev/null
+++ b/module_option.diff
@@ -0,0 +1,57 @@
+diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h
+index 76d271a..e145790 100644
+--- a/include/freetype/config/ftmodule.h
++++ b/include/freetype/config/ftmodule.h
+@@ -12,14 +12,7 @@
+
+ FT_USE_MODULE( FT_Module_Class, autofit_module_class )
+ FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
+ FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
+-FT_USE_MODULE( FT_Module_Class, psaux_module_class )
+ FT_USE_MODULE( FT_Module_Class, psnames_module_class )
+ FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
+@@ -27,6 +20,5 @@ FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class )
+ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class )
+-FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
+
+ /* EOF */
+diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
+index b481f8f..3819586 100644
+--- a/include/freetype/config/ftoption.h
++++ b/include/freetype/config/ftoption.h
+@@ -225,7 +225,7 @@ FT_BEGIN_HEADER
+ /* */
+ /* Define this macro if you want to enable this `feature'. */
+ /* */
+-/* #define FT_CONFIG_OPTION_USE_PNG */
++#define FT_CONFIG_OPTION_USE_PNG
+
+
+ /*************************************************************************/
+@@ -370,7 +370,7 @@ FT_BEGIN_HEADER
+ /* supply font data incrementally as the document is parsed, such */
+ /* as the Ghostscript interpreter for the PostScript language. */
+ /* */
+-#define FT_CONFIG_OPTION_INCREMENTAL
++/* #define FT_CONFIG_OPTION_INCREMENTAL */
+
+
+ /*************************************************************************/
+@@ -843,7 +843,7 @@ FT_BEGIN_HEADER
+ /* `warping' property of the auto-hinter (see file `ftautoh.h' for more */
+ /* information; by default it is switched off). */
+ /* */
+-#define AF_CONFIG_OPTION_USE_WARPER
++/* #define AF_CONFIG_OPTION_USE_WARPER */
+
+ /* */
+
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index b44a5ba..1b1eb31 100644
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -5,7 +5,7 @@
/* Routines used to compute vector angles with limited accuracy */
/* and very high speed. It also contains sorting routines (body). */
/* */
-/* Copyright 2003-2006, 2011-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,66 +20,6 @@
#include "aftypes.h"
-#if 0
-
- FT_LOCAL_DEF( FT_Int )
- af_corner_is_flat( FT_Pos x_in,
- FT_Pos y_in,
- FT_Pos x_out,
- FT_Pos y_out )
- {
- FT_Pos ax = x_in;
- FT_Pos ay = y_in;
-
- FT_Pos d_in, d_out, d_corner;
-
-
- if ( ax < 0 )
- ax = -ax;
- if ( ay < 0 )
- ay = -ay;
- d_in = ax + ay;
-
- ax = x_out;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out;
- if ( ay < 0 )
- ay = -ay;
- d_out = ax + ay;
-
- ax = x_out + x_in;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out + y_in;
- if ( ay < 0 )
- ay = -ay;
- d_corner = ax + ay;
-
- return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
- }
-
-
- FT_LOCAL_DEF( FT_Int )
- af_corner_orientation( FT_Pos x_in,
- FT_Pos y_in,
- FT_Pos x_out,
- FT_Pos y_out )
- {
- FT_Pos delta;
-
-
- delta = x_in * y_out - y_in * x_out;
-
- if ( delta == 0 )
- return 0;
- else
- return 1 - 2 * ( delta < 0 );
- }
-
-#endif /* 0 */
-
-
/*
* We are not using `af_angle_atan' anymore, but we keep the source
* code below just in case...
@@ -319,7 +259,7 @@
sum += table[j].org;
table[j].org = 0;
}
- table[cur_idx].org = sum / j;
+ table[cur_idx].org = sum / (FT_Pos)j;
if ( i < *count - 1 )
{
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
new file mode 100644
index 0000000..104ee17
--- /dev/null
+++ b/src/autofit/afblue.c
@@ -0,0 +1,302 @@
+/* This file has been generated by the Perl script `afblue.pl', */
+/* using data from file `afblue.dat'. */
+
+/***************************************************************************/
+/* */
+/* afblue.c */
+/* */
+/* Auto-fitter data for blue strings (body). */
+/* */
+/* Copyright 2013-2015 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 "aftypes.h"
+
+
+ FT_LOCAL_ARRAY_DEF( char )
+ af_blue_strings[] =
+ {
+ /* */
+ '\xD8', '\xA7', ' ', '\xD8', '\xA5', ' ', '\xD9', '\x84', ' ', '\xD9', '\x83', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', /* ا إ ل ك ط ظ */
+ '\0',
+ '\xD8', '\xAA', ' ', '\xD8', '\xAB', ' ', '\xD8', '\xB7', ' ', '\xD8', '\xB8', ' ', '\xD9', '\x83', /* ت ث ط ظ ك */
+ '\0',
+ '\xD9', '\x80', /* ـ */
+ '\0',
+ '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\x9F', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е П З О С Э */
+ '\0',
+ '\xD0', '\x91', ' ', '\xD0', '\x92', ' ', '\xD0', '\x95', ' ', '\xD0', '\xA8', ' ', '\xD0', '\x97', ' ', '\xD0', '\x9E', ' ', '\xD0', '\xA1', ' ', '\xD0', '\xAD', /* Б В Е Ш З О С Э */
+ '\0',
+ '\xD1', '\x85', ' ', '\xD0', '\xBF', ' ', '\xD0', '\xBD', ' ', '\xD1', '\x88', ' ', '\xD0', '\xB5', ' ', '\xD0', '\xB7', ' ', '\xD0', '\xBE', ' ', '\xD1', '\x81', /* х п н ш е з о с */
+ '\0',
+ '\xD1', '\x80', ' ', '\xD1', '\x83', ' ', '\xD1', '\x84', /* р у ф */
+ '\0',
+ '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
+ '\0',
+ '\xE0', '\xA4', '\x88', ' ', '\xE0', '\xA4', '\x90', ' ', '\xE0', '\xA4', '\x93', ' ', '\xE0', '\xA4', '\x94', ' ', '\xE0', '\xA4', '\xBF', ' ', '\xE0', '\xA5', '\x80', ' ', '\xE0', '\xA5', '\x8B', ' ', '\xE0', '\xA5', '\x8C', /* ई ऐ ओ औ ि ी ो ौ */
+ '\0',
+ '\xE0', '\xA4', '\x95', ' ', '\xE0', '\xA4', '\xAE', ' ', '\xE0', '\xA4', '\x85', ' ', '\xE0', '\xA4', '\x86', ' ', '\xE0', '\xA4', '\xA5', ' ', '\xE0', '\xA4', '\xA7', ' ', '\xE0', '\xA4', '\xAD', ' ', '\xE0', '\xA4', '\xB6', /* क म अ आ थ ध भ श */
+ '\0',
+ '\xE0', '\xA5', '\x81', ' ', '\xE0', '\xA5', '\x83', /* ु ृ */
+ '\0',
+ '\xCE', '\x93', ' ', '\xCE', '\x92', ' ', '\xCE', '\x95', ' ', '\xCE', '\x96', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', ' ', '\xCE', '\xA9', /* Γ Β Ε Ζ Θ Ο Ω */
+ '\0',
+ '\xCE', '\x92', ' ', '\xCE', '\x94', ' ', '\xCE', '\x96', ' ', '\xCE', '\x9E', ' ', '\xCE', '\x98', ' ', '\xCE', '\x9F', /* Β Δ Ζ Ξ Θ Ο */
+ '\0',
+ '\xCE', '\xB2', ' ', '\xCE', '\xB8', ' ', '\xCE', '\xB4', ' ', '\xCE', '\xB6', ' ', '\xCE', '\xBB', ' ', '\xCE', '\xBE', /* β θ δ ζ λ ξ */
+ '\0',
+ '\xCE', '\xB1', ' ', '\xCE', '\xB5', ' ', '\xCE', '\xB9', ' ', '\xCE', '\xBF', ' ', '\xCF', '\x80', ' ', '\xCF', '\x83', ' ', '\xCF', '\x84', ' ', '\xCF', '\x89', /* α ε ι ο π σ τ ω */
+ '\0',
+ '\xCE', '\xB2', ' ', '\xCE', '\xB3', ' ', '\xCE', '\xB7', ' ', '\xCE', '\xBC', ' ', '\xCF', '\x81', ' ', '\xCF', '\x86', ' ', '\xCF', '\x87', ' ', '\xCF', '\x88', /* β γ η μ ρ φ χ ψ */
+ '\0',
+ '\xD7', '\x91', ' ', '\xD7', '\x93', ' ', '\xD7', '\x94', ' ', '\xD7', '\x97', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', /* ב ד ה ח ך כ ם ס */
+ '\0',
+ '\xD7', '\x91', ' ', '\xD7', '\x98', ' ', '\xD7', '\x9B', ' ', '\xD7', '\x9D', ' ', '\xD7', '\xA1', ' ', '\xD7', '\xA6', /* ב ט כ ם ס צ */
+ '\0',
+ '\xD7', '\xA7', ' ', '\xD7', '\x9A', ' ', '\xD7', '\x9F', ' ', '\xD7', '\xA3', ' ', '\xD7', '\xA5', /* ק ך ן ף ץ */
+ '\0',
+ '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6', /* ខ ទ ន ឧ ឩ ា */
+ '\0',
+ '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90', /* ក្ក ក្ខ ក្គ ក្ថ */
+ '\0',
+ '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2', /* ខ ឃ ច ឋ ប ម យ ឲ */
+ '\0',
+ '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF', /* ត្រ រៀ ឲ្យ អឿ */
+ '\0',
+ '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x83', ' ', '\xE1', '\x9E', '\x84', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x85', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\x93', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x8F', '\xE1', '\x9E', '\xBF', ' ', '\xE1', '\x9E', '\x9B', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x94', '\xE1', '\x9E', '\xBF', /* ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ */
+ '\0',
+ '\xE1', '\xA7', '\xA0', ' ', '\xE1', '\xA7', '\xA1', /* ᧠ ᧡ */
+ '\0',
+ '\xE1', '\xA7', '\xB6', ' ', '\xE1', '\xA7', '\xB9', /* ᧶ ᧹ */
+ '\0',
+ '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\x94', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\xA1', ' ', '\xE0', '\xBA', '\xA5', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\x87', /* າ ດ ອ ມ ລ ວ ຣ ງ */
+ '\0',
+ '\xE0', '\xBA', '\xB2', ' ', '\xE0', '\xBA', '\xAD', ' ', '\xE0', '\xBA', '\x9A', ' ', '\xE0', '\xBA', '\x8D', ' ', '\xE0', '\xBA', '\xA3', ' ', '\xE0', '\xBA', '\xAE', ' ', '\xE0', '\xBA', '\xA7', ' ', '\xE0', '\xBA', '\xA2', /* າ ອ ບ ຍ ຣ ຮ ວ ຢ */
+ '\0',
+ '\xE0', '\xBA', '\x9B', ' ', '\xE0', '\xBA', '\xA2', ' ', '\xE0', '\xBA', '\x9F', ' ', '\xE0', '\xBA', '\x9D', /* ປ ຢ ຟ ຝ */
+ '\0',
+ '\xE0', '\xBB', '\x82', ' ', '\xE0', '\xBB', '\x84', ' ', '\xE0', '\xBB', '\x83', /* ໂ ໄ ໃ */
+ '\0',
+ '\xE0', '\xBA', '\x87', ' ', '\xE0', '\xBA', '\x8A', ' ', '\xE0', '\xBA', '\x96', ' ', '\xE0', '\xBA', '\xBD', ' ', '\xE0', '\xBB', '\x86', ' ', '\xE0', '\xBA', '\xAF', /* ງ ຊ ຖ ຽ ໆ ຯ */
+ '\0',
+ 'T', ' ', 'H', ' ', 'E', ' ', 'Z', ' ', 'O', ' ', 'C', ' ', 'Q', ' ', 'S', /* T H E Z O C Q S */
+ '\0',
+ 'H', ' ', 'E', ' ', 'Z', ' ', 'L', ' ', 'O', ' ', 'C', ' ', 'U', ' ', 'S', /* H E Z L O C U S */
+ '\0',
+ 'f', ' ', 'i', ' ', 'j', ' ', 'k', ' ', 'd', ' ', 'b', ' ', 'h', /* f i j k d b h */
+ '\0',
+ 'x', ' ', 'z', ' ', 'r', ' ', 'o', ' ', 'e', ' ', 's', ' ', 'c', /* x z r o e s c */
+ '\0',
+ 'p', ' ', 'q', ' ', 'g', ' ', 'j', ' ', 'y', /* p q g j y */
+ '\0',
+ '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x85', ' ', '\xE2', '\x82', '\x87', ' ', '\xE2', '\x82', '\x88', /* ₀ ₃ ₅ ₇ ₈ */
+ '\0',
+ '\xE2', '\x82', '\x80', ' ', '\xE2', '\x82', '\x81', ' ', '\xE2', '\x82', '\x82', ' ', '\xE2', '\x82', '\x83', ' ', '\xE2', '\x82', '\x88', /* ₀ ₁ ₂ ₃ ₈ */
+ '\0',
+ '\xE1', '\xB5', '\xA2', ' ', '\xE2', '\xB1', '\xBC', ' ', '\xE2', '\x82', '\x95', ' ', '\xE2', '\x82', '\x96', ' ', '\xE2', '\x82', '\x97', /* ᵢ ⱼ ₕ ₖ ₗ */
+ '\0',
+ '\xE2', '\x82', '\x90', ' ', '\xE2', '\x82', '\x91', ' ', '\xE2', '\x82', '\x92', ' ', '\xE2', '\x82', '\x93', ' ', '\xE2', '\x82', '\x99', ' ', '\xE2', '\x82', '\x9B', ' ', '\xE1', '\xB5', '\xA5', ' ', '\xE1', '\xB5', '\xA4', ' ', '\xE1', '\xB5', '\xA3', /* ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ */
+ '\0',
+ '\xE1', '\xB5', '\xA6', ' ', '\xE1', '\xB5', '\xA7', ' ', '\xE1', '\xB5', '\xA8', ' ', '\xE1', '\xB5', '\xA9', ' ', '\xE2', '\x82', '\x9A', /* ᵦ ᵧ ᵨ ᵩ ₚ */
+ '\0',
+ '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB3', ' ', '\xE2', '\x81', '\xB5', ' ', '\xE2', '\x81', '\xB7', ' ', '\xE1', '\xB5', '\x80', ' ', '\xE1', '\xB4', '\xB4', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xBC', /* ⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ */
+ '\0',
+ '\xE2', '\x81', '\xB0', ' ', '\xC2', '\xB9', ' ', '\xC2', '\xB2', ' ', '\xC2', '\xB3', ' ', '\xE1', '\xB4', '\xB1', ' ', '\xE1', '\xB4', '\xB8', ' ', '\xE1', '\xB4', '\xBC', ' ', '\xE1', '\xB5', '\x81', /* ⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ */
+ '\0',
+ '\xE1', '\xB5', '\x87', ' ', '\xE1', '\xB5', '\x88', ' ', '\xE1', '\xB5', '\x8F', ' ', '\xCA', '\xB0', ' ', '\xCA', '\xB2', ' ', '\xE1', '\xB6', '\xA0', ' ', '\xE2', '\x81', '\xB1', /* ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ */
+ '\0',
+ '\xE1', '\xB5', '\x89', ' ', '\xE1', '\xB5', '\x92', ' ', '\xCA', '\xB3', ' ', '\xCB', '\xA2', ' ', '\xCB', '\xA3', ' ', '\xE1', '\xB6', '\x9C', ' ', '\xE1', '\xB6', '\xBB', /* ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ */
+ '\0',
+ '\xE1', '\xB5', '\x96', ' ', '\xCA', '\xB8', ' ', '\xE1', '\xB5', '\x8D', /* ᵖ ʸ ᵍ */
+ '\0',
+ '\xE1', '\x80', '\x81', ' ', '\xE1', '\x80', '\x82', ' ', '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\xA5', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* ခ ဂ င ဒ ဝ ၥ ၊ ။ */
+ '\0',
+ '\xE1', '\x80', '\x84', ' ', '\xE1', '\x80', '\x8E', ' ', '\xE1', '\x80', '\x92', ' ', '\xE1', '\x80', '\x95', ' ', '\xE1', '\x80', '\x97', ' ', '\xE1', '\x80', '\x9D', ' ', '\xE1', '\x81', '\x8A', ' ', '\xE1', '\x81', '\x8B', /* င ဎ ဒ ပ ဗ ဝ ၊ ။ */
+ '\0',
+ '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xBC', ' ', '\xE1', '\x81', '\x8D', ' ', '\xE1', '\x81', '\x8F', ' ', '\xE1', '\x81', '\x86', ' ', '\xE1', '\x80', '\xAB', ' ', '\xE1', '\x80', '\xAD', /* ဩ ြ ၍ ၏ ၆ ါ ိ */
+ '\0',
+ '\xE1', '\x80', '\x89', ' ', '\xE1', '\x80', '\x8A', ' ', '\xE1', '\x80', '\xA5', ' ', '\xE1', '\x80', '\xA9', ' ', '\xE1', '\x80', '\xA8', ' ', '\xE1', '\x81', '\x82', ' ', '\xE1', '\x81', '\x85', ' ', '\xE1', '\x81', '\x89', /* ဉ ည ဥ ဩ ဨ ၂ ၅ ၉ */
+ '\0',
+ '\xE0', '\xB0', '\x87', ' ', '\xE0', '\xB0', '\x8C', ' ', '\xE0', '\xB0', '\x99', ' ', '\xE0', '\xB0', '\x9E', ' ', '\xE0', '\xB0', '\xA3', ' ', '\xE0', '\xB0', '\xB1', ' ', '\xE0', '\xB1', '\xAF', /* ఇ ఌ ఙ ఞ ణ ఱ ౯ */
+ '\0',
+ '\xE0', '\xB0', '\x85', ' ', '\xE0', '\xB0', '\x95', ' ', '\xE0', '\xB0', '\x9A', ' ', '\xE0', '\xB0', '\xB0', ' ', '\xE0', '\xB0', '\xBD', ' ', '\xE0', '\xB1', '\xA8', ' ', '\xE0', '\xB1', '\xAC', /* అ క చ ర ఽ ౨ ౬ */
+ '\0',
+ '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB9', '\x80', ' ', '\xE0', '\xB9', '\x81', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\x81', ' ', '\xE0', '\xB8', '\xB2', /* บ เ แ อ ก า */
+ '\0',
+ '\xE0', '\xB8', '\x9A', ' ', '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\xA9', ' ', '\xE0', '\xB8', '\xAF', ' ', '\xE0', '\xB8', '\xAD', ' ', '\xE0', '\xB8', '\xA2', ' ', '\xE0', '\xB8', '\xAE', /* บ ป ษ ฯ อ ย ฮ */
+ '\0',
+ '\xE0', '\xB8', '\x9B', ' ', '\xE0', '\xB8', '\x9D', ' ', '\xE0', '\xB8', '\x9F', /* ป ฝ ฟ */
+ '\0',
+ '\xE0', '\xB9', '\x82', ' ', '\xE0', '\xB9', '\x83', ' ', '\xE0', '\xB9', '\x84', /* โ ใ ไ */
+ '\0',
+ '\xE0', '\xB8', '\x8E', ' ', '\xE0', '\xB8', '\x8F', ' ', '\xE0', '\xB8', '\xA4', ' ', '\xE0', '\xB8', '\xA6', /* ฎ ฏ ฤ ฦ */
+ '\0',
+ '\xE0', '\xB8', '\x8D', ' ', '\xE0', '\xB8', '\x90', /* ญ ฐ */
+ '\0',
+ '\xE0', '\xB9', '\x90', ' ', '\xE0', '\xB9', '\x91', ' ', '\xE0', '\xB9', '\x93', /* ๐ ๑ ๓ */
+#ifdef AF_CONFIG_OPTION_CJK
+ '\0',
+ '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 他 们 你 來 們 到 和 地 */
+ ' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB8', '\xAD', ' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x83', /* 对 對 就 席 我 时 時 會 */
+ ' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\x88', '\xB0', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 来 為 能 舰 說 说 这 這 */
+ ' ', '\xE9', '\xBD', '\x8A', ' ', '|', /* 齊 | */
+ ' ', '\xE5', '\x86', '\x9B', ' ', '\xE5', '\x90', '\x8C', ' ', '\xE5', '\xB7', '\xB2', ' ', '\xE6', '\x84', '\xBF', ' ', '\xE6', '\x97', '\xA2', ' ', '\xE6', '\x98', '\x9F', ' ', '\xE6', '\x98', '\xAF', ' ', '\xE6', '\x99', '\xAF', /* 军 同 已 愿 既 星 是 景 */
+ ' ', '\xE6', '\xB0', '\x91', ' ', '\xE7', '\x85', '\xA7', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\xA8', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\xA6', '\x81', /* 民 照 现 現 理 用 置 要 */
+ ' ', '\xE8', '\xBB', '\x8D', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x85', '\x8D', ' ', '\xE9', '\x87', '\x8C', ' ', '\xE9', '\x96', '\x8B', ' ', '\xE9', '\x9B', '\xB7', ' ', '\xE9', '\x9C', '\xB2', ' ', '\xE9', '\x9D', '\xA2', /* 軍 那 配 里 開 雷 露 面 */
+ ' ', '\xE9', '\xA1', '\xBE', /* 顾 */
+ '\0',
+ '\xE4', '\xB8', '\xAA', ' ', '\xE4', '\xB8', '\xBA', ' ', '\xE4', '\xBA', '\xBA', ' ', '\xE4', '\xBB', '\x96', ' ', '\xE4', '\xBB', '\xA5', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', /* 个 为 人 他 以 们 你 來 */
+ ' ', '\xE5', '\x80', '\x8B', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\xA4', '\xA7', ' ', '\xE5', '\xAF', '\xB9', ' ', '\xE5', '\xB0', '\x8D', ' ', '\xE5', '\xB0', '\xB1', /* 個 們 到 和 大 对 對 就 */
+ ' ', '\xE6', '\x88', '\x91', ' ', '\xE6', '\x97', '\xB6', ' ', '\xE6', '\x99', '\x82', ' ', '\xE6', '\x9C', '\x89', ' ', '\xE6', '\x9D', '\xA5', ' ', '\xE7', '\x82', '\xBA', ' ', '\xE8', '\xA6', '\x81', ' ', '\xE8', '\xAA', '\xAA', /* 我 时 時 有 来 為 要 說 */
+ ' ', '\xE8', '\xAF', '\xB4', ' ', '|', /* 说 | */
+ ' ', '\xE4', '\xB8', '\xBB', ' ', '\xE4', '\xBA', '\x9B', ' ', '\xE5', '\x9B', '\xA0', ' ', '\xE5', '\xAE', '\x83', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x84', '\x8F', ' ', '\xE7', '\x90', '\x86', ' ', '\xE7', '\x94', '\x9F', /* 主 些 因 它 想 意 理 生 */
+ ' ', '\xE7', '\x95', '\xB6', ' ', '\xE7', '\x9C', '\x8B', ' ', '\xE7', '\x9D', '\x80', ' ', '\xE7', '\xBD', '\xAE', ' ', '\xE8', '\x80', '\x85', ' ', '\xE8', '\x87', '\xAA', ' ', '\xE8', '\x91', '\x97', ' ', '\xE8', '\xA3', '\xA1', /* 當 看 着 置 者 自 著 裡 */
+ ' ', '\xE8', '\xBF', '\x87', ' ', '\xE8', '\xBF', '\x98', ' ', '\xE8', '\xBF', '\x9B', ' ', '\xE9', '\x80', '\xB2', ' ', '\xE9', '\x81', '\x8E', ' ', '\xE9', '\x81', '\x93', ' ', '\xE9', '\x82', '\x84', ' ', '\xE9', '\x87', '\x8C', /* 过 还 进 進 過 道 還 里 */
+ ' ', '\xE9', '\x9D', '\xA2', /* 面 */
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ '\0',
+ ' ', '\xE4', '\xBA', '\x9B', ' ', '\xE4', '\xBB', '\xAC', ' ', '\xE4', '\xBD', '\xA0', ' ', '\xE4', '\xBE', '\x86', ' ', '\xE5', '\x80', '\x91', ' ', '\xE5', '\x88', '\xB0', ' ', '\xE5', '\x92', '\x8C', ' ', '\xE5', '\x9C', '\xB0', /* 些 们 你 來 們 到 和 地 */
+ ' ', '\xE5', '\xA5', '\xB9', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE5', '\xB0', '\xB1', ' ', '\xE5', '\xB9', '\xB4', ' ', '\xE5', '\xBE', '\x97', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x9C', '\x80', /* 她 将 將 就 年 得 情 最 */
+ ' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE7', '\x90', '\x86', ' ', '\xE8', '\x83', '\xBD', ' ', '\xE8', '\xAA', '\xAA', ' ', '\xE8', '\xAF', '\xB4', ' ', '\xE8', '\xBF', '\x99', ' ', '\xE9', '\x80', '\x99', /* 样 樣 理 能 說 说 这 這 */
+ ' ', '\xE9', '\x80', '\x9A', ' ', '|', /* 通 | */
+ ' ', '\xE5', '\x8D', '\xB3', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x90', '\xA7', ' ', '\xE5', '\x90', '\xAC', ' ', '\xE5', '\x91', '\xA2', ' ', '\xE5', '\x93', '\x81', ' ', '\xE5', '\x93', '\x8D', ' ', '\xE5', '\x97', '\x8E', /* 即 吗 吧 听 呢 品 响 嗎 */
+ ' ', '\xE5', '\xB8', '\x88', ' ', '\xE5', '\xB8', '\xAB', ' ', '\xE6', '\x94', '\xB6', ' ', '\xE6', '\x96', '\xAD', ' ', '\xE6', '\x96', '\xB7', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE7', '\x9C', '\xBC', ' ', '\xE9', '\x96', '\x93', /* 师 師 收 断 斷 明 眼 間 */
+ ' ', '\xE9', '\x97', '\xB4', ' ', '\xE9', '\x99', '\x85', ' ', '\xE9', '\x99', '\x88', ' ', '\xE9', '\x99', '\x90', ' ', '\xE9', '\x99', '\xA4', ' ', '\xE9', '\x99', '\xB3', ' ', '\xE9', '\x9A', '\x8F', ' ', '\xE9', '\x9A', '\x9B', /* 间 际 陈 限 除 陳 随 際 */
+ ' ', '\xE9', '\x9A', '\xA8', /* 隨 */
+ '\0',
+ '\xE4', '\xBA', '\x8B', ' ', '\xE5', '\x89', '\x8D', ' ', '\xE5', '\xAD', '\xB8', ' ', '\xE5', '\xB0', '\x86', ' ', '\xE5', '\xB0', '\x87', ' ', '\xE6', '\x83', '\x85', ' ', '\xE6', '\x83', '\xB3', ' ', '\xE6', '\x88', '\x96', /* 事 前 學 将 將 情 想 或 */
+ ' ', '\xE6', '\x94', '\xBF', ' ', '\xE6', '\x96', '\xAF', ' ', '\xE6', '\x96', '\xB0', ' ', '\xE6', '\xA0', '\xB7', ' ', '\xE6', '\xA8', '\xA3', ' ', '\xE6', '\xB0', '\x91', ' ', '\xE6', '\xB2', '\x92', ' ', '\xE6', '\xB2', '\xA1', /* 政 斯 新 样 樣 民 沒 没 */
+ ' ', '\xE7', '\x84', '\xB6', ' ', '\xE7', '\x89', '\xB9', ' ', '\xE7', '\x8E', '\xB0', ' ', '\xE7', '\x8F', '\xBE', ' ', '\xE7', '\x90', '\x83', ' ', '\xE7', '\xAC', '\xAC', ' ', '\xE7', '\xB6', '\x93', ' ', '\xE8', '\xB0', '\x81', /* 然 特 现 現 球 第 經 谁 */
+ ' ', '\xE8', '\xB5', '\xB7', ' ', '|', /* 起 | */
+ ' ', '\xE4', '\xBE', '\x8B', ' ', '\xE5', '\x88', '\xA5', ' ', '\xE5', '\x88', '\xAB', ' ', '\xE5', '\x88', '\xB6', ' ', '\xE5', '\x8A', '\xA8', ' ', '\xE5', '\x8B', '\x95', ' ', '\xE5', '\x90', '\x97', ' ', '\xE5', '\x97', '\x8E', /* 例 別 别 制 动 動 吗 嗎 */
+ ' ', '\xE5', '\xA2', '\x9E', ' ', '\xE6', '\x8C', '\x87', ' ', '\xE6', '\x98', '\x8E', ' ', '\xE6', '\x9C', '\x9D', ' ', '\xE6', '\x9C', '\x9F', ' ', '\xE6', '\x9E', '\x84', ' ', '\xE7', '\x89', '\xA9', ' ', '\xE7', '\xA1', '\xAE', /* 增 指 明 朝 期 构 物 确 */
+ ' ', '\xE7', '\xA7', '\x8D', ' ', '\xE8', '\xAA', '\xBF', ' ', '\xE8', '\xB0', '\x83', ' ', '\xE8', '\xB2', '\xBB', ' ', '\xE8', '\xB4', '\xB9', ' ', '\xE9', '\x82', '\xA3', ' ', '\xE9', '\x83', '\xBD', ' ', '\xE9', '\x96', '\x93', /* 种 調 调 費 费 那 都 間 */
+ ' ', '\xE9', '\x97', '\xB4', /* 间 */
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+#endif /* AF_CONFIG_OPTION_CJK */
+ '\0',
+
+ };
+
+
+ /* stringsets are specific to styles */
+ FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
+ af_blue_stringsets[] =
+ {
+ /* */
+ { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_ARABIC_BOTTOM, 0 },
+ { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 },
+ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_NEUTRAL |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 },
+ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_GREEK_SMALL, 0 },
+ { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_LONG },
+ { AF_BLUE_STRING_HEBREW_BOTTOM, 0 },
+ { AF_BLUE_STRING_HEBREW_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP },
+ { AF_BLUE_STRING_KHMER_BOTTOM, 0 },
+ { AF_BLUE_STRING_KHMER_DESCENDER, 0 },
+ { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LAO_BOTTOM, 0 },
+ { AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LAO_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LATIN_SMALL, 0 },
+ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 },
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 },
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_MYANMAR_BOTTOM, 0 },
+ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_TELUGU_BOTTOM, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+ { AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT },
+ { AF_BLUE_STRING_THAI_BOTTOM, 0 },
+ { AF_BLUE_STRING_THAI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_THAI_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP },
+ { AF_BLUE_STRING_THAI_DESCENDER, 0 },
+ { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 },
+ { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 },
+ { AF_BLUE_STRING_MAX, 0 },
+#ifdef AF_CONFIG_OPTION_CJK
+ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP },
+ { AF_BLUE_STRING_CJK_BOTTOM, 0 },
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ },
+ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
+ AF_BLUE_PROPERTY_CJK_RIGHT },
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+ { AF_BLUE_STRING_MAX, 0 },
+#endif /* AF_CONFIG_OPTION_CJK */
+
+ };
+
+
+/* END */
diff --git a/src/base/ftxf86.c b/src/autofit/afblue.cin
similarity index 66%
copy from src/base/ftxf86.c
copy to src/autofit/afblue.cin
index a4bf767..b303a4b 100644
--- a/src/base/ftxf86.c
+++ b/src/autofit/afblue.cin
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* ftxf86.c */
+/* afblue.c */
/* */
-/* FreeType utility file for X11 support (body). */
+/* Auto-fitter data for blue strings (body). */
/* */
-/* Copyright 2002, 2003, 2004 by */
+/* Copyright 2013-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,25 +16,24 @@
/***************************************************************************/
-#include <ft2build.h>
-#include FT_XFREE86_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_SERVICE_XFREE86_NAME_H
+#include "aftypes.h"
- /* documentation is in ftxf86.h */
-
- FT_EXPORT_DEF( const char* )
- FT_Get_X11_Font_Format( FT_Face face )
+ FT_LOCAL_ARRAY_DEF( char )
+ af_blue_strings[] =
{
- const char* result = NULL;
+ /* */
+@AF_BLUE_STRINGS_ARRAY@
+ };
- if ( face )
- FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
-
- return result;
- }
+ /* stringsets are specific to styles */
+ FT_LOCAL_ARRAY_DEF( AF_Blue_StringRec )
+ af_blue_stringsets[] =
+ {
+ /* */
+@AF_BLUE_STRINGSETS_ARRAY@
+ };
/* END */
diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
new file mode 100644
index 0000000..5ffb852
--- /dev/null
+++ b/src/autofit/afblue.dat
@@ -0,0 +1,521 @@
+// afblue.dat
+//
+// Auto-fitter data for blue strings.
+//
+// Copyright 2013-2015 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 contains data specific to blue zones. It gets processed by
+// a script to simulate `jagged arrays', with enumeration values holding
+// offsets into the arrays.
+//
+// The format of the file is rather simple: A section starts with three
+// labels separated by whitespace and followed by a colon (everything in a
+// single line); the first label gives the name of the enumeration template,
+// the second the name of the array template, and the third the name of the
+// `maximum' template. The script then fills the corresponding templates
+// (indicated by `@' characters around the name).
+//
+// A section contains one or more data records. Each data record consists
+// of two or more lines. The first line holds the enumeration name, and the
+// remaining lines the corresponding array data.
+//
+// There are two possible representations for array data.
+//
+// - A string of characters or character clusters (for example, representing
+// Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
+// quotes, using C syntax, where the elements are separated by spaces.
+// There can be only one string per line, thus the starting and ending
+// double quote must be the first and last character in the line,
+// respectively, ignoring whitespace before and after the string. If
+// there are multiple strings (in multiple lines), they are concatenated
+// to a single string. In the output, a string gets represented as a
+// series of singles bytes, followed by a zero byte. The enumeration
+// values simply hold byte offsets to the start of the corresponding
+// strings.
+//
+// For strings, the `maximum' template holds the maximum number of
+// non-space characters in all strings.
+//
+// - Data blocks enclosed in balanced braces, which get copied verbatim and
+// which can span multiple lines. The opening brace of a block must be
+// the first character of a line (ignoring whitespace), and the closing
+// brace the last (ignoring whitespace also). The script appends a comma
+// character after each block and counts the number of blocks to set the
+// enumeration values.
+//
+// For data blocks, the `maximum' template holds the maximum number of
+// array elements.
+//
+// A section can contain either strings only or data blocks only.
+//
+// A comment line starts with `//'; it gets removed. A preprocessor
+// directive line (using the standard syntax of `cpp') starts with `#' and
+// gets copied verbatim to both the enumeration and the array. Whitespace
+// outside of a string is insignificant.
+//
+// Preprocessor directives are ignored while the script computes maximum
+// values; this essentially means that the maximum values can easily be too
+// large. Given that the purpose of those values is to create local
+// fixed-size arrays at compile time for further processing of the blue zone
+// data, this isn't a problem. Note the the final zero byte of a string is
+// not counted. Note also that the count holds the number of UTF-8 encoded
+// characters, not bytes.
+
+
+// The blue zone string data, to be used in the blue stringsets below.
+
+AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
+
+ AF_BLUE_STRING_ARABIC_TOP
+ "ا إ ل ك ط ظ"
+ AF_BLUE_STRING_ARABIC_BOTTOM
+ "ت ث ط ظ ك"
+ // We don't necessarily have access to medial forms via Unicode in case
+ // Arabic presentational forms are missing. The only character that is
+ // guaranteed to have the same vertical position with joining (this is,
+ // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
+ // round and flat curves.
+ AF_BLUE_STRING_ARABIC_JOIN
+ "ـ"
+
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
+ "Б В Е П З О С Э"
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
+ "Б В Е Ш З О С Э"
+ AF_BLUE_STRING_CYRILLIC_SMALL
+ "х п н ш е з о с"
+ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
+ "р у ф"
+
+ AF_BLUE_STRING_DEVANAGARI_BASE
+ "क म अ आ थ ध भ श"
+ AF_BLUE_STRING_DEVANAGARI_TOP
+ "ई ऐ ओ औ ि ी ो ौ"
+ // note that some fonts have extreme variation in the height of the
+ // round head elements; for this reason we also define the `base'
+ // blue zone, which must be always present
+ AF_BLUE_STRING_DEVANAGARI_HEAD
+ "क म अ आ थ ध भ श"
+ AF_BLUE_STRING_DEVANAGARI_BOTTOM
+ "ु ृ"
+
+ AF_BLUE_STRING_GREEK_CAPITAL_TOP
+ "Γ Β Ε Ζ Θ Ο Ω"
+ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
+ "Β Δ Ζ Ξ Θ Ο"
+ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
+ "β θ δ ζ λ ξ"
+ AF_BLUE_STRING_GREEK_SMALL
+ "α ε ι ο π σ τ ω"
+ AF_BLUE_STRING_GREEK_SMALL_DESCENDER
+ "β γ η μ ρ φ χ ψ"
+
+ AF_BLUE_STRING_HEBREW_TOP
+ "ב ד ה ח ך כ ם ס"
+ AF_BLUE_STRING_HEBREW_BOTTOM
+ "ב ט כ ם ס צ"
+ AF_BLUE_STRING_HEBREW_DESCENDER
+ "ק ך ן ף ץ"
+
+ AF_BLUE_STRING_KHMER_TOP
+ "ខ ទ ន ឧ ឩ ា"
+ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
+ "ក្ក ក្ខ ក្គ ក្ថ"
+ AF_BLUE_STRING_KHMER_BOTTOM
+ "ខ ឃ ច ឋ ប ម យ ឲ"
+ AF_BLUE_STRING_KHMER_DESCENDER
+ "ត្រ រៀ ឲ្យ អឿ"
+ AF_BLUE_STRING_KHMER_LARGE_DESCENDER
+ "ន្ត្រៃ ង្ខ្យ ក្បៀ ច្រៀ ន្តឿ ល្បឿ"
+
+ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
+ "᧠ ᧡"
+ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
+ "᧶ ᧹"
+
+ AF_BLUE_STRING_LAO_TOP
+ "າ ດ ອ ມ ລ ວ ຣ ງ"
+ AF_BLUE_STRING_LAO_BOTTOM
+ "າ ອ ບ ຍ ຣ ຮ ວ ຢ"
+ AF_BLUE_STRING_LAO_ASCENDER
+ "ປ ຢ ຟ ຝ"
+ AF_BLUE_STRING_LAO_LARGE_ASCENDER
+ "ໂ ໄ ໃ"
+ AF_BLUE_STRING_LAO_DESCENDER
+ "ງ ຊ ຖ ຽ ໆ ຯ"
+
+ AF_BLUE_STRING_LATIN_CAPITAL_TOP
+ "T H E Z O C Q S"
+ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
+ "H E Z L O C U S"
+ AF_BLUE_STRING_LATIN_SMALL_F_TOP
+ "f i j k d b h"
+ AF_BLUE_STRING_LATIN_SMALL
+ "x z r o e s c"
+ AF_BLUE_STRING_LATIN_SMALL_DESCENDER
+ "p q g j y"
+
+ // we assume that both the subscript and superscript ranges
+ // don't contain oldstyle digits (actually, most fonts probably
+ // have digits only in those ranges)
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
+ "₀ ₃ ₅ ₇ ₈"
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
+ "₀ ₁ ₂ ₃ ₈"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
+ "ᵢ ⱼ ₕ ₖ ₗ"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL
+ "ₐ ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
+ "ᵦ ᵧ ᵨ ᵩ ₚ"
+
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
+ "⁰ ³ ⁵ ⁷ ᵀ ᴴ ᴱ ᴼ"
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
+ "⁰ ¹ ² ³ ᴱ ᴸ ᴼ ᵁ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
+ "ᵇ ᵈ ᵏ ʰ ʲ ᶠ ⁱ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL
+ "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
+ "ᵖ ʸ ᵍ"
+
+ AF_BLUE_STRING_MYANMAR_TOP
+ "ခ ဂ င ဒ ဝ ၥ ၊ ။"
+ AF_BLUE_STRING_MYANMAR_BOTTOM
+ "င ဎ ဒ ပ ဗ ဝ ၊ ။"
+ AF_BLUE_STRING_MYANMAR_ASCENDER
+ "ဩ ြ ၍ ၏ ၆ ါ ိ"
+ AF_BLUE_STRING_MYANMAR_DESCENDER
+ "ဉ ည ဥ ဩ ဨ ၂ ၅ ၉"
+
+ AF_BLUE_STRING_TELUGU_TOP
+ "ఇ ఌ ఙ ఞ ణ ఱ ౯"
+ AF_BLUE_STRING_TELUGU_BOTTOM
+ "అ క చ ర ఽ ౨ ౬"
+
+ AF_BLUE_STRING_THAI_TOP
+ "บ เ แ อ ก า"
+ AF_BLUE_STRING_THAI_BOTTOM
+ "บ ป ษ ฯ อ ย ฮ"
+ AF_BLUE_STRING_THAI_ASCENDER
+ "ป ฝ ฟ"
+ AF_BLUE_STRING_THAI_LARGE_ASCENDER
+ "โ ใ ไ"
+ AF_BLUE_STRING_THAI_DESCENDER
+ "ฎ ฏ ฤ ฦ"
+ AF_BLUE_STRING_THAI_LARGE_DESCENDER
+ "ญ ฐ"
+ AF_BLUE_STRING_THAI_DIGIT_TOP
+ "๐ ๑ ๓"
+
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+ AF_BLUE_STRING_CJK_TOP
+ "他 们 你 來 們 到 和 地"
+ " 对 對 就 席 我 时 時 會"
+ " 来 為 能 舰 說 说 这 這"
+ " 齊 |"
+ " 军 同 已 愿 既 星 是 景"
+ " 民 照 现 現 理 用 置 要"
+ " 軍 那 配 里 開 雷 露 面"
+ " 顾"
+ AF_BLUE_STRING_CJK_BOTTOM
+ "个 为 人 他 以 们 你 來"
+ " 個 們 到 和 大 对 對 就"
+ " 我 时 時 有 来 為 要 說"
+ " 说 |"
+ " 主 些 因 它 想 意 理 生"
+ " 當 看 着 置 者 自 著 裡"
+ " 过 还 进 進 過 道 還 里"
+ " 面"
+
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
+ AF_BLUE_STRING_CJK_LEFT
+ " 些 们 你 來 們 到 和 地"
+ " 她 将 將 就 年 得 情 最"
+ " 样 樣 理 能 說 说 这 這"
+ " 通 |"
+ " 即 吗 吧 听 呢 品 响 嗎"
+ " 师 師 收 断 斷 明 眼 間"
+ " 间 际 陈 限 除 陳 随 際"
+ " 隨"
+ AF_BLUE_STRING_CJK_RIGHT
+ "事 前 學 将 將 情 想 或"
+ " 政 斯 新 样 樣 民 沒 没"
+ " 然 特 现 現 球 第 經 谁"
+ " 起 |"
+ " 例 別 别 制 动 動 吗 嗎"
+ " 增 指 明 朝 期 构 物 确"
+ " 种 調 调 費 费 那 都 間"
+ " 间"
+
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'.
+//
+// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some
+// explanations.
+//
+// A blue zone in general is defined by a reference and an overshoot line.
+// During the hinting process, all coordinate values between those two lines
+// are set equal to the reference value, provided that the blue zone is not
+// wider than 0.75 pixels (otherwise the blue zone gets ignored). All
+// entries must have `AF_BLUE_STRING_MAX' as the final line.
+//
+// During the glyph analysis, edges are sorted from bottom to top, and then
+// sequentially checked, edge by edge, against the blue zones in the order
+// given below.
+//
+//
+// latin auto-hinter
+// -----------------
+//
+// Characters in a blue string are automatically classified as having a flat
+// (reference) or a round (overshoot) extremum. The blue zone is then set
+// up by the mean values of all flat extrema and all round extrema,
+// respectively. Only horizontal blue zones (i.e., adjusting vertical
+// coordinate values) are supported.
+//
+// Some scripts like Khmer need character composition to get all necessary
+// blue zones, since Unicode only provides an abstract data model that
+// doesn't represent all possible glyph shapes. For such character
+// clusters, the HarfBuzz library is used to convert them into the
+// corresponding glyphs. The largest glyph element (where `largest' can be
+// either `largest ascender' or `largest descender') then defines the
+// corresponding flat or round extremum.
+//
+// For the latin auto-hinter, the overshoot should be larger than the
+// reference for top zones, and vice versa for bottom zones.
+//
+// LATIN_TOP
+// Take the maximum flat and round coordinate values of the blue string
+// characters for computing the blue zone's reference and overshoot
+// values.
+//
+// If not set, take the minimum values.
+//
+// Mutually exclusive with `LATIN_SUB_TOP'.
+//
+// LATIN_SUB_TOP
+// For all glyphs of a character cluster, compute the maximum flat
+// and round coordinate values of each component, then take the
+// smallest of the maximum values. The idea is to get the top of
+// subscript glyphs, as used in Khmer, for example. Note that
+// this mechanism doesn't work for ordinary ligatures.
+//
+// This flags indicates a secondary blue zone: It gets removed if
+// there is a non-LATIN_SUB_TOP blue zone at the same coordinate
+// value (after scaling).
+//
+// Mutually exclusive with `LATIN_TOP'.
+//
+// LATIN_NEUTRAL
+// Ignore round extrema and define the blue zone with flat values only.
+// Both top and bottom of contours can match. This is useful for
+// scripts like Devanagari where vowel signs attach to the base
+// character and are implemented as components of composite glyphs.
+//
+// If not set, both round and flat extrema are taken into account.
+// Additionally, only the top or the bottom of a contour can match,
+// depending on the LATIN_TOP flag.
+//
+// Neutral blue zones should always follow non-neutral blue zones.
+//
+// LATIN_X_HEIGHT
+// Scale all glyphs vertically from the corresponding script to make the
+// reference line of this blue zone align on the grid. The scaling
+// takes place before all other blue zones get aligned to the grid.
+// Only one blue character string of a script style can have this flag.
+//
+// LATIN_LONG
+// Apply an additional constraint for blue zone values: Don't
+// necessarily use the extremum as-is but a segment of the topmost (or
+// bottommost) contour that is longer than a heuristic threshold, and
+// which is not too far away vertically from the real extremum. This
+// ensures that small bumps in the outline are ignored (for example, the
+// `vertical serifs' found in many Hebrew glyph designs).
+//
+// The segment must be at least EM/25 font units long, and the distance
+// to the extremum must be smaller than EM/4.
+//
+//
+// cjk auto-hinter
+// ---------------
+//
+// Characters in a blue string are *not* automatically classified. Instead,
+// first come the characters used for the overshoot value, then the
+// character `|', then the characters used for the reference value
+// (everything separated by space characters). The blue zone is then set up
+// by the mean values of all reference values and all overshoot values,
+// respectively. Both horizontal and vertical blue zones (i.e., adjusting
+// vertical and horizontal coordinate values, respectively) are supported.
+//
+// For the cjk auto-hinter, the overshoot should be smaller than the
+// reference for top zones, and vice versa for bottom zones.
+//
+// CJK_TOP
+// Take the maximum flat and round coordinate values of the blue string
+// characters. If not set, take the minimum values.
+//
+// CJK_RIGHT
+// A synonym for CJK_TOP. If CJK_HORIZ is set, this flag indicates the
+// right blue zone, taking horizontal maximum values.
+//
+// CJK_HORIZ
+// Define a blue zone for horizontal hinting (i.e., vertical blue
+// zones). If not set, this is a blue zone for vertical hinting.
+
+
+AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
+
+ AF_BLUE_STRINGSET_ARAB
+ { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }
+ { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_CYRL
+ { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }
+ { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_DEVA
+ { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_NEUTRAL |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }
+ { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_GREK
+ { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_GREEK_SMALL, 0 }
+ { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_HEBR
+ { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_LONG }
+ { AF_BLUE_STRING_HEBREW_BOTTOM, 0 }
+ { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_KHMR
+ { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP }
+ { AF_BLUE_STRING_KHMER_BOTTOM, 0 }
+ { AF_BLUE_STRING_KHMER_DESCENDER, 0 }
+ { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_KHMS
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LAO
+ { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LAO_BOTTOM, 0 }
+ { AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LAO_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LATN
+ { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LATIN_SMALL, 0 }
+ { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LATB
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 }
+ { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_LATP
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }
+ { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_MYMR
+ { AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_MYANMAR_BOTTOM, 0 }
+ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_TELU
+ { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_TELUGU_BOTTOM, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+ AF_BLUE_STRINGSET_THAI
+ { AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
+ AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
+ { AF_BLUE_STRING_THAI_BOTTOM, 0 }
+ { AF_BLUE_STRING_THAI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_THAI_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
+ { AF_BLUE_STRING_THAI_DESCENDER, 0 }
+ { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 }
+ { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 }
+ { AF_BLUE_STRING_MAX, 0 }
+
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+ AF_BLUE_STRINGSET_HANI
+ { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }
+ { AF_BLUE_STRING_CJK_BOTTOM, 0 }
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ }
+ { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
+ AF_BLUE_PROPERTY_CJK_RIGHT }
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+ { AF_BLUE_STRING_MAX, 0 }
+
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+// END
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
new file mode 100644
index 0000000..34f90e9
--- /dev/null
+++ b/src/autofit/afblue.h
@@ -0,0 +1,251 @@
+/* This file has been generated by the Perl script `afblue.pl', */
+/* using data from file `afblue.dat'. */
+
+/***************************************************************************/
+/* */
+/* afblue.h */
+/* */
+/* Auto-fitter data for blue strings (specification). */
+/* */
+/* Copyright 2013-2015 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 __AFBLUE_H__
+#define __AFBLUE_H__
+
+
+FT_BEGIN_HEADER
+
+
+ /* an auxiliary macro to decode a UTF-8 character -- since we only use */
+ /* hard-coded, self-converted data, no error checking is performed */
+#define GET_UTF8_CHAR( ch, p ) \
+ do \
+ { \
+ ch = (unsigned char)*p++; \
+ if ( ch >= 0x80 ) \
+ { \
+ FT_UInt len_; \
+ \
+ \
+ if ( ch < 0xE0 ) \
+ { \
+ len_ = 1; \
+ ch &= 0x1F; \
+ } \
+ else if ( ch < 0xF0 ) \
+ { \
+ len_ = 2; \
+ ch &= 0x0F; \
+ } \
+ else \
+ { \
+ len_ = 3; \
+ ch &= 0x07; \
+ } \
+ \
+ for ( ; len_ > 0; len_-- ) \
+ ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+ } \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** B L U E S T R I N G S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* At the bottommost level, we define strings for finding blue zones. */
+
+
+#define AF_BLUE_STRING_MAX_LEN 51
+
+ /* The AF_Blue_String enumeration values are offsets into the */
+ /* `af_blue_strings' array. */
+
+ typedef enum AF_Blue_String_
+ {
+ AF_BLUE_STRING_ARABIC_TOP = 0,
+ AF_BLUE_STRING_ARABIC_BOTTOM = 18,
+ AF_BLUE_STRING_ARABIC_JOIN = 33,
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP = 36,
+ AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM = 60,
+ AF_BLUE_STRING_CYRILLIC_SMALL = 84,
+ AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER = 108,
+ AF_BLUE_STRING_DEVANAGARI_BASE = 117,
+ AF_BLUE_STRING_DEVANAGARI_TOP = 149,
+ AF_BLUE_STRING_DEVANAGARI_HEAD = 181,
+ AF_BLUE_STRING_DEVANAGARI_BOTTOM = 213,
+ AF_BLUE_STRING_GREEK_CAPITAL_TOP = 221,
+ AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM = 242,
+ AF_BLUE_STRING_GREEK_SMALL_BETA_TOP = 260,
+ AF_BLUE_STRING_GREEK_SMALL = 278,
+ AF_BLUE_STRING_GREEK_SMALL_DESCENDER = 302,
+ AF_BLUE_STRING_HEBREW_TOP = 326,
+ AF_BLUE_STRING_HEBREW_BOTTOM = 350,
+ AF_BLUE_STRING_HEBREW_DESCENDER = 368,
+ AF_BLUE_STRING_KHMER_TOP = 383,
+ AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 407,
+ AF_BLUE_STRING_KHMER_BOTTOM = 447,
+ AF_BLUE_STRING_KHMER_DESCENDER = 479,
+ AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 513,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 600,
+ AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 608,
+ AF_BLUE_STRING_LAO_TOP = 616,
+ AF_BLUE_STRING_LAO_BOTTOM = 648,
+ AF_BLUE_STRING_LAO_ASCENDER = 680,
+ AF_BLUE_STRING_LAO_LARGE_ASCENDER = 696,
+ AF_BLUE_STRING_LAO_DESCENDER = 708,
+ AF_BLUE_STRING_LATIN_CAPITAL_TOP = 732,
+ AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 748,
+ AF_BLUE_STRING_LATIN_SMALL_F_TOP = 764,
+ AF_BLUE_STRING_LATIN_SMALL = 778,
+ AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 792,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 802,
+ AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 822,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 842,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL = 862,
+ AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 898,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 918,
+ AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 949,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 978,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL = 1004,
+ AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 1029,
+ AF_BLUE_STRING_MYANMAR_TOP = 1040,
+ AF_BLUE_STRING_MYANMAR_BOTTOM = 1072,
+ AF_BLUE_STRING_MYANMAR_ASCENDER = 1104,
+ AF_BLUE_STRING_MYANMAR_DESCENDER = 1132,
+ AF_BLUE_STRING_TELUGU_TOP = 1164,
+ AF_BLUE_STRING_TELUGU_BOTTOM = 1192,
+ AF_BLUE_STRING_THAI_TOP = 1220,
+ AF_BLUE_STRING_THAI_BOTTOM = 1244,
+ AF_BLUE_STRING_THAI_ASCENDER = 1272,
+ AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1284,
+ AF_BLUE_STRING_THAI_DESCENDER = 1296,
+ AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1312,
+ AF_BLUE_STRING_THAI_DIGIT_TOP = 1320,
+ af_blue_1_1 = 1331,
+#ifdef AF_CONFIG_OPTION_CJK
+ AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
+ AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
+ af_blue_1_1_1 = af_blue_1_1 + 404,
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ AF_BLUE_STRING_CJK_LEFT = af_blue_1_1_1 + 1,
+ AF_BLUE_STRING_CJK_RIGHT = af_blue_1_1_1 + 204,
+ af_blue_1_1_2 = af_blue_1_1_1 + 405,
+#else
+ af_blue_1_1_2 = af_blue_1_1_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+ af_blue_1_2 = af_blue_1_1_2 + 0,
+#else
+ af_blue_1_2 = af_blue_1_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+ AF_BLUE_STRING_MAX /* do not remove */
+
+ } AF_Blue_String;
+
+
+ FT_LOCAL_ARRAY( char )
+ af_blue_strings[];
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** B L U E S T R I N G S E T S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* The next level is to group blue strings into style-specific sets. */
+
+
+ /* Properties are specific to a writing system. We assume that a given */
+ /* blue string can't be used in more than a single writing system, which */
+ /* is a safe bet. */
+#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
+
+#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
+#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
+#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
+
+
+#define AF_BLUE_STRINGSET_MAX_LEN 8
+
+ /* The AF_Blue_Stringset enumeration values are offsets into the */
+ /* `af_blue_stringsets' array. */
+
+ typedef enum AF_Blue_Stringset_
+ {
+ AF_BLUE_STRINGSET_ARAB = 0,
+ AF_BLUE_STRINGSET_CYRL = 4,
+ AF_BLUE_STRINGSET_DEVA = 10,
+ AF_BLUE_STRINGSET_GREK = 16,
+ AF_BLUE_STRINGSET_HEBR = 23,
+ AF_BLUE_STRINGSET_KHMR = 27,
+ AF_BLUE_STRINGSET_KHMS = 33,
+ AF_BLUE_STRINGSET_LAO = 36,
+ AF_BLUE_STRINGSET_LATN = 42,
+ AF_BLUE_STRINGSET_LATB = 49,
+ AF_BLUE_STRINGSET_LATP = 56,
+ AF_BLUE_STRINGSET_MYMR = 63,
+ AF_BLUE_STRINGSET_TELU = 68,
+ AF_BLUE_STRINGSET_THAI = 71,
+ af_blue_2_1 = 79,
+#ifdef AF_CONFIG_OPTION_CJK
+ AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
+ af_blue_2_1_1 = af_blue_2_1 + 2,
+#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ af_blue_2_1_2 = af_blue_2_1_1 + 2,
+#else
+ af_blue_2_1_2 = af_blue_2_1_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+ af_blue_2_2 = af_blue_2_1_2 + 1,
+#else
+ af_blue_2_2 = af_blue_2_1 + 0,
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+ AF_BLUE_STRINGSET_MAX /* do not remove */
+
+ } AF_Blue_Stringset;
+
+
+ typedef struct AF_Blue_StringRec_
+ {
+ AF_Blue_String string;
+ FT_UShort properties;
+
+ } AF_Blue_StringRec;
+
+
+ FT_LOCAL_ARRAY( AF_Blue_StringRec )
+ af_blue_stringsets[];
+
+/* */
+
+FT_END_HEADER
+
+
+#endif /* __AFBLUE_H__ */
+
+
+/* END */
diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin
new file mode 100644
index 0000000..1eb9172
--- /dev/null
+++ b/src/autofit/afblue.hin
@@ -0,0 +1,146 @@
+/***************************************************************************/
+/* */
+/* afblue.h */
+/* */
+/* Auto-fitter data for blue strings (specification). */
+/* */
+/* Copyright 2013-2015 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 __AFBLUE_H__
+#define __AFBLUE_H__
+
+
+FT_BEGIN_HEADER
+
+
+ /* an auxiliary macro to decode a UTF-8 character -- since we only use */
+ /* hard-coded, self-converted data, no error checking is performed */
+#define GET_UTF8_CHAR( ch, p ) \
+ do \
+ { \
+ ch = (unsigned char)*p++; \
+ if ( ch >= 0x80 ) \
+ { \
+ FT_UInt len_; \
+ \
+ \
+ if ( ch < 0xE0 ) \
+ { \
+ len_ = 1; \
+ ch &= 0x1F; \
+ } \
+ else if ( ch < 0xF0 ) \
+ { \
+ len_ = 2; \
+ ch &= 0x0F; \
+ } \
+ else \
+ { \
+ len_ = 3; \
+ ch &= 0x07; \
+ } \
+ \
+ for ( ; len_ > 0; len_-- ) \
+ ch = ( ch << 6 ) | ( *p++ & 0x3F ); \
+ } \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** B L U E S T R I N G S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* At the bottommost level, we define strings for finding blue zones. */
+
+
+#define AF_BLUE_STRING_MAX_LEN @AF_BLUE_STRING_MAX_LEN@
+
+ /* The AF_Blue_String enumeration values are offsets into the */
+ /* `af_blue_strings' array. */
+
+ typedef enum AF_Blue_String_
+ {
+@AF_BLUE_STRING_ENUM@
+
+ AF_BLUE_STRING_MAX /* do not remove */
+
+ } AF_Blue_String;
+
+
+ FT_LOCAL_ARRAY( char )
+ af_blue_strings[];
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** B L U E S T R I N G S E T S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* The next level is to group blue strings into style-specific sets. */
+
+
+ /* Properties are specific to a writing system. We assume that a given */
+ /* blue string can't be used in more than a single writing system, which */
+ /* is a safe bet. */
+#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 )
+
+#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */
+#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */
+#define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP
+
+
+#define AF_BLUE_STRINGSET_MAX_LEN @AF_BLUE_STRINGSET_MAX_LEN@
+
+ /* The AF_Blue_Stringset enumeration values are offsets into the */
+ /* `af_blue_stringsets' array. */
+
+ typedef enum AF_Blue_Stringset_
+ {
+@AF_BLUE_STRINGSET_ENUM@
+
+ AF_BLUE_STRINGSET_MAX /* do not remove */
+
+ } AF_Blue_Stringset;
+
+
+ typedef struct AF_Blue_StringRec_
+ {
+ AF_Blue_String string;
+ FT_UShort properties;
+
+ } AF_Blue_StringRec;
+
+
+ FT_LOCAL_ARRAY( AF_Blue_StringRec )
+ af_blue_stringsets[];
+
+/* */
+
+FT_END_HEADER
+
+
+#endif /* __AFBLUE_H__ */
+
+
+/* END */
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index f69a528..73d75ae 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -2,9 +2,9 @@
/* */
/* afcjk.c */
/* */
-/* Auto-fitter hinting routines for CJK script (body). */
+/* Auto-fitter hinting routines for CJK writing system (body). */
/* */
-/* Copyright 2006-2013 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,7 +26,8 @@
#include FT_ADVANCES_H
#include FT_INTERNAL_DEBUG_H
-#include "aftypes.h"
+#include "afglobal.h"
+#include "afpic.h"
#include "aflatin.h"
@@ -73,6 +74,12 @@
AF_GlyphHintsRec hints[1];
+ FT_TRACE5(( "\n"
+ "cjk standard widths computation (style `%s')\n"
+ "===================================================\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
+
af_glyph_hints_init( hints, face->memory );
metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
@@ -80,17 +87,75 @@
{
FT_Error error;
- FT_UInt glyph_index;
+ FT_ULong glyph_index;
int dim;
AF_CJKMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
+#ifdef FT_CONFIG_OPTION_PIC
+ AF_FaceGlobals globals = metrics->root.globals;
+#endif
- glyph_index = FT_Get_Char_Index( face,
- metrics->root.clazz->standard_char );
- if ( glyph_index == 0 )
+ AF_StyleClass style_class = metrics->root.style_class;
+ AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
+ [style_class->script];
+
+ void* shaper_buf;
+ const char* p;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_ULong ch;
+#endif
+
+ p = script_class->standard_charstring;
+ shaper_buf = af_shaper_buf_create( face );
+
+ /* We check a list of standard characters. The first match wins. */
+
+ glyph_index = 0;
+ while ( *p )
+ {
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+#endif
+
+
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
+
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
+ /* otherwise exit loop if we have a result */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
+ if ( glyph_index )
+ break;
+ }
+
+ af_shaper_buf_destroy( face, shaper_buf );
+
+ if ( !glyph_index )
goto Exit;
+ if ( !glyph_index )
+ goto Exit;
+
+ FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
+ ch, glyph_index ));
+
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || face->glyph->outline.n_points <= 0 )
goto Exit;
@@ -108,7 +173,7 @@
scaler->render_mode = FT_RENDER_MODE_NORMAL;
scaler->flags = 0;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
error = af_glyph_hints_reload( hints, &face->glyph->outline );
if ( error )
@@ -122,11 +187,21 @@
FT_UInt num_widths = 0;
- error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim );
+ error = af_latin_hints_compute_segments( hints,
+ (AF_Dimension)dim );
if ( error )
goto Exit;
- af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+ /*
+ * We assume that the glyphs selected for the stem width
+ * computation are `featureless' enough so that the linking
+ * algorithm works fine without adjustments of its scoring
+ * function.
+ */
+ af_latin_hints_link_segments( hints,
+ 0,
+ NULL,
+ (AF_Dimension)dim );
seg = axhints->segments;
limit = seg + axhints->num_segments;
@@ -151,7 +226,7 @@
}
/* this also replaces multiple almost identical stem widths */
- /* with a single one (the value 100 is heuristic) */
+ /* with a single one (the value 100 is heuristic) */
af_sort_and_quantize_widths( &num_widths, axis->widths,
dummy->units_per_em / 100 );
axis->width_count = num_widths;
@@ -171,264 +246,239 @@
axis->edge_distance_threshold = stdw / 5;
axis->standard_width = stdw;
axis->extra_light = 0;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt i;
+
+
+ FT_TRACE5(( "%s widths:\n",
+ dim == AF_DIMENSION_VERT ? "horizontal"
+ : "vertical" ));
+
+ FT_TRACE5(( " %d (standard)", axis->standard_width ));
+ for ( i = 1; i < axis->width_count; i++ )
+ FT_TRACE5(( " %d", axis->widths[i].org ));
+
+ FT_TRACE5(( "\n" ));
+ }
+#endif
}
}
+ FT_TRACE5(( "\n" ));
+
af_glyph_hints_done( hints );
}
-#define AF_CJK_MAX_TEST_CHARACTERS 32
-
-
- /* Each blue zone has two types of fill and unfill, this is, */
- /* filling the entire glyph square or not. */
-
- enum
- {
- AF_CJK_BLUE_TYPE_FILL,
- AF_CJK_BLUE_TYPE_UNFILL,
- AF_CJK_BLUE_TYPE_MAX
- };
-
-
- /* Put some common and representative Han Ideographs characters here. */
- static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX]
- [AF_CJK_BLUE_TYPE_MAX]
- [AF_CJK_MAX_TEST_CHARACTERS] =
- {
- {
- {
- 0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
- 0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703,
- 0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
- 0x9F4A /* top fill */
- },
- {
- 0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F,
- 0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981,
- 0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762,
- 0x987E /* top unfill */
- }
- },
- {
- {
- 0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86,
- 0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31,
- 0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA,
- 0x8BF4 /* bottom fill */
- },
- {
- 0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F,
- 0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1,
- 0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC,
- 0x9762 /* bottom unfill */
- }
- },
-#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
- { {0x0000}, {0x0000} },
- { {0x0000}, {0x0000} }
-#else
- {
- {
- 0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
- 0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700,
- 0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
- 0x901A /* left fill */
- },
- {
- 0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE,
- 0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593,
- 0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B,
- 0x96A8 /* left unfill */
- }
- },
- {
- {
- 0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216,
- 0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1,
- 0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01,
- 0x8D77 /* right fill */
- },
- {
- 0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE,
- 0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E,
- 0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593,
- 0x95F4 /* right unfill */
- }
- }
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
- };
-
-
- /* Calculate blue zones for all the CJK_BLUE_XXX's. */
+ /* Find all blue zones. */
static void
- af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
- FT_Face face,
- const FT_ULong blue_chars
- [AF_CJK_BLUE_MAX]
- [AF_CJK_BLUE_TYPE_MAX]
- [AF_CJK_MAX_TEST_CHARACTERS] )
+ af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
+ FT_Face face )
{
- FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
- FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
+ FT_Pos fills[AF_BLUE_STRING_MAX_LEN];
+ FT_Pos flats[AF_BLUE_STRING_MAX_LEN];
- FT_Int num_fills;
- FT_Int num_flats;
+ FT_UInt num_fills;
+ FT_UInt num_flats;
- FT_Int bb;
- AF_CJKBlue blue;
- FT_Error error;
- AF_CJKAxis axis;
- FT_GlyphSlot glyph = face->glyph;
+ FT_Bool fill;
+
+ AF_CJKBlue blue;
+ FT_Error error;
+ AF_CJKAxis axis;
+ FT_Outline outline;
+
+ AF_StyleClass sc = metrics->root.style_class;
+
+ AF_Blue_Stringset bss = sc->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+
+ void* shaper_buf;
+
+
+ /* we walk over the blue character strings as specified in the */
+ /* style's entry in the `af_blue_stringset' array, computing its */
+ /* extremum points (depending on the string properties) */
+
+ FT_TRACE5(( "cjk blue zones computation\n"
+ "==========================\n"
+ "\n" ));
+
+ shaper_buf = af_shaper_buf_create( face );
+
+ for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
+ {
+ const char* p = &af_blue_strings[bs->string];
+ FT_Pos* blue_ref;
+ FT_Pos* blue_shoot;
+
+
+ if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
+ axis = &metrics->axis[AF_DIMENSION_HORZ];
+ else
+ axis = &metrics->axis[AF_DIMENSION_VERT];
#ifdef FT_DEBUG_LEVEL_TRACE
- FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = {
- (FT_String*)"top",
- (FT_String*)"bottom",
- (FT_String*)"left",
- (FT_String*)"right"
- };
- FT_String* cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = {
- (FT_String*)"filled",
- (FT_String*)"unfilled"
- };
-#endif
+ {
+ FT_String* cjk_blue_name[4] =
+ {
+ (FT_String*)"bottom", /* -- , -- */
+ (FT_String*)"top", /* -- , TOP */
+ (FT_String*)"left", /* HORIZ, -- */
+ (FT_String*)"right" /* HORIZ, TOP */
+ };
- /* We compute the blues simply by loading each character from the */
- /* `blue_chars[blues]' string, then computing its extreme points */
- /* (depending blue zone type etc.). */
-
- FT_TRACE5(( "cjk blue zones computation\n" ));
- FT_TRACE5(( "------------------------------------------------\n" ));
-
- for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
- {
- FT_Int fill_type;
- FT_Pos* blue_ref;
- FT_Pos* blue_shoot;
-
+ FT_TRACE5(( "blue zone %d (%s):\n",
+ axis->blue_count,
+ cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) |
+ AF_CJK_IS_TOP_BLUE( bs ) ] ));
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
num_fills = 0;
num_flats = 0;
- for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
+ fill = 1; /* start with characters that define fill values */
+ FT_TRACE5(( " [overshoot values]\n" ));
+
+ while ( *p )
{
- const FT_ULong* p = blue_chars[bb][fill_type];
- const FT_ULong* limit = p + AF_CJK_MAX_TEST_CHARACTERS;
- FT_Bool fill = FT_BOOL(
- fill_type == AF_CJK_BLUE_TYPE_FILL );
+ FT_ULong glyph_index;
+ FT_Pos best_pos; /* same as points.y or points.x, resp. */
+ FT_Int best_point;
+ FT_Vector* points;
+
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+ FT_ULong ch;
+#endif
- FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
- cjk_blue_type_name[fill_type] ));
+ while ( *p == ' ' )
+ p++;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
- for ( ; p < limit && *p; p++ )
+ /* switch to characters that define flat values */
+ if ( *p == '|' )
{
- FT_UInt glyph_index;
- FT_Pos best_pos; /* same as points.y */
- FT_Int best_point;
- FT_Vector* points;
+ fill = 0;
+ FT_TRACE5(( " [reference values]\n" ));
+ p++;
+ continue;
+ }
+
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
+ if ( glyph_index == 0 )
+ {
+ FT_TRACE5(( " U+%04lX unavailable\n", ch ));
+ continue;
+ }
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ outline = face->glyph->outline;
+ if ( error || outline.n_points <= 2 )
+ {
+ FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
+ continue;
+ }
+
+ /* now compute min or max point indices and coordinates */
+ points = outline.points;
+ best_point = -1;
+ best_pos = 0; /* make compiler happy */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
- FT_TRACE5(( " U+%lX...", *p ));
-
- /* load the character in the face -- skip unknown or empty ones */
- glyph_index = FT_Get_Char_Index( face, *p );
- if ( glyph_index == 0 )
+ for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
{
- FT_TRACE5(( "unavailable\n" ));
- continue;
- }
-
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
- if ( error || glyph->outline.n_points <= 0 )
- {
- FT_TRACE5(( "no outline\n" ));
- continue;
- }
-
- /* now compute min or max point indices and coordinates */
- points = glyph->outline.points;
- best_point = -1;
- best_pos = 0; /* make compiler happy */
-
- {
- FT_Int nn;
- FT_Int first = 0;
- FT_Int last = -1;
+ FT_Int pp;
- for ( nn = 0;
- nn < glyph->outline.n_contours;
- first = last + 1, nn++ )
+ last = outline.contours[nn];
+
+ /* Avoid single-point contours since they are never rasterized. */
+ /* In some fonts, they correspond to mark attachment points */
+ /* which are way outside of the glyph's real outline. */
+ if ( last <= first )
+ continue;
+
+ if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
{
- FT_Int pp;
-
-
- last = glyph->outline.contours[nn];
-
- /* Avoid single-point contours since they are never */
- /* rasterized. In some fonts, they correspond to mark */
- /* attachment points which are way outside of the glyph's */
- /* real outline. */
- if ( last <= first )
- continue;
-
- switch ( bb )
+ if ( AF_CJK_IS_RIGHT_BLUE( bs ) )
{
- case AF_CJK_BLUE_TOP:
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y > best_pos )
- {
- best_point = pp;
- best_pos = points[pp].y;
- }
- break;
-
- case AF_CJK_BLUE_BOTTOM:
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y < best_pos )
- {
- best_point = pp;
- best_pos = points[pp].y;
- }
- break;
-
- case AF_CJK_BLUE_LEFT:
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].x < best_pos )
- {
- best_point = pp;
- best_pos = points[pp].x;
- }
- break;
-
- case AF_CJK_BLUE_RIGHT:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x > best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
- break;
-
- default:
- ;
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].x < best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].x;
+ }
}
}
- FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
+ else
+ {
+ if ( AF_CJK_IS_TOP_BLUE( bs ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y > best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].y;
+ }
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y < best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].y;
+ }
+ }
+ }
}
- if ( fill )
- fills[num_fills++] = best_pos;
- else
- flats[num_flats++] = best_pos;
+ FT_TRACE5(( " U+%04lX: best_pos = %5ld\n", ch, best_pos ));
}
- }
+
+ if ( fill )
+ fills[num_fills++] = best_pos;
+ else
+ flats[num_flats++] = best_pos;
+
+ } /* end while loop */
if ( num_flats == 0 && num_fills == 0 )
{
@@ -436,34 +486,30 @@
* we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then
*/
- FT_TRACE5(( "empty\n" ));
+ FT_TRACE5(( " empty\n" ));
continue;
}
- /* we have computed the contents of the `fill' and `flats' tables, */
- /* now determine the reference position of the blue -- */
- /* we simply take the median value after a simple sort */
- af_sort_pos( num_flats, flats );
+ /* we have computed the contents of the `fill' and `flats' tables, */
+ /* now determine the reference and overshoot position of the blue -- */
+ /* we simply take the median value after a simple sort */
af_sort_pos( num_fills, fills );
+ af_sort_pos( num_flats, flats );
- if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb )
- axis = &metrics->axis[AF_DIMENSION_VERT];
- else
- axis = &metrics->axis[AF_DIMENSION_HORZ];
-
- blue = & axis->blues[axis->blue_count];
- blue_ref = & blue->ref.org;
- blue_shoot = & blue->shoot.org;
+ blue = &axis->blues[axis->blue_count];
+ blue_ref = &blue->ref.org;
+ blue_shoot = &blue->shoot.org;
axis->blue_count++;
+
if ( num_flats == 0 )
{
- *blue_ref = fills[num_fills / 2];
+ *blue_ref =
*blue_shoot = fills[num_fills / 2];
}
else if ( num_fills == 0 )
{
- *blue_ref = flats[num_flats / 2];
+ *blue_ref =
*blue_shoot = flats[num_flats / 2];
}
else
@@ -481,51 +527,71 @@
FT_Bool under_ref = FT_BOOL( shoot < ref );
- if ( ( AF_CJK_BLUE_TOP == bb ||
- AF_CJK_BLUE_RIGHT == bb ) ^ under_ref )
- *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ /* AF_CJK_IS_TOP_BLUE covers `right' and `top' */
+ if ( AF_CJK_IS_TOP_BLUE( bs ) ^ under_ref )
+ {
+ *blue_ref =
+ *blue_shoot = ( shoot + ref ) / 2;
+
+ FT_TRACE5(( " [reference smaller than overshoot,"
+ " taking mean value]\n" ));
+ }
}
blue->flags = 0;
- if ( AF_CJK_BLUE_TOP == bb )
- blue->flags |= AF_CJK_BLUE_IS_TOP;
- else if ( AF_CJK_BLUE_RIGHT == bb )
- blue->flags |= AF_CJK_BLUE_IS_RIGHT;
+ if ( AF_CJK_IS_TOP_BLUE( bs ) )
+ blue->flags |= AF_CJK_BLUE_TOP;
- FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n",
- cjk_blue_name[bb], *blue_ref, *blue_shoot ));
- }
+ FT_TRACE5(( " -> reference = %ld\n"
+ " overshoot = %ld\n",
+ *blue_ref, *blue_shoot ));
+
+ } /* end for loop */
+
+ af_shaper_buf_destroy( face, shaper_buf );
+
+ FT_TRACE5(( "\n" ));
return;
}
/* Basically the Latin version with type AF_CJKMetrics for metrics. */
+
FT_LOCAL_DEF( void )
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face )
{
- FT_UInt i;
FT_Bool started = 0, same_width = 1;
FT_Fixed advance, old_advance = 0;
+ void* shaper_buf;
- /* check whether all ASCII digits have the same advance width; */
- /* digit `0' is 0x30 in all supported charmaps */
- for ( i = 0x30; i <= 0x39; i++ )
+ /* in all supported charmaps, digits have character codes 0x30-0x39 */
+ const char digits[] = "0 1 2 3 4 5 6 7 8 9";
+ const char* p;
+
+
+ p = digits;
+ shaper_buf = af_shaper_buf_create( face );
+
+ while ( *p )
{
- FT_UInt glyph_index;
+ FT_ULong glyph_index;
+ unsigned int num_idx;
- glyph_index = FT_Get_Char_Index( face, i );
- if ( glyph_index == 0 )
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
continue;
- if ( FT_Get_Advance( face, glyph_index,
- FT_LOAD_NO_SCALE |
- FT_LOAD_NO_HINTING |
- FT_LOAD_IGNORE_TRANSFORM,
- &advance ) )
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ &advance,
+ NULL );
+ if ( !glyph_index )
continue;
if ( started )
@@ -543,10 +609,14 @@
}
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
metrics->root.digits_have_same_width = same_width;
}
+ /* Initialize global metrics. */
+
FT_LOCAL_DEF( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
@@ -556,21 +626,21 @@
metrics->units_per_em = face->units_per_EM;
- if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
- face->charmap = NULL;
- else
+ if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
{
af_cjk_metrics_init_widths( metrics, face );
- af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
+ af_cjk_metrics_init_blues( metrics, face );
af_cjk_metrics_check_digits( metrics, face );
}
FT_Set_Charmap( face, oldmap );
-
return FT_Err_Ok;
}
+ /* Adjust scaling value, then scale and shift widths */
+ /* and blue zones (if applicable) for given dimension. */
+
static void
af_cjk_metrics_scale_dim( AF_CJKMetrics metrics,
AF_Scaler scaler,
@@ -582,8 +652,6 @@
FT_UInt nn;
- axis = &metrics->axis[dim];
-
if ( dim == AF_DIMENSION_HORZ )
{
scale = scaler->x_scale;
@@ -595,6 +663,8 @@
delta = scaler->y_delta;
}
+ axis = &metrics->axis[dim];
+
if ( axis->org_scale == scale && axis->org_delta == delta )
return;
@@ -650,12 +720,13 @@
blue->shoot.fit = blue->ref.fit - delta2;
- FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: "
- "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n",
- ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
- nn, blue->ref.org, blue->shoot.org,
- blue->ref.cur / 64.0, blue->ref.fit / 64.0,
- blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+ FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
+ " ref: cur=%.2f fit=%.2f\n"
+ " shoot: cur=%.2f fit=%.2f\n",
+ ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
+ nn, blue->ref.org, blue->shoot.org,
+ blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+ blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
blue->flags |= AF_CJK_BLUE_ACTIVE;
}
@@ -663,10 +734,14 @@
}
+ /* Scale global values in both directions. */
+
FT_LOCAL_DEF( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler )
{
+ /* we copy the whole structure since the x and y scaling values */
+ /* are not modified, contrary to e.g. the `latin' auto-hinter */
metrics->root.scaler = *scaler;
af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
@@ -674,6 +749,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_cjk_get_standard_widths( AF_CJKMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -682,6 +773,9 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Walk over all contours and compute its segments. */
+
static FT_Error
af_cjk_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim )
@@ -703,8 +797,8 @@
{
AF_Point pt = seg->first;
AF_Point last = seg->last;
- AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
- AF_Flags f1;
+ FT_UInt f0 = pt->flags & AF_FLAG_CONTROL;
+ FT_UInt f1;
seg->flags &= ~AF_EDGE_ROUND;
@@ -712,7 +806,7 @@
for ( ; pt != last; f0 = f1 )
{
pt = pt->next;
- f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
+ f1 = pt->flags & AF_FLAG_CONTROL;
if ( !f0 && !f1 )
break;
@@ -748,10 +842,6 @@
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
- /* the fake segments are for metrics hinting only */
- if ( seg1->first == seg1->last )
- continue;
-
if ( seg1->dir != major_dir )
continue;
@@ -850,19 +940,19 @@
if ( link == seg2 )
{
- seg->link = 0;
+ seg->link = NULL;
seg->serif = link1;
}
else if ( link == link2 )
{
- seg->link = 0;
+ seg->link = NULL;
seg->serif = seg1;
}
}
}
else
{
- seg1->link = link1->link = 0;
+ seg1->link = link1->link = NULL;
break;
}
@@ -879,7 +969,7 @@
seg2->num_linked++;
if ( seg2->link != seg1 )
{
- seg1->link = 0;
+ seg1->link = NULL;
if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 )
seg1->serif = seg2->link;
@@ -938,7 +1028,7 @@
for ( seg = segments; seg < segment_limit; seg++ )
{
- AF_Edge found = 0;
+ AF_Edge found = NULL;
FT_Pos best = 0xFFFFU;
FT_Int ee;
@@ -1011,10 +1101,11 @@
edge->first = seg;
edge->last = seg;
- edge->fpos = seg->pos;
- edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
- seg->edge_next = seg;
edge->dir = seg->dir;
+ edge->fpos = seg->pos;
+ edge->opos = FT_MulFix( seg->pos, scale );
+ edge->pos = edge->opos;
+ seg->edge_next = seg;
}
else
{
@@ -1026,25 +1117,26 @@
}
}
- /*********************************************************************/
- /* */
- /* Good, we now compute each edge's properties according to segments */
- /* found on its position. Basically, these are as follows. */
- /* */
- /* - edge's main direction */
- /* - stem edge, serif edge or both (which defaults to stem then) */
- /* - rounded edge, straight or both (which defaults to straight) */
- /* - link for edge */
- /* */
- /*********************************************************************/
+ /******************************************************************/
+ /* */
+ /* Good, we now compute each edge's properties according to the */
+ /* segments found on its position. Basically, these are */
+ /* */
+ /* - the edge's main direction */
+ /* - stem edge, serif edge or both (which defaults to stem then) */
+ /* - rounded edge, straight or both (which defaults to straight) */
+ /* - link for edge */
+ /* */
+ /******************************************************************/
- /* first of all, set the `edge' field in each segment -- this is */
- /* required in order to compute edge links */
- /* */
- /* Note that removing this loop and setting the `edge' field of each */
- /* segment directly in the code above slows down execution speed for */
- /* some reasons on platforms like the Sun. */
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+ /*
+ * Note that removing this loop and setting the `edge' field of each
+ * segment directly in the code above slows down execution speed for
+ * some reasons on platforms like the Sun.
+ */
{
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
@@ -1144,7 +1236,7 @@
/* Example: the `c' in cour.pfa at size 13 */
if ( edge->serif && edge->link )
- edge->serif = 0;
+ edge->serif = NULL;
}
}
@@ -1153,6 +1245,8 @@
}
+ /* Detect segments and edges for given dimension. */
+
static FT_Error
af_cjk_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1171,7 +1265,9 @@
}
- FT_LOCAL_DEF( void )
+ /* Compute all edges which lie within blue zones. */
+
+ static void
af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
AF_CJKMetrics metrics,
AF_Dimension dim )
@@ -1218,10 +1314,10 @@
/* zone, check for left edges */
/* */
/* of course, that's for TrueType */
- is_top_right_blue =
- FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP ) != 0 ) ||
- ( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) );
- is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+ is_top_right_blue =
+ (FT_Byte)( ( blue->flags & AF_CJK_BLUE_TOP ) != 0 );
+ is_major_dir =
+ FT_BOOL( edge->dir == axis->major_dir );
/* if it is a top zone, the edge must be against the major */
/* direction; if it is a bottom zone, it must be in the major */
@@ -1258,6 +1354,8 @@
}
+ /* Initalize hinting engine. */
+
FT_LOCAL_DEF( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
@@ -1266,7 +1364,7 @@
FT_UInt32 scaler_flags, other_flags;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
* correct x_scale and y_scale when needed, since they may have
@@ -1280,7 +1378,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#ifdef AF_CONFIG_OPTION_USE_WARPER
+#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
#endif
@@ -1313,10 +1411,16 @@
scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
- return 0;
+ return FT_Err_Ok;
}
@@ -1328,18 +1432,18 @@
/*************************************************************************/
/*************************************************************************/
- /* snap a given width in scaled coordinates to one of the */
- /* current standard widths */
+ /* Snap a given width in scaled coordinates to one of the */
+ /* current standard widths. */
static FT_Pos
af_cjk_snap_width( AF_Width widths,
- FT_Int count,
+ FT_UInt count,
FT_Pos width )
{
- int n;
- FT_Pos best = 64 + 32 + 2;
- FT_Pos reference = width;
- FT_Pos scaled;
+ FT_UInt n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
for ( n = 0; n < count; n++ )
@@ -1376,17 +1480,19 @@
}
- /* compute the snapped width of a given stem */
+ /* Compute the snapped width of a given stem. */
+ /* There is a lot of voodoo in this function; changing the hard-coded */
+ /* parameters influence the whole hinting process. */
static FT_Pos
af_cjk_compute_stem_width( AF_GlyphHints hints,
AF_Dimension dim,
FT_Pos width,
- AF_Edge_Flags base_flags,
- AF_Edge_Flags stem_flags )
+ FT_UInt base_flags,
+ FT_UInt stem_flags )
{
- AF_CJKMetrics metrics = (AF_CJKMetrics) hints->metrics;
- AF_CJKAxis axis = & metrics->axis[dim];
+ AF_CJKMetrics metrics = (AF_CJKMetrics)hints->metrics;
+ AF_CJKAxis axis = &metrics->axis[dim];
FT_Pos dist = width;
FT_Int sign = 0;
FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT );
@@ -1497,7 +1603,7 @@
}
- /* align one stem edge relative to the previous stem edge */
+ /* Align one stem edge relative to the previous stem edge. */
static void
af_cjk_align_linked_edge( AF_GlyphHints hints,
@@ -1507,16 +1613,24 @@
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
- FT_Pos fitted_width = af_cjk_compute_stem_width(
- hints, dim, dist,
- (AF_Edge_Flags)base_edge->flags,
- (AF_Edge_Flags)stem_edge->flags );
+ FT_Pos fitted_width = af_cjk_compute_stem_width( hints, dim, dist,
+ base_edge->flags,
+ stem_edge->flags );
stem_edge->pos = base_edge->pos + fitted_width;
+
+ FT_TRACE5(( " CJKLINK: edge %d @%d (opos=%.2f) linked to %.2f,"
+ " dist was %.2f, now %.2f\n",
+ stem_edge - hints->axis[dim].edges, stem_edge->fpos,
+ stem_edge->opos / 64.0, stem_edge->pos / 64.0,
+ dist / 64.0, fitted_width / 64.0 ));
}
+ /* Shift the coordinates of the `serif' edge by the same amount */
+ /* as the corresponding `base' edge has been moved already. */
+
static void
af_cjk_align_serif_edge( AF_GlyphHints hints,
AF_Edge base,
@@ -1579,8 +1693,8 @@
org_len = edge2->opos - edge->opos;
cur_len = af_cjk_compute_stem_width( hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ edge->flags,
+ edge2->flags );
org_center = ( edge->opos + edge2->opos ) / 2 + anchor;
cur_pos1 = org_center - cur_len / 2;
@@ -1670,6 +1784,8 @@
}
+ /* The main grid-fitting routine. */
+
static void
af_cjk_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1679,16 +1795,22 @@
AF_Edge edge_limit = edges + axis->num_edges;
FT_PtrDist n_edges;
AF_Edge edge;
- AF_Edge anchor = 0;
+ AF_Edge anchor = NULL;
FT_Pos delta = 0;
FT_Int skipped = 0;
FT_Bool has_last_stem = FALSE;
FT_Pos last_stem_pos = 0;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_UInt num_actions = 0;
+#endif
+
+
+ FT_TRACE5(( "cjk %s edge hinting (style `%s')\n",
+ dim == AF_DIMENSION_VERT ? "horizontal" : "vertical",
+ af_style_names[hints->metrics->style_class->style] ));
/* we begin by aligning all stems relative to the blue zone */
- FT_TRACE5(( "==== cjk hinting %s edges =====\n",
- dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
if ( AF_HINTS_DO_BLUES( hints ) )
{
@@ -1719,10 +1841,14 @@
if ( !edge1 )
continue;
- FT_TRACE5(( "CJKBLUE: edge %d @%d (opos=%.2f) snapped to (%.2f), "
- "was (%.2f)\n",
- edge1-edges, edge1->fpos, edge1->opos / 64.0, blue->fit / 64.0,
- edge1->pos / 64.0 ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE5(( " CJKBLUE: edge %d @%d (opos=%.2f) snapped to %.2f,"
+ " was %.2f\n",
+ edge1 - edges, edge1->fpos, edge1->opos / 64.0,
+ blue->fit / 64.0, edge1->pos / 64.0 ));
+
+ num_actions++;
+#endif
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
@@ -1731,6 +1857,10 @@
{
af_cjk_align_linked_edge( hints, dim, edge1, edge2 );
edge2->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ num_actions++;
+#endif
}
if ( !anchor )
@@ -1772,6 +1902,7 @@
}
/* now align the stem */
+
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
@@ -1779,6 +1910,11 @@
af_cjk_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ num_actions++;
+#endif
+
continue;
}
@@ -1786,6 +1922,11 @@
{
af_cjk_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ num_actions++;
+#endif
+
/* We rarely reaches here it seems;
* usually the two edges belonging
* to one stem are marked as DONE together
@@ -1953,7 +2094,7 @@
}
if ( !skipped )
- return;
+ goto Exit;
/*
* now hint the remaining edges (serifs and single) in order
@@ -1973,7 +2114,7 @@
}
if ( !skipped )
- return;
+ goto Exit;
for ( edge = edges; edge < edge_limit; edge++ )
{
@@ -2011,6 +2152,16 @@
}
}
}
+
+ Exit:
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !num_actions )
+ FT_TRACE5(( " (none)\n" ));
+ FT_TRACE5(( "\n" ));
+#endif
+
+ return;
}
@@ -2104,8 +2255,11 @@
}
+ /* Apply the complete hinting algorithm to a CJK glyph. */
+
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
+ af_cjk_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
@@ -2113,6 +2267,7 @@
int dim;
FT_UNUSED( metrics );
+ FT_UNUSED( glyph_index );
error = af_glyph_hints_reload( hints, outline );
@@ -2120,7 +2275,13 @@
goto Exit;
/* analyze glyph outline */
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) ) ||
+ AF_HINTS_DO_HORIZONTAL( hints ) )
+#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+#endif
{
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
@@ -2146,8 +2307,9 @@
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
@@ -2169,12 +2331,6 @@
}
}
-#if 0
- af_glyph_hints_dump_points( hints );
- af_glyph_hints_dump_segments( hints );
- af_glyph_hints_dump_edges( hints );
-#endif
-
af_glyph_hints_save( hints, outline );
Exit:
@@ -2191,84 +2347,43 @@
/*************************************************************************/
- /* this corresponds to Unicode 6.0 */
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_cjk_writing_system_class,
- static const AF_Script_UniRangeRec af_cjk_uniranges[] =
- {
- AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo */
- AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */
- AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */
- AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */
- AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */
- AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */
- AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */
- AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */
- AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */
- AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */
- AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */
- AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */
- AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */
- AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */
- AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */
- AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */
- AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */
- AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */
- AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */
- AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */
- AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */
- AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */
- AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */
- AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */
- AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */
- AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */
- AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */
- AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */
- AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */
- AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */
- AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */
- AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */
- AF_UNIRANGE_REC( 0UL, 0UL )
- };
-
-
- AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
- AF_SCRIPT_CJK,
- af_cjk_uniranges,
- 0x7530, /* 田 */
+ AF_WRITING_SYSTEM_CJK,
sizeof ( AF_CJKMetricsRec ),
- (AF_Script_InitMetricsFunc) af_cjk_metrics_init,
- (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init,
+ (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_cjk_get_standard_widths,
- (AF_Script_InitHintsFunc) af_cjk_hints_init,
- (AF_Script_ApplyHintsFunc) af_cjk_hints_apply
+ (AF_WritingSystem_InitHintsFunc) af_cjk_hints_init,
+ (AF_WritingSystem_ApplyHintsFunc) af_cjk_hints_apply
)
+
#else /* !AF_CONFIG_OPTION_CJK */
- static const AF_Script_UniRangeRec af_cjk_uniranges[] =
- {
- AF_UNIRANGE_REC( 0UL, 0UL )
- };
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_cjk_writing_system_class,
- AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
- AF_SCRIPT_CJK,
- af_cjk_uniranges,
- 0,
+ AF_WRITING_SYSTEM_CJK,
sizeof ( AF_CJKMetricsRec ),
- (AF_Script_InitMetricsFunc) NULL,
- (AF_Script_ScaleMetricsFunc)NULL,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) NULL,
+ (AF_WritingSystem_ScaleMetricsFunc)NULL,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
- (AF_Script_InitHintsFunc) NULL,
- (AF_Script_ApplyHintsFunc) NULL
+ (AF_WritingSystem_InitHintsFunc) NULL,
+ (AF_WritingSystem_ApplyHintsFunc) NULL
)
+
#endif /* !AF_CONFIG_OPTION_CJK */
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index ab816f2..e395e74 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -2,9 +2,9 @@
/* */
/* afcjk.h */
/* */
-/* Auto-fitter hinting routines for CJK script (specification). */
+/* Auto-fitter hinting routines for CJK writing system (specification). */
/* */
-/* Copyright 2006, 2007, 2011, 2012 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,41 +26,39 @@
FT_BEGIN_HEADER
- /* the CJK-specific script class */
+ /* the CJK-specific writing system */
- AF_DECLARE_SCRIPT_CLASS( af_cjk_script_class )
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_cjk_writing_system_class )
- /* CJK (global) metrics management */
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C J K G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
/*
* CJK glyphs tend to fill the square. So we have both vertical and
* horizontal blue zones. But some glyphs have flat bounding strokes that
* leave some space between neighbour glyphs.
*/
- enum
- {
- AF_CJK_BLUE_TOP,
- AF_CJK_BLUE_BOTTOM,
- AF_CJK_BLUE_LEFT,
- AF_CJK_BLUE_RIGHT,
- AF_CJK_BLUE_MAX
- };
-
+#define AF_CJK_IS_TOP_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP )
+#define AF_CJK_IS_HORIZ_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ )
+#define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE
#define AF_CJK_MAX_WIDTHS 16
-#define AF_CJK_MAX_BLUES AF_CJK_BLUE_MAX
- enum
- {
- AF_CJK_BLUE_ACTIVE = 1 << 0,
- AF_CJK_BLUE_IS_TOP = 1 << 1,
- AF_CJK_BLUE_IS_RIGHT = 1 << 2,
- AF_CJK_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */
- /* optimization */
- AF_CJK_BLUE_FLAG_MAX
- };
+#define AF_CJK_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
+#define AF_CJK_BLUE_TOP ( 1U << 1 ) /* result of AF_CJK_IS_TOP_BLUE */
+#define AF_CJK_BLUE_ADJUSTMENT ( 1U << 2 ) /* used for scale adjustment */
+ /* optimization */
typedef struct AF_CJKBlueRec_
@@ -77,16 +75,16 @@
FT_Fixed scale;
FT_Pos delta;
- FT_UInt width_count;
- AF_WidthRec widths[AF_CJK_MAX_WIDTHS];
- FT_Pos edge_distance_threshold;
- FT_Pos standard_width;
- FT_Bool extra_light;
+ FT_UInt width_count; /* number of used widths */
+ AF_WidthRec widths[AF_CJK_MAX_WIDTHS]; /* widths array */
+ FT_Pos edge_distance_threshold; /* used for creating edges */
+ FT_Pos standard_width; /* the default stem thickness */
+ FT_Bool extra_light; /* is standard width very light? */
/* used for horizontal metrics too for CJK */
FT_Bool control_overshoot;
FT_UInt blue_count;
- AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
+ AF_CJKBlueRec blues[AF_BLUE_STRINGSET_MAX];
FT_Fixed org_scale;
FT_Pos org_delta;
@@ -96,9 +94,9 @@
typedef struct AF_CJKMetricsRec_
{
- AF_ScriptMetricsRec root;
- FT_UInt units_per_em;
- AF_CJKAxisRec axis[AF_DIMENSION_MAX];
+ AF_StyleMetricsRec root;
+ FT_UInt units_per_em;
+ AF_CJKAxisRec axis[AF_DIMENSION_MAX];
} AF_CJKMetricsRec, *AF_CJKMetrics;
@@ -117,7 +115,8 @@
AF_CJKMetrics metrics );
FT_LOCAL( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
+ af_cjk_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics );
diff --git a/src/autofit/afcover.h b/src/autofit/afcover.h
new file mode 100644
index 0000000..520e8a4
--- /dev/null
+++ b/src/autofit/afcover.h
@@ -0,0 +1,105 @@
+/***************************************************************************/
+/* */
+/* afcover.h */
+/* */
+/* Auto-fitter coverages (specification only). */
+/* */
+/* Copyright 2013-2015 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 header file can be included multiple times. */
+ /* Define `COVERAGE' as needed. */
+
+
+ /* Add new coverages here. The first and second arguments are the */
+ /* coverage name in lowercase and uppercase, respectively, followed */
+ /* by a description string. The last four arguments are the four */
+ /* characters defining the corresponding OpenType feature. */
+
+#if 0
+ /* XXX: It's not possible to define blue zone characters in advance. */
+ COVERAGE( alternative_fractions, ALTERNATIVE_FRACTIONS,
+ "alternative fractions",
+ 'a', 'f', 'r', 'c' )
+#endif
+
+ COVERAGE( petite_capitals_from_capitals, PETITE_CAPITALS_FROM_CAPITALS,
+ "petite capitals from capitals",
+ 'c', '2', 'c', 'p' )
+
+ COVERAGE( small_capitals_from_capitals, SMALL_CAPITALS_FROM_CAPITALS,
+ "small capitals from capitals",
+ 'c', '2', 's', 'c' )
+
+#if 0
+ /* XXX: Only digits are in this coverage, however, both normal style */
+ /* and oldstyle representation forms are possible. */
+ COVERAGE( denominators, DENOMINATORS,
+ "denominators",
+ 'd', 'n', 'o', 'm' )
+#endif
+
+#if 0
+ /* XXX: It's not possible to define blue zone characters in advance. */
+ COVERAGE( fractions, FRACTIONS,
+ "fractions",
+ 'f', 'r', 'a', 'c' )
+#endif
+
+#if 0
+ /* XXX: Only digits are in this coverage, however, both normal style */
+ /* and oldstyle representation forms are possible. */
+ COVERAGE( numerators, NUMERATORS,
+ "numerators",
+ 'n', 'u', 'm', 'r' )
+#endif
+
+ COVERAGE( ordinals, ORDINALS,
+ "ordinals",
+ 'o', 'r', 'd', 'n' )
+
+ COVERAGE( petite_capitals, PETITE_CAPITALS,
+ "petite capitals",
+ 'p', 'c', 'a', 'p' )
+
+ COVERAGE( ruby, RUBY,
+ "ruby",
+ 'r', 'u', 'b', 'y' )
+
+ COVERAGE( scientific_inferiors, SCIENTIFIC_INFERIORS,
+ "scientific inferiors",
+ 's', 'i', 'n', 'f' )
+
+ COVERAGE( small_capitals, SMALL_CAPITALS,
+ "small capitals",
+ 's', 'm', 'c', 'p' )
+
+ COVERAGE( subscript, SUBSCRIPT,
+ "subscript",
+ 's', 'u', 'b', 's' )
+
+ COVERAGE( superscript, SUPERSCRIPT,
+ "superscript",
+ 's', 'u', 'p', 's' )
+
+ COVERAGE( titling, TITLING,
+ "titling",
+ 't', 'i', 't', 'l' )
+
+#if 0
+ /* to be always excluded */
+ COVERAGE(nalt, 'n', 'a', 'l', 't'); /* Alternate Annotation Forms (?) */
+ COVERAGE(ornm, 'o', 'r', 'n', 'm'); /* Ornaments (?) */
+#endif
+
+
+/* END */
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 2294455..9142c78 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (body). */
/* */
-/* Copyright 2003-2005, 2011, 2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,39 +23,52 @@
static FT_Error
- af_dummy_hints_init( AF_GlyphHints hints,
- AF_ScriptMetrics metrics )
+ af_dummy_hints_init( AF_GlyphHints hints,
+ AF_StyleMetrics metrics )
{
- af_glyph_hints_rescale( hints,
- metrics );
+ af_glyph_hints_rescale( hints, metrics );
+
+ hints->x_scale = metrics->scaler.x_scale;
+ hints->y_scale = metrics->scaler.y_scale;
+ hints->x_delta = metrics->scaler.x_delta;
+ hints->y_delta = metrics->scaler.y_delta;
+
return FT_Err_Ok;
}
static FT_Error
- af_dummy_hints_apply( AF_GlyphHints hints,
+ af_dummy_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline )
{
- FT_UNUSED( hints );
- FT_UNUSED( outline );
+ FT_Error error;
- return FT_Err_Ok;
+ FT_UNUSED( glyph_index );
+
+
+ error = af_glyph_hints_reload( hints, outline );
+ if ( !error )
+ af_glyph_hints_save( hints, outline );
+
+ return error;
}
- AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
- AF_SCRIPT_DUMMY,
- NULL,
- 0,
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_dummy_writing_system_class,
- sizeof ( AF_ScriptMetricsRec ),
+ AF_WRITING_SYSTEM_DUMMY,
- (AF_Script_InitMetricsFunc) NULL,
- (AF_Script_ScaleMetricsFunc)NULL,
- (AF_Script_DoneMetricsFunc) NULL,
+ sizeof ( AF_StyleMetricsRec ),
- (AF_Script_InitHintsFunc) af_dummy_hints_init,
- (AF_Script_ApplyHintsFunc) af_dummy_hints_apply
+ (AF_WritingSystem_InitMetricsFunc) NULL,
+ (AF_WritingSystem_ScaleMetricsFunc)NULL,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
+
+ (AF_WritingSystem_InitHintsFunc) af_dummy_hints_init,
+ (AF_WritingSystem_ApplyHintsFunc) af_dummy_hints_apply
)
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index 95d8f8c..b4fdc78 100644
--- a/src/autofit/afdummy.h
+++ b/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (specification). */
/* */
-/* Copyright 2003-2005, 2011 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,11 +25,9 @@
FT_BEGIN_HEADER
- /* A dummy script metrics class used when no hinting should
- * be performed. This is the default for non-latin glyphs!
- */
+ /* A dummy writing system used when no hinting should be performed. */
- AF_DECLARE_SCRIPT_CLASS( af_dummy_script_class )
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_dummy_writing_system_class )
/* */
diff --git a/src/autofit/aferrors.h b/src/autofit/aferrors.h
index 50e1a22..7b416e4 100644
--- a/src/autofit/aferrors.h
+++ b/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
/* */
/* Autofitter error codes (specification only). */
/* */
-/* Copyright 2005, 2012 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 3e41465..3223358 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter routines to compute global hinting values (body). */
/* */
-/* Copyright 2003-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,107 +17,244 @@
#include "afglobal.h"
-#include "afdummy.h"
-#include "aflatin.h"
-#include "afcjk.h"
-#include "afindic.h"
-#include "afpic.h"
+#include "afranges.h"
+#include "afshaper.h"
+#include FT_INTERNAL_DEBUG_H
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afglobal
+
+
+ /* get writing system specific header files */
+#undef WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS ) /* empty */
+#include "afwrtsys.h"
#include "aferrors.h"
+#include "afpic.h"
-#ifdef FT_OPTION_AUTOFIT2
-#include "aflatin2.h"
-#endif
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ AF_DEFINE_SCRIPT_CLASS( \
+ af_ ## s ## _script_class, \
+ AF_SCRIPT_ ## S, \
+ af_ ## s ## _uniranges, \
+ af_ ## s ## _nonbase_uniranges, \
+ ss )
+
+#include "afscript.h"
+
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, ss, c ) \
+ AF_DEFINE_STYLE_CLASS( \
+ af_ ## s ## _style_class, \
+ AF_STYLE_ ## S, \
+ ws, \
+ sc, \
+ ss, \
+ c )
+
+#include "afstyles.h"
+
#ifndef FT_CONFIG_OPTION_PIC
- /* when updating this table, don't forget to update */
- /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
+#undef WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS ) \
+ &af_ ## ws ## _writing_system_class,
- /* populate this list when you add new scripts */
- static AF_ScriptClass const af_script_classes[] =
+ FT_LOCAL_ARRAY_DEF( AF_WritingSystemClass )
+ af_writing_system_classes[] =
{
- &af_dummy_script_class,
-#ifdef FT_OPTION_AUTOFIT2
- &af_latin2_script_class,
-#endif
- &af_latin_script_class,
- &af_cjk_script_class,
- &af_indic_script_class,
+
+#include "afwrtsys.h"
+
+ NULL /* do not remove */
+ };
+
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ &af_ ## s ## _script_class,
+
+ FT_LOCAL_ARRAY_DEF( AF_ScriptClass )
+ af_script_classes[] =
+ {
+
+#include "afscript.h"
+
+ NULL /* do not remove */
+ };
+
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, ss, c ) \
+ &af_ ## s ## _style_class,
+
+ FT_LOCAL_ARRAY_DEF( AF_StyleClass )
+ af_style_classes[] =
+ {
+
+#include "afstyles.h"
+
NULL /* do not remove */
};
#endif /* !FT_CONFIG_OPTION_PIC */
- /* Compute the script index of each glyph within a given face. */
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, ss, c ) #s,
+
+ FT_LOCAL_ARRAY_DEF( char* )
+ af_style_names[] =
+ {
+
+#include "afstyles.h"
+
+ };
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
+ /* Compute the style index of each glyph within a given face. */
static FT_Error
- af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
+ af_face_globals_compute_style_coverage( AF_FaceGlobals globals )
{
FT_Error error;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
- FT_Byte* gscripts = globals->glyph_scripts;
+ FT_UShort* gstyles = globals->glyph_styles;
FT_UInt ss;
FT_UInt i;
+ FT_UInt dflt = ~0U; /* a non-valid value */
- /* the value AF_SCRIPT_NONE means `uncovered glyph' */
- FT_MEM_SET( globals->glyph_scripts,
- AF_SCRIPT_NONE,
- globals->glyph_count );
+ /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */
+ for ( i = 0; i < (FT_UInt)globals->glyph_count; i++ )
+ gstyles[i] = AF_STYLE_UNASSIGNED;
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
{
- /*
- * Ignore this error; we simply use the fallback script.
- * XXX: Shouldn't we rather disable hinting?
- */
+ /*
+ * Ignore this error; we simply use the fallback style.
+ * XXX: Shouldn't we rather disable hinting?
+ */
error = FT_Err_Ok;
goto Exit;
}
- /* scan each script in a Unicode charmap */
- for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
+ /* scan each style in a Unicode charmap */
+ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
{
- AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[ss];
+ AF_StyleClass style_class =
+ AF_STYLE_CLASSES_GET[ss];
+ AF_ScriptClass script_class =
+ AF_SCRIPT_CLASSES_GET[style_class->script];
AF_Script_UniRange range;
- if ( clazz->script_uni_ranges == NULL )
+ if ( script_class->script_uni_ranges == NULL )
continue;
/*
* Scan all Unicode points in the range and set the corresponding
- * glyph script index.
+ * glyph style index.
*/
- for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
+ if ( style_class->coverage == AF_COVERAGE_DEFAULT )
{
- FT_ULong charcode = range->first;
- FT_UInt gindex;
+ if ( (FT_UInt)style_class->script ==
+ globals->module->default_script )
+ dflt = ss;
-
- gindex = FT_Get_Char_Index( face, charcode );
-
- if ( gindex != 0 &&
- gindex < (FT_ULong)globals->glyph_count &&
- gscripts[gindex] == AF_SCRIPT_NONE )
- gscripts[gindex] = (FT_Byte)ss;
-
- for (;;)
+ for ( range = script_class->script_uni_ranges;
+ range->first != 0;
+ range++ )
{
- charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ FT_ULong charcode = range->first;
+ FT_UInt gindex;
- if ( gindex == 0 || charcode > range->last )
- break;
- if ( gindex < (FT_ULong)globals->glyph_count &&
- gscripts[gindex] == AF_SCRIPT_NONE )
- gscripts[gindex] = (FT_Byte)ss;
+ gindex = FT_Get_Char_Index( face, charcode );
+
+ if ( gindex != 0 &&
+ gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+ gstyles[gindex] = (FT_UShort)ss;
+
+ for (;;)
+ {
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+
+ if ( gindex == 0 || charcode > range->last )
+ break;
+
+ if ( gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
+ gstyles[gindex] = (FT_UShort)ss;
+ }
+ }
+
+ /* do the same for the script's non-base characters */
+ for ( range = script_class->script_uni_nonbase_ranges;
+ range->first != 0;
+ range++ )
+ {
+ FT_ULong charcode = range->first;
+ FT_UInt gindex;
+
+
+ gindex = FT_Get_Char_Index( face, charcode );
+
+ if ( gindex != 0 &&
+ gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+ gstyles[gindex] |= AF_NONBASE;
+
+ for (;;)
+ {
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+
+ if ( gindex == 0 || charcode > range->last )
+ break;
+
+ if ( gindex < (FT_ULong)globals->glyph_count &&
+ ( gstyles[gindex] & AF_STYLE_MASK ) == (FT_UShort)ss )
+ gstyles[gindex] |= AF_NONBASE;
+ }
}
}
+ else
+ {
+ /* get glyphs not directly addressable by cmap */
+ af_shaper_get_coverage( globals, style_class, gstyles );
+ }
+ }
+
+ /* handle the default OpenType features of the default script ... */
+ af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
+
+ /* ... and the remaining default OpenType features */
+ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ {
+ AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+
+
+ if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
+ af_shaper_get_coverage( globals, style_class, gstyles );
}
/* mark ASCII digits */
@@ -127,29 +264,68 @@
if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
- gscripts[gindex] |= AF_DIGIT;
+ gstyles[gindex] |= AF_DIGIT;
}
Exit:
/*
- * By default, all uncovered glyphs are set to the fallback script.
+ * By default, all uncovered glyphs are set to the fallback style.
* XXX: Shouldn't we disable hinting or do something similar?
*/
- if ( globals->module->fallback_script != AF_SCRIPT_NONE )
+ if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED )
{
FT_Long nn;
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
- if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_NONE )
+ if ( ( gstyles[nn] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED )
{
- gscripts[nn] &= ~AF_SCRIPT_NONE;
- gscripts[nn] |= globals->module->fallback_script;
+ gstyles[nn] &= ~AF_STYLE_MASK;
+ gstyles[nn] |= globals->module->fallback_style;
}
}
}
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+ FT_TRACE4(( "\n"
+ "style coverage\n"
+ "==============\n"
+ "\n" ));
+
+ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ {
+ AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+ FT_UInt count = 0;
+ FT_Long idx;
+
+
+ FT_TRACE4(( "%s:\n", af_style_names[style_class->style] ));
+
+ for ( idx = 0; idx < globals->glyph_count; idx++ )
+ {
+ if ( ( gstyles[idx] & AF_STYLE_MASK ) == style_class->style )
+ {
+ if ( !( count % 10 ) )
+ FT_TRACE4(( " " ));
+
+ FT_TRACE4(( " %d", idx ));
+ count++;
+
+ if ( !( count % 10 ) )
+ FT_TRACE4(( "\n" ));
+ }
+ }
+
+ if ( !count )
+ FT_TRACE4(( " (none)\n" ));
+ if ( count % 10 )
+ FT_TRACE4(( "\n" ));
+ }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
FT_Set_Charmap( face, old_charmap );
return error;
}
@@ -167,23 +343,38 @@
memory = face->memory;
- if ( FT_ALLOC( globals, sizeof ( *globals ) +
- face->num_glyphs * sizeof ( FT_Byte ) ) )
+ /* we allocate an AF_FaceGlobals structure together */
+ /* with the glyph_styles array */
+ if ( FT_ALLOC( globals,
+ sizeof ( *globals ) +
+ (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
goto Exit;
- globals->face = face;
- globals->glyph_count = face->num_glyphs;
- globals->glyph_scripts = (FT_Byte*)( globals + 1 );
- globals->module = module;
+ globals->face = face;
+ globals->glyph_count = face->num_glyphs;
+ /* right after the globals structure come the glyph styles */
+ globals->glyph_styles = (FT_UShort*)( globals + 1 );
+ globals->module = module;
+ globals->stem_darkening_for_ppem = 0;
+ globals->darken_x = 0;
+ globals->darken_y = 0;
+ globals->standard_vertical_width = 0;
+ globals->standard_horizontal_width = 0;
+ globals->scale_down_factor = 0;
- error = af_face_globals_compute_script_coverage( globals );
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ globals->hb_font = hb_ft_font_create( face, NULL );
+ globals->hb_buf = hb_buffer_create();
+#endif
+
+ error = af_face_globals_compute_style_coverage( globals );
if ( error )
{
af_face_globals_free( globals );
globals = NULL;
}
-
- globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
+ else
+ globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
Exit:
*aglobals = globals;
@@ -200,25 +391,41 @@
FT_UInt nn;
- for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
+ for ( nn = 0; nn < AF_STYLE_MAX; nn++ )
{
if ( globals->metrics[nn] )
{
- AF_ScriptClass clazz = AF_SCRIPT_CLASSES_GET[nn];
+ AF_StyleClass style_class =
+ AF_STYLE_CLASSES_GET[nn];
+ AF_WritingSystemClass writing_system_class =
+ AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
- FT_ASSERT( globals->metrics[nn]->clazz == clazz );
-
- if ( clazz->script_metrics_done )
- clazz->script_metrics_done( globals->metrics[nn] );
+ if ( writing_system_class->style_metrics_done )
+ writing_system_class->style_metrics_done( globals->metrics[nn] );
FT_FREE( globals->metrics[nn] );
}
}
- globals->glyph_count = 0;
- globals->glyph_scripts = NULL; /* no need to free this one! */
- globals->face = NULL;
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ hb_font_destroy( globals->hb_font );
+ globals->hb_font = NULL;
+
+ hb_buffer_destroy( globals->hb_buf );
+ globals->hb_buf = NULL;
+#endif
+
+ globals->glyph_count = 0;
+ globals->stem_darkening_for_ppem = 0;
+ globals->darken_x = 0;
+ globals->darken_y = 0;
+ globals->standard_vertical_width = 0;
+ globals->standard_horizontal_width = 0;
+ globals->scale_down_factor = 0;
+ /* no need to free this one! */
+ globals->glyph_styles = NULL;
+ globals->face = NULL;
FT_FREE( globals );
}
@@ -226,18 +433,18 @@
FT_LOCAL_DEF( FT_Error )
- af_face_globals_get_metrics( AF_FaceGlobals globals,
- FT_UInt gindex,
- FT_UInt options,
- AF_ScriptMetrics *ametrics )
+ af_face_globals_get_metrics( AF_FaceGlobals globals,
+ FT_UInt gindex,
+ FT_UInt options,
+ AF_StyleMetrics *ametrics )
{
- AF_ScriptMetrics metrics = NULL;
- FT_UInt gidx;
- AF_ScriptClass clazz;
- FT_UInt script = options & 15;
- const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
- sizeof ( AF_SCRIPT_CLASSES_GET[0] );
- FT_Error error = FT_Err_Ok;
+ AF_StyleMetrics metrics = NULL;
+
+ AF_Style style = (AF_Style)options;
+ AF_WritingSystemClass writing_system_class;
+ AF_StyleClass style_class;
+
+ FT_Error error = FT_Err_Ok;
if ( gindex >= (FT_ULong)globals->glyph_count )
@@ -246,41 +453,44 @@
goto Exit;
}
- gidx = script;
- if ( gidx == 0 || gidx + 1 >= script_max )
- gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_NONE;
+ /* if we have a forced style (via `options'), use it, */
+ /* otherwise look into `glyph_styles' array */
+ if ( style == AF_STYLE_NONE_DFLT || style + 1 >= AF_STYLE_MAX )
+ style = (AF_Style)( globals->glyph_styles[gindex] &
+ AF_STYLE_UNASSIGNED );
- clazz = AF_SCRIPT_CLASSES_GET[gidx];
- if ( script == 0 )
- script = clazz->script;
+ style_class = AF_STYLE_CLASSES_GET[style];
+ writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET
+ [style_class->writing_system];
- metrics = globals->metrics[clazz->script];
+ metrics = globals->metrics[style];
if ( metrics == NULL )
{
/* create the global metrics object if necessary */
FT_Memory memory = globals->face->memory;
- if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
+ if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) )
goto Exit;
- metrics->clazz = clazz;
- metrics->globals = globals;
+ metrics->style_class = style_class;
+ metrics->globals = globals;
- if ( clazz->script_metrics_init )
+ if ( writing_system_class->style_metrics_init )
{
- error = clazz->script_metrics_init( metrics, globals->face );
+ error = writing_system_class->style_metrics_init( metrics,
+ globals->face );
if ( error )
{
- if ( clazz->script_metrics_done )
- clazz->script_metrics_done( metrics );
+ if ( writing_system_class->style_metrics_done )
+ writing_system_class->style_metrics_done( metrics );
FT_FREE( metrics );
goto Exit;
}
}
- globals->metrics[clazz->script] = metrics;
+ globals->metrics[style] = metrics;
}
Exit:
@@ -295,7 +505,7 @@
FT_UInt gindex )
{
if ( gindex < (FT_ULong)globals->glyph_count )
- return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
+ return (FT_Bool)( globals->glyph_styles[gindex] & AF_DIGIT );
return (FT_Bool)0;
}
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 2e24900..5b4e439 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
/* Auto-fitter routines to compute global hinting values */
/* (specification). */
/* */
-/* Copyright 2003-2005, 2007, 2009, 2011-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,22 +23,65 @@
#include "aftypes.h"
#include "afmodule.h"
+#include "afshaper.h"
FT_BEGIN_HEADER
+ FT_LOCAL_ARRAY( AF_WritingSystemClass )
+ af_writing_system_classes[];
+
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ AF_DECLARE_SCRIPT_CLASS( af_ ## s ## _script_class )
+
+#include "afscript.h"
+
+ FT_LOCAL_ARRAY( AF_ScriptClass )
+ af_script_classes[];
+
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, ss, c ) \
+ AF_DECLARE_STYLE_CLASS( af_ ## s ## _style_class )
+
+#include "afstyles.h"
+
+ FT_LOCAL_ARRAY( AF_StyleClass )
+ af_style_classes[];
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_LOCAL_ARRAY( char* )
+ af_style_names[];
+#endif
+
+
/*
* Default values and flags for both autofitter globals (found in
* AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
*/
- /* index of fallback script in `af_script_classes' */
-#define AF_SCRIPT_FALLBACK 2
- /* a bit mask indicating an uncovered glyph */
-#define AF_SCRIPT_NONE 0x7F
- /* if this flag is set, we have an ASCII digit */
-#define AF_DIGIT 0x80
+ /* index of fallback style in `af_style_classes' */
+#ifdef AF_CONFIG_OPTION_CJK
+#define AF_STYLE_FALLBACK AF_STYLE_HANI_DFLT
+#else
+#define AF_STYLE_FALLBACK AF_STYLE_NONE_DFLT
+#endif
+ /* default script for OpenType; ignored if HarfBuzz isn't used */
+#define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN
+
+ /* a bit mask for AF_DIGIT and AF_NONBASE */
+#define AF_STYLE_MASK 0x3FFF
+ /* an uncovered glyph */
+#define AF_STYLE_UNASSIGNED AF_STYLE_MASK
+
+ /* if this flag is set, we have an ASCII digit */
+#define AF_DIGIT 0x8000U
+ /* if this flag is set, we have a non-base character */
+#define AF_NONBASE 0x4000U
/* `increase-x-height' property */
#define AF_PROP_INCREASE_X_HEIGHT_MIN 6
@@ -55,29 +98,50 @@
/*
- * Note that glyph_scripts[] is used to map each glyph into
- * an index into the `af_script_classes' array.
+ * Note that glyph_styles[] maps each glyph to an index into the
+ * `af_style_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
{
- FT_Face face;
- FT_Long glyph_count; /* same as face->num_glyphs */
- FT_Byte* glyph_scripts;
+ FT_Face face;
+ FT_Long glyph_count; /* same as face->num_glyphs */
+ FT_UShort* glyph_styles;
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+ hb_font_t* hb_font;
+ hb_buffer_t* hb_buf; /* for feature comparison */
+#endif
/* per-face auto-hinter properties */
- FT_UInt increase_x_height;
+ FT_UInt increase_x_height;
- AF_ScriptMetrics metrics[AF_SCRIPT_MAX];
+ AF_StyleMetrics metrics[AF_STYLE_MAX];
- AF_Module module; /* to access global properties */
+ /* Compute darkening amount once per size. Use this to check whether */
+ /* darken_{x,y} needs to be recomputed. */
+ FT_UShort stem_darkening_for_ppem;
+ /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_HORZ] */
+ /* to compute the darkening amount. */
+ FT_Pos standard_vertical_width;
+ /* Copy from e.g. AF_LatinMetrics.axis[AF_DIMENSION_VERT] */
+ /* to compute the darkening amount. */
+ FT_Pos standard_horizontal_width;
+ /* The actual amount to darken a glyph along the X axis. */
+ FT_Pos darken_x;
+ /* The actual amount to darken a glyph along the Y axis. */
+ FT_Pos darken_y;
+ /* Amount to scale down by to keep emboldened points */
+ /* on the Y-axis in pre-computed blue zones. */
+ FT_Fixed scale_down_factor;
+ AF_Module module; /* to access global properties */
} AF_FaceGlobalsRec;
/*
* model the global hints data for a given face, decomposed into
- * script-specific items
+ * style-specific items
*/
FT_LOCAL( FT_Error )
@@ -86,10 +150,10 @@
AF_Module module );
FT_LOCAL( FT_Error )
- af_face_globals_get_metrics( AF_FaceGlobals globals,
- FT_UInt gindex,
- FT_UInt options,
- AF_ScriptMetrics *ametrics );
+ af_face_globals_get_metrics( AF_FaceGlobals globals,
+ FT_UInt gindex,
+ FT_UInt options,
+ AF_StyleMetrics *ametrics );
FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals );
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index e8defaa..56c8220 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (body). */
/* */
-/* Copyright 2003-2007, 2009-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -43,7 +43,15 @@
AF_Segment segment = NULL;
- if ( axis->num_segments >= axis->max_segments )
+ if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
+ {
+ if ( axis->segments == NULL )
+ {
+ axis->segments = axis->embedded.segments;
+ axis->max_segments = AF_SEGMENTS_EMBEDDED;
+ }
+ }
+ else if ( axis->num_segments >= axis->max_segments )
{
FT_Int old_max = axis->max_segments;
FT_Int new_max = old_max;
@@ -60,8 +68,18 @@
if ( new_max < old_max || new_max > big_max )
new_max = big_max;
- if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
- goto Exit;
+ if ( axis->segments == axis->embedded.segments )
+ {
+ if ( FT_NEW_ARRAY( axis->segments, new_max ) )
+ goto Exit;
+ ft_memcpy( axis->segments, axis->embedded.segments,
+ sizeof ( axis->embedded.segments ) );
+ }
+ else
+ {
+ if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
+ goto Exit;
+ }
axis->max_segments = new_max;
}
@@ -74,7 +92,8 @@
}
- /* Get new edge for given axis, direction, and position. */
+ /* Get new edge for given axis, direction, and position, */
+ /* without initializing the edge itself. */
FT_LOCAL( FT_Error )
af_axis_hints_new_edge( AF_AxisHints axis,
@@ -88,7 +107,15 @@
AF_Edge edges;
- if ( axis->num_edges >= axis->max_edges )
+ if ( axis->num_edges < AF_EDGES_EMBEDDED )
+ {
+ if ( axis->edges == NULL )
+ {
+ axis->edges = axis->embedded.edges;
+ axis->max_edges = AF_EDGES_EMBEDDED;
+ }
+ }
+ else if ( axis->num_edges >= axis->max_edges )
{
FT_Int old_max = axis->max_edges;
FT_Int new_max = old_max;
@@ -105,8 +132,18 @@
if ( new_max < old_max || new_max > big_max )
new_max = big_max;
- if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
- goto Exit;
+ if ( axis->edges == axis->embedded.edges )
+ {
+ if ( FT_NEW_ARRAY( axis->edges, new_max ) )
+ goto Exit;
+ ft_memcpy( axis->edges, axis->embedded.edges,
+ sizeof ( axis->embedded.edges ) );
+ }
+ else
+ {
+ if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
+ goto Exit;
+ }
axis->max_edges = new_max;
}
@@ -130,10 +167,6 @@
axis->num_edges++;
- FT_ZERO( edge );
- edge->fpos = (FT_Short)fpos;
- edge->dir = (FT_Char)dir;
-
Exit:
*anedge = edge;
return error;
@@ -144,6 +177,17 @@
#include FT_CONFIG_STANDARD_LIBRARY_H
+ /* The dump functions are used in the `ftgrid' demo program, too. */
+#define AF_DUMP( varformat ) \
+ do \
+ { \
+ if ( to_stdout ) \
+ printf varformat; \
+ else \
+ FT_TRACE7( varformat ); \
+ } while ( 0 )
+
+
static const char*
af_dir_str( AF_Direction dir )
{
@@ -172,41 +216,134 @@
}
-#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
+#define AF_INDEX_NUM( ptr, base ) (int)( (ptr) ? ( (ptr) - (base) ) : -1 )
+
+
+ static char*
+ af_print_idx( char* p,
+ int idx )
+ {
+ if ( idx == -1 )
+ {
+ p[0] = '-';
+ p[1] = '-';
+ p[2] = '\0';
+ }
+ else
+ ft_sprintf( p, "%d", idx );
+
+ return p;
+ }
+
+
+ static int
+ af_get_segment_index( AF_GlyphHints hints,
+ int point_idx,
+ int dimension )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Point point = hints->points + point_idx;
+ AF_Segment segments = axis->segments;
+ AF_Segment limit = segments + axis->num_segments;
+ AF_Segment segment;
+
+
+ for ( segment = segments; segment < limit; segment++ )
+ {
+ if ( segment->first <= segment->last )
+ {
+ if ( point >= segment->first && point <= segment->last )
+ break;
+ }
+ else
+ {
+ AF_Point p = segment->first;
+
+
+ for (;;)
+ {
+ if ( point == p )
+ goto Exit;
+
+ if ( p == segment->last )
+ break;
+
+ p = p->next;
+ }
+ }
+ }
+
+ Exit:
+ if ( segment == limit )
+ return -1;
+
+ return (int)( segment - segments );
+ }
+
+
+ static int
+ af_get_edge_index( AF_GlyphHints hints,
+ int segment_idx,
+ int dimension )
+ {
+ AF_AxisHints axis = &hints->axis[dimension];
+ AF_Edge edges = axis->edges;
+ AF_Segment segment = axis->segments + segment_idx;
+
+
+ return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges );
+ }
#ifdef __cplusplus
extern "C" {
#endif
void
- af_glyph_hints_dump_points( AF_GlyphHints hints )
+ af_glyph_hints_dump_points( AF_GlyphHints hints,
+ FT_Bool to_stdout )
{
AF_Point points = hints->points;
AF_Point limit = points + hints->num_points;
AF_Point point;
- FT_TRACE7(( "Table of points:\n"
- " [ index | xorg | yorg | xscale | yscale"
- " | xfit | yfit | flags ]\n" ));
+ AF_DUMP(( "Table of points:\n" ));
+
+ if ( hints->num_points )
+ AF_DUMP(( " index hedge hseg vedge vseg flags"
+ " xorg yorg xscale yscale xfit yfit\n" ));
+ else
+ AF_DUMP(( " (none)\n" ));
for ( point = points; point < limit; point++ )
- FT_TRACE7(( " [ %5d | %5d | %5d | %6.2f | %6.2f"
- " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
- point - points,
- point->fx,
- point->fy,
- point->ox / 64.0,
- point->oy / 64.0,
- point->x / 64.0,
- point->y / 64.0,
- ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
- ( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',
- ( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',
- ( point->flags & AF_FLAG_EXTREMA_Y ) ? 'v' : ' ',
- ( point->flags & AF_FLAG_ROUND_X ) ? '(' : ' ',
- ( point->flags & AF_FLAG_ROUND_Y ) ? 'u' : ' '));
- FT_TRACE7(( "\n" ));
+ {
+ int point_idx = AF_INDEX_NUM( point, points );
+ int segment_idx_0 = af_get_segment_index( hints, point_idx, 0 );
+ int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 );
+
+ char buf1[16], buf2[16], buf3[16], buf4[16];
+
+
+ AF_DUMP(( " %5d %5s %5s %5s %5s %s "
+ " %5d %5d %7.2f %7.2f %7.2f %7.2f\n",
+ point_idx,
+ af_print_idx( buf1,
+ af_get_edge_index( hints, segment_idx_1, 1 ) ),
+ af_print_idx( buf2, segment_idx_1 ),
+ af_print_idx( buf3,
+ af_get_edge_index( hints, segment_idx_0, 0 ) ),
+ af_print_idx( buf4, segment_idx_0 ),
+ ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? "weak"
+ : " -- ",
+
+ point->fx,
+ point->fy,
+ point->ox / 64.0,
+ point->oy / 64.0,
+ point->x / 64.0,
+ point->y / 64.0 ));
+ }
+ AF_DUMP(( "\n" ));
}
#ifdef __cplusplus
}
@@ -214,7 +351,7 @@
static const char*
- af_edge_flags_to_string( AF_Edge_Flags flags )
+ af_edge_flags_to_string( FT_UInt flags )
{
static char temp[32];
int pos = 0;
@@ -247,7 +384,8 @@
extern "C" {
#endif
void
- af_glyph_hints_dump_segments( AF_GlyphHints hints )
+ af_glyph_hints_dump_segments( AF_GlyphHints hints,
+ FT_Bool to_stdout )
{
FT_Int dimension;
@@ -261,35 +399,39 @@
AF_Segment limit = segments + axis->num_segments;
AF_Segment seg;
+ char buf1[16], buf2[16], buf3[16];
- FT_TRACE7(( "Table of %s segments:\n",
- dimension == AF_DIMENSION_HORZ ? "vertical"
- : "horizontal" ));
+
+ AF_DUMP(( "Table of %s segments:\n",
+ dimension == AF_DIMENSION_HORZ ? "vertical"
+ : "horizontal" ));
if ( axis->num_segments )
- FT_TRACE7(( " [ index | pos | dir | from"
- " | to | link | serif | edge"
- " | height | extra | flags ]\n" ));
+ AF_DUMP(( " index pos dir from to"
+ " link serif edge"
+ " height extra flags\n" ));
else
- FT_TRACE7(( " (none)\n" ));
+ AF_DUMP(( " (none)\n" ));
for ( seg = segments; seg < limit; seg++ )
- FT_TRACE7(( " [ %5d | %5.2g | %5s | %4d"
- " | %4d | %4d | %5d | %4d"
- " | %6d | %5d | %11s ]\n",
- seg - segments,
- dimension == AF_DIMENSION_HORZ
- ? (int)seg->first->ox / 64.0
- : (int)seg->first->oy / 64.0,
- af_dir_str( (AF_Direction)seg->dir ),
- AF_INDEX_NUM( seg->first, points ),
- AF_INDEX_NUM( seg->last, points ),
- AF_INDEX_NUM( seg->link, segments ),
- AF_INDEX_NUM( seg->serif, segments ),
- AF_INDEX_NUM( seg->edge, edges ),
- seg->height,
- seg->height - ( seg->max_coord - seg->min_coord ),
- af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) ));
- FT_TRACE7(( "\n" ));
+ AF_DUMP(( " %5d %5.2g %5s %4d %4d"
+ " %4s %5s %4s"
+ " %6d %5d %11s\n",
+ AF_INDEX_NUM( seg, segments ),
+ dimension == AF_DIMENSION_HORZ
+ ? (int)seg->first->ox / 64.0
+ : (int)seg->first->oy / 64.0,
+ af_dir_str( (AF_Direction)seg->dir ),
+ AF_INDEX_NUM( seg->first, points ),
+ AF_INDEX_NUM( seg->last, points ),
+
+ af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ),
+ af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ),
+ af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ),
+
+ seg->height,
+ seg->height - ( seg->max_coord - seg->min_coord ),
+ af_edge_flags_to_string( seg->flags ) ));
+ AF_DUMP(( "\n" ));
}
}
#ifdef __cplusplus
@@ -332,7 +474,9 @@
af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
FT_Int dimension,
FT_Int idx,
- FT_Pos* offset )
+ FT_Pos *offset,
+ FT_Bool *is_blue,
+ FT_Pos *blue_offset )
{
AF_Dimension dim;
AF_AxisHints axis;
@@ -349,9 +493,18 @@
if ( idx < 0 || idx >= axis->num_segments )
return FT_THROW( Invalid_Argument );
- seg = &axis->segments[idx];
- *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
- : seg->first->oy;
+ seg = &axis->segments[idx];
+ *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
+ : seg->first->oy;
+ if ( seg->edge )
+ *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 );
+ else
+ *is_blue = FALSE;
+
+ if ( *is_blue )
+ *blue_offset = seg->edge->blue_edge->cur;
+ else
+ *blue_offset = 0;
return FT_Err_Ok;
}
@@ -366,7 +519,8 @@
extern "C" {
#endif
void
- af_glyph_hints_dump_edges( AF_GlyphHints hints )
+ af_glyph_hints_dump_edges( AF_GlyphHints hints,
+ FT_Bool to_stdout )
{
FT_Int dimension;
@@ -378,99 +532,43 @@
AF_Edge limit = edges + axis->num_edges;
AF_Edge edge;
+ char buf1[16], buf2[16];
+
/*
* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
* since they have a constant X coordinate.
*/
- FT_TRACE7(( "Table of %s edges:\n",
- dimension == AF_DIMENSION_HORZ ? "vertical"
- : "horizontal" ));
+ AF_DUMP(( "Table of %s edges:\n",
+ dimension == AF_DIMENSION_HORZ ? "vertical"
+ : "horizontal" ));
if ( axis->num_edges )
- FT_TRACE7(( " [ index | pos | dir | link"
- " | serif | blue | opos | pos | flags ]\n" ));
+ AF_DUMP(( " index pos dir link serif"
+ " blue opos pos flags\n" ));
else
- FT_TRACE7(( " (none)\n" ));
+ AF_DUMP(( " (none)\n" ));
for ( edge = edges; edge < limit; edge++ )
- FT_TRACE7(( " [ %5d | %5.2g | %5s | %4d"
- " | %5d | %c | %5.2f | %5.2f | %11s ]\n",
- edge - edges,
- (int)edge->opos / 64.0,
- af_dir_str( (AF_Direction)edge->dir ),
- AF_INDEX_NUM( edge->link, edges ),
- AF_INDEX_NUM( edge->serif, edges ),
- edge->blue_edge ? 'y' : 'n',
- edge->opos / 64.0,
- edge->pos / 64.0,
- af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) ));
- FT_TRACE7(( "\n" ));
+ AF_DUMP(( " %5d %5.2g %5s %4s %5s"
+ " %c %5.2f %5.2f %11s\n",
+ AF_INDEX_NUM( edge, edges ),
+ (int)edge->opos / 64.0,
+ af_dir_str( (AF_Direction)edge->dir ),
+ af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ),
+ af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ),
+
+ edge->blue_edge ? 'y' : 'n',
+ edge->opos / 64.0,
+ edge->pos / 64.0,
+ af_edge_flags_to_string( edge->flags ) ));
+ AF_DUMP(( "\n" ));
}
}
#ifdef __cplusplus
}
#endif
-#else /* !FT_DEBUG_AUTOFIT */
-
- /* these empty stubs are only used to link the `ftgrid' test program */
- /* if debugging is disabled */
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- void
- af_glyph_hints_dump_points( AF_GlyphHints hints )
- {
- FT_UNUSED( hints );
- }
-
-
- void
- af_glyph_hints_dump_segments( AF_GlyphHints hints )
- {
- FT_UNUSED( hints );
- }
-
-
- FT_Error
- af_glyph_hints_get_num_segments( AF_GlyphHints hints,
- FT_Int dimension,
- FT_Int* num_segments )
- {
- FT_UNUSED( hints );
- FT_UNUSED( dimension );
- FT_UNUSED( num_segments );
-
- return 0;
- }
-
-
- FT_Error
- af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
- FT_Int dimension,
- FT_Int idx,
- FT_Pos* offset )
- {
- FT_UNUSED( hints );
- FT_UNUSED( dimension );
- FT_UNUSED( idx );
- FT_UNUSED( offset );
-
- return 0;
- }
-
-
- void
- af_glyph_hints_dump_edges( AF_GlyphHints hints )
- {
- FT_UNUSED( hints );
- }
-
-#ifdef __cplusplus
- }
-#endif
+#undef AF_DUMP
#endif /* !FT_DEBUG_AUTOFIT */
@@ -511,15 +609,15 @@
else
{
dir = AF_DIR_DOWN;
- ll = dy;
+ ll = -dy;
ss = dx;
}
}
- /* return no direction if arm lengths differ too much */
+ /* return no direction if arm lengths do not differ enough */
/* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
- ss *= 14;
- if ( FT_ABS( ll ) <= FT_ABS( ss ) )
+ /* the long arm is never negative */
+ if ( ll <= 14 * FT_ABS( ss ) )
dir = AF_DIR_NONE;
return dir;
@@ -530,7 +628,8 @@
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory )
{
- FT_ZERO( hints );
+ /* no need to initialize the embedded items */
+ FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) );
hints->memory = memory;
}
@@ -538,13 +637,15 @@
FT_LOCAL_DEF( void )
af_glyph_hints_done( AF_GlyphHints hints )
{
- FT_Memory memory = hints->memory;
+ FT_Memory memory;
int dim;
if ( !( hints && hints->memory ) )
return;
+ memory = hints->memory;
+
/*
* note that we don't need to free the segment and edge
* buffers since they are really within the hints->points array
@@ -556,20 +657,24 @@
axis->num_segments = 0;
axis->max_segments = 0;
- FT_FREE( axis->segments );
+ if ( axis->segments != axis->embedded.segments )
+ FT_FREE( axis->segments );
axis->num_edges = 0;
axis->max_edges = 0;
- FT_FREE( axis->edges );
+ if ( axis->edges != axis->embedded.edges )
+ FT_FREE( axis->edges );
}
- FT_FREE( hints->contours );
+ if ( hints->contours != hints->embedded.contours )
+ FT_FREE( hints->contours );
hints->max_contours = 0;
hints->num_contours = 0;
- FT_FREE( hints->points );
- hints->num_points = 0;
+ if ( hints->points != hints->embedded.points )
+ FT_FREE( hints->points );
hints->max_points = 0;
+ hints->num_points = 0;
hints->memory = NULL;
}
@@ -578,8 +683,8 @@
/* Reset metrics. */
FT_LOCAL_DEF( void )
- af_glyph_hints_rescale( AF_GlyphHints hints,
- AF_ScriptMetrics metrics )
+ af_glyph_hints_rescale( AF_GlyphHints hints,
+ AF_StyleMetrics metrics )
{
hints->metrics = metrics;
hints->scaler_flags = metrics->scaler.flags;
@@ -613,15 +718,27 @@
/* first of all, reallocate the contours array if necessary */
new_max = (FT_UInt)outline->n_contours;
- old_max = hints->max_contours;
- if ( new_max > old_max )
+ old_max = (FT_UInt)hints->max_contours;
+
+ if ( new_max <= AF_CONTOURS_EMBEDDED )
{
- new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
+ if ( hints->contours == NULL )
+ {
+ hints->contours = hints->embedded.contours;
+ hints->max_contours = AF_CONTOURS_EMBEDDED;
+ }
+ }
+ else if ( new_max > old_max )
+ {
+ if ( hints->contours == hints->embedded.contours )
+ hints->contours = NULL;
+
+ new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
- hints->max_contours = new_max;
+ hints->max_contours = (FT_Int)new_max;
}
/*
@@ -630,15 +747,27 @@
* hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
- old_max = hints->max_points;
- if ( new_max > old_max )
+ old_max = (FT_UInt)hints->max_points;
+
+ if ( new_max <= AF_POINTS_EMBEDDED )
{
- new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
+ if ( hints->points == NULL )
+ {
+ hints->points = hints->embedded.points;
+ hints->max_points = AF_POINTS_EMBEDDED;
+ }
+ }
+ else if ( new_max > old_max )
+ {
+ if ( hints->points == hints->embedded.points )
+ hints->points = NULL;
+
+ new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */
if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
goto Exit;
- hints->max_points = new_max;
+ hints->max_points = (FT_Int)new_max;
}
hints->num_points = outline->n_points;
@@ -685,6 +814,9 @@
for ( point = points; point < point_limit; point++, vec++, tag++ )
{
+ point->in_dir = (FT_Char)AF_DIR_NONE;
+ point->out_dir = (FT_Char)AF_DIR_NONE;
+
point->fx = (FT_Short)vec->x;
point->fy = (FT_Short)vec->y;
point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
@@ -732,60 +864,223 @@
}
}
- /* compute directions of in & out vectors */
{
- AF_Point first = points;
- AF_Point prev = NULL;
- FT_Pos in_x = 0;
- FT_Pos in_y = 0;
- AF_Direction in_dir = AF_DIR_NONE;
+ /*
+ * Compute directions of `in' and `out' vectors.
+ *
+ * Note that distances between points that are very near to each
+ * other are accumulated. In other words, the auto-hinter
+ * prepends the small vectors between near points to the first
+ * non-near vector. All intermediate points are tagged as
+ * weak; the directions are adjusted also to be equal to the
+ * accumulated one.
+ */
+ /* value 20 in `near_limit' is heuristic */
+ FT_UInt units_per_em = hints->metrics->scaler.face->units_per_EM;
+ FT_Int near_limit = 20 * units_per_em / 2048;
+ FT_Int near_limit2 = 2 * near_limit - 1;
+
+ AF_Point* contour;
+ AF_Point* contour_limit = hints->contours + hints->num_contours;
+
+
+ for ( contour = hints->contours; contour < contour_limit; contour++ )
+ {
+ AF_Point first = *contour;
+ AF_Point next, prev, curr;
+
+ FT_Pos out_x, out_y;
+
+
+ /* since the first point of a contour could be part of a */
+ /* series of near points, go backwards to find the first */
+ /* non-near point and adjust `first' */
+
+ point = first;
+ prev = first->prev;
+
+ while ( prev != first )
+ {
+ out_x = point->fx - prev->fx;
+ out_y = point->fy - prev->fy;
+
+ /*
+ * We use Taxicab metrics to measure the vector length.
+ *
+ * Note that the accumulated distances so far could have the
+ * opposite direction of the distance measured here. For this
+ * reason we use `near_limit2' for the comparison to get a
+ * non-near point even in the worst case.
+ */
+ if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 )
+ break;
+
+ point = prev;
+ prev = prev->prev;
+ }
+
+ /* adjust first point */
+ first = point;
+
+ /* now loop over all points of the contour to get */
+ /* `in' and `out' vector directions */
+
+ curr = first;
+
+ /*
+ * We abuse the `u' and `v' fields to store index deltas to the
+ * next and previous non-near point, respectively.
+ *
+ * To avoid problems with not having non-near points, we point to
+ * `first' by default as the next non-near point.
+ *
+ */
+ curr->u = (FT_Pos)( first - curr );
+ first->v = -curr->u;
+
+ out_x = 0;
+ out_y = 0;
+
+ next = first;
+ do
+ {
+ AF_Direction out_dir;
+
+
+ point = next;
+ next = point->next;
+
+ out_x += next->fx - point->fx;
+ out_y += next->fy - point->fy;
+
+ if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit )
+ {
+ next->flags |= AF_FLAG_WEAK_INTERPOLATION;
+ continue;
+ }
+
+ curr->u = (FT_Pos)( next - curr );
+ next->v = -curr->u;
+
+ out_dir = af_direction_compute( out_x, out_y );
+
+ /* adjust directions for all points inbetween; */
+ /* the loop also updates position of `curr' */
+ curr->out_dir = (FT_Char)out_dir;
+ for ( curr = curr->next; curr != next; curr = curr->next )
+ {
+ curr->in_dir = (FT_Char)out_dir;
+ curr->out_dir = (FT_Char)out_dir;
+ }
+ next->in_dir = (FT_Char)out_dir;
+
+ curr->u = (FT_Pos)( first - curr );
+ first->v = -curr->u;
+
+ out_x = 0;
+ out_y = 0;
+
+ } while ( next != first );
+ }
+
+ /*
+ * The next step is to `simplify' an outline's topology so that we
+ * can identify local extrema more reliably: A series of
+ * non-horizontal or non-vertical vectors pointing into the same
+ * quadrant are handled as a single, long vector. From a
+ * topological point of the view, the intermediate points are of no
+ * interest and thus tagged as weak.
+ */
for ( point = points; point < point_limit; point++ )
{
- AF_Point next;
- FT_Pos out_x, out_y;
+ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
+ continue;
-
- if ( point == first )
+ if ( point->in_dir == AF_DIR_NONE &&
+ point->out_dir == AF_DIR_NONE )
{
- prev = first->prev;
- in_x = first->fx - prev->fx;
- in_y = first->fy - prev->fy;
- in_dir = af_direction_compute( in_x, in_y );
- first = prev + 1;
+ /* check whether both vectors point into the same quadrant */
+
+ FT_Pos in_x, in_y;
+ FT_Pos out_x, out_y;
+
+ AF_Point next_u = point + point->u;
+ AF_Point prev_v = point + point->v;
+
+
+ in_x = point->fx - prev_v->fx;
+ in_y = point->fy - prev_v->fy;
+
+ out_x = next_u->fx - point->fx;
+ out_y = next_u->fy - point->fy;
+
+ if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 )
+ {
+ /* yes, so tag current point as weak */
+ /* and update index deltas */
+
+ point->flags |= AF_FLAG_WEAK_INTERPOLATION;
+
+ prev_v->u = (FT_Pos)( next_u - prev_v );
+ next_u->v = -prev_v->u;
+ }
}
+ }
- point->in_dir = (FT_Char)in_dir;
+ /*
+ * Finally, check for remaining weak points. Everything else not
+ * collected in edges so far is then implicitly classified as strong
+ * points.
+ */
- next = point->next;
- out_x = next->fx - point->fx;
- out_y = next->fy - point->fy;
-
- in_dir = af_direction_compute( out_x, out_y );
- point->out_dir = (FT_Char)in_dir;
-
- /* check for weak points */
+ for ( point = points; point < point_limit; point++ )
+ {
+ if ( point->flags & AF_FLAG_WEAK_INTERPOLATION )
+ continue;
if ( point->flags & AF_FLAG_CONTROL )
{
+ /* control points are always weak */
Is_Weak_Point:
point->flags |= AF_FLAG_WEAK_INTERPOLATION;
}
else if ( point->out_dir == point->in_dir )
{
if ( point->out_dir != AF_DIR_NONE )
+ {
+ /* current point lies on a horizontal or */
+ /* vertical segment (but doesn't start or end it) */
goto Is_Weak_Point;
+ }
- if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
- goto Is_Weak_Point;
+ {
+ AF_Point next_u = point + point->u;
+ AF_Point prev_v = point + point->v;
+
+
+ if ( ft_corner_is_flat( point->fx - prev_v->fx,
+ point->fy - prev_v->fy,
+ next_u->fx - point->fx,
+ next_u->fy - point->fy ) )
+ {
+ /* either the `in' or the `out' vector is much more */
+ /* dominant than the other one, so tag current point */
+ /* as weak and update index deltas */
+
+ prev_v->u = (FT_Pos)( next_u - prev_v );
+ next_u->v = -prev_v->u;
+
+ goto Is_Weak_Point;
+ }
+ }
}
else if ( point->in_dir == -point->out_dir )
+ {
+ /* current point forms a spike */
goto Is_Weak_Point;
-
- in_x = out_x;
- in_y = out_y;
- prev = point;
+ }
}
}
}
@@ -916,7 +1211,7 @@
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
- AF_Flags touch_flag;
+ FT_UInt touch_flag;
if ( dim == AF_DIMENSION_HORZ )
@@ -942,8 +1237,7 @@
/* if this point is candidate to weak interpolation, we */
/* interpolate it after all strong points have been processed */
- if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
- !( point->flags & AF_FLAG_INFLECTION ) )
+ if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) )
continue;
if ( dim == AF_DIMENSION_VERT )
@@ -1098,33 +1392,27 @@
AF_Point ref2 )
{
AF_Point p;
- FT_Pos u;
- FT_Pos v1 = ref1->v;
- FT_Pos v2 = ref2->v;
- FT_Pos d1 = ref1->u - v1;
- FT_Pos d2 = ref2->u - v2;
+ FT_Pos u, v1, v2, u1, u2, d1, d2;
if ( p1 > p2 )
return;
- if ( v1 == v2 )
+ if ( ref1->v > ref2->v )
{
- for ( p = p1; p <= p2; p++ )
- {
- u = p->v;
-
- if ( u <= v1 )
- u += d1;
- else
- u += d2;
-
- p->u = u;
- }
- return;
+ p = ref1;
+ ref1 = ref2;
+ ref2 = p;
}
- if ( v1 < v2 )
+ v1 = ref1->v;
+ v2 = ref2->v;
+ u1 = ref1->u;
+ u2 = ref2->u;
+ d1 = u1 - v1;
+ d2 = u2 - v2;
+
+ if ( u1 == u2 || v1 == v2 )
{
for ( p = p1; p <= p2; p++ )
{
@@ -1135,23 +1423,26 @@
else if ( u >= v2 )
u += d2;
else
- u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+ u = u1;
p->u = u;
}
}
else
{
+ FT_Fixed scale = FT_DivFix( u2 - u1, v2 - v1 );
+
+
for ( p = p1; p <= p2; p++ )
{
u = p->v;
- if ( u <= v2 )
- u += d2;
- else if ( u >= v1 )
+ if ( u <= v1 )
u += d1;
+ else if ( u >= v2 )
+ u += d2;
else
- u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+ u = u1 + FT_MulFix( u - v1, scale );
p->u = u;
}
@@ -1170,7 +1461,7 @@
AF_Point point_limit = points + hints->num_points;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
- AF_Flags touch_flag;
+ FT_UInt touch_flag;
AF_Point point;
AF_Point end_point;
AF_Point first_point;
@@ -1199,8 +1490,6 @@
}
}
- point = points;
-
for ( ; contour < contour_limit; contour++ )
{
AF_Point first_touched, last_touched;
@@ -1223,7 +1512,6 @@
}
first_touched = point;
- last_touched = point;
for (;;)
{
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 776b3c8..a64c7a4 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (specification). */
/* */
-/* Copyright 2003-2008, 2010-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,7 +27,7 @@
/*
* The definition of outline glyph hints. These are shared by all
- * script analysis routines (until now).
+ * writing system analysis routines (until now).
*/
typedef enum AF_Dimension_
@@ -62,33 +62,34 @@
*
* by David Turner and Werner Lemberg
*
- * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ *
+ * with appropriate updates.
*
*
* Segments
*
* `af_{cjk,latin,...}_hints_compute_segments' are the functions to
- * find segments in an outline. A segment is a series of consecutive
- * points that are approximately aligned along a coordinate axis. The
- * analysis to do so is specific to a script.
+ * find segments in an outline.
*
- * A segment must have at least two points, except in the case of
- * `fake' segments that are generated to hint metrics appropriately,
- * and which consist of a single point.
+ * A segment is a series of at least two consecutive points that are
+ * approximately aligned along a coordinate axis. The analysis to do
+ * so is specific to a writing system.
*
*
* Edges
*
+ * `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
+ * edges.
+ *
* As soon as segments are defined, the auto-hinter groups them into
* edges. An edge corresponds to a single position on the main
* dimension that collects one or more segments (allowing for a small
* threshold).
*
- * The auto-hinter first tries to grid fit edges, then to align
- * segments on the edges unless it detects that they form a serif.
- *
- * `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
- * edges; they are specific to a script.
+ * As an example, the `latin' writing system first tries to grid-fit
+ * edges, then to align segments on the edges unless it detects that
+ * they form a serif.
*
*
* A H
@@ -107,6 +108,8 @@
*
* Stems
*
+ * Stems are detected by `af_{cjk,latin,...}_hint_edges'.
+ *
* Segments need to be `linked' to other ones in order to detect stems.
* A stem is made of two segments that face each other in opposite
* directions and that are sufficiently close to each other. Using
@@ -127,17 +130,21 @@
* The best candidate is stored in field `link' in structure
* `AF_Segment'.
*
- * Stems are detected by `af_{cjk,latin,...}_hint_edges'.
- *
* In the above ASCII drawing, the best candidate for both AB and CD is
* GH, while the best candidate for GH is AB. Similarly, the best
* candidate for EF and GH is AB, while the best candidate for AB is
* GH.
*
+ * The detection and handling of stems is dependent on the writing
+ * system.
+ *
*
* Serifs
*
- * On the opposite, a serif has
+ * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+ *
+ * In comparison to a stem, a serif (as handled by the auto-hinter
+ * module that takes care of the `latin' writing system) has
*
* best segment_1 = segment_2 && best segment_2 != segment_1
*
@@ -147,8 +154,6 @@
* The best candidate is stored in field `serif' in structure
* `AF_Segment' (and `link' is set to NULL).
*
- * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
- *
*
* Touched points
*
@@ -169,18 +174,19 @@
*
* Strong Points
*
- * Experience has shown that points which are not part of an edge need
- * to be interpolated linearly between their two closest edges, even if
- * these are not part of the contour of those particular points.
- * Typical candidates for this are
+ * Experience has shown that points not part of an edge need to be
+ * interpolated linearly between their two closest edges, even if these
+ * are not part of the contour of those particular points. Typical
+ * candidates for this are
*
* - angle points (i.e., points where the `in' and `out' direction
* differ greatly)
*
* - inflection points (i.e., where the `in' and `out' angles are the
- * same, but the curvature changes sign)
+ * same, but the curvature changes sign) [currently, such points
+ * aren't handled specially in the auto-hinter]
*
- * `af_glyph_hints_align_strong_points' is the function which takes
+ * `af_glyph_hints_align_strong_points' is the function that takes
* care of such situations; it is equivalent to the TrueType `IP'
* hinting instruction.
*
@@ -201,45 +207,27 @@
/* point hint flags */
- typedef enum AF_Flags_
- {
- AF_FLAG_NONE = 0,
+#define AF_FLAG_NONE 0
- /* point type flags */
- AF_FLAG_CONIC = 1 << 0,
- AF_FLAG_CUBIC = 1 << 1,
- AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
+ /* point type flags */
+#define AF_FLAG_CONIC ( 1U << 0 )
+#define AF_FLAG_CUBIC ( 1U << 1 )
+#define AF_FLAG_CONTROL ( AF_FLAG_CONIC | AF_FLAG_CUBIC )
- /* point extremum flags */
- AF_FLAG_EXTREMA_X = 1 << 2,
- AF_FLAG_EXTREMA_Y = 1 << 3,
+ /* point touch flags */
+#define AF_FLAG_TOUCH_X ( 1U << 2 )
+#define AF_FLAG_TOUCH_Y ( 1U << 3 )
- /* point roundness flags */
- AF_FLAG_ROUND_X = 1 << 4,
- AF_FLAG_ROUND_Y = 1 << 5,
-
- /* point touch flags */
- AF_FLAG_TOUCH_X = 1 << 6,
- AF_FLAG_TOUCH_Y = 1 << 7,
-
- /* candidates for weak interpolation have this flag set */
- AF_FLAG_WEAK_INTERPOLATION = 1 << 8,
-
- /* all inflection points in the outline have this flag set */
- AF_FLAG_INFLECTION = 1 << 9
-
- } AF_Flags;
+ /* candidates for weak interpolation have this flag set */
+#define AF_FLAG_WEAK_INTERPOLATION ( 1U << 4 )
/* edge hint flags */
- typedef enum AF_Edge_Flags_
- {
- AF_EDGE_NORMAL = 0,
- AF_EDGE_ROUND = 1 << 0,
- AF_EDGE_SERIF = 1 << 1,
- AF_EDGE_DONE = 1 << 2
-
- } AF_Edge_Flags;
+#define AF_EDGE_NORMAL 0
+#define AF_EDGE_ROUND ( 1U << 0 )
+#define AF_EDGE_SERIF ( 1U << 1 )
+#define AF_EDGE_DONE ( 1U << 2 )
+#define AF_EDGE_NEUTRAL ( 1U << 3 ) /* edge aligns to a neutral blue zone */
typedef struct AF_PointRec_* AF_Point;
@@ -309,6 +297,8 @@
} AF_EdgeRec;
+#define AF_SEGMENTS_EMBEDDED 18 /* number of embedded segments */
+#define AF_EDGES_EMBEDDED 12 /* number of embedded edges */
typedef struct AF_AxisHintsRec_
{
@@ -325,36 +315,55 @@
AF_Direction major_dir; /* either vertical or horizontal */
+ /* two arrays to avoid allocation penalty */
+ struct
+ {
+ AF_SegmentRec segments[AF_SEGMENTS_EMBEDDED];
+ AF_EdgeRec edges[AF_EDGES_EMBEDDED];
+ } embedded;
+
+
} AF_AxisHintsRec, *AF_AxisHints;
+#define AF_POINTS_EMBEDDED 96 /* number of embedded points */
+#define AF_CONTOURS_EMBEDDED 8 /* number of embedded contours */
+
typedef struct AF_GlyphHintsRec_
{
- FT_Memory memory;
+ FT_Memory memory;
- FT_Fixed x_scale;
- FT_Pos x_delta;
+ FT_Fixed x_scale;
+ FT_Pos x_delta;
- FT_Fixed y_scale;
- FT_Pos y_delta;
+ FT_Fixed y_scale;
+ FT_Pos y_delta;
- FT_Int max_points; /* number of allocated points */
- FT_Int num_points; /* number of used points */
- AF_Point points; /* points array */
+ FT_Int max_points; /* number of allocated points */
+ FT_Int num_points; /* number of used points */
+ AF_Point points; /* points array */
- FT_Int max_contours; /* number of allocated contours */
- FT_Int num_contours; /* number of used contours */
- AF_Point* contours; /* contours array */
+ FT_Int max_contours; /* number of allocated contours */
+ FT_Int num_contours; /* number of used contours */
+ AF_Point* contours; /* contours array */
- AF_AxisHintsRec axis[AF_DIMENSION_MAX];
+ AF_AxisHintsRec axis[AF_DIMENSION_MAX];
- FT_UInt32 scaler_flags; /* copy of scaler flags */
- FT_UInt32 other_flags; /* free for script-specific */
- /* implementations */
- AF_ScriptMetrics metrics;
+ FT_UInt32 scaler_flags; /* copy of scaler flags */
+ FT_UInt32 other_flags; /* free for style-specific */
+ /* implementations */
+ AF_StyleMetrics metrics;
- FT_Pos xmin_delta; /* used for warping */
- FT_Pos xmax_delta;
+ FT_Pos xmin_delta; /* used for warping */
+ FT_Pos xmax_delta;
+
+ /* Two arrays to avoid allocation penalty. */
+ /* The `embedded' structure must be the last element! */
+ struct
+ {
+ AF_Point contours[AF_CONTOURS_EMBEDDED];
+ AF_PointRec points[AF_POINTS_EMBEDDED];
+ } embedded;
} AF_GlyphHintsRec;
@@ -373,9 +382,6 @@
( !_af_debug_disable_vert_hints && \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
-#define AF_HINTS_DO_ADVANCE( h ) \
- !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
-
#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )
#else /* !FT_DEBUG_AUTOFIT */
@@ -386,14 +392,19 @@
#define AF_HINTS_DO_VERTICAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
-#define AF_HINTS_DO_ADVANCE( h ) \
- !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
-
#define AF_HINTS_DO_BLUES( h ) 1
#endif /* !FT_DEBUG_AUTOFIT */
+#define AF_HINTS_DO_ADVANCE( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
+
+#define AF_HINTS_DO_WARP( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
+
+
+
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
@@ -416,8 +427,8 @@
FT_Memory memory );
FT_LOCAL( void )
- af_glyph_hints_rescale( AF_GlyphHints hints,
- AF_ScriptMetrics metrics );
+ af_glyph_hints_rescale( AF_GlyphHints hints,
+ AF_StyleMetrics metrics );
FT_LOCAL( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 8c24972..59b14d7 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -2,9 +2,9 @@
/* */
/* afindic.c */
/* */
-/* Auto-fitter hinting routines for Indic scripts (body). */
+/* Auto-fitter hinting routines for Indic writing system (body). */
/* */
-/* Copyright 2007, 2011-2013 by */
+/* Copyright 2007-2015 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -79,12 +79,29 @@
static FT_Error
- af_indic_hints_apply( AF_GlyphHints hints,
+ af_indic_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
/* use CJK routines */
- return af_cjk_hints_apply( hints, outline, metrics );
+ return af_cjk_hints_apply( glyph_index, hints, outline, metrics );
+ }
+
+
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ static void
+ af_indic_get_standard_widths( AF_CJKMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
}
@@ -97,60 +114,43 @@
/*************************************************************************/
- static const AF_Script_UniRangeRec af_indic_uniranges[] =
- {
-#if 0
- AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */
-#endif
- AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL), /* Indic Range */
- AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL), /* Tibetan */
- AF_UNIRANGE_REC( 0x1900UL, 0x194FUL), /* Limbu */
- AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL), /* Sundanese */
- AF_UNIRANGE_REC( 0x1C80UL, 0x1CDFUL), /* Meetei Mayak */
- AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL), /* Syloti Nagri */
- AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL), /* Sharada */
- AF_UNIRANGE_REC( 0UL, 0UL)
- };
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_indic_writing_system_class,
-
- AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
- AF_SCRIPT_INDIC,
- af_indic_uniranges,
- 'o', /* XXX */
+ AF_WRITING_SYSTEM_INDIC,
sizeof ( AF_CJKMetricsRec ),
- (AF_Script_InitMetricsFunc) af_indic_metrics_init,
- (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) af_indic_metrics_init,
+ (AF_WritingSystem_ScaleMetricsFunc)af_indic_metrics_scale,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_indic_get_standard_widths,
- (AF_Script_InitHintsFunc) af_indic_hints_init,
- (AF_Script_ApplyHintsFunc) af_indic_hints_apply
+ (AF_WritingSystem_InitHintsFunc) af_indic_hints_init,
+ (AF_WritingSystem_ApplyHintsFunc) af_indic_hints_apply
)
+
#else /* !AF_CONFIG_OPTION_INDIC */
- static const AF_Script_UniRangeRec af_indic_uniranges[] =
- {
- { 0, 0 }
- };
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_indic_writing_system_class,
- AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
- AF_SCRIPT_INDIC,
- af_indic_uniranges,
- 0,
+ AF_WRITING_SYSTEM_INDIC,
sizeof ( AF_CJKMetricsRec ),
- (AF_Script_InitMetricsFunc) NULL,
- (AF_Script_ScaleMetricsFunc)NULL,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) NULL,
+ (AF_WritingSystem_ScaleMetricsFunc)NULL,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)NULL,
- (AF_Script_InitHintsFunc) NULL,
- (AF_Script_ApplyHintsFunc) NULL
+ (AF_WritingSystem_InitHintsFunc) NULL,
+ (AF_WritingSystem_ApplyHintsFunc) NULL
)
+
#endif /* !AF_CONFIG_OPTION_INDIC */
diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h
index c252cf2..4c36908 100644
--- a/src/autofit/afindic.h
+++ b/src/autofit/afindic.h
@@ -2,9 +2,10 @@
/* */
/* afindic.h */
/* */
-/* Auto-fitter hinting routines for Indic scripts (specification). */
+/* Auto-fitter hinting routines for Indic writing system */
+/* (specification). */
/* */
-/* Copyright 2007, 2012 by */
+/* Copyright 2007-2015 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,9 +26,9 @@
FT_BEGIN_HEADER
- /* the Indic-specific script class */
+ /* the `indic' writing system */
- AF_DECLARE_SCRIPT_CLASS( af_indic_script_class )
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_indic_writing_system_class )
/* */
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index ef0157a..9c9f370 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -2,9 +2,9 @@
/* */
/* aflatin.c */
/* */
-/* Auto-fitter hinting routines for latin script (body). */
+/* Auto-fitter hinting routines for latin writing system (body). */
/* */
-/* Copyright 2003-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,7 @@
#include FT_INTERNAL_DEBUG_H
#include "afglobal.h"
+#include "afpic.h"
#include "aflatin.h"
#include "aferrors.h"
@@ -40,6 +41,10 @@
#define FT_COMPONENT trace_aflatin
+ /* needed for computation of round vs. flat segments */
+#define FLAT_THRESHOLD( x ) ( x / 14 )
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -60,8 +65,11 @@
AF_GlyphHintsRec hints[1];
- FT_TRACE5(( "standard widths computation\n"
- "===========================\n\n" ));
+ FT_TRACE5(( "\n"
+ "latin standard widths computation (style `%s')\n"
+ "=====================================================\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
af_glyph_hints_init( hints, face->memory );
@@ -70,19 +78,76 @@
{
FT_Error error;
- FT_UInt glyph_index;
+ FT_ULong glyph_index;
int dim;
AF_LatinMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
+#ifdef FT_CONFIG_OPTION_PIC
+ AF_FaceGlobals globals = metrics->root.globals;
+#endif
- glyph_index = FT_Get_Char_Index( face,
- metrics->root.clazz->standard_char );
- if ( glyph_index == 0 )
+ AF_StyleClass style_class = metrics->root.style_class;
+ AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
+ [style_class->script];
+
+ void* shaper_buf;
+ const char* p;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_ULong ch;
+#endif
+
+ p = script_class->standard_charstring;
+ shaper_buf = af_shaper_buf_create( face );
+
+ /*
+ * We check a list of standard characters to catch features like
+ * `c2sc' (small caps from caps) that don't contain lowercase letters
+ * by definition, or other features that mainly operate on numerals.
+ * The first match wins.
+ */
+
+ glyph_index = 0;
+ while ( *p )
+ {
+ unsigned int num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+#endif
+
+
+ while ( *p == ' ' )
+ p++;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
+
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
+ continue;
+
+ /* otherwise exit loop if we have a result */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ NULL,
+ NULL );
+ if ( glyph_index )
+ break;
+ }
+
+ af_shaper_buf_destroy( face, shaper_buf );
+
+ if ( !glyph_index )
goto Exit;
- FT_TRACE5(( "standard character: 0x%X (glyph index %d)\n",
- metrics->root.clazz->standard_char, glyph_index ));
+ FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
+ ch, glyph_index ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || face->glyph->outline.n_points <= 0 )
@@ -101,7 +166,7 @@
scaler->render_mode = FT_RENDER_MODE_NORMAL;
scaler->flags = 0;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
error = af_glyph_hints_reload( hints, &face->glyph->outline );
if ( error )
@@ -120,7 +185,15 @@
if ( error )
goto Exit;
+ /*
+ * We assume that the glyphs selected for the stem width
+ * computation are `featureless' enough so that the linking
+ * algorithm works fine without adjustments of its scoring
+ * function.
+ */
af_latin_hints_link_segments( hints,
+ 0,
+ NULL,
(AF_Dimension)dim );
seg = axhints->segments;
@@ -146,22 +219,21 @@
}
/* this also replaces multiple almost identical stem widths */
- /* with a single one (the value 100 is heuristic) */
+ /* with a single one (the value 100 is heuristic) */
af_sort_and_quantize_widths( &num_widths, axis->widths,
dummy->units_per_em / 100 );
axis->width_count = num_widths;
}
- Exit:
+ Exit:
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos stdw;
- stdw = ( axis->width_count > 0 )
- ? axis->widths[0].org
- : AF_LATIN_CONSTANT( metrics, 50 );
+ stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
/* let's try 20% of the smallest width */
axis->edge_distance_threshold = stdw / 5;
@@ -193,22 +265,6 @@
}
-
-#define AF_LATIN_MAX_TEST_CHARACTERS 12
-
-
- static const char af_latin_blue_chars[AF_LATIN_MAX_BLUES]
- [AF_LATIN_MAX_TEST_CHARACTERS + 1] =
- {
- "THEZOCQS",
- "HEZLOCUS",
- "fijkdbh",
- "xzroesc",
- "xzroesc",
- "pqgjy"
- };
-
-
/* Find all blue zones. Flat segments give the reference points, */
/* round segments the overshoot positions. */
@@ -216,203 +272,575 @@
af_latin_metrics_init_blues( AF_LatinMetrics metrics,
FT_Face face )
{
- FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
- FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
- FT_Int num_flats;
- FT_Int num_rounds;
- FT_Int bb;
+ FT_Pos flats [AF_BLUE_STRING_MAX_LEN];
+ FT_Pos rounds[AF_BLUE_STRING_MAX_LEN];
+
+ FT_UInt num_flats;
+ FT_UInt num_rounds;
+
AF_LatinBlue blue;
FT_Error error;
- AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
FT_Outline outline;
+ AF_StyleClass sc = metrics->root.style_class;
- /* we compute the blues simply by loading each character from the */
- /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
- /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+ AF_Blue_Stringset bss = sc->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
- FT_TRACE5(( "blue zones computation\n"
- "======================\n\n" ));
+ FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
- for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ void* shaper_buf;
+
+
+ /* we walk over the blue character strings as specified in the */
+ /* style's entry in the `af_blue_stringset' array */
+
+ FT_TRACE5(( "latin blue zones computation\n"
+ "============================\n"
+ "\n" ));
+
+ shaper_buf = af_shaper_buf_create( face );
+
+ for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
- const char* p = af_latin_blue_chars[bb];
- const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
+ const char* p = &af_blue_strings[bs->string];
FT_Pos* blue_ref;
FT_Pos* blue_shoot;
+ FT_Pos ascender;
+ FT_Pos descender;
- FT_TRACE5(( "blue zone %d:\n", bb ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_Bool have_flag = 0;
+
+
+ FT_TRACE5(( "blue zone %d", axis->blue_count ));
+
+ if ( bs->properties )
+ {
+ FT_TRACE5(( " (" ));
+
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ {
+ FT_TRACE5(( "top" ));
+ have_flag = 1;
+ }
+ else if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ {
+ FT_TRACE5(( "sub top" ));
+ have_flag = 1;
+ }
+
+ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
+ {
+ if ( have_flag )
+ FT_TRACE5(( ", " ));
+ FT_TRACE5(( "neutral" ));
+ have_flag = 1;
+ }
+
+ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
+ {
+ if ( have_flag )
+ FT_TRACE5(( ", " ));
+ FT_TRACE5(( "small top" ));
+ have_flag = 1;
+ }
+
+ if ( AF_LATIN_IS_LONG_BLUE( bs ) )
+ {
+ if ( have_flag )
+ FT_TRACE5(( ", " ));
+ FT_TRACE5(( "long" ));
+ }
+
+ FT_TRACE5(( ")" ));
+ }
+
+ FT_TRACE5(( ":\n" ));
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
num_flats = 0;
num_rounds = 0;
+ ascender = 0;
+ descender = 0;
- for ( ; p < limit && *p; p++ )
+ while ( *p )
{
- FT_UInt glyph_index;
- FT_Pos best_y; /* same as points.y */
+ FT_ULong glyph_index;
+ FT_Long y_offset;
FT_Int best_point, best_contour_first, best_contour_last;
FT_Vector* points;
- FT_Bool round = 0;
+
+ FT_Pos best_y_extremum; /* same as points.y */
+ FT_Bool best_round = 0;
+
+ unsigned int i, num_idx;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ const char* p_old;
+ FT_ULong ch;
+#endif
- /* load the character in the face -- skip unknown or empty ones */
- glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
- if ( glyph_index == 0 )
- continue;
+ while ( *p == ' ' )
+ p++;
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
- outline = face->glyph->outline;
- if ( error || outline.n_points <= 0 )
- continue;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ p_old = p;
+ GET_UTF8_CHAR( ch, p_old );
+#endif
- /* now compute min or max point indices and coordinates */
- points = outline.points;
- best_point = -1;
- best_y = 0; /* make compiler happy */
- best_contour_first = 0; /* ditto */
- best_contour_last = 0; /* ditto */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( !num_idx )
{
- FT_Int nn;
- FT_Int first = 0;
- FT_Int last = -1;
-
-
- for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
- {
- FT_Int old_best_point = best_point;
- FT_Int pp;
-
-
- last = outline.contours[nn];
-
- /* Avoid single-point contours since they are never rasterized. */
- /* In some fonts, they correspond to mark attachment points */
- /* which are way outside of the glyph's real outline. */
- if ( last <= first )
- continue;
-
- if ( AF_LATIN_IS_TOP_BLUE( bb ) )
- {
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y > best_y )
- {
- best_point = pp;
- best_y = points[pp].y;
- }
- }
- else
- {
- for ( pp = first; pp <= last; pp++ )
- if ( best_point < 0 || points[pp].y < best_y )
- {
- best_point = pp;
- best_y = points[pp].y;
- }
- }
-
- if ( best_point != old_best_point )
- {
- best_contour_first = first;
- best_contour_last = last;
- }
- }
- FT_TRACE5(( " %c %ld", *p, best_y ));
+ FT_TRACE5(( " U+%04lX unavailable\n", ch ));
+ continue;
}
- /* now check whether the point belongs to a straight or round */
- /* segment; we first need to find in which contour the extremum */
- /* lies, then inspect its previous and next points */
- if ( best_point >= 0 )
- {
- FT_Pos best_x = points[best_point].x;
- FT_Int prev, next;
- FT_Int best_on_point_first, best_on_point_last;
- FT_Pos dist;
-
-
- if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
- {
- best_on_point_first = best_point;
- best_on_point_last = best_point;
- }
- else
- {
- best_on_point_first = -1;
- best_on_point_last = -1;
- }
-
- /* look for the previous and next points that are not on the */
- /* same Y coordinate, then threshold the `closeness'... */
- prev = best_point;
- next = prev;
-
- do
- {
- if ( prev > best_contour_first )
- prev--;
- else
- prev = best_contour_last;
-
- dist = FT_ABS( points[prev].y - best_y );
- /* accept a small distance or a small angle (both values are */
- /* heuristic; value 20 corresponds to approx. 2.9 degrees) */
- if ( dist > 5 )
- if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
- break;
-
- if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
- {
- best_on_point_first = prev;
- if ( best_on_point_last < 0 )
- best_on_point_last = prev;
- }
-
- } while ( prev != best_point );
-
- do
- {
- if ( next < best_contour_last )
- next++;
- else
- next = best_contour_first;
-
- dist = FT_ABS( points[next].y - best_y );
- if ( dist > 5 )
- if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
- break;
-
- if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
- {
- best_on_point_last = next;
- if ( best_on_point_first < 0 )
- best_on_point_first = next;
- }
-
- } while ( next != best_point );
-
- /* now set the `round' flag depending on the segment's kind */
- /* (value 8 is heuristic) */
- if ( best_on_point_first >= 0 &&
- best_on_point_last >= 0 &&
- (FT_UInt)( FT_ABS( points[best_on_point_last].x -
- points[best_on_point_first].x ) ) >
- metrics->units_per_em / 8 )
- round = 0;
- else
- round = FT_BOOL(
- FT_CURVE_TAG( outline.tags[prev] ) != FT_CURVE_TAG_ON ||
- FT_CURVE_TAG( outline.tags[next] ) != FT_CURVE_TAG_ON );
-
- FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
- }
-
- if ( round )
- rounds[num_rounds++] = best_y;
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ best_y_extremum = FT_INT_MIN;
else
- flats[num_flats++] = best_y;
- }
+ best_y_extremum = FT_INT_MAX;
+
+ /* iterate over all glyph elements of the character cluster */
+ /* and get the data of the `biggest' one */
+ for ( i = 0; i < num_idx; i++ )
+ {
+ FT_Pos best_y;
+ FT_Bool round = 0;
+
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ i,
+ NULL,
+ &y_offset );
+ if ( glyph_index == 0 )
+ {
+ FT_TRACE5(( " U+%04lX unavailable\n", ch ));
+ continue;
+ }
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ outline = face->glyph->outline;
+ /* reject glyphs that don't produce any rendering */
+ if ( error || outline.n_points <= 2 )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( num_idx == 1 )
+ FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
+ else
+ FT_TRACE5(( " component %d of cluster starting with U+%04lX"
+ " contains no (usable) outlines\n", i, ch ));
+#endif
+ continue;
+ }
+
+ /* now compute min or max point indices and coordinates */
+ points = outline.points;
+ best_point = -1;
+ best_y = 0; /* make compiler happy */
+ best_contour_first = 0; /* ditto */
+ best_contour_last = 0; /* ditto */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
+
+
+ for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
+ {
+ FT_Int old_best_point = best_point;
+ FT_Int pp;
+
+
+ last = outline.contours[nn];
+
+ /* Avoid single-point contours since they are never */
+ /* rasterized. In some fonts, they correspond to mark */
+ /* attachment points that are way outside of the glyph's */
+ /* real outline. */
+ if ( last <= first )
+ continue;
+
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) ||
+ AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
+ {
+ if ( best_point < 0 || points[pp].y > best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ ascender = FT_MAX( ascender, best_y + y_offset );
+ }
+ else
+ descender = FT_MIN( descender, points[pp].y + y_offset );
+ }
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ {
+ if ( best_point < 0 || points[pp].y < best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ descender = FT_MIN( descender, best_y + y_offset );
+ }
+ else
+ ascender = FT_MAX( ascender, points[pp].y + y_offset );
+ }
+ }
+
+ if ( best_point != old_best_point )
+ {
+ best_contour_first = first;
+ best_contour_last = last;
+ }
+ }
+ }
+
+ /* now check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then inspect its previous and next points */
+ if ( best_point >= 0 )
+ {
+ FT_Pos best_x = points[best_point].x;
+ FT_Int prev, next;
+ FT_Int best_segment_first, best_segment_last;
+ FT_Int best_on_point_first, best_on_point_last;
+ FT_Pos dist;
+
+
+ best_segment_first = best_point;
+ best_segment_last = best_point;
+
+ if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_first = best_point;
+ best_on_point_last = best_point;
+ }
+ else
+ {
+ best_on_point_first = -1;
+ best_on_point_last = -1;
+ }
+
+ /* look for the previous and next points on the contour */
+ /* that are not on the same Y coordinate, then threshold */
+ /* the `closeness'... */
+ prev = best_point;
+ next = prev;
+
+ do
+ {
+ if ( prev > best_contour_first )
+ prev--;
+ else
+ prev = best_contour_last;
+
+ dist = FT_ABS( points[prev].y - best_y );
+ /* accept a small distance or a small angle (both values are */
+ /* heuristic; value 20 corresponds to approx. 2.9 degrees) */
+ if ( dist > 5 )
+ if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+ break;
+
+ best_segment_first = prev;
+
+ if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_first = prev;
+ if ( best_on_point_last < 0 )
+ best_on_point_last = prev;
+ }
+
+ } while ( prev != best_point );
+
+ do
+ {
+ if ( next < best_contour_last )
+ next++;
+ else
+ next = best_contour_first;
+
+ dist = FT_ABS( points[next].y - best_y );
+ if ( dist > 5 )
+ if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
+ break;
+
+ best_segment_last = next;
+
+ if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
+ {
+ best_on_point_last = next;
+ if ( best_on_point_first < 0 )
+ best_on_point_first = next;
+ }
+
+ } while ( next != best_point );
+
+ if ( AF_LATIN_IS_LONG_BLUE( bs ) )
+ {
+ /* If this flag is set, we have an additional constraint to */
+ /* get the blue zone distance: Find a segment of the topmost */
+ /* (or bottommost) contour that is longer than a heuristic */
+ /* threshold. This ensures that small bumps in the outline */
+ /* are ignored (for example, the `vertical serifs' found in */
+ /* many Hebrew glyph designs). */
+
+ /* If this segment is long enough, we are done. Otherwise, */
+ /* search the segment next to the extremum that is long */
+ /* enough, has the same direction, and a not too large */
+ /* vertical distance from the extremum. Note that the */
+ /* algorithm doesn't check whether the found segment is */
+ /* actually the one (vertically) nearest to the extremum. */
+
+ /* heuristic threshold value */
+ FT_Pos length_threshold = metrics->units_per_em / 25;
+
+
+ dist = FT_ABS( points[best_segment_last].x -
+ points[best_segment_first].x );
+
+ if ( dist < length_threshold &&
+ best_segment_last - best_segment_first + 2 <=
+ best_contour_last - best_contour_first )
+ {
+ /* heuristic threshold value */
+ FT_Pos height_threshold = metrics->units_per_em / 4;
+
+ FT_Int first;
+ FT_Int last;
+ FT_Bool hit;
+
+ /* we intentionally declare these two variables */
+ /* outside of the loop since various compilers emit */
+ /* incorrect warning messages otherwise, talking about */
+ /* `possibly uninitialized variables' */
+ FT_Int p_first = 0; /* make compiler happy */
+ FT_Int p_last = 0;
+
+ FT_Bool left2right;
+
+
+ /* compute direction */
+ prev = best_point;
+
+ do
+ {
+ if ( prev > best_contour_first )
+ prev--;
+ else
+ prev = best_contour_last;
+
+ if ( points[prev].x != best_x )
+ break;
+
+ } while ( prev != best_point );
+
+ /* skip glyph for the degenerate case */
+ if ( prev == best_point )
+ continue;
+
+ left2right = FT_BOOL( points[prev].x < points[best_point].x );
+
+ first = best_segment_last;
+ last = first;
+ hit = 0;
+
+ do
+ {
+ FT_Bool l2r;
+ FT_Pos d;
+
+
+ if ( !hit )
+ {
+ /* no hit; adjust first point */
+ first = last;
+
+ /* also adjust first and last on point */
+ if ( FT_CURVE_TAG( outline.tags[first] ) ==
+ FT_CURVE_TAG_ON )
+ {
+ p_first = first;
+ p_last = first;
+ }
+ else
+ {
+ p_first = -1;
+ p_last = -1;
+ }
+
+ hit = 1;
+ }
+
+ if ( last < best_contour_last )
+ last++;
+ else
+ last = best_contour_first;
+
+ if ( FT_ABS( best_y - points[first].y ) > height_threshold )
+ {
+ /* vertical distance too large */
+ hit = 0;
+ continue;
+ }
+
+ /* same test as above */
+ dist = FT_ABS( points[last].y - points[first].y );
+ if ( dist > 5 )
+ if ( FT_ABS( points[last].x - points[first].x ) <=
+ 20 * dist )
+ {
+ hit = 0;
+ continue;
+ }
+
+ if ( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
+ {
+ p_last = last;
+ if ( p_first < 0 )
+ p_first = last;
+ }
+
+ l2r = FT_BOOL( points[first].x < points[last].x );
+ d = FT_ABS( points[last].x - points[first].x );
+
+ if ( l2r == left2right &&
+ d >= length_threshold )
+ {
+ /* all constraints are met; update segment after */
+ /* finding its end */
+ do
+ {
+ if ( last < best_contour_last )
+ last++;
+ else
+ last = best_contour_first;
+
+ d = FT_ABS( points[last].y - points[first].y );
+ if ( d > 5 )
+ if ( FT_ABS( points[next].x - points[first].x ) <=
+ 20 * dist )
+ {
+ if ( last > best_contour_first )
+ last--;
+ else
+ last = best_contour_last;
+ break;
+ }
+
+ p_last = last;
+
+ if ( FT_CURVE_TAG( outline.tags[last] ) ==
+ FT_CURVE_TAG_ON )
+ {
+ p_last = last;
+ if ( p_first < 0 )
+ p_first = last;
+ }
+
+ } while ( last != best_segment_first );
+
+ best_y = points[first].y;
+
+ best_segment_first = first;
+ best_segment_last = last;
+
+ best_on_point_first = p_first;
+ best_on_point_last = p_last;
+
+ break;
+ }
+
+ } while ( last != best_segment_first );
+ }
+ }
+
+ /* for computing blue zones, we add the y offset as returned */
+ /* by the currently used OpenType feature -- for example, */
+ /* superscript glyphs might be identical to subscript glyphs */
+ /* with a vertical shift */
+ best_y += y_offset;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( num_idx == 1 )
+ FT_TRACE5(( " U+%04lX: best_y = %5ld", ch, best_y ));
+ else
+ FT_TRACE5(( " component %d of cluster starting with U+%04lX:"
+ " best_y = %5ld", i, ch, best_y ));
+#endif
+
+ /* now set the `round' flag depending on the segment's kind: */
+ /* */
+ /* - if the horizontal distance between the first and last */
+ /* `on' point is larger than a heuristic threshold */
+ /* we have a flat segment */
+ /* - if either the first or the last point of the segment is */
+ /* an `off' point, the segment is round, otherwise it is */
+ /* flat */
+ if ( best_on_point_first >= 0 &&
+ best_on_point_last >= 0 &&
+ ( FT_ABS( points[best_on_point_last].x -
+ points[best_on_point_first].x ) ) >
+ flat_threshold )
+ round = 0;
+ else
+ round = FT_BOOL(
+ FT_CURVE_TAG( outline.tags[best_segment_first] ) !=
+ FT_CURVE_TAG_ON ||
+ FT_CURVE_TAG( outline.tags[best_segment_last] ) !=
+ FT_CURVE_TAG_ON );
+
+ if ( round && AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
+ {
+ /* only use flat segments for a neutral blue zone */
+ FT_TRACE5(( " (round, skipped)\n" ));
+ continue;
+ }
+
+ FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+ }
+
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+ {
+ if ( best_y > best_y_extremum )
+ {
+ best_y_extremum = best_y;
+ best_round = round;
+ }
+ }
+ else
+ {
+ if ( best_y < best_y_extremum )
+ {
+ best_y_extremum = best_y;
+ best_round = round;
+ }
+ }
+
+ } /* end for loop */
+
+ if ( !( best_y_extremum == FT_INT_MIN ||
+ best_y_extremum == FT_INT_MAX ) )
+ {
+ if ( best_round )
+ rounds[num_rounds++] = best_y_extremum;
+ else
+ flats[num_flats++] = best_y_extremum;
+ }
+
+ } /* end while loop */
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -448,7 +876,7 @@
}
else
{
- *blue_ref = flats[num_flats / 2];
+ *blue_ref = flats [num_flats / 2];
*blue_shoot = rounds[num_rounds / 2];
}
@@ -462,7 +890,8 @@
FT_Bool over_ref = FT_BOOL( shoot > ref );
- if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+ if ( ( AF_LATIN_IS_TOP_BLUE( bs ) ||
+ AF_LATIN_IS_SUB_TOP_BLUE( bs) ) ^ over_ref )
{
*blue_ref =
*blue_shoot = ( shoot + ref ) / 2;
@@ -472,22 +901,32 @@
}
}
+ blue->ascender = ascender;
+ blue->descender = descender;
+
blue->flags = 0;
- if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ if ( AF_LATIN_IS_TOP_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_TOP;
+ if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+ blue->flags |= AF_LATIN_BLUE_SUB_TOP;
+ if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
+ blue->flags |= AF_LATIN_BLUE_NEUTRAL;
/*
* The following flag is used later to adjust the y and x scales
* in order to optimize the pixel grid alignment of the top of small
* letters.
*/
- if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
FT_TRACE5(( " -> reference = %ld\n"
" overshoot = %ld\n",
*blue_ref, *blue_shoot ));
- }
+
+ } /* end for loop */
+
+ af_shaper_buf_destroy( face, shaper_buf );
FT_TRACE5(( "\n" ));
@@ -501,26 +940,36 @@
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face )
{
- FT_UInt i;
FT_Bool started = 0, same_width = 1;
FT_Fixed advance, old_advance = 0;
+ void* shaper_buf;
- /* digit `0' is 0x30 in all supported charmaps */
- for ( i = 0x30; i <= 0x39; i++ )
+ /* in all supported charmaps, digits have character codes 0x30-0x39 */
+ const char digits[] = "0 1 2 3 4 5 6 7 8 9";
+ const char* p;
+
+
+ p = digits;
+ shaper_buf = af_shaper_buf_create( face );
+
+ while ( *p )
{
- FT_UInt glyph_index;
+ FT_ULong glyph_index;
+ unsigned int num_idx;
- glyph_index = FT_Get_Char_Index( face, i );
- if ( glyph_index == 0 )
+ /* reject input that maps to more than a single glyph */
+ p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
+ if ( num_idx > 1 )
continue;
- if ( FT_Get_Advance( face, glyph_index,
- FT_LOAD_NO_SCALE |
- FT_LOAD_NO_HINTING |
- FT_LOAD_IGNORE_TRANSFORM,
- &advance ) )
+ glyph_index = af_shaper_get_elem( &metrics->root,
+ shaper_buf,
+ 0,
+ &advance,
+ NULL );
+ if ( !glyph_index )
continue;
if ( started )
@@ -538,6 +987,8 @@
}
}
+ af_shaper_buf_destroy( face, shaper_buf );
+
metrics->root.digits_have_same_width = same_width;
}
@@ -650,7 +1101,54 @@
else
#endif
if ( dim == AF_DIMENSION_VERT )
- scale = FT_MulDiv( scale, fitted, scaled );
+ {
+ FT_Pos max_height;
+ FT_Pos dist;
+ FT_Fixed new_scale;
+
+
+ new_scale = FT_MulDiv( scale, fitted, scaled );
+
+ /* the scaling should not change the result by more than two pixels */
+ max_height = metrics->units_per_em;
+
+ for ( nn = 0; nn < Axis->blue_count; nn++ )
+ {
+ max_height = FT_MAX( max_height, Axis->blues[nn].ascender );
+ max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
+ }
+
+ dist = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
+ dist &= ~127;
+
+ if ( dist == 0 )
+ {
+ scale = new_scale;
+
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " vertical scaling changed from %.4f to %.4f (by %d%%)\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style],
+ axis->org_scale / 65536.0,
+ scale / 65536.0,
+ ( fitted - scaled ) * 100 / scaled ));
+ }
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ {
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " excessive vertical scaling abandoned\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
+ }
+#endif
+ }
}
}
}
@@ -669,6 +1167,10 @@
metrics->root.scaler.y_delta = delta;
}
+ FT_TRACE5(( "%s widths (style `%s')\n",
+ dim == AF_DIMENSION_HORZ ? "horizontal" : "vertical",
+ af_style_names[metrics->root.style_class->style] ));
+
/* scale the widths */
for ( nn = 0; nn < axis->width_count; nn++ )
{
@@ -677,15 +1179,34 @@
width->cur = FT_MulFix( width->org, scale );
width->fit = width->cur;
+
+ FT_TRACE5(( " %d scaled to %.2f\n",
+ width->org,
+ width->cur / 64.0 ));
}
+ FT_TRACE5(( "\n" ));
+
/* an extra-light axis corresponds to a standard width that is */
/* smaller than 5/8 pixels */
axis->extra_light =
(FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( axis->extra_light )
+ FT_TRACE5(( "`%s' style is extra light (at current resolution)\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
+#endif
+
if ( dim == AF_DIMENSION_VERT )
{
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( axis->blue_count )
+ FT_TRACE5(( "blue zones (style `%s')\n",
+ af_style_names[metrics->root.style_class->style] ));
+#endif
+
/* scale the blue zones */
for ( nn = 0; nn < axis->blue_count; nn++ )
{
@@ -759,6 +1280,61 @@
blue->flags |= AF_LATIN_BLUE_ACTIVE;
}
}
+
+ /* use sub-top blue zone only if it doesn't overlap with */
+ /* another (non-sup-top) blue zone; otherwise, the */
+ /* effect would be similar to a neutral blue zone, which */
+ /* is not desired here */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+ FT_UInt i;
+
+
+ if ( !( blue->flags & AF_LATIN_BLUE_SUB_TOP ) )
+ continue;
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ for ( i = 0; i < axis->blue_count; i++ )
+ {
+ AF_LatinBlue b = &axis->blues[i];
+
+
+ if ( b->flags & AF_LATIN_BLUE_SUB_TOP )
+ continue;
+ if ( !( b->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ if ( b->ref.fit <= blue->shoot.fit &&
+ b->shoot.fit >= blue->ref.fit )
+ {
+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+ break;
+ }
+ }
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+
+
+ FT_TRACE5(( " reference %d: %d scaled to %.2f%s\n"
+ " overshoot %d: %d scaled to %.2f%s\n",
+ nn,
+ blue->ref.org,
+ blue->ref.fit / 64.0,
+ blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+ : " (inactive)",
+ nn,
+ blue->shoot.org,
+ blue->shoot.fit / 64.0,
+ blue->flags & AF_LATIN_BLUE_ACTIVE ? ""
+ : " (inactive)" ));
+ }
+#endif
}
}
@@ -778,6 +1354,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_latin_get_standard_widths( AF_LatinMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -793,14 +1385,17 @@
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim )
{
- AF_AxisHints axis = &hints->axis[dim];
- FT_Memory memory = hints->memory;
- FT_Error error = FT_Err_Ok;
- AF_Segment segment = NULL;
- AF_SegmentRec seg0;
- AF_Point* contour = hints->contours;
- AF_Point* contour_limit = contour + hints->num_contours;
- AF_Direction major_dir, segment_dir;
+ AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = FT_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
+
+ FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
FT_ZERO( &seg0 );
@@ -841,11 +1436,13 @@
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
- AF_Point point = contour[0];
- AF_Point last = point->prev;
- int on_edge = 0;
- FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
- FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ AF_Point point = contour[0];
+ AF_Point last = point->prev;
+ int on_edge = 0;
+ FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
+ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
+ FT_Pos min_on_pos = 32000;
+ FT_Pos max_on_pos = -32000;
FT_Bool passed;
@@ -887,6 +1484,16 @@
if ( u > max_pos )
max_pos = u;
+ /* get minimum and maximum coordinate of on points */
+ if ( !( point->flags & AF_FLAG_CONTROL ) )
+ {
+ v = point->v;
+ if ( v < min_on_pos )
+ min_on_pos = v;
+ if ( v > max_on_pos )
+ max_on_pos = v;
+ }
+
if ( point->out_dir != segment_dir || point == last )
{
/* we are just leaving an edge; record a new segment! */
@@ -894,9 +1501,10 @@
segment->pos = (FT_Short)( ( min_pos + max_pos ) >> 1 );
/* a segment is round if either its first or last point */
- /* is a control point */
- if ( ( segment->first->flags | point->flags ) &
- AF_FLAG_CONTROL )
+ /* is a control point, and the length of the on points */
+ /* inbetween doesn't exceed a heuristic limit */
+ if ( ( segment->first->flags | point->flags ) & AF_FLAG_CONTROL &&
+ ( max_on_pos - min_on_pos ) < flat_threshold )
segment->flags |= AF_EDGE_ROUND;
/* compute segment size */
@@ -932,17 +1540,28 @@
/* this is the start of a new segment! */
segment_dir = (AF_Direction)point->out_dir;
- /* clear all segment fields */
error = af_axis_hints_new_segment( axis, memory, &segment );
if ( error )
goto Exit;
- segment[0] = seg0;
- segment->dir = (FT_Char)segment_dir;
+ /* clear all segment fields */
+ segment[0] = seg0;
+
+ segment->dir = (FT_Char)segment_dir;
+ segment->first = point;
+ segment->last = point;
+
min_pos = max_pos = point->u;
- segment->first = point;
- segment->last = point;
- on_edge = 1;
+
+ if ( point->flags & AF_FLAG_CONTROL )
+ {
+ min_on_pos = 32000;
+ max_on_pos = -32000;
+ }
+ else
+ min_on_pos = max_on_pos = point->v;
+
+ on_edge = 1;
}
point = point->next;
@@ -966,9 +1585,6 @@
FT_Pos last_v = last->v;
- if ( first == last )
- continue;
-
if ( first_v < last_v )
{
AF_Point p;
@@ -1007,31 +1623,44 @@
}
- /* Link segments to form stems and serifs. */
+ /* Link segments to form stems and serifs. If `width_count' and */
+ /* `widths' are non-zero, use them to fine-tune the scoring function. */
FT_LOCAL_DEF( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
+ FT_UInt width_count,
+ AF_WidthRec* widths,
AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
- FT_Pos len_threshold, len_score;
+ FT_Pos len_threshold, len_score, dist_score, max_width;
AF_Segment seg1, seg2;
+ if ( width_count )
+ max_width = widths[width_count - 1].org;
+ else
+ max_width = 0;
+
+ /* a heuristic value to set up a minimum value for overlapping */
len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
if ( len_threshold == 0 )
len_threshold = 1;
+ /* a heuristic value to weight lengths */
len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
+ /* a heuristic value to weight distances (no call to */
+ /* AF_LATIN_CONSTANT needed, since we work on multiples */
+ /* of the stem width) */
+ dist_score = 3000;
+
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
- /* the fake segments are introduced to hint the metrics -- */
- /* we must never link them to anything */
- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ if ( seg1->dir != axis->major_dir )
continue;
/* search for stems having opposite directions, */
@@ -1045,10 +1674,9 @@
if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
{
/* compute distance between the two segments */
- FT_Pos dist = pos2 - pos1;
- FT_Pos min = seg1->min_coord;
- FT_Pos max = seg1->max_coord;
- FT_Pos len, score;
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len;
if ( min < seg2->min_coord )
@@ -1058,15 +1686,49 @@
max = seg2->max_coord;
/* compute maximum coordinate difference of the two segments */
+ /* (this is, how much they overlap) */
len = max - min;
if ( len >= len_threshold )
{
- /* small coordinate differences cause a higher score, and */
- /* segments with a greater distance cause a higher score also */
- score = dist + len_score / len;
+ /*
+ * The score is the sum of two demerits indicating the
+ * `badness' of a fit, measured along the segments' main axis
+ * and orthogonal to it, respectively.
+ *
+ * o The less overlapping along the main axis, the worse it
+ * is, causing a larger demerit.
+ *
+ * o The nearer the orthogonal distance to a stem width, the
+ * better it is, causing a smaller demerit. For simplicity,
+ * however, we only increase the demerit for values that
+ * exceed the largest stem width.
+ */
+
+ FT_Pos dist = pos2 - pos1;
+
+ FT_Pos dist_demerit, score;
+
+
+ if ( max_width )
+ {
+ /* distance demerits are based on multiples of `max_width'; */
+ /* we scale by 1024 for getting more precision */
+ FT_Pos delta = ( dist << 10 ) / max_width - ( 1 << 10 );
+
+
+ if ( delta > 10000 )
+ dist_demerit = 32000;
+ else if ( delta > 0 )
+ dist_demerit = delta * delta / dist_score;
+ else
+ dist_demerit = 0;
+ }
+ else
+ dist_demerit = dist; /* default if no widths available */
+
+ score = dist_demerit + len_score / len;
/* and we search for the smallest score */
- /* of the sum of the two values */
if ( score < seg1->score )
{
seg1->score = score;
@@ -1385,7 +2047,7 @@
/* Example: the `c' in cour.pfa at size 13 */
if ( edge->serif && edge->link )
- edge->serif = 0;
+ edge->serif = NULL;
}
}
@@ -1398,6 +2060,8 @@
FT_LOCAL_DEF( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
+ FT_UInt width_count,
+ AF_WidthRec* widths,
AF_Dimension dim )
{
FT_Error error;
@@ -1406,7 +2070,7 @@
error = af_latin_hints_compute_segments( hints, dim );
if ( !error )
{
- af_latin_hints_link_segments( hints, dim );
+ af_latin_hints_link_segments( hints, width_count, widths, dim );
error = af_latin_hints_compute_edges( hints, dim );
}
@@ -1417,7 +2081,7 @@
/* Compute all edges which lie within blue zones. */
- FT_LOCAL_DEF( void )
+ static void
af_latin_hints_compute_blue_edges( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
@@ -1435,8 +2099,9 @@
for ( ; edge < edge_limit; edge++ )
{
FT_UInt bb;
- AF_Width best_blue = NULL;
- FT_Pos best_dist; /* initial threshold */
+ AF_Width best_blue = NULL;
+ FT_Bool best_blue_is_neutral = 0;
+ FT_Pos best_dist; /* initial threshold */
/* compute the initial threshold as a fraction of the EM size */
@@ -1450,24 +2115,27 @@
for ( bb = 0; bb < latin->blue_count; bb++ )
{
AF_LatinBlue blue = latin->blues + bb;
- FT_Bool is_top_blue, is_major_dir;
+ FT_Bool is_top_blue, is_neutral_blue, is_major_dir;
/* skip inactive blue zones (i.e., those that are too large) */
if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
continue;
- /* if it is a top zone, check for right edges -- if it is a bottom */
- /* zone, check for left edges */
- /* */
- /* of course, that's for TrueType */
- is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
- is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+ /* if it is a top zone, check for right edges (against the major */
+ /* direction); if it is a bottom zone, check for left edges (in */
+ /* the major direction) -- this assumes the TrueType convention */
+ /* for the orientation of contours */
+ is_top_blue =
+ (FT_Byte)( ( blue->flags & ( AF_LATIN_BLUE_TOP |
+ AF_LATIN_BLUE_SUB_TOP ) ) != 0 );
+ is_neutral_blue =
+ (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
+ is_major_dir =
+ FT_BOOL( edge->dir == axis->major_dir );
- /* if it is a top zone, the edge must be against the major */
- /* direction; if it is a bottom zone, it must be in the major */
- /* direction */
- if ( is_top_blue ^ is_major_dir )
+ /* neutral blue zones are handled for both directions */
+ if ( is_top_blue ^ is_major_dir || is_neutral_blue )
{
FT_Pos dist;
@@ -1480,15 +2148,19 @@
dist = FT_MulFix( dist, scale );
if ( dist < best_dist )
{
- best_dist = dist;
- best_blue = &blue->ref;
+ best_dist = dist;
+ best_blue = &blue->ref;
+ best_blue_is_neutral = is_neutral_blue;
}
/* now compare it to the overshoot position and check whether */
/* the edge is rounded, and whether the edge is over the */
/* reference position of a top zone, or under the reference */
- /* position of a bottom zone */
- if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
+ /* position of a bottom zone (provided we don't have a */
+ /* neutral blue zone) */
+ if ( edge->flags & AF_EDGE_ROUND &&
+ dist != 0 &&
+ !is_neutral_blue )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
@@ -1502,8 +2174,9 @@
dist = FT_MulFix( dist, scale );
if ( dist < best_dist )
{
- best_dist = dist;
- best_blue = &blue->shoot;
+ best_dist = dist;
+ best_blue = &blue->shoot;
+ best_blue_is_neutral = is_neutral_blue;
}
}
}
@@ -1511,7 +2184,11 @@
}
if ( best_blue )
+ {
edge->blue_edge = best_blue;
+ if ( best_blue_is_neutral )
+ edge->flags |= AF_EDGE_NEUTRAL;
+ }
}
}
@@ -1527,7 +2204,7 @@
FT_Face face = metrics->root.scaler.face;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
* correct x_scale and y_scale if needed, since they may have
@@ -1575,11 +2252,20 @@
/*
* In `light' hinting mode we disable horizontal hinting completely.
* We also do it if the face is italic.
+ *
+ * However, if warping is enabled (which only works in `light' hinting
+ * mode), advance widths get adjusted, too.
*/
if ( mode == FT_RENDER_MODE_LIGHT ||
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
@@ -1600,13 +2286,13 @@
static FT_Pos
af_latin_snap_width( AF_Width widths,
- FT_Int count,
+ FT_UInt count,
FT_Pos width )
{
- int n;
- FT_Pos best = 64 + 32 + 2;
- FT_Pos reference = width;
- FT_Pos scaled;
+ FT_UInt n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
for ( n = 0; n < count; n++ )
@@ -1651,11 +2337,11 @@
af_latin_compute_stem_width( AF_GlyphHints hints,
AF_Dimension dim,
FT_Pos width,
- AF_Edge_Flags base_flags,
- AF_Edge_Flags stem_flags )
+ FT_UInt base_flags,
+ FT_UInt stem_flags )
{
- AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
- AF_LatinAxis axis = & metrics->axis[dim];
+ AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
+ AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos dist = width;
FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT );
@@ -1819,17 +2505,16 @@
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
- FT_Pos fitted_width = af_latin_compute_stem_width(
- hints, dim, dist,
- (AF_Edge_Flags)base_edge->flags,
- (AF_Edge_Flags)stem_edge->flags );
+ FT_Pos fitted_width = af_latin_compute_stem_width( hints, dim, dist,
+ base_edge->flags,
+ stem_edge->flags );
stem_edge->pos = base_edge->pos + fitted_width;
FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to %.2f,"
" dist was %.2f, now %.2f\n",
- stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge - hints->axis[dim].edges, stem_edge->opos / 64.0,
stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
}
@@ -1861,7 +2546,7 @@
/* The main grid-fitting routine. */
- FT_LOCAL_DEF( void )
+ static void
af_latin_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
{
@@ -1878,8 +2563,9 @@
#endif
- FT_TRACE5(( "%s edge hinting\n",
- dim == AF_DIMENSION_VERT ? "horizontal" : "vertical" ));
+ FT_TRACE5(( "latin %s edge hinting (style `%s')\n",
+ dim == AF_DIMENSION_VERT ? "horizontal" : "vertical",
+ af_style_names[hints->metrics->style_class->style] ));
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
@@ -1895,14 +2581,41 @@
if ( edge->flags & AF_EDGE_DONE )
continue;
- blue = edge->blue_edge;
edge1 = NULL;
edge2 = edge->link;
+ /*
+ * If a stem contains both a neutral and a non-neutral blue zone,
+ * skip the neutral one. Otherwise, outlines with different
+ * directions might be incorrectly aligned at the same vertical
+ * position.
+ *
+ * If we have two neutral blue zones, skip one of them.
+ *
+ */
+ if ( edge->blue_edge && edge2 && edge2->blue_edge )
+ {
+ FT_Byte neutral = edge->flags & AF_EDGE_NEUTRAL;
+ FT_Byte neutral2 = edge2->flags & AF_EDGE_NEUTRAL;
+
+
+ if ( neutral2 )
+ {
+ edge2->blue_edge = NULL;
+ edge2->flags &= ~AF_EDGE_NEUTRAL;
+ }
+ else if ( neutral )
+ {
+ edge->blue_edge = NULL;
+ edge->flags &= ~AF_EDGE_NEUTRAL;
+ }
+ }
+
+ blue = edge->blue_edge;
if ( blue )
edge1 = edge;
- /* flip edges if the other stem is aligned to a blue zone */
+ /* flip edges if the other edge is aligned to a blue zone */
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;
@@ -1969,7 +2682,7 @@
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
- FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges ));
+ FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2 - edges ));
af_latin_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
@@ -1989,10 +2702,9 @@
org_len = edge2->opos - edge->opos;
- cur_len = af_latin_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
/* some voodoo to specially round edges for small stem widths; */
/* the idea is to align the center of a stem, then shifting */
@@ -2059,10 +2771,9 @@
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
- cur_len = af_latin_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
if ( edge2->flags & AF_EDGE_DONE )
{
@@ -2120,10 +2831,9 @@
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
- cur_len = af_latin_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ cur_len = af_latin_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
cur_pos1 = FT_PIX_ROUND( org_pos );
delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
@@ -2351,13 +3061,16 @@
/* Apply the complete hinting algorithm to a latin glyph. */
static FT_Error
- af_latin_hints_apply( AF_GlyphHints hints,
+ af_latin_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
+ AF_LatinAxis axis;
+
error = af_glyph_hints_reload( hints, outline );
if ( error )
@@ -2365,24 +3078,35 @@
/* analyze glyph outline */
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
+ if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) ) ||
+ AF_HINTS_DO_HORIZONTAL( hints ) )
#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
#endif
{
- error = af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
+ axis = &metrics->axis[AF_DIMENSION_HORZ];
+ error = af_latin_hints_detect_features( hints,
+ axis->width_count,
+ axis->widths,
+ AF_DIMENSION_HORZ );
if ( error )
goto Exit;
}
if ( AF_HINTS_DO_VERTICAL( hints ) )
{
- error = af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
+ axis = &metrics->axis[AF_DIMENSION_VERT];
+ error = af_latin_hints_detect_features( hints,
+ axis->width_count,
+ axis->widths,
+ AF_DIMENSION_VERT );
if ( error )
goto Exit;
- af_latin_hints_compute_blue_edges( hints, metrics );
+ /* apply blue zones to base characters only */
+ if ( !( metrics->root.globals->glyph_styles[glyph_index] & AF_NONBASE ) )
+ af_latin_hints_compute_blue_edges( hints, metrics );
}
/* grid-fit the outline */
@@ -2390,7 +3114,8 @@
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
@@ -2403,7 +3128,7 @@
scale, delta );
continue;
}
-#endif
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
@@ -2414,6 +3139,7 @@
af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
}
}
+
af_glyph_hints_save( hints, outline );
Exit:
@@ -2430,56 +3156,20 @@
/*************************************************************************/
- /* XXX: this should probably fine tuned to differentiate better between */
- /* scripts... */
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_latin_writing_system_class,
- static const AF_Script_UniRangeRec af_latin_uniranges[] =
- {
- AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */
- AF_UNIRANGE_REC( 0x00A0UL, 0x00FFUL ), /* Latin-1 Supplement (no control chars) */
- AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */
- AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */
- AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */
- AF_UNIRANGE_REC( 0x02B0UL, 0x02FFUL ), /* Spacing Modifier Letters */
- AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */
- AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */
- AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */
- AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */
- AF_UNIRANGE_REC( 0x1D00UL, 0x1D7FUL ), /* Phonetic Extensions */
- AF_UNIRANGE_REC( 0x1D80UL, 0x1DBFUL ), /* Phonetic Extensions Supplement */
- AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */
- AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */
- AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */
- AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */
- AF_UNIRANGE_REC( 0x2070UL, 0x209FUL ), /* Superscripts and Subscripts */
- AF_UNIRANGE_REC( 0x20A0UL, 0x20CFUL ), /* Currency Symbols */
- AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */
- AF_UNIRANGE_REC( 0x2460UL, 0x24FFUL ), /* Enclosed Alphanumerics */
- AF_UNIRANGE_REC( 0x2C60UL, 0x2C7FUL ), /* Latin Extended-C */
- AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */
- AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */
- AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */
- AF_UNIRANGE_REC( 0xA720UL, 0xA7FFUL ), /* Latin Extended-D */
- AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */
- AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */
- AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ), /* Enclosed Alphanumeric Supplement */
- AF_UNIRANGE_REC( 0UL, 0UL )
- };
-
-
- AF_DEFINE_SCRIPT_CLASS( af_latin_script_class,
- AF_SCRIPT_LATIN,
- af_latin_uniranges,
- 'o',
+ AF_WRITING_SYSTEM_LATIN,
sizeof ( AF_LatinMetricsRec ),
- (AF_Script_InitMetricsFunc) af_latin_metrics_init,
- (AF_Script_ScaleMetricsFunc)af_latin_metrics_scale,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init,
+ (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths,
- (AF_Script_InitHintsFunc) af_latin_hints_init,
- (AF_Script_ApplyHintsFunc) af_latin_hints_apply
+ (AF_WritingSystem_InitHintsFunc) af_latin_hints_init,
+ (AF_WritingSystem_ApplyHintsFunc) af_latin_hints_apply
)
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index d9170b3..414060f 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -2,9 +2,10 @@
/* */
/* aflatin.h */
/* */
-/* Auto-fitter hinting routines for latin script (specification). */
+/* Auto-fitter hinting routines for latin writing system */
+/* (specification). */
/* */
-/* Copyright 2003-2007, 2009, 2011-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,10 +25,9 @@
FT_BEGIN_HEADER
+ /* the `latin' writing system */
- /* the latin-specific script class */
-
- AF_DECLARE_SCRIPT_CLASS( af_latin_script_class )
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin_writing_system_class )
/* constants are given with units_per_em == 2048 in mind */
@@ -46,48 +46,40 @@
/*
* The following declarations could be embedded in the file `aflatin.c';
- * they have been made semi-public to allow alternate script hinters to
- * re-use some of them.
+ * they have been made semi-public to allow alternate writing system
+ * hinters to re-use some of them.
*/
- /* Latin (global) metrics management */
-
- enum
- {
- AF_LATIN_BLUE_CAPITAL_TOP,
- AF_LATIN_BLUE_CAPITAL_BOTTOM,
- AF_LATIN_BLUE_SMALL_F_TOP,
- AF_LATIN_BLUE_SMALL_TOP,
- AF_LATIN_BLUE_SMALL_BOTTOM,
- AF_LATIN_BLUE_SMALL_MINOR,
-
- AF_LATIN_BLUE_MAX
- };
-
-
-#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
- (b) == AF_LATIN_BLUE_SMALL_F_TOP || \
- (b) == AF_LATIN_BLUE_SMALL_TOP )
+#define AF_LATIN_IS_TOP_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
+#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
+#define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
+#define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT )
+#define AF_LATIN_IS_LONG_BLUE( b ) \
+ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG )
#define AF_LATIN_MAX_WIDTHS 16
-#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX
- enum
- {
- AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
- AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */
- AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
- /* optimization */
- AF_LATIN_BLUE_FLAG_MAX
- };
+#define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
+#define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */
+#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript top */
+ /* blue zone */
+#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have neutral blue zone */
+#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustment */
+ /* optimization */
typedef struct AF_LatinBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot;
+ FT_Pos ascender;
+ FT_Pos descender;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
@@ -106,7 +98,7 @@
/* ignored for horizontal metrics */
FT_UInt blue_count;
- AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];
+ AF_LatinBlueRec blues[AF_BLUE_STRINGSET_MAX];
FT_Fixed org_scale;
FT_Pos org_delta;
@@ -116,9 +108,9 @@
typedef struct AF_LatinMetricsRec_
{
- AF_ScriptMetricsRec root;
- FT_UInt units_per_em;
- AF_LatinAxisRec axis[AF_DIMENSION_MAX];
+ AF_StyleMetricsRec root;
+ FT_UInt units_per_em;
+ AF_LatinAxisRec axis[AF_DIMENSION_MAX];
} AF_LatinMetricsRec, *AF_LatinMetrics;
@@ -148,15 +140,11 @@
/*************************************************************************/
/*************************************************************************/
- enum
- {
- AF_LATIN_HINTS_HORZ_SNAP = 1 << 0, /* enable stem width snapping */
- AF_LATIN_HINTS_VERT_SNAP = 1 << 1, /* enable stem height snapping */
- AF_LATIN_HINTS_STEM_ADJUST = 1 << 2, /* enable stem width/height */
- /* adjustment */
- AF_LATIN_HINTS_MONO = 1 << 3 /* indicate monochrome */
- /* rendering */
- };
+#define AF_LATIN_HINTS_HORZ_SNAP ( 1U << 0 ) /* stem width snapping */
+#define AF_LATIN_HINTS_VERT_SNAP ( 1U << 1 ) /* stem height snapping */
+#define AF_LATIN_HINTS_STEM_ADJUST ( 1U << 2 ) /* stem width/height */
+ /* adjustment */
+#define AF_LATIN_HINTS_MONO ( 1U << 3 ) /* monochrome rendering */
#define AF_LATIN_HINTS_DO_HORZ_SNAP( h ) \
@@ -174,7 +162,7 @@
/*
* The next functions shouldn't normally be exported. However, other
- * scripts might like to use these functions as-is.
+ * writing systems might like to use these functions as-is.
*/
FT_LOCAL( FT_Error )
af_latin_hints_compute_segments( AF_GlyphHints hints,
@@ -182,6 +170,8 @@
FT_LOCAL( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
+ FT_UInt width_count,
+ AF_WidthRec* widths,
AF_Dimension dim );
FT_LOCAL( FT_Error )
@@ -190,6 +180,8 @@
FT_LOCAL( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
+ FT_UInt width_count,
+ AF_WidthRec* widths,
AF_Dimension dim );
/* */
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index b1e9658..2fb7d1d 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -2,9 +2,9 @@
/* */
/* aflatin2.c */
/* */
-/* Auto-fitter hinting routines for latin script (body). */
+/* Auto-fitter hinting routines for latin writing system (body). */
/* */
-/* Copyright 2003-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -76,8 +76,9 @@
AF_Scaler scaler = &dummy->root.scaler;
- glyph_index = FT_Get_Char_Index( face,
- metrics->root.clazz->standard_char );
+ glyph_index = FT_Get_Char_Index(
+ face,
+ metrics->root.style_class->standard_char );
if ( glyph_index == 0 )
goto Exit;
@@ -94,7 +95,7 @@
scaler->render_mode = FT_RENDER_MODE_NORMAL;
scaler->flags = 0;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
error = af_glyph_hints_reload( hints, &face->glyph->outline );
if ( error )
@@ -409,11 +410,11 @@
blue->flags |= AF_LATIN_BLUE_TOP;
/*
- * The following flags is used later to adjust the y and x scales
+ * The following flag is used later to adjust the y and x scales
* in order to optimize the pixel grid alignment of the top of small
* letters.
*/
- if ( bb == AF_LATIN_BLUE_SMALL_TOP )
+ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
FT_TRACE5(( " -> reference = %ld\n"
@@ -692,6 +693,22 @@
}
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_latin2_get_standard_widths( AF_LatinMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -834,8 +851,8 @@
{
AF_Point pt = first;
AF_Point last = point;
- AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
- AF_Flags f1;
+ FT_UInt f0 = pt->flags & AF_FLAG_CONTROL;
+ FT_UInt f1;
segment->flags &= ~AF_EDGE_ROUND;
@@ -843,7 +860,7 @@
for ( ; pt != last; f0 = f1 )
{
pt = pt->next;
- f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
+ f1 = pt->flags & AF_FLAG_CONTROL;
if ( !f0 && !f1 )
break;
@@ -889,9 +906,6 @@
FT_Pos last_v = last->v;
- if ( first == last )
- continue;
-
if ( first_v < last_v )
{
p = first->prev;
@@ -983,7 +997,7 @@
#ifdef AF_SORT_SEGMENTS
for ( seg1 = segments; seg1 < segment_mid; seg1++ )
{
- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ if ( seg1->dir != axis->major_dir )
continue;
for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
@@ -991,9 +1005,7 @@
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
- /* the fake segments are introduced to hint the metrics -- */
- /* we must never link them to anything */
- if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
+ if ( seg1->dir != axis->major_dir )
continue;
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
@@ -1052,7 +1064,7 @@
{
if ( seg2->link != seg1 )
{
- seg1->link = 0;
+ seg1->link = NULL;
seg1->serif = seg2->link;
}
}
@@ -1132,7 +1144,7 @@
for ( seg = segments; seg < segment_limit; seg++ )
{
- AF_Edge found = 0;
+ AF_Edge found = NULL;
FT_Int ee;
@@ -1193,9 +1205,10 @@
edge->first = seg;
edge->last = seg;
- edge->fpos = seg->pos;
edge->dir = seg->dir;
- edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ edge->fpos = seg->pos;
+ edge->opos = FT_MulFix( seg->pos, scale );
+ edge->pos = edge->opos;
seg->edge_next = seg;
}
else
@@ -1358,7 +1371,7 @@
/* Example: the `c' in cour.pfa at size 13 */
if ( edge->serif && edge->link )
- edge->serif = 0;
+ edge->serif = NULL;
}
}
@@ -1385,7 +1398,7 @@
}
- FT_LOCAL_DEF( void )
+ static void
af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
@@ -1500,7 +1513,7 @@
FT_Face face = metrics->root.scaler.face;
- af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
/*
* correct x_scale and y_scale if needed, since they may have
@@ -1516,9 +1529,7 @@
#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
- {
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
- }
#endif
scaler_flags = hints->scaler_flags;
@@ -1555,6 +1566,12 @@
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
@@ -1575,13 +1592,13 @@
static FT_Pos
af_latin2_snap_width( AF_Width widths,
- FT_Int count,
+ FT_UInt count,
FT_Pos width )
{
- int n;
- FT_Pos best = 64 + 32 + 2;
- FT_Pos reference = width;
- FT_Pos scaled;
+ FT_UInt n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
for ( n = 0; n < count; n++ )
@@ -1624,8 +1641,8 @@
af_latin2_compute_stem_width( AF_GlyphHints hints,
AF_Dimension dim,
FT_Pos width,
- AF_Edge_Flags base_flags,
- AF_Edge_Flags stem_flags )
+ FT_UInt base_flags,
+ FT_UInt stem_flags )
{
AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
AF_LatinAxis axis = & metrics->axis[dim];
@@ -1796,10 +1813,9 @@
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
- FT_Pos fitted_width = af_latin2_compute_stem_width(
- hints, dim, dist,
- (AF_Edge_Flags)base_edge->flags,
- (AF_Edge_Flags)stem_edge->flags );
+ FT_Pos fitted_width = af_latin2_compute_stem_width( hints, dim, dist,
+ base_edge->flags,
+ stem_edge->flags );
stem_edge->pos = base_edge->pos + fitted_width;
@@ -1833,7 +1849,7 @@
/*************************************************************************/
- FT_LOCAL_DEF( void )
+ static void
af_latin2_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
{
@@ -1841,7 +1857,7 @@
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Edge edge;
- AF_Edge anchor = 0;
+ AF_Edge anchor = NULL;
FT_Int has_serifs = 0;
FT_Pos anchor_drift = 0;
@@ -1945,10 +1961,9 @@
org_len = edge2->opos - edge->opos;
- cur_len = af_latin2_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
if ( cur_len <= 64 )
u_off = d_off = 32;
else
@@ -2010,10 +2025,9 @@
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
- cur_len = af_latin2_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
org_left = org_pos + ( ( org_len - cur_len ) >> 1 );
org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
@@ -2302,13 +2316,16 @@
static FT_Error
- af_latin2_hints_apply( AF_GlyphHints hints,
+ af_latin2_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
+ FT_UNUSED( glyph_index );
+
error = af_glyph_hints_reload( hints, outline );
if ( error )
@@ -2316,8 +2333,9 @@
/* analyze glyph outline */
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
+ if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) ) ||
+ AF_HINTS_DO_HORIZONTAL( hints ) )
#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
#endif
@@ -2340,8 +2358,9 @@
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
- if ( ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT &&
+ AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
@@ -2352,7 +2371,7 @@
af_glyph_hints_scale_dim( hints, dim, scale, delta );
continue;
}
-#endif
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
@@ -2379,27 +2398,20 @@
/*************************************************************************/
- static const AF_Script_UniRangeRec af_latin2_uniranges[] =
- {
- AF_UNIRANGE_REC( 32UL, 127UL ), /* TODO: Add new Unicode ranges here! */
- AF_UNIRANGE_REC( 160UL, 255UL ),
- AF_UNIRANGE_REC( 0UL, 0UL )
- };
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_latin2_writing_system_class,
-
- AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class,
- AF_SCRIPT_LATIN2,
- af_latin2_uniranges,
- 'o',
+ AF_WRITING_SYSTEM_LATIN2,
sizeof ( AF_LatinMetricsRec ),
- (AF_Script_InitMetricsFunc) af_latin2_metrics_init,
- (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale,
- (AF_Script_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,
+ (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,
+ (AF_WritingSystem_DoneMetricsFunc) NULL,
+ (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths,
- (AF_Script_InitHintsFunc) af_latin2_hints_init,
- (AF_Script_ApplyHintsFunc) af_latin2_hints_apply
+ (AF_WritingSystem_InitHintsFunc) af_latin2_hints_init,
+ (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply
)
diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h
index cbfa395..9326753 100644
--- a/src/autofit/aflatin2.h
+++ b/src/autofit/aflatin2.h
@@ -2,9 +2,10 @@
/* */
/* aflatin2.h */
/* */
-/* Auto-fitter hinting routines for latin script (specification). */
+/* Auto-fitter hinting routines for latin writing system */
+/* (specification). */
/* */
-/* Copyright 2003-2007, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,9 +26,10 @@
FT_BEGIN_HEADER
- /* the latin-specific script class */
+ /* the `latin' writing system */
- AF_DECLARE_SCRIPT_CLASS( af_latin2_script_class )
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
+
/* */
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 17a6fb7..aa5b8fd 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (body). */
/* */
-/* Copyright 2003-2009, 2011-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,42 +21,36 @@
#include "afhints.h"
#include "aferrors.h"
#include "afmodule.h"
+#include "afpic.h"
+
+#include FT_INTERNAL_CALC_H
/* Initialize glyph loader. */
- FT_LOCAL_DEF( FT_Error )
- af_loader_init( AF_Module module )
+ FT_LOCAL_DEF( void )
+ af_loader_init( AF_Loader loader,
+ AF_GlyphHints hints )
{
- AF_Loader loader = module->loader;
- FT_Memory memory = module->root.library->memory;
-
-
FT_ZERO( loader );
- af_glyph_hints_init( &loader->hints, memory );
-#ifdef FT_DEBUG_AUTOFIT
- _af_debug_hints = &loader->hints;
-#endif
- return FT_GlyphLoader_New( memory, &loader->gloader );
+ loader->hints = hints;
}
/* Reset glyph loader and compute globals if necessary. */
FT_LOCAL_DEF( FT_Error )
- af_loader_reset( AF_Module module,
+ af_loader_reset( AF_Loader loader,
+ AF_Module module,
FT_Face face )
{
- FT_Error error = FT_Err_Ok;
- AF_Loader loader = module->loader;
+ FT_Error error = FT_Err_Ok;
loader->face = face;
loader->globals = (AF_FaceGlobals)face->autohint.data;
- FT_GlyphLoader_Rewind( loader->gloader );
-
if ( loader->globals == NULL )
{
error = af_face_globals_new( face, &loader->globals, module );
@@ -76,42 +70,43 @@
/* Finalize glyph loader. */
FT_LOCAL_DEF( void )
- af_loader_done( AF_Module module )
+ af_loader_done( AF_Loader loader )
{
- AF_Loader loader = module->loader;
-
-
- af_glyph_hints_done( &loader->hints );
-
loader->face = NULL;
loader->globals = NULL;
-
-#ifdef FT_DEBUG_AUTOFIT
- _af_debug_hints = NULL;
-#endif
- FT_GlyphLoader_Done( loader->gloader );
- loader->gloader = NULL;
+ loader->hints = NULL;
}
- /* Load a single glyph component. This routine calls itself */
- /* recursively, if necessary, and does the main work of */
- /* `af_loader_load_glyph.' */
+#define af_intToFixed( i ) \
+ ( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define af_fixedToInt( x ) \
+ ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define af_floatToFixed( f ) \
+ ( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
+
+
+ /* Do the main work of `af_loader_load_glyph'. Note that we never */
+ /* have to deal with composite glyphs as those get loaded into */
+ /* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function. */
+ /* In the rare cases where FT_LOAD_NO_RECURSE is set, it implies */
+ /* FT_LOAD_NO_SCALE and as such the auto-hinter is never called. */
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index,
- FT_Int32 load_flags,
- FT_UInt depth )
+ FT_Int32 load_flags )
{
+ AF_Module module = loader->globals->module;
+
FT_Error error;
FT_Face face = loader->face;
- FT_GlyphLoader gloader = loader->gloader;
- AF_ScriptMetrics metrics = loader->metrics;
- AF_GlyphHints hints = &loader->hints;
+ AF_StyleMetrics metrics = loader->metrics;
+ AF_GlyphHints hints = loader->hints;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal;
+ FT_GlyphLoader gloader = internal->loader;
FT_Int32 flags;
@@ -120,6 +115,132 @@
if ( error )
goto Exit;
+ /*
+ * Apply stem darkening (emboldening) here before hints are applied to
+ * the outline. Glyphs are scaled down proportionally to the
+ * emboldening so that curve points don't fall outside their precomputed
+ * blue zones.
+ *
+ * Any emboldening done by the font driver (e.g., the CFF driver)
+ * doesn't reach here because the autohinter loads the unprocessed
+ * glyphs in font units for analysis (functions `af_*_metrics_init_*')
+ * and then above to prepare it for the rasterizers by itself,
+ * independently of the font driver. So emboldening must be done here,
+ * within the autohinter.
+ *
+ * All glyphs to be autohinted pass through here one by one. The
+ * standard widths can therefore change from one glyph to the next,
+ * depending on what script a glyph is assigned to (each script has its
+ * own set of standard widths and other metrics). The darkening amount
+ * must therefore be recomputed for each size and
+ * `standard_{vertical,horizontal}_width' change.
+ */
+ if ( !module->no_stem_darkening )
+ {
+ AF_FaceGlobals globals = loader->globals;
+ AF_WritingSystemClass writing_system_class;
+
+ FT_Pos stdVW = 0;
+ FT_Pos stdHW = 0;
+
+ FT_Bool size_changed = face->size->metrics.x_ppem
+ != globals->stem_darkening_for_ppem;
+
+ FT_Fixed em_size = af_intToFixed( face->units_per_EM );
+ FT_Fixed em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
+
+ FT_Matrix scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
+
+
+ /* Skip stem darkening for broken fonts. */
+ if ( !face->units_per_EM )
+ goto After_Emboldening;
+
+ /*
+ * We depend on the writing system (script analyzers) to supply
+ * standard widths for the script of the glyph we are looking at. If
+ * it can't deliver, stem darkening is effectively disabled.
+ */
+ writing_system_class =
+ AF_WRITING_SYSTEM_CLASSES_GET[metrics->style_class->writing_system];
+
+ if ( writing_system_class->style_metrics_getstdw )
+ writing_system_class->style_metrics_getstdw( metrics,
+ &stdHW,
+ &stdVW );
+ else
+ goto After_Emboldening;
+
+
+ if ( size_changed ||
+ ( stdVW > 0 && stdVW != globals->standard_vertical_width ) )
+ {
+ FT_Fixed darken_by_font_units_x, darken_x;
+
+
+ darken_by_font_units_x =
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdVW ) );
+ darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
+ face->size->metrics.x_scale ),
+ em_ratio );
+
+ globals->standard_vertical_width = stdVW;
+ globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+ globals->darken_x = af_fixedToInt( darken_x );
+ }
+
+ if ( size_changed ||
+ ( stdHW > 0 && stdHW != globals->standard_horizontal_width ) )
+ {
+ FT_Fixed darken_by_font_units_y, darken_y;
+
+
+ darken_by_font_units_y =
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdHW ) );
+ darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
+ face->size->metrics.y_scale ),
+ em_ratio );
+
+ globals->standard_horizontal_width = stdHW;
+ globals->stem_darkening_for_ppem = face->size->metrics.x_ppem;
+ globals->darken_y = af_fixedToInt( darken_y );
+
+ /*
+ * Scale outlines down on the Y-axis to keep them inside their blue
+ * zones. The stronger the emboldening, the stronger the
+ * downscaling (plus heuristical padding to prevent outlines still
+ * falling out their zones due to rounding).
+ *
+ * Reason: `FT_Outline_Embolden' works by shifting the rightmost
+ * points of stems farther to the right, and topmost points farther
+ * up. This positions points on the Y-axis outside their
+ * pre-computed blue zones and leads to distortion when applying the
+ * hints in the code further below. Code outside this emboldening
+ * block doesn't know we are presenting it with modified outlines
+ * the analyzer didn't see!
+ *
+ * An unfortunate side effect of downscaling is that the emboldening
+ * effect is slightly decreased. The loss becomes more pronounced
+ * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
+ */
+ globals->scale_down_factor =
+ FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
+ em_size );
+ }
+
+ FT_Outline_EmboldenXY( &slot->outline,
+ globals->darken_x,
+ globals->darken_y );
+
+ scale_down_matrix.yy = globals->scale_down_factor;
+ FT_Outline_Transform( &slot->outline, &scale_down_matrix );
+ }
+
+ After_Emboldening:
loader->transformed = internal->glyph_transformed;
if ( loader->transformed )
{
@@ -130,8 +251,8 @@
loader->trans_delta = internal->glyph_delta;
inverse = loader->trans_matrix;
- FT_Matrix_Invert( &inverse );
- FT_Vector_Transform( &loader->trans_delta, &inverse );
+ if ( !FT_Matrix_Invert( &inverse ) )
+ FT_Vector_Transform( &loader->trans_delta, &inverse );
}
switch ( slot->format )
@@ -143,29 +264,6 @@
loader->trans_delta.x,
loader->trans_delta.y );
- /* copy the outline points in the loader's current */
- /* extra points which are used to keep original glyph coordinates */
- error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
- slot->outline.n_points + 4,
- slot->outline.n_contours );
- if ( error )
- goto Exit;
-
- FT_ARRAY_COPY( gloader->current.outline.points,
- slot->outline.points,
- slot->outline.n_points );
-
- FT_ARRAY_COPY( gloader->current.outline.contours,
- slot->outline.contours,
- slot->outline.n_contours );
-
- FT_ARRAY_COPY( gloader->current.outline.tags,
- slot->outline.tags,
- slot->outline.n_points );
-
- gloader->current.outline.n_points = slot->outline.n_points;
- gloader->current.outline.n_contours = slot->outline.n_contours;
-
/* compute original horizontal phantom points (and ignore */
/* vertical ones) */
loader->pp1.x = hints->x_delta;
@@ -180,10 +278,21 @@
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
- if ( metrics->clazz->script_hints_apply )
- metrics->clazz->script_hints_apply( hints,
- &gloader->current.outline,
- metrics );
+ {
+#ifdef FT_CONFIG_OPTION_PIC
+ AF_FaceGlobals globals = loader->globals;
+#endif
+ AF_StyleClass style_class = metrics->style_class;
+ AF_WritingSystemClass writing_system_class =
+ AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
+
+
+ if ( writing_system_class->style_hints_apply )
+ writing_system_class->style_hints_apply( glyph_index,
+ hints,
+ &gloader->base.outline,
+ metrics );
+ }
/* we now need to adjust the metrics according to the change in */
/* width/positioning that occurred during the hinting process */
@@ -256,133 +365,6 @@
slot->rsb_delta = loader->pp2.x - pp2x;
}
- /* good, we simply add the glyph to our loader's base */
- FT_GlyphLoader_Add( gloader );
- break;
-
- case FT_GLYPH_FORMAT_COMPOSITE:
- {
- FT_UInt nn, num_subglyphs = slot->num_subglyphs;
- FT_UInt num_base_subgs, start_point;
- FT_SubGlyph subglyph;
-
-
- start_point = gloader->base.outline.n_points;
-
- /* first of all, copy the subglyph descriptors in the glyph loader */
- error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
- if ( error )
- goto Exit;
-
- FT_ARRAY_COPY( gloader->current.subglyphs,
- slot->subglyphs,
- num_subglyphs );
-
- gloader->current.num_subglyphs = num_subglyphs;
- num_base_subgs = gloader->base.num_subglyphs;
-
- /* now read each subglyph independently */
- for ( nn = 0; nn < num_subglyphs; nn++ )
- {
- FT_Vector pp1, pp2;
- FT_Pos x, y;
- FT_UInt num_points, num_new_points, num_base_points;
-
-
- /* gloader.current.subglyphs can change during glyph loading due */
- /* to re-allocation -- we must recompute the current subglyph on */
- /* each iteration */
- subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
- pp1 = loader->pp1;
- pp2 = loader->pp2;
-
- num_base_points = gloader->base.outline.n_points;
-
- error = af_loader_load_g( loader, scaler, subglyph->index,
- load_flags, depth + 1 );
- if ( error )
- goto Exit;
-
- /* recompute subglyph pointer */
- subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
- if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
- {
- pp1 = loader->pp1;
- pp2 = loader->pp2;
- }
- else
- {
- loader->pp1 = pp1;
- loader->pp2 = pp2;
- }
-
- num_points = gloader->base.outline.n_points;
- num_new_points = num_points - num_base_points;
-
- /* now perform the transformation required for this subglyph */
-
- if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
- FT_SUBGLYPH_FLAG_XY_SCALE |
- FT_SUBGLYPH_FLAG_2X2 ) )
- {
- FT_Vector* cur = gloader->base.outline.points +
- num_base_points;
- FT_Vector* limit = cur + num_new_points;
-
-
- for ( ; cur < limit; cur++ )
- FT_Vector_Transform( cur, &subglyph->transform );
- }
-
- /* apply offset */
-
- if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
- {
- FT_Int k = subglyph->arg1;
- FT_UInt l = subglyph->arg2;
- FT_Vector* p1;
- FT_Vector* p2;
-
-
- if ( start_point + k >= num_base_points ||
- l >= (FT_UInt)num_new_points )
- {
- error = FT_THROW( Invalid_Composite );
- goto Exit;
- }
-
- l += num_base_points;
-
- /* for now, only use the current point coordinates; */
- /* we eventually may consider another approach */
- p1 = gloader->base.outline.points + start_point + k;
- p2 = gloader->base.outline.points + start_point + l;
-
- x = p1->x - p2->x;
- y = p1->y - p2->y;
- }
- else
- {
- x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
- y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
-
- x = FT_PIX_ROUND( x );
- y = FT_PIX_ROUND( y );
- }
-
- {
- FT_Outline dummy = gloader->base.outline;
-
-
- dummy.points += num_base_points;
- dummy.n_points = (short)num_new_points;
-
- FT_Outline_Translate( &dummy, x, y );
- }
- }
- }
break;
default:
@@ -391,7 +373,6 @@
}
Hint_Metrics:
- if ( depth == 0 )
{
FT_BBox bbox;
FT_Vector vvector;
@@ -466,18 +447,14 @@
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
- /* now copy outline into glyph slot */
- FT_GlyphLoader_Rewind( internal->loader );
- error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
- if ( error )
- goto Exit;
-
+#if 0
/* reassign all outline fields except flags to protect them */
slot->outline.n_contours = internal->loader->base.outline.n_contours;
slot->outline.n_points = internal->loader->base.outline.n_points;
slot->outline.points = internal->loader->base.outline.points;
slot->outline.tags = internal->loader->base.outline.tags;
slot->outline.contours = internal->loader->base.outline.contours;
+#endif
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
@@ -490,19 +467,19 @@
/* Load a glyph. */
FT_LOCAL_DEF( FT_Error )
- af_loader_load_glyph( AF_Module module,
+ af_loader_load_glyph( AF_Loader loader,
+ AF_Module module,
FT_Face face,
FT_UInt gindex,
FT_Int32 load_flags )
{
FT_Error error;
FT_Size size = face->size;
- AF_Loader loader = module->loader;
AF_ScalerRec scaler;
if ( !size )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Invalid_Size_Handle );
FT_ZERO( &scaler );
@@ -515,42 +492,50 @@
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0; /* XXX: fix this */
- error = af_loader_reset( module, face );
+ error = af_loader_reset( loader, module, face );
if ( !error )
{
- AF_ScriptMetrics metrics;
- FT_UInt options = 0;
+ AF_StyleMetrics metrics;
+ FT_UInt options = AF_STYLE_NONE_DFLT;
#ifdef FT_OPTION_AUTOFIT2
- /* XXX: undocumented hook to activate the latin2 hinter */
+ /* XXX: undocumented hook to activate the latin2 writing system */
if ( load_flags & ( 1UL << 20 ) )
- options = 2;
+ options = AF_STYLE_LTN2_DFLT;
#endif
error = af_face_globals_get_metrics( loader->globals, gindex,
options, &metrics );
if ( !error )
{
+#ifdef FT_CONFIG_OPTION_PIC
+ AF_FaceGlobals globals = loader->globals;
+#endif
+ AF_StyleClass style_class = metrics->style_class;
+ AF_WritingSystemClass writing_system_class =
+ AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
+
+
loader->metrics = metrics;
- if ( metrics->clazz->script_metrics_scale )
- metrics->clazz->script_metrics_scale( metrics, &scaler );
+ if ( writing_system_class->style_metrics_scale )
+ writing_system_class->style_metrics_scale( metrics, &scaler );
else
metrics->scaler = scaler;
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
- if ( metrics->clazz->script_hints_init )
+ if ( writing_system_class->style_hints_init )
{
- error = metrics->clazz->script_hints_init( &loader->hints,
- metrics );
+ error = writing_system_class->style_hints_init( loader->hints,
+ metrics );
if ( error )
goto Exit;
}
- error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
+ error = af_loader_load_g( loader, &scaler, gindex, load_flags );
}
}
Exit:
@@ -558,4 +543,134 @@
}
+ /*
+ * Compute amount of font units the face should be emboldened by, in
+ * analogy to the CFF driver's `cf2_computeDarkening' function. See there
+ * for details of the algorithm.
+ *
+ * XXX: Currently a crude adaption of the original algorithm. Do better?
+ */
+ FT_LOCAL_DEF( FT_Int32 )
+ af_loader_compute_darkening( AF_Loader loader,
+ FT_Face face,
+ FT_Pos standard_width )
+ {
+ AF_Module module = loader->globals->module;
+
+ FT_UShort units_per_EM;
+ FT_Fixed ppem, em_ratio;
+ FT_Fixed stem_width, stem_width_per_1000, scaled_stem, darken_amount;
+ FT_Int log_base_2;
+ FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
+
+
+ ppem = FT_MAX( af_intToFixed( 4 ),
+ af_intToFixed( face->size->metrics.x_ppem ) );
+ units_per_EM = face->units_per_EM;
+
+ em_ratio = FT_DivFix( af_intToFixed( 1000 ),
+ af_intToFixed ( units_per_EM ) );
+ if ( em_ratio < af_floatToFixed( .01 ) )
+ {
+ /* If something goes wrong, don't embolden. */
+ return 0;
+ }
+
+ x1 = module->darken_params[0];
+ y1 = module->darken_params[1];
+ x2 = module->darken_params[2];
+ y2 = module->darken_params[3];
+ x3 = module->darken_params[4];
+ y3 = module->darken_params[5];
+ x4 = module->darken_params[6];
+ y4 = module->darken_params[7];
+
+ if ( standard_width <= 0 )
+ {
+ stem_width = af_intToFixed( 75 ); /* taken from cf2font.c */
+ stem_width_per_1000 = stem_width;
+ }
+ else
+ {
+ stem_width = af_intToFixed( standard_width );
+ stem_width_per_1000 = FT_MulFix( stem_width, em_ratio );
+ }
+
+ log_base_2 = FT_MSB( (FT_UInt32)stem_width_per_1000 ) +
+ FT_MSB( (FT_UInt32)ppem );
+
+ if ( log_base_2 >= 46 )
+ {
+ /* possible overflow */
+ scaled_stem = af_intToFixed( x4 );
+ }
+ else
+ scaled_stem = FT_MulFix( stem_width_per_1000, ppem );
+
+ /* now apply the darkening parameters */
+ if ( scaled_stem < af_intToFixed( x1 ) )
+ darken_amount = FT_DivFix( af_intToFixed( y1 ), ppem );
+
+ else if ( scaled_stem < af_intToFixed( x2 ) )
+ {
+ FT_Int xdelta = x2 - x1;
+ FT_Int ydelta = y2 - y1;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x1 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x3;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y1 ), ppem );
+ }
+
+ else if ( scaled_stem < af_intToFixed( x3 ) )
+ {
+ Try_x3:
+ {
+ FT_Int xdelta = x3 - x2;
+ FT_Int ydelta = y3 - y2;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x2 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x4;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y2 ), ppem );
+ }
+ }
+
+ else if ( scaled_stem < af_intToFixed( x4 ) )
+ {
+ Try_x4:
+ {
+ FT_Int xdelta = x4 - x3;
+ FT_Int ydelta = y4 - y3;
+ FT_Int x = stem_width_per_1000 -
+ FT_DivFix( af_intToFixed( x3 ), ppem );
+
+
+ if ( !xdelta )
+ goto Use_y4;
+
+ darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( af_intToFixed( y3 ), ppem );
+ }
+ }
+
+ else
+ {
+ Use_y4:
+ darken_amount = FT_DivFix( af_intToFixed( y4 ), ppem );
+ }
+
+ /* Convert darken_amount from per 1000 em to true character space. */
+ return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
+ }
+
+
/* END */
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index 1f34d17..4c4affc 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (specification). */
/* */
-/* Copyright 2003-2005, 2011-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,13 +20,12 @@
#define __AFLOADER_H__
#include "afhints.h"
+#include "afmodule.h"
#include "afglobal.h"
FT_BEGIN_HEADER
- typedef struct AF_ModuleRec_* AF_Module;
-
/*
* The autofitter module's (global) data structure to communicate with
* actual fonts. If necessary, `local' data like the current face, the
@@ -42,9 +41,8 @@
AF_FaceGlobals globals;
/* current glyph data */
- FT_GlyphLoader gloader;
- AF_GlyphHintsRec hints;
- AF_ScriptMetrics metrics;
+ AF_GlyphHints hints;
+ AF_StyleMetrics metrics;
FT_Bool transformed;
FT_Matrix trans_matrix;
FT_Vector trans_delta;
@@ -55,25 +53,33 @@
} AF_LoaderRec, *AF_Loader;
- FT_LOCAL( FT_Error )
- af_loader_init( AF_Module module );
+ FT_LOCAL( void )
+ af_loader_init( AF_Loader loader,
+ AF_GlyphHints hints );
FT_LOCAL( FT_Error )
- af_loader_reset( AF_Module module,
+ af_loader_reset( AF_Loader loader,
+ AF_Module module,
FT_Face face );
FT_LOCAL( void )
- af_loader_done( AF_Module module );
+ af_loader_done( AF_Loader loader );
FT_LOCAL( FT_Error )
- af_loader_load_glyph( AF_Module module,
+ af_loader_load_glyph( AF_Loader loader,
+ AF_Module module,
FT_Face face,
FT_UInt gindex,
FT_Int32 load_flags );
+ FT_LOCAL_DEF( FT_Int32 )
+ af_loader_compute_darkening( AF_Loader loader,
+ FT_Face face,
+ FT_Pos standard_width );
+
/* */
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index b1bb5ee..45fd360 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (body). */
/* */
-/* Copyright 2003-2006, 2009, 2011-2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,10 +23,35 @@
#include "afpic.h"
#ifdef FT_DEBUG_AUTOFIT
- int _af_debug_disable_horz_hints;
- int _af_debug_disable_vert_hints;
- int _af_debug_disable_blue_hints;
- void* _af_debug_hints;
+
+#ifndef FT_MAKE_OPTION_SINGLE_OBJECT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ extern void
+ af_glyph_hints_dump_segments( AF_GlyphHints hints,
+ FT_Bool to_stdout );
+ extern void
+ af_glyph_hints_dump_points( AF_GlyphHints hints,
+ FT_Bool to_stdout );
+ extern void
+ af_glyph_hints_dump_edges( AF_GlyphHints hints,
+ FT_Bool to_stdout );
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
+ int _af_debug_disable_horz_hints;
+ int _af_debug_disable_vert_hints;
+ int _af_debug_disable_blue_hints;
+
+ /* we use a global object instead of a local one for debugging */
+ AF_GlyphHintsRec _af_debug_hints_rec[1];
+
+ void* _af_debug_hints = _af_debug_hints_rec;
#endif
#include FT_INTERNAL_OBJECTS_H
@@ -45,7 +70,7 @@
#define FT_COMPONENT trace_afmodule
- FT_Error
+ static FT_Error
af_property_get_face_globals( FT_Face face,
AF_FaceGlobals* aglobals,
AF_Module module )
@@ -55,13 +80,13 @@
if ( !face )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Invalid_Face_Handle );
globals = (AF_FaceGlobals)face->autohint.data;
if ( !globals )
{
- /* trigger computation of the global script data */
- /* in case it hasn't been done yet */
+ /* trigger computation of the global style data */
+ /* in case it hasn't been done yet */
error = af_face_globals_new( face, &globals, module );
if ( !error )
{
@@ -79,7 +104,7 @@
}
- FT_Error
+ static FT_Error
af_property_set( FT_Module ft_module,
const char* property_name,
const void* value )
@@ -92,8 +117,40 @@
{
FT_UInt* fallback_script = (FT_UInt*)value;
+ FT_UInt ss;
- module->fallback_script = *fallback_script;
+
+ /* We translate the fallback script to a fallback style that uses */
+ /* `fallback-script' as its script and `AF_COVERAGE_NONE' as its */
+ /* coverage value. */
+ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
+ {
+ AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss];
+
+
+ if ( (FT_UInt)style_class->script == *fallback_script &&
+ style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+ module->fallback_style = ss;
+ break;
+ }
+ }
+
+ if ( !AF_STYLE_CLASSES_GET[ss] )
+ {
+ FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n",
+ fallback_script, property_name ));
+ return FT_THROW( Invalid_Argument );
+ }
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "default-script" ) )
+ {
+ FT_UInt* default_script = (FT_UInt*)value;
+
+
+ module->default_script = *default_script;
return error;
}
@@ -109,6 +166,57 @@
return error;
}
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ else if ( !ft_strcmp( property_name, "warping" ) )
+ {
+ FT_Bool* warping = (FT_Bool*)value;
+
+
+ module->warping = *warping;
+
+ return error;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+ else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = (FT_Int*)value;
+
+ FT_Int x1 = darken_params[0];
+ FT_Int y1 = darken_params[1];
+ FT_Int x2 = darken_params[2];
+ FT_Int y2 = darken_params[3];
+ FT_Int x3 = darken_params[4];
+ FT_Int y3 = darken_params[5];
+ FT_Int x4 = darken_params[6];
+ FT_Int y4 = darken_params[7];
+
+
+ if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
+ y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
+ x1 > x2 || x2 > x3 || x3 > x4 ||
+ y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+ return FT_THROW( Invalid_Argument );
+
+ module->darken_params[0] = x1;
+ module->darken_params[1] = y1;
+ module->darken_params[2] = x2;
+ module->darken_params[3] = y2;
+ module->darken_params[4] = x3;
+ module->darken_params[5] = y3;
+ module->darken_params[6] = x4;
+ module->darken_params[7] = y4;
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+ FT_Bool* no_stem_darkening = (FT_Bool*)value;
+
+
+ module->no_stem_darkening = *no_stem_darkening;
+
+ return error;
+ }
FT_TRACE0(( "af_property_set: missing property `%s'\n",
property_name ));
@@ -116,14 +224,18 @@
}
- FT_Error
+ static FT_Error
af_property_get( FT_Module ft_module,
const char* property_name,
void* value )
{
- FT_Error error = FT_Err_Ok;
- AF_Module module = (AF_Module)ft_module;
- FT_UInt fallback_script = module->fallback_script;
+ FT_Error error = FT_Err_Ok;
+ AF_Module module = (AF_Module)ft_module;
+ FT_UInt fallback_style = module->fallback_style;
+ FT_UInt default_script = module->default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_Bool warping = module->warping;
+#endif
if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
@@ -134,7 +246,7 @@
error = af_property_get_face_globals( prop->face, &globals, module );
if ( !error )
- prop->map = globals->glyph_scripts;
+ prop->map = globals->glyph_styles;
return error;
}
@@ -142,8 +254,19 @@
{
FT_UInt* val = (FT_UInt*)value;
+ AF_StyleClass style_class = AF_STYLE_CLASSES_GET[fallback_style];
- *val = fallback_script;
+
+ *val = style_class->script;
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "default-script" ) )
+ {
+ FT_UInt* val = (FT_UInt*)value;
+
+
+ *val = default_script;
return error;
}
@@ -159,8 +282,45 @@
return error;
}
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ else if ( !ft_strcmp( property_name, "warping" ) )
+ {
+ FT_Bool* val = (FT_Bool*)value;
+ *val = warping;
+
+ return error;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+ else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = module->darken_params;
+ FT_Int* val = (FT_Int*)value;
+
+
+ val[0] = darken_params[0];
+ val[1] = darken_params[1];
+ val[2] = darken_params[2];
+ val[3] = darken_params[3];
+ val[4] = darken_params[4];
+ val[5] = darken_params[5];
+ val[6] = darken_params[6];
+ val[7] = darken_params[7];
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+ {
+ FT_Bool no_stem_darkening = module->no_stem_darkening;
+ FT_Bool* val = (FT_Bool*)value;
+
+
+ *val = no_stem_darkening;
+
+ return error;
+ }
+
FT_TRACE0(( "af_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
@@ -169,8 +329,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
af_service_properties,
- (FT_Properties_SetFunc)af_property_set,
- (FT_Properties_GetFunc)af_property_get )
+ (FT_Properties_SetFunc)af_property_set, /* set_property */
+ (FT_Properties_GetFunc)af_property_get ) /* get_property */
FT_DEFINE_SERVICEDESCREC1(
@@ -182,7 +342,7 @@
af_get_interface( FT_Module module,
const char* module_interface )
{
- /* AF_SERVICES_GET derefers `library' in PIC mode */
+ /* AF_SERVICES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
FT_Library library;
@@ -206,19 +366,35 @@
AF_Module module = (AF_Module)ft_module;
- module->fallback_script = AF_SCRIPT_FALLBACK;
+ module->fallback_style = AF_STYLE_FALLBACK;
+ module->default_script = AF_SCRIPT_DEFAULT;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ module->warping = 0;
+#endif
+ module->no_stem_darkening = TRUE;
- return af_loader_init( module );
+ module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+ module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+ module->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+ module->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+ module->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+ module->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+ module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+ module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
+
+ return FT_Err_Ok;
}
FT_CALLBACK_DEF( void )
af_autofitter_done( FT_Module ft_module ) /* AF_Module */
{
- AF_Module module = (AF_Module)ft_module;
+ FT_UNUSED( ft_module );
-
- af_loader_done( module );
+#ifdef FT_DEBUG_AUTOFIT
+ if ( _af_debug_hints_rec->memory )
+ af_glyph_hints_done( _af_debug_hints_rec );
+#endif
}
@@ -229,10 +405,56 @@
FT_UInt glyph_index,
FT_Int32 load_flags )
{
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = module->root.library->memory;
+
+#ifdef FT_DEBUG_AUTOFIT
+
+ /* in debug mode, we use a global object that survives this routine */
+
+ AF_GlyphHints hints = _af_debug_hints_rec;
+ AF_LoaderRec loader[1];
+
FT_UNUSED( size );
- return af_loader_load_glyph( module, slot->face,
- glyph_index, load_flags );
+
+ if ( hints->memory )
+ af_glyph_hints_done( hints );
+
+ af_glyph_hints_init( hints, memory );
+ af_loader_init( loader, hints );
+
+ error = af_loader_load_glyph( loader, module, slot->face,
+ glyph_index, load_flags );
+
+ af_glyph_hints_dump_points( hints, 0 );
+ af_glyph_hints_dump_segments( hints, 0 );
+ af_glyph_hints_dump_edges( hints, 0 );
+
+ af_loader_done( loader );
+
+ return error;
+
+#else /* !FT_DEBUG_AUTOFIT */
+
+ AF_GlyphHintsRec hints[1];
+ AF_LoaderRec loader[1];
+
+ FT_UNUSED( size );
+
+
+ af_glyph_hints_init( hints, memory );
+ af_loader_init( loader, hints );
+
+ error = af_loader_load_glyph( loader, module, slot->face,
+ glyph_index, load_flags );
+
+ af_loader_done( loader );
+ af_glyph_hints_done( hints );
+
+ return error;
+
+#endif /* !FT_DEBUG_AUTOFIT */
}
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index c4e8f8f..3c61d89 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (specification). */
/* */
-/* Copyright 2003, 2004, 2005 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,31 +23,31 @@
#include FT_INTERNAL_OBJECTS_H
#include FT_MODULE_H
-#include "afloader.h"
-
FT_BEGIN_HEADER
/*
- * This is the `extended' FT_Module structure which holds the
- * autofitter's global data. Right before hinting a glyph, the data
- * specific to the glyph's face (blue zones, stem widths, etc.) are
- * loaded into `loader' (see function `af_loader_reset').
+ * This is the `extended' FT_Module structure that holds the
+ * autofitter's global data.
*/
typedef struct AF_ModuleRec_
{
FT_ModuleRec root;
- FT_UInt fallback_script;
+ FT_UInt fallback_style;
+ FT_UInt default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_Bool warping;
+#endif
+ FT_Bool no_stem_darkening;
+ FT_Int darken_params[8];
- AF_LoaderRec loader[1];
-
- } AF_ModuleRec;
+ } AF_ModuleRec, *AF_Module;
-FT_DECLARE_MODULE(autofit_module_class)
+FT_DECLARE_MODULE( autofit_module_class )
FT_END_HEADER
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 45e1448..37254a2 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009-2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,6 +20,7 @@
#include FT_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "afpic.h"
+#include "afglobal.h"
#include "aferrors.h"
@@ -42,14 +43,11 @@
FT_AutoHinter_InterfaceRec* clazz );
- /* forward declaration of PIC init functions from script classes */
-#include "aflatin.h"
-#ifdef FT_OPTION_AUTOFIT2
-#include "aflatin2.h"
-#endif
-#include "afcjk.h"
-#include "afdummy.h"
-#include "afindic.h"
+ /* forward declaration of PIC init functions from writing system classes */
+#undef WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS ) /* empty */
+
+#include "afwrtsys.h"
void
@@ -100,27 +98,44 @@
FT_Init_Class_af_service_properties( &container->af_service_properties );
- for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
- {
+ for ( ss = 0; ss < AF_WRITING_SYSTEM_MAX; ss++ )
+ container->af_writing_system_classes[ss] =
+ &container->af_writing_system_classes_rec[ss];
+ container->af_writing_system_classes[AF_WRITING_SYSTEM_MAX] = NULL;
+
+ for ( ss = 0; ss < AF_SCRIPT_MAX; ss++ )
container->af_script_classes[ss] =
&container->af_script_classes_rec[ss];
- }
- container->af_script_classes[AF_SCRIPT_CLASSES_COUNT - 1] = NULL;
+ container->af_script_classes[AF_SCRIPT_MAX] = NULL;
- /* add call to initialization function when you add new scripts */
+ for ( ss = 0; ss < AF_STYLE_MAX; ss++ )
+ container->af_style_classes[ss] =
+ &container->af_style_classes_rec[ss];
+ container->af_style_classes[AF_STYLE_MAX] = NULL;
+
+#undef WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS ) \
+ FT_Init_Class_af_ ## ws ## _writing_system_class( \
+ &container->af_writing_system_classes_rec[ss++] );
+
ss = 0;
- FT_Init_Class_af_dummy_script_class(
- &container->af_script_classes_rec[ss++] );
-#ifdef FT_OPTION_AUTOFIT2
- FT_Init_Class_af_latin2_script_class(
- &container->af_script_classes_rec[ss++] );
-#endif
- FT_Init_Class_af_latin_script_class(
- &container->af_script_classes_rec[ss++] );
- FT_Init_Class_af_cjk_script_class(
- &container->af_script_classes_rec[ss++] );
- FT_Init_Class_af_indic_script_class(
- &container->af_script_classes_rec[ss++] );
+#include "afwrtsys.h"
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, sss ) \
+ FT_Init_Class_af_ ## s ## _script_class( \
+ &container->af_script_classes_rec[ss++] );
+
+ ss = 0;
+#include "afscript.h"
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, bss, c ) \
+ FT_Init_Class_af_ ## s ## _style_class( \
+ &container->af_style_classes_rec[ss++] );
+
+ ss = 0;
+#include "afstyles.h"
FT_Init_Class_af_autofitter_interface(
library, &container->af_autofitter_interface );
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 0acf803..9b45069 100644
--- a/src/autofit/afpic.h
+++ b/src/autofit/afpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009, 2011-2012 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,18 +20,18 @@
#define __AFPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
#ifndef FT_CONFIG_OPTION_PIC
-#define AF_SERVICES_GET af_services
-#define AF_SERVICE_PROPERTIES_GET af_service_properties
+#define AF_SERVICES_GET af_services
+#define AF_SERVICE_PROPERTIES_GET af_service_properties
-#define AF_SCRIPT_CLASSES_GET af_script_classes
-#define AF_INTERFACE_GET af_autofitter_interface
+#define AF_WRITING_SYSTEM_CLASSES_GET af_writing_system_classes
+#define AF_SCRIPT_CLASSES_GET af_script_classes
+#define AF_STYLE_CLASSES_GET af_style_classes
+#define AF_INTERFACE_GET af_autofitter_interface
#else /* FT_CONFIG_OPTION_PIC */
@@ -40,24 +40,29 @@
#include "aftypes.h"
- /* increase these when you add new scripts, */
- /* and update autofit_module_class_pic_init */
-#ifdef FT_OPTION_AUTOFIT2
-#define AF_SCRIPT_CLASSES_COUNT 6
-#else
-#define AF_SCRIPT_CLASSES_COUNT 5
-#endif
-#define AF_SCRIPT_CLASSES_REC_COUNT ( AF_SCRIPT_CLASSES_COUNT - 1 )
-
+FT_BEGIN_HEADER
typedef struct AFModulePIC_
{
FT_ServiceDescRec* af_services;
FT_Service_PropertiesRec af_service_properties;
- AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
- AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
+ AF_WritingSystemClass af_writing_system_classes
+ [AF_WRITING_SYSTEM_MAX + 1];
+ AF_WritingSystemClassRec af_writing_system_classes_rec
+ [AF_WRITING_SYSTEM_MAX];
+
+ AF_ScriptClass af_script_classes
+ [AF_SCRIPT_MAX + 1];
+ AF_ScriptClassRec af_script_classes_rec
+ [AF_SCRIPT_MAX];
+
+ AF_StyleClass af_style_classes
+ [AF_STYLE_MAX + 1];
+ AF_StyleClassRec af_style_classes_rec
+ [AF_STYLE_MAX];
+
FT_AutoHinter_InterfaceRec af_autofitter_interface;
} AFModulePIC;
@@ -71,8 +76,12 @@
#define AF_SERVICE_PROPERTIES_GET \
( GET_PIC( library )->af_service_properties )
+#define AF_WRITING_SYSTEM_CLASSES_GET \
+ ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_writing_system_classes )
#define AF_SCRIPT_CLASSES_GET \
( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_script_classes )
+#define AF_STYLE_CLASSES_GET \
+ ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_style_classes )
#define AF_INTERFACE_GET \
( GET_PIC( library )->af_autofitter_interface )
@@ -84,12 +93,12 @@
FT_Error
autofit_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __AFPIC_H__ */
diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c
new file mode 100644
index 0000000..cf8bb7c
--- /dev/null
+++ b/src/autofit/afranges.c
@@ -0,0 +1,639 @@
+/***************************************************************************/
+/* */
+/* afranges.c */
+/* */
+/* Auto-fitter Unicode script ranges (body). */
+/* */
+/* Copyright 2013-2015 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 "afranges.h"
+
+ /*
+ * The algorithm for assigning properties and styles to the `glyph_styles'
+ * array is as follows (cf. the implementation in
+ * `af_face_globals_compute_style_coverage').
+ *
+ * Walk over all scripts (as listed in `afscript.h').
+ *
+ * For a given script, walk over all styles (as listed in `afstyles.h').
+ * The order of styles is important and should be as follows.
+ *
+ * - First come styles based on OpenType features (small caps, for
+ * example). Since features rely on glyph indices, thus completely
+ * bypassing character codes, no properties are assigned.
+ *
+ * - Next comes the default style, using the character ranges as defined
+ * below. This also assigns properties.
+ *
+ * Note that there also exist fallback scripts, mainly covering
+ * superscript and subscript glyphs of a script that are not present as
+ * OpenType features. Fallback scripts are defined below, also
+ * assigning properties; they are applied after the corresponding
+ * script.
+ *
+ */
+
+
+ /* XXX Check base character ranges again: */
+ /* Right now, they are quickly derived by visual inspection. */
+ /* I can imagine that fine-tuning is necessary. */
+
+ /* for the auto-hinter, a `non-base character' is something that should */
+ /* not be affected by blue zones, regardless of whether this is a */
+ /* spacing or no-spacing glyph */
+
+ /* the `ta_xxxx_nonbase_uniranges' ranges must be strict subsets */
+ /* of the corresponding `ta_xxxx_uniranges' ranges */
+
+
+ const AF_Script_UniRangeRec af_arab_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0600UL, 0x06FFUL ), /* Arabic */
+ AF_UNIRANGE_REC( 0x0750UL, 0x07FFUL ), /* Arabic Supplement */
+ AF_UNIRANGE_REC( 0x08A0UL, 0x08FFUL ), /* Arabic Extended-A */
+ AF_UNIRANGE_REC( 0xFB50UL, 0xFDFFUL ), /* Arabic Presentation Forms-A */
+ AF_UNIRANGE_REC( 0xFE70UL, 0xFEFFUL ), /* Arabic Presentation Forms-B */
+ AF_UNIRANGE_REC( 0x1EE00UL, 0x1EEFFUL ), /* Arabic Mathematical Alphabetic Symbols */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_arab_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0600UL, 0x0605UL ),
+ AF_UNIRANGE_REC( 0x0610UL, 0x061AUL ),
+ AF_UNIRANGE_REC( 0x064BUL, 0x065FUL ),
+ AF_UNIRANGE_REC( 0x0670UL, 0x0670UL ),
+ AF_UNIRANGE_REC( 0x06D6UL, 0x06DCUL ),
+ AF_UNIRANGE_REC( 0x06DFUL, 0x06E4UL ),
+ AF_UNIRANGE_REC( 0x06E7UL, 0x06E8UL ),
+ AF_UNIRANGE_REC( 0x06EAUL, 0x06EDUL ),
+ AF_UNIRANGE_REC( 0x08E3UL, 0x08FFUL ),
+ AF_UNIRANGE_REC( 0xFBB2UL, 0xFBC1UL ),
+ AF_UNIRANGE_REC( 0xFE70UL, 0xFE70UL ),
+ AF_UNIRANGE_REC( 0xFE72UL, 0xFE72UL ),
+ AF_UNIRANGE_REC( 0xFE74UL, 0xFE74UL ),
+ AF_UNIRANGE_REC( 0xFE76UL, 0xFE76UL ),
+ AF_UNIRANGE_REC( 0xFE78UL, 0xFE78UL ),
+ AF_UNIRANGE_REC( 0xFE7AUL, 0xFE7AUL ),
+ AF_UNIRANGE_REC( 0xFE7CUL, 0xFE7CUL ),
+ AF_UNIRANGE_REC( 0xFE7EUL, 0xFE7EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_cyrl_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0400UL, 0x04FFUL ), /* Cyrillic */
+ AF_UNIRANGE_REC( 0x0500UL, 0x052FUL ), /* Cyrillic Supplement */
+ AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ), /* Cyrillic Extended-A */
+ AF_UNIRANGE_REC( 0xA640UL, 0xA69FUL ), /* Cyrillic Extended-B */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_cyrl_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0483UL, 0x0489UL ),
+ AF_UNIRANGE_REC( 0x2DE0UL, 0x2DFFUL ),
+ AF_UNIRANGE_REC( 0xA66FUL, 0xA67FUL ),
+ AF_UNIRANGE_REC( 0xA69EUL, 0xA69FUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ /* There are some characters in the Devanagari Unicode block that are */
+ /* generic to Indic scripts; we omit them so that their presence doesn't */
+ /* trigger Devanagari. */
+
+ const AF_Script_UniRangeRec af_deva_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0900UL, 0x093BUL ), /* Devanagari */
+ /* omitting U+093C nukta */
+ AF_UNIRANGE_REC( 0x093DUL, 0x0950UL ), /* ... continued */
+ /* omitting U+0951 udatta, U+0952 anudatta */
+ AF_UNIRANGE_REC( 0x0953UL, 0x0963UL ), /* ... continued */
+ /* omitting U+0964 danda, U+0965 double danda */
+ AF_UNIRANGE_REC( 0x0966UL, 0x097FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x20B9UL, 0x20B9UL ), /* (new) Rupee sign */
+ AF_UNIRANGE_REC( 0xA8E0UL, 0xA8FFUL ), /* Devanagari Extended */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_deva_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0900UL, 0x0902UL ),
+ AF_UNIRANGE_REC( 0x093AUL, 0x093AUL ),
+ AF_UNIRANGE_REC( 0x0941UL, 0x0948UL ),
+ AF_UNIRANGE_REC( 0x094DUL, 0x094DUL ),
+ AF_UNIRANGE_REC( 0x0953UL, 0x0957UL ),
+ AF_UNIRANGE_REC( 0x0962UL, 0x0963UL ),
+ AF_UNIRANGE_REC( 0xA8E0UL, 0xA8F1UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_grek_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0370UL, 0x03FFUL ), /* Greek and Coptic */
+ AF_UNIRANGE_REC( 0x1F00UL, 0x1FFFUL ), /* Greek Extended */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_grek_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x037AUL, 0x037AUL ),
+ AF_UNIRANGE_REC( 0x0384UL, 0x0385UL ),
+ AF_UNIRANGE_REC( 0x1FBDUL, 0x1FC1UL ),
+ AF_UNIRANGE_REC( 0x1FCDUL, 0x1FCFUL ),
+ AF_UNIRANGE_REC( 0x1FDDUL, 0x1FDFUL ),
+ AF_UNIRANGE_REC( 0x1FEDUL, 0x1FEFUL ),
+ AF_UNIRANGE_REC( 0x1FFDUL, 0x1FFEUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_hebr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0590UL, 0x05FFUL ), /* Hebrew */
+ AF_UNIRANGE_REC( 0xFB1DUL, 0xFB4FUL ), /* Alphab. Present. Forms (Hebrew) */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_hebr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0591UL, 0x05BFUL ),
+ AF_UNIRANGE_REC( 0x05C1UL, 0x05C2UL ),
+ AF_UNIRANGE_REC( 0x05C4UL, 0x05C5UL ),
+ AF_UNIRANGE_REC( 0x05C7UL, 0x05C7UL ),
+ AF_UNIRANGE_REC( 0xFB1EUL, 0xFB1EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_khmr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1780UL, 0x17FFUL ), /* Khmer */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_khmr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x17B7UL, 0x17BDUL ),
+ AF_UNIRANGE_REC( 0x17C6UL, 0x17C6UL ),
+ AF_UNIRANGE_REC( 0x17C9UL, 0x17D3UL ),
+ AF_UNIRANGE_REC( 0x17DDUL, 0x17DDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_khms_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x19E0UL, 0x19FFUL ), /* Khmer Symbols */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_khms_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_lao_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0E80UL, 0x0EFFUL ), /* Lao */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_lao_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0EB1UL, 0x0EB1UL ),
+ AF_UNIRANGE_REC( 0x0EB4UL, 0x0EBCUL ),
+ AF_UNIRANGE_REC( 0x0EC8UL, 0x0ECDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_latn_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0020UL, 0x007FUL ), /* Basic Latin (no control chars) */
+ AF_UNIRANGE_REC( 0x00A0UL, 0x00A9UL ), /* Latin-1 Supplement (no control chars) */
+ AF_UNIRANGE_REC( 0x00ABUL, 0x00B1UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x00B4UL, 0x00B8UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x00BBUL, 0x00FFUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x0100UL, 0x017FUL ), /* Latin Extended-A */
+ AF_UNIRANGE_REC( 0x0180UL, 0x024FUL ), /* Latin Extended-B */
+ AF_UNIRANGE_REC( 0x0250UL, 0x02AFUL ), /* IPA Extensions */
+ AF_UNIRANGE_REC( 0x02B9UL, 0x02DFUL ), /* Spacing Modifier Letters */
+ AF_UNIRANGE_REC( 0x02E5UL, 0x02FFUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ), /* Combining Diacritical Marks */
+ AF_UNIRANGE_REC( 0x1AB0UL, 0x1ABEUL ), /* Combining Diacritical Marks Extended */
+ AF_UNIRANGE_REC( 0x1D00UL, 0x1D2BUL ), /* Phonetic Extensions */
+ AF_UNIRANGE_REC( 0x1D6BUL, 0x1D77UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x1D79UL, 0x1D7FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x1D80UL, 0x1D9AUL ), /* Phonetic Extensions Supplement */
+ AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ), /* Combining Diacritical Marks Supplement */
+ AF_UNIRANGE_REC( 0x1E00UL, 0x1EFFUL ), /* Latin Extended Additional */
+ AF_UNIRANGE_REC( 0x2000UL, 0x206FUL ), /* General Punctuation */
+ AF_UNIRANGE_REC( 0x20A0UL, 0x20B8UL ), /* Currency Symbols ... */
+ AF_UNIRANGE_REC( 0x20BAUL, 0x20CFUL ), /* ... except new Rupee sign */
+ AF_UNIRANGE_REC( 0x2150UL, 0x218FUL ), /* Number Forms */
+ AF_UNIRANGE_REC( 0x2C60UL, 0x2C7BUL ), /* Latin Extended-C */
+ AF_UNIRANGE_REC( 0x2C7EUL, 0x2C7FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0x2E00UL, 0x2E7FUL ), /* Supplemental Punctuation */
+ AF_UNIRANGE_REC( 0xA720UL, 0xA76FUL ), /* Latin Extended-D */
+ AF_UNIRANGE_REC( 0xA771UL, 0xA7F7UL ), /* ... continued */
+ AF_UNIRANGE_REC( 0xA7FAUL, 0xA7FFUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0xAB30UL, 0xAB5BUL ), /* Latin Extended-E */
+ AF_UNIRANGE_REC( 0xAB60UL, 0xAB6FUL ), /* ... continued */
+ AF_UNIRANGE_REC( 0xFB00UL, 0xFB06UL ), /* Alphab. Present. Forms (Latin Ligs) */
+ AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ), /* Mathematical Alphanumeric Symbols */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latn_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x005EUL, 0x0060UL ),
+ AF_UNIRANGE_REC( 0x007EUL, 0x007EUL ),
+ AF_UNIRANGE_REC( 0x00A8UL, 0x00A9UL ),
+ AF_UNIRANGE_REC( 0x00AEUL, 0x00B0UL ),
+ AF_UNIRANGE_REC( 0x00B4UL, 0x00B4UL ),
+ AF_UNIRANGE_REC( 0x00B8UL, 0x00B8UL ),
+ AF_UNIRANGE_REC( 0x00BCUL, 0x00BEUL ),
+ AF_UNIRANGE_REC( 0x02B9UL, 0x02DFUL ),
+ AF_UNIRANGE_REC( 0x02E5UL, 0x02FFUL ),
+ AF_UNIRANGE_REC( 0x0300UL, 0x036FUL ),
+ AF_UNIRANGE_REC( 0x1AB0UL, 0x1ABEUL ),
+ AF_UNIRANGE_REC( 0x1DC0UL, 0x1DFFUL ),
+ AF_UNIRANGE_REC( 0x2017UL, 0x2017UL ),
+ AF_UNIRANGE_REC( 0x203EUL, 0x203EUL ),
+ AF_UNIRANGE_REC( 0xA788UL, 0xA788UL ),
+ AF_UNIRANGE_REC( 0xA7F8UL, 0xA7FAUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_latb_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1D62UL, 0x1D6AUL ), /* some small subscript letters */
+ AF_UNIRANGE_REC( 0x2080UL, 0x209CUL ), /* subscript digits and letters */
+ AF_UNIRANGE_REC( 0x2C7CUL, 0x2C7CUL ), /* latin subscript small letter j */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latb_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_latp_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x00AAUL, 0x00AAUL ), /* feminine ordinal indicator */
+ AF_UNIRANGE_REC( 0x00B2UL, 0x00B3UL ), /* superscript two and three */
+ AF_UNIRANGE_REC( 0x00B9UL, 0x00BAUL ), /* superscript one, masc. ord. indic. */
+ AF_UNIRANGE_REC( 0x02B0UL, 0x02B8UL ), /* some latin superscript mod. letters */
+ AF_UNIRANGE_REC( 0x02E0UL, 0x02E4UL ), /* some IPA modifier letters */
+ AF_UNIRANGE_REC( 0x1D2CUL, 0x1D61UL ), /* latin superscript modifier letters */
+ AF_UNIRANGE_REC( 0x1D78UL, 0x1D78UL ), /* modifier letter cyrillic en */
+ AF_UNIRANGE_REC( 0x1D9BUL, 0x1DBFUL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0x2070UL, 0x207FUL ), /* superscript digits and letters */
+ AF_UNIRANGE_REC( 0x2C7DUL, 0x2C7DUL ), /* modifier letter capital v */
+ AF_UNIRANGE_REC( 0xA770UL, 0xA770UL ), /* modifier letter us */
+ AF_UNIRANGE_REC( 0xA7F8UL, 0xA7F9UL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0xAB5CUL, 0xAB5FUL ), /* more modifier letters */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_latp_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_mymr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1000UL, 0x109FUL ), /* Myanmar */
+ AF_UNIRANGE_REC( 0xA9E0UL, 0xA9FFUL ), /* Myanmar Extended-B */
+ AF_UNIRANGE_REC( 0xAA60UL, 0xAA7FUL ), /* Myanmar Extended-A */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_mymr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x102DUL, 0x1030UL ),
+ AF_UNIRANGE_REC( 0x1032UL, 0x1037UL ),
+ AF_UNIRANGE_REC( 0x103AUL, 0x103AUL ),
+ AF_UNIRANGE_REC( 0x103DUL, 0x103EUL ),
+ AF_UNIRANGE_REC( 0x1058UL, 0x1059UL ),
+ AF_UNIRANGE_REC( 0x105EUL, 0x1060UL ),
+ AF_UNIRANGE_REC( 0x1071UL, 0x1074UL ),
+ AF_UNIRANGE_REC( 0x1082UL, 0x1082UL ),
+ AF_UNIRANGE_REC( 0x1085UL, 0x1086UL ),
+ AF_UNIRANGE_REC( 0x108DUL, 0x108DUL ),
+ AF_UNIRANGE_REC( 0xA9E5UL, 0xA9E5UL ),
+ AF_UNIRANGE_REC( 0xAA7CUL, 0xAA7CUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_none_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_none_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_telu_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C00UL, 0x0C7FUL ), /* Telugu */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_telu_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C00UL, 0x0C00UL ),
+ AF_UNIRANGE_REC( 0x0C3EUL, 0x0C40UL ),
+ AF_UNIRANGE_REC( 0x0C46UL, 0x0C56UL ),
+ AF_UNIRANGE_REC( 0x0C62UL, 0x0C63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_thai_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0E00UL, 0x0E7FUL ), /* Thai */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_thai_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0E31UL, 0x0E31UL ),
+ AF_UNIRANGE_REC( 0x0E34UL, 0x0E3AUL ),
+ AF_UNIRANGE_REC( 0x0E47UL, 0x0E4EUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+ const AF_Script_UniRangeRec af_beng_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0980UL, 0x09FFUL ), /* Bengali */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_beng_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0981UL, 0x0981UL ),
+ AF_UNIRANGE_REC( 0x09BCUL, 0x09BCUL ),
+ AF_UNIRANGE_REC( 0x09C1UL, 0x09C4UL ),
+ AF_UNIRANGE_REC( 0x09CDUL, 0x09CDUL ),
+ AF_UNIRANGE_REC( 0x09E2UL, 0x09E3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_gujr_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A80UL, 0x0AFFUL ), /* Gujarati */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_gujr_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A81UL, 0x0A82UL ),
+ AF_UNIRANGE_REC( 0x0ABCUL, 0x0ABCUL ),
+ AF_UNIRANGE_REC( 0x0AC1UL, 0x0AC8UL ),
+ AF_UNIRANGE_REC( 0x0ACDUL, 0x0ACDUL ),
+ AF_UNIRANGE_REC( 0x0AE2UL, 0x0AE3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_guru_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A00UL, 0x0A7FUL ), /* Gurmukhi */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_guru_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0A01UL, 0x0A02UL ),
+ AF_UNIRANGE_REC( 0x0A3CUL, 0x0A3EUL ),
+ AF_UNIRANGE_REC( 0x0A41UL, 0x0A51UL ),
+ AF_UNIRANGE_REC( 0x0A70UL, 0x0A71UL ),
+ AF_UNIRANGE_REC( 0x0A75UL, 0x0A75UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_knda_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C80UL, 0x0CFFUL ), /* Kannada */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_knda_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0C81UL, 0x0C81UL ),
+ AF_UNIRANGE_REC( 0x0CBCUL, 0x0CBCUL ),
+ AF_UNIRANGE_REC( 0x0CBFUL, 0x0CBFUL ),
+ AF_UNIRANGE_REC( 0x0CC6UL, 0x0CC6UL ),
+ AF_UNIRANGE_REC( 0x0CCCUL, 0x0CCDUL ),
+ AF_UNIRANGE_REC( 0x0CE2UL, 0x0CE3UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_limb_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1900UL, 0x194FUL ), /* Limbu */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_limb_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1920UL, 0x1922UL ),
+ AF_UNIRANGE_REC( 0x1927UL, 0x1934UL ),
+ AF_UNIRANGE_REC( 0x1937UL, 0x193BUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_mlym_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0D00UL, 0x0D7FUL ), /* Malayalam */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_mlym_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0D01UL, 0x0D01UL ),
+ AF_UNIRANGE_REC( 0x0D4DUL, 0x0D4EUL ),
+ AF_UNIRANGE_REC( 0x0D62UL, 0x0D63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_orya_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B00UL, 0x0B7FUL ), /* Oriya */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_orya_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B01UL, 0x0B02UL ),
+ AF_UNIRANGE_REC( 0x0B3CUL, 0x0B3CUL ),
+ AF_UNIRANGE_REC( 0x0B3FUL, 0x0B3FUL ),
+ AF_UNIRANGE_REC( 0x0B41UL, 0x0B44UL ),
+ AF_UNIRANGE_REC( 0x0B4DUL, 0x0B56UL ),
+ AF_UNIRANGE_REC( 0x0B62UL, 0x0B63UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_sinh_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0D80UL, 0x0DFFUL ), /* Sinhala */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_sinh_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0DCAUL, 0x0DCAUL ),
+ AF_UNIRANGE_REC( 0x0DD2UL, 0x0DD6UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_sund_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL ), /* Sundanese */
+ AF_UNIRANGE_REC( 0x1CC0UL, 0x1CCFUL ), /* Sundanese Supplement */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_sund_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1B80UL, 0x1B82UL ),
+ AF_UNIRANGE_REC( 0x1BA1UL, 0x1BADUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_sylo_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL ), /* Syloti Nagri */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_sylo_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0xA802UL, 0xA802UL ),
+ AF_UNIRANGE_REC( 0xA806UL, 0xA806UL ),
+ AF_UNIRANGE_REC( 0xA80BUL, 0xA80BUL ),
+ AF_UNIRANGE_REC( 0xA825UL, 0xA826UL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_taml_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B80UL, 0x0BFFUL ), /* Tamil */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_taml_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0B82UL, 0x0B82UL ),
+ AF_UNIRANGE_REC( 0x0BC0UL, 0x0BC2UL ),
+ AF_UNIRANGE_REC( 0x0BCDUL, 0x0BCDUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+
+ const AF_Script_UniRangeRec af_tibt_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL ), /* Tibetan */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_tibt_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x0F18UL, 0x0F19UL ),
+ AF_UNIRANGE_REC( 0x0F35UL, 0x0F35UL ),
+ AF_UNIRANGE_REC( 0x0F37UL, 0x0F37UL ),
+ AF_UNIRANGE_REC( 0x0F39UL, 0x0F39UL ),
+ AF_UNIRANGE_REC( 0x0F3EUL, 0x0F3FUL ),
+ AF_UNIRANGE_REC( 0x0F71UL, 0x0F7EUL ),
+ AF_UNIRANGE_REC( 0x0F80UL, 0x0F84UL ),
+ AF_UNIRANGE_REC( 0x0F86UL, 0x0F87UL ),
+ AF_UNIRANGE_REC( 0x0F8DUL, 0x0FBCUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+#endif /* !AF_CONFIG_OPTION_INDIC */
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+ /* this corresponds to Unicode 6.0 */
+
+ const AF_Script_UniRangeRec af_hani_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo */
+ AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */
+ AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */
+ AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */
+ AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */
+ AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */
+ AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */
+ AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */
+ AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */
+ AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */
+ AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */
+ AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */
+ AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */
+ AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */
+ AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */
+ AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */
+ AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */
+ AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */
+ AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */
+ AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */
+ AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */
+ AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */
+ AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */
+ AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */
+ AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */
+ AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */
+ AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */
+ AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */
+ AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */
+ AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+ const AF_Script_UniRangeRec af_hani_nonbase_uniranges[] =
+ {
+ AF_UNIRANGE_REC( 0x302AUL, 0x302FUL ),
+ AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ),
+ AF_UNIRANGE_REC( 0UL, 0UL )
+ };
+
+#endif /* !AF_CONFIG_OPTION_CJK */
+
+/* END */
diff --git a/src/autofit/afranges.h b/src/autofit/afranges.h
new file mode 100644
index 0000000..bca5084
--- /dev/null
+++ b/src/autofit/afranges.h
@@ -0,0 +1,47 @@
+/***************************************************************************/
+/* */
+/* afranges.h */
+/* */
+/* Auto-fitter Unicode script ranges (specification). */
+/* */
+/* Copyright 2013-2015 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 __AFRANGES_H__
+#define __AFRANGES_H__
+
+
+#include "aftypes.h"
+
+
+FT_BEGIN_HEADER
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ extern const AF_Script_UniRangeRec af_ ## s ## _uniranges[];
+
+#include "afscript.h"
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ extern const AF_Script_UniRangeRec af_ ## s ## _nonbase_uniranges[];
+
+#include "afscript.h"
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __AFRANGES_H__ */
+
+
+/* END */
diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
new file mode 100644
index 0000000..39ec652
--- /dev/null
+++ b/src/autofit/afscript.h
@@ -0,0 +1,185 @@
+/***************************************************************************/
+/* */
+/* afscript.h */
+/* */
+/* Auto-fitter scripts (specification only). */
+/* */
+/* Copyright 2013-2015 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 following part can be included multiple times. */
+ /* Define `SCRIPT' as needed. */
+
+
+ /* Add new scripts here. The first and second arguments are the */
+ /* script name in lowercase and uppercase, respectively, followed */
+ /* by a description string. Then comes the corresponding HarfBuzz */
+ /* script name tag, followed by a string of standard characters (to */
+ /* derive the standard width and height of stems). */
+ /* */
+ /* Note that fallback scripts only have a default style, thus we */
+ /* use `HB_SCRIPT_INVALID' as the HarfBuzz script name tag for */
+ /* them. */
+
+ SCRIPT( arab, ARAB,
+ "Arabic",
+ HB_SCRIPT_ARABIC,
+ "\xD9\x84 \xD8\xAD \xD9\x80" ) /* ل ح ـ */
+
+ SCRIPT( cyrl, CYRL,
+ "Cyrillic",
+ HB_SCRIPT_CYRILLIC,
+ "\xD0\xBE \xD0\x9E" ) /* о О */
+
+ SCRIPT( deva, DEVA,
+ "Devanagari",
+ HB_SCRIPT_DEVANAGARI,
+ "\xE0\xA4\xA0 \xE0\xA4\xB5 \xE0\xA4\x9F" ) /* ठ व ट */
+
+ SCRIPT( grek, GREK,
+ "Greek",
+ HB_SCRIPT_GREEK,
+ "\xCE\xBF \xCE\x9F" ) /* ο Ο */
+
+ SCRIPT( hebr, HEBR,
+ "Hebrew",
+ HB_SCRIPT_HEBREW,
+ "\xD7\x9D" ) /* ם */
+
+ /* only digit zero has a simple shape in the Khmer script */
+ SCRIPT( khmr, KHMR,
+ "Khmer",
+ HB_SCRIPT_KHMER,
+ "\xE1\x9F\xA0" ) /* ០ */
+
+ SCRIPT( khms, KHMS,
+ "Khmer Symbols",
+ HB_SCRIPT_INVALID,
+ "\xE1\xA7\xA1 \xE1\xA7\xAA" ) /* ᧡ ᧪ */
+
+ /* only digit zero has a simple shape in the Lao script */
+ SCRIPT( lao, LAO,
+ "Lao",
+ HB_SCRIPT_LAO,
+ "\xE0\xBB\x90" ) /* ໐ */
+
+ SCRIPT( latn, LATN,
+ "Latin",
+ HB_SCRIPT_LATIN,
+ "o O 0" )
+
+ SCRIPT( latb, LATB,
+ "Latin Subscript Fallback",
+ HB_SCRIPT_INVALID,
+ "\xE2\x82\x92 \xE2\x82\x80" ) /* ₒ ₀ */
+
+ SCRIPT( latp, LATP,
+ "Latin Superscript Fallback",
+ HB_SCRIPT_INVALID,
+ "\xE1\xB5\x92 \xE1\xB4\xBC \xE2\x81\xB0" ) /* ᵒ ᴼ ⁰ */
+
+ SCRIPT( mymr, MYMR,
+ "Myanmar",
+ HB_SCRIPT_MYANMAR,
+ "\xE1\x80\x9D \xE1\x80\x84 \xE1\x80\x82" ) /* ဝ င ဂ */
+
+ SCRIPT( none, NONE,
+ "no script",
+ HB_SCRIPT_INVALID,
+ "" )
+
+ /* there are no simple forms for letters; we thus use two digit shapes */
+ SCRIPT( telu, TELU,
+ "Telugu",
+ HB_SCRIPT_TELUGU,
+ "\xE0\xB1\xA6 \xE0\xB1\xA7" ) /* ౦ ౧ */
+
+ SCRIPT( thai, THAI,
+ "Thai",
+ HB_SCRIPT_THAI,
+ "\xE0\xB8\xB2 \xE0\xB9\x85 \xE0\xB9\x90" ) /* า ๅ ๐ */
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+ SCRIPT( beng, BENG,
+ "Bengali",
+ HB_SCRIPT_BENGALI,
+ "o" ) /* XXX */
+
+ SCRIPT( gujr, GUJR,
+ "Gujarati",
+ HB_SCRIPT_GUJARATI,
+ "o" ) /* XXX */
+
+ SCRIPT( guru, GURU,
+ "Gurmukhi",
+ HB_SCRIPT_GURMUKHI,
+ "o" ) /* XXX */
+
+ SCRIPT( knda, KNDA,
+ "Kannada",
+ HB_SCRIPT_KANNADA,
+ "o" ) /* XXX */
+
+ SCRIPT( limb, LIMB,
+ "Limbu",
+ HB_SCRIPT_LIMBU,
+ "o" ) /* XXX */
+
+ SCRIPT( mlym, MLYM,
+ "Malayalam",
+ HB_SCRIPT_MALAYALAM,
+ "o" ) /* XXX */
+
+ SCRIPT( orya, ORYA,
+ "Oriya",
+ HB_SCRIPT_ORIYA,
+ "o" ) /* XXX */
+
+ SCRIPT( sinh, SINH,
+ "Sinhala",
+ HB_SCRIPT_SINHALA,
+ "o" ) /* XXX */
+
+ SCRIPT( sund, SUND,
+ "Sundanese",
+ HB_SCRIPT_SUNDANESE,
+ "o" ) /* XXX */
+
+ SCRIPT( sylo, SYLO,
+ "Syloti Nagri",
+ HB_SCRIPT_SYLOTI_NAGRI,
+ "o" ) /* XXX */
+
+ SCRIPT( taml, TAML,
+ "Tamil",
+ HB_SCRIPT_TAMIL,
+ "o" ) /* XXX */
+
+ SCRIPT( tibt, TIBT,
+ "Tibetan",
+ HB_SCRIPT_TIBETAN,
+ "o" ) /* XXX */
+
+#endif /* AF_CONFIG_OPTION_INDIC */
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+ SCRIPT( hani, HANI,
+ "CJKV ideographs",
+ HB_SCRIPT_HAN,
+ "\xE7\x94\xB0 \xE5\x9B\x97" ) /* 田 囗 */
+
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+/* END */
diff --git a/src/autofit/afshaper.c b/src/autofit/afshaper.c
new file mode 100644
index 0000000..6ba9190
--- /dev/null
+++ b/src/autofit/afshaper.c
@@ -0,0 +1,676 @@
+/***************************************************************************/
+/* */
+/* afshaper.c */
+/* */
+/* HarfBuzz interface for accessing OpenType features (body). */
+/* */
+/* Copyright 2013-2015 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 <ft2build.h>
+#include FT_FREETYPE_H
+#include "afglobal.h"
+#include "aftypes.h"
+#include "afshaper.h"
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afshaper
+
+
+ /*
+ * We use `sets' (in the HarfBuzz sense, which comes quite near to the
+ * usual mathematical meaning) to manage both lookups and glyph indices.
+ *
+ * 1. For each coverage, collect lookup IDs in a set. Note that an
+ * auto-hinter `coverage' is represented by one `feature', and a
+ * feature consists of an arbitrary number of (font specific) `lookup's
+ * that actually do the mapping job. Please check the OpenType
+ * specification for more details on features and lookups.
+ *
+ * 2. Create glyph ID sets from the corresponding lookup sets.
+ *
+ * 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
+ * with all lookups specific to the OpenType script activated. It
+ * relies on the order of AF_DEFINE_STYLE_CLASS entries so that
+ * special coverages (like `oldstyle figures') don't get overwritten.
+ *
+ */
+
+
+ /* load coverage tags */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_tag_t name ## _coverage[] = \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ HB_TAG_NONE \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between coverage tags and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _coverage,
+
+
+ static const hb_tag_t* coverages[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ /* load HarfBuzz script tags */
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) h,
+
+
+ static const hb_script_t scripts[] =
+ {
+#include "afscript.h"
+ };
+
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles )
+ {
+ hb_face_t* face;
+
+ hb_set_t* gsub_lookups; /* GSUB lookups for a given script */
+ hb_set_t* gsub_glyphs; /* glyphs covered by GSUB lookups */
+ hb_set_t* gpos_lookups; /* GPOS lookups for a given script */
+ hb_set_t* gpos_glyphs; /* glyphs covered by GPOS lookups */
+
+ hb_script_t script;
+ const hb_tag_t* coverage_tags;
+ hb_tag_t script_tags[] = { HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE };
+
+ hb_codepoint_t idx;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count;
+#endif
+
+
+ if ( !globals || !style_class || !gstyles )
+ return FT_THROW( Invalid_Argument );
+
+ face = hb_font_get_face( globals->hb_font );
+
+ gsub_lookups = hb_set_create();
+ gsub_glyphs = hb_set_create();
+ gpos_lookups = hb_set_create();
+ gpos_glyphs = hb_set_create();
+
+ coverage_tags = coverages[style_class->coverage];
+ script = scripts[style_class->script];
+
+ /* Convert a HarfBuzz script tag into the corresponding OpenType */
+ /* tag or tags -- some Indic scripts like Devanagari have an old */
+ /* and a new set of features. */
+ hb_ot_tags_from_script( script,
+ &script_tags[0],
+ &script_tags[1] );
+
+ /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
+ /* as the second tag. We change that to HB_TAG_NONE except for the */
+ /* default script. */
+ if ( style_class->script == globals->module->default_script &&
+ style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+ if ( script_tags[0] == HB_TAG_NONE )
+ script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else
+ {
+ if ( script_tags[1] == HB_TAG_NONE )
+ script_tags[1] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else if ( script_tags[1] != HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[2] = HB_OT_TAG_DEFAULT_SCRIPT;
+ }
+ }
+ else
+ {
+ if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[1] = HB_TAG_NONE;
+ }
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GSUB,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gsub_lookups );
+
+ if ( hb_set_is_empty( gsub_lookups ) )
+ goto Exit; /* nothing to do */
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GPOS,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gpos_lookups );
+
+ FT_TRACE4(( "GSUB lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get output coverage of GSUB feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GSUB,
+ idx,
+ NULL,
+ NULL,
+ NULL,
+ gsub_glyphs );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ FT_TRACE4(( "GPOS lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get input coverage of GPOS feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GPOS,
+ idx,
+ NULL,
+ gpos_glyphs,
+ NULL,
+ NULL );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ /*
+ * We now check whether we can construct blue zones, using glyphs
+ * covered by the feature only. In case there is not a single zone
+ * (this is, not a single character is covered), we skip this coverage.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ {
+ AF_Blue_Stringset bss = style_class->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+
+ FT_Bool found = 0;
+
+
+ for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
+ {
+ const char* p = &af_blue_strings[bs->string];
+
+
+ while ( *p )
+ {
+ hb_codepoint_t ch;
+
+
+ GET_UTF8_CHAR( ch, p );
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups,
+ &idx ); )
+ {
+ hb_codepoint_t gidx = FT_Get_Char_Index( globals->face, ch );
+
+
+ if ( hb_ot_layout_lookup_would_substitute( face, idx,
+ &gidx, 1, 1 ) )
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !found )
+ {
+ FT_TRACE4(( " no blue characters found; style skipped\n" ));
+ goto Exit;
+ }
+ }
+
+ /*
+ * Various OpenType features might use the same glyphs at different
+ * vertical positions; for example, superscript and subscript glyphs
+ * could be the same. However, the auto-hinter is completely
+ * agnostic of OpenType features after the feature analysis has been
+ * completed: The engine then simply receives a glyph index and returns a
+ * hinted and usually rendered glyph.
+ *
+ * Consider the superscript feature of font `pala.ttf': Some of the
+ * glyphs are `real', this is, they have a zero vertical offset, but
+ * most of them are small caps glyphs shifted up to the superscript
+ * position (this is, the `sups' feature is present in both the GSUB and
+ * GPOS tables). The code for blue zones computation actually uses a
+ * feature's y offset so that the `real' glyphs get correct hints. But
+ * later on it is impossible to decide whether a glyph index belongs to,
+ * say, the small caps or superscript feature.
+ *
+ * For this reason, we don't assign a style to a glyph if the current
+ * feature covers the glyph in both the GSUB and the GPOS tables. This
+ * is quite a broad condition, assuming that
+ *
+ * (a) glyphs that get used in multiple features are present in a
+ * feature without vertical shift,
+ *
+ * and
+ *
+ * (b) a feature's GPOS data really moves the glyph vertically.
+ *
+ * Not fulfilling condition (a) makes a font larger; it would also
+ * reduce the number of glyphs that could be addressed directly without
+ * using OpenType features, so this assumption is rather strong.
+ *
+ * Condition (b) is much weaker, and there might be glyphs which get
+ * missed. However, the OpenType features we are going to handle are
+ * primarily located in GSUB, and HarfBuzz doesn't provide an API to
+ * directly get the necessary information from the GPOS table. A
+ * possible solution might be to directly parse the GPOS table to find
+ * out whether a glyph gets shifted vertically, but this is something I
+ * would like to avoid if not really necessary.
+ *
+ * Note that we don't follow this logic for the default coverage.
+ * Complex scripts like Devanagari have mandatory GPOS features to
+ * position many glyph elements, using mark-to-base or mark-to-ligature
+ * tables; the number of glyphs missed due to condition (b) would be far
+ * too large.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ hb_set_subtract( gsub_glyphs, gpos_glyphs );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" ));
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( count % 10 ) )
+ FT_TRACE4(( "\n"
+ " " ));
+
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
+ /* can be arbitrary: some fonts use fake indices for processing */
+ /* internal to GSUB or GPOS, which is fully valid */
+ if ( idx >= (hb_codepoint_t)globals->glyph_count )
+ continue;
+
+ if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
+ gstyles[idx] = (FT_UShort)style_class->style;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ FT_TRACE4(( "*" ));
+#endif
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( "\n"
+ " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ Exit:
+ hb_set_destroy( gsub_lookups );
+ hb_set_destroy( gsub_glyphs );
+ hb_set_destroy( gpos_lookups );
+ hb_set_destroy( gpos_glyphs );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* construct HarfBuzz features */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_feature_t name ## _feature[] = \
+ { \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ 1, 0, (unsigned int)-1 \
+ } \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between HarfBuzz features and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _feature,
+
+
+ static const hb_feature_t* features[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ void*
+ af_shaper_buf_create( FT_Face face )
+ {
+ FT_UNUSED( face );
+
+ return (void*)hb_buffer_create();
+ }
+
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf )
+ {
+ FT_UNUSED( face );
+
+ hb_buffer_destroy( (hb_buffer_t*)buf );
+ }
+
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count )
+ {
+ AF_StyleClass style_class;
+ const hb_feature_t* feature;
+ FT_Int upem;
+ const char* q;
+ int len;
+
+ hb_buffer_t* buf = (hb_buffer_t*)buf_;
+ hb_font_t* font;
+ hb_codepoint_t dummy;
+
+
+ upem = (FT_Int)metrics->globals->face->units_per_EM;
+ style_class = metrics->style_class;
+ feature = features[style_class->coverage];
+
+ font = metrics->globals->hb_font;
+
+ /* we shape at a size of units per EM; this means font units */
+ hb_font_set_scale( font, upem, upem );
+
+ while ( *p == ' ' )
+ p++;
+
+ /* count bytes up to next space (or end of buffer) */
+ q = p;
+ while ( !( *q == ' ' || *q == '\0' ) )
+ GET_UTF8_CHAR( dummy, q );
+ len = (int)( q - p );
+
+ /* feed character(s) to the HarfBuzz buffer */
+ hb_buffer_clear_contents( buf );
+ hb_buffer_add_utf8( buf, p, len, 0, len );
+
+ /* we let HarfBuzz guess the script and writing direction */
+ hb_buffer_guess_segment_properties( buf );
+
+ /* shape buffer, which means conversion from character codes to */
+ /* glyph indices, possibly applying a feature */
+ hb_shape( font, buf, feature, feature ? 1 : 0 );
+
+ if ( feature )
+ {
+ hb_buffer_t* hb_buf = metrics->globals->hb_buf;
+
+ unsigned int gcount;
+ hb_glyph_info_t* ginfo;
+
+ unsigned int hb_gcount;
+ hb_glyph_info_t* hb_ginfo;
+
+
+ /* we have to check whether applying a feature does actually change */
+ /* glyph indices; otherwise the affected glyph or glyphs aren't */
+ /* available at all in the feature */
+
+ hb_buffer_clear_contents( hb_buf );
+ hb_buffer_add_utf8( hb_buf, p, len, 0, len );
+ hb_buffer_guess_segment_properties( hb_buf );
+ hb_shape( font, hb_buf, NULL, 0 );
+
+ ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+ hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount );
+
+ if ( gcount == hb_gcount )
+ {
+ unsigned int i;
+
+
+ for (i = 0; i < gcount; i++ )
+ if ( ginfo[i].codepoint != hb_ginfo[i].codepoint )
+ break;
+
+ if ( i == gcount )
+ {
+ /* both buffers have identical glyph indices */
+ hb_buffer_clear_contents( buf );
+ }
+ }
+ }
+
+ *count = hb_buffer_get_length( buf );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( feature && *count > 1 )
+ FT_TRACE1(( "af_shaper_get_cluster:"
+ " input character mapped to multiple glyphs\n" ));
+#endif
+
+ return q;
+ }
+
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* advance,
+ FT_Long* y_offset )
+ {
+ hb_buffer_t* buf = (hb_buffer_t*)buf_;
+ hb_glyph_info_t* ginfo;
+ hb_glyph_position_t* gpos;
+ unsigned int gcount;
+
+ FT_UNUSED( metrics );
+
+
+ ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+ gpos = hb_buffer_get_glyph_positions( buf, &gcount );
+
+ if ( idx >= gcount )
+ return 0;
+
+ if ( advance )
+ *advance = gpos[idx].x_advance;
+ if ( y_offset )
+ *y_offset = gpos[idx].y_offset;
+
+ return ginfo[idx].codepoint;
+ }
+
+
+#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles )
+ {
+ FT_UNUSED( globals );
+ FT_UNUSED( style_class );
+ FT_UNUSED( gstyles );
+
+ return FT_Err_Ok;
+ }
+
+
+ void*
+ af_shaper_buf_create( FT_Face face )
+ {
+ FT_Error error;
+ FT_Memory memory = face->memory;
+ FT_ULong* buf;
+
+
+ FT_MEM_ALLOC( buf, sizeof ( FT_ULong ) );
+
+ return (void*)buf;
+ }
+
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf )
+ {
+ FT_Memory memory = face->memory;
+
+
+ FT_FREE( buf );
+ }
+
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count )
+ {
+ FT_Face face = metrics->globals->face;
+ FT_ULong ch, dummy = 0;
+ FT_ULong* buf = (FT_ULong*)buf_;
+
+
+ while ( *p == ' ' )
+ p++;
+
+ GET_UTF8_CHAR( ch, p );
+
+ /* since we don't have an engine to handle clusters, */
+ /* we scan the characters but return zero */
+ while ( !( *p == ' ' || *p == '\0' ) )
+ GET_UTF8_CHAR( dummy, p );
+
+ if ( dummy )
+ {
+ *buf = 0;
+ *count = 0;
+ }
+ else
+ {
+ *buf = FT_Get_Char_Index( face, ch );
+ *count = 1;
+ }
+
+ return p;
+ }
+
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* advance,
+ FT_Long* y_offset )
+ {
+ FT_Face face = metrics->globals->face;
+ FT_ULong glyph_index = *(FT_ULong*)buf_;
+
+ FT_UNUSED( idx );
+
+
+ if ( advance )
+ FT_Get_Advance( face,
+ glyph_index,
+ FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_IGNORE_TRANSFORM,
+ advance );
+
+ if ( y_offset )
+ *y_offset = 0;
+
+ return glyph_index;
+ }
+
+
+#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+/* END */
diff --git a/src/autofit/afshaper.h b/src/autofit/afshaper.h
new file mode 100644
index 0000000..db1b4e0
--- /dev/null
+++ b/src/autofit/afshaper.h
@@ -0,0 +1,71 @@
+/***************************************************************************/
+/* */
+/* afshaper.h */
+/* */
+/* HarfBuzz interface for accessing OpenType features (specification). */
+/* */
+/* Copyright 2013-2015 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 __AFSHAPER_H__
+#define __AFSHAPER_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+#endif
+
+
+FT_BEGIN_HEADER
+
+ FT_Error
+ af_shaper_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_UShort* gstyles );
+
+
+ void*
+ af_shaper_buf_create( FT_Face face );
+
+ void
+ af_shaper_buf_destroy( FT_Face face,
+ void* buf );
+
+ const char*
+ af_shaper_get_cluster( const char* p,
+ AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int* count );
+
+ FT_ULong
+ af_shaper_get_elem( AF_StyleMetrics metrics,
+ void* buf_,
+ unsigned int idx,
+ FT_Long* x_advance,
+ FT_Long* y_offset );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __AFSHAPER_H__ */
+
+
+/* END */
diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h
new file mode 100644
index 0000000..e214442
--- /dev/null
+++ b/src/autofit/afstyles.h
@@ -0,0 +1,224 @@
+/***************************************************************************/
+/* */
+/* afstyles.h */
+/* */
+/* Auto-fitter styles (specification only). */
+/* */
+/* Copyright 2013-2015 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 following part can be included multiple times. */
+ /* Define `STYLE' as needed. */
+
+
+ /* Add new styles here. The first and second arguments are the */
+ /* style name in lowercase and uppercase, respectively, followed */
+ /* by a description string. The next arguments are the */
+ /* corresponding writing system, script, blue stringset, and */
+ /* coverage. */
+ /* */
+ /* Note that styles using `AF_COVERAGE_DEFAULT' should always */
+ /* come after styles with other coverages. Also note that */
+ /* fallback scripts only use `AF_COVERAGE_DEFAULT' for its */
+ /* style. */
+ /* */
+ /* Example: */
+ /* */
+ /* STYLE( cyrl_dflt, CYRL_DFLT, */
+ /* "Cyrillic default style", */
+ /* AF_WRITING_SYSTEM_LATIN, */
+ /* AF_SCRIPT_CYRL, */
+ /* AF_BLUE_STRINGSET_CYRL, */
+ /* AF_COVERAGE_DEFAULT ) */
+
+#undef STYLE_LATIN
+#define STYLE_LATIN( s, S, f, F, ds, df, C ) \
+ STYLE( s ## _ ## f, S ## _ ## F, \
+ ds " " df " style", \
+ AF_WRITING_SYSTEM_LATIN, \
+ AF_SCRIPT_ ## S, \
+ AF_BLUE_STRINGSET_ ## S, \
+ AF_COVERAGE_ ## C )
+
+#undef META_STYLE_LATIN
+#define META_STYLE_LATIN( s, S, ds ) \
+ STYLE_LATIN( s, S, c2cp, C2CP, ds, \
+ "petite capticals from capitals", \
+ PETITE_CAPITALS_FROM_CAPITALS ) \
+ STYLE_LATIN( s, S, c2sc, C2SC, ds, \
+ "small capticals from capitals", \
+ SMALL_CAPITALS_FROM_CAPITALS ) \
+ STYLE_LATIN( s, S, ordn, ORDN, ds, \
+ "ordinals", \
+ ORDINALS ) \
+ STYLE_LATIN( s, S, pcap, PCAP, ds, \
+ "petite capitals", \
+ PETITE_CAPITALS ) \
+ STYLE_LATIN( s, S, sinf, SINF, ds, \
+ "scientific inferiors", \
+ SCIENTIFIC_INFERIORS ) \
+ STYLE_LATIN( s, S, smcp, SMCP, ds, \
+ "small capitals", \
+ SMALL_CAPITALS ) \
+ STYLE_LATIN( s, S, subs, SUBS, ds, \
+ "subscript", \
+ SUBSCRIPT ) \
+ STYLE_LATIN( s, S, sups, SUPS, ds, \
+ "superscript", \
+ SUPERSCRIPT ) \
+ STYLE_LATIN( s, S, titl, TITL, ds, \
+ "titling", \
+ TITLING ) \
+ STYLE_LATIN( s, S, dflt, DFLT, ds, \
+ "default", \
+ DEFAULT )
+
+
+ STYLE( arab_dflt, ARAB_DFLT,
+ "Arabic default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_ARAB,
+ AF_BLUE_STRINGSET_ARAB,
+ AF_COVERAGE_DEFAULT )
+
+ META_STYLE_LATIN( cyrl, CYRL, "Cyrillic" )
+
+ STYLE( deva_dflt, DEVA_DFLT,
+ "Devanagari default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_DEVA,
+ AF_BLUE_STRINGSET_DEVA,
+ AF_COVERAGE_DEFAULT )
+
+ META_STYLE_LATIN( grek, GREK, "Greek" )
+
+ STYLE( hebr_dflt, HEBR_DFLT,
+ "Hebrew default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_HEBR,
+ AF_BLUE_STRINGSET_HEBR,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( khmr_dflt, KHMR_DFLT,
+ "Khmer default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_KHMR,
+ AF_BLUE_STRINGSET_KHMR,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( khms_dflt, KHMS_DFLT,
+ "Khmer Symbols default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_KHMS,
+ AF_BLUE_STRINGSET_KHMS,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( lao_dflt, LAO_DFLT,
+ "Lao default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_LAO,
+ AF_BLUE_STRINGSET_LAO,
+ AF_COVERAGE_DEFAULT )
+
+ META_STYLE_LATIN( latn, LATN, "Latin" )
+
+ STYLE( latb_dflt, LATB_DFLT,
+ "Latin subscript fallback default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_LATB,
+ AF_BLUE_STRINGSET_LATB,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( latp_dflt, LATP_DFLT,
+ "Latin superscript fallback default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_LATP,
+ AF_BLUE_STRINGSET_LATP,
+ AF_COVERAGE_DEFAULT )
+
+#ifdef FT_OPTION_AUTOFIT2
+ STYLE( ltn2_dflt, LTN2_DFLT,
+ "Latin 2 default style",
+ AF_WRITING_SYSTEM_LATIN2,
+ AF_SCRIPT_LATN,
+ AF_BLUE_STRINGSET_LATN,
+ AF_COVERAGE_DEFAULT )
+#endif
+
+ STYLE( mymr_dflt, MYMR_DFLT,
+ "Myanmar default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_MYMR,
+ AF_BLUE_STRINGSET_MYMR,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( none_dflt, NONE_DFLT,
+ "no style",
+ AF_WRITING_SYSTEM_DUMMY,
+ AF_SCRIPT_NONE,
+ (AF_Blue_Stringset)0,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( telu_dflt, TELU_DFLT,
+ "Telugu default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_TELU,
+ AF_BLUE_STRINGSET_TELU,
+ AF_COVERAGE_DEFAULT )
+
+ STYLE( thai_dflt, THAI_DFLT,
+ "Thai default style",
+ AF_WRITING_SYSTEM_LATIN,
+ AF_SCRIPT_THAI,
+ AF_BLUE_STRINGSET_THAI,
+ AF_COVERAGE_DEFAULT )
+
+#ifdef AF_CONFIG_OPTION_INDIC
+
+ /* no blue stringset support for the Indic writing system yet */
+#undef STYLE_DEFAULT_INDIC
+#define STYLE_DEFAULT_INDIC( s, S, d ) \
+ STYLE( s ## _dflt, S ## _DFLT, \
+ d " default style", \
+ AF_WRITING_SYSTEM_INDIC, \
+ AF_SCRIPT_ ## S, \
+ (AF_Blue_Stringset)0, \
+ AF_COVERAGE_DEFAULT )
+
+ STYLE_DEFAULT_INDIC( beng, BENG, "Bengali" )
+ STYLE_DEFAULT_INDIC( gujr, GUJR, "Gujarati" )
+ STYLE_DEFAULT_INDIC( guru, GURU, "Gurmukhi" )
+ STYLE_DEFAULT_INDIC( knda, KNDA, "Kannada" )
+ STYLE_DEFAULT_INDIC( limb, LIMB, "Limbu" )
+ STYLE_DEFAULT_INDIC( mlym, MLYM, "Malayalam" )
+ STYLE_DEFAULT_INDIC( orya, ORYA, "Oriya" )
+ STYLE_DEFAULT_INDIC( sinh, SINH, "Sinhala" )
+ STYLE_DEFAULT_INDIC( sund, SUND, "Sundanese" )
+ STYLE_DEFAULT_INDIC( sylo, SYLO, "Syloti Nagri" )
+ STYLE_DEFAULT_INDIC( taml, TAML, "Tamil" )
+ STYLE_DEFAULT_INDIC( tibt, TIBT, "Tibetan" )
+
+#endif /* AF_CONFIG_OPTION_INDIC */
+
+#ifdef AF_CONFIG_OPTION_CJK
+
+ STYLE( hani_dflt, HANI_DFLT,
+ "CJKV ideographs default style",
+ AF_WRITING_SYSTEM_CJK,
+ AF_SCRIPT_HANI,
+ AF_BLUE_STRINGSET_HANI,
+ AF_COVERAGE_DEFAULT )
+
+#endif /* AF_CONFIG_OPTION_CJK */
+
+
+/* END */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 9acd7ad..b483619 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter types (specification only). */
/* */
-/* Copyright 2003-2009, 2011-2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,15 +20,12 @@
*
* The auto-fitter is a complete rewrite of the old auto-hinter.
* Its main feature is the ability to differentiate between different
- * scripts in order to apply language-specific rules.
+ * writing systems and scripts in order to apply specific rules.
*
* The code has also been compartmentized into several entities that
* should make algorithmic experimentation easier than with the old
* code.
*
- * Finally, we get rid of the Catharon license, since this code is
- * released under the FreeType one.
- *
*************************************************************************/
@@ -42,6 +39,12 @@
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
+#include "afblue.h"
+
+#ifdef FT_DEBUG_AUTOFIT
+#include FT_CONFIG_STANDARD_LIBRARY_H
+#endif
+
FT_BEGIN_HEADER
@@ -55,8 +58,6 @@
#ifdef FT_DEBUG_AUTOFIT
-#include FT_CONFIG_STANDARD_LIBRARY_H
-
extern int _af_debug_disable_horz_hints;
extern int _af_debug_disable_vert_hints;
extern int _af_debug_disable_blue_hints;
@@ -139,11 +140,10 @@
AF_Angle _delta = (angle2) - (angle1); \
\
\
- _delta %= AF_ANGLE_2PI; \
- if ( _delta < 0 ) \
+ while ( _delta <= -AF_ANGLE_PI ) \
_delta += AF_ANGLE_2PI; \
\
- if ( _delta > AF_ANGLE_PI ) \
+ while ( _delta > AF_ANGLE_PI ) \
_delta -= AF_ANGLE_2PI; \
\
result = _delta; \
@@ -169,13 +169,10 @@
* auto-hinted glyph image.
*/
- typedef enum AF_ScalerFlags_
- {
- AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
- AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
- AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
-
- } AF_ScalerFlags;
+#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */
+#define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */
+#define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */
+#define AF_SCALER_FLAG_NO_WARPER 8U /* disable warper */
typedef struct AF_ScalerRec_
@@ -198,92 +195,134 @@
(a)->y_delta == (b)->y_delta )
+ typedef struct AF_StyleMetricsRec_* AF_StyleMetrics;
+
+ /* This function parses an FT_Face to compute global metrics for
+ * a specific style.
+ */
+ typedef FT_Error
+ (*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics metrics,
+ FT_Face face );
+
+ typedef void
+ (*AF_WritingSystem_ScaleMetricsFunc)( AF_StyleMetrics metrics,
+ AF_Scaler scaler );
+
+ typedef void
+ (*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics metrics );
+
+ typedef void
+ (*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW );
+
+
+ typedef FT_Error
+ (*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints hints,
+ AF_StyleMetrics metrics );
+
+ typedef void
+ (*AF_WritingSystem_ApplyHintsFunc)( FT_UInt glyph_index,
+ AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_StyleMetrics metrics );
+
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
- /***** S C R I P T S *****/
+ /***** W R I T I N G S Y S T E M S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
- * The list of known scripts. Each different script corresponds to the
- * following information:
+ * For the auto-hinter, a writing system consists of multiple scripts that
+ * can be handled similarly *in a typographical way*; the relationship is
+ * not based on history. For example, both the Greek and the unrelated
+ * Armenian scripts share the same features like ascender, descender,
+ * x-height, etc. Essentially, a writing system is covered by a
+ * submodule of the auto-fitter; it contains
*
- * - A set of Unicode ranges to test whether the face supports the
- * script.
+ * - a specific global analyzer that computes global metrics specific to
+ * the script (based on script-specific characters to identify ascender
+ * height, x-height, etc.),
*
- * - A specific global analyzer that will compute global metrics
- * specific to the script.
+ * - a specific glyph analyzer that computes segments and edges for each
+ * glyph covered by the script,
*
- * - A specific glyph analyzer that will compute segments and
- * edges for each glyph covered by the script.
- *
- * - A specific grid-fitting algorithm that will distort the
- * scaled glyph outline according to the results of the glyph
- * analyzer.
- *
- * Note that a given analyzer and/or grid-fitting algorithm can be
- * used by more than one script.
+ * - a specific grid-fitting algorithm that distorts the scaled glyph
+ * outline according to the results of the glyph analyzer.
*/
+#define __AFWRTSYS_H__ /* don't load header files */
+#undef WRITING_SYSTEM
+#define WRITING_SYSTEM( ws, WS ) \
+ AF_WRITING_SYSTEM_ ## WS,
+
+ /* The list of known writing systems. */
+ typedef enum AF_WritingSystem_
+ {
+
+#include "afwrtsys.h"
+
+ AF_WRITING_SYSTEM_MAX /* do not remove */
+
+ } AF_WritingSystem;
+
+#undef __AFWRTSYS_H__
+
+
+ typedef struct AF_WritingSystemClassRec_
+ {
+ AF_WritingSystem writing_system;
+
+ FT_Offset style_metrics_size;
+ AF_WritingSystem_InitMetricsFunc style_metrics_init;
+ AF_WritingSystem_ScaleMetricsFunc style_metrics_scale;
+ AF_WritingSystem_DoneMetricsFunc style_metrics_done;
+ AF_WritingSystem_GetStdWidthsFunc style_metrics_getstdw;
+
+ AF_WritingSystem_InitHintsFunc style_hints_init;
+ AF_WritingSystem_ApplyHintsFunc style_hints_apply;
+
+ } AF_WritingSystemClassRec;
+
+ typedef const AF_WritingSystemClassRec* AF_WritingSystemClass;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S C R I P T S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * Each script is associated with two sets of Unicode ranges to test
+ * whether the font face supports the script, and which non-base
+ * characters the script contains.
+ *
+ * We use four-letter script tags from the OpenType specification,
+ * extended by `NONE', which indicates `no script'.
+ */
+
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, ss ) \
+ AF_SCRIPT_ ## S,
+
+ /* The list of known scripts. */
typedef enum AF_Script_
{
- AF_SCRIPT_DUMMY = 0,
- AF_SCRIPT_LATIN = 1,
- AF_SCRIPT_CJK = 2,
- AF_SCRIPT_INDIC = 3,
-#ifdef FT_OPTION_AUTOFIT2
- AF_SCRIPT_LATIN2 = 4,
-#endif
- /* add new scripts here. Don't forget to update the list in */
- /* `afglobal.c'. */
+#include "afscript.h"
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
- typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
- typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
-
- typedef struct AF_ScriptMetricsRec_
- {
- AF_ScriptClass clazz;
- AF_ScalerRec scaler;
- FT_Bool digits_have_same_width;
-
- AF_FaceGlobals globals; /* to access properties */
-
- } AF_ScriptMetricsRec, *AF_ScriptMetrics;
-
-
- /* This function parses an FT_Face to compute global metrics for
- * a specific script.
- */
- typedef FT_Error
- (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
- FT_Face face );
-
- typedef void
- (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
- AF_Scaler scaler );
-
- typedef void
- (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
-
-
- typedef FT_Error
- (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
- AF_ScriptMetrics metrics );
-
- typedef void
- (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_ScriptMetrics metrics );
-
-
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
@@ -293,76 +332,299 @@
#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }
- typedef const AF_Script_UniRangeRec *AF_Script_UniRange;
+ typedef const AF_Script_UniRangeRec* AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
- AF_Script script;
- AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
- FT_UInt32 standard_char; /* for default width and height */
+ AF_Script script;
- FT_Offset script_metrics_size;
- AF_Script_InitMetricsFunc script_metrics_init;
- AF_Script_ScaleMetricsFunc script_metrics_scale;
- AF_Script_DoneMetricsFunc script_metrics_done;
+ /* last element in the ranges must be { 0, 0 } */
+ AF_Script_UniRange script_uni_ranges;
+ AF_Script_UniRange script_uni_nonbase_ranges;
- AF_Script_InitHintsFunc script_hints_init;
- AF_Script_ApplyHintsFunc script_hints_apply;
+ const char* standard_charstring; /* for default width and height */
} AF_ScriptClassRec;
+ typedef const AF_ScriptClassRec* AF_ScriptClass;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** C O V E R A G E S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * Usually, a font contains more glyphs than can be addressed by its
+ * character map.
+ *
+ * In the PostScript font world, encoding vectors specific to a given
+ * task are used to select such glyphs, and these glyphs can be often
+ * recognized by having a suffix in its glyph names. For example, a
+ * superscript glyph `A' might be called `A.sup'. Unfortunately, this
+ * naming scheme is not standardized and thus unusable for us.
+ *
+ * In the OpenType world, a better solution was invented, namely
+ * `features', which cleanly separate a character's input encoding from
+ * the corresponding glyph's appearance, and which don't use glyph names
+ * at all. For our purposes, and slightly generalized, an OpenType
+ * feature is a name of a mapping that maps character codes to
+ * non-standard glyph indices (features get used for other things also).
+ * For example, the `sups' feature provides superscript glyphs, thus
+ * mapping character codes like `A' or `B' to superscript glyph
+ * representation forms. How this mapping happens is completely
+ * uninteresting to us.
+ *
+ * For the auto-hinter, a `coverage' represents all glyphs of an OpenType
+ * feature collected in a set (as listed below) that can be hinted
+ * together. To continue the above example, superscript glyphs must not
+ * be hinted together with normal glyphs because the blue zones
+ * completely differ.
+ *
+ * Note that FreeType itself doesn't compute coverages; it only provides
+ * the glyphs addressable by the default Unicode character map. Instead,
+ * we use the HarfBuzz library (if available), which has many functions
+ * exactly for this purpose.
+ *
+ * AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
+ * listed separately (including the glyphs addressable by the character
+ * map). In case HarfBuzz isn't available, it exactly covers the glyphs
+ * addressable by the character map.
+ *
+ */
+
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ AF_COVERAGE_ ## NAME,
+
+
+ typedef enum AF_Coverage_
+ {
+#include "afcover.h"
+
+ AF_COVERAGE_DEFAULT
+
+ } AF_Coverage;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S T Y L E S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * The topmost structure for modelling the auto-hinter glyph input data
+ * is a `style class', grouping everything together.
+ */
+
+#undef STYLE
+#define STYLE( s, S, d, ws, sc, ss, c ) \
+ AF_STYLE_ ## S,
+
+ /* The list of known styles. */
+ typedef enum AF_Style_
+ {
+
+#include "afstyles.h"
+
+ AF_STYLE_MAX /* do not remove */
+
+ } AF_Style;
+
+
+ typedef struct AF_StyleClassRec_
+ {
+ AF_Style style;
+
+ AF_WritingSystem writing_system;
+ AF_Script script;
+ AF_Blue_Stringset blue_stringset;
+ AF_Coverage coverage;
+
+ } AF_StyleClassRec;
+
+ typedef const AF_StyleClassRec* AF_StyleClass;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** S T Y L E M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
+
+ /* This is the main structure that combines everything. Autofit modules */
+ /* specific to writing systems derive their structures from it, for */
+ /* example `AF_LatinMetrics'. */
+
+ typedef struct AF_StyleMetricsRec_
+ {
+ AF_StyleClass style_class;
+ AF_ScalerRec scaler;
+ FT_Bool digits_have_same_width;
+
+ AF_FaceGlobals globals; /* to access properties */
+
+ } AF_StyleMetricsRec;
+
/* Declare and define vtables for classes */
#ifndef FT_CONFIG_OPTION_PIC
+#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
+ FT_CALLBACK_TABLE const AF_WritingSystemClassRec \
+ writing_system_class;
+
+#define AF_DEFINE_WRITING_SYSTEM_CLASS( \
+ writing_system_class, \
+ system, \
+ m_size, \
+ m_init, \
+ m_scale, \
+ m_done, \
+ m_stdw, \
+ h_init, \
+ h_apply ) \
+ FT_CALLBACK_TABLE_DEF \
+ const AF_WritingSystemClassRec writing_system_class = \
+ { \
+ system, \
+ \
+ m_size, \
+ \
+ m_init, \
+ m_scale, \
+ m_done, \
+ m_stdw, \
+ \
+ h_init, \
+ h_apply \
+ };
+
+
#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
FT_CALLBACK_TABLE const AF_ScriptClassRec \
script_class;
-#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, def_char, \
- m_size, \
- m_init, m_scale, m_done, h_init, h_apply ) \
- FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec script_class = \
- { \
- script_, \
- ranges, \
- def_char, \
- \
- m_size, \
- \
- m_init, \
- m_scale, \
- m_done, \
- \
- h_init, \
- h_apply \
+#define AF_DEFINE_SCRIPT_CLASS( \
+ script_class, \
+ script, \
+ ranges, \
+ nonbase_ranges, \
+ std_charstring ) \
+ FT_CALLBACK_TABLE_DEF \
+ const AF_ScriptClassRec script_class = \
+ { \
+ script, \
+ ranges, \
+ nonbase_ranges, \
+ std_charstring, \
+ };
+
+
+#define AF_DECLARE_STYLE_CLASS( style_class ) \
+ FT_CALLBACK_TABLE const AF_StyleClassRec \
+ style_class;
+
+#define AF_DEFINE_STYLE_CLASS( \
+ style_class, \
+ style, \
+ writing_system, \
+ script, \
+ blue_stringset, \
+ coverage ) \
+ FT_CALLBACK_TABLE_DEF \
+ const AF_StyleClassRec style_class = \
+ { \
+ style, \
+ writing_system, \
+ script, \
+ blue_stringset, \
+ coverage \
};
#else /* FT_CONFIG_OPTION_PIC */
+#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
+ FT_LOCAL( void ) \
+ FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac );
+
+#define AF_DEFINE_WRITING_SYSTEM_CLASS( \
+ writing_system_class, \
+ system, \
+ m_size, \
+ m_init, \
+ m_scale, \
+ m_done, \
+ h_init, \
+ h_apply ) \
+ FT_LOCAL_DEF( void ) \
+ FT_Init_Class_ ## writing_system_class( AF_WritingSystemClassRec* ac ) \
+ { \
+ ac->writing_system = system; \
+ \
+ ac->style_metrics_size = m_size; \
+ \
+ ac->style_metrics_init = m_init; \
+ ac->style_metrics_scale = m_scale; \
+ ac->style_metrics_done = m_done; \
+ ac->style_metrics_getstdw = m_stdw; \
+ \
+ ac->style_hints_init = h_init; \
+ ac->style_hints_apply = h_apply; \
+ }
+
+
#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
FT_LOCAL( void ) \
FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac );
-#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, def_char, \
- m_size, \
- m_init, m_scale, m_done, h_init, h_apply ) \
- FT_LOCAL_DEF( void ) \
- FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \
- { \
- ac->script = script_; \
- ac->script_uni_ranges = ranges; \
- ac->default_char = def_char; \
- \
- ac->script_metrics_size = m_size; \
- \
- ac->script_metrics_init = m_init; \
- ac->script_metrics_scale = m_scale; \
- ac->script_metrics_done = m_done; \
- \
- ac->script_hints_init = h_init; \
- ac->script_hints_apply = h_apply; \
+#define AF_DEFINE_SCRIPT_CLASS( \
+ script_class, \
+ script_, \
+ ranges, \
+ nonbase_ranges, \
+ std_charstring ) \
+ FT_LOCAL_DEF( void ) \
+ FT_Init_Class_ ## script_class( AF_ScriptClassRec* ac ) \
+ { \
+ ac->script = script_; \
+ ac->script_uni_ranges = ranges; \
+ ac->script_uni_nonbase_ranges = nonbase_ranges; \
+ ac->standard_charstring = std_charstring; \
+ }
+
+
+#define AF_DECLARE_STYLE_CLASS( style_class ) \
+ FT_LOCAL( void ) \
+ FT_Init_Class_ ## style_class( AF_StyleClassRec* ac );
+
+#define AF_DEFINE_STYLE_CLASS( \
+ style_class, \
+ style_, \
+ writing_system_, \
+ script_, \
+ blue_stringset_, \
+ coverage_ ) \
+ FT_LOCAL_DEF( void ) \
+ FT_Init_Class_ ## style_class( AF_StyleClassRec* ac ) \
+ { \
+ ac->style = style_; \
+ ac->writing_system = writing_system_; \
+ ac->script = script_; \
+ ac->blue_stringset = blue_stringset_; \
+ ac->coverage = coverage_; \
}
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
index 34a97ff..ae92db1 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (body). */
/* */
-/* Copyright 2006, 2007, 2011 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -76,10 +76,10 @@
FT_Pos xx2,
AF_WarpScore base_distort,
AF_Segment segments,
- FT_UInt num_segments )
+ FT_Int num_segments )
{
FT_Int idx_min, idx_max, idx0;
- FT_UInt nn;
+ FT_Int nn;
AF_WarpScore scores[65];
@@ -171,7 +171,7 @@
FT_Fixed org_scale;
FT_Pos org_delta;
- FT_UInt nn, num_points, num_segments;
+ FT_Int nn, num_points, num_segments;
FT_Int X1, X2;
FT_Int w;
@@ -193,7 +193,7 @@
warper->best_scale = org_scale;
warper->best_delta = org_delta;
- warper->best_score = INT_MIN;
+ warper->best_score = FT_INT_MIN;
warper->best_distort = 0;
axis = &hints->axis[dim];
diff --git a/src/autofit/afwarp.h b/src/autofit/afwarp.h
index 7343fdd..6069b6b 100644
--- a/src/autofit/afwarp.h
+++ b/src/autofit/afwarp.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (specification). */
/* */
-/* Copyright 2006, 2007 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,7 +25,7 @@
#define AF_WARPER_SCALE
-#define AF_WARPER_FLOOR( x ) ( (x) & ~63 )
+#define AF_WARPER_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )
diff --git a/src/autofit/afwrtsys.h b/src/autofit/afwrtsys.h
new file mode 100644
index 0000000..4aa89d2
--- /dev/null
+++ b/src/autofit/afwrtsys.h
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/* */
+/* afwrtsys.h */
+/* */
+/* Auto-fitter writing systems (specification only). */
+/* */
+/* Copyright 2013-2015 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 __AFWRTSYS_H__
+#define __AFWRTSYS_H__
+
+ /* Since preprocessor directives can't create other preprocessor */
+ /* directives, we have to include the header files manually. */
+
+#include "afdummy.h"
+#include "aflatin.h"
+#include "afcjk.h"
+#include "afindic.h"
+#ifdef FT_OPTION_AUTOFIT2
+#include "aflatin2.h"
+#endif
+
+#endif /* __AFWRTSYS_H__ */
+
+
+ /* The following part can be included multiple times. */
+ /* Define `WRITING_SYSTEM' as needed. */
+
+
+ /* Add new writing systems here. The arguments are the writing system */
+ /* name in lowercase and uppercase, respectively. */
+
+ WRITING_SYSTEM( dummy, DUMMY )
+ WRITING_SYSTEM( latin, LATIN )
+ WRITING_SYSTEM( cjk, CJK )
+ WRITING_SYSTEM( indic, INDIC )
+#ifdef FT_OPTION_AUTOFIT2
+ WRITING_SYSTEM( latin2, LATIN2 )
+#endif
+
+
+/* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index 3883a0a..a971a24 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module (body). */
/* */
-/* Copyright 2003-2007, 2011 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,9 +20,12 @@
#include <ft2build.h>
#include "afpic.c"
#include "afangles.c"
+#include "afblue.c"
#include "afglobal.c"
#include "afhints.c"
+#include "afranges.c"
+
#include "afdummy.c"
#include "aflatin.c"
#ifdef FT_OPTION_AUTOFIT2
@@ -31,6 +34,8 @@
#include "afcjk.c"
#include "afindic.c"
+#include "afshaper.c"
+
#include "afloader.c"
#include "afmodule.c"
diff --git a/src/autofit/hbshim.c b/src/autofit/hbshim.c
new file mode 100644
index 0000000..c9c1db0
--- /dev/null
+++ b/src/autofit/hbshim.c
@@ -0,0 +1,546 @@
+/***************************************************************************/
+/* */
+/* hbshim.c */
+/* */
+/* HarfBuzz interface for accessing OpenType features (body). */
+/* */
+/* Copyright 2013-2015 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 <ft2build.h>
+#include FT_FREETYPE_H
+#include "afglobal.h"
+#include "aftypes.h"
+#include "hbshim.h"
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afharfbuzz
+
+
+ /*
+ * We use `sets' (in the HarfBuzz sense, which comes quite near to the
+ * usual mathematical meaning) to manage both lookups and glyph indices.
+ *
+ * 1. For each coverage, collect lookup IDs in a set. Note that an
+ * auto-hinter `coverage' is represented by one `feature', and a
+ * feature consists of an arbitrary number of (font specific) `lookup's
+ * that actually do the mapping job. Please check the OpenType
+ * specification for more details on features and lookups.
+ *
+ * 2. Create glyph ID sets from the corresponding lookup sets.
+ *
+ * 3. The glyph set corresponding to AF_COVERAGE_DEFAULT is computed
+ * with all lookups specific to the OpenType script activated. It
+ * relies on the order of AF_DEFINE_STYLE_CLASS entries so that
+ * special coverages (like `oldstyle figures') don't get overwritten.
+ *
+ */
+
+
+ /* load coverage tags */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_tag_t name ## _coverage[] = \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ HB_TAG_NONE \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between coverage tags and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _coverage,
+
+
+ static const hb_tag_t* coverages[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ /* load HarfBuzz script tags */
+#undef SCRIPT
+#define SCRIPT( s, S, d, h, sc1, sc2, sc3 ) h,
+
+
+ static const hb_script_t scripts[] =
+ {
+#include "afscript.h"
+ };
+
+
+ FT_Error
+ af_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_Byte* gstyles )
+ {
+ hb_face_t* face;
+
+ hb_set_t* gsub_lookups; /* GSUB lookups for a given script */
+ hb_set_t* gsub_glyphs; /* glyphs covered by GSUB lookups */
+ hb_set_t* gpos_lookups; /* GPOS lookups for a given script */
+ hb_set_t* gpos_glyphs; /* glyphs covered by GPOS lookups */
+
+ hb_script_t script;
+ const hb_tag_t* coverage_tags;
+ hb_tag_t script_tags[] = { HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE,
+ HB_TAG_NONE };
+
+ hb_codepoint_t idx;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count;
+#endif
+
+
+ if ( !globals || !style_class || !gstyles )
+ return FT_THROW( Invalid_Argument );
+
+ face = hb_font_get_face( globals->hb_font );
+
+ gsub_lookups = hb_set_create();
+ gsub_glyphs = hb_set_create();
+ gpos_lookups = hb_set_create();
+ gpos_glyphs = hb_set_create();
+
+ coverage_tags = coverages[style_class->coverage];
+ script = scripts[style_class->script];
+
+ /* Convert a HarfBuzz script tag into the corresponding OpenType */
+ /* tag or tags -- some Indic scripts like Devanagari have an old */
+ /* and a new set of features. */
+ hb_ot_tags_from_script( script,
+ &script_tags[0],
+ &script_tags[1] );
+
+ /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
+ /* as the second tag. We change that to HB_TAG_NONE except for the */
+ /* default script. */
+ if ( style_class->script == globals->module->default_script &&
+ style_class->coverage == AF_COVERAGE_DEFAULT )
+ {
+ if ( script_tags[0] == HB_TAG_NONE )
+ script_tags[0] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else
+ {
+ if ( script_tags[1] == HB_TAG_NONE )
+ script_tags[1] = HB_OT_TAG_DEFAULT_SCRIPT;
+ else if ( script_tags[1] != HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[2] = HB_OT_TAG_DEFAULT_SCRIPT;
+ }
+ }
+ else
+ {
+ if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[1] = HB_TAG_NONE;
+ }
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GSUB,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gsub_lookups );
+
+ if ( hb_set_is_empty( gsub_lookups ) )
+ goto Exit; /* nothing to do */
+
+ hb_ot_layout_collect_lookups( face,
+ HB_OT_TAG_GPOS,
+ script_tags,
+ NULL,
+ coverage_tags,
+ gpos_lookups );
+
+ FT_TRACE4(( "GSUB lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get output coverage of GSUB feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GSUB,
+ idx,
+ NULL,
+ NULL,
+ NULL,
+ gsub_glyphs );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ FT_TRACE4(( "GPOS lookups (style `%s'):\n"
+ " ",
+ af_style_names[style_class->style] ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* get input coverage of GPOS feature */
+ hb_ot_layout_lookup_collect_glyphs( face,
+ HB_OT_TAG_GPOS,
+ idx,
+ NULL,
+ gpos_glyphs,
+ NULL,
+ NULL );
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ /*
+ * We now check whether we can construct blue zones, using glyphs
+ * covered by the feature only. In case there is not a single zone
+ * (this is, not a single character is covered), we skip this coverage.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ {
+ AF_Blue_Stringset bss = style_class->blue_stringset;
+ const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
+
+ FT_Bool found = 0;
+
+
+ for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
+ {
+ const char* p = &af_blue_strings[bs->string];
+
+
+ while ( *p )
+ {
+ hb_codepoint_t ch;
+
+
+ GET_UTF8_CHAR( ch, p );
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups,
+ &idx ); )
+ {
+ hb_codepoint_t gidx = FT_Get_Char_Index( globals->face, ch );
+
+
+ if ( hb_ot_layout_lookup_would_substitute( face, idx,
+ &gidx, 1, 1 ) )
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !found )
+ {
+ FT_TRACE4(( " no blue characters found; style skipped\n" ));
+ goto Exit;
+ }
+ }
+
+ /*
+ * Various OpenType features might use the same glyphs at different
+ * vertical positions; for example, superscript and subscript glyphs
+ * could be the same. However, the auto-hinter is completely
+ * agnostic of OpenType features after the feature analysis has been
+ * completed: The engine then simply receives a glyph index and returns a
+ * hinted and usually rendered glyph.
+ *
+ * Consider the superscript feature of font `pala.ttf': Some of the
+ * glyphs are `real', this is, they have a zero vertical offset, but
+ * most of them are small caps glyphs shifted up to the superscript
+ * position (this is, the `sups' feature is present in both the GSUB and
+ * GPOS tables). The code for blue zones computation actually uses a
+ * feature's y offset so that the `real' glyphs get correct hints. But
+ * later on it is impossible to decide whether a glyph index belongs to,
+ * say, the small caps or superscript feature.
+ *
+ * For this reason, we don't assign a style to a glyph if the current
+ * feature covers the glyph in both the GSUB and the GPOS tables. This
+ * is quite a broad condition, assuming that
+ *
+ * (a) glyphs that get used in multiple features are present in a
+ * feature without vertical shift,
+ *
+ * and
+ *
+ * (b) a feature's GPOS data really moves the glyph vertically.
+ *
+ * Not fulfilling condition (a) makes a font larger; it would also
+ * reduce the number of glyphs that could be addressed directly without
+ * using OpenType features, so this assumption is rather strong.
+ *
+ * Condition (b) is much weaker, and there might be glyphs which get
+ * missed. However, the OpenType features we are going to handle are
+ * primarily located in GSUB, and HarfBuzz doesn't provide an API to
+ * directly get the necessary information from the GPOS table. A
+ * possible solution might be to directly parse the GPOS table to find
+ * out whether a glyph gets shifted vertically, but this is something I
+ * would like to avoid if not really necessary.
+ *
+ * Note that we don't follow this logic for the default coverage.
+ * Complex scripts like Devanagari have mandatory GPOS features to
+ * position many glyph elements, using mark-to-base or mark-to-ligature
+ * tables; the number of glyphs missed due to condition (b) would be far
+ * too large.
+ *
+ */
+ if ( style_class->coverage != AF_COVERAGE_DEFAULT )
+ hb_set_subtract( gsub_glyphs, gpos_glyphs );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" ));
+ count = 0;
+#endif
+
+ for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !( count % 10 ) )
+ FT_TRACE4(( "\n"
+ " " ));
+
+ FT_TRACE4(( " %d", idx ));
+ count++;
+#endif
+
+ /* glyph indices returned by `hb_ot_layout_lookup_collect_glyphs' */
+ /* can be arbitrary: some fonts use fake indices for processing */
+ /* internal to GSUB or GPOS, which is fully valid */
+ if ( idx >= (hb_codepoint_t)globals->glyph_count )
+ continue;
+
+ if ( gstyles[idx] == AF_STYLE_UNASSIGNED )
+ gstyles[idx] = (FT_Byte)style_class->style;
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ FT_TRACE4(( "*" ));
+#endif
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE4(( "\n"
+ " (none)" ));
+ FT_TRACE4(( "\n\n" ));
+#endif
+
+ Exit:
+ hb_set_destroy( gsub_lookups );
+ hb_set_destroy( gsub_glyphs );
+ hb_set_destroy( gpos_lookups );
+ hb_set_destroy( gpos_glyphs );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* construct HarfBuzz features */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ static const hb_feature_t name ## _feature[] = \
+ { \
+ { \
+ HB_TAG( tag1, tag2, tag3, tag4 ), \
+ 1, 0, (unsigned int)-1 \
+ } \
+ };
+
+
+#include "afcover.h"
+
+
+ /* define mapping between HarfBuzz features and AF_Coverage */
+#undef COVERAGE
+#define COVERAGE( name, NAME, description, \
+ tag1, tag2, tag3, tag4 ) \
+ name ## _feature,
+
+
+ static const hb_feature_t* features[] =
+ {
+#include "afcover.h"
+
+ NULL /* AF_COVERAGE_DEFAULT */
+ };
+
+
+ FT_Error
+ af_get_char_index( AF_StyleMetrics metrics,
+ FT_ULong charcode,
+ FT_ULong *codepoint,
+ FT_Long *y_offset )
+ {
+ AF_StyleClass style_class;
+
+ const hb_feature_t* feature;
+
+ FT_ULong in_idx, out_idx;
+
+
+ if ( !metrics )
+ return FT_THROW( Invalid_Argument );
+
+ in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );
+
+ style_class = metrics->style_class;
+
+ feature = features[style_class->coverage];
+
+ if ( feature )
+ {
+ FT_Int upem = (FT_Int)metrics->globals->face->units_per_EM;
+
+ hb_font_t* font = metrics->globals->hb_font;
+ hb_buffer_t* buf = hb_buffer_create();
+
+ uint32_t c = (uint32_t)charcode;
+
+ hb_glyph_info_t* ginfo;
+ hb_glyph_position_t* gpos;
+ unsigned int gcount;
+
+
+ /* we shape at a size of units per EM; this means font units */
+ hb_font_set_scale( font, upem, upem );
+
+ /* XXX: is this sufficient for a single character of any script? */
+ hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
+ hb_buffer_set_script( buf, scripts[style_class->script] );
+
+ /* we add one character to `buf' ... */
+ hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
+
+ /* ... and apply one feature */
+ hb_shape( font, buf, feature, 1 );
+
+ ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
+ gpos = hb_buffer_get_glyph_positions( buf, &gcount );
+
+ out_idx = ginfo[0].codepoint;
+
+ /* getting the same index indicates no substitution, */
+ /* which means that the glyph isn't available in the feature */
+ if ( in_idx == out_idx )
+ {
+ *codepoint = 0;
+ *y_offset = 0;
+ }
+ else
+ {
+ *codepoint = out_idx;
+ *y_offset = gpos[0].y_offset;
+ }
+
+ hb_buffer_destroy( buf );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( gcount > 1 )
+ FT_TRACE1(( "af_get_char_index:"
+ " input character mapped to multiple glyphs\n" ));
+#endif
+ }
+ else
+ {
+ *codepoint = in_idx;
+ *y_offset = 0;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+ FT_Error
+ af_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_Byte* gstyles )
+ {
+ FT_UNUSED( globals );
+ FT_UNUSED( style_class );
+ FT_UNUSED( gstyles );
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_Error
+ af_get_char_index( AF_StyleMetrics metrics,
+ FT_ULong charcode,
+ FT_ULong *codepoint,
+ FT_Long *y_offset )
+ {
+ FT_Face face;
+
+
+ if ( !metrics )
+ return FT_THROW( Invalid_Argument );
+
+ face = metrics->globals->face;
+
+ *codepoint = FT_Get_Char_Index( face, charcode );
+ *y_offset = 0;
+
+ return FT_Err_Ok;
+ }
+
+
+#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+/* END */
diff --git a/src/autofit/hbshim.h b/src/autofit/hbshim.h
new file mode 100644
index 0000000..5636ca6
--- /dev/null
+++ b/src/autofit/hbshim.h
@@ -0,0 +1,56 @@
+/***************************************************************************/
+/* */
+/* hbshim.h */
+/* */
+/* HarfBuzz interface for accessing OpenType features (specification). */
+/* */
+/* Copyright 2013-2015 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 __HBSHIM_H__
+#define __HBSHIM_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
+
+#include <hb.h>
+#include <hb-ot.h>
+#include <hb-ft.h>
+
+#endif
+
+
+FT_BEGIN_HEADER
+
+ FT_Error
+ af_get_coverage( AF_FaceGlobals globals,
+ AF_StyleClass style_class,
+ FT_Byte* gstyles );
+
+ FT_Error
+ af_get_char_index( AF_StyleMetrics metrics,
+ FT_ULong charcode,
+ FT_ULong *codepoint,
+ FT_Long *y_offset );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __HBSHIM_H__ */
+
+
+/* END */
diff --git a/src/base/basepic.c b/src/base/basepic.c
index 0af770e..9850ed9 100644
--- a/src/base/basepic.c
+++ b/src/base/basepic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for base. */
/* */
-/* Copyright 2009, 2012 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -35,7 +35,7 @@
/* forward declaration of PIC init function from ftrfork.c */
/* (not modularized) */
void
- FT_Init_Table_raccess_guess_table( ft_raccess_guess_rec* record );
+ FT_Init_Table_ft_raccess_guess_table( ft_raccess_guess_rec* record );
#endif
/* forward declaration of PIC init functions from ftinit.c */
@@ -92,7 +92,7 @@
FT_Init_Class_ft_bitmap_glyph_class(
&container->ft_bitmap_glyph_class );
#ifdef FT_CONFIG_OPTION_MAC_FONTS
- FT_Init_Table_raccess_guess_table(
+ FT_Init_Table_ft_raccess_guess_table(
(ft_raccess_guess_rec*)&container->ft_raccess_guess_table );
#endif
diff --git a/src/base/basepic.h b/src/base/basepic.h
index 329d7c8..c5d7cbf 100644
--- a/src/base/basepic.h
+++ b/src/base/basepic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for base. */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,10 +20,9 @@
#define __BASEPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
@@ -43,6 +42,8 @@
#endif
+FT_BEGIN_HEADER
+
typedef struct BasePIC_
{
FT_Module_Class** default_module_classes;
@@ -78,12 +79,12 @@
FT_Error
ft_base_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __BASEPIC_H__ */
diff --git a/src/base/ftadvanc.c b/src/base/ftadvanc.c
index 5207847..f12908f 100644
--- a/src/base/ftadvanc.c
+++ b/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
/* */
/* Quick computation of advance widths (body). */
/* */
-/* Copyright 2008, 2009, 2011, 2013 by */
+/* Copyright 2008-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -80,6 +80,9 @@
if ( !face )
return FT_THROW( Invalid_Face_Handle );
+ if ( !padvance )
+ return FT_THROW( Invalid_Argument );
+
if ( gindex >= (FT_UInt)face->num_glyphs )
return FT_THROW( Invalid_Glyph_Index );
@@ -118,6 +121,9 @@
if ( !face )
return FT_THROW( Invalid_Face_Handle );
+ if ( !padvances )
+ return FT_THROW( Invalid_Argument );
+
num = (FT_UInt)face->num_glyphs;
end = start + count;
if ( start >= num || end < start || end > num )
diff --git a/src/base/ftapi.c b/src/base/ftapi.c
index 8914d1f..f22a181 100644
--- a/src/base/ftapi.c
+++ b/src/base/ftapi.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType compatibility functions (body). */
/* */
-/* Copyright 2002 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/base/ftbase.c b/src/base/ftbase.c
index 5e5d70e..253dfb7 100644
--- a/src/base/ftbase.c
+++ b/src/base/ftbase.c
@@ -4,7 +4,7 @@
/* */
/* Single object library component (body only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index 51a1db1..e37fefa 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType private functions used in base module (specification). */
/* */
-/* Copyright 2008, 2010 by */
+/* Copyright 2008-2015 by */
/* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,6 +27,11 @@
FT_BEGIN_HEADER
+ /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */
+ /* see https://support.microsoft.com/en-us/kb/130437 */
+#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL
+
+
/* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
/* font, and try to load a face specified by the face_index. */
FT_LOCAL( FT_Error )
diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
index 6d1c44c..10df98d 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
/* */
/* FreeType bbox computation (body). */
/* */
-/* Copyright 1996-2002, 2004, 2006, 2010, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -42,16 +42,35 @@
} TBBox_Rec;
+#define FT_UPDATE_BBOX( p, bbox ) \
+ FT_BEGIN_STMNT \
+ if ( p->x < bbox.xMin ) \
+ bbox.xMin = p->x; \
+ if ( p->x > bbox.xMax ) \
+ bbox.xMax = p->x; \
+ if ( p->y < bbox.yMin ) \
+ bbox.yMin = p->y; \
+ if ( p->y > bbox.yMax ) \
+ bbox.yMax = p->y; \
+ FT_END_STMNT
+
+#define CHECK_X( p, bbox ) \
+ ( p->x < bbox.xMin || p->x > bbox.xMax )
+
+#define CHECK_Y( p, bbox ) \
+ ( p->y < bbox.yMin || p->y > bbox.yMax )
+
+
/*************************************************************************/
/* */
/* <Function> */
/* BBox_Move_To */
/* */
/* <Description> */
- /* This function is used as a `move_to' and `line_to' emitter during */
+ /* This function is used as a `move_to' emitter during */
/* FT_Outline_Decompose(). It simply records the destination point */
- /* in `user->last'; no further computations are necessary since we */
- /* use the cbox as the starting bbox which must be refined. */
+ /* in `user->last'. We also update bbox in case contour starts with */
+ /* an implicit `on' point. */
/* */
/* <Input> */
/* to :: A pointer to the destination vector. */
@@ -66,17 +85,42 @@
BBox_Move_To( FT_Vector* to,
TBBox_Rec* user )
{
+ FT_UPDATE_BBOX( to, user->bbox );
+
user->last = *to;
return 0;
}
-#define CHECK_X( p, bbox ) \
- ( p->x < bbox.xMin || p->x > bbox.xMax )
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* BBox_Line_To */
+ /* */
+ /* <Description> */
+ /* This function is used as a `line_to' emitter during */
+ /* FT_Outline_Decompose(). It simply records the destination point */
+ /* in `user->last'; no further computations are necessary because */
+ /* bbox already contains both explicit ends of the line segment. */
+ /* */
+ /* <Input> */
+ /* to :: A pointer to the destination vector. */
+ /* */
+ /* <InOut> */
+ /* user :: A pointer to the current walk context. */
+ /* */
+ /* <Return> */
+ /* Always 0. Needed for the interface only. */
+ /* */
+ static int
+ BBox_Line_To( FT_Vector* to,
+ TBBox_Rec* user )
+ {
+ user->last = *to;
-#define CHECK_Y( p, bbox ) \
- ( p->y < bbox.yMin || p->y > bbox.yMax )
+ return 0;
+ }
/*************************************************************************/
@@ -85,7 +129,7 @@
/* BBox_Conic_Check */
/* */
/* <Description> */
- /* Finds the extrema of a 1-dimensional conic Bezier curve and update */
+ /* Find the extrema of a 1-dimensional conic Bezier curve and update */
/* a bounding range. This version uses direct computation, as it */
/* doesn't need square roots. */
/* */
@@ -108,30 +152,19 @@
FT_Pos* min,
FT_Pos* max )
{
- if ( y1 <= y3 && y2 == y1 ) /* flat arc */
- goto Suite;
+ /* This function is only called when a control off-point is outside */
+ /* the bbox that contains all on-points. It finds a local extremum */
+ /* within the segment, equal to (y1*y3 - y2*y2)/(y1 - 2*y2 + y3). */
+ /* Or, offsetting from y2, we get */
- if ( y1 < y3 )
- {
- if ( y2 >= y1 && y2 <= y3 ) /* ascending arc */
- goto Suite;
- }
- else
- {
- if ( y2 >= y3 && y2 <= y1 ) /* descending arc */
- {
- y2 = y1;
- y1 = y3;
- y3 = y2;
- goto Suite;
- }
- }
+ y1 -= y2;
+ y3 -= y2;
+ y2 += FT_MulDiv( y1, y3, y1 + y3 );
- y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
-
- Suite:
- if ( y1 < *min ) *min = y1;
- if ( y3 > *max ) *max = y3;
+ if ( y2 < *min )
+ *min = y2;
+ if ( y2 > *max )
+ *max = y2;
}
@@ -166,8 +199,8 @@
FT_Vector* to,
TBBox_Rec* user )
{
- /* we don't need to check `to' since it is always an `on' point, thus */
- /* within the bbox */
+ /* in case `to' is implicit and not included in bbox yet */
+ FT_UPDATE_BBOX( to, user->bbox );
if ( CHECK_X( control, user->bbox ) )
BBox_Conic_Check( user->last.x,
@@ -195,9 +228,9 @@
/* BBox_Cubic_Check */
/* */
/* <Description> */
- /* Finds the extrema of a 1-dimensional cubic Bezier curve and */
- /* updates a bounding range. This version uses splitting because we */
- /* don't want to use square roots and extra accuracy. */
+ /* Find the extrema of a 1-dimensional cubic Bezier curve and */
+ /* update a bounding range. This version uses iterative splitting */
+ /* because it is faster than the exact solution with square roots. */
/* */
/* <Input> */
/* p1 :: The start coordinate. */
@@ -213,28 +246,52 @@
/* */
/* max :: The address of the current maximum. */
/* */
-
-#if 0
-
- static void
- BBox_Cubic_Check( FT_Pos p1,
- FT_Pos p2,
- FT_Pos p3,
- FT_Pos p4,
- FT_Pos* min,
- FT_Pos* max )
+ static FT_Pos
+ cubic_peak( FT_Pos q1,
+ FT_Pos q2,
+ FT_Pos q3,
+ FT_Pos q4 )
{
- FT_Pos q1, q2, q3, q4;
+ FT_Pos peak = 0;
+ FT_Int shift;
- q1 = p1;
- q2 = p2;
- q3 = p3;
- q4 = p4;
+ /* This function finds a peak of a cubic segment if it is above 0 */
+ /* using iterative bisection of the segment, or returns 0. */
+ /* The fixed-point arithmetic of bisection is inherently stable */
+ /* but may loose accuracy in the two lowest bits. To compensate, */
+ /* we upscale the segment if there is room. Large values may need */
+ /* to be downscaled to avoid overflows during bisection. */
+ /* It is called with either q2 or q3 positive, which is necessary */
+ /* for the peak to exist and avoids undefined FT_MSB. */
- /* for a conic segment to possibly reach new maximum */
- /* one of its off-points must be above the current value */
- while ( q2 > *max || q3 > *max )
+ shift = 27 - FT_MSB( (FT_UInt32)( FT_ABS( q1 ) |
+ FT_ABS( q2 ) |
+ FT_ABS( q3 ) |
+ FT_ABS( q4 ) ) );
+
+ if ( shift > 0 )
+ {
+ /* upscaling too much just wastes time */
+ if ( shift > 2 )
+ shift = 2;
+
+ q1 <<= shift;
+ q2 <<= shift;
+ q3 <<= shift;
+ q4 <<= shift;
+ }
+ else
+ {
+ q1 >>= -shift;
+ q2 >>= -shift;
+ q3 >>= -shift;
+ q4 >>= -shift;
+ }
+
+ /* for a peak to exist above 0, the cubic segment must have */
+ /* at least one of its control off-points above 0. */
+ while ( q2 > 0 || q3 > 0 )
{
/* determine which half contains the maximum and split */
if ( q1 + q2 > q3 + q4 ) /* first half */
@@ -260,232 +317,49 @@
q3 = q3 / 2;
}
- /* check if either end reached the maximum */
+ /* check whether either end reached the maximum */
if ( q1 == q2 && q1 >= q3 )
{
- *max = q1;
+ peak = q1;
break;
}
if ( q3 == q4 && q2 <= q4 )
{
- *max = q4;
+ peak = q4;
break;
}
}
- q1 = p1;
- q2 = p2;
- q3 = p3;
- q4 = p4;
+ if ( shift > 0 )
+ peak >>= shift;
+ else
+ peak <<= -shift;
- /* for a conic segment to possibly reach new minimum */
- /* one of its off-points must be below the current value */
- while ( q2 < *min || q3 < *min )
- {
- /* determine which half contains the minimum and split */
- if ( q1 + q2 < q3 + q4 ) /* first half */
- {
- q4 = q4 + q3;
- q3 = q3 + q2;
- q2 = q2 + q1;
- q4 = q4 + q3;
- q3 = q3 + q2;
- q4 = ( q4 + q3 ) / 8;
- q3 = q3 / 4;
- q2 = q2 / 2;
- }
- else /* second half */
- {
- q1 = q1 + q2;
- q2 = q2 + q3;
- q3 = q3 + q4;
- q1 = q1 + q2;
- q2 = q2 + q3;
- q1 = ( q1 + q2 ) / 8;
- q2 = q2 / 4;
- q3 = q3 / 2;
- }
-
- /* check if either end reached the minimum */
- if ( q1 == q2 && q1 <= q3 )
- {
- *min = q1;
- break;
- }
- if ( q3 == q4 && q2 >= q4 )
- {
- *min = q4;
- break;
- }
- }
- }
-
-#else
-
- static void
- test_cubic_extrema( FT_Pos y1,
- FT_Pos y2,
- FT_Pos y3,
- FT_Pos y4,
- FT_Fixed u,
- FT_Pos* min,
- FT_Pos* max )
- {
- /* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */
- FT_Pos b = y3 - 2*y2 + y1;
- FT_Pos c = y2 - y1;
- FT_Pos d = y1;
- FT_Pos y;
- FT_Fixed uu;
-
- FT_UNUSED ( y4 );
-
-
- /* The polynomial is */
- /* */
- /* P(x) = a*x^3 + 3b*x^2 + 3c*x + d , */
- /* */
- /* dP/dx = 3a*x^2 + 6b*x + 3c . */
- /* */
- /* However, we also have */
- /* */
- /* dP/dx(u) = 0 , */
- /* */
- /* which implies by subtraction that */
- /* */
- /* P(u) = b*u^2 + 2c*u + d . */
-
- if ( u > 0 && u < 0x10000L )
- {
- uu = FT_MulFix( u, u );
- y = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
-
- if ( y < *min ) *min = y;
- if ( y > *max ) *max = y;
- }
+ return peak;
}
static void
- BBox_Cubic_Check( FT_Pos y1,
- FT_Pos y2,
- FT_Pos y3,
- FT_Pos y4,
+ BBox_Cubic_Check( FT_Pos p1,
+ FT_Pos p2,
+ FT_Pos p3,
+ FT_Pos p4,
FT_Pos* min,
FT_Pos* max )
{
- /* always compare first and last points */
- if ( y1 < *min ) *min = y1;
- else if ( y1 > *max ) *max = y1;
+ /* This function is only called when a control off-point is outside */
+ /* the bbox that contains all on-points. So at least one of the */
+ /* conditions below holds and cubic_peak is called with at least one */
+ /* non-zero argument. */
- if ( y4 < *min ) *min = y4;
- else if ( y4 > *max ) *max = y4;
+ if ( p2 > *max || p3 > *max )
+ *max += cubic_peak( p1 - *max, p2 - *max, p3 - *max, p4 - *max );
- /* now, try to see if there are split points here */
- if ( y1 <= y4 )
- {
- /* flat or ascending arc test */
- if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
- return;
- }
- else /* y1 > y4 */
- {
- /* descending arc test */
- if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
- return;
- }
-
- /* There are some split points. Find them. */
- /* We already made sure that a, b, and c below cannot be all zero. */
- {
- FT_Pos a = y4 - 3*y3 + 3*y2 - y1;
- FT_Pos b = y3 - 2*y2 + y1;
- FT_Pos c = y2 - y1;
- FT_Pos d;
- FT_Fixed t;
- FT_Int shift;
-
-
- /* We need to solve `ax^2+2bx+c' here, without floating points! */
- /* The trick is to normalize to a different representation in order */
- /* to use our 16.16 fixed-point routines. */
- /* */
- /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
- /* These values must fit into a single 16.16 value. */
- /* */
- /* We normalize a, b, and c to `8.16' fixed-point values to ensure */
- /* that their product is held in a `16.16' value including the sign. */
- /* Necessarily, we need to shift `a', `b', and `c' so that the most */
- /* significant bit of their absolute values is at position 22. */
- /* */
- /* This also means that we are using 23 bits of precision to compute */
- /* the zeros, independently of the range of the original polynomial */
- /* coefficients. */
- /* */
- /* This algorithm should ensure reasonably accurate values for the */
- /* zeros. Note that they are only expressed with 16 bits when */
- /* computing the extrema (the zeros need to be in 0..1 exclusive */
- /* to be considered part of the arc). */
-
- shift = FT_MSB( FT_ABS( a ) | FT_ABS( b ) | FT_ABS( c ) );
-
- if ( shift > 22 )
- {
- shift -= 22;
-
- /* this loses some bits of precision, but we use 23 of them */
- /* for the computation anyway */
- a >>= shift;
- b >>= shift;
- c >>= shift;
- }
- else
- {
- shift = 22 - shift;
-
- a <<= shift;
- b <<= shift;
- c <<= shift;
- }
-
- /* handle a == 0 */
- if ( a == 0 )
- {
- if ( b != 0 )
- {
- t = - FT_DivFix( c, b ) / 2;
- test_cubic_extrema( y1, y2, y3, y4, t, min, max );
- }
- }
- else
- {
- /* solve the equation now */
- d = FT_MulFix( b, b ) - FT_MulFix( a, c );
- if ( d < 0 )
- return;
-
- if ( d == 0 )
- {
- /* there is a single split point at -b/a */
- t = - FT_DivFix( b, a );
- test_cubic_extrema( y1, y2, y3, y4, t, min, max );
- }
- else
- {
- /* there are two solutions; we need to filter them */
- d = FT_SqrtFixed( (FT_Int32)d );
- t = - FT_DivFix( b - d, a );
- test_cubic_extrema( y1, y2, y3, y4, t, min, max );
-
- t = - FT_DivFix( b + d, a );
- test_cubic_extrema( y1, y2, y3, y4, t, min, max );
- }
- }
- }
+ /* now flip the signs to update the minimum */
+ if ( p2 < *min || p3 < *min )
+ *min -= cubic_peak( *min - p1, *min - p2, *min - p3, *min - p4 );
}
-#endif
-
/*************************************************************************/
/* */
@@ -521,8 +395,9 @@
FT_Vector* to,
TBBox_Rec* user )
{
- /* we don't need to check `to' since it is always an `on' point, thus */
- /* within the bbox */
+ /* We don't need to check `to' since it is always an on-point, */
+ /* thus within the bbox. Only segments with an off-point outside */
+ /* the bbox can possibly reach new extreme values. */
if ( CHECK_X( control1, user->bbox ) ||
CHECK_X( control2, user->bbox ) )
@@ -547,22 +422,26 @@
return 0;
}
-FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
+
+ FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
(FT_Outline_MoveTo_Func) BBox_Move_To,
- (FT_Outline_LineTo_Func) BBox_Move_To,
+ (FT_Outline_LineTo_Func) BBox_Line_To,
(FT_Outline_ConicTo_Func)BBox_Conic_To,
(FT_Outline_CubicTo_Func)BBox_Cubic_To,
0, 0
)
+
/* documentation is in ftbbox.h */
FT_EXPORT_DEF( FT_Error )
FT_Outline_Get_BBox( FT_Outline* outline,
FT_BBox *abbox )
{
- FT_BBox cbox;
- FT_BBox bbox;
+ FT_BBox cbox = { 0x7FFFFFFFL, 0x7FFFFFFFL,
+ -0x7FFFFFFFL, -0x7FFFFFFFL };
+ FT_BBox bbox = { 0x7FFFFFFFL, 0x7FFFFFFFL,
+ -0x7FFFFFFFL, -0x7FFFFFFFL };
FT_Vector* vec;
FT_UShort n;
@@ -586,32 +465,13 @@
/* coincide, we exit immediately. */
vec = outline->points;
- bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
- bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
- vec++;
- for ( n = 1; n < outline->n_points; n++ )
+ for ( n = 0; n < outline->n_points; n++ )
{
- FT_Pos x = vec->x;
- FT_Pos y = vec->y;
-
-
- /* update control box */
- if ( x < cbox.xMin ) cbox.xMin = x;
- if ( x > cbox.xMax ) cbox.xMax = x;
-
- if ( y < cbox.yMin ) cbox.yMin = y;
- if ( y > cbox.yMax ) cbox.yMax = y;
+ FT_UPDATE_BBOX( vec, cbox);
if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
- {
- /* update bbox for `on' points only */
- if ( x < bbox.xMin ) bbox.xMin = x;
- if ( x > bbox.xMax ) bbox.xMax = x;
-
- if ( y < bbox.yMin ) bbox.yMin = y;
- if ( y > bbox.yMax ) bbox.yMax = y;
- }
+ FT_UPDATE_BBOX( vec, bbox);
vec++;
}
diff --git a/src/base/ftbdf.c b/src/base/ftbdf.c
new file mode 100644
index 0000000..aa72ddc
--- /dev/null
+++ b/src/base/ftbdf.c
@@ -0,0 +1,91 @@
+/***************************************************************************/
+/* */
+/* ftbdf.c */
+/* */
+/* FreeType API for accessing BDF-specific strings (body). */
+/* */
+/* Copyright 2002-2015 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 <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_BDF_H
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Charset_ID( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry )
+ {
+ FT_Error error;
+ const char* encoding = NULL;
+ const char* registry = NULL;
+
+ FT_Service_BDF service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_charset_id )
+ error = service->get_charset_id( face, &encoding, ®istry );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ if ( acharset_encoding )
+ *acharset_encoding = encoding;
+
+ if ( acharset_registry )
+ *acharset_registry = registry;
+
+ return error;
+ }
+
+
+ /* documentation is in ftbdf.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_BDF_Property( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty )
+ {
+ FT_Error error;
+
+ FT_Service_BDF service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !aproperty )
+ return FT_THROW( Invalid_Argument );
+
+ aproperty->type = BDF_PROPERTY_TYPE_NONE;
+
+ FT_FACE_FIND_SERVICE( face, service, BDF );
+
+ if ( service && service->get_property )
+ error = service->get_property( face, prop_name, aproperty );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 975818e..a54572a 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility functions for bitmaps (body). */
/* */
-/* Copyright 2004-2009, 2011, 2013 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,9 +31,20 @@
/* documentation is in ftbitmap.h */
FT_EXPORT_DEF( void )
+ FT_Bitmap_Init( FT_Bitmap *abitmap )
+ {
+ if ( abitmap )
+ *abitmap = null_bitmap;
+ }
+
+
+ /* deprecated function name; retained for ABI compatibility */
+
+ FT_EXPORT_DEF( void )
FT_Bitmap_New( FT_Bitmap *abitmap )
{
- *abitmap = null_bitmap;
+ if ( abitmap )
+ *abitmap = null_bitmap;
}
@@ -44,25 +55,42 @@
const FT_Bitmap *source,
FT_Bitmap *target)
{
- FT_Memory memory = library->memory;
+ FT_Memory memory;
FT_Error error = FT_Err_Ok;
- FT_Int pitch = source->pitch;
- FT_ULong size;
+ FT_Int pitch;
+ FT_ULong size;
+
+ FT_Int source_pitch_sign, target_pitch_sign;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !source || !target )
+ return FT_THROW( Invalid_Argument );
if ( source == target )
return FT_Err_Ok;
+ source_pitch_sign = source->pitch < 0 ? -1 : 1;
+ target_pitch_sign = target->pitch < 0 ? -1 : 1;
+
if ( source->buffer == NULL )
{
*target = *source;
+ if ( source_pitch_sign != target_pitch_sign )
+ target->pitch = -target->pitch;
return FT_Err_Ok;
}
+ memory = library->memory;
+ pitch = source->pitch;
+
if ( pitch < 0 )
pitch = -pitch;
- size = (FT_ULong)( pitch * source->rows );
+ size = (FT_ULong)pitch * source->rows;
if ( target->buffer )
{
@@ -70,9 +98,9 @@
FT_ULong target_size;
- if ( target_pitch < 0 )
+ if ( target_pitch < 0 )
target_pitch = -target_pitch;
- target_size = (FT_ULong)( target_pitch * target->rows );
+ target_size = (FT_ULong)target_pitch * target->rows;
if ( target_size != size )
(void)FT_QREALLOC( target->buffer, target_size, size );
@@ -89,13 +117,35 @@
*target = *source;
target->buffer = p;
- FT_MEM_COPY( target->buffer, source->buffer, size );
+ if ( source_pitch_sign == target_pitch_sign )
+ FT_MEM_COPY( target->buffer, source->buffer, size );
+ else
+ {
+ /* take care of bitmap flow */
+ FT_UInt i;
+ FT_Byte* s = source->buffer;
+ FT_Byte* t = target->buffer;
+
+
+ t += (FT_ULong)pitch * ( target->rows - 1 );
+
+ for ( i = target->rows; i > 0; i-- )
+ {
+ FT_ARRAY_COPY( t, s, pitch );
+
+ s += pitch;
+ t -= pitch;
+ }
+ }
}
return error;
}
+ /* Enlarge `bitmap' horizontally and vertically by `xpixels' */
+ /* and `ypixels', respectively. */
+
static FT_Error
ft_bitmap_assure_buffer( FT_Memory memory,
FT_Bitmap* bitmap,
@@ -106,7 +156,7 @@
int pitch;
int new_pitch;
FT_UInt bpp;
- FT_Int i, width, height;
+ FT_UInt i, width, height;
unsigned char* buffer = NULL;
@@ -120,21 +170,21 @@
{
case FT_PIXEL_MODE_MONO:
bpp = 1;
- new_pitch = ( width + xpixels + 7 ) >> 3;
+ new_pitch = (int)( ( width + xpixels + 7 ) >> 3 );
break;
case FT_PIXEL_MODE_GRAY2:
bpp = 2;
- new_pitch = ( width + xpixels + 3 ) >> 2;
+ new_pitch = (int)( ( width + xpixels + 3 ) >> 2 );
break;
case FT_PIXEL_MODE_GRAY4:
bpp = 4;
- new_pitch = ( width + xpixels + 1 ) >> 1;
+ new_pitch = (int)( ( width + xpixels + 1 ) >> 1 );
break;
case FT_PIXEL_MODE_GRAY:
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
bpp = 8;
- new_pitch = ( width + xpixels );
+ new_pitch = (int)( width + xpixels );
break;
default:
return FT_THROW( Invalid_Glyph_Format );
@@ -144,17 +194,17 @@
if ( ypixels == 0 && new_pitch <= pitch )
{
/* zero the padding */
- FT_Int bit_width = pitch * 8;
- FT_Int bit_last = ( width + xpixels ) * bpp;
+ FT_UInt bit_width = (FT_UInt)pitch * 8;
+ FT_UInt bit_last = ( width + xpixels ) * bpp;
if ( bit_last < bit_width )
{
FT_Byte* line = bitmap->buffer + ( bit_last >> 3 );
FT_Byte* end = bitmap->buffer + pitch;
- FT_Int shift = bit_last & 7;
+ FT_UInt shift = bit_last & 7;
FT_UInt mask = 0xFF00U >> shift;
- FT_Int count = height;
+ FT_UInt count = height;
for ( ; count > 0; count--, line += pitch, end += pitch )
@@ -168,33 +218,38 @@
write++;
}
if ( write < end )
- FT_MEM_ZERO( write, end-write );
+ FT_MEM_ZERO( write, end - write );
}
}
return FT_Err_Ok;
}
+ /* otherwise allocate new buffer */
if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) )
return error;
+ /* new rows get added at the top of the bitmap, */
+ /* thus take care of the flow direction */
if ( bitmap->pitch > 0 )
{
- FT_Int len = ( width * bpp + 7 ) >> 3;
+ FT_UInt len = ( width * bpp + 7 ) >> 3;
for ( i = 0; i < bitmap->rows; i++ )
- FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ),
- bitmap->buffer + pitch * i, len );
+ FT_MEM_COPY( buffer + (FT_UInt)new_pitch * ( ypixels + i ),
+ bitmap->buffer + (FT_UInt)pitch * i,
+ len );
}
else
{
- FT_Int len = ( width * bpp + 7 ) >> 3;
+ FT_UInt len = ( width * bpp + 7 ) >> 3;
for ( i = 0; i < bitmap->rows; i++ )
- FT_MEM_COPY( buffer + new_pitch * i,
- bitmap->buffer + pitch * i, len );
+ FT_MEM_COPY( buffer + (FT_UInt)new_pitch * i,
+ bitmap->buffer + (FT_UInt)pitch * i,
+ len );
}
FT_FREE( bitmap->buffer );
@@ -220,7 +275,8 @@
{
FT_Error error;
unsigned char* p;
- FT_Int i, x, y, pitch;
+ FT_Int i, x, pitch;
+ FT_UInt y;
FT_Int xstr, ystr;
@@ -248,17 +304,11 @@
case FT_PIXEL_MODE_GRAY4:
{
FT_Bitmap tmp;
- FT_Int align;
- if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY2 )
- align = ( bitmap->width + xstr + 3 ) / 4;
- else
- align = ( bitmap->width + xstr + 1 ) / 2;
-
- FT_Bitmap_New( &tmp );
-
- error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
+ /* convert to 8bpp */
+ FT_Bitmap_Init( &tmp );
+ error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 );
if ( error )
return error;
@@ -285,17 +335,19 @@
return FT_Err_Ok;
}
- error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
+ error = ft_bitmap_assure_buffer( library->memory, bitmap,
+ (FT_UInt)xstr, (FT_UInt)ystr );
if ( error )
return error;
+ /* take care of bitmap flow */
pitch = bitmap->pitch;
if ( pitch > 0 )
p = bitmap->buffer + pitch * ystr;
else
{
pitch = -pitch;
- p = bitmap->buffer + pitch * ( bitmap->rows - 1 );
+ p = bitmap->buffer + (FT_UInt)pitch * ( bitmap->rows - 1 );
}
/* for each row */
@@ -309,7 +361,7 @@
*/
for ( x = pitch - 1; x >= 0; x-- )
{
- unsigned char tmp;
+ unsigned char tmp;
tmp = p[x];
@@ -324,7 +376,7 @@
p[x] |= p[x - 1] << ( 8 - i );
#if 0
- if ( p[x] == 0xff )
+ if ( p[x] == 0xFF )
break;
#endif
}
@@ -334,12 +386,12 @@
{
if ( p[x] + p[x - i] > bitmap->num_grays - 1 )
{
- p[x] = (unsigned char)(bitmap->num_grays - 1);
+ p[x] = (unsigned char)( bitmap->num_grays - 1 );
break;
}
else
{
- p[x] = (unsigned char)(p[x] + p[x-i]);
+ p[x] = (unsigned char)( p[x] + p[x - i] );
if ( p[x] == bitmap->num_grays - 1 )
break;
}
@@ -368,63 +420,56 @@
p += bitmap->pitch;
}
- bitmap->width += xstr;
- bitmap->rows += ystr;
+ bitmap->width += (FT_UInt)xstr;
+ bitmap->rows += (FT_UInt)ystr;
return FT_Err_Ok;
}
- FT_Byte
+ static FT_Byte
ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra )
{
- FT_Long a = bgra[3];
- FT_Long b = bgra[0];
- FT_Long g = bgra[1];
- FT_Long r = bgra[2];
- FT_Long l;
+ FT_UInt a = bgra[3];
+ FT_UInt l;
+ /* Short-circuit transparent color to avoid division by zero. */
+ if ( !a )
+ return 0;
+
/*
* Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
* coefficients for RGB channels *on the linear colors*.
* A gamma of 2.2 is fair to assume. And then, we need to
* undo the premultiplication too.
*
- * http://accessibility.kde.org/hsl-adjusted.php
+ * http://accessibility.kde.org/hsl-adjusted.php
*
- * We do the computation with integers only.
+ * We do the computation with integers only, applying a gamma of 2.0.
+ * We guarantee 32-bit arithmetic to avoid overflow but the resulting
+ * luminosity fits into 16 bits.
+ *
*/
- /* Undo premultification, get the number in a 16.16 form. */
- b = FT_MulDiv( b, 65536, a );
- g = FT_MulDiv( g, 65536, a );
- r = FT_MulDiv( r, 65536, a );
- a = a * 256;
-
- /* Apply gamma of 2.0 instead of 2.2. */
- b = FT_MulFix( b, b );
- g = FT_MulFix( g, g );
- r = FT_MulFix( r, r );
-
- /* Apply coefficients. */
- b = FT_MulFix( b, 4731 /* 0.0722 * 65536 */ );
- g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ );
- r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ );
-
- l = r + g + b;
+ l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
+ 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
+ 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
/*
- * Final transparency can be determined this way:
+ * Final transparency can be determined as follows.
*
* - If alpha is zero, we want 0.
* - If alpha is zero and luminosity is zero, we want 255.
* - If alpha is zero and luminosity is one, we want 0.
*
- * So the formula is a * (1 - l).
+ * So the formula is a * (1 - l) = a - l * a.
+ *
+ * We still need to undo premultiplication by dividing l by a*a.
+ *
*/
- return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 );
+ return (FT_Byte)( a - l / a );
}
@@ -439,10 +484,16 @@
FT_Error error = FT_Err_Ok;
FT_Memory memory;
+ FT_Byte* s;
+ FT_Byte* t;
+
if ( !library )
return FT_THROW( Invalid_Library_Handle );
+ if ( !source || !target )
+ return FT_THROW( Invalid_Argument );
+
memory = library->memory;
switch ( source->pixel_mode )
@@ -455,13 +506,15 @@
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_BGRA:
{
- FT_Int pad;
- FT_Long old_size;
+ FT_Int pad, old_target_pitch, target_pitch;
+ FT_ULong old_size;
- old_size = target->rows * target->pitch;
- if ( old_size < 0 )
- old_size = -old_size;
+ old_target_pitch = target->pitch;
+ if ( old_target_pitch < 0 )
+ old_target_pitch = -old_target_pitch;
+
+ old_size = target->rows * (FT_UInt)old_target_pitch;
target->pixel_mode = FT_PIXEL_MODE_GRAY;
target->rows = source->rows;
@@ -470,21 +523,23 @@
pad = 0;
if ( alignment > 0 )
{
- pad = source->width % alignment;
+ pad = (FT_Int)source->width % alignment;
if ( pad != 0 )
pad = alignment - pad;
}
- target->pitch = source->width + pad;
+ target_pitch = (FT_Int)source->width + pad;
- if ( target->pitch > 0 &&
- (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
+ if ( target_pitch > 0 &&
+ (FT_ULong)target->rows > FT_ULONG_MAX / (FT_ULong)target_pitch )
return FT_THROW( Invalid_Argument );
- if ( target->rows * target->pitch > old_size &&
+ if ( target->rows * (FT_ULong)target_pitch > old_size &&
FT_QREALLOC( target->buffer,
- old_size, target->rows * target->pitch ) )
+ old_size, target->rows * (FT_UInt)target_pitch ) )
return error;
+
+ target->pitch = target->pitch < 0 ? -target_pitch : target_pitch;
}
break;
@@ -492,13 +547,20 @@
error = FT_THROW( Invalid_Argument );
}
+ s = source->buffer;
+ t = target->buffer;
+
+ /* take care of bitmap flow */
+ if ( source->pitch < 0 )
+ s -= source->pitch * (FT_Int)( source->rows - 1 );
+ if ( target->pitch < 0 )
+ t -= target->pitch * (FT_Int)( target->rows - 1 );
+
switch ( source->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
{
- FT_Byte* s = source->buffer;
- FT_Byte* t = target->buffer;
- FT_Int i;
+ FT_UInt i;
target->num_grays = 2;
@@ -507,7 +569,7 @@
{
FT_Byte* ss = s;
FT_Byte* tt = t;
- FT_Int j;
+ FT_UInt j;
/* get the full bytes */
@@ -555,12 +617,8 @@
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
{
- FT_Int width = source->width;
- FT_Byte* s = source->buffer;
- FT_Byte* t = target->buffer;
- FT_Int s_pitch = source->pitch;
- FT_Int t_pitch = target->pitch;
- FT_Int i;
+ FT_UInt width = source->width;
+ FT_UInt i;
target->num_grays = 256;
@@ -569,8 +627,8 @@
{
FT_ARRAY_COPY( t, s, width );
- s += s_pitch;
- t += t_pitch;
+ s += source->pitch;
+ t += target->pitch;
}
}
break;
@@ -578,9 +636,7 @@
case FT_PIXEL_MODE_GRAY2:
{
- FT_Byte* s = source->buffer;
- FT_Byte* t = target->buffer;
- FT_Int i;
+ FT_UInt i;
target->num_grays = 4;
@@ -589,7 +645,7 @@
{
FT_Byte* ss = s;
FT_Byte* tt = t;
- FT_Int j;
+ FT_UInt j;
/* get the full bytes */
@@ -630,9 +686,7 @@
case FT_PIXEL_MODE_GRAY4:
{
- FT_Byte* s = source->buffer;
- FT_Byte* t = target->buffer;
- FT_Int i;
+ FT_UInt i;
target->num_grays = 16;
@@ -641,7 +695,7 @@
{
FT_Byte* ss = s;
FT_Byte* tt = t;
- FT_Int j;
+ FT_UInt j;
/* get the full bytes */
@@ -666,13 +720,10 @@
}
break;
+
case FT_PIXEL_MODE_BGRA:
{
- FT_Byte* s = source->buffer;
- FT_Byte* t = target->buffer;
- FT_Int s_pitch = source->pitch;
- FT_Int t_pitch = target->pitch;
- FT_Int i;
+ FT_UInt i;
target->num_grays = 256;
@@ -681,7 +732,7 @@
{
FT_Byte* ss = s;
FT_Byte* tt = t;
- FT_Int j;
+ FT_UInt j;
for ( j = source->width; j > 0; j-- )
@@ -692,8 +743,8 @@
tt += 1;
}
- s += s_pitch;
- t += t_pitch;
+ s += source->pitch;
+ t += target->pitch;
}
}
break;
@@ -718,7 +769,7 @@
FT_Error error;
- FT_Bitmap_New( &bitmap );
+ FT_Bitmap_Init( &bitmap );
error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap );
if ( error )
return error;
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index 0ec0d78..619a08b 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -4,7 +4,7 @@
/* */
/* Arithmetic computations (body). */
/* */
-/* Copyright 1996-2006, 2008, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -39,7 +39,8 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
-#ifdef FT_MULFIX_INLINED
+
+#ifdef FT_MULFIX_ASSEMBLER
#undef FT_MulFix
#endif
@@ -67,6 +68,16 @@
#define FT_COMPONENT trace_calc
+ /* transfer sign leaving a positive number */
+#define FT_MOVE_SIGN( x, s ) \
+ FT_BEGIN_STMNT \
+ if ( x < 0 ) \
+ { \
+ x = -x; \
+ s = -s; \
+ } \
+ FT_END_STMNT
+
/* The following three functions are available regardless of whether */
/* FT_LONG64 is defined. */
@@ -75,8 +86,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix( FT_Fixed a )
{
- return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL
- : -((-a + 0x8000L ) & ~0xFFFFL );
+ return ( a + 0x8000L - ( a < 0 ) ) & ~0xFFFFL;
}
@@ -85,8 +95,7 @@
FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix( FT_Fixed a )
{
- return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL
- : -((-a + 0xFFFFL ) & ~0xFFFFL );
+ return ( a + 0xFFFFL ) & ~0xFFFFL;
}
@@ -95,46 +104,49 @@
FT_EXPORT_DEF( FT_Fixed )
FT_FloorFix( FT_Fixed a )
{
- return ( a >= 0 ) ? a & ~0xFFFFL
- : -((-a) & ~0xFFFFL );
+ return a & ~0xFFFFL;
}
+#ifndef FT_MSB
FT_BASE_DEF ( FT_Int )
FT_MSB( FT_UInt32 z )
{
- FT_Int shift = 0;
+ FT_Int shift = 0;
+
/* determine msb bit index in `shift' */
- if ( z >= ( 1L << 16 ) )
+ if ( z & 0xFFFF0000UL )
{
z >>= 16;
shift += 16;
}
- if ( z >= ( 1L << 8 ) )
+ if ( z & 0x0000FF00UL )
{
z >>= 8;
shift += 8;
}
- if ( z >= ( 1L << 4 ) )
+ if ( z & 0x000000F0UL )
{
z >>= 4;
shift += 4;
}
- if ( z >= ( 1L << 2 ) )
+ if ( z & 0x0000000CUL )
{
z >>= 2;
shift += 2;
}
- if ( z >= ( 1L << 1 ) )
+ if ( z & 0x00000002UL )
{
- z >>= 1;
+ /* z >>= 1; */
shift += 1;
}
return shift;
}
+#endif /* !FT_MSB */
+
/* documentation is in ftcalc.h */
@@ -158,80 +170,77 @@
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
- FT_MulDiv( FT_Long a,
- FT_Long b,
- FT_Long c )
+ FT_MulDiv( FT_Long a_,
+ FT_Long b_,
+ FT_Long c_ )
{
- FT_Int s;
- FT_Long d;
+ FT_Int s = 1;
+ FT_UInt64 a, b, c, d;
+ FT_Long d_;
- s = 1;
- if ( a < 0 ) { a = -a; s = -1; }
- if ( b < 0 ) { b = -b; s = -s; }
- if ( c < 0 ) { c = -c; s = -s; }
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
+ FT_MOVE_SIGN( c_, s );
- d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
- : 0x7FFFFFFFL );
+ a = (FT_UInt64)a_;
+ b = (FT_UInt64)b_;
+ c = (FT_UInt64)c_;
- return ( s > 0 ) ? d : -d;
+ d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
+ : 0x7FFFFFFFUL;
+
+ d_ = (FT_Long)d;
+
+ return s < 0 ? -d_ : d_;
}
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Long )
- FT_MulDiv_No_Round( FT_Long a,
- FT_Long b,
- FT_Long c )
+ FT_MulDiv_No_Round( FT_Long a_,
+ FT_Long b_,
+ FT_Long c_ )
{
- FT_Int s;
- FT_Long d;
+ FT_Int s = 1;
+ FT_UInt64 a, b, c, d;
+ FT_Long d_;
- s = 1;
- if ( a < 0 ) { a = -a; s = -1; }
- if ( b < 0 ) { b = -b; s = -s; }
- if ( c < 0 ) { c = -c; s = -s; }
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
+ FT_MOVE_SIGN( c_, s );
- d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
- : 0x7FFFFFFFL );
+ a = (FT_UInt64)a_;
+ b = (FT_UInt64)b_;
+ c = (FT_UInt64)c_;
- return ( s > 0 ) ? d : -d;
+ d = c > 0 ? a * b / c
+ : 0x7FFFFFFFUL;
+
+ d_ = (FT_Long)d;
+
+ return s < 0 ? -d_ : d_;
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
- FT_MulFix( FT_Long a,
- FT_Long b )
+ FT_MulFix( FT_Long a_,
+ FT_Long b_ )
{
#ifdef FT_MULFIX_ASSEMBLER
- return FT_MULFIX_ASSEMBLER( a, b );
+ return FT_MULFIX_ASSEMBLER( a_, b_ );
#else
- FT_Int s = 1;
- FT_Long c;
+ FT_Int64 ab = (FT_Int64)a_ * (FT_Int64)b_;
-
- if ( a < 0 )
- {
- a = -a;
- s = -1;
- }
-
- if ( b < 0 )
- {
- b = -b;
- s = -s;
- }
-
- c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
-
- return ( s > 0 ) ? c : -c;
+ /* this requires arithmetic right shift of signed numbers */
+ return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 );
#endif /* FT_MULFIX_ASSEMBLER */
}
@@ -240,33 +249,26 @@
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
- FT_DivFix( FT_Long a,
- FT_Long b )
+ FT_DivFix( FT_Long a_,
+ FT_Long b_ )
{
- FT_Int32 s;
- FT_UInt32 q;
+ FT_Int s = 1;
+ FT_UInt64 a, b, q;
+ FT_Long q_;
- s = 1;
- if ( a < 0 )
- {
- a = -a;
- s = -1;
- }
- if ( b < 0 )
- {
- b = -b;
- s = -s;
- }
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
- if ( b == 0 )
- /* check for division by 0 */
- q = 0x7FFFFFFFL;
- else
- /* compute result directly */
- q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b );
+ a = (FT_UInt64)a_;
+ b = (FT_UInt64)b_;
- return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
+ q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
+ : 0x7FFFFFFFUL;
+
+ q_ = (FT_Long)q;
+
+ return s < 0 ? -q_ : q_;
}
@@ -314,25 +316,30 @@
FT_Int i;
- q = 0;
- r = hi;
-
- if ( r >= y )
+ if ( hi >= y )
return (FT_UInt32)0x7FFFFFFFL;
- i = 32;
+ /* We shift as many bits as we can into the high register, perform */
+ /* 32-bit division with modulo there, then work through the remaining */
+ /* bits with long division. This optimization is especially noticeable */
+ /* for smaller dividends that barely use the high register. */
+
+ i = 31 - FT_MSB( hi );
+ r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */
+ q = r / y;
+ r -= q * y; /* remainder */
+
+ i = 32 - i; /* bits remaining in low register */
do
{
- r <<= 1;
q <<= 1;
- r |= lo >> 31;
+ r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;
if ( r >= y )
{
r -= y;
q |= 1;
}
- lo <<= 1;
} while ( --i );
return q;
@@ -344,7 +351,7 @@
FT_Int64* y,
FT_Int64 *z )
{
- register FT_UInt32 lo, hi;
+ FT_UInt32 lo, hi;
lo = x->lo + y->lo;
@@ -355,105 +362,155 @@
}
+ /* The FT_MulDiv function has been optimized thanks to ideas from */
+ /* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */
+ /* a rather common case when everything fits within 32-bits. */
+ /* */
+ /* We compute 'a*b+c/2', then divide it by 'c' (all positive values). */
+ /* */
+ /* The product of two positive numbers never exceeds the square of */
+ /* its mean values. Therefore, we always avoid the overflow by */
+ /* imposing */
+ /* */
+ /* (a + b) / 2 <= sqrt(X - c/2) , */
+ /* */
+ /* where X = 2^32 - 1, the maximum unsigned 32-bit value, and using */
+ /* unsigned arithmetic. Now we replace `sqrt' with a linear function */
+ /* that is smaller or equal for all values of c in the interval */
+ /* [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the */
+ /* endpoints. Substituting the linear solution and explicit numbers */
+ /* we get */
+ /* */
+ /* a + b <= 131071.99 - c / 122291.84 . */
+ /* */
+ /* In practice, we should use a faster and even stronger inequality */
+ /* */
+ /* a + b <= 131071 - (c >> 16) */
+ /* */
+ /* or, alternatively, */
+ /* */
+ /* a + b <= 129894 - (c >> 17) . */
+ /* */
+ /* FT_MulFix, on the other hand, is optimized for a small value of */
+ /* the first argument, when the second argument can be much larger. */
+ /* This can be achieved by scaling the second argument and the limit */
+ /* in the above inequalities. For example, */
+ /* */
+ /* a + (b >> 8) <= (131071 >> 4) */
+ /* */
+ /* covers the practical range of use. The actual test below is a bit */
+ /* tighter to avoid the border case overflows. */
+ /* */
+ /* In the case of FT_DivFix, the exact overflow check */
+ /* */
+ /* a << 16 <= X - c/2 */
+ /* */
+ /* is scaled down by 2^16 and we use */
+ /* */
+ /* a <= 65535 - (c >> 17) . */
+
/* documentation is in freetype.h */
- /* The FT_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 */
- /* */
-
FT_EXPORT_DEF( FT_Long )
- FT_MulDiv( FT_Long a,
- FT_Long b,
- FT_Long c )
+ FT_MulDiv( FT_Long a_,
+ FT_Long b_,
+ FT_Long c_ )
{
- long s;
+ FT_Int s = 1;
+ FT_UInt32 a, b, c;
/* XXX: this function does not allow 64-bit arguments */
- if ( a == 0 || b == c )
- return a;
- s = a; a = FT_ABS( a );
- s ^= b; b = FT_ABS( b );
- s ^= c; c = FT_ABS( c );
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
+ FT_MOVE_SIGN( c_, s );
- if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
+ a = (FT_UInt32)a_;
+ b = (FT_UInt32)b_;
+ c = (FT_UInt32)c_;
+
+ if ( c == 0 )
+ a = 0x7FFFFFFFUL;
+
+ else if ( a + b <= 129894UL - ( c >> 17 ) )
a = ( a * b + ( c >> 1 ) ) / c;
- else if ( (FT_Int32)c > 0 )
+ else
{
FT_Int64 temp, temp2;
- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
+ ft_multo64( a, b, &temp );
temp2.hi = 0;
- temp2.lo = (FT_UInt32)(c >> 1);
- FT_Add64( &temp, &temp2, &temp );
- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
- }
- else
- a = 0x7FFFFFFFL;
+ temp2.lo = c >> 1;
- return ( s < 0 ? -a : a );
+ FT_Add64( &temp, &temp2, &temp );
+
+ /* last attempt to ditch long division */
+ a = temp.hi == 0 ? temp.lo / c
+ : ft_div64by32( temp.hi, temp.lo, c );
+ }
+
+ a_ = (FT_Long)a;
+
+ return s < 0 ? -a_ : a_;
}
FT_BASE_DEF( FT_Long )
- FT_MulDiv_No_Round( FT_Long a,
- FT_Long b,
- FT_Long c )
+ FT_MulDiv_No_Round( FT_Long a_,
+ FT_Long b_,
+ FT_Long c_ )
{
- long s;
+ FT_Int s = 1;
+ FT_UInt32 a, b, c;
- if ( a == 0 || b == c )
- return a;
+ /* XXX: this function does not allow 64-bit arguments */
- s = a; a = FT_ABS( a );
- s ^= b; b = FT_ABS( b );
- s ^= c; c = FT_ABS( c );
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
+ FT_MOVE_SIGN( c_, s );
- if ( a <= 46340L && b <= 46340L && c > 0 )
+ a = (FT_UInt32)a_;
+ b = (FT_UInt32)b_;
+ c = (FT_UInt32)c_;
+
+ if ( c == 0 )
+ a = 0x7FFFFFFFUL;
+
+ else if ( a + b <= 131071UL )
a = a * b / c;
- else if ( (FT_Int32)c > 0 )
+ else
{
FT_Int64 temp;
- ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
- a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
- }
- else
- a = 0x7FFFFFFFL;
+ ft_multo64( a, b, &temp );
- return ( s < 0 ? -a : a );
+ /* last attempt to ditch long division */
+ a = temp.hi == 0 ? temp.lo / c
+ : ft_div64by32( temp.hi, temp.lo, c );
+ }
+
+ a_ = (FT_Long)a;
+
+ return s < 0 ? -a_ : a_;
}
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
- FT_MulFix( FT_Long a,
- FT_Long b )
+ FT_MulFix( FT_Long a_,
+ FT_Long b_ )
{
#ifdef FT_MULFIX_ASSEMBLER
- return FT_MULFIX_ASSEMBLER( a, b );
+ return FT_MULFIX_ASSEMBLER( a_, b_ );
#elif 0
@@ -464,13 +521,10 @@
* the leftmost bits by copying the sign bit, it might be faster.
*/
- FT_Long sa, sb;
- FT_ULong ua, ub;
+ FT_Long sa, sb;
+ FT_UInt32 a, b;
- if ( a == 0 || b == 0x10000L )
- return a;
-
/*
* This is a clever way of converting a signed number `a' into its
* absolute value (stored back into `a') and its sign. The sign is
@@ -489,57 +543,58 @@
* with the value 1 rather than -1. After that, everything else goes
* wrong.
*/
- sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
- a = ( a ^ sa ) - sa;
- sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
- b = ( b ^ sb ) - sb;
+ sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) );
+ a = ( a_ ^ sa ) - sa;
+ sb = ( b_ >> ( sizeof ( b_ ) * 8 - 1 ) );
+ b = ( b_ ^ sb ) - sb;
- ua = (FT_ULong)a;
- ub = (FT_ULong)b;
+ a = (FT_UInt32)a_;
+ b = (FT_UInt32)b_;
- if ( ua <= 2048 && ub <= 1048576L )
- ua = ( ua * ub + 0x8000U ) >> 16;
+ if ( a + ( b >> 8 ) <= 8190UL )
+ a = ( a * b + 0x8000U ) >> 16;
else
{
- FT_ULong al = ua & 0xFFFFU;
+ FT_UInt32 al = a & 0xFFFFUL;
- ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
- ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
+ a = ( a >> 16 ) * b + al * ( b >> 16 ) +
+ ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
}
- sa ^= sb,
- ua = (FT_ULong)(( ua ^ sa ) - sa);
+ sa ^= sb;
+ a = ( a ^ sa ) - sa;
- return (FT_Long)ua;
+ return (FT_Long)a;
#else /* 0 */
- FT_Long s;
- FT_ULong ua, ub;
+ FT_Int s = 1;
+ FT_UInt32 a, b;
- if ( a == 0 || b == 0x10000L )
- return a;
+ /* XXX: this function does not allow 64-bit arguments */
- s = a; a = FT_ABS( a );
- s ^= b; b = FT_ABS( b );
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
- ua = (FT_ULong)a;
- ub = (FT_ULong)b;
+ a = (FT_UInt32)a_;
+ b = (FT_UInt32)b_;
- if ( ua <= 2048 && ub <= 1048576L )
- ua = ( ua * ub + 0x8000UL ) >> 16;
+ if ( a + ( b >> 8 ) <= 8190UL )
+ a = ( a * b + 0x8000UL ) >> 16;
else
{
- FT_ULong al = ua & 0xFFFFUL;
+ FT_UInt32 al = a & 0xFFFFUL;
- ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
- ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
+ a = ( a >> 16 ) * b + al * ( b >> 16 ) +
+ ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
}
- return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
+ a_ = (FT_Long)a;
+
+ return s < 0 ? -a_ : a_;
#endif /* 0 */
@@ -549,26 +604,31 @@
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
- FT_DivFix( FT_Long a,
- FT_Long b )
+ FT_DivFix( FT_Long a_,
+ FT_Long b_ )
{
- FT_Int32 s;
- FT_UInt32 q;
+ FT_Int s = 1;
+ FT_UInt32 a, b, q;
+ FT_Long q_;
/* XXX: this function does not allow 64-bit arguments */
- s = (FT_Int32)a; a = FT_ABS( a );
- s ^= (FT_Int32)b; b = FT_ABS( b );
- if ( (FT_UInt32)b == 0 )
+ FT_MOVE_SIGN( a_, s );
+ FT_MOVE_SIGN( b_, s );
+
+ a = (FT_UInt32)a_;
+ b = (FT_UInt32)b_;
+
+ if ( b == 0 )
{
/* check for division by 0 */
- q = (FT_UInt32)0x7FFFFFFFL;
+ q = 0x7FFFFFFFUL;
}
- else if ( ( a >> 16 ) == 0 )
+ else if ( a <= 65535UL - ( b >> 17 ) )
{
/* compute result directly */
- q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
+ q = ( ( a << 16 ) + ( b >> 1 ) ) / b;
}
else
{
@@ -576,140 +636,22 @@
FT_Int64 temp, temp2;
- temp.hi = (FT_Int32)( a >> 16 );
- temp.lo = (FT_UInt32)a << 16;
+ temp.hi = a >> 16;
+ temp.lo = a << 16;
temp2.hi = 0;
- temp2.lo = (FT_UInt32)( b >> 1 );
+ temp2.lo = b >> 1;
+
FT_Add64( &temp, &temp2, &temp );
- q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );
+ q = ft_div64by32( temp.hi, temp.lo, b );
}
- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+ q_ = (FT_Long)q;
+
+ return s < 0 ? -q_ : q_;
}
-#if 0
-
- /* documentation is in ftcalc.h */
-
- FT_EXPORT_DEF( void )
- FT_MulTo64( FT_Int32 x,
- FT_Int32 y,
- FT_Int64 *z )
- {
- FT_Int32 s;
-
-
- s = x; x = FT_ABS( x );
- s ^= y; y = FT_ABS( y );
-
- ft_multo64( x, y, z );
-
- if ( s < 0 )
- {
- z->lo = (FT_UInt32)-(FT_Int32)z->lo;
- z->hi = ~z->hi + !( z->lo );
- }
- }
-
-
- /* apparently, the second version of this code is not compiled correctly */
- /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
-
-#if 1
-
- FT_EXPORT_DEF( FT_Int32 )
- FT_Div64by32( FT_Int64* x,
- FT_Int32 y )
- {
- FT_Int32 s;
- FT_UInt32 q, r, i, lo;
-
-
- s = x->hi;
- if ( s < 0 )
- {
- x->lo = (FT_UInt32)-(FT_Int32)x->lo;
- x->hi = ~x->hi + !x->lo;
- }
- s ^= y; y = FT_ABS( y );
-
- /* Shortcut */
- if ( x->hi == 0 )
- {
- if ( y > 0 )
- q = x->lo / y;
- else
- q = 0x7FFFFFFFL;
-
- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
- }
-
- r = x->hi;
- lo = x->lo;
-
- if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
- return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
- /* Return Max/Min Int32 if division overflow. */
- /* This includes division by zero! */
- q = 0;
- for ( i = 0; i < 32; i++ )
- {
- r <<= 1;
- q <<= 1;
- r |= lo >> 31;
-
- if ( r >= (FT_UInt32)y )
- {
- r -= y;
- q |= 1;
- }
- lo <<= 1;
- }
-
- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
- }
-
-#else /* 0 */
-
- FT_EXPORT_DEF( FT_Int32 )
- FT_Div64by32( FT_Int64* x,
- FT_Int32 y )
- {
- FT_Int32 s;
- FT_UInt32 q;
-
-
- s = x->hi;
- if ( s < 0 )
- {
- x->lo = (FT_UInt32)-(FT_Int32)x->lo;
- x->hi = ~x->hi + !x->lo;
- }
- s ^= y; y = FT_ABS( y );
-
- /* Shortcut */
- if ( x->hi == 0 )
- {
- if ( y > 0 )
- q = ( x->lo + ( y >> 1 ) ) / y;
- else
- q = 0x7FFFFFFFL;
-
- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
- }
-
- q = ft_div64by32( x->hi, x->lo, y );
-
- return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
- }
-
-#endif /* 0 */
-
-#endif /* 0 */
-
-
-#endif /* FT_LONG64 */
+#endif /* !FT_LONG64 */
/* documentation is in ftglyph.h */
@@ -818,6 +760,104 @@
/* documentation is in ftcalc.h */
+ FT_BASE_DEF( FT_UInt32 )
+ FT_Vector_NormLen( FT_Vector* vector )
+ {
+ FT_Int32 x_ = vector->x;
+ FT_Int32 y_ = vector->y;
+ FT_Int32 b, z;
+ FT_UInt32 x, y, u, v, l;
+ FT_Int sx = 1, sy = 1, shift;
+
+
+ FT_MOVE_SIGN( x_, sx );
+ FT_MOVE_SIGN( y_, sy );
+
+ x = (FT_UInt32)x_;
+ y = (FT_UInt32)y_;
+
+ /* trivial cases */
+ if ( x == 0 )
+ {
+ if ( y > 0 )
+ vector->y = sy * 0x10000;
+ return y;
+ }
+ else if ( y == 0 )
+ {
+ if ( x > 0 )
+ vector->x = sx * 0x10000;
+ return x;
+ }
+
+ /* Estimate length and prenormalize by shifting so that */
+ /* the new approximate length is between 2/3 and 4/3. */
+ /* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps */
+ /* achieve this in 16.16 fixed-point representation. */
+ l = x > y ? x + ( y >> 1 )
+ : y + ( x >> 1 );
+
+ shift = 31 - FT_MSB( l );
+ shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );
+
+ if ( shift > 0 )
+ {
+ x <<= shift;
+ y <<= shift;
+
+ /* re-estimate length for tiny vectors */
+ l = x > y ? x + ( y >> 1 )
+ : y + ( x >> 1 );
+ }
+ else
+ {
+ x >>= -shift;
+ y >>= -shift;
+ l >>= -shift;
+ }
+
+ /* lower linear approximation for reciprocal length minus one */
+ b = 0x10000 - (FT_Int32)l;
+
+ x_ = (FT_Int32)x;
+ y_ = (FT_Int32)y;
+
+ /* Newton's iterations */
+ do
+ {
+ u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
+ v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );
+
+ /* Normalized squared length in the parentheses approaches 2^32. */
+ /* On two's complement systems, converting to signed gives the */
+ /* difference with 2^32 even if the expression wraps around. */
+ z = -(FT_Int32)( u * u + v * v ) / 0x200;
+ z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;
+
+ b += z;
+
+ } while ( z > 0 );
+
+ vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
+ vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;
+
+ /* Conversion to signed helps to recover from likely wrap around */
+ /* in calculating the prenormalized length, because it gives the */
+ /* correct difference with 2^32 on two's complement systems. */
+ l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
+ if ( shift > 0 )
+ l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
+ else
+ l <<= -shift;
+
+ return l;
+ }
+
+
+#if 0
+
+ /* documentation is in ftcalc.h */
+
FT_BASE_DEF( FT_Int32 )
FT_SqrtFixed( FT_Int32 x )
{
@@ -830,7 +870,7 @@
if ( x > 0 )
{
rem_hi = 0;
- rem_lo = x;
+ rem_lo = (FT_UInt32)x;
count = 24;
do
{
@@ -850,6 +890,8 @@
return (FT_Int32)root;
}
+#endif /* 0 */
+
/* documentation is in ftcalc.h */
@@ -859,58 +901,40 @@
FT_Pos out_x,
FT_Pos out_y )
{
- FT_Long result; /* avoid overflow on 16-bit system */
-
-
- /* deal with the trivial cases quickly */
- if ( in_y == 0 )
- {
- if ( in_x >= 0 )
- result = out_y;
- else
- result = -out_y;
- }
- else if ( in_x == 0 )
- {
- if ( in_y >= 0 )
- result = -out_x;
- else
- result = out_x;
- }
- else if ( out_y == 0 )
- {
- if ( out_x >= 0 )
- result = in_y;
- else
- result = -in_y;
- }
- else if ( out_x == 0 )
- {
- if ( out_y >= 0 )
- result = -in_x;
- else
- result = in_x;
- }
- else /* general case */
- {
#ifdef FT_LONG64
- FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
+ FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
- if ( delta == 0 )
- result = 0;
- else
- result = 1 - 2 * ( delta < 0 );
+ return ( delta > 0 ) - ( delta < 0 );
#else
+ FT_Int result;
+
+
+ if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 131071UL &&
+ (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 131071UL )
+ {
+ FT_Long z1 = in_x * out_y;
+ FT_Long z2 = in_y * out_x;
+
+
+ if ( z1 > z2 )
+ result = +1;
+ else if ( z1 < z2 )
+ result = -1;
+ else
+ result = 0;
+ }
+ else /* products might overflow 32 bits */
+ {
FT_Int64 z1, z2;
/* XXX: this function does not allow 64-bit arguments */
- ft_multo64( (FT_Int32)in_x, (FT_Int32)out_y, &z1 );
- ft_multo64( (FT_Int32)in_y, (FT_Int32)out_x, &z2 );
+ ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 );
+ ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 );
if ( z1.hi > z2.hi )
result = +1;
@@ -922,12 +946,12 @@
result = -1;
else
result = 0;
-
-#endif
}
/* XXX: only the sign of return value, +1/0/-1 must be used */
- return (FT_Int)result;
+ return result;
+
+#endif
}
@@ -939,35 +963,40 @@
FT_Pos out_x,
FT_Pos out_y )
{
- FT_Pos ax = in_x;
- FT_Pos ay = in_y;
+ FT_Pos ax = in_x + out_x;
+ FT_Pos ay = in_y + out_y;
- FT_Pos d_in, d_out, d_corner;
+ FT_Pos d_in, d_out, d_hypot;
- if ( ax < 0 )
- ax = -ax;
- if ( ay < 0 )
- ay = -ay;
- d_in = ax + ay;
+ /* The idea of this function is to compare the length of the */
+ /* hypotenuse with the `in' and `out' length. The `corner' */
+ /* represented by `in' and `out' is flat if the hypotenuse's */
+ /* length isn't too large. */
+ /* */
+ /* This approach has the advantage that the angle between */
+ /* `in' and `out' is not checked. In case one of the two */
+ /* vectors is `dominant', this is, much larger than the */
+ /* other vector, we thus always have a flat corner. */
+ /* */
+ /* hypotenuse */
+ /* x---------------------------x */
+ /* \ / */
+ /* \ / */
+ /* in \ / out */
+ /* \ / */
+ /* o */
+ /* Point */
- ax = out_x;
- if ( ax < 0 )
- ax = -ax;
- ay = out_y;
- if ( ay < 0 )
- ay = -ay;
- d_out = ax + ay;
+ d_in = FT_HYPOT( in_x, in_y );
+ d_out = FT_HYPOT( out_x, out_y );
+ d_hypot = FT_HYPOT( ax, ay );
- ax = out_x + in_x;
- if ( ax < 0 )
- ax = -ax;
- ay = out_y + in_y;
- if ( ay < 0 )
- ay = -ay;
- d_corner = ax + ay;
+ /* now do a simple length comparison: */
+ /* */
+ /* d_in + d_out < 17/16 d_hypot */
- return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
+ return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 );
}
diff --git a/src/base/ftcid.c b/src/base/ftcid.c
new file mode 100644
index 0000000..0734881
--- /dev/null
+++ b/src/base/ftcid.c
@@ -0,0 +1,118 @@
+/***************************************************************************/
+/* */
+/* ftcid.c */
+/* */
+/* FreeType API for accessing CID font information. */
+/* */
+/* Copyright 2007-2015 by */
+/* Derek Clegg and Michael Toftdal. */
+/* */
+/* 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 <ft2build.h>
+#include FT_CID_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_CID_H
+
+
+ /* documentation is in ftcid.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
+ const char* *registry,
+ const char* *ordering,
+ FT_Int *supplement)
+ {
+ FT_Error error;
+ const char* r = NULL;
+ const char* o = NULL;
+ FT_Int s = 0;
+
+
+ error = FT_ERR( Invalid_Argument );
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_ros )
+ error = service->get_ros( face, &r, &o, &s );
+ }
+
+ if ( registry )
+ *registry = r;
+
+ if ( ordering )
+ *ordering = o;
+
+ if ( supplement )
+ *supplement = s;
+
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,
+ FT_Bool *is_cid )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Bool ic = 0;
+
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_is_cid )
+ error = service->get_is_cid( face, &ic);
+ }
+
+ if ( is_cid )
+ *is_cid = ic;
+
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_CID_From_Glyph_Index( FT_Face face,
+ FT_UInt glyph_index,
+ FT_UInt *cid )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_UInt c = 0;
+
+
+ if ( face )
+ {
+ FT_Service_CID service;
+
+
+ FT_FACE_FIND_SERVICE( face, service, CID );
+
+ if ( service && service->get_cid_from_glyph_index )
+ error = service->get_cid_from_glyph_index( face, glyph_index, &c);
+ }
+
+ if ( cid )
+ *cid = c;
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 6fb86fe..02eeb01 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
/* */
/* Memory debugger (body). */
/* */
-/* Copyright 2001-2006, 2009, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -35,7 +35,7 @@
#include FT_CONFIG_STANDARD_LIBRARY_H
- FT_BASE_DEF( const char* ) _ft_debug_file = 0;
+ FT_BASE_DEF( const char* ) _ft_debug_file = NULL;
FT_BASE_DEF( long ) _ft_debug_lineno = 0;
extern void
@@ -47,7 +47,7 @@
typedef struct FT_MemTableRec_* FT_MemTable;
-#define FT_MEM_VAL( addr ) ((FT_PtrDist)(FT_Pointer)( addr ))
+#define FT_MEM_VAL( addr ) ( (FT_PtrDist)(FT_Pointer)( addr ) )
/*
* This structure holds statistics for a single allocation/release
@@ -76,7 +76,7 @@
/*
- * We don't need a resizable array for the memory sources, because
+ * We don't need a resizable array for the memory sources because
* their number is pretty limited within FreeType.
*/
#define FT_MEM_SOURCE_BUCKETS 128
@@ -85,8 +85,8 @@
* This structure holds information related to a single allocated
* memory block. If KEEPALIVE is defined, blocks that are freed by
* FreeType are never released to the system. Instead, their `size'
- * field is set to -size. This is mainly useful to detect double frees,
- * at the price of large memory footprint during execution.
+ * field is set to `-size'. This is mainly useful to detect double
+ * frees, at the price of a large memory footprint during execution.
*/
typedef struct FT_MemNodeRec_
{
@@ -111,20 +111,20 @@
*/
typedef struct FT_MemTableRec_
{
- FT_ULong size;
- FT_ULong nodes;
+ FT_Long size;
+ FT_Long nodes;
FT_MemNode* buckets;
- FT_ULong alloc_total;
- FT_ULong alloc_current;
- FT_ULong alloc_max;
- FT_ULong alloc_count;
+ FT_Long alloc_total;
+ FT_Long alloc_current;
+ FT_Long alloc_max;
+ FT_Long alloc_count;
FT_Bool bound_total;
- FT_ULong alloc_total_max;
+ FT_Long alloc_total_max;
FT_Bool bound_count;
- FT_ULong alloc_count_max;
+ FT_Long alloc_count_max;
FT_MemSource sources[FT_MEM_SOURCE_BUCKETS];
@@ -142,14 +142,14 @@
#define FT_MEM_SIZE_MIN 7
#define FT_MEM_SIZE_MAX 13845163
-#define FT_FILENAME( x ) ((x) ? (x) : "unknown file")
+#define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" )
/*
* Prime numbers are ugly to handle. It would be better to implement
* L-Hashing, which is 10% faster and doesn't require divisions.
*/
- static const FT_UInt ft_mem_primes[] =
+ static const FT_Int ft_mem_primes[] =
{
7,
11,
@@ -189,10 +189,10 @@
};
- static FT_ULong
- ft_mem_closest_prime( FT_ULong num )
+ static FT_Long
+ ft_mem_closest_prime( FT_Long num )
{
- FT_UInt i;
+ size_t i;
for ( i = 0;
@@ -204,7 +204,7 @@
}
- extern void
+ static void
ft_mem_debug_panic( const char* fmt,
... )
{
@@ -254,19 +254,20 @@
static void
ft_mem_table_resize( FT_MemTable table )
{
- FT_ULong new_size;
+ FT_Long new_size;
new_size = ft_mem_closest_prime( table->nodes );
if ( new_size != table->size )
{
FT_MemNode* new_buckets;
- FT_ULong i;
+ FT_Long i;
new_buckets = (FT_MemNode *)
- ft_mem_table_alloc( table,
- new_size * sizeof ( FT_MemNode ) );
+ ft_mem_table_alloc(
+ table,
+ new_size * (FT_Long)sizeof ( FT_MemNode ) );
if ( new_buckets == NULL )
return;
@@ -282,7 +283,7 @@
while ( node )
{
next = node->link;
- hash = FT_MEM_VAL( node->address ) % new_size;
+ hash = FT_MEM_VAL( node->address ) % (FT_PtrDist)new_size;
pnode = new_buckets + hash;
node->link = pnode[0];
@@ -325,8 +326,9 @@
table->free = memory->free;
table->buckets = (FT_MemNode *)
- memory->alloc( memory,
- table->size * sizeof ( FT_MemNode ) );
+ memory->alloc(
+ memory,
+ table->size * (FT_Long)sizeof ( FT_MemNode ) );
if ( table->buckets )
FT_ARRAY_ZERO( table->buckets, table->size );
else
@@ -343,9 +345,9 @@
static void
ft_mem_table_destroy( FT_MemTable table )
{
- FT_ULong i;
- FT_Long leak_count = 0;
- FT_ULong leaks = 0;
+ FT_Long i;
+ FT_Long leak_count = 0;
+ FT_Long leaks = 0;
FT_DumpMemory( table->memory );
@@ -359,7 +361,7 @@
while ( node )
{
next = node->link;
- node->link = 0;
+ node->link = NULL;
if ( node->size > 0 )
{
@@ -381,7 +383,7 @@
ft_mem_table_free( table, node );
node = next;
}
- table->buckets[i] = 0;
+ table->buckets[i] = NULL;
}
ft_mem_table_free( table, table->buckets );
@@ -430,7 +432,7 @@
hash = FT_MEM_VAL( address );
- pnode = table->buckets + ( hash % table->size );
+ pnode = table->buckets + ( hash % (FT_PtrDist)table->size );
for (;;)
{
@@ -460,14 +462,14 @@
(FT_UInt32)( 5 * _ft_debug_lineno );
pnode = &table->sources[hash % FT_MEM_SOURCE_BUCKETS];
- for ( ;; )
+ for (;;)
{
node = *pnode;
if ( node == NULL )
break;
- if ( node->file_name == _ft_debug_file &&
- node->line_no == _ft_debug_lineno )
+ if ( node->file_name == _ft_debug_file &&
+ node->line_no == _ft_debug_lineno )
goto Exit;
pnode = &node->link;
@@ -485,11 +487,11 @@
node->max_blocks = 0;
node->all_blocks = 0;
- node->cur_size = 0;
- node->max_size = 0;
- node->all_size = 0;
+ node->cur_size = 0;
+ node->max_size = 0;
+ node->all_size = 0;
- node->cur_max = 0;
+ node->cur_max = 0;
node->link = NULL;
node->hash = hash;
@@ -503,7 +505,7 @@
static void
ft_mem_table_set( FT_MemTable table,
FT_Byte* address,
- FT_ULong size,
+ FT_Long size,
FT_Long delta )
{
FT_MemNode *pnode, node;
@@ -558,7 +560,7 @@
source->max_blocks = source->cur_blocks;
}
- if ( size > (FT_ULong)source->cur_max )
+ if ( size > source->cur_max )
source->cur_max = size;
if ( delta != 0 )
@@ -671,7 +673,7 @@
}
- extern FT_Pointer
+ static FT_Pointer
ft_mem_debug_alloc( FT_Memory memory,
FT_Long size )
{
@@ -688,14 +690,14 @@
return NULL;
/* return NULL if this allocation would overflow the maximum heap size */
- if ( table->bound_total &&
- table->alloc_total_max - table->alloc_current > (FT_ULong)size )
+ if ( table->bound_total &&
+ table->alloc_total_max - table->alloc_current > size )
return NULL;
block = (FT_Byte *)ft_mem_table_alloc( table, size );
if ( block )
{
- ft_mem_table_set( table, block, (FT_ULong)size, 0 );
+ ft_mem_table_set( table, block, size, 0 );
table->alloc_count++;
}
@@ -707,7 +709,7 @@
}
- extern void
+ static void
ft_mem_debug_free( FT_Memory memory,
FT_Pointer block )
{
@@ -731,7 +733,7 @@
}
- extern FT_Pointer
+ static FT_Pointer
ft_mem_debug_realloc( FT_Memory memory,
FT_Long cur_size,
FT_Long new_size,
@@ -787,21 +789,22 @@
table->alloc_count >= table->alloc_count_max )
return NULL;
- delta = (FT_Long)( new_size - cur_size );
+ delta = new_size - cur_size;
/* return NULL if this allocation would overflow the maximum heap size */
- if ( delta > 0 &&
- table->bound_total &&
- table->alloc_current + (FT_ULong)delta > table->alloc_total_max )
+ if ( delta > 0 &&
+ table->bound_total &&
+ table->alloc_current + delta > table->alloc_total_max )
return NULL;
- new_block = (FT_Byte *)ft_mem_table_alloc( table, new_size );
+ new_block = (FT_Pointer)ft_mem_table_alloc( table, new_size );
if ( new_block == NULL )
return NULL;
ft_mem_table_set( table, (FT_Byte*)new_block, new_size, delta );
- ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size );
+ ft_memcpy( new_block, block, cur_size < new_size ? (size_t)cur_size
+ : (size_t)new_size );
ft_mem_table_remove( table, (FT_Byte*)block, delta );
@@ -844,7 +847,7 @@
if ( total_max > 0 )
{
table->bound_total = 1;
- table->alloc_total_max = (FT_ULong)total_max;
+ table->alloc_total_max = total_max;
}
}
@@ -857,7 +860,7 @@
if ( total_count > 0 )
{
table->bound_count = 1;
- table->alloc_count_max = (FT_ULong)total_count;
+ table->alloc_count_max = total_count;
}
}
@@ -896,7 +899,6 @@
}
-
static int
ft_mem_source_compare( const void* p1,
const void* p2 )
@@ -925,7 +927,7 @@
FT_MemSource* bucket = table->sources;
FT_MemSource* limit = bucket + FT_MEM_SOURCE_BUCKETS;
FT_MemSource* sources;
- FT_UInt nn, count;
+ FT_Int nn, count;
const char* fmt;
@@ -939,8 +941,9 @@
count++;
}
- sources = (FT_MemSource*)ft_mem_table_alloc(
- table, sizeof ( *sources ) * count );
+ sources = (FT_MemSource*)
+ ft_mem_table_alloc(
+ table, count * (FT_Long)sizeof ( *sources ) );
count = 0;
for ( bucket = table->sources; bucket < limit; bucket++ )
@@ -952,7 +955,10 @@
sources[count++] = source;
}
- ft_qsort( sources, count, sizeof ( *sources ), ft_mem_source_compare );
+ ft_qsort( sources,
+ (size_t)count,
+ sizeof ( *sources ),
+ ft_mem_source_compare );
printf( "FreeType Memory Dump: "
"current=%ld max=%ld total=%ld count=%ld\n",
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index b9156d1..03e18a8 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -4,7 +4,7 @@
/* */
/* Debugging and logging component (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2008, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -152,8 +152,8 @@
/* the memory and stream components which are set to 7 and 5, */
/* respectively. */
/* */
- /* See the file <include/freetype/internal/fttrace.h> for details of the */
- /* available toggle names. */
+ /* See the file `include/freetype/internal/fttrace.h' for details of */
+ /* the available toggle names. */
/* */
/* The level must be between 0 and 7; 0 means quiet (except for serious */
/* runtime errors), and 7 means _very_ verbose. */
diff --git a/src/base/ftxf86.c b/src/base/ftfntfmt.c
similarity index 67%
copy from src/base/ftxf86.c
copy to src/base/ftfntfmt.c
index a4bf767..98e7431 100644
--- a/src/base/ftxf86.c
+++ b/src/base/ftfntfmt.c
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* ftxf86.c */
+/* ftfntfmt.c */
/* */
-/* FreeType utility file for X11 support (body). */
+/* FreeType utility file for font formats (body). */
/* */
-/* Copyright 2002, 2003, 2004 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,12 +17,27 @@
#include <ft2build.h>
-#include FT_XFREE86_H
+#include FT_FONT_FORMATS_H
#include FT_INTERNAL_OBJECTS_H
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
- /* documentation is in ftxf86.h */
+ /* documentation is in ftfntfmt.h */
+
+ FT_EXPORT_DEF( const char* )
+ FT_Get_Font_Format( FT_Face face )
+ {
+ const char* result = NULL;
+
+
+ if ( face )
+ FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
+
+ return result;
+ }
+
+
+ /* deprecated function name; retained for ABI compatibility */
FT_EXPORT_DEF( const char* )
FT_Get_X11_Font_Format( FT_Face face )
@@ -31,7 +46,7 @@
if ( face )
- FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
+ FT_FACE_FIND_SERVICE( face, result, FONT_FORMAT );
return result;
}
diff --git a/src/base/ftfstype.c b/src/base/ftfstype.c
index 0bf29c7..cd3458f 100644
--- a/src/base/ftfstype.c
+++ b/src/base/ftfstype.c
@@ -1,62 +1,62 @@
-/***************************************************************************/
-/* */
-/* ftfstype.c */
-/* */
-/* FreeType utility file to access FSType data (body). */
-/* */
-/* Copyright 2008, 2009 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 <ft2build.h>
-#include FT_TYPE1_TABLES_H
-#include FT_TRUETYPE_TABLES_H
-#include FT_INTERNAL_SERVICE_H
-#include FT_SERVICE_POSTSCRIPT_INFO_H
-
-
- /* documentation is in freetype.h */
-
- FT_EXPORT_DEF( FT_UShort )
- FT_Get_FSType_Flags( FT_Face face )
- {
- TT_OS2* os2;
-
-
- /* first, try to get the fs_type directly from the font */
- if ( face )
- {
- FT_Service_PsInfo service = NULL;
-
-
- FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
-
- if ( service && service->ps_get_font_extra )
- {
- PS_FontExtraRec extra;
-
-
- if ( !service->ps_get_font_extra( face, &extra ) &&
- extra.fs_type != 0 )
- return extra.fs_type;
- }
- }
-
- /* look at FSType before fsType for Type42 */
-
- if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, ft_sfnt_os2 ) ) != NULL &&
- os2->version != 0xFFFFU )
- return os2->fsType;
-
- return 0;
- }
-
-
-/* END */
+/***************************************************************************/
+/* */
+/* ftfstype.c */
+/* */
+/* FreeType utility file to access FSType data (body). */
+/* */
+/* Copyright 2008-2015 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 <ft2build.h>
+#include FT_TYPE1_TABLES_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_UShort )
+ FT_Get_FSType_Flags( FT_Face face )
+ {
+ TT_OS2* os2;
+
+
+ /* first, try to get the fs_type directly from the font */
+ if ( face )
+ {
+ FT_Service_PsInfo service = NULL;
+
+
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_extra )
+ {
+ PS_FontExtraRec extra;
+
+
+ if ( !service->ps_get_font_extra( face, &extra ) &&
+ extra.fs_type != 0 )
+ return extra.fs_type;
+ }
+ }
+
+ /* look at FSType before fsType for Type42 */
+
+ if ( ( os2 = (TT_OS2*)FT_Get_Sfnt_Table( face, FT_SFNT_OS2 ) ) != NULL &&
+ os2->version != 0xFFFFU )
+ return os2->fsType;
+
+ return 0;
+ }
+
+
+/* END */
diff --git a/src/base/ftgasp.c b/src/base/ftgasp.c
index 8485d29..bbd257c 100644
--- a/src/base/ftgasp.c
+++ b/src/base/ftgasp.c
@@ -4,7 +4,7 @@
/* */
/* Access of TrueType's `gasp' table (body). */
/* */
-/* Copyright 2007 by */
+/* Copyright 2007-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c
index 663db26..7e28638 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph loader (body). */
/* */
-/* Copyright 2002-2006, 2010, 2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -212,7 +212,8 @@
/* check points & tags */
- new_max = base->n_points + current->n_points + n_points;
+ new_max = (FT_UInt)base->n_points + (FT_UInt)current->n_points +
+ n_points;
old_max = loader->max_points;
if ( new_max > old_max )
@@ -245,7 +246,7 @@
/* check contours */
old_max = loader->max_contours;
- new_max = base->n_contours + current->n_contours +
+ new_max = (FT_UInt)base->n_contours + (FT_UInt)current->n_contours +
n_contours;
if ( new_max > old_max )
{
@@ -265,6 +266,9 @@
FT_GlyphLoader_Adjust_Points( loader );
Exit:
+ if ( error )
+ FT_GlyphLoader_Reset( loader );
+
return error;
}
@@ -326,9 +330,9 @@
FT_GlyphLoad base;
FT_GlyphLoad current;
- FT_UInt n_curr_contours;
- FT_UInt n_base_points;
- FT_UInt n;
+ FT_Int n_curr_contours;
+ FT_Int n_base_points;
+ FT_Int n;
if ( !loader )
@@ -362,8 +366,8 @@
FT_GlyphLoader source )
{
FT_Error error;
- FT_UInt num_points = source->base.outline.n_points;
- FT_UInt num_contours = source->base.outline.n_contours;
+ FT_UInt num_points = (FT_UInt)source->base.outline.n_points;
+ FT_UInt num_contours = (FT_UInt)source->base.outline.n_contours;
error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index 5dd28a8..2778743 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (body). */
/* */
-/* Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -82,7 +82,7 @@
}
else
{
- FT_Bitmap_New( &glyph->bitmap );
+ FT_Bitmap_Init( &glyph->bitmap );
error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
}
@@ -125,10 +125,10 @@
FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
- cbox->xMin = glyph->left << 6;
- cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
- cbox->yMax = glyph->top << 6;
- cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
+ cbox->xMin = glyph->left * 64;
+ cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
+ cbox->yMax = glyph->top * 64;
+ cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
}
@@ -173,7 +173,9 @@
}
/* allocate new outline */
- error = FT_Outline_New( library, source->n_points, source->n_contours,
+ error = FT_Outline_New( library,
+ (FT_UInt)source->n_points,
+ source->n_contours,
&glyph->outline );
if ( error )
goto Exit;
@@ -205,8 +207,10 @@
FT_Library library = FT_GLYPH( source )->library;
- error = FT_Outline_New( library, source->outline.n_points,
- source->outline.n_contours, &target->outline );
+ error = FT_Outline_New( library,
+ (FT_UInt)source->outline.n_points,
+ source->outline.n_contours,
+ &target->outline );
if ( !error )
FT_Outline_Copy( &source->outline, &target->outline );
@@ -287,7 +291,7 @@
FT_Glyph glyph = NULL;
- *aglyph = 0;
+ *aglyph = NULL;
if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
{
@@ -314,13 +318,13 @@
/* check arguments */
- if ( !target )
+ if ( !target || !source || !source->clazz )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
- *target = 0;
+ *target = NULL;
if ( !source || !source->clazz )
{
@@ -359,7 +363,7 @@
FT_Error error;
FT_Glyph glyph;
- const FT_Glyph_Class* clazz = 0;
+ const FT_Glyph_Class* clazz = NULL;
if ( !slot )
@@ -399,9 +403,9 @@
if ( error )
goto Exit;
- /* copy advance while converting it to 16.16 format */
- glyph->advance.x = slot->advance.x << 10;
- glyph->advance.y = slot->advance.y << 10;
+ /* copy advance while converting 26.6 to 16.16 format */
+ glyph->advance.x = slot->advance.x * 1024;
+ glyph->advance.y = slot->advance.y * 1024;
/* now import the image from the glyph slot */
error = clazz->glyph_init( glyph, slot );
@@ -424,15 +428,16 @@
FT_Matrix* matrix,
FT_Vector* delta )
{
- const FT_Glyph_Class* clazz;
- FT_Error error = FT_Err_Ok;
+ FT_Error error = FT_Err_Ok;
if ( !glyph || !glyph->clazz )
error = FT_THROW( Invalid_Argument );
else
{
- clazz = glyph->clazz;
+ const FT_Glyph_Class* clazz = glyph->clazz;
+
+
if ( clazz->glyph_transform )
{
/* transform glyph image */
@@ -466,38 +471,33 @@
if ( !glyph || !glyph->clazz )
return;
- else
+
+ clazz = glyph->clazz;
+ if ( !clazz->glyph_bbox )
+ return;
+
+ /* retrieve bbox in 26.6 coordinates */
+ clazz->glyph_bbox( glyph, acbox );
+
+ /* perform grid fitting if needed */
+ if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
+ bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
- clazz = glyph->clazz;
- if ( !clazz->glyph_bbox )
- return;
- else
- {
- /* retrieve bbox in 26.6 coordinates */
- clazz->glyph_bbox( glyph, acbox );
-
- /* perform grid fitting if needed */
- if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
- bbox_mode == FT_GLYPH_BBOX_PIXELS )
- {
- acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
- acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
- acbox->xMax = FT_PIX_CEIL( acbox->xMax );
- acbox->yMax = FT_PIX_CEIL( acbox->yMax );
- }
-
- /* convert to integer pixels if needed */
- if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
- bbox_mode == FT_GLYPH_BBOX_PIXELS )
- {
- acbox->xMin >>= 6;
- acbox->yMin >>= 6;
- acbox->xMax >>= 6;
- acbox->yMax >>= 6;
- }
- }
+ acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
+ acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
+ acbox->xMax = FT_PIX_CEIL( acbox->xMax );
+ acbox->yMax = FT_PIX_CEIL( acbox->yMax );
}
- return;
+
+ /* convert to integer pixels if needed */
+ if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
+ bbox_mode == FT_GLYPH_BBOX_PIXELS )
+ {
+ acbox->xMin >>= 6;
+ acbox->yMin >>= 6;
+ acbox->xMax >>= 6;
+ acbox->yMax >>= 6;
+ }
}
@@ -516,7 +516,7 @@
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
- /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
+ /* FT_BITMAP_GLYPH_CLASS_GET dereferences `library' in PIC mode */
FT_Library library;
diff --git a/src/base/ftgxval.c b/src/base/ftgxval.c
new file mode 100644
index 0000000..58868f2
--- /dev/null
+++ b/src/base/ftgxval.c
@@ -0,0 +1,142 @@
+/***************************************************************************/
+/* */
+/* ftgxval.c */
+/* */
+/* FreeType API for validating TrueTyepGX/AAT tables (body). */
+/* */
+/* Copyright 2004-2015 by */
+/* Masatake YAMATO, Redhat K.K, */
+/* 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. */
+/* */
+/***************************************************************************/
+
+/***************************************************************************/
+/* */
+/* gxvalid is derived from both gxlayout module and otvalid module. */
+/* Development of gxlayout is supported by the Information-technology */
+/* Promotion Agency(IPA), Japan. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_GX_VALIDATE_H
+
+
+ /* documentation is in ftgxval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_TrueTypeGX_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length )
+ {
+ FT_Service_GXvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !tables )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ tables,
+ table_length );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_TrueTypeGX_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+ FT_FREE( table );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_ClassicKern_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *ckern_table )
+ {
+ FT_Service_CKERNvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !ckern_table )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ ckern_table );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_ClassicKern_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index 85f321f..b65a91d 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -4,7 +4,7 @@
/* */
/* FreeType initialization layer (body). */
/* */
-/* Copyright 1996-2002, 2005, 2007, 2009, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -138,7 +138,7 @@
#include FT_CONFIG_MODULES_H
FT_FREE( classes );
- pic_container->default_module_classes = 0;
+ pic_container->default_module_classes = NULL;
}
@@ -164,7 +164,7 @@
memory = library->memory;
- pic_container->default_module_classes = 0;
+ pic_container->default_module_classes = NULL;
if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) *
( FT_NUM_MODULE_CLASSES + 1 ) ) )
@@ -172,8 +172,8 @@
/* initialize all pointers to 0, especially the last one */
for ( i = 0; i < FT_NUM_MODULE_CLASSES; i++ )
- classes[i] = 0;
- classes[FT_NUM_MODULE_CLASSES] = 0;
+ classes[i] = NULL;
+ classes[FT_NUM_MODULE_CLASSES] = NULL;
i = 0;
@@ -235,6 +235,8 @@
FT_Memory memory;
+ /* check of `alibrary' delayed to `FT_New_Library' */
+
/* First of all, allocate a new system object -- this function is part */
/* of the system-specific component, i.e. `ftsystem.c'. */
@@ -263,17 +265,19 @@
FT_EXPORT_DEF( FT_Error )
FT_Done_FreeType( FT_Library library )
{
- if ( library )
- {
- FT_Memory memory = library->memory;
+ FT_Memory memory;
- /* Discard the library object */
- FT_Done_Library( library );
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
- /* discard memory manager */
- FT_Done_Memory( memory );
- }
+ memory = library->memory;
+
+ /* Discard the library object */
+ FT_Done_Library( library );
+
+ /* discard memory manager */
+ FT_Done_Memory( memory );
return FT_Err_Ok;
}
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 852fb32..5ee7e0a 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for color filtering of subpixel bitmap glyphs (body). */
/* */
-/* Copyright 2006, 2008-2010, 2013 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -46,9 +46,16 @@
FT_Byte* line = bitmap->buffer;
+ /* take care of bitmap flow */
+ if ( bitmap->pitch < 0 )
+ line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
+ /* `fir' and `pix' must be at least 32 bit wide, since the sum of */
+ /* the values in `weights' can exceed 0xFF */
+
for ( ; height > 0; height--, line += bitmap->pitch )
{
- FT_UInt fir[5];
+ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
FT_UInt val1, xx;
@@ -57,7 +64,6 @@
fir[1] = weights[3] * val1;
fir[2] = weights[4] * val1;
fir[3] = 0;
- fir[4] = 0;
val1 = line[1];
fir[0] += weights[1] * val1;
@@ -78,7 +84,7 @@
fir[3] = weights[4] * val;
pix >>= 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
line[xx - 2] = (FT_Byte)pix;
}
@@ -87,11 +93,11 @@
pix = fir[0] >> 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
line[xx - 2] = (FT_Byte)pix;
pix = fir[1] >> 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
line[xx - 1] = (FT_Byte)pix;
}
}
@@ -104,10 +110,14 @@
FT_Int pitch = bitmap->pitch;
+ /* take care of bitmap flow */
+ if ( bitmap->pitch < 0 )
+ column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
- FT_UInt fir[5];
+ FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
FT_UInt val1, yy;
@@ -116,7 +126,6 @@
fir[1] = weights[3] * val1;
fir[2] = weights[4] * val1;
fir[3] = 0;
- fir[4] = 0;
col += pitch;
val1 = col[0];
@@ -139,7 +148,7 @@
fir[3] = weights[4] * val;
pix >>= 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
col[-2 * pitch] = (FT_Byte)pix;
col += pitch;
}
@@ -149,11 +158,11 @@
pix = fir[0] >> 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
col[-2 * pitch] = (FT_Byte)pix;
pix = fir[1] >> 8;
- pix |= -( pix >> 8 );
+ pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
col[-pitch] = (FT_Byte)pix;
}
}
@@ -173,7 +182,7 @@
FT_UInt height = (FT_UInt)bitmap->rows;
FT_Int pitch = bitmap->pitch;
- static const int filters[3][3] =
+ static const unsigned int filters[3][3] =
{
{ 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
{ 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
@@ -189,6 +198,10 @@
FT_Byte* line = bitmap->buffer;
+ /* take care of bitmap flow */
+ if ( bitmap->pitch < 0 )
+ line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
for ( ; height > 0; height--, line += pitch )
{
FT_UInt xx;
@@ -228,10 +241,14 @@
FT_Byte* column = bitmap->buffer;
+ /* take care of bitmap flow */
+ if ( bitmap->pitch < 0 )
+ column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
+
for ( ; width > 0; width--, column++ )
{
FT_Byte* col = column;
- FT_Byte* col_end = col + height * pitch;
+ FT_Byte* col_end = col + (FT_Int)height * pitch;
for ( ; col < col_end; col += 3 * pitch )
@@ -272,7 +289,10 @@
FT_Library_SetLcdFilterWeights( FT_Library library,
unsigned char *weights )
{
- if ( !library || !weights )
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !weights )
return FT_THROW( Invalid_Argument );
ft_memcpy( library->lcd_weights, weights, 5 );
@@ -285,16 +305,14 @@
FT_Library_SetLcdFilter( FT_Library library,
FT_LcdFilter filter )
{
+ static const FT_Byte default_filter[5] =
+ { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
static const FT_Byte light_filter[5] =
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
- /* the values here sum up to a value larger than 256, */
- /* providing a cheap gamma correction */
- static const FT_Byte default_filter[5] =
- { 0x10, 0x40, 0x70, 0x40, 0x10 };
if ( !library )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Invalid_Library_Handle );
switch ( filter )
{
@@ -334,6 +352,7 @@
#ifdef USE_LEGACY
case FT_LCD_FILTER_LEGACY:
+ case FT_LCD_FILTER_LEGACY1:
library->lcd_filter_func = _ft_lcd_filter_legacy;
library->lcd_extra = 0;
break;
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
new file mode 100644
index 0000000..114bbb6
--- /dev/null
+++ b/src/base/ftmac.c
@@ -0,0 +1,1080 @@
+/***************************************************************************/
+/* */
+/* ftmac.c */
+/* */
+/* Mac FOND support. Written by just@letterror.com. */
+/* Heavily modified by mpsuzuki, George Williams, and Sean McBride. */
+/* */
+/* This file is for Mac OS X only; see builds/mac/ftoldmac.c for */
+/* classic platforms built by MPW. */
+/* */
+/* Copyright 1996-2015 by */
+/* Just van Rossum, 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
+
+ Mac suitcase files can (and often do!) contain multiple fonts. To
+ support this I use the face_index argument of FT_(Open|New)_Face()
+ functions, and pretend the suitcase file is a collection.
+
+ Warning: fbit and NFNT bitmap resources are not supported yet. In old
+ sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
+ resources instead of the `bdat' table in the sfnt resource. Therefore,
+ face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
+ resource is unavailable at present.
+
+ The Mac FOND support works roughly like this:
+
+ - Check whether the offered stream points to a Mac suitcase file. This
+ is done by checking the file type: it has to be 'FFIL' or 'tfil'. The
+ stream that gets passed to our init_face() routine is a stdio stream,
+ which isn't usable for us, since the FOND resources live in the
+ resource fork. So we just grab the stream->pathname field.
+
+ - Read the FOND resource into memory, then check whether there is a
+ TrueType font and/or(!) a Type 1 font available.
+
+ - If there is a Type 1 font available (as a separate `LWFN' file), read
+ its data into memory, massage it slightly so it becomes PFB data, wrap
+ it into a memory stream, load the Type 1 driver and delegate the rest
+ of the work to it by calling FT_Open_Face(). (XXX TODO: after this
+ has been done, the kerning data from the FOND resource should be
+ appended to the face: On the Mac there are usually no AFM files
+ available. However, this is tricky since we need to map Mac char
+ codes to ps glyph names to glyph ID's...)
+
+ - If there is a TrueType font (an `sfnt' resource), read it into memory,
+ wrap it into a memory stream, load the TrueType driver and delegate
+ the rest of the work to it, by calling FT_Open_Face().
+
+ - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
+ itself, even though it doesn't contains `POST' resources. To handle
+ this special case without opening the file an extra time, we just
+ ignore errors from the `LWFN' and fallback to the `sfnt' if both are
+ available.
+ */
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_STREAM_H
+#include "ftbase.h"
+
+ /* This is for Mac OS X. Without redefinition, OS_INLINE */
+ /* expands to `static inline' which doesn't survive the */
+ /* -ansi compilation flag of GCC. */
+#if !HAVE_ANSI_OS_INLINE
+#undef OS_INLINE
+#define OS_INLINE static __inline__
+#endif
+
+ /* `configure' checks the availability of `ResourceIndex' strictly */
+ /* and sets HAVE_TYPE_RESOURCE_INDEX 1 or 0 always. If it is */
+ /* not set (e.g., a build without `configure'), the availability */
+ /* is guessed from the SDK version. */
+#ifndef HAVE_TYPE_RESOURCE_INDEX
+#if !defined( MAC_OS_X_VERSION_10_5 ) || \
+ ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 )
+#define HAVE_TYPE_RESOURCE_INDEX 0
+#else
+#define HAVE_TYPE_RESOURCE_INDEX 1
+#endif
+#endif /* !HAVE_TYPE_RESOURCE_INDEX */
+
+#if ( HAVE_TYPE_RESOURCE_INDEX == 0 )
+ typedef short ResourceIndex;
+#endif
+
+#include <CoreServices/CoreServices.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <sys/syslimits.h> /* PATH_MAX */
+
+ /* Don't want warnings about our own use of deprecated functions. */
+#define FT_DEPRECATED_ATTRIBUTE
+
+#include FT_MAC_H
+
+#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
+#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
+#endif
+
+
+ /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+ TrueType in case *both* are available (this is not common,
+ but it *is* possible). */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#endif
+
+
+#ifdef FT_MACINTOSH
+
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFile_From_Mac_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ /* Private function. */
+ /* The FSSpec type has been discouraged for a long time, */
+ /* unfortunately an FSRef replacement API for */
+ /* ATSFontGetFileSpecification() is only available in */
+ /* Mac OS X 10.5 and later. */
+ static OSStatus
+ FT_ATSFontGetFileReference( ATSFontRef ats_font_id,
+ FSRef* ats_font_ref )
+ {
+#if defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
+
+ OSStatus err;
+
+ err = ATSFontGetFileReference( ats_font_id, ats_font_ref );
+
+ return err;
+#elif __LP64__ /* No 64bit Carbon API on legacy platforms */
+ FT_UNUSED( ats_font_id );
+ FT_UNUSED( ats_font_ref );
+
+
+ return fnfErr;
+#else /* 32bit Carbon API on legacy platforms */
+ OSStatus err;
+ FSSpec spec;
+
+
+ err = ATSFontGetFileSpecification( ats_font_id, &spec );
+ if ( noErr == err )
+ err = FSpMakeFSRef( &spec, ats_font_ref );
+
+ return err;
+#endif
+ }
+
+
+ static FT_Error
+ FT_GetFileRef_From_Mac_ATS_Name( const char* fontName,
+ FSRef* ats_font_ref,
+ FT_Long* face_index )
+ {
+ CFStringRef cf_fontName;
+ ATSFontRef ats_font_id;
+
+
+ *face_index = 0;
+
+ cf_fontName = CFStringCreateWithCString( NULL, fontName,
+ kCFStringEncodingMacRoman );
+ ats_font_id = ATSFontFindFromName( cf_fontName,
+ kATSOptionFlagsUnRestrictedScope );
+ CFRelease( cf_fontName );
+
+ if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
+ return FT_THROW( Unknown_File_Format );
+
+ if ( noErr != FT_ATSFontGetFileReference( ats_font_id, ats_font_ref ) )
+ return FT_THROW( Unknown_File_Format );
+
+ /* face_index calculation by searching preceding fontIDs */
+ /* with same FSRef */
+ {
+ ATSFontRef id2 = ats_font_id - 1;
+ FSRef ref2;
+
+
+ while ( id2 > 0 )
+ {
+ if ( noErr != FT_ATSFontGetFileReference( id2, &ref2 ) )
+ break;
+ if ( noErr != FSCompareFSRefs( ats_font_ref, &ref2 ) )
+ break;
+
+ id2 --;
+ }
+ *face_index = ats_font_id - ( id2 + 1 );
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
+ UInt8* path,
+ UInt32 maxPathSize,
+ FT_Long* face_index )
+ {
+ FSRef ref;
+ FT_Error err;
+
+
+ if ( !fontName || !face_index )
+ return FT_THROW( Invalid_Argument) ;
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( err )
+ return err;
+
+ if ( noErr != FSRefMakePath( &ref, path, maxPathSize ) )
+ return FT_THROW( Unknown_File_Format );
+
+ return FT_Err_Ok;
+ }
+
+
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ {
+#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
+ FT_UNUSED( fontName );
+ FT_UNUSED( pathSpec );
+ FT_UNUSED( face_index );
+
+ return FT_THROW( Unimplemented_Feature );
+#else
+ FSRef ref;
+ FT_Error err;
+
+
+ if ( !fontName || !face_index )
+ return FT_THROW( Invalid_Argument );
+
+ err = FT_GetFileRef_From_Mac_ATS_Name( fontName, &ref, face_index );
+ if ( err )
+ return err;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL,
+ pathSpec, NULL ) )
+ return FT_THROW( Unknown_File_Format );
+
+ return FT_Err_Ok;
+#endif
+ }
+
+
+ static OSErr
+ FT_FSPathMakeRes( const UInt8* pathname,
+ ResFileRefNum* res )
+ {
+ OSErr err;
+ FSRef ref;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ /* at present, no support for dfont format */
+ err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
+ if ( noErr == err )
+ return err;
+
+ /* fallback to original resource-fork font */
+ *res = FSOpenResFile( &ref, fsRdPerm );
+ err = ResError();
+
+ return err;
+ }
+
+
+ /* Return the file type for given pathname */
+ static OSType
+ get_file_type_from_path( const UInt8* pathname )
+ {
+ FSRef ref;
+ FSCatalogInfo info;
+
+
+ if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
+ return ( OSType ) 0;
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoFinderInfo, &info,
+ NULL, NULL, NULL ) )
+ return ( OSType ) 0;
+
+ return ((FInfo *)(info.finderInfo))->fdType;
+ }
+
+
+ /* Given a PostScript font name, create the Macintosh LWFN file name. */
+ static void
+ create_lwfn_name( char* ps_name,
+ Str255 lwfn_file_name )
+ {
+ int max = 5, count = 0;
+ FT_Byte* p = lwfn_file_name;
+ FT_Byte* q = (FT_Byte*)ps_name;
+
+
+ lwfn_file_name[0] = 0;
+
+ while ( *q )
+ {
+ if ( ft_isupper( *q ) )
+ {
+ if ( count )
+ max = 3;
+ count = 0;
+ }
+ if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
+ {
+ *++p = *q;
+ lwfn_file_name[0]++;
+ count++;
+ }
+ q++;
+ }
+ }
+
+
+ static short
+ count_faces_sfnt( char* fond_data )
+ {
+ /* The count is 1 greater than the value in the FOND. */
+ /* Isn't that cute? :-) */
+
+ return EndianS16_BtoN( *( (short*)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ }
+
+
+ static short
+ count_faces_scalable( char* fond_data )
+ {
+ AsscEntry* assoc;
+ short i, face, face_all;
+
+
+ face_all = EndianS16_BtoN( *( (short *)( fond_data +
+ sizeof ( FamRec ) ) ) ) + 1;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ face = 0;
+
+ for ( i = 0; i < face_all; i++ )
+ {
+ if ( 0 == EndianS16_BtoN( assoc[i].fontSize ) )
+ face++;
+ }
+ return face;
+ }
+
+
+ /* Look inside the FOND data, answer whether there should be an SFNT
+ resource, and answer the name of a possible LWFN Type 1 file.
+
+ Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
+ to load a face OTHER than the first one in the FOND!
+ */
+
+
+ static void
+ parse_fond( char* fond_data,
+ short* have_sfnt,
+ ResID* sfnt_id,
+ Str255 lwfn_file_name,
+ short face_index )
+ {
+ AsscEntry* assoc;
+ AsscEntry* base_assoc;
+ FamRec* fond;
+
+
+ *sfnt_id = 0;
+ *have_sfnt = 0;
+ lwfn_file_name[0] = 0;
+
+ fond = (FamRec*)fond_data;
+ assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+ base_assoc = assoc;
+
+ /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */
+ if ( 47 < face_index )
+ return;
+
+ /* Let's do a little range checking before we get too excited here */
+ if ( face_index < count_faces_sfnt( fond_data ) )
+ {
+ assoc += face_index; /* add on the face_index! */
+
+ /* if the face at this index is not scalable,
+ fall back to the first one (old behavior) */
+ if ( EndianS16_BtoN( assoc->fontSize ) == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( assoc->fontID );
+ }
+ else if ( base_assoc->fontSize == 0 )
+ {
+ *have_sfnt = 1;
+ *sfnt_id = EndianS16_BtoN( base_assoc->fontID );
+ }
+ }
+
+ if ( EndianS32_BtoN( fond->ffStylOff ) )
+ {
+ unsigned char* p = (unsigned char*)fond_data;
+ StyleTable* style;
+ unsigned short string_count;
+ char ps_name[256];
+ unsigned char* names[64];
+ int i;
+
+
+ p += EndianS32_BtoN( fond->ffStylOff );
+ style = (StyleTable*)p;
+ p += sizeof ( StyleTable );
+ string_count = EndianS16_BtoN( *(short*)(p) );
+ string_count = FT_MIN( 64, string_count );
+ p += sizeof ( short );
+
+ for ( i = 0; i < string_count; i++ )
+ {
+ names[i] = p;
+ p += names[i][0];
+ p++;
+ }
+
+ {
+ size_t ps_name_len = (size_t)names[0][0];
+
+
+ if ( ps_name_len != 0 )
+ {
+ ft_memcpy(ps_name, names[0] + 1, ps_name_len);
+ ps_name[ps_name_len] = 0;
+ }
+ if ( style->indexes[face_index] > 1 &&
+ style->indexes[face_index] <= string_count )
+ {
+ unsigned char* suffixes = names[style->indexes[face_index] - 1];
+
+
+ for ( i = 1; i <= suffixes[0]; i++ )
+ {
+ unsigned char* s;
+ size_t j = suffixes[i] - 1;
+
+
+ if ( j < string_count && ( s = names[j] ) != NULL )
+ {
+ size_t s_len = (size_t)s[0];
+
+
+ if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
+ {
+ ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
+ ps_name_len += s_len;
+ ps_name[ps_name_len] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ create_lwfn_name( ps_name, lwfn_file_name );
+ }
+ }
+
+
+ static FT_Error
+ lookup_lwfn_by_fond( const UInt8* path_fond,
+ ConstStr255Param base_lwfn,
+ UInt8* path_lwfn,
+ size_t path_size )
+ {
+ FSRef ref, par_ref;
+ size_t dirname_len;
+
+
+ /* Pathname for FSRef can be in various formats: HFS, HFS+, and POSIX. */
+ /* We should not extract parent directory by string manipulation. */
+
+ if ( noErr != FSPathMakeRef( path_fond, &ref, FALSE ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, &par_ref ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( noErr != FSRefMakePath( &par_ref, path_lwfn, path_size ) )
+ return FT_THROW( Invalid_Argument );
+
+ if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size )
+ return FT_THROW( Invalid_Argument );
+
+ /* now we have absolute dirname in path_lwfn */
+ ft_strcat( (char *)path_lwfn, "/" );
+ dirname_len = ft_strlen( (char *)path_lwfn );
+ ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 );
+ path_lwfn[dirname_len + base_lwfn[0]] = '\0';
+
+ if ( noErr != FSPathMakeRef( path_lwfn, &ref, FALSE ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ if ( noErr != FSGetCatalogInfo( &ref, kFSCatInfoNone,
+ NULL, NULL, NULL, NULL ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ return FT_Err_Ok;
+ }
+
+
+ static short
+ count_faces( Handle fond,
+ const UInt8* pathname )
+ {
+ ResID sfnt_id;
+ short have_sfnt, have_lwfn;
+ Str255 lwfn_file_name;
+ UInt8 buff[PATH_MAX];
+ FT_Error err;
+ short num_faces;
+
+
+ have_sfnt = have_lwfn = 0;
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
+
+ if ( lwfn_file_name[0] )
+ {
+ err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
+ buff, sizeof ( buff ) );
+ if ( !err )
+ have_lwfn = 1;
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ num_faces = 1;
+ else
+ num_faces = count_faces_scalable( *fond );
+
+ return num_faces;
+ }
+
+
+ /* Read Type 1 data from the POST resources inside the LWFN file,
+ return a PFB buffer. This is somewhat convoluted because the FT2
+ PFB parser wants the ASCII header as one chunk, and the LWFN
+ chunks are often not organized that way, so we glue chunks
+ of the same type together. */
+ static FT_Error
+ read_lwfn( FT_Memory memory,
+ ResFileRefNum res,
+ FT_Byte** pfb_data,
+ FT_ULong* size )
+ {
+ FT_Error error = FT_Err_Ok;
+ ResID res_id;
+ unsigned char *buffer, *p, *size_p = NULL;
+ FT_ULong total_size = 0;
+ FT_ULong old_total_size = 0;
+ FT_ULong post_size, pfb_chunk_size;
+ Handle post_data;
+ char code, last_code;
+
+
+ UseResFile( res );
+
+ /* First pass: load all POST resources, and determine the size of */
+ /* the output buffer. */
+ res_id = 501;
+ last_code = -1;
+
+ for (;;)
+ {
+ post_data = Get1Resource( TTAG_POST, res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( code == 5 )
+ total_size += 2; /* just the end code */
+ else
+ total_size += 6; /* code + 4 bytes chunk length */
+ }
+
+ total_size += (FT_ULong)GetHandleSize( post_data ) - 2;
+ last_code = code;
+
+ /* detect resource fork overflow */
+ if ( FT_MAC_RFORK_MAX_LEN < total_size )
+ {
+ error = FT_THROW( Array_Too_Large );
+ goto Error;
+ }
+
+ old_total_size = total_size;
+ }
+
+ if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
+ goto Error;
+
+ /* Second pass: append all POST data to the buffer, add PFB fields. */
+ /* Glue all consecutive chunks of the same type together. */
+ p = buffer;
+ res_id = 501;
+ last_code = -1;
+ pfb_chunk_size = 0;
+
+ for (;;)
+ {
+ post_data = Get1Resource( TTAG_POST, res_id++ );
+ if ( post_data == NULL )
+ break; /* we are done */
+
+ post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
+ code = (*post_data)[0];
+
+ if ( code != last_code )
+ {
+ if ( last_code != -1 )
+ {
+ /* we are done adding a chunk, fill in the size field */
+ if ( size_p != NULL )
+ {
+ *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
+ *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
+ }
+ pfb_chunk_size = 0;
+ }
+
+ *p++ = 0x80;
+ if ( code == 5 )
+ *p++ = 0x03; /* the end */
+ else if ( code == 2 )
+ *p++ = 0x02; /* binary segment */
+ else
+ *p++ = 0x01; /* ASCII segment */
+
+ if ( code != 5 )
+ {
+ size_p = p; /* save for later */
+ p += 4; /* make space for size field */
+ }
+ }
+
+ ft_memcpy( p, *post_data + 2, post_size );
+ pfb_chunk_size += post_size;
+ p += post_size;
+ last_code = code;
+ }
+
+ *pfb_data = buffer;
+ *size = total_size;
+
+ Error:
+ CloseResFile( res );
+ return error;
+ }
+
+
+ /* Create a new FT_Face from a file path to an LWFN file. */
+ static FT_Error
+ FT_New_Face_From_LWFN( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Byte* pfb_data;
+ FT_ULong pfb_size;
+ FT_Error error;
+ ResFileRefNum res;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ pfb_data = NULL;
+ pfb_size = 0;
+ error = read_lwfn( library->memory, res, &pfb_data, &pfb_size );
+ CloseResFile( res ); /* PFB is already loaded, useless anymore */
+ if ( error )
+ return error;
+
+ return open_face_from_buffer( library,
+ pfb_data,
+ pfb_size,
+ face_index,
+ "type1",
+ aface );
+ }
+
+
+ /* Create a new FT_Face from an SFNT resource, specified by res ID. */
+ static FT_Error
+ FT_New_Face_From_SFNT( FT_Library library,
+ ResID sfnt_id,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ Handle sfnt = NULL;
+ FT_Byte* sfnt_data;
+ size_t sfnt_size;
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = library->memory;
+ int is_cff, is_sfnt_ps;
+
+
+ sfnt = GetResource( TTAG_sfnt, sfnt_id );
+ if ( sfnt == NULL )
+ return FT_THROW( Invalid_Handle );
+
+ sfnt_size = (FT_ULong)GetHandleSize( sfnt );
+
+ /* detect resource fork overflow */
+ if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
+ return FT_THROW( Array_Too_Large );
+
+ if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+ {
+ ReleaseResource( sfnt );
+ return error;
+ }
+
+ ft_memcpy( sfnt_data, *sfnt, sfnt_size );
+ ReleaseResource( sfnt );
+
+ is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
+ is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 );
+
+ if ( is_sfnt_ps )
+ {
+ FT_Stream stream;
+
+
+ if ( FT_NEW( stream ) )
+ goto Try_OpenType;
+
+ FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size );
+ if ( !open_face_PS_from_sfnt_stream( library,
+ stream,
+ face_index,
+ 0, NULL,
+ aface ) )
+ {
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+ FT_FREE( sfnt_data );
+ goto Exit;
+ }
+
+ FT_FREE( stream );
+ }
+ Try_OpenType:
+ error = open_face_from_buffer( library,
+ sfnt_data,
+ sfnt_size,
+ face_index,
+ is_cff ? "cff" : "truetype",
+ aface );
+ Exit:
+ return error;
+ }
+
+
+ /* Create a new FT_Face from a file path to a suitcase file. */
+ static FT_Error
+ FT_New_Face_From_Suitcase( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error = FT_ERR( Cannot_Open_Resource );
+ ResFileRefNum res_ref;
+ ResourceIndex res_index;
+ Handle fond;
+ short num_faces_in_res;
+
+
+ if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
+ return FT_THROW( Cannot_Open_Resource );
+
+ UseResFile( res_ref );
+ if ( ResError() )
+ return FT_THROW( Cannot_Open_Resource );
+
+ num_faces_in_res = 0;
+ for ( res_index = 1; ; ++res_index )
+ {
+ short num_faces_in_fond;
+
+
+ fond = Get1IndResource( TTAG_FOND, res_index );
+ if ( ResError() )
+ break;
+
+ num_faces_in_fond = count_faces( fond, pathname );
+ num_faces_in_res += num_faces_in_fond;
+
+ if ( 0 <= face_index && face_index < num_faces_in_fond && error )
+ error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+
+ face_index -= num_faces_in_fond;
+ }
+
+ CloseResFile( res_ref );
+ if ( !error && aface && *aface )
+ (*aface)->num_faces = num_faces_in_res;
+ return error;
+ }
+
+
+ /* documentation is in ftmac.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FOND( FT_Library library,
+ Handle fond,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ short have_sfnt, have_lwfn = 0;
+ ResID sfnt_id, fond_id;
+ OSType fond_type;
+ Str255 fond_name;
+ Str255 lwfn_file_name;
+ UInt8 path_lwfn[PATH_MAX];
+ OSErr err;
+ FT_Error error = FT_Err_Ok;
+
+
+ /* check of `library' and `aface' delayed to `FT_New_Face_From_XXX' */
+
+ GetResInfo( fond, &fond_id, &fond_type, fond_name );
+ if ( ResError() != noErr || fond_type != TTAG_FOND )
+ return FT_THROW( Invalid_File_Format );
+
+ parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index );
+
+ if ( lwfn_file_name[0] )
+ {
+ ResFileRefNum res;
+
+
+ res = HomeResFile( fond );
+ if ( noErr != ResError() )
+ goto found_no_lwfn_file;
+
+ {
+ UInt8 path_fond[PATH_MAX];
+ FSRef ref;
+
+
+ err = FSGetForkCBInfo( res, kFSInvalidVolumeRefNum,
+ NULL, NULL, NULL, &ref, NULL );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ err = FSRefMakePath( &ref, path_fond, sizeof ( path_fond ) );
+ if ( noErr != err )
+ goto found_no_lwfn_file;
+
+ error = lookup_lwfn_by_fond( path_fond, lwfn_file_name,
+ path_lwfn, sizeof ( path_lwfn ) );
+ if ( !error )
+ have_lwfn = 1;
+ }
+ }
+
+ if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+ error = FT_New_Face_From_LWFN( library,
+ path_lwfn,
+ face_index,
+ aface );
+ else
+ error = FT_THROW( Unknown_File_Format );
+
+ found_no_lwfn_file:
+ if ( have_sfnt && error )
+ error = FT_New_Face_From_SFNT( library,
+ sfnt_id,
+ face_index,
+ aface );
+
+ return error;
+ }
+
+
+ /* Common function to load a new FT_Face from a resource file. */
+ static FT_Error
+ FT_New_Face_From_Resource( FT_Library library,
+ const UInt8* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ OSType file_type;
+ FT_Error error;
+
+
+ /* LWFN is a (very) specific file format, check for it explicitly */
+ file_type = get_file_type_from_path( pathname );
+ if ( file_type == TTAG_LWFN )
+ return FT_New_Face_From_LWFN( library, pathname, face_index, aface );
+
+ /* Otherwise the file type doesn't matter (there are more than */
+ /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
+ /* if it works, fine. */
+
+ error = FT_New_Face_From_Suitcase( library, pathname, face_index, aface );
+ if ( error == 0 )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.); */
+ /* we signal this by returning no error and no FT_Face */
+ *aface = NULL;
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face */
+ /* */
+ /* <Description> */
+ /* This is the Mac-specific implementation of FT_New_Face. In */
+ /* addition to the standard FT_New_Face() functionality, it also */
+ /* accepts pathnames to Mac suitcase files. For further */
+ /* documentation see the original FT_New_Face() in freetype.h. */
+ /* */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* pathname,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Open_Args args;
+ FT_Error error;
+
+
+ /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ if ( !pathname )
+ return FT_THROW( Invalid_Argument );
+
+ *aface = NULL;
+
+ /* try resourcefork based font: LWFN, FFIL */
+ error = FT_New_Face_From_Resource( library, (UInt8 *)pathname,
+ face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* let it fall through to normal loader (.ttf, .otf, etc.) */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSRef */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSRef is identical to FT_New_Face except it */
+ /* accepts an FSRef instead of a path. */
+ /* */
+ /* This function is deprecated because Carbon data types (FSRef) */
+ /* are not cross-platform, and thus not suitable for the freetype API. */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSRef( FT_Library library,
+ const FSRef* ref,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+ FT_Error error;
+ FT_Open_Args args;
+
+ OSErr err;
+ UInt8 pathname[PATH_MAX];
+
+
+ /* check of `library' and `aface' delayed to */
+ /* `FT_New_Face_From_Resource' */
+
+ if ( !ref )
+ return FT_THROW( Invalid_Argument );
+
+ err = FSRefMakePath( ref, pathname, sizeof ( pathname ) );
+ if ( err )
+ error = FT_THROW( Cannot_Open_Resource );
+
+ error = FT_New_Face_From_Resource( library, pathname, face_index, aface );
+ if ( error != 0 || *aface != NULL )
+ return error;
+
+ /* fallback to datafork font */
+ args.flags = FT_OPEN_PATHNAME;
+ args.pathname = (char*)pathname;
+ return FT_Open_Face( library, &args, face_index, aface );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Face_From_FSSpec */
+ /* */
+ /* <Description> */
+ /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
+ /* accepts an FSSpec instead of a path. */
+ /* */
+ /* This function is deprecated because FSSpec is deprecated in Mac OS X */
+ FT_EXPORT_DEF( FT_Error )
+ FT_New_Face_From_FSSpec( FT_Library library,
+ const FSSpec* spec,
+ FT_Long face_index,
+ FT_Face* aface )
+ {
+#if ( __LP64__ ) || ( defined( MAC_OS_X_VERSION_10_5 ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ) )
+ FT_UNUSED( library );
+ FT_UNUSED( spec );
+ FT_UNUSED( face_index );
+ FT_UNUSED( aface );
+
+ return FT_THROW( Unimplemented_Feature );
+#else
+ FSRef ref;
+
+
+ /* check of `library' and `aface' delayed to `FT_New_Face_From_FSRef' */
+
+ if ( !spec || FSpMakeFSRef( spec, &ref ) != noErr )
+ return FT_THROW( Invalid_Argument );
+ else
+ return FT_New_Face_From_FSRef( library, &ref, face_index, aface );
+#endif
+ }
+
+#endif /* FT_MACINTOSH */
+
+
+/* END */
diff --git a/src/base/ftmm.c b/src/base/ftmm.c
index 18ff879..7c012aa 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -4,7 +4,7 @@
/* */
/* Multiple Master font support (body). */
/* */
-/* Copyright 1996-2001, 2003, 2004, 2009, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -72,6 +72,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !amaster )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
@@ -94,6 +99,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !amaster )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
@@ -117,6 +127,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !coords )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
@@ -140,6 +155,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !coords )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
@@ -163,6 +183,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !coords )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
@@ -189,6 +214,11 @@
FT_Service_MultiMasters service;
+ /* check of `face' delayed to `ft_face_get_mm_service' */
+
+ if ( !coords )
+ return FT_THROW( Invalid_Argument );
+
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index ac2a39c..96572bd 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType private base classes (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -55,10 +55,19 @@
#pragma warning( disable : 4244 )
#endif /* _MSC_VER */
- /* it's easiest to include `md5.c' directly */
-#define free md5_free /* suppress a shadow warning */
+ /* It's easiest to include `md5.c' directly. However, since OpenSSL */
+ /* also provides the same functions, there might be conflicts if */
+ /* both FreeType and OpenSSL are built as static libraries. For */
+ /* this reason, we put the MD5 stuff into the `FT_' namespace. */
+#define MD5_u32plus FT_MD5_u32plus
+#define MD5_CTX FT_MD5_CTX
+#define MD5_Init FT_MD5_Init
+#define MD5_Update FT_MD5_Update
+#define MD5_Final FT_MD5_Final
+
+#undef HAVE_OPENSSL
+
#include "md5.c"
-#undef free
#if defined( _MSC_VER )
#pragma warning( pop )
@@ -160,7 +169,7 @@
FT_Stream stream = NULL;
- *astream = 0;
+ *astream = NULL;
if ( !library )
return FT_THROW( Invalid_Library_Handle );
@@ -180,7 +189,7 @@
/* create a memory-based stream */
FT_Stream_OpenMemory( stream,
(const FT_Byte*)args->memory_base,
- args->memory_size );
+ (FT_ULong)args->memory_size );
}
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
@@ -355,10 +364,10 @@
slot->bitmap_left = 0;
slot->bitmap_top = 0;
slot->num_subglyphs = 0;
- slot->subglyphs = 0;
- slot->control_data = 0;
+ slot->subglyphs = NULL;
+ slot->control_data = NULL;
slot->control_len = 0;
- slot->other = 0;
+ slot->other = NULL;
slot->format = FT_GLYPH_FORMAT_NONE;
slot->linearHoriAdvance = 0;
@@ -389,7 +398,7 @@
if ( FT_DRIVER_USES_OUTLINES( driver ) )
{
FT_GlyphLoader_Done( slot->internal->loader );
- slot->internal->loader = 0;
+ slot->internal->loader = NULL;
}
FT_FREE( slot->internal );
@@ -410,7 +419,10 @@
FT_GlyphSlot slot = NULL;
- if ( !face || !face->driver )
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !face->driver )
return FT_THROW( Invalid_Argument );
driver = face->driver;
@@ -437,7 +449,7 @@
*aslot = slot;
}
else if ( aslot )
- *aslot = 0;
+ *aslot = NULL;
Exit:
@@ -510,6 +522,7 @@
internal->transform_matrix.xy = 0;
internal->transform_matrix.yx = 0;
internal->transform_matrix.yy = 0x10000L;
+
matrix = &internal->transform_matrix;
}
else
@@ -525,6 +538,7 @@
{
internal->transform_delta.x = 0;
internal->transform_delta.y = 0;
+
delta = &internal->transform_delta;
}
else
@@ -667,11 +681,19 @@
/* the check for `num_locations' assures that we actually */
/* test for instructions in a TTF and not in a CFF-based OTF */
- if ( mode == FT_RENDER_MODE_LIGHT ||
+ /* */
+ /* since `maxSizeOfInstructions' might be unreliable, we */
+ /* check the size of the `fpgm' and `prep' tables, too -- */
+ /* the assumption is that there don't exist real TTFs where */
+ /* both `fpgm' and `prep' tables are missing */
+ if ( ( mode == FT_RENDER_MODE_LIGHT &&
+ !FT_DRIVER_HINTS_LIGHTLY( driver ) ) ||
face->internal->ignore_unpatented_hinter ||
( FT_IS_SFNT( face ) &&
ttface->num_locations &&
- ttface->max_profile.maxSizeOfInstructions == 0 ) )
+ ttface->max_profile.maxSizeOfInstructions == 0 &&
+ ttface->font_program_size == 0 &&
+ ttface->cvt_program_size == 0 ) )
autohint = TRUE;
}
}
@@ -922,7 +944,7 @@
(FT_List_Destructor)destroy_size,
memory,
driver );
- face->size = 0;
+ face->size = NULL;
/* now discard client data */
if ( face->generic.finalizer )
@@ -940,7 +962,7 @@
face->stream,
( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
- face->stream = 0;
+ face->stream = NULL;
/* get rid of it */
if ( face->internal )
@@ -958,10 +980,6 @@
(FT_List_Destructor)destroy_face,
driver->root.memory,
driver );
-
- /* check whether we need to drop the driver's glyph loader */
- if ( FT_DRIVER_USES_OUTLINES( driver ) )
- FT_GlyphLoader_Done( driver->glyph_loader );
}
@@ -1035,14 +1053,6 @@
( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
{
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
- "at too late position (%d)\n", cur - first ));
- continue;
- }
-#endif
face->charmap = cur[0];
return FT_Err_Ok;
}
@@ -1057,14 +1067,6 @@
{
if ( cur[0]->encoding == FT_ENCODING_UNICODE )
{
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
- "at too late position (%d)\n", cur - first ));
- continue;
- }
-#endif
face->charmap = cur[0];
return FT_Err_Ok;
}
@@ -1106,17 +1108,7 @@
if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
FT_Get_CMap_Format( cur[0] ) == 14 )
- {
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
- "at too late position (%d)\n", cur - first ));
- continue;
- }
-#endif
return cur[0];
- }
}
return NULL;
@@ -1133,7 +1125,8 @@
/* */
static FT_Error
open_face( FT_Driver driver,
- FT_Stream stream,
+ FT_Stream *astream,
+ FT_Bool external_stream,
FT_Long face_index,
FT_Int num_params,
FT_Parameter* params,
@@ -1141,10 +1134,11 @@
{
FT_Memory memory;
FT_Driver_Class clazz;
- FT_Face face = 0;
- FT_Error error, error2;
+ FT_Face face = NULL;
FT_Face_Internal internal = NULL;
+ FT_Error error, error2;
+
clazz = driver->clazz;
memory = driver->root.memory;
@@ -1153,21 +1147,25 @@
if ( FT_ALLOC( face, clazz->face_object_size ) )
goto Fail;
+ face->driver = driver;
+ face->memory = memory;
+ face->stream = *astream;
+
+ /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+ if ( external_stream )
+ face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
if ( FT_NEW( internal ) )
goto Fail;
face->internal = internal;
- face->driver = driver;
- face->memory = memory;
- face->stream = stream;
-
#ifdef FT_CONFIG_OPTION_INCREMENTAL
{
int i;
- face->internal->incremental_interface = 0;
+ face->internal->incremental_interface = NULL;
for ( i = 0; i < num_params && !face->internal->incremental_interface;
i++ )
if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
@@ -1177,11 +1175,12 @@
#endif
if ( clazz->init_face )
- error = clazz->init_face( stream,
+ error = clazz->init_face( *astream,
face,
(FT_Int)face_index,
num_params,
params );
+ *astream = face->stream; /* Stream may have been changed. */
if ( error )
goto Fail;
@@ -1208,7 +1207,7 @@
clazz->done_face( face );
FT_FREE( internal );
FT_FREE( face );
- *aface = 0;
+ *aface = NULL;
}
return error;
@@ -1231,7 +1230,7 @@
FT_Open_Args args;
- /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+ /* test for valid `library' and `aface' delayed to `FT_Open_Face' */
if ( !pathname )
return FT_THROW( Invalid_Argument );
@@ -1257,7 +1256,7 @@
FT_Open_Args args;
- /* test for valid `library' and `face' delayed to FT_Open_Face() */
+ /* test for valid `library' and `face' delayed to `FT_Open_Face' */
if ( !file_base )
return FT_THROW( Invalid_Argument );
@@ -1311,8 +1310,8 @@
FT_FREE( stream->base );
stream->size = 0;
- stream->base = 0;
- stream->close = 0;
+ stream->base = NULL;
+ stream->close = NULL;
}
@@ -1336,7 +1335,7 @@
if ( !base )
return FT_THROW( Invalid_Argument );
- *astream = 0;
+ *astream = NULL;
memory = library->memory;
if ( FT_NEW( stream ) )
goto Exit;
@@ -1388,13 +1387,13 @@
}
#ifdef FT_MACINTOSH
- /* At this point, face_index has served its purpose; */
+ /* At this point, the face index has served its purpose; */
/* whoever calls this function has already used it to */
/* locate the correct font data. We should not propagate */
/* this index to FT_Open_Face() (unless it is negative). */
if ( face_index > 0 )
- face_index = 0;
+ face_index &= 0x7FFF0000L; /* retain GX data */
#endif
error = FT_Open_Face( library, &args, face_index, aface );
@@ -1500,7 +1499,7 @@
FT_Error error;
FT_Memory memory = library->memory;
FT_ULong offset, length;
- FT_Long pos;
+ FT_ULong pos;
FT_Bool is_sfnt_cid;
FT_Byte* sfnt_ps = NULL;
@@ -1508,7 +1507,11 @@
FT_UNUSED( params );
- pos = FT_Stream_Pos( stream );
+ /* ignore GX stuff */
+ if ( face_index > 0 )
+ face_index &= 0xFFFFL;
+
+ pos = FT_STREAM_POS();
error = ft_lookup_PS_in_sfnt_stream( stream,
face_index,
@@ -1518,15 +1521,18 @@
if ( error )
goto Exit;
- if ( FT_Stream_Seek( stream, pos + offset ) )
+ error = FT_Stream_Seek( stream, pos + offset );
+ if ( error )
goto Exit;
if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
goto Exit;
error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
- if ( error )
+ if ( error ) {
+ FT_FREE( sfnt_ps );
goto Exit;
+ }
error = open_face_from_buffer( library,
sfnt_ps,
@@ -1571,9 +1577,9 @@
FT_Memory memory = library->memory;
FT_Byte* pfb_data = NULL;
int i, type, flags;
- FT_Long len;
- FT_Long pfb_len, pfb_pos, pfb_lenpos;
- FT_Long rlen, temp;
+ FT_ULong len;
+ FT_ULong pfb_len, pfb_pos, pfb_lenpos;
+ FT_ULong rlen, temp;
if ( face_index == -1 )
@@ -1586,14 +1592,39 @@
pfb_len = 0;
for ( i = 0; i < resource_cnt; ++i )
{
- error = FT_Stream_Seek( stream, offsets[i] );
+ error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
if ( error )
goto Exit;
- if ( FT_READ_LONG( temp ) )
+ if ( FT_READ_ULONG( temp ) )
goto Exit;
+
+ /* FT2 allocator takes signed long buffer length,
+ * too large value causing overflow should be checked
+ */
+ FT_TRACE4(( " POST fragment #%d: length=0x%08x"
+ " total pfb_len=0x%08x\n",
+ i, temp, pfb_len + temp + 6));
+ if ( FT_MAC_RFORK_MAX_LEN < temp ||
+ FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 )
+ {
+ FT_TRACE2(( " MacOS resource length cannot exceed"
+ " 0x%08x\n", FT_MAC_RFORK_MAX_LEN ));
+ error = FT_THROW( Invalid_Offset );
+ goto Exit;
+ }
+
pfb_len += temp + 6;
}
+ FT_TRACE2(( " total buffer size to concatenate %d"
+ " POST fragments: 0x%08x\n",
+ resource_cnt, pfb_len + 2));
+ if ( pfb_len + 2 < 6 ) {
+ FT_TRACE2(( " too long fragment length makes"
+ " pfb_len confused: pfb_len=0x%08x\n", pfb_len ));
+ error = FT_THROW( Array_Too_Large );
+ goto Exit;
+ }
if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
goto Exit;
@@ -1610,19 +1641,33 @@
type = 1;
for ( i = 0; i < resource_cnt; ++i )
{
- error = FT_Stream_Seek( stream, offsets[i] );
+ error = FT_Stream_Seek( stream, (FT_ULong)offsets[i] );
if ( error )
goto Exit2;
- if ( FT_READ_LONG( rlen ) )
- goto Exit;
+ if ( FT_READ_ULONG( rlen ) )
+ goto Exit2;
+
+ /* FT2 allocator takes signed long buffer length,
+ * too large fragment length causing overflow should be checked
+ */
+ if ( 0x7FFFFFFFUL < rlen )
+ {
+ error = FT_THROW( Invalid_Offset );
+ goto Exit2;
+ }
+
if ( FT_READ_USHORT( flags ) )
- goto Exit;
+ goto Exit2;
FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n",
i, offsets[i], rlen, flags ));
+ error = FT_ERR( Array_Too_Large );
/* postpone the check of rlen longer than buffer until FT_Stream_Read() */
if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */
+ {
+ FT_TRACE3(( " Skip POST fragment #%d because it is a comment\n", i ));
continue;
+ }
/* the flags are part of the resource, so rlen >= 2. */
/* but some fonts declare rlen = 0 for empty fragment */
@@ -1635,6 +1680,8 @@
len += rlen;
else
{
+ FT_TRACE3(( " Write POST fragment #%d header (4-byte) to buffer"
+ " %p + 0x%08x\n", i, pfb_data, pfb_lenpos ));
if ( pfb_lenpos + 3 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_lenpos ] = (FT_Byte)( len );
@@ -1645,6 +1692,8 @@
if ( ( flags >> 8 ) == 5 ) /* End of font mark */
break;
+ FT_TRACE3(( " Write POST fragment #%d header (6-byte) to buffer"
+ " %p + 0x%08x\n", i, pfb_data, pfb_pos ));
if ( pfb_pos + 6 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_pos++] = 0x80;
@@ -1660,16 +1709,18 @@
pfb_data[pfb_pos++] = 0;
}
- error = FT_ERR( Cannot_Open_Resource );
if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
goto Exit2;
+ FT_TRACE3(( " Load POST fragment #%d (%d byte) to buffer"
+ " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos ));
error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
if ( error )
goto Exit2;
pfb_pos += rlen;
}
+ error = FT_ERR( Array_Too_Large );
if ( pfb_pos + 2 > pfb_len + 2 )
goto Exit2;
pfb_data[pfb_pos++] = 0x80;
@@ -1690,6 +1741,13 @@
aface );
Exit2:
+ if ( error == FT_ERR( Array_Too_Large ) )
+ FT_TRACE2(( " Abort due to too-short buffer to store"
+ " all POST fragments\n" ));
+ else if ( error == FT_ERR( Invalid_Offset ) )
+ FT_TRACE2(( " Abort due to invalid offset in a POST fragment\n" ));
+ if ( error )
+ error = FT_ERR( Cannot_Open_Resource );
FT_FREE( pfb_data );
Exit:
@@ -1700,7 +1758,7 @@
/* The resource header says we've got resource_cnt `sfnt' */
/* (TrueType/OpenType) resources in this file. Look through */
/* them for the one indicated by face_index, load it into mem, */
- /* pass it on the the truetype driver and return it. */
+ /* pass it on to the truetype driver, and return it. */
/* */
static FT_Error
Mac_Read_sfnt_Resource( FT_Library library,
@@ -1713,7 +1771,7 @@
FT_Memory memory = library->memory;
FT_Byte* sfnt_data = NULL;
FT_Error error;
- FT_Long flag_offset;
+ FT_ULong flag_offset;
FT_Long rlen;
int is_cff;
FT_Long face_index_in_resource = 0;
@@ -1724,7 +1782,7 @@
if ( face_index >= resource_cnt )
return FT_THROW( Cannot_Open_Resource );
- flag_offset = offsets[face_index];
+ flag_offset = (FT_ULong)offsets[face_index];
error = FT_Stream_Seek( stream, flag_offset );
if ( error )
goto Exit;
@@ -1733,6 +1791,8 @@
goto Exit;
if ( rlen == -1 )
return FT_THROW( Cannot_Open_Resource );
+ if ( (FT_ULong)rlen > FT_MAC_RFORK_MAX_LEN )
+ return FT_THROW( Invalid_Offset );
error = open_face_PS_from_sfnt_stream( library,
stream,
@@ -1743,19 +1803,22 @@
goto Exit;
/* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
- if ( FT_Stream_Seek( stream, flag_offset + 4 ) )
- goto Exit;
-
- if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) )
- return error;
- error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen );
+ error = FT_Stream_Seek( stream, flag_offset + 4 );
if ( error )
goto Exit;
+ if ( FT_ALLOC( sfnt_data, rlen ) )
+ return error;
+ error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen );
+ if ( error ) {
+ FT_FREE( sfnt_data );
+ goto Exit;
+ }
+
is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 );
error = open_face_from_buffer( library,
sfnt_data,
- rlen,
+ (FT_ULong)rlen,
face_index_in_resource,
is_cff ? "cff" : "truetype",
aface );
@@ -1789,9 +1852,10 @@
if ( error )
return error;
+ /* POST resources must be sorted to concatenate properly */
error = FT_Raccess_Get_DataOffsets( library, stream,
map_offset, rdara_pos,
- TTAG_POST,
+ TTAG_POST, TRUE,
&data_offsets, &count );
if ( !error )
{
@@ -1804,9 +1868,11 @@
return error;
}
+ /* sfnt resources should not be sorted to preserve the face order by
+ QuickDraw API */
error = FT_Raccess_Get_DataOffsets( library, stream,
map_offset, rdara_pos,
- TTAG_sfnt,
+ TTAG_sfnt, FALSE,
&data_offsets, &count );
if ( !error )
{
@@ -1849,13 +1915,14 @@
if ( error )
goto Exit;
- if ( header[ 0] != 0 ||
- header[74] != 0 ||
- header[82] != 0 ||
- header[ 1] == 0 ||
- header[ 1] > 33 ||
- header[63] != 0 ||
- header[2 + header[1]] != 0 )
+ if ( header[ 0] != 0 ||
+ header[74] != 0 ||
+ header[82] != 0 ||
+ header[ 1] == 0 ||
+ header[ 1] > 33 ||
+ header[63] != 0 ||
+ header[2 + header[1]] != 0 ||
+ header[0x53] > 0x7F )
return FT_THROW( Unknown_File_Format );
dlen = ( header[0x53] << 24 ) |
@@ -1866,7 +1933,7 @@
rlen = ( header[0x57] << 24 ) |
( header[0x58] << 16 ) |
( header[0x59] << 8 ) |
- header[0x5a];
+ header[0x5A];
#endif /* 0 */
offset = 128 + ( ( dlen + 127 ) & ~127 );
@@ -1890,7 +1957,7 @@
FT_Memory memory = library->memory;
FT_Error error = FT_ERR( Unknown_File_Format );
- int i;
+ FT_UInt i;
char * file_names[FT_RACCESS_N_RULES];
FT_Long offsets[FT_RACCESS_N_RULES];
@@ -1898,7 +1965,7 @@
FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
FT_Open_Args args2;
- FT_Stream stream2 = 0;
+ FT_Stream stream2 = NULL;
FT_Raccess_Guess( library, stream,
@@ -1992,7 +2059,11 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
- FT_TRACE3(( "Try as dfont: %s ...", args->pathname ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE3(( "Try as dfont: " ));
+ if ( !( args->flags & FT_OPEN_MEMORY ) )
+ FT_TRACE3(( "%s ...", args->pathname ));
+#endif
error = IsMacResource( library, stream, 0, face_index, aface );
@@ -2024,8 +2095,8 @@
FT_Face *aface )
{
FT_Error error;
- FT_Driver driver;
- FT_Memory memory;
+ FT_Driver driver = NULL;
+ FT_Memory memory = NULL;
FT_Stream stream = NULL;
FT_Face face = NULL;
FT_ListNode node = NULL;
@@ -2034,8 +2105,7 @@
FT_Module* limit;
- /* test for valid `library' delayed to */
- /* FT_Stream_New() */
+ /* test for valid `library' delayed to `FT_Stream_New' */
if ( ( !aface && face_index >= 0 ) || !args )
return FT_THROW( Invalid_Argument );
@@ -2060,7 +2130,7 @@
if ( FT_MODULE_IS_DRIVER( driver ) )
{
FT_Int num_params = 0;
- FT_Parameter* params = 0;
+ FT_Parameter* params = NULL;
if ( args->flags & FT_OPEN_PARAMS )
@@ -2069,7 +2139,7 @@
params = args->params;
}
- error = open_face( driver, stream, face_index,
+ error = open_face( driver, &stream, external_stream, face_index,
num_params, params, &face );
if ( !error )
goto Success;
@@ -2094,7 +2164,7 @@
if ( FT_MODULE_IS_DRIVER( cur[0] ) )
{
FT_Int num_params = 0;
- FT_Parameter* params = 0;
+ FT_Parameter* params = NULL;
driver = FT_DRIVER( cur[0] );
@@ -2105,7 +2175,7 @@
params = args->params;
}
- error = open_face( driver, stream, face_index,
+ error = open_face( driver, &stream, external_stream, face_index,
num_params, params, &face );
if ( !error )
goto Success;
@@ -2115,7 +2185,8 @@
FT_ERR_EQ( error, Table_Missing ) )
{
/* TrueType but essential tables are missing */
- if ( FT_Stream_Seek( stream, 0 ) )
+ error = FT_Stream_Seek( stream, 0 );
+ if ( error )
break;
error = open_face_PS_from_sfnt_stream( library,
@@ -2174,10 +2245,6 @@
Success:
FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
- /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
- if ( external_stream )
- face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
-
/* add the face object to its driver's list */
if ( FT_NEW( node ) )
goto Fail;
@@ -2265,7 +2332,10 @@
goto Exit;
Fail:
- FT_Done_Face( face );
+ if ( node )
+ FT_Done_Face( face ); /* face must be in the driver's list */
+ else if ( face )
+ destroy_face( memory, face, driver );
Exit:
FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
@@ -2283,7 +2353,7 @@
FT_Open_Args open;
- /* test for valid `face' delayed to FT_Attach_Stream() */
+ /* test for valid `face' delayed to `FT_Attach_Stream' */
if ( !filepathname )
return FT_THROW( Invalid_Argument );
@@ -2309,7 +2379,7 @@
FT_Driver_Class clazz;
- /* test for valid `parameters' delayed to FT_Stream_New() */
+ /* test for valid `parameters' delayed to `FT_Stream_New' */
if ( !face )
return FT_THROW( Invalid_Face_Handle );
@@ -2345,6 +2415,9 @@
FT_EXPORT_DEF( FT_Error )
FT_Reference_Face( FT_Face face )
{
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
face->internal->refcount++;
return FT_Err_Ok;
@@ -2403,20 +2476,20 @@
FT_Driver driver;
FT_Driver_Class clazz;
- FT_Size size = 0;
- FT_ListNode node = 0;
+ FT_Size size = NULL;
+ FT_ListNode node = NULL;
if ( !face )
return FT_THROW( Invalid_Face_Handle );
if ( !asize )
- return FT_THROW( Invalid_Size_Handle );
+ return FT_THROW( Invalid_Argument );
if ( !face->driver )
return FT_THROW( Invalid_Driver_Handle );
- *asize = 0;
+ *asize = NULL;
driver = face->driver;
clazz = driver->clazz;
@@ -2429,7 +2502,7 @@
size->face = face;
/* for now, do not use any internal fields in size objects */
- size->internal = 0;
+ size->internal = NULL;
if ( clazz->init_size )
error = clazz->init_size( size );
@@ -2487,7 +2560,7 @@
if ( face->size == size )
{
- face->size = 0;
+ face->size = NULL;
if ( face->sizes_list.head )
face->size = (FT_Size)(face->sizes_list.head->data);
}
@@ -2920,6 +2993,8 @@
FT_Size_RequestRec req;
+ /* check of `face' delayed to `FT_Request_Size' */
+
if ( !char_width )
char_width = char_height;
else if ( !char_height )
@@ -2958,6 +3033,8 @@
FT_Size_RequestRec req;
+ /* check of `face' delayed to `FT_Request_Size' */
+
if ( pixel_width == 0 )
pixel_width = pixel_height;
else if ( pixel_height == 0 )
@@ -2969,14 +3046,14 @@
pixel_height = 1;
/* use `>=' to avoid potential compiler warning on 16bit platforms */
- if ( pixel_width >= 0xFFFFU )
- pixel_width = 0xFFFFU;
+ if ( pixel_width >= 0xFFFFU )
+ pixel_width = 0xFFFFU;
if ( pixel_height >= 0xFFFFU )
pixel_height = 0xFFFFU;
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
- req.width = pixel_width << 6;
- req.height = pixel_height << 6;
+ req.width = (FT_Long)( pixel_width << 6 );
+ req.height = (FT_Long)( pixel_height << 6 );
req.horiResolution = 0;
req.vertResolution = 0;
@@ -3023,18 +3100,37 @@
if ( kern_mode != FT_KERNING_UNFITTED )
{
+ FT_Pos orig_x = akerning->x;
+ FT_Pos orig_y = akerning->y;
+
+
/* we scale down kerning values for small ppem values */
/* to avoid that rounding makes them too big. */
/* `25' has been determined heuristically. */
if ( face->size->metrics.x_ppem < 25 )
- akerning->x = FT_MulDiv( akerning->x,
+ akerning->x = FT_MulDiv( orig_x,
face->size->metrics.x_ppem, 25 );
if ( face->size->metrics.y_ppem < 25 )
- akerning->y = FT_MulDiv( akerning->y,
+ akerning->y = FT_MulDiv( orig_y,
face->size->metrics.y_ppem, 25 );
akerning->x = FT_PIX_ROUND( akerning->x );
akerning->y = FT_PIX_ROUND( akerning->y );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_Pos orig_x_rounded = FT_PIX_ROUND( orig_x );
+ FT_Pos orig_y_rounded = FT_PIX_ROUND( orig_y );
+
+
+ if ( akerning->x != orig_x_rounded ||
+ akerning->y != orig_y_rounded )
+ FT_TRACE5(( "FT_Get_Kerning: horizontal kerning"
+ " (%d, %d) scaled down to (%d, %d) pixels\n",
+ orig_x_rounded / 64, orig_y_rounded / 64,
+ akerning->x / 64, akerning->y / 64 ));
+ }
+#endif
}
}
}
@@ -3108,15 +3204,6 @@
{
if ( cur[0]->encoding == encoding )
{
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
- "but in too late position to cache\n",
- cur - face->charmaps ));
- continue;
- }
-#endif
face->charmap = cur[0];
return 0;
}
@@ -3140,8 +3227,9 @@
return FT_THROW( Invalid_Face_Handle );
cur = face->charmaps;
- if ( !cur )
+ if ( !cur || !charmap )
return FT_THROW( Invalid_CharMap_Handle );
+
if ( FT_Get_CMap_Format( charmap ) == 14 )
return FT_THROW( Invalid_Argument );
@@ -3151,19 +3239,11 @@
{
if ( cur[0] == charmap )
{
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
- "but in too late position to cache\n",
- cur - face->charmaps ));
- continue;
- }
-#endif
face->charmap = cur[0];
- return 0;
+ return FT_Err_Ok;
}
}
+
return FT_THROW( Invalid_Argument );
}
@@ -3185,15 +3265,6 @@
FT_ASSERT( i < charmap->face->num_charmaps );
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( i > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
- "but in too late position to cache\n",
- i ));
- return -i;
- }
-#endif
return i;
}
@@ -3330,8 +3401,12 @@
FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
FT_TRACE1(( " 0x%x is truncated\n", charcode ));
}
+
result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
+ if ( result >= (FT_UInt)face->num_glyphs )
+ result = 0;
}
+
return result;
}
@@ -3346,10 +3421,11 @@
FT_UInt gindex = 0;
+ /* only do something if we have a charmap, and we have glyphs at all */
if ( face && face->charmap && face->num_glyphs )
{
gindex = FT_Get_Char_Index( face, 0 );
- if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs )
+ if ( gindex == 0 )
result = FT_Get_Next_Char( face, 0, &gindex );
}
@@ -3377,8 +3453,10 @@
FT_CMap cmap = FT_CMAP( face->charmap );
- do {
+ do
+ {
gindex = cmap->clazz->char_next( cmap, &code );
+
} while ( gindex >= (FT_UInt)face->num_glyphs );
result = ( gindex == 0 ) ? 0 : code;
@@ -3401,8 +3479,9 @@
FT_UInt result = 0;
- if ( face && face->charmap &&
- face->charmap->encoding == FT_ENCODING_UNICODE )
+ if ( face &&
+ face->charmap &&
+ face->charmap->encoding == FT_ENCODING_UNICODE )
{
FT_CharMap charmap = find_variant_selector_charmap( face );
FT_CMap ucmap = FT_CMAP( face->charmap );
@@ -3580,7 +3659,9 @@
FT_UInt result = 0;
- if ( face && FT_HAS_GLYPH_NAMES( face ) )
+ if ( face &&
+ FT_HAS_GLYPH_NAMES( face ) &&
+ glyph_name )
{
FT_Service_GlyphDict service;
@@ -3605,27 +3686,30 @@
FT_Pointer buffer,
FT_UInt buffer_max )
{
- FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Error error;
+ FT_Service_GlyphDict service;
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !buffer || buffer_max == 0 )
+ return FT_THROW( Invalid_Argument );
+
/* clean up buffer */
- if ( buffer && buffer_max > 0 )
- ((FT_Byte*)buffer)[0] = 0;
+ ((FT_Byte*)buffer)[0] = '\0';
- if ( face &&
- (FT_Long)glyph_index <= face->num_glyphs &&
- FT_HAS_GLYPH_NAMES( face ) )
- {
- FT_Service_GlyphDict service;
+ if ( (FT_Long)glyph_index >= face->num_glyphs )
+ return FT_THROW( Invalid_Glyph_Index );
+ if ( !FT_HAS_GLYPH_NAMES( face ) )
+ return FT_THROW( Invalid_Argument );
- FT_FACE_LOOKUP_SERVICE( face,
- service,
- GLYPH_DICT );
-
- if ( service && service->get_name )
- error = service->get_name( face, glyph_index, buffer, buffer_max );
- }
+ FT_FACE_LOOKUP_SERVICE( face, service, GLYPH_DICT );
+ if ( service && service->get_name )
+ error = service->get_name( face, glyph_index, buffer, buffer_max );
+ else
+ error = FT_THROW( Invalid_Argument );
return error;
}
@@ -3666,7 +3750,7 @@
FT_Get_Sfnt_Table( FT_Face face,
FT_Sfnt_Tag tag )
{
- void* table = 0;
+ void* table = NULL;
FT_Service_SFNT_Table service;
@@ -3716,6 +3800,8 @@
FT_ULong offset;
+ /* test for valid `length' delayed to `service->table_info' */
+
if ( !face || !FT_IS_SFNT( face ) )
return FT_THROW( Invalid_Face_Handle );
@@ -3783,12 +3869,12 @@
FT_Face face;
- if ( size == NULL )
- return FT_THROW( Invalid_Argument );
+ if ( !size )
+ return FT_THROW( Invalid_Size_Handle );
face = size->face;
- if ( face == NULL || face->driver == NULL )
- return FT_THROW( Invalid_Argument );
+ if ( !face || !face->driver )
+ return FT_THROW( Invalid_Face_Handle );
/* we don't need anything more complex than that; all size objects */
/* are already listed by the face */
@@ -3817,7 +3903,7 @@
FT_ListNode* node )
{
FT_ListNode cur;
- FT_Renderer result = 0;
+ FT_Renderer result = NULL;
if ( !library )
@@ -3829,7 +3915,7 @@
{
if ( *node )
cur = (*node)->next;
- *node = 0;
+ *node = NULL;
}
while ( cur )
@@ -3930,11 +4016,17 @@
static void
ft_remove_renderer( FT_Module module )
{
- FT_Library library = module->library;
- FT_Memory memory = library->memory;
+ FT_Library library;
+ FT_Memory memory;
FT_ListNode node;
+ library = module->library;
+ if ( !library )
+ return;
+
+ memory = library->memory;
+
node = FT_List_Find( &library->renderers, module );
if ( node )
{
@@ -3961,7 +4053,7 @@
FT_Get_Renderer( FT_Library library,
FT_Glyph_Format format )
{
- /* test for valid `library' delayed to FT_Lookup_Renderer() */
+ /* test for valid `library' delayed to `FT_Lookup_Renderer' */
return FT_Lookup_Renderer( library, format, 0 );
}
@@ -3978,12 +4070,26 @@
FT_ListNode node;
FT_Error error = FT_Err_Ok;
+ FT_Renderer_SetModeFunc set_mode;
+
if ( !library )
- return FT_THROW( Invalid_Library_Handle );
+ {
+ error = FT_THROW( Invalid_Library_Handle );
+ goto Exit;
+ }
if ( !renderer )
- return FT_THROW( Invalid_Argument );
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ if ( num_params > 0 && !parameters )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
node = FT_List_Find( &library->renderers, renderer );
if ( !node )
@@ -3997,18 +4103,14 @@
if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
library->cur_renderer = renderer;
- if ( num_params > 0 )
+ set_mode = renderer->clazz->set_mode;
+
+ for ( ; num_params > 0; num_params-- )
{
- FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode;
-
-
- for ( ; num_params > 0; num_params-- )
- {
- error = set_mode( renderer, parameters->tag, parameters->data );
- if ( error )
- break;
- parameters++;
- }
+ error = set_mode( renderer, parameters->tag, parameters->data );
+ if ( error )
+ break;
+ parameters++;
}
Exit:
@@ -4033,8 +4135,7 @@
default:
{
- FT_ListNode node = 0;
- FT_Bool update = 0;
+ FT_ListNode node = NULL;
/* small shortcut for the very common case */
@@ -4061,13 +4162,7 @@
/* now, look for another renderer that supports the same */
/* format. */
renderer = FT_Lookup_Renderer( library, slot->format, &node );
- update = 1;
}
-
- /* if we changed the current renderer for the glyph image format */
- /* we need to select it as the next current one */
- if ( !error && update && renderer )
- FT_Set_Renderer( library, renderer, 0, 0 );
}
}
@@ -4076,35 +4171,50 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_bitmap
- /* we convert to a single bitmap format for computing the checksum */
+ /*
+ * Computing the MD5 checksum is expensive, unnecessarily distorting a
+ * possible profiling of FreeType if compiled with tracing support. For
+ * this reason, we execute the following code only if explicitly
+ * requested.
+ */
+
+ /* we use FT_TRACE3 in this block */
+ if ( ft_trace_levels[trace_bitmap] >= 3 )
{
- FT_Bitmap bitmap;
- FT_Error err;
-
-
- FT_Bitmap_New( &bitmap );
-
- err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
- if ( !err )
+ /* we convert to a single bitmap format for computing the checksum */
+ if ( !error )
{
- MD5_CTX ctx;
- unsigned char md5[16];
- int i;
+ FT_Bitmap bitmap;
+ FT_Error err;
- MD5_Init( &ctx);
- MD5_Update( &ctx, bitmap.buffer, bitmap.rows * bitmap.pitch );
- MD5_Final( md5, &ctx );
+ FT_Bitmap_Init( &bitmap );
- FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
- " ",
- bitmap.rows, bitmap.pitch ));
- for ( i = 0; i < 16; i++ )
- FT_TRACE3(( "%02X", md5[i] ));
- FT_TRACE3(( "\n" ));
+ /* this also converts the bitmap flow to `down' (i.e., pitch > 0) */
+ err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
+ if ( !err )
+ {
+ MD5_CTX ctx;
+ unsigned char md5[16];
+ int i;
+ unsigned int rows = bitmap.rows;
+ unsigned int pitch = (unsigned int)bitmap.pitch;
+
+
+ MD5_Init( &ctx );
+ MD5_Update( &ctx, bitmap.buffer, rows * pitch );
+ MD5_Final( md5, &ctx );
+
+ FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
+ " ",
+ rows, pitch ));
+ for ( i = 0; i < 16; i++ )
+ FT_TRACE3(( "%02X", md5[i] ));
+ FT_TRACE3(( "\n" ));
+ }
+
+ FT_Bitmap_Done( library, &bitmap );
}
-
- FT_Bitmap_Done( library, &bitmap );
}
#undef FT_COMPONENT
@@ -4171,7 +4281,7 @@
if ( library && library->auto_hinter == module )
- library->auto_hinter = 0;
+ library->auto_hinter = NULL;
/* if the module is a renderer */
if ( FT_MODULE_IS_RENDERER( module ) )
@@ -4267,17 +4377,10 @@
/* if the module is a font driver */
if ( FT_MODULE_IS_DRIVER( module ) )
{
- /* allocate glyph loader if needed */
FT_Driver driver = FT_DRIVER( module );
driver->clazz = (FT_Driver_Class)module->clazz;
- if ( FT_DRIVER_USES_OUTLINES( driver ) )
- {
- error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
- if ( error )
- goto Fail;
- }
}
if ( clazz->module_init )
@@ -4294,21 +4397,13 @@
return error;
Fail:
- if ( FT_MODULE_IS_DRIVER( module ) )
- {
- FT_Driver driver = FT_DRIVER( module );
-
-
- if ( FT_DRIVER_USES_OUTLINES( driver ) )
- FT_GlyphLoader_Done( driver->glyph_loader );
- }
-
if ( FT_MODULE_IS_RENDERER( module ) )
{
FT_Renderer renderer = FT_RENDERER( module );
- if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
+ if ( renderer->clazz &&
+ renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
renderer->raster )
renderer->clazz->raster_class->raster_done( renderer->raster );
}
@@ -4324,7 +4419,7 @@
FT_Get_Module( FT_Library library,
const char* module_name )
{
- FT_Module result = 0;
+ FT_Module result = NULL;
FT_Module* cur;
FT_Module* limit;
@@ -4436,7 +4531,7 @@
cur[0] = cur[1];
cur++;
}
- limit[0] = 0;
+ limit[0] = NULL;
/* destroy the module */
Destroy_Module( module );
@@ -4449,7 +4544,7 @@
}
- FT_Error
+ static FT_Error
ft_property_do( FT_Library library,
const FT_String* module_name,
const FT_String* property_name,
@@ -4513,9 +4608,9 @@
service = (FT_Service_Properties)interface;
if ( set )
- missing_func = !service->set_property;
+ missing_func = (FT_Bool)( !service->set_property );
else
- missing_func = !service->get_property;
+ missing_func = (FT_Bool)( !service->get_property );
if ( missing_func )
{
@@ -4579,6 +4674,9 @@
FT_EXPORT_DEF( FT_Error )
FT_Reference_Library( FT_Library library )
{
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
library->refcount++;
return FT_Err_Ok;
@@ -4595,7 +4693,7 @@
FT_Error error;
- if ( !memory )
+ if ( !memory || !alibrary )
return FT_THROW( Invalid_Argument );
#ifdef FT_DEBUG_LEVEL_ERROR
@@ -4616,12 +4714,9 @@
goto Fail;
#endif
- /* allocate the render pool */
- library->raster_pool_size = FT_RENDER_POOL_SIZE;
-#if FT_RENDER_POOL_SIZE > 0
- if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
- goto Fail;
-#endif
+ /* we don't use raster_pool anymore. */
+ library->raster_pool_size = 0;
+ library->raster_pool = NULL;
library->version_major = FREETYPE_MAJOR;
library->version_minor = FREETYPE_MINOR;
@@ -4634,8 +4729,8 @@
return FT_Err_Ok;
- Fail:
#ifdef FT_CONFIG_OPTION_PIC
+ Fail:
ft_pic_container_destroy( library );
#endif
FT_FREE( library );
@@ -4764,16 +4859,12 @@
if ( module )
{
Destroy_Module( module );
- library->modules[n] = 0;
+ library->modules[n] = NULL;
}
}
}
#endif
- /* Destroy raster objects */
- FT_FREE( library->raster_pool );
- library->raster_pool_size = 0;
-
#ifdef FT_CONFIG_OPTION_PIC
/* Destroy pic container contents */
ft_pic_container_destroy( library );
@@ -4857,6 +4948,8 @@
*p_arg1 = subg->arg1;
*p_arg2 = subg->arg2;
*p_transform = subg->transform;
+
+ error = FT_Err_Ok;
}
return error;
diff --git a/src/base/ftotval.c b/src/base/ftotval.c
new file mode 100644
index 0000000..786457b
--- /dev/null
+++ b/src/base/ftotval.c
@@ -0,0 +1,91 @@
+/***************************************************************************/
+/* */
+/* ftotval.c */
+/* */
+/* FreeType API for validating OpenType tables (body). */
+/* */
+/* Copyright 2004-2015 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 <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_OPENTYPE_VALIDATE_H
+#include FT_OPENTYPE_VALIDATE_H
+
+
+ /* documentation is in ftotval.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_OpenType_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *BASE_table,
+ FT_Bytes *GDEF_table,
+ FT_Bytes *GPOS_table,
+ FT_Bytes *GSUB_table,
+ FT_Bytes *JSTF_table )
+ {
+ FT_Service_OTvalidate service;
+ FT_Error error;
+
+
+ if ( !face )
+ {
+ error = FT_THROW( Invalid_Face_Handle );
+ goto Exit;
+ }
+
+ if ( !( BASE_table &&
+ GDEF_table &&
+ GPOS_table &&
+ GSUB_table &&
+ JSTF_table ) )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ FT_FACE_FIND_GLOBAL_SERVICE( face, service, OPENTYPE_VALIDATE );
+
+ if ( service )
+ error = service->validate( face,
+ validation_flags,
+ BASE_table,
+ GDEF_table,
+ GPOS_table,
+ GSUB_table,
+ JSTF_table );
+ else
+ error = FT_THROW( Unimplemented_Feature );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_EXPORT_DEF( void )
+ FT_OpenType_Free( FT_Face face,
+ FT_Bytes table )
+ {
+ FT_Memory memory;
+
+
+ if ( !face )
+ return;
+
+ memory = FT_FACE_MEMORY( face );
+
+ FT_FREE( table );
+ }
+
+
+/* END */
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 54ca5cd..201ceab 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -4,7 +4,7 @@
/* */
/* FreeType outline management (body). */
/* */
-/* Copyright 1996-2008, 2010, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,8 +52,9 @@
const FT_Outline_Funcs* func_interface,
void* user )
{
-#undef SCALED
-#define SCALED( x ) ( ( (x) << shift ) - delta )
+#undef SCALED
+#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \
+ : ( (x) << shift ) ) - delta )
FT_Vector v_last;
FT_Vector v_control;
@@ -73,7 +74,10 @@
FT_Pos delta;
- if ( !outline || !func_interface )
+ if ( !outline )
+ return FT_THROW( Invalid_Outline );
+
+ if ( !func_interface )
return FT_THROW( Invalid_Argument );
shift = func_interface->shift;
@@ -128,7 +132,7 @@
v_start.x = ( v_start.x + v_last.x ) / 2;
v_start.y = ( v_start.y + v_last.y ) / 2;
- v_last = v_start;
+ /* v_last = v_start; */
}
point--;
tags--;
@@ -276,7 +280,7 @@
if ( error )
goto Exit;
- first = last + 1;
+ first = (FT_UInt)last + 1;
}
FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
@@ -317,7 +321,7 @@
FT_NEW_ARRAY( anoutline->contours, numContours ) )
goto Fail;
- anoutline->n_points = (FT_UShort)numPoints;
+ anoutline->n_points = (FT_Short)numPoints;
anoutline->n_contours = (FT_Short)numContours;
anoutline->flags |= FT_OUTLINE_OWNER;
@@ -362,7 +366,7 @@
/* empty glyph? */
if ( n_points == 0 && n_contours == 0 )
- return 0;
+ return FT_Err_Ok;
/* check point and contour counts */
if ( n_points <= 0 || n_contours <= 0 )
@@ -384,7 +388,7 @@
goto Bad;
/* XXX: check the tags array */
- return 0;
+ return FT_Err_Ok;
}
Bad:
@@ -401,8 +405,10 @@
FT_Int is_owner;
- if ( !source || !target ||
- source->n_points != target->n_points ||
+ if ( !source || !target )
+ return FT_THROW( Invalid_Outline );
+
+ if ( source->n_points != target->n_points ||
source->n_contours != target->n_contours )
return FT_THROW( Invalid_Argument );
@@ -430,20 +436,21 @@
FT_Outline_Done_Internal( FT_Memory memory,
FT_Outline* outline )
{
- if ( memory && outline )
- {
- if ( outline->flags & FT_OUTLINE_OWNER )
- {
- FT_FREE( outline->points );
- FT_FREE( outline->tags );
- FT_FREE( outline->contours );
- }
- *outline = null_outline;
+ if ( !outline )
+ return FT_THROW( Invalid_Outline );
- return FT_Err_Ok;
- }
- else
+ if ( !memory )
return FT_THROW( Invalid_Argument );
+
+ if ( outline->flags & FT_OUTLINE_OWNER )
+ {
+ FT_FREE( outline->points );
+ FT_FREE( outline->tags );
+ FT_FREE( outline->contours );
+ }
+ *outline = null_outline;
+
+ return FT_Err_Ok;
}
@@ -576,11 +583,13 @@
{
char* p = outline->tags + first;
char* q = outline->tags + last;
- char swap;
while ( p < q )
{
+ char swap;
+
+
swap = *p;
*p = *q;
*q = swap;
@@ -604,7 +613,6 @@
FT_Raster_Params* params )
{
FT_Error error;
- FT_Bool update = FALSE;
FT_Renderer renderer;
FT_ListNode node;
@@ -612,7 +620,10 @@
if ( !library )
return FT_THROW( Invalid_Library_Handle );
- if ( !outline || !params )
+ if ( !outline )
+ return FT_THROW( Invalid_Outline );
+
+ if ( !params )
return FT_THROW( Invalid_Argument );
renderer = library->cur_renderer;
@@ -635,14 +646,8 @@
/* format */
renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
&node );
- update = TRUE;
}
- /* if we changed the current renderer for the glyph image format */
- /* we need to select it as the next current one */
- if ( !error && update && renderer )
- FT_Set_Renderer( library, renderer, 0, 0 );
-
return error;
}
@@ -660,7 +665,7 @@
if ( !abitmap )
return FT_THROW( Invalid_Argument );
- /* other checks are delayed to FT_Outline_Render() */
+ /* other checks are delayed to `FT_Outline_Render' */
params.target = abitmap;
params.flags = 0;
@@ -721,7 +726,8 @@
#if 0
#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \
- do { \
+ do \
+ { \
(first) = ( c > 0 ) ? (outline)->points + \
(outline)->contours[c - 1] + 1 \
: (outline)->points; \
@@ -902,13 +908,12 @@
FT_Pos ystrength )
{
FT_Vector* points;
- FT_Vector v_prev, v_first, v_next, v_cur;
- FT_Int c, n, first;
+ FT_Int c, first, last;
FT_Int orientation;
if ( !outline )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Invalid_Outline );
xstrength /= 2;
ystrength /= 2;
@@ -929,87 +934,98 @@
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
- FT_Vector in, out, shift;
- FT_Fixed l_in, l_out, l, q, d;
- int last = outline->contours[c];
+ FT_Vector in, out, anchor, shift;
+ FT_Fixed l_in, l_out, l_anchor = 0, l, q, d;
+ FT_Int i, j, k;
- v_first = points[first];
- v_prev = points[last];
- v_cur = v_first;
+ l_in = 0;
+ last = outline->contours[c];
- /* compute incoming normalized vector */
- in.x = v_cur.x - v_prev.x;
- in.y = v_cur.y - v_prev.y;
- l_in = FT_Vector_Length( &in );
- if ( l_in )
+ /* pacify compiler */
+ in.x = in.y = anchor.x = anchor.y = 0;
+
+ /* Counter j cycles though the points; counter i advances only */
+ /* when points are moved; anchor k marks the first moved point. */
+ for ( i = last, j = first, k = -1;
+ j != i && i != k;
+ j = j < last ? j + 1 : first )
{
- in.x = FT_DivFix( in.x, l_in );
- in.y = FT_DivFix( in.y, l_in );
- }
-
- for ( n = first; n <= last; n++ )
- {
- if ( n < last )
- v_next = points[n + 1];
- else
- v_next = v_first;
-
- /* compute outgoing normalized vector */
- out.x = v_next.x - v_cur.x;
- out.y = v_next.y - v_cur.y;
- l_out = FT_Vector_Length( &out );
- if ( l_out )
+ if ( j != k )
{
- out.x = FT_DivFix( out.x, l_out );
- out.y = FT_DivFix( out.y, l_out );
- }
+ out.x = points[j].x - points[i].x;
+ out.y = points[j].y - points[i].y;
+ l_out = (FT_Fixed)FT_Vector_NormLen( &out );
- d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
-
- /* shift only if turn is less than ~160 degrees */
- if ( d > -0xF000L )
- {
- d = d + 0x10000L;
-
- /* shift components are aligned along lateral bisector */
- /* and directed according to the outline orientation. */
- shift.x = in.y + out.y;
- shift.y = in.x + out.x;
-
- if ( orientation == FT_ORIENTATION_TRUETYPE )
- shift.x = -shift.x;
- else
- shift.y = -shift.y;
-
- /* restrict shift magnitude to better handle collapsing segments */
- q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
- if ( orientation == FT_ORIENTATION_TRUETYPE )
- q = -q;
-
- l = FT_MIN( l_in, l_out );
-
- /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
- if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
- shift.x = FT_MulDiv( shift.x, xstrength, d );
- else
- shift.x = FT_MulDiv( shift.x, l, q );
-
-
- if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
- shift.y = FT_MulDiv( shift.y, ystrength, d );
- else
- shift.y = FT_MulDiv( shift.y, l, q );
+ if ( l_out == 0 )
+ continue;
}
else
- shift.x = shift.y = 0;
+ {
+ out = anchor;
+ l_out = l_anchor;
+ }
- outline->points[n].x = v_cur.x + xstrength + shift.x;
- outline->points[n].y = v_cur.y + ystrength + shift.y;
+ if ( l_in != 0 )
+ {
+ if ( k < 0 )
+ {
+ k = i;
+ anchor = in;
+ l_anchor = l_in;
+ }
- in = out;
- l_in = l_out;
- v_cur = v_next;
+ d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
+
+ /* shift only if turn is less than ~160 degrees */
+ if ( d > -0xF000L )
+ {
+ d = d + 0x10000L;
+
+ /* shift components along lateral bisector in proper orientation */
+ shift.x = in.y + out.y;
+ shift.y = in.x + out.x;
+
+ if ( orientation == FT_ORIENTATION_TRUETYPE )
+ shift.x = -shift.x;
+ else
+ shift.y = -shift.y;
+
+ /* restrict shift magnitude to better handle collapsing segments */
+ q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
+ if ( orientation == FT_ORIENTATION_TRUETYPE )
+ q = -q;
+
+ l = FT_MIN( l_in, l_out );
+
+ /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
+ if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) )
+ shift.x = FT_MulDiv( shift.x, xstrength, d );
+ else
+ shift.x = FT_MulDiv( shift.x, l, q );
+
+
+ if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) )
+ shift.y = FT_MulDiv( shift.y, ystrength, d );
+ else
+ shift.y = FT_MulDiv( shift.y, l, q );
+ }
+ else
+ shift.x = shift.y = 0;
+
+ for ( ;
+ i != j;
+ i = i < last ? i + 1 : first )
+ {
+ points[i].x += xstrength + shift.x;
+ points[i].y += ystrength + shift.y;
+ }
+ }
+ else
+ i = j;
+
+ in = out;
+ l_in = l_out;
}
first = last + 1;
@@ -1038,14 +1054,19 @@
/* We use the nonzero winding rule to find the orientation. */
/* Since glyph outlines behave much more `regular' than arbitrary */
/* cubic or quadratic curves, this test deals with the polygon */
- /* only which is spanned up by the control points. */
+ /* only that is spanned up by the control points. */
FT_Outline_Get_CBox( outline, &cbox );
- xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
+ /* Handle collapsed outlines to avoid undefined FT_MSB. */
+ if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax )
+ return FT_ORIENTATION_NONE;
+
+ xshift = FT_MSB( (FT_UInt32)( FT_ABS( cbox.xMax ) |
+ FT_ABS( cbox.xMin ) ) ) - 14;
xshift = FT_MAX( xshift, 0 );
- yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
+ yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14;
yshift = FT_MAX( yshift, 0 );
points = outline->points;
@@ -1056,13 +1077,16 @@
FT_Int last = outline->contours[c];
- v_prev = points[last];
+ v_prev.x = points[last].x >> xshift;
+ v_prev.y = points[last].y >> yshift;
for ( n = first; n <= last; n++ )
{
- v_cur = points[n];
- area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
- ( ( v_cur.x + v_prev.x ) >> xshift );
+ v_cur.x = points[n].x >> xshift;
+ v_cur.y = points[n].y >> yshift;
+
+ area += ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x );
+
v_prev = v_cur;
}
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
index 82b42f0..bf2b085 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -5,7 +5,8 @@
/* FreeType API for checking patented TrueType bytecode instructions */
/* (body). */
/* */
-/* Copyright 2007, 2008, 2010 by David Turner. */
+/* Copyright 2007-2015 by */
+/* David Turner. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
diff --git a/src/base/ftpfr.c b/src/base/ftpfr.c
new file mode 100644
index 0000000..39f089e
--- /dev/null
+++ b/src/base/ftpfr.c
@@ -0,0 +1,153 @@
+/***************************************************************************/
+/* */
+/* ftpfr.c */
+/* */
+/* FreeType API for accessing PFR-specific data (body). */
+/* */
+/* Copyright 2002-2015 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 <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_SERVICE_PFR_H
+
+
+ /* check the format */
+ static FT_Service_PfrMetrics
+ ft_pfr_check( FT_Face face )
+ {
+ FT_Service_PfrMetrics service = NULL;
+
+
+ if ( face )
+ FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
+
+ return service;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Metrics( FT_Face face,
+ FT_UInt *aoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ {
+ error = service->get_metrics( face,
+ aoutline_resolution,
+ ametrics_resolution,
+ ametrics_x_scale,
+ ametrics_y_scale );
+ }
+ else
+ {
+ FT_Fixed x_scale, y_scale;
+
+
+ /* this is not a PFR font */
+ if ( aoutline_resolution )
+ *aoutline_resolution = face->units_per_EM;
+
+ if ( ametrics_resolution )
+ *ametrics_resolution = face->units_per_EM;
+
+ x_scale = y_scale = 0x10000L;
+ if ( face->size )
+ {
+ x_scale = face->size->metrics.x_scale;
+ y_scale = face->size->metrics.y_scale;
+ }
+
+ if ( ametrics_x_scale )
+ *ametrics_x_scale = x_scale;
+
+ if ( ametrics_y_scale )
+ *ametrics_y_scale = y_scale;
+
+ error = FT_THROW( Unknown_File_Format );
+ }
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Kerning( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !avector )
+ return FT_THROW( Invalid_Argument );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ error = service->get_kerning( face, left, right, avector );
+ else
+ error = FT_Get_Kerning( face, left, right,
+ FT_KERNING_UNSCALED, avector );
+
+ return error;
+ }
+
+
+ /* documentation is in ftpfr.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PFR_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance )
+ {
+ FT_Error error;
+ FT_Service_PfrMetrics service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !aadvance )
+ return FT_THROW( Invalid_Argument );
+
+ service = ft_pfr_check( face );
+ if ( service )
+ error = service->get_advance( face, gindex, aadvance );
+ else
+ /* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+/* END */
diff --git a/src/base/ftpic.c b/src/base/ftpic.c
index 1c87101..6c4b1cd 100644
--- a/src/base/ftpic.c
+++ b/src/base/ftpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services (body). */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,7 +29,7 @@
ft_pic_container_init( FT_Library library )
{
FT_PIC_Container* pic_container = &library->pic_container;
- FT_Error error = FT_Err_Ok;
+ FT_Error error;
FT_MEM_SET( pic_container, 0, sizeof ( *pic_container ) );
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 8049117..c30c766 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -4,7 +4,7 @@
/* */
/* Embedded resource forks accessor (body). */
/* */
-/* Copyright 2004-2010, 2013 by */
+/* Copyright 2004-2015 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
@@ -29,6 +29,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
#include "basepic.h"
+#include "ftbase.h"
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
@@ -62,7 +63,7 @@
FT_UNUSED( library );
- error = FT_Stream_Seek( stream, rfork_offset );
+ error = FT_Stream_Seek( stream, (FT_ULong)rfork_offset );
if ( error )
return error;
@@ -70,25 +71,36 @@
if ( error )
return error;
- *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
- ( head[1] << 16 ) |
- ( head[2] << 8 ) |
- head[3] );
- map_pos = rfork_offset + ( ( head[4] << 24 ) |
- ( head[5] << 16 ) |
- ( head[6] << 8 ) |
- head[7] );
- rdata_len = ( head[ 8] << 24 ) |
- ( head[ 9] << 16 ) |
- ( head[10] << 8 ) |
- head[11];
+ /* ensure positive values */
+ if ( head[0] >= 0x80 || head[4] >= 0x80 || head[8] >= 0x80 )
+ return FT_THROW( Unknown_File_Format );
+
+ *rdata_pos = ( head[ 0] << 24 ) |
+ ( head[ 1] << 16 ) |
+ ( head[ 2] << 8 ) |
+ head[ 3];
+ map_pos = ( head[ 4] << 24 ) |
+ ( head[ 5] << 16 ) |
+ ( head[ 6] << 8 ) |
+ head[ 7];
+ rdata_len = ( head[ 8] << 24 ) |
+ ( head[ 9] << 16 ) |
+ ( head[10] << 8 ) |
+ head[11];
/* map_len = head[12] .. head[15] */
- if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
+ if ( *rdata_pos != map_pos - rdata_len || map_pos == 0 )
return FT_THROW( Unknown_File_Format );
- error = FT_Stream_Seek( stream, map_pos );
+ if ( FT_LONG_MAX - rfork_offset < *rdata_pos ||
+ FT_LONG_MAX - rfork_offset < map_pos )
+ return FT_THROW( Unknown_File_Format );
+
+ *rdata_pos += rfork_offset;
+ map_pos += rfork_offset;
+
+ error = FT_Stream_Seek( stream, (FT_ULong)map_pos );
if ( error )
return error;
@@ -123,7 +135,7 @@
if ( type_list == -1 )
return FT_THROW( Unknown_File_Format );
- error = FT_Stream_Seek( stream, map_pos + type_list );
+ error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) );
if ( error )
return error;
@@ -151,6 +163,7 @@
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
+ FT_Bool sort_by_res_id,
FT_Long **offsets,
FT_Long *count )
{
@@ -163,7 +176,8 @@
FT_RFork_Ref *ref = NULL;
- error = FT_Stream_Seek( stream, map_offset );
+ FT_TRACE3(( "\n" ));
+ error = FT_Stream_Seek( stream, (FT_ULong)map_offset );
if ( error )
return error;
@@ -179,17 +193,19 @@
return error;
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
- (char)( 0xff & ( tag_internal >> 24 ) ),
- (char)( 0xff & ( tag_internal >> 16 ) ),
- (char)( 0xff & ( tag_internal >> 8 ) ),
- (char)( 0xff & ( tag_internal >> 0 ) ) ));
+ (char)( 0xFF & ( tag_internal >> 24 ) ),
+ (char)( 0xFF & ( tag_internal >> 16 ) ),
+ (char)( 0xFF & ( tag_internal >> 8 ) ),
+ (char)( 0xFF & ( tag_internal >> 0 ) ) ));
+ FT_TRACE3(( " : subcount=%d, suboffset=0x%04x\n",
+ subcnt, rpos ));
if ( tag_internal == tag )
{
*count = subcnt + 1;
rpos += map_offset;
- error = FT_Stream_Seek( stream, rpos );
+ error = FT_Stream_Seek( stream, (FT_ULong)rpos );
if ( error )
return error;
@@ -208,11 +224,24 @@
goto Exit;
ref[j].offset = temp & 0xFFFFFFL;
+ FT_TRACE3(( " [%d]:"
+ " resource_id=0x%04x, offset=0x%08x\n",
+ j, ref[j].res_id, ref[j].offset ));
}
- ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
- ( int(*)(const void*, const void*) )
- ft_raccess_sort_ref_by_id );
+ if (sort_by_res_id)
+ {
+ ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ),
+ ( int(*)(const void*, const void*) )
+ ft_raccess_sort_ref_by_id );
+
+ FT_TRACE3(( " -- sort resources by their ids --\n" ));
+ for ( j = 0; j < *count; ++ j ) {
+ FT_TRACE3(( " [%d]:"
+ " resource_id=0x%04x, offset=0x%08x\n",
+ j, ref[j].res_id, ref[j].offset ));
+ }
+ }
if ( FT_NEW_ARRAY( offsets_internal, *count ) )
goto Exit;
@@ -695,9 +724,9 @@
FT_UShort n_of_entries;
int i;
- FT_UInt32 entry_id, entry_offset, entry_length = 0;
+ FT_Int32 entry_id, entry_offset, entry_length = 0;
- const FT_UInt32 resource_fork_entry_id = 0x2;
+ const FT_Int32 resource_fork_entry_id = 0x2;
FT_UNUSED( library );
FT_UNUSED( base_file_name );
@@ -795,7 +824,9 @@
tmp = ft_strrchr( original_name, '/' );
if ( tmp )
{
- ft_strncpy( new_name, original_name, tmp - original_name + 1 );
+ ft_strncpy( new_name,
+ original_name,
+ (size_t)( tmp - original_name + 1 ) );
new_name[tmp - original_name + 1] = '\0';
slash = tmp + 1;
}
diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c
index 260e91c..80304e5 100644
--- a/src/base/ftsnames.c
+++ b/src/base/ftsnames.c
@@ -7,7 +7,7 @@
/* */
/* This is _not_ used to retrieve glyph names! */
/* */
-/* Copyright 1996-2001, 2002, 2009 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index d965333..b68f3f8 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
/* */
/* I/O stream support (body). */
/* */
-/* Copyright 2000-2002, 2004-2006, 2008-2011, 2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -39,9 +39,9 @@
stream->base = (FT_Byte*) base;
stream->size = size;
stream->pos = 0;
- stream->cursor = 0;
- stream->read = 0;
- stream->close = 0;
+ stream->cursor = NULL;
+ stream->read = NULL;
+ stream->close = NULL;
}
@@ -95,11 +95,11 @@
if ( distance < 0 )
return FT_THROW( Invalid_Stream_Operation );
- return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
+ return FT_Stream_Seek( stream, stream->pos + (FT_ULong)distance );
}
- FT_BASE_DEF( FT_Long )
+ FT_BASE_DEF( FT_ULong )
FT_Stream_Pos( FT_Stream stream )
{
return stream->pos;
@@ -203,8 +203,8 @@
*pbytes = (FT_Byte*)stream->cursor;
/* equivalent to FT_Stream_ExitFrame(), with no memory block release */
- stream->cursor = 0;
- stream->limit = 0;
+ stream->cursor = NULL;
+ stream->limit = NULL;
}
return error;
@@ -226,7 +226,7 @@
FT_FREE( *pbytes );
#endif
}
- *pbytes = 0;
+ *pbytes = NULL;
}
@@ -260,7 +260,9 @@
#ifdef FT_DEBUG_MEMORY
/* assume _ft_debug_file and _ft_debug_lineno are already set */
- stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
+ stream->base = (unsigned char*)ft_mem_qalloc( memory,
+ (FT_Long)count,
+ &error );
if ( error )
goto Exit;
#else
@@ -333,8 +335,8 @@
FT_FREE( stream->base );
#endif
}
- stream->cursor = 0;
- stream->limit = 0;
+ stream->cursor = NULL;
+ stream->limit = NULL;
}
@@ -348,7 +350,7 @@
result = 0;
if ( stream->cursor < stream->limit )
- result = *stream->cursor++;
+ result = (FT_Char)*stream->cursor++;
return result;
}
@@ -357,8 +359,8 @@
FT_BASE_DEF( FT_UShort )
FT_Stream_GetUShort( FT_Stream stream )
{
- FT_Byte* p;
- FT_Short result;
+ FT_Byte* p;
+ FT_UShort result;
FT_ASSERT( stream && stream->cursor );
@@ -376,8 +378,8 @@
FT_BASE_DEF( FT_UShort )
FT_Stream_GetUShortLE( FT_Stream stream )
{
- FT_Byte* p;
- FT_Short result;
+ FT_Byte* p;
+ FT_UShort result;
FT_ASSERT( stream && stream->cursor );
@@ -396,7 +398,7 @@
FT_Stream_GetUOffset( FT_Stream stream )
{
FT_Byte* p;
- FT_Long result;
+ FT_ULong result;
FT_ASSERT( stream && stream->cursor );
@@ -414,7 +416,7 @@
FT_Stream_GetULong( FT_Stream stream )
{
FT_Byte* p;
- FT_Long result;
+ FT_ULong result;
FT_ASSERT( stream && stream->cursor );
@@ -432,7 +434,7 @@
FT_Stream_GetULongLE( FT_Stream stream )
{
FT_Byte* p;
- FT_Long result;
+ FT_ULong result;
FT_ASSERT( stream && stream->cursor );
@@ -471,7 +473,7 @@
}
stream->pos++;
- return result;
+ return (FT_Char)result;
Fail:
*error = FT_THROW( Invalid_Stream_Operation );
@@ -485,11 +487,11 @@
FT_BASE_DEF( FT_UShort )
FT_Stream_ReadUShort( FT_Stream stream,
- FT_Error* error )
+ FT_Error* error )
{
- FT_Byte reads[2];
- FT_Byte* p = 0;
- FT_Short result = 0;
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_UShort result = 0;
FT_ASSERT( stream );
@@ -506,9 +508,7 @@
p = reads;
}
else
- {
p = stream->base + stream->pos;
- }
if ( p )
result = FT_NEXT_USHORT( p );
@@ -532,11 +532,11 @@
FT_BASE_DEF( FT_UShort )
FT_Stream_ReadUShortLE( FT_Stream stream,
- FT_Error* error )
+ FT_Error* error )
{
- FT_Byte reads[2];
- FT_Byte* p = 0;
- FT_Short result = 0;
+ FT_Byte reads[2];
+ FT_Byte* p = 0;
+ FT_UShort result = 0;
FT_ASSERT( stream );
@@ -553,9 +553,7 @@
p = reads;
}
else
- {
p = stream->base + stream->pos;
- }
if ( p )
result = FT_NEXT_USHORT_LE( p );
@@ -579,11 +577,11 @@
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadUOffset( FT_Stream stream,
- FT_Error* error )
+ FT_Error* error )
{
FT_Byte reads[3];
- FT_Byte* p = 0;
- FT_Long result = 0;
+ FT_Byte* p = 0;
+ FT_ULong result = 0;
FT_ASSERT( stream );
@@ -600,9 +598,7 @@
p = reads;
}
else
- {
p = stream->base + stream->pos;
- }
if ( p )
result = FT_NEXT_UOFF3( p );
@@ -626,11 +622,11 @@
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadULong( FT_Stream stream,
- FT_Error* error )
+ FT_Error* error )
{
FT_Byte reads[4];
- FT_Byte* p = 0;
- FT_Long result = 0;
+ FT_Byte* p = 0;
+ FT_ULong result = 0;
FT_ASSERT( stream );
@@ -647,9 +643,7 @@
p = reads;
}
else
- {
p = stream->base + stream->pos;
- }
if ( p )
result = FT_NEXT_ULONG( p );
@@ -673,11 +667,11 @@
FT_BASE_DEF( FT_ULong )
FT_Stream_ReadULongLE( FT_Stream stream,
- FT_Error* error )
+ FT_Error* error )
{
FT_Byte reads[4];
- FT_Byte* p = 0;
- FT_Long result = 0;
+ FT_Byte* p = 0;
+ FT_ULong result = 0;
FT_ASSERT( stream );
@@ -694,9 +688,7 @@
p = reads;
}
else
- {
p = stream->base + stream->pos;
- }
if ( p )
result = FT_NEXT_ULONG_LE( p );
@@ -728,9 +720,12 @@
FT_Byte* cursor;
- if ( !fields || !stream )
+ if ( !fields )
return FT_THROW( Invalid_Argument );
+ if ( !stream )
+ return FT_THROW( Invalid_Stream_Handle );
+
cursor = stream->cursor;
error = FT_Err_Ok;
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index ee61cec..fecb3cc 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (body). */
/* */
-/* Copyright 2002-2006, 2008-2011, 2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,6 +24,16 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_OBJECTS_H
+#include "basepic.h"
+
+
+ /* declare an extern to access `ft_outline_glyph_class' globally */
+ /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
+ /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
+#ifndef FT_CONFIG_OPTION_PIC
+ FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class;
+#endif
+
/* documentation is in ftstroke.h */
@@ -347,7 +357,7 @@
ft_stroke_border_close( FT_StrokeBorder border,
FT_Bool reverse )
{
- FT_UInt start = border->start;
+ FT_UInt start = (FT_UInt)border->start;
FT_UInt count = border->num_points;
@@ -599,7 +609,7 @@
if ( border->start >= 0 )
ft_stroke_border_close( border, FALSE );
- border->start = border->num_points;
+ border->start = (FT_Int)border->num_points;
border->movable = FALSE;
return ft_stroke_border_lineto( border, to, FALSE );
@@ -742,7 +752,7 @@
}
}
- outline->n_points = (short)( outline->n_points + border->num_points );
+ outline->n_points += (short)border->num_points;
FT_ASSERT( FT_Outline_Check( outline ) == 0 );
}
@@ -795,6 +805,9 @@
if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !astroker )
return FT_THROW( Invalid_Argument );
memory = library->memory;
@@ -822,14 +835,17 @@
FT_Stroker_LineJoin line_join,
FT_Fixed miter_limit )
{
+ if ( !stroker )
+ return;
+
stroker->radius = radius;
stroker->line_cap = line_cap;
stroker->line_join = line_join;
stroker->miter_limit = miter_limit;
/* ensure miter limit has sensible value */
- if ( stroker->miter_limit < 0x10000 )
- stroker->miter_limit = 0x10000;
+ if ( stroker->miter_limit < 0x10000L )
+ stroker->miter_limit = 0x10000L;
/* save line join style: */
/* line join style can be temporarily changed when stroking curves */
@@ -993,7 +1009,9 @@
/* Only intersect borders if between two lineto's and both */
/* lines are long enough (line_length is zero for curves). */
- if ( !border->movable || line_length == 0 )
+ /* Also avoid U-turns of nearly 180 degree. */
+ if ( !border->movable || line_length == 0 ||
+ theta > 0x59C000 || theta < -0x59C000 )
intersect = FALSE;
else
{
@@ -1002,7 +1020,8 @@
FT_Tan( theta ) ) );
- intersect = FT_BOOL( stroker->line_length >= min_length &&
+ intersect = FT_BOOL( min_length &&
+ stroker->line_length >= min_length &&
line_length >= min_length );
}
@@ -1213,11 +1232,8 @@
goto Exit;
/* when we turn to the right, the inside side is 0 */
- inside_side = 0;
-
/* otherwise, the inside side is 1 */
- if ( turn < 0 )
- inside_side = 1;
+ inside_side = ( turn < 0 );
/* process the inside side */
error = ft_stroker_inside( stroker, inside_side, line_length );
@@ -1225,7 +1241,7 @@
goto Exit;
/* process the outside side */
- error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
+ error = ft_stroker_outside( stroker, !inside_side, line_length );
Exit:
return error;
@@ -1287,6 +1303,9 @@
FT_Fixed line_length;
+ if ( !stroker || !to )
+ return FT_THROW( Invalid_Argument );
+
delta.x = to->x - stroker->center.x;
delta.y = to->y - stroker->center.y;
@@ -1360,6 +1379,12 @@
FT_Bool first_arc = TRUE;
+ if ( !stroker || !control || !to )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
/* if all control points are coincident, this is a no-op; */
/* avoid creating a spurious corner */
if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
@@ -1556,6 +1581,12 @@
FT_Bool first_arc = TRUE;
+ if ( !stroker || !control1 || !control2 || !to )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
/* if all control points are coincident, this is a no-op; */
/* avoid creating a spurious corner */
if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
@@ -1758,6 +1789,9 @@
FT_Vector* to,
FT_Bool open )
{
+ if ( !stroker || !to )
+ return FT_THROW( Invalid_Argument );
+
/* We cannot process the first point, because there is not enough */
/* information regarding its corner/cap. The latter will be processed */
/* in the `FT_Stroker_EndSubPath' routine. */
@@ -1797,7 +1831,7 @@
FT_ASSERT( left->start >= 0 );
- new_points = left->num_points - left->start;
+ new_points = (FT_Int)left->num_points - left->start;
if ( new_points > 0 )
{
error = ft_stroke_border_grow( right, (FT_UInt)new_points );
@@ -1837,8 +1871,8 @@
}
}
- left->num_points = left->start;
- right->num_points += new_points;
+ left->num_points = (FT_UInt)left->start;
+ right->num_points += (FT_UInt)new_points;
right->movable = FALSE;
left->movable = FALSE;
@@ -1858,6 +1892,12 @@
FT_Error error = FT_Err_Ok;
+ if ( !stroker )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
if ( stroker->subpath_open )
{
FT_StrokeBorder right = stroker->borders;
@@ -1910,11 +1950,8 @@
if ( turn != 0 )
{
/* when we turn to the right, the inside side is 0 */
- inside_side = 0;
-
/* otherwise, the inside side is 1 */
- if ( turn < 0 )
- inside_side = 1;
+ inside_side = ( turn < 0 );
error = ft_stroker_inside( stroker,
inside_side,
@@ -1924,7 +1961,7 @@
/* process the outside side */
error = ft_stroker_outside( stroker,
- 1 - inside_side,
+ !inside_side,
stroker->subpath_line_length );
if ( error )
goto Exit;
@@ -1983,6 +2020,12 @@
FT_Error error;
+ if ( !stroker )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
error = ft_stroke_border_get_counts( stroker->borders + 0,
&count1, &count2 );
if ( error )
@@ -1997,8 +2040,12 @@
num_contours = count2 + count4;
Exit:
- *anum_points = num_points;
- *anum_contours = num_contours;
+ if ( anum_points )
+ *anum_points = num_points;
+
+ if ( anum_contours )
+ *anum_contours = num_contours;
+
return error;
}
@@ -2010,6 +2057,9 @@
FT_StrokerBorder border,
FT_Outline* outline )
{
+ if ( !stroker || !outline )
+ return;
+
if ( border == FT_STROKER_BORDER_LEFT ||
border == FT_STROKER_BORDER_RIGHT )
{
@@ -2059,7 +2109,10 @@
FT_Int tag; /* current point's state */
- if ( !outline || !stroker )
+ if ( !outline )
+ return FT_THROW( Invalid_Outline );
+
+ if ( !stroker )
return FT_THROW( Invalid_Argument );
FT_Stroker_Rewind( stroker );
@@ -2071,7 +2124,7 @@
FT_UInt last; /* index of last point in contour */
- last = outline->contours[n];
+ last = (FT_UInt)outline->contours[n];
limit = outline->points + last;
/* skip empty points; we don't stroke these */
@@ -2242,15 +2295,6 @@
}
- /* declare an extern to access `ft_outline_glyph_class' globally */
- /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
- /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
-#ifndef FT_CONFIG_OPTION_PIC
- extern const FT_Glyph_Class ft_outline_glyph_class;
-#endif
-#include "basepic.h"
-
-
/* documentation is in ftstroke.h */
FT_EXPORT_DEF( FT_Error )
@@ -2258,18 +2302,20 @@
FT_Stroker stroker,
FT_Bool destroy )
{
- FT_Error error = FT_ERR( Invalid_Argument );
- FT_Glyph glyph = NULL;
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Glyph glyph = NULL;
+
+ /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
FT_Library library = stroker->library;
FT_UNUSED( library );
- if ( pglyph == NULL )
+ if ( !pglyph )
goto Exit;
glyph = *pglyph;
- if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+ if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
goto Exit;
{
@@ -2293,12 +2339,14 @@
if ( error )
goto Fail;
- (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
+ FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
FT_Outline_Done( glyph->library, outline );
error = FT_Outline_New( glyph->library,
- num_points, num_contours, outline );
+ num_points,
+ (FT_Int)num_contours,
+ outline );
if ( error )
goto Fail;
@@ -2334,18 +2382,20 @@
FT_Bool inside,
FT_Bool destroy )
{
- FT_Error error = FT_ERR( Invalid_Argument );
- FT_Glyph glyph = NULL;
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FT_Glyph glyph = NULL;
+
+ /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
FT_Library library = stroker->library;
FT_UNUSED( library );
- if ( pglyph == NULL )
+ if ( !pglyph )
goto Exit;
glyph = *pglyph;
- if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
+ if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
goto Exit;
{
@@ -2379,14 +2429,14 @@
if ( error )
goto Fail;
- (void)FT_Stroker_GetBorderCounts( stroker, border,
- &num_points, &num_contours );
+ FT_Stroker_GetBorderCounts( stroker, border,
+ &num_points, &num_contours );
FT_Outline_Done( glyph->library, outline );
error = FT_Outline_New( glyph->library,
num_points,
- num_contours,
+ (FT_Int)num_contours,
outline );
if ( error )
goto Fail;
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index 241d37f..cd68533 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -4,7 +4,7 @@
/* */
/* FreeType synthesizing code for emboldening and slanting (body). */
/* */
-/* Copyright 2000-2006, 2010, 2012 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -48,9 +48,14 @@
FT_GlyphSlot_Oblique( FT_GlyphSlot slot )
{
FT_Matrix transform;
- FT_Outline* outline = &slot->outline;
+ FT_Outline* outline;
+ if ( !slot )
+ return;
+
+ outline = &slot->outline;
+
/* only oblique outline glyphs */
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
return;
@@ -84,12 +89,18 @@
FT_EXPORT_DEF( void )
FT_GlyphSlot_Embolden( FT_GlyphSlot slot )
{
- FT_Library library = slot->library;
- FT_Face face = slot->face;
+ FT_Library library;
+ FT_Face face;
FT_Error error;
FT_Pos xstr, ystr;
+ if ( !slot )
+ return;
+
+ library = slot->library;
+ face = slot->face;
+
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
slot->format != FT_GLYPH_FORMAT_BITMAP )
return;
@@ -100,10 +111,8 @@
ystr = xstr;
if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
- {
- /* ignore error */
- (void)FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
- }
+ FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
+
else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
{
/* round to full pixels */
@@ -139,10 +148,11 @@
if ( slot->advance.y )
slot->advance.y += ystr;
- slot->metrics.width += xstr;
- slot->metrics.height += ystr;
- slot->metrics.horiAdvance += xstr;
- slot->metrics.vertAdvance += ystr;
+ slot->metrics.width += xstr;
+ slot->metrics.height += ystr;
+ slot->metrics.horiAdvance += xstr;
+ slot->metrics.vertAdvance += ystr;
+ slot->metrics.horiBearingY += ystr;
/* XXX: 16-bit overflow case must be excluded before here */
if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 2c6ddac..1938fd8 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -4,7 +4,7 @@
/* */
/* ANSI-specific FreeType low-level system interface (body). */
/* */
-/* Copyright 1996-2002, 2006, 2008-2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -71,7 +71,7 @@
{
FT_UNUSED( memory );
- return ft_smalloc( size );
+ return ft_smalloc( (size_t)size );
}
@@ -104,7 +104,7 @@
FT_UNUSED( memory );
FT_UNUSED( cur_size );
- return ft_srealloc( block, new_size );
+ return ft_srealloc( block, (size_t)new_size );
}
@@ -171,7 +171,7 @@
stream->descriptor.pointer = NULL;
stream->size = 0;
- stream->base = 0;
+ stream->base = NULL;
}
@@ -212,7 +212,7 @@
file = STREAM_FILE( stream );
if ( stream->pos != offset )
- ft_fseek( file, offset, SEEK_SET );
+ ft_fseek( file, (long)offset, SEEK_SET );
return (unsigned long)ft_fread( buffer, 1, count, file );
}
@@ -232,7 +232,7 @@
stream->descriptor.pointer = NULL;
stream->pathname.pointer = (char*)filepathname;
- stream->base = 0;
+ stream->base = NULL;
stream->pos = 0;
stream->read = NULL;
stream->close = NULL;
@@ -247,7 +247,7 @@
}
ft_fseek( file, 0, SEEK_END );
- stream->size = ft_ftell( file );
+ stream->size = (unsigned long)ft_ftell( file );
if ( !stream->size )
{
FT_ERROR(( "FT_Stream_Open:" ));
@@ -292,7 +292,7 @@
memory = (FT_Memory)ft_smalloc( sizeof ( *memory ) );
if ( memory )
{
- memory->user = 0;
+ memory->user = NULL;
memory->alloc = ft_alloc;
memory->realloc = ft_realloc;
memory->free = ft_free;
diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c
index 4ffdcb7..5b24304 100644
--- a/src/base/fttrigon.c
+++ b/src/base/fttrigon.c
@@ -4,7 +4,7 @@
/* */
/* FreeType trigonometric functions (body). */
/* */
-/* Copyright 2001-2005, 2012-2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -45,7 +45,7 @@
/* this table was generated for FT_PI = 180L << 16, i.e. degrees */
#define FT_TRIG_MAX_ITERS 23
- static const FT_Fixed
+ static const FT_Angle
ft_trig_arctan_table[] =
{
1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
@@ -60,17 +60,20 @@
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
- FT_Fixed s;
- FT_Int64 v;
+ FT_Int s = 1;
- s = val;
- val = FT_ABS( val );
+ if ( val < 0 )
+ {
+ val = -val;
+ s = -1;
+ }
- v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
- val = (FT_Fixed)( v >> 32 );
+ /* 0x40000000 comes from regression analysis between true */
+ /* and CORDIC hypotenuse, so it minimizes the error */
+ val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
- return ( s >= 0 ) ? val : -val;
+ return s < 0 ? -val : val;
}
#else /* !FT_LONG64 */
@@ -79,38 +82,53 @@
static FT_Fixed
ft_trig_downscale( FT_Fixed val )
{
- FT_Fixed s;
- FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3;
+ FT_Int s = 1;
+ FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
- s = val;
- val = FT_ABS( val );
+ if ( val < 0 )
+ {
+ val = -val;
+ s = -1;
+ }
- v1 = (FT_UInt32)val >> 16;
- v2 = (FT_UInt32)( val & 0xFFFFL );
+ lo1 = (FT_UInt32)val & 0x0000FFFFU;
+ hi1 = (FT_UInt32)val >> 16;
+ lo2 = FT_TRIG_SCALE & 0x0000FFFFU;
+ hi2 = FT_TRIG_SCALE >> 16;
- k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */
- k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL ); /* constant */
+ lo = lo1 * lo2;
+ i1 = lo1 * hi2;
+ i2 = lo2 * hi1;
+ hi = hi1 * hi2;
- hi = k1 * v1;
- lo1 = k1 * v2 + k2 * v1; /* can't overflow */
+ /* Check carry overflow of i1 + i2 */
+ i1 += i2;
+ hi += (FT_UInt32)( i1 < i2 ) << 16;
- lo2 = ( k2 * v2 ) >> 16;
- lo3 = FT_MAX( lo1, lo2 );
- lo1 += lo2;
+ hi += i1 >> 16;
+ i1 = i1 << 16;
- hi += lo1 >> 16;
- if ( lo1 < lo3 )
- hi += (FT_UInt32)0x10000UL;
+ /* Check carry overflow of i1 + lo */
+ lo += i1;
+ hi += ( lo < i1 );
- val = (FT_Fixed)hi;
+ /* 0x40000000 comes from regression analysis between true */
+ /* and CORDIC hypotenuse, so it minimizes the error */
- return ( s >= 0 ) ? val : -val;
+ /* Check carry overflow of lo + 0x40000000 */
+ lo += 0x40000000UL;
+ hi += ( lo < 0x40000000UL );
+
+ val = (FT_Fixed)hi;
+
+ return s < 0 ? -val : val;
}
#endif /* !FT_LONG64 */
+ /* undefined and never called for zero vector */
static FT_Int
ft_trig_prenorm( FT_Vector* vec )
{
@@ -121,7 +139,7 @@
x = vec->x;
y = vec->y;
- shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) );
+ shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) );
if ( shift <= FT_TRIG_SAFE_MSB )
{
@@ -147,7 +165,7 @@
{
FT_Int i;
FT_Fixed x, y, xtemp, b;
- const FT_Fixed *arctanptr;
+ const FT_Angle *arctanptr;
x = vec->x;
@@ -202,7 +220,7 @@
FT_Angle theta;
FT_Int i;
FT_Fixed x, y, xtemp, b;
- const FT_Fixed *arctanptr;
+ const FT_Angle *arctanptr;
x = vec->x;
@@ -261,11 +279,12 @@
}
}
- /* round theta */
+ /* round theta to acknowledge its error that mostly comes */
+ /* from accumulated rounding errors in the arctan table */
if ( theta >= 0 )
- theta = FT_PAD_ROUND( theta, 32 );
+ theta = FT_PAD_ROUND( theta, 16 );
else
- theta = -FT_PAD_ROUND( -theta, 32 );
+ theta = -FT_PAD_ROUND( -theta, 16 );
vec->x = x;
vec->y = theta;
@@ -280,11 +299,9 @@
FT_Vector v;
- v.x = FT_TRIG_SCALE >> 8;
- v.y = 0;
- ft_trig_pseudo_rotate( &v, angle );
+ FT_Vector_Unit( &v, angle );
- return ( v.x + 0x80L ) >> 8;
+ return v.x;
}
@@ -293,7 +310,12 @@
FT_EXPORT_DEF( FT_Fixed )
FT_Sin( FT_Angle angle )
{
- return FT_Cos( FT_ANGLE_PI2 - angle );
+ FT_Vector v;
+
+
+ FT_Vector_Unit( &v, angle );
+
+ return v.y;
}
@@ -305,9 +327,7 @@
FT_Vector v;
- v.x = FT_TRIG_SCALE >> 8;
- v.y = 0;
- ft_trig_pseudo_rotate( &v, angle );
+ FT_Vector_Unit( &v, angle );
return FT_DivFix( v.y, v.x );
}
@@ -340,6 +360,9 @@
FT_Vector_Unit( FT_Vector* vec,
FT_Angle angle )
{
+ if ( !vec )
+ return;
+
vec->x = FT_TRIG_SCALE >> 8;
vec->y = 0;
ft_trig_pseudo_rotate( vec, angle );
@@ -366,30 +389,32 @@
FT_Vector v;
- v.x = vec->x;
- v.y = vec->y;
+ if ( !vec || !angle )
+ return;
- if ( angle && ( v.x != 0 || v.y != 0 ) )
+ v = *vec;
+
+ if ( v.x == 0 && v.y == 0 )
+ return;
+
+ shift = ft_trig_prenorm( &v );
+ ft_trig_pseudo_rotate( &v, angle );
+ v.x = ft_trig_downscale( v.x );
+ v.y = ft_trig_downscale( v.y );
+
+ if ( shift > 0 )
{
- shift = ft_trig_prenorm( &v );
- ft_trig_pseudo_rotate( &v, angle );
- v.x = ft_trig_downscale( v.x );
- v.y = ft_trig_downscale( v.y );
-
- if ( shift > 0 )
- {
- FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
+ FT_Int32 half = (FT_Int32)1L << ( shift - 1 );
- vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
- vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
- }
- else
- {
- shift = -shift;
- vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
- vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
- }
+ vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
+ vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
+ }
+ else
+ {
+ shift = -shift;
+ vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
+ vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
}
}
@@ -403,6 +428,9 @@
FT_Vector v;
+ if ( !vec )
+ return 0;
+
v = *vec;
/* handle trivial cases */
@@ -422,7 +450,7 @@
v.x = ft_trig_downscale( v.x );
if ( shift > 0 )
- return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
+ return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift;
return (FT_Fixed)( (FT_UInt32)v.x << -shift );
}
@@ -439,6 +467,9 @@
FT_Vector v;
+ if ( !vec || !length || !angle )
+ return;
+
v = *vec;
if ( v.x == 0 && v.y == 0 )
@@ -449,8 +480,8 @@
v.x = ft_trig_downscale( v.x );
- *length = ( shift >= 0 ) ? ( v.x >> shift )
- : (FT_Fixed)( (FT_UInt32)v.x << -shift );
+ *length = shift >= 0 ? ( v.x >> shift )
+ : (FT_Fixed)( (FT_UInt32)v.x << -shift );
*angle = v.y;
}
@@ -462,6 +493,9 @@
FT_Fixed length,
FT_Angle angle )
{
+ if ( !vec )
+ return;
+
vec->x = length;
vec->y = 0;
@@ -478,11 +512,10 @@
FT_Angle delta = angle2 - angle1;
- delta %= FT_ANGLE_2PI;
- if ( delta < 0 )
+ while ( delta <= -FT_ANGLE_PI )
delta += FT_ANGLE_2PI;
- if ( delta > FT_ANGLE_PI )
+ while ( delta > FT_ANGLE_PI )
delta -= FT_ANGLE_2PI;
return delta;
diff --git a/src/base/fttype1.c b/src/base/fttype1.c
index 1d17402..c549382 100644
--- a/src/base/fttype1.c
+++ b/src/base/fttype1.c
@@ -1,114 +1,127 @@
-/***************************************************************************/
-/* */
-/* fttype1.c */
-/* */
-/* FreeType utility file for PS names support (body). */
-/* */
-/* Copyright 2002-2004, 2011 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 <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_SERVICE_H
-#include FT_SERVICE_POSTSCRIPT_INFO_H
-
-
- /* documentation is in t1tables.h */
-
- FT_EXPORT_DEF( FT_Error )
- FT_Get_PS_Font_Info( FT_Face face,
- PS_FontInfoRec* afont_info )
- {
- FT_Error error = FT_ERR( Invalid_Argument );
-
-
- if ( face )
- {
- FT_Service_PsInfo service = NULL;
-
-
- FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
-
- if ( service && service->ps_get_font_info )
- error = service->ps_get_font_info( face, afont_info );
- }
-
- return error;
- }
-
-
- /* documentation is in t1tables.h */
-
- FT_EXPORT_DEF( FT_Int )
- FT_Has_PS_Glyph_Names( FT_Face face )
- {
- FT_Int result = 0;
- FT_Service_PsInfo service = NULL;
-
-
- if ( face )
- {
- FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
-
- if ( service && service->ps_has_glyph_names )
- result = service->ps_has_glyph_names( face );
- }
-
- return result;
- }
-
-
- /* documentation is in t1tables.h */
-
- FT_EXPORT_DEF( FT_Error )
- FT_Get_PS_Font_Private( FT_Face face,
- PS_PrivateRec* afont_private )
- {
- FT_Error error = FT_ERR( Invalid_Argument );
-
-
- if ( face )
- {
- FT_Service_PsInfo service = NULL;
-
-
- FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
-
- if ( service && service->ps_get_font_private )
- error = service->ps_get_font_private( face, afont_private );
- }
-
- return error;
- }
-
-/* documentation is in t1tables.h */
-FT_EXPORT_DEF( FT_Long )
-FT_Get_PS_Font_Value( FT_Face face,
- PS_Dict_Keys key,
- FT_UInt idx,
- void *value,
- FT_Long value_len )
-{
- FT_Int result = 0;
- FT_Service_PsInfo service = NULL;
-
- if ( face )
- {
- FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
- if ( service && service->ps_get_font_value )
- result = service->ps_get_font_value( face, key, idx,
- value, value_len );
- }
- return result;
-}
-
-/* END */
+/***************************************************************************/
+/* */
+/* fttype1.c */
+/* */
+/* FreeType utility file for PS names support (body). */
+/* */
+/* Copyright 2002-2015 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 <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_INFO_H
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PS_Font_Info( FT_Face face,
+ PS_FontInfoRec* afont_info )
+ {
+ FT_Error error;
+ FT_Service_PsInfo service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !afont_info )
+ return FT_THROW( Invalid_Argument );
+
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_info )
+ error = service->ps_get_font_info( face, afont_info );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Int )
+ FT_Has_PS_Glyph_Names( FT_Face face )
+ {
+ FT_Int result = 0;
+ FT_Service_PsInfo service;
+
+
+ if ( face )
+ {
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_has_glyph_names )
+ result = service->ps_has_glyph_names( face );
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Get_PS_Font_Private( FT_Face face,
+ PS_PrivateRec* afont_private )
+ {
+ FT_Error error;
+ FT_Service_PsInfo service;
+
+
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !afont_private )
+ return FT_THROW( Invalid_Argument );
+
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_private )
+ error = service->ps_get_font_private( face, afont_private );
+ else
+ error = FT_THROW( Invalid_Argument );
+
+ return error;
+ }
+
+
+ /* documentation is in t1tables.h */
+
+ FT_EXPORT_DEF( FT_Long )
+ FT_Get_PS_Font_Value( FT_Face face,
+ PS_Dict_Keys key,
+ FT_UInt idx,
+ void *value,
+ FT_Long value_len )
+ {
+ FT_Int result = 0;
+ FT_Service_PsInfo service = NULL;
+
+
+ if ( face )
+ {
+ FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
+
+ if ( service && service->ps_get_font_value )
+ result = service->ps_get_font_value( face, key, idx,
+ value, value_len );
+ }
+
+ return result;
+ }
+
+
+/* END */
diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index 879d027..f5b72db 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for memory and list management (body). */
/* */
-/* Copyright 2002, 2004-2007, 2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -180,7 +180,7 @@
FT_Error *p_error )
{
FT_Error error;
- FT_Pointer p = ft_mem_qalloc( memory, size, &error );
+ FT_Pointer p = ft_mem_qalloc( memory, (FT_Long)size, &error );
if ( !error && address )
@@ -245,6 +245,9 @@
FT_ListNode cur;
+ if ( !list )
+ return NULL;
+
cur = list->head;
while ( cur )
{
@@ -254,7 +257,7 @@
cur = cur->next;
}
- return (FT_ListNode)0;
+ return NULL;
}
@@ -264,10 +267,15 @@
FT_List_Add( FT_List list,
FT_ListNode node )
{
- FT_ListNode before = list->tail;
+ FT_ListNode before;
- node->next = 0;
+ if ( !list || !node )
+ return;
+
+ before = list->tail;
+
+ node->next = NULL;
node->prev = before;
if ( before )
@@ -285,11 +293,16 @@
FT_List_Insert( FT_List list,
FT_ListNode node )
{
- FT_ListNode after = list->head;
+ FT_ListNode after;
+ if ( !list || !node )
+ return;
+
+ after = list->head;
+
node->next = after;
- node->prev = 0;
+ node->prev = NULL;
if ( !after )
list->tail = node;
@@ -309,6 +322,9 @@
FT_ListNode before, after;
+ if ( !list || !node )
+ return;
+
before = node->prev;
after = node->next;
@@ -333,6 +349,9 @@
FT_ListNode before, after;
+ if ( !list || !node )
+ return;
+
before = node->prev;
after = node->next;
@@ -347,7 +366,7 @@
else
list->tail = before;
- node->prev = 0;
+ node->prev = NULL;
node->next = list->head;
list->head->prev = node;
list->head = node;
@@ -357,14 +376,19 @@
/* documentation is in ftlist.h */
FT_EXPORT_DEF( FT_Error )
- FT_List_Iterate( FT_List list,
- FT_List_Iterator iterator,
- void* user )
+ FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user )
{
- FT_ListNode cur = list->head;
+ FT_ListNode cur;
FT_Error error = FT_Err_Ok;
+ if ( !list || !iterator )
+ return FT_THROW( Invalid_Argument );
+
+ cur = list->head;
+
while ( cur )
{
FT_ListNode next = cur->next;
@@ -392,6 +416,9 @@
FT_ListNode cur;
+ if ( !list || !memory )
+ return;
+
cur = list->head;
while ( cur )
{
@@ -406,30 +433,8 @@
cur = next;
}
- list->head = 0;
- list->tail = 0;
- }
-
-
- FT_BASE_DEF( FT_UInt32 )
- ft_highpow2( FT_UInt32 value )
- {
- FT_UInt32 value2;
-
-
- /*
- * We simply clear the lowest bit in each iteration. When
- * we reach 0, we know that the previous value was our result.
- */
- for ( ;; )
- {
- value2 = value & (value - 1); /* clear lowest bit */
- if ( value2 == 0 )
- break;
-
- value = value2;
- }
- return value;
+ list->head = NULL;
+ list->tail = NULL;
}
diff --git a/src/base/ftwinfnt.c b/src/base/ftwinfnt.c
index 463ae76..76a19af 100644
--- a/src/base/ftwinfnt.c
+++ b/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing Windows FNT specific info (body). */
/* */
-/* Copyright 2003, 2004 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,6 +17,7 @@
#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
#include FT_WINFONTS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_WINFNT_H
@@ -32,17 +33,18 @@
FT_Error error;
- error = FT_ERR( Invalid_Argument );
+ if ( !face )
+ return FT_THROW( Invalid_Face_Handle );
- if ( face != NULL )
- {
- FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
+ if ( !header )
+ return FT_THROW( Invalid_Argument );
- if ( service != NULL )
- {
- error = service->get_header( face, header );
- }
- }
+ FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
+
+ if ( service )
+ error = service->get_header( face, header );
+ else
+ error = FT_THROW( Invalid_Argument );
return error;
}
diff --git a/src/base/md5.c b/src/base/md5.c
index 2f01c93..52d96ac 100644
--- a/src/base/md5.c
+++ b/src/base/md5.c
@@ -50,7 +50,8 @@
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
@@ -89,13 +90,13 @@
* This processes one or more 64-byte data blocks, but does NOT update
* the bit counters. There are no alignment requirements.
*/
-static void *body(MD5_CTX *ctx, void *data, unsigned long size)
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
- unsigned char *ptr;
+ const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
- ptr = (unsigned char *)data;
+ ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
@@ -146,21 +147,21 @@
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
- STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
- STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
- STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
- STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
- STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
- STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
- STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
- STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
@@ -207,10 +208,10 @@
ctx->hi = 0;
}
-void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
- unsigned long used, free;
+ unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
@@ -220,16 +221,16 @@
used = saved_lo & 0x3f;
if (used) {
- free = 64 - used;
+ available = 64 - used;
- if (size < free) {
+ if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
- memcpy(&ctx->buffer[used], data, free);
- data = (unsigned char *)data + free;
- size -= free;
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
body(ctx, ctx->buffer, 64);
}
@@ -243,22 +244,22 @@
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
- unsigned long used, free;
+ unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
- free = 64 - used;
+ available = 64 - used;
- if (free < 8) {
- memset(&ctx->buffer[used], 0, free);
+ if (available < 8) {
+ memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
- free = 64;
+ available = 64;
}
- memset(&ctx->buffer[used], 0, free - 8);
+ memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
ctx->buffer[56] = ctx->lo;
diff --git a/src/base/md5.h b/src/base/md5.h
index f1a6857..2da44bf 100644
--- a/src/base/md5.h
+++ b/src/base/md5.h
@@ -39,7 +39,7 @@
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
-extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif
diff --git a/src/base/ftxf86.c b/src/cache/ftcache.c
similarity index 67%
rename from src/base/ftxf86.c
rename to src/cache/ftcache.c
index a4bf767..8de527a 100644
--- a/src/base/ftxf86.c
+++ b/src/cache/ftcache.c
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* ftxf86.c */
+/* ftcache.c */
/* */
-/* FreeType utility file for X11 support (body). */
+/* The FreeType Caching sub-system (body only). */
/* */
-/* Copyright 2002, 2003, 2004 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,25 +16,16 @@
/***************************************************************************/
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
#include <ft2build.h>
-#include FT_XFREE86_H
-#include FT_INTERNAL_OBJECTS_H
-#include FT_SERVICE_XFREE86_NAME_H
-
-
- /* documentation is in ftxf86.h */
-
- FT_EXPORT_DEF( const char* )
- FT_Get_X11_Font_Format( FT_Face face )
- {
- const char* result = NULL;
-
-
- if ( face )
- FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
-
- return result;
- }
-
+#include "ftcmru.c"
+#include "ftcmanag.c"
+#include "ftccache.c"
+#include "ftccmap.c"
+#include "ftcglyph.c"
+#include "ftcimage.c"
+#include "ftcsbits.c"
+#include "ftcbasic.c"
/* END */
diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c
index 84d336d..ac3290c 100644
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType basic cache interface (body). */
/* */
-/* Copyright 2003-2007, 2009-2011, 2013 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -45,8 +45,8 @@
FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
(a)->load_flags == (b)->load_flags )
-#define FTC_BASIC_ATTR_HASH( a ) \
- ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
+#define FTC_BASIC_ATTR_HASH( a ) \
+ ( FTC_SCALER_HASH( &(a)->scaler ) + 31 * (a)->load_flags )
typedef struct FTC_BasicQueryRec_
@@ -110,10 +110,9 @@
return result;
if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
- {
- FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
- FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
- }
+ FT_TRACE1(( "ftc_basic_family_get_count:"
+ " too large number of glyphs in this face, truncated\n",
+ face->num_glyphs ));
if ( !error )
result = (FT_UInt)face->num_glyphs;
@@ -139,8 +138,10 @@
FT_Face face = size->face;
- error = FT_Load_Glyph( face, gindex,
- family->attrs.load_flags | FT_LOAD_RENDER );
+ error = FT_Load_Glyph(
+ face,
+ gindex,
+ (FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
if ( !error )
*aface = face;
}
@@ -170,7 +171,9 @@
{
face = size->face;
- error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
+ error = FT_Load_Glyph( face,
+ gindex,
+ (FT_Int)family->attrs.load_flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
@@ -229,7 +232,7 @@
*
*/
- FT_CALLBACK_TABLE_DEF
+ static
const FTC_IFamilyClassRec ftc_basic_image_family_class =
{
{
@@ -243,7 +246,7 @@
};
- FT_CALLBACK_TABLE_DEF
+ static
const FTC_GCacheClassRec ftc_basic_image_cache_class =
{
{
@@ -284,10 +287,10 @@
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FT_Error error;
- FT_PtrDist hash;
+ FT_Offset hash;
- /* some argument checks are delayed to FTC_Cache_Lookup */
+ /* some argument checks are delayed to `FTC_Cache_Lookup' */
if ( !aglyph )
{
error = FT_THROW( Invalid_Argument );
@@ -298,18 +301,15 @@
if ( anode )
*anode = NULL;
- {
- if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
- {
- FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
- FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
- }
+ if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+ FT_TRACE1(( "FTC_ImageCache_Lookup:"
+ " higher bits in load_flags 0x%x are dropped\n",
+ (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
- query.attrs.scaler.face_id = type->face_id;
- query.attrs.scaler.width = type->width;
- query.attrs.scaler.height = type->height;
- query.attrs.load_flags = (FT_UInt)type->flags;
- }
+ query.attrs.scaler.face_id = type->face_id;
+ query.attrs.scaler.width = type->width;
+ query.attrs.scaler.height = type->height;
+ query.attrs.load_flags = (FT_UInt)type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
@@ -360,10 +360,10 @@
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FT_Error error;
- FT_PtrDist hash;
+ FT_Offset hash;
- /* some argument checks are delayed to FTC_Cache_Lookup */
+ /* some argument checks are delayed to `FTC_Cache_Lookup' */
if ( !aglyph || !scaler )
{
error = FT_THROW( Invalid_Argument );
@@ -374,12 +374,11 @@
if ( anode )
*anode = NULL;
- /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+ /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
if ( load_flags > FT_UINT_MAX )
- {
- FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
- FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
- }
+ FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
+ " higher bits in load_flags 0x%x are dropped\n",
+ load_flags & ~((FT_ULong)FT_UINT_MAX) ));
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
@@ -415,7 +414,7 @@
*
*/
- FT_CALLBACK_TABLE_DEF
+ static
const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
{
{
@@ -430,7 +429,7 @@
};
- FT_CALLBACK_TABLE_DEF
+ static
const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
{
{
@@ -471,30 +470,27 @@
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
- FT_PtrDist hash;
+ FT_Offset hash;
if ( anode )
*anode = NULL;
- /* other argument checks delayed to FTC_Cache_Lookup */
+ /* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit )
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
- {
- if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
- {
- FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
- FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
- }
+ if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX )
+ FT_TRACE1(( "FTC_ImageCache_Lookup:"
+ " higher bits in load_flags 0x%x are dropped\n",
+ (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
- query.attrs.scaler.face_id = type->face_id;
- query.attrs.scaler.width = type->width;
- query.attrs.scaler.height = type->height;
- query.attrs.load_flags = (FT_UInt)type->flags;
- }
+ query.attrs.scaler.face_id = type->face_id;
+ query.attrs.scaler.width = type->width;
+ query.attrs.scaler.height = type->height;
+ query.attrs.load_flags = (FT_UInt)type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
@@ -549,24 +545,23 @@
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
- FT_PtrDist hash;
+ FT_Offset hash;
if ( anode )
*anode = NULL;
- /* other argument checks delayed to FTC_Cache_Lookup */
+ /* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit || !scaler )
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
- /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+ /* `FT_Load_Glyph' and `FT_Load_Char' take FT_UInt flags */
if ( load_flags > FT_UINT_MAX )
- {
- FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
- FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
- }
+ FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
+ " higher bits in load_flags 0x%x are dropped\n",
+ load_flags & ~((FT_ULong)FT_UINT_MAX) ));
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index f20dd45..b82a789 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType internal cache interface (body). */
/* */
-/* Copyright 2000-2007, 2009-2011, 2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -88,16 +88,16 @@
* body for FTC_NODE__TOP_FOR_HASH( cache, hash )
*/
FT_LOCAL_DEF( FTC_Node* )
- ftc_get_top_node_for_hash( FTC_Cache cache,
- FT_PtrDist hash )
+ ftc_get_top_node_for_hash( FTC_Cache cache,
+ FT_Offset hash )
{
FTC_Node* pnode;
- FT_UInt idx;
+ FT_Offset idx;
- idx = (FT_UInt)( hash & cache->mask );
+ idx = hash & cache->mask;
if ( idx < cache->p )
- idx = (FT_UInt)( hash & ( 2 * cache->mask + 1 ) );
+ idx = hash & ( 2 * cache->mask + 1 );
pnode = cache->buckets + idx;
return pnode;
}
@@ -414,7 +414,7 @@
static void
ftc_cache_add( FTC_Cache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FTC_Node node )
{
node->hash = hash;
@@ -442,7 +442,7 @@
FT_LOCAL_DEF( FT_Error )
FTC_Cache_NewNode( FTC_Cache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_Pointer query,
FTC_Node *anode )
{
@@ -481,7 +481,7 @@
FT_LOCAL_DEF( FT_Error )
FTC_Cache_Lookup( FTC_Cache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_Pointer query,
FTC_Node *anode )
{
@@ -576,7 +576,7 @@
FTC_Node* pnode = bucket;
- for ( ;; )
+ for (;;)
{
FTC_Node node = *pnode;
FT_Bool list_changed = FALSE;
diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h
index 4155f32..4e17c7a 100644
--- a/src/cache/ftccache.h
+++ b/src/cache/ftccache.h
@@ -4,7 +4,7 @@
/* */
/* FreeType internal cache interface (specification). */
/* */
-/* Copyright 2000-2007, 2009-2011, 2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,8 +24,8 @@
FT_BEGIN_HEADER
-#define _FTC_FACE_ID_HASH( i ) \
- ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
+#define _FTC_FACE_ID_HASH( i ) \
+ ( ( (FT_Offset)(i) >> 3 ) ^ ( (FT_Offset)(i) << 7 ) )
/* handle to cache object */
typedef struct FTC_CacheRec_* FTC_Cache;
@@ -59,7 +59,7 @@
{
FTC_MruNodeRec mru; /* circular mru list pointer */
FTC_Node link; /* used for hashing */
- FT_PtrDist hash; /* used for hashing too */
+ FT_Offset hash; /* used for hashing too */
FT_UShort cache_index; /* index of cache the node belongs to */
FT_Short ref_count; /* reference count for this node */
@@ -80,8 +80,8 @@
: ( ( hash ) & ( cache )->mask ) ) )
#else
FT_LOCAL( FTC_Node* )
- ftc_get_top_node_for_hash( FTC_Cache cache,
- FT_PtrDist hash );
+ ftc_get_top_node_for_hash( FTC_Cache cache,
+ FT_Offset hash );
#define FTC_NODE__TOP_FOR_HASH( cache, hash ) \
ftc_get_top_node_for_hash( ( cache ), ( hash ) )
#endif
@@ -179,14 +179,14 @@
#ifndef FTC_INLINE
FT_LOCAL( FT_Error )
FTC_Cache_Lookup( FTC_Cache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_Pointer query,
FTC_Node *anode );
#endif
FT_LOCAL( FT_Error )
FTC_Cache_NewNode( FTC_Cache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_Pointer query,
FTC_Node *anode );
@@ -211,7 +211,7 @@
FT_BEGIN_STMNT \
FTC_Node *_bucket, *_pnode, _node; \
FTC_Cache _cache = FTC_CACHE(cache); \
- FT_PtrDist _hash = (FT_PtrDist)(hash); \
+ FT_Offset _hash = (FT_Offset)(hash); \
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
FT_Bool _list_changed = FALSE; \
\
diff --git a/src/cache/ftccback.h b/src/cache/ftccback.h
index 9528279..b3237d5 100644
--- a/src/cache/ftccback.h
+++ b/src/cache/ftccback.h
@@ -4,7 +4,7 @@
/* */
/* Callback functions of the caching sub-system (specification only). */
/* */
-/* Copyright 2004-2006, 2011, 2013 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c
index 848349b..b826222 100644
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
/* */
/* FreeType CharMap cache (body) */
/* */
-/* Copyright 2000-2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -63,8 +63,6 @@
} FTC_CMapQueryRec, *FTC_CMapQuery;
#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
-#define FTC_CMAP_QUERY_HASH( x ) \
- FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
/* the cmap cache node */
typedef struct FTC_CMapNodeRec_
@@ -78,8 +76,6 @@
} FTC_CMapNodeRec, *FTC_CMapNode;
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
-#define FTC_CMAP_NODE_HASH( x ) \
- FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
@@ -202,7 +198,7 @@
/*************************************************************************/
- FT_CALLBACK_TABLE_DEF
+ static
const FTC_CacheClassRec ftc_cmap_cache_class =
{
ftc_cmap_node_new,
@@ -242,7 +238,7 @@
FTC_Node node;
FT_Error error;
FT_UInt gindex = 0;
- FT_PtrDist hash;
+ FT_Offset hash;
FT_Int no_cmap_change = 0;
@@ -263,11 +259,14 @@
return 0;
}
+ if ( !face_id )
+ return 0;
+
query.face_id = face_id;
query.cmap_index = (FT_UInt)cmap_index;
query.char_code = char_code;
- hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
+ hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );
#if 1
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
@@ -301,12 +300,6 @@
if ( error )
goto Exit;
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- /* something rotten can happen with rogue clients */
- if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
- return 0; /* XXX: should return appropriate error */
-#endif
-
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
{
FT_CharMap old, cmap = NULL;
diff --git a/src/cache/ftcerror.h b/src/cache/ftcerror.h
new file mode 100644
index 0000000..15adec5
--- /dev/null
+++ b/src/cache/ftcerror.h
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/* */
+/* ftcerror.h */
+/* */
+/* Caching sub-system error codes (specification only). */
+/* */
+/* Copyright 2001-2015 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 define the caching sub-system error enumeration */
+ /* constants. */
+ /* */
+ /*************************************************************************/
+
+#ifndef __FTCERROR_H__
+#define __FTCERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef FT_ERR_PREFIX
+#define FT_ERR_PREFIX FTC_Err_
+#define FT_ERR_BASE FT_Mod_Err_Cache
+
+#include FT_ERRORS_H
+
+#endif /* __FTCERROR_H__ */
+
+/* END */
diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c
index 441e177..343b8a7 100644
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Glyph Image (FT_Glyph) cache (body). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006, 2009, 2011 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -185,7 +185,7 @@
FT_LOCAL_DEF( FT_Error )
FTC_GCache_Lookup( FTC_GCache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_UInt gindex,
FTC_GQuery query,
FTC_Node *anode )
diff --git a/src/cache/ftcglyph.h b/src/cache/ftcglyph.h
index 5fed19c..6cadbe2 100644
--- a/src/cache/ftcglyph.h
+++ b/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType abstract glyph cache (specification). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -260,7 +260,7 @@
#ifndef FTC_INLINE
FT_LOCAL( FT_Error )
FTC_GCache_Lookup( FTC_GCache cache,
- FT_PtrDist hash,
+ FT_Offset hash,
FT_UInt gindex,
FTC_GQuery query,
FTC_Node *anode );
diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c
new file mode 100644
index 0000000..f519a61
--- /dev/null
+++ b/src/cache/ftcimage.c
@@ -0,0 +1,164 @@
+/***************************************************************************/
+/* */
+/* ftcimage.c */
+/* */
+/* FreeType Image cache (body). */
+/* */
+/* Copyright 2000-2015 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 <ft2build.h>
+#include FT_CACHE_H
+#include "ftcimage.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+ /* finalize a given glyph image node */
+ FT_LOCAL_DEF( void )
+ ftc_inode_free( FTC_Node ftcinode,
+ FTC_Cache cache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Memory memory = cache->memory;
+
+
+ if ( inode->glyph )
+ {
+ FT_Done_Glyph( inode->glyph );
+ inode->glyph = NULL;
+ }
+
+ FTC_GNode_Done( FTC_GNODE( inode ), cache );
+ FT_FREE( inode );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache )
+ {
+ ftc_inode_free( FTC_NODE( inode ), cache );
+ }
+
+
+ /* initialize a new glyph image node */
+ FT_LOCAL_DEF( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache )
+ {
+ FT_Memory memory = cache->memory;
+ FT_Error error;
+ FTC_INode inode = NULL;
+
+
+ if ( !FT_NEW( inode ) )
+ {
+ FTC_GNode gnode = FTC_GNODE( inode );
+ FTC_Family family = gquery->family;
+ FT_UInt gindex = gquery->gindex;
+ FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
+
+
+ /* initialize its inner fields */
+ FTC_GNode_Init( gnode, gindex, family );
+
+ /* we will now load the glyph image */
+ error = clazz->family_load_glyph( family, gindex, cache,
+ &inode->glyph );
+ if ( error )
+ {
+ FTC_INode_Free( inode, cache );
+ inode = NULL;
+ }
+ }
+
+ *pinode = inode;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ ftc_inode_new( FTC_Node *ftcpinode,
+ FT_Pointer ftcgquery,
+ FTC_Cache cache )
+ {
+ FTC_INode *pinode = (FTC_INode*)ftcpinode;
+ FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
+
+
+ return FTC_INode_New( pinode, gquery, cache );
+ }
+
+
+ FT_LOCAL_DEF( FT_Offset )
+ ftc_inode_weight( FTC_Node ftcinode,
+ FTC_Cache ftccache )
+ {
+ FTC_INode inode = (FTC_INode)ftcinode;
+ FT_Offset size = 0;
+ FT_Glyph glyph = inode->glyph;
+
+ FT_UNUSED( ftccache );
+
+
+ switch ( glyph->format )
+ {
+ case FT_GLYPH_FORMAT_BITMAP:
+ {
+ FT_BitmapGlyph bitg;
+
+
+ bitg = (FT_BitmapGlyph)glyph;
+ size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
+ sizeof ( *bitg );
+ }
+ break;
+
+ case FT_GLYPH_FORMAT_OUTLINE:
+ {
+ FT_OutlineGlyph outg;
+
+
+ outg = (FT_OutlineGlyph)glyph;
+ size = (FT_Offset)outg->outline.n_points *
+ ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
+ (FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +
+ sizeof ( *outg );
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ size += sizeof ( *inode );
+ return size;
+ }
+
+
+#if 0
+
+ FT_LOCAL_DEF( FT_Offset )
+ FTC_INode_Weight( FTC_INode inode )
+ {
+ return ftc_inode_weight( FTC_NODE( inode ), NULL );
+ }
+
+#endif /* 0 */
+
+
+/* END */
diff --git a/src/cache/ftcimage.h b/src/cache/ftcimage.h
new file mode 100644
index 0000000..b312eaa
--- /dev/null
+++ b/src/cache/ftcimage.h
@@ -0,0 +1,107 @@
+/***************************************************************************/
+/* */
+/* ftcimage.h */
+/* */
+/* FreeType Generic Image cache (specification) */
+/* */
+/* Copyright 2000-2015 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. */
+/* */
+/***************************************************************************/
+
+
+ /*
+ * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph
+ * image per cache node.
+ *
+ * FTC_ICache extends FTC_GCache. For an implementation example,
+ * see FTC_ImageCache in `src/cache/ftbasic.c'.
+ */
+
+
+ /*************************************************************************/
+ /* */
+ /* Each image cache really manages FT_Glyph objects. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCIMAGE_H__
+#define __FTCIMAGE_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+FT_BEGIN_HEADER
+
+
+ /* the FT_Glyph image node type - we store only 1 glyph per node */
+ typedef struct FTC_INodeRec_
+ {
+ FTC_GNodeRec gnode;
+ FT_Glyph glyph;
+
+ } FTC_INodeRec, *FTC_INode;
+
+#define FTC_INODE( x ) ( (FTC_INode)( x ) )
+#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
+#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
+
+ typedef FT_Error
+ (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
+ FT_UInt gindex,
+ FTC_Cache cache,
+ FT_Glyph *aglyph );
+
+ typedef struct FTC_IFamilyClassRec_
+ {
+ FTC_MruListClassRec clazz;
+ FTC_IFamily_LoadGlyphFunc family_load_glyph;
+
+ } FTC_IFamilyClassRec;
+
+ typedef const FTC_IFamilyClassRec* FTC_IFamilyClass;
+
+#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
+
+#define FTC_CACHE__IFAMILY_CLASS( x ) \
+ FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class )
+
+
+ /* can be used as a @FTC_Node_FreeFunc */
+ FT_LOCAL( void )
+ FTC_INode_Free( FTC_INode inode,
+ FTC_Cache cache );
+
+ /* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family'
+ * must be set correctly. This function will call the `family_load_glyph'
+ * method to load the FT_Glyph into the cache node.
+ */
+ FT_LOCAL( FT_Error )
+ FTC_INode_New( FTC_INode *pinode,
+ FTC_GQuery gquery,
+ FTC_Cache cache );
+
+#if 0
+ /* can be used as @FTC_Node_WeightFunc */
+ FT_LOCAL( FT_ULong )
+ FTC_INode_Weight( FTC_INode inode );
+#endif
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCIMAGE_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
new file mode 100644
index 0000000..658614c
--- /dev/null
+++ b/src/cache/ftcmanag.c
@@ -0,0 +1,703 @@
+/***************************************************************************/
+/* */
+/* ftcmanag.c */
+/* */
+/* FreeType Cache Manager (body). */
+/* */
+/* Copyright 2000-2015 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 <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_SIZES_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "cache system does not support PIC yet"
+#endif
+
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_cache
+
+
+ static FT_Error
+ ftc_scaler_lookup_size( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Face face;
+ FT_Size size = NULL;
+ FT_Error error;
+
+
+ error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
+ if ( error )
+ goto Exit;
+
+ error = FT_New_Size( face, &size );
+ if ( error )
+ goto Exit;
+
+ FT_Activate_Size( size );
+
+ if ( scaler->pixel )
+ error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
+ else
+ error = FT_Set_Char_Size( face,
+ (FT_F26Dot6)scaler->width,
+ (FT_F26Dot6)scaler->height,
+ scaler->x_res,
+ scaler->y_res );
+ if ( error )
+ {
+ FT_Done_Size( size );
+ size = NULL;
+ }
+
+ Exit:
+ *asize = size;
+ return error;
+ }
+
+
+ typedef struct FTC_SizeNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FT_Size size;
+ FTC_ScalerRec scaler;
+
+ } FTC_SizeNodeRec, *FTC_SizeNode;
+
+#define FTC_SIZE_NODE( x ) ( (FTC_SizeNode)( x ) )
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_size_node_done( FTC_MruNode ftcnode,
+ FT_Pointer data )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FT_Size size = node->size;
+ FT_UNUSED( data );
+
+
+ if ( size )
+ FT_Done_Size( size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_size_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Scaler scaler0 = &node->scaler;
+
+
+ if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
+ {
+ FT_Activate_Size( node->size );
+ return 1;
+ }
+ return 0;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_size_node_reset( FTC_MruNode ftcnode,
+ FT_Pointer ftcscaler,
+ FT_Pointer ftcmanager )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ FT_Done_Size( node->size );
+
+ node->scaler = scaler[0];
+
+ return ftc_scaler_lookup_size( manager, scaler, &node->size );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_size_list_class =
+ {
+ sizeof ( FTC_SizeNodeRec ),
+ ftc_size_node_compare,
+ ftc_size_node_init,
+ ftc_size_node_reset,
+ ftc_size_node_done
+ };
+
+
+ /* helper function used by ftc_face_node_done */
+ static FT_Bool
+ ftc_size_node_compare_faceid( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_SizeNode node = (FTC_SizeNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->scaler.face_id == face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !asize || !scaler )
+ return FT_THROW( Invalid_Argument );
+
+ *asize = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->sizes, scaler, &mrunode );
+#endif
+
+ if ( !error )
+ *asize = FTC_SIZE_NODE( mrunode )->size;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** FACE MRU IMPLEMENTATION *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef struct FTC_FaceNodeRec_
+ {
+ FTC_MruNodeRec node;
+ FTC_FaceID face_id;
+ FT_Face face;
+
+ } FTC_FaceNodeRec, *FTC_FaceNode;
+
+#define FTC_FACE_NODE( x ) ( ( FTC_FaceNode )( x ) )
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ftc_face_node_init( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+ FT_Error error;
+
+
+ node->face_id = face_id;
+
+ error = manager->request_face( face_id,
+ manager->library,
+ manager->request_data,
+ &node->face );
+ if ( !error )
+ {
+ /* destroy initial size object; it will be re-created later */
+ if ( node->face->size )
+ FT_Done_Size( node->face->size );
+ }
+
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ftc_face_node_done( FTC_MruNode ftcnode,
+ FT_Pointer ftcmanager )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_Manager manager = (FTC_Manager)ftcmanager;
+
+
+ /* we must begin by removing all scalers for the target face */
+ /* from the manager's list */
+ FTC_MruList_RemoveSelection( &manager->sizes,
+ ftc_size_node_compare_faceid,
+ node->face_id );
+
+ /* all right, we can discard the face now */
+ FT_Done_Face( node->face );
+ node->face = NULL;
+ node->face_id = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Bool )
+ ftc_face_node_compare( FTC_MruNode ftcnode,
+ FT_Pointer ftcface_id )
+ {
+ FTC_FaceNode node = (FTC_FaceNode)ftcnode;
+ FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
+
+
+ return FT_BOOL( node->face_id == face_id );
+ }
+
+
+ static
+ const FTC_MruListClassRec ftc_face_list_class =
+ {
+ sizeof ( FTC_FaceNodeRec),
+
+ ftc_face_node_compare,
+ ftc_face_node_init,
+ 0, /* FTC_MruNode_ResetFunc */
+ ftc_face_node_done
+ };
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface )
+ {
+ FT_Error error;
+ FTC_MruNode mrunode;
+
+
+ if ( !aface || !face_id )
+ return FT_THROW( Invalid_Argument );
+
+ *aface = NULL;
+
+ if ( !manager )
+ return FT_THROW( Invalid_Cache_Handle );
+
+ /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
+
+ FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
+ mrunode, error );
+
+#else
+ error = FTC_MruList_Lookup( &manager->faces, face_id, &mrunode );
+#endif
+
+ if ( !error )
+ *aface = FTC_FACE_NODE( mrunode )->face;
+
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER ROUTINES *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FTC_Manager manager = 0;
+
+
+ if ( !library )
+ return FT_THROW( Invalid_Library_Handle );
+
+ if ( !amanager || !requester )
+ return FT_THROW( Invalid_Argument );
+
+ memory = library->memory;
+
+ if ( FT_NEW( manager ) )
+ goto Exit;
+
+ if ( max_faces == 0 )
+ max_faces = FTC_MAX_FACES_DEFAULT;
+
+ if ( max_sizes == 0 )
+ max_sizes = FTC_MAX_SIZES_DEFAULT;
+
+ if ( max_bytes == 0 )
+ max_bytes = FTC_MAX_BYTES_DEFAULT;
+
+ manager->library = library;
+ manager->memory = memory;
+ manager->max_weight = max_bytes;
+
+ manager->request_face = requester;
+ manager->request_data = req_data;
+
+ FTC_MruList_Init( &manager->faces,
+ &ftc_face_list_class,
+ max_faces,
+ manager,
+ memory );
+
+ FTC_MruList_Init( &manager->sizes,
+ &ftc_size_list_class,
+ max_sizes,
+ manager,
+ memory );
+
+ *amanager = manager;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Done( FTC_Manager manager )
+ {
+ FT_Memory memory;
+ FT_UInt idx;
+
+
+ if ( !manager || !manager->library )
+ return;
+
+ memory = manager->memory;
+
+ /* now discard all caches */
+ for (idx = manager->num_caches; idx-- > 0; )
+ {
+ FTC_Cache cache = manager->caches[idx];
+
+
+ if ( cache )
+ {
+ cache->clazz.cache_done( cache );
+ FT_FREE( cache );
+ manager->caches[idx] = NULL;
+ }
+ }
+ manager->num_caches = 0;
+
+ /* discard faces and sizes */
+ FTC_MruList_Done( &manager->sizes );
+ FTC_MruList_Done( &manager->faces );
+
+ manager->library = NULL;
+ manager->memory = NULL;
+
+ FT_FREE( manager );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_Reset( FTC_Manager manager )
+ {
+ if ( !manager )
+ return;
+
+ FTC_MruList_Reset( &manager->sizes );
+ FTC_MruList_Reset( &manager->faces );
+
+ FTC_Manager_FlushN( manager, manager->num_nodes );
+ }
+
+
+#ifdef FT_DEBUG_ERROR
+
+ static void
+ FTC_Manager_Check( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ first = manager->nodes_list;
+
+ /* check node weights */
+ if ( first )
+ {
+ FT_Offset weight = 0;
+
+
+ node = first;
+
+ do
+ {
+ FTC_Cache cache = manager->caches[node->cache_index];
+
+
+ if ( (FT_UInt)node->cache_index >= manager->num_caches )
+ FT_TRACE0(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
+ node->cache_index ));
+ else
+ weight += cache->clazz.node_weight( node, cache );
+
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( weight != manager->cur_weight )
+ FT_TRACE0(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n",
+ manager->cur_weight, weight ));
+ }
+
+ /* check circular list */
+ if ( first )
+ {
+ FT_UFast count = 0;
+
+
+ node = first;
+ do
+ {
+ count++;
+ node = FTC_NODE__NEXT( node );
+
+ } while ( node != first );
+
+ if ( count != manager->num_nodes )
+ FT_TRACE0(( "FTC_Manager_Check:"
+ " invalid cache node count %d instead of %d\n",
+ manager->num_nodes, count ));
+ }
+ }
+
+#endif /* FT_DEBUG_ERROR */
+
+
+ /* `Compress' the manager's data, i.e., get rid of old cache nodes */
+ /* that are not referenced anymore in order to limit the total */
+ /* memory used by the cache. */
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( void )
+ FTC_Manager_Compress( FTC_Manager manager )
+ {
+ FTC_Node node, first;
+
+
+ if ( !manager )
+ return;
+
+ first = manager->nodes_list;
+
+#ifdef FT_DEBUG_ERROR
+ FTC_Manager_Check( manager );
+
+ FT_TRACE0(( "compressing, weight = %ld, max = %ld, nodes = %d\n",
+ manager->cur_weight, manager->max_weight,
+ manager->num_nodes ));
+#endif
+
+ if ( manager->cur_weight < manager->max_weight || first == NULL )
+ return;
+
+ /* go to last node -- it's a circular list */
+ node = FTC_NODE__PREV( first );
+ do
+ {
+ FTC_Node prev;
+
+
+ prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
+
+ if ( node->ref_count <= 0 )
+ ftc_node_destroy( node, manager );
+
+ node = prev;
+
+ } while ( node && manager->cur_weight > manager->max_weight );
+ }
+
+
+ /* documentation is in ftcmanag.h */
+
+ FT_LOCAL_DEF( FT_Error )
+ FTC_Manager_RegisterCache( FTC_Manager manager,
+ FTC_CacheClass clazz,
+ FTC_Cache *acache )
+ {
+ FT_Error error = FT_ERR( Invalid_Argument );
+ FTC_Cache cache = NULL;
+
+
+ if ( manager && clazz && acache )
+ {
+ FT_Memory memory = manager->memory;
+
+
+ if ( manager->num_caches >= FTC_MAX_CACHES )
+ {
+ error = FT_THROW( Too_Many_Caches );
+ FT_ERROR(( "FTC_Manager_RegisterCache:"
+ " too many registered caches\n" ));
+ goto Exit;
+ }
+
+ if ( !FT_ALLOC( cache, clazz->cache_size ) )
+ {
+ cache->manager = manager;
+ cache->memory = memory;
+ cache->clazz = clazz[0];
+ cache->org_class = clazz;
+
+ /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
+ /* IF IT IS NOT SET CORRECTLY */
+ cache->index = manager->num_caches;
+
+ error = clazz->cache_init( cache );
+ if ( error )
+ {
+ clazz->cache_done( cache );
+ FT_FREE( cache );
+ goto Exit;
+ }
+
+ manager->caches[manager->num_caches++] = cache;
+ }
+ }
+
+ Exit:
+ if ( acache )
+ *acache = cache;
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_UInt )
+ FTC_Manager_FlushN( FTC_Manager manager,
+ FT_UInt count )
+ {
+ FTC_Node first = manager->nodes_list;
+ FTC_Node node;
+ FT_UInt result;
+
+
+ /* try to remove `count' nodes from the list */
+ if ( first == NULL ) /* empty list! */
+ return 0;
+
+ /* go to last node - it's a circular list */
+ node = FTC_NODE__PREV(first);
+ for ( result = 0; result < count; )
+ {
+ FTC_Node prev = FTC_NODE__PREV( node );
+
+
+ /* don't touch locked nodes */
+ if ( node->ref_count <= 0 )
+ {
+ ftc_node_destroy( node, manager );
+ result++;
+ }
+
+ if ( node == first )
+ break;
+
+ node = prev;
+ }
+ return result;
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id )
+ {
+ FT_UInt nn;
+
+
+ if ( !manager || !face_id )
+ return;
+
+ /* this will remove all FTC_SizeNode that correspond to
+ * the face_id as well
+ */
+ FTC_MruList_RemoveSelection( &manager->faces,
+ ftc_face_node_compare,
+ face_id );
+
+ for ( nn = 0; nn < manager->num_caches; nn++ )
+ FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
+ }
+
+
+ /* documentation is in ftcache.h */
+
+ FT_EXPORT_DEF( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager )
+ {
+ if ( node &&
+ manager &&
+ (FT_UInt)node->cache_index < manager->num_caches )
+ node->ref_count--;
+ }
+
+
+/* END */
diff --git a/src/cache/ftcmanag.h b/src/cache/ftcmanag.h
index 0aec33c..c6787b7 100644
--- a/src/cache/ftcmanag.h
+++ b/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache Manager (specification). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006, 2010, 2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c
index dc8b4cc..10ce4f3 100644
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
/* */
/* FreeType MRU support (body). */
/* */
-/* Copyright 2003, 2004, 2006, 2009 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cache/ftcmru.h b/src/cache/ftcmru.h
new file mode 100644
index 0000000..c0c35f9
--- /dev/null
+++ b/src/cache/ftcmru.h
@@ -0,0 +1,246 @@
+/***************************************************************************/
+/* */
+/* ftcmru.h */
+/* */
+/* Simple MRU list-cache (specification). */
+/* */
+/* Copyright 2000-2015 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. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* An MRU is a list that cannot hold more than a certain number of */
+ /* elements (`max_elements'). All elements in the list are sorted in */
+ /* least-recently-used order, i.e., the `oldest' element is at the tail */
+ /* of the list. */
+ /* */
+ /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */
+ /* the list is searched for an element with the corresponding key. If */
+ /* it is found, the element is moved to the head of the list and is */
+ /* returned. */
+ /* */
+ /* If no corresponding element is found, the lookup routine will try to */
+ /* obtain a new element with the relevant key. If the list is already */
+ /* full, the oldest element from the list is discarded and replaced by a */
+ /* new one; a new element is added to the list otherwise. */
+ /* */
+ /* Note that it is possible to pre-allocate the element list nodes. */
+ /* This is handy if `max_elements' is sufficiently small, as it saves */
+ /* allocations/releases during the lookup process. */
+ /* */
+ /*************************************************************************/
+
+
+#ifndef __FTCMRU_H__
+#define __FTCMRU_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+#define xxFT_DEBUG_ERROR
+#define FTC_INLINE
+
+FT_BEGIN_HEADER
+
+ typedef struct FTC_MruNodeRec_* FTC_MruNode;
+
+ typedef struct FTC_MruNodeRec_
+ {
+ FTC_MruNode next;
+ FTC_MruNode prev;
+
+ } FTC_MruNodeRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruNode_Prepend( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Up( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruNode_Remove( FTC_MruNode *plist,
+ FTC_MruNode node );
+
+
+ typedef struct FTC_MruListRec_* FTC_MruList;
+
+ typedef struct FTC_MruListClassRec_ const * FTC_MruListClass;
+
+
+ typedef FT_Bool
+ (*FTC_MruNode_CompareFunc)( FTC_MruNode node,
+ FT_Pointer key );
+
+ typedef FT_Error
+ (*FTC_MruNode_InitFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef FT_Error
+ (*FTC_MruNode_ResetFunc)( FTC_MruNode node,
+ FT_Pointer key,
+ FT_Pointer data );
+
+ typedef void
+ (*FTC_MruNode_DoneFunc)( FTC_MruNode node,
+ FT_Pointer data );
+
+
+ typedef struct FTC_MruListClassRec_
+ {
+ FT_Offset node_size;
+ FTC_MruNode_CompareFunc node_compare;
+ FTC_MruNode_InitFunc node_init;
+ FTC_MruNode_ResetFunc node_reset;
+ FTC_MruNode_DoneFunc node_done;
+
+ } FTC_MruListClassRec;
+
+ typedef struct FTC_MruListRec_
+ {
+ FT_UInt num_nodes;
+ FT_UInt max_nodes;
+ FTC_MruNode nodes;
+ FT_Pointer data;
+ FTC_MruListClassRec clazz;
+ FT_Memory memory;
+
+ } FTC_MruListRec;
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Init( FTC_MruList list,
+ FTC_MruListClass clazz,
+ FT_UInt max_nodes,
+ FT_Pointer data,
+ FT_Memory memory );
+
+ FT_LOCAL( void )
+ FTC_MruList_Reset( FTC_MruList list );
+
+
+ FT_LOCAL( void )
+ FTC_MruList_Done( FTC_MruList list );
+
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_New( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *anode );
+
+ FT_LOCAL( void )
+ FTC_MruList_Remove( FTC_MruList list,
+ FTC_MruNode node );
+
+ FT_LOCAL( void )
+ FTC_MruList_RemoveSelection( FTC_MruList list,
+ FTC_MruNode_CompareFunc selection,
+ FT_Pointer key );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode* _pfirst = &(list)->nodes; \
+ FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
+ FTC_MruNode _first, _node; \
+ \
+ \
+ error = FT_Err_Ok; \
+ _first = *(_pfirst); \
+ _node = NULL; \
+ \
+ if ( _first ) \
+ { \
+ _node = _first; \
+ do \
+ { \
+ if ( _compare( _node, (key) ) ) \
+ { \
+ if ( _node != _first ) \
+ FTC_MruNode_Up( _pfirst, _node ); \
+ \
+ node = _node; \
+ goto _MruOk; \
+ } \
+ _node = _node->next; \
+ \
+ } while ( _node != _first) ; \
+ } \
+ \
+ error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \
+ _MruOk: \
+ ; \
+ FT_END_STMNT
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
+
+#else /* !FTC_INLINE */
+
+ FT_LOCAL( FTC_MruNode )
+ FTC_MruList_Find( FTC_MruList list,
+ FT_Pointer key );
+
+ FT_LOCAL( FT_Error )
+ FTC_MruList_Lookup( FTC_MruList list,
+ FT_Pointer key,
+ FTC_MruNode *pnode );
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+ error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
+
+#endif /* !FTC_INLINE */
+
+
+#define FTC_MRULIST_LOOP( list, node ) \
+ FT_BEGIN_STMNT \
+ FTC_MruNode _first = (list)->nodes; \
+ \
+ \
+ if ( _first ) \
+ { \
+ FTC_MruNode _node = _first; \
+ \
+ \
+ do \
+ { \
+ *(FTC_MruNode*)&(node) = _node;
+
+
+#define FTC_MRULIST_LOOP_END() \
+ _node = _node->next; \
+ \
+ } while ( _node != _first ); \
+ } \
+ FT_END_STMNT
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCMRU_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c
index 6df1c19..8141719 100644
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
/* */
/* FreeType sbits manager (body). */
/* */
-/* Copyright 2000-2006, 2009-2011, 2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,7 +52,7 @@
if ( pitch < 0 )
pitch = -pitch;
- size = (FT_ULong)( pitch * bitmap->rows );
+ size = (FT_ULong)pitch * bitmap->rows;
if ( !FT_ALLOC( sbit->buffer, size ) )
FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
@@ -142,12 +142,12 @@
goto BadGlyph;
}
- /* Check that our values fit into 8-bit containers! */
+ /* Check whether our values fit into 8-bit containers! */
/* If this is not the case, our bitmap is too large */
/* and we will leave it as `missing' with sbit.buffer = 0 */
-#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
-#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
+#define CHECK_CHAR( d ) ( temp = (FT_Char)d, (FT_Int) temp == (FT_Int) d )
+#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, (FT_UInt)temp == (FT_UInt)d )
/* horizontal advance in pixels */
xadvance = ( slot->advance.x + 32 ) >> 6;
@@ -181,7 +181,7 @@
/* now, compute size */
if ( asize )
- *asize = FT_ABS( sbit->pitch ) * sbit->height;
+ *asize = (FT_ULong)FT_ABS( sbit->pitch ) * sbit->height;
} /* glyph loading successful */
@@ -302,7 +302,7 @@
pitch = -pitch;
/* add the size of a given glyph image */
- size += pitch * sbit->height;
+ size += (FT_Offset)pitch * sbit->height;
}
}
diff --git a/src/cache/ftcsbits.h b/src/cache/ftcsbits.h
index df55dca..5a2fa1a 100644
--- a/src/cache/ftcsbits.h
+++ b/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
/* */
/* A small-bitmap cache (specification). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2006, 2011 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cf2arrst.c b/src/cff/cf2arrst.c
index c8d6f13..89f3e9f 100644
--- a/src/cff/cf2arrst.c
+++ b/src/cff/cf2arrst.c
@@ -101,10 +101,10 @@
FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
FT_Memory memory = arrstack->memory; /* for FT_REALLOC */
- FT_Long newSize = (FT_Long)( numElements * arrstack->sizeItem );
+ size_t newSize = numElements * arrstack->sizeItem;
- if ( numElements > LONG_MAX / arrstack->sizeItem )
+ if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
goto exit;
diff --git a/src/cff/cf2blues.c b/src/cff/cf2blues.c
index 5b34839..250f89e 100644
--- a/src/cff/cf2blues.c
+++ b/src/cff/cf2blues.c
@@ -4,7 +4,7 @@
/* */
/* Adobe's code for handling Blue Zones (body). */
/* */
-/* Copyright 2009-2013 Adobe Systems Incorporated. */
+/* Copyright 2009-2014 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
@@ -86,11 +86,13 @@
size_t i;
CF2_Fixed emBoxBottom, emBoxTop;
+#if 0
CF2_Int unitsPerEm = font->unitsPerEm;
if ( unitsPerEm == 0 )
unitsPerEm = 1000;
+#endif
FT_ZERO( blues );
blues->scale = font->innerTransform.d;
@@ -406,11 +408,10 @@
/* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
/* 10ppem Arial */
- blues->boost = FT_MulFix(
- cf2_floatToFixed( .6 ),
- ( cf2_intToFixed( 1 ) -
- FT_DivFix( blues->scale,
- blues->blueScale ) ) );
+ blues->boost = cf2_floatToFixed( .6 ) -
+ FT_MulDiv( cf2_floatToFixed ( .6 ),
+ blues->scale,
+ blues->blueScale );
if ( blues->boost > 0x7FFF )
{
/* boost must remain less than 0.5, or baseline could go negative */
diff --git a/src/cff/cf2fixed.h b/src/cff/cf2fixed.h
index ed1452a..d6d9faf 100644
--- a/src/cff/cf2fixed.h
+++ b/src/cff/cf2fixed.h
@@ -57,22 +57,22 @@
/* in C 89, left and right shift of negative numbers is */
/* implementation specific behaviour in the general case */
-#define cf2_intToFixed( i ) \
+#define cf2_intToFixed( i ) \
( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
-#define cf2_fixedToInt( x ) \
+#define cf2_fixedToInt( x ) \
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
-#define cf2_fixedRound( x ) \
- ( (CF2_Fixed)( ( (x) + 0x8000 ) & 0xFFFF0000L ) )
-#define cf2_floatToFixed( f ) \
+#define cf2_fixedRound( x ) \
+ ( (CF2_Fixed)( ( (FT_UInt32)(x) + 0x8000U ) & 0xFFFF0000UL ) )
+#define cf2_floatToFixed( f ) \
( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
-#define cf2_fixedAbs( x ) \
+#define cf2_fixedAbs( x ) \
( (x) < 0 ? -(x) : (x) )
-#define cf2_fixedFloor( x ) \
- ( (CF2_Fixed)( (x) & 0xFFFF0000L ) )
-#define cf2_fixedFraction( x ) \
+#define cf2_fixedFloor( x ) \
+ ( (CF2_Fixed)( (FT_UInt32)(x) & 0xFFFF0000UL ) )
+#define cf2_fixedFraction( x ) \
( (x) - cf2_fixedFloor( x ) )
-#define cf2_fracToFixed( x ) \
- ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \
+#define cf2_fracToFixed( x ) \
+ ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 ) \
: ( ( (x) + 0x2000 ) >> 14 ) )
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
index 8b2331d..83fd348 100644
--- a/src/cff/cf2font.c
+++ b/src/cff/cf2font.c
@@ -4,7 +4,7 @@
/* */
/* Adobe's code for font instances (body). */
/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
@@ -36,6 +36,9 @@
/***************************************************************************/
+#include <ft2build.h>
+#include FT_INTERNAL_CALC_H
+
#include "cf2ft.h"
#include "cf2glue.h"
@@ -51,11 +54,61 @@
CF2_Fixed stemWidth,
CF2_Fixed* darkenAmount,
CF2_Fixed boldenAmount,
- FT_Bool stemDarkened )
+ FT_Bool stemDarkened,
+ FT_Int* darkenParams )
{
+ /*
+ * Total darkening amount is computed in 1000 unit character space
+ * using the modified 5 part curve as Adobe's Avalon rasterizer.
+ * The darkening amount is smaller for thicker stems.
+ * It becomes zero when the stem is thicker than 2.333 pixels.
+ *
+ * By default, we use
+ *
+ * darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels,
+ * darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
+ * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
+ *
+ * and piecewise linear in-between:
+ *
+ *
+ * darkening
+ * ^
+ * |
+ * | (x1,y1)
+ * |--------+
+ * | \
+ * | \
+ * | \ (x3,y3)
+ * | +----------+
+ * | (x2,y2) \
+ * | \
+ * | \
+ * | +-----------------
+ * | (x4,y4)
+ * +---------------------------------------------> stem
+ * thickness
+ *
+ *
+ * This corresponds to the following values for the
+ * `darkening-parameters' property:
+ *
+ * (x1, y1) = (500, 400)
+ * (x2, y2) = (1000, 275)
+ * (x3, y3) = (1667, 275)
+ * (x4, y4) = (2333, 0)
+ *
+ */
+
/* Internal calculations are done in units per thousand for */
- /* convenience. */
+ /* convenience. The x axis is scaled stem width in */
+ /* thousandths of a pixel. That is, 1000 is 1 pixel. */
+ /* The y axis is darkening amount in thousandths of a pixel.*/
+ /* In the code, below, dividing by ppem and */
+ /* adjusting for emRatio converts darkenAmount to character */
+ /* space (font units). */
CF2_Fixed stemWidthPer1000, scaledStem;
+ FT_Int logBase2;
*darkenAmount = 0;
@@ -69,59 +122,107 @@
if ( stemDarkened )
{
+ FT_Int x1 = darkenParams[0];
+ FT_Int y1 = darkenParams[1];
+ FT_Int x2 = darkenParams[2];
+ FT_Int y2 = darkenParams[3];
+ FT_Int x3 = darkenParams[4];
+ FT_Int y3 = darkenParams[5];
+ FT_Int x4 = darkenParams[6];
+ FT_Int y4 = darkenParams[7];
+
+
/* convert from true character space to 1000 unit character space; */
/* add synthetic emboldening effect */
- /* we have to assure that the computation of `scaledStem' */
- /* and `stemWidthPer1000' don't overflow */
+ /* `stemWidthPer1000' will not overflow for a legitimate font */
stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
- if ( emRatio > CF2_FIXED_ONE &&
- stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
- {
- stemWidthPer1000 = 0; /* to pacify compiler */
- scaledStem = cf2_intToFixed( 2333 );
- }
+ /* `scaledStem' can easily overflow, so we must clamp its maximum */
+ /* value; the test doesn't need to be precise, but must be */
+ /* conservative. The clamp value (default 2333) where */
+ /* `darkenAmount' is zero is well below the overflow value of */
+ /* 32767. */
+ /* */
+ /* FT_MSB computes the integer part of the base 2 logarithm. The */
+ /* number of bits for the product is 1 or 2 more than the sum of */
+ /* logarithms; remembering that the 16 lowest bits of the fraction */
+ /* are dropped this is correct to within a factor of almost 4. */
+ /* For example, 0x80.0000 * 0x80.0000 = 0x4000.0000 is 23+23 and */
+ /* is flagged as possible overflow because 0xFF.FFFF * 0xFF.FFFF = */
+ /* 0xFFFF.FE00 is also 23+23. */
+
+ logBase2 = FT_MSB( (FT_UInt32)stemWidthPer1000 ) +
+ FT_MSB( (FT_UInt32)ppem );
+
+ if ( logBase2 >= 46 )
+ /* possible overflow */
+ scaledStem = cf2_intToFixed( x4 );
else
- {
scaledStem = FT_MulFix( stemWidthPer1000, ppem );
- if ( ppem > CF2_FIXED_ONE &&
- scaledStem <= stemWidthPer1000 )
- scaledStem = cf2_intToFixed( 2333 );
+ /* now apply the darkening parameters */
+
+ if ( scaledStem < cf2_intToFixed( x1 ) )
+ *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
+
+ else if ( scaledStem < cf2_intToFixed( x2 ) )
+ {
+ FT_Int xdelta = x2 - x1;
+ FT_Int ydelta = y2 - y1;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x1 ), ppem );
+
+
+ if ( !xdelta )
+ goto Try_x3;
+
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y1 ), ppem );
}
- /*
- * Total darkening amount is computed in 1000 unit character space
- * using the modified 5 part curve as Avalon rasterizer.
- * The darkening amount is smaller for thicker stems.
- * It becomes zero when the stem is thicker than 2.333 pixels.
- *
- * In Avalon rasterizer,
- *
- * darkenAmount = 0.5 pixels if scaledStem <= 0.5 pixels,
- * darkenAmount = 0.333 pixels if 1 <= scaledStem <= 1.667 pixels,
- * darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
- *
- * and piecewise linear in-between.
- *
- */
- if ( scaledStem < cf2_intToFixed( 500 ) )
- *darkenAmount = FT_DivFix( cf2_intToFixed( 400 ), ppem );
+ else if ( scaledStem < cf2_intToFixed( x3 ) )
+ {
+ Try_x3:
+ {
+ FT_Int xdelta = x3 - x2;
+ FT_Int ydelta = y3 - y2;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x2 ), ppem );
- else if ( scaledStem < cf2_intToFixed( 1000 ) )
- *darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
- FT_MulFix( stemWidthPer1000,
- cf2_floatToFixed( .25 ) );
- else if ( scaledStem < cf2_intToFixed( 1667 ) )
- *darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
+ if ( !xdelta )
+ goto Try_x4;
- else if ( scaledStem < cf2_intToFixed( 2333 ) )
- *darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
- FT_MulFix( stemWidthPer1000,
- cf2_floatToFixed( .413 ) );
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y2 ), ppem );
+ }
+ }
+
+ else if ( scaledStem < cf2_intToFixed( x4 ) )
+ {
+ Try_x4:
+ {
+ FT_Int xdelta = x4 - x3;
+ FT_Int ydelta = y4 - y3;
+ FT_Int x = stemWidthPer1000 -
+ FT_DivFix( cf2_intToFixed( x3 ), ppem );
+
+
+ if ( !xdelta )
+ goto Use_y4;
+
+ *darkenAmount = FT_MulDiv( x, ydelta, xdelta ) +
+ FT_DivFix( cf2_intToFixed( y3 ), ppem );
+ }
+ }
+
+ else
+ {
+ Use_y4:
+ *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
+ }
/* use half the amount on each side and convert back to true */
/* character space */
@@ -143,13 +244,14 @@
/* pointer to parsed font object */
CFF_Decoder* decoder = font->decoder;
- FT_Bool needExtraSetup;
+ FT_Bool needExtraSetup = FALSE;
/* character space units */
CF2_Fixed boldenX = font->syntheticEmboldeningAmountX;
CF2_Fixed boldenY = font->syntheticEmboldeningAmountY;
- CF2_Fixed ppem;
+ CFF_SubFont subFont;
+ CF2_Fixed ppem;
/* clear previous error */
@@ -157,7 +259,12 @@
/* if a CID fontDict has changed, we need to recompute some cached */
/* data */
- needExtraSetup = font->lastSubfont != cf2_getSubfont( decoder );
+ subFont = cf2_getSubfont( decoder );
+ if ( font->lastSubfont != subFont )
+ {
+ font->lastSubfont = subFont;
+ needExtraSetup = TRUE;
+ }
/* if ppem has changed, we need to recompute some cached data */
/* note: because of CID font matrix concatenation, ppem and transform */
@@ -170,7 +277,7 @@
}
/* copy hinted flag on each call */
- font->hinted = font->renderingFlags & CF2_FlagsHinted;
+ font->hinted = (FT_Bool)( font->renderingFlags & CF2_FlagsHinted );
/* determine if transform has changed; */
/* include Fontmatrix but ignore translation */
@@ -204,7 +311,8 @@
*/
if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
{
- font->stemDarkened = font->renderingFlags & CF2_FlagsDarkened;
+ font->stemDarkened =
+ (FT_Bool)( font->renderingFlags & CF2_FlagsDarkened );
/* blue zones depend on darkened flag */
needExtraSetup = TRUE;
@@ -266,7 +374,8 @@
font->stdVW,
&font->darkenX,
boldenX,
- FALSE );
+ FALSE,
+ font->darkenParams );
}
else
cf2_computeDarkening( emRatio,
@@ -274,7 +383,8 @@
font->stdVW,
&font->darkenX,
0,
- font->stemDarkened );
+ font->stemDarkened,
+ font->darkenParams );
#if 0
/* since hstem is measured in the y-direction, we use the `d' member */
@@ -301,7 +411,8 @@
font->stdHW,
&font->darkenY,
boldenY,
- font->stemDarkened );
+ font->stemDarkened,
+ font->darkenParams );
if ( font->darkenX != 0 || font->darkenY != 0 )
font->darkened = TRUE;
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
index f9dd1bb..86cf02f 100644
--- a/src/cff/cf2font.h
+++ b/src/cff/cf2font.h
@@ -48,7 +48,12 @@
#define CF2_OPERAND_STACK_SIZE 48
-#define CF2_MAX_SUBR 10 /* maximum subroutine nesting */
+#define CF2_MAX_SUBR 16 /* maximum subroutine nesting; */
+ /* only 10 are allowed but there exist */
+ /* fonts like `HiraKakuProN-W3.ttf' */
+ /* (Hiragino Kaku Gothic ProN W3; */
+ /* 8.2d6e1; 2014-12-19) that exceed */
+ /* this limit */
/* typedef is in `cf2glue.h' */
@@ -85,6 +90,8 @@
/* i.e. darkenX != 0 || darkenY != 0 */
FT_Bool stemDarkened;
+ FT_Int darkenParams[8]; /* 1000 unit character space */
+
/* variables that depend on both FontDict and Transform */
CF2_Fixed stdVW; /* in character space; depends on dict entry */
CF2_Fixed stdHW; /* in character space; depends on dict entry */
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index c09a024..55f3206 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Glue Component to Adobe's Interpreter (body). */
/* */
-/* Copyright 2013 Adobe Systems Incorporated. */
+/* Copyright 2013-2014 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
@@ -61,7 +61,9 @@
FT_ASSERT( unitsPerEm > 0 );
- FT_ASSERT( transform->a > 0 && transform->d > 0 );
+ if ( transform->a <= 0 || transform->d <= 0 )
+ return FT_THROW( Invalid_Size_Handle );
+
FT_ASSERT( transform->b == 0 && transform->c == 0 );
FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
@@ -140,6 +142,8 @@
cf2_builder_lineTo( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params )
{
+ FT_Error error;
+
/* downcast the object pointer */
CF2_Outline outline = (CF2_Outline)callbacks;
CFF_Builder* builder;
@@ -154,15 +158,27 @@
{
/* record the move before the line; also check points and set */
/* `path_begun' */
- cff_builder_start_point( builder,
- params->pt0.x,
- params->pt0.y );
+ error = cff_builder_start_point( builder,
+ params->pt0.x,
+ params->pt0.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
}
/* `cff_builder_add_point1' includes a check_points call for one point */
- cff_builder_add_point1( builder,
- params->pt1.x,
- params->pt1.y );
+ error = cff_builder_add_point1( builder,
+ params->pt1.x,
+ params->pt1.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
}
@@ -170,6 +186,8 @@
cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks,
const CF2_CallbackParams params )
{
+ FT_Error error;
+
/* downcast the object pointer */
CF2_Outline outline = (CF2_Outline)callbacks;
CFF_Builder* builder;
@@ -184,13 +202,25 @@
{
/* record the move before the line; also check points and set */
/* `path_begun' */
- cff_builder_start_point( builder,
- params->pt0.x,
- params->pt0.y );
+ error = cff_builder_start_point( builder,
+ params->pt0.x,
+ params->pt0.y );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
}
/* prepare room for 3 points: 2 off-curve, 1 on-curve */
- cff_check_points( builder, 3 );
+ error = cff_check_points( builder, 3 );
+ if ( error )
+ {
+ if ( !*callbacks->error )
+ *callbacks->error = error;
+ return;
+ }
cff_builder_add_point( builder,
params->pt1.x,
@@ -236,10 +266,8 @@
if ( *hinted )
{
- *x_scale = FT_DivFix( decoder->builder.glyph->x_scale,
- cf2_intToFixed( 64 ) );
- *y_scale = FT_DivFix( decoder->builder.glyph->y_scale,
- cf2_intToFixed( 64 ) );
+ *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64;
+ *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64;
}
else
{
@@ -344,13 +372,25 @@
if ( scaled && !driver->no_stem_darkening )
font->renderingFlags |= CF2_FlagsDarkened;
+ font->darkenParams[0] = driver->darken_params[0];
+ font->darkenParams[1] = driver->darken_params[1];
+ font->darkenParams[2] = driver->darken_params[2];
+ font->darkenParams[3] = driver->darken_params[3];
+ font->darkenParams[4] = driver->darken_params[4];
+ font->darkenParams[5] = driver->darken_params[5];
+ font->darkenParams[6] = driver->darken_params[6];
+ font->darkenParams[7] = driver->darken_params[7];
+
/* now get an outline for this glyph; */
/* also get units per em to validate scale */
font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
- error2 = cf2_checkTransform( &transform, font->unitsPerEm );
- if ( error2 )
- return error2;
+ if ( scaled )
+ {
+ error2 = cf2_checkTransform( &transform, font->unitsPerEm );
+ if ( error2 )
+ return error2;
+ }
error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
if ( error2 )
@@ -380,8 +420,16 @@
FT_ASSERT( decoder &&
decoder->builder.face &&
decoder->builder.face->root.size );
- FT_ASSERT( decoder->builder.face->root.size->metrics.y_ppem );
+ /*
+ * Note that `y_ppem' can be zero if there wasn't a call to
+ * `FT_Set_Char_Size' or something similar. However, this isn't a
+ * problem since we come to this place in the code only if
+ * FT_LOAD_NO_SCALE is set (the other case gets caught by
+ * `cf2_checkTransform'). The ppem value is needed to compute the stem
+ * darkening, which is disabled for getting the unscaled outline.
+ *
+ */
return cf2_intToFixed(
decoder->builder.face->root.size->metrics.y_ppem );
}
@@ -496,17 +544,22 @@
/* return 0 on success */
FT_LOCAL_DEF( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
- FT_ASSERT( decoder && decoder->globals );
+ CF2_UInt idx;
+
+
+ FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += decoder->globals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->globals_bias );
if ( idx >= decoder->num_globals )
return TRUE; /* error */
+ FT_ASSERT( decoder->globals );
+
buf->start =
buf->ptr = decoder->globals[idx];
buf->end = decoder->globals[idx + 1];
@@ -519,7 +572,7 @@
/* used for seac component */
FT_LOCAL_DEF( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
- CF2_UInt code,
+ CF2_Int code,
CF2_Buffer buf )
{
CF2_Int gid;
@@ -532,12 +585,21 @@
FT_ZERO( buf );
- gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
- if ( gid < 0 )
- return FT_THROW( Invalid_Glyph_Format );
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+ /* Incremental fonts don't necessarily have valid charsets. */
+ /* They use the character code, not the glyph index, in this case. */
+ if ( decoder->builder.face->root.internal->incremental_interface )
+ gid = code;
+ else
+#endif /* FT_CONFIG_OPTION_INCREMENTAL */
+ {
+ gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
+ if ( gid < 0 )
+ return FT_THROW( Invalid_Glyph_Format );
+ }
error = cff_get_glyph_data( decoder->builder.face,
- gid,
+ (CF2_UInt)gid,
&charstring,
&len );
/* TODO: for now, just pass the FreeType error through */
@@ -569,17 +631,22 @@
FT_LOCAL_DEF( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
- FT_ASSERT( decoder && decoder->locals );
+ CF2_UInt idx;
+
+
+ FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += decoder->locals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->locals_bias );
if ( idx >= decoder->num_locals )
return TRUE; /* error */
+ FT_ASSERT( decoder->locals );
+
buf->start =
buf->ptr = decoder->locals[idx];
buf->end = decoder->locals[idx + 1];
diff --git a/src/cff/cf2ft.h b/src/cff/cf2ft.h
index 731da3c..9810511 100644
--- a/src/cff/cf2ft.h
+++ b/src/cff/cf2ft.h
@@ -99,18 +99,18 @@
FT_LOCAL( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
- CF2_UInt code,
+ CF2_Int code,
CF2_Buffer buf );
FT_LOCAL( void )
cf2_freeSeacComponent( CFF_Decoder* decoder,
CF2_Buffer buf );
FT_LOCAL( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( CF2_Fixed )
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
index 1666e4f..bbbe8e3 100644
--- a/src/cff/cf2hints.c
+++ b/src/cff/cf2hints.c
@@ -4,7 +4,7 @@
/* */
/* Adobe's code for handling CFF hints (body). */
/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
@@ -217,52 +217,52 @@
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isValid( const CF2_Hint hint )
{
- return hint->flags != 0;
+ return (FT_Bool)( hint->flags != 0 );
}
static FT_Bool
cf2_hint_isPair( const CF2_Hint hint )
{
- return ( hint->flags &
- ( CF2_PairBottom | CF2_PairTop ) ) != 0;
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
}
static FT_Bool
cf2_hint_isPairTop( const CF2_Hint hint )
{
- return ( hint->flags & CF2_PairTop ) != 0;
+ return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
}
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isTop( const CF2_Hint hint )
{
- return ( hint->flags &
- ( CF2_PairTop | CF2_GhostTop ) ) != 0;
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairTop | CF2_GhostTop ) ) != 0 );
}
FT_LOCAL_DEF( FT_Bool )
cf2_hint_isBottom( const CF2_Hint hint )
{
- return ( hint->flags &
- ( CF2_PairBottom | CF2_GhostBottom ) ) != 0;
+ return (FT_Bool)( ( hint->flags &
+ ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
}
static FT_Bool
cf2_hint_isLocked( const CF2_Hint hint )
{
- return ( hint->flags & CF2_Locked ) != 0;
+ return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
}
static FT_Bool
cf2_hint_isSynthetic( const CF2_Hint hint )
{
- return ( hint->flags & CF2_Synthetic ) != 0;
+ return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
}
@@ -304,9 +304,6 @@
cf2_hintmap_map( CF2_HintMap hintmap,
CF2_Fixed csCoord )
{
- FT_ASSERT( hintmap->isValid ); /* must call Build before Map */
- FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
-
if ( hintmap->count == 0 || ! hintmap->hinted )
{
/* there are no hints; use uniform scale and zero offset */
@@ -317,6 +314,7 @@
/* start linear search from last hit */
CF2_UInt i = hintmap->lastIndex;
+ FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
/* search up */
while ( i < hintmap->count - 1 &&
@@ -462,7 +460,8 @@
hintmap->edge[i].dsCoord + moveDown - downMinCounter )
{
move = moveDown;
- saveEdge = moveUp < -moveDown; /* true if non-optimum move */
+ /* true if non-optimum move */
+ saveEdge = (FT_Bool)( moveUp < -moveDown );
}
else
{
@@ -588,29 +587,39 @@
}
/* paired edges must be in proper order */
- FT_ASSERT( !isPair ||
- topHintEdge->csCoord >= bottomHintEdge->csCoord );
+ if ( isPair &&
+ topHintEdge->csCoord < bottomHintEdge->csCoord )
+ return;
/* linear search to find index value of insertion point */
indexInsert = 0;
for ( ; indexInsert < hintmap->count; indexInsert++ )
{
- if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord )
+ if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord )
break;
}
/*
- * Discard any hints that overlap in character space. Most often,
- * this is while building the initial map, but in theory, it can also
- * occur because of darkening.
+ * Discard any hints that overlap in character space. Most often, this
+ * is while building the initial map, where captured hints from all
+ * zones are combined. Define overlap to include hints that `touch'
+ * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that
+ * touch. Some fonts have non-ideographic glyphs that overlap our
+ * synthetic hints.
+ *
+ * Overlap also occurs when darkening stem hints that are close.
*
*/
if ( indexInsert < hintmap->count )
{
- /* we are inserting before an existing edge: */
+ /* we are inserting before an existing edge: */
+ /* verify that an existing edge is not the same */
+ if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
+ return; /* ignore overlapping stem hint */
+
/* verify that a new pair does not straddle the next edge */
- if ( isPair &&
- hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord )
+ if ( isPair &&
+ hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
return; /* ignore overlapping stem hint */
/* verify that we are not inserting between paired edges */
@@ -644,8 +653,27 @@
firstHintEdge->csCoord );
}
- /* discard any hints that overlap in device space; this can occur */
- /* because locked hints have been moved to align with blue zones */
+ /*
+ * Discard any hints that overlap in device space; this can occur
+ * because locked hints have been moved to align with blue zones.
+ *
+ * TODO: Although we might correct this later during adjustment, we
+ * don't currently have a way to delete a conflicting hint once it has
+ * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened,
+ * initial hint map for second path, glyph 945 (the perispomeni (tilde)
+ * in U+1F6E, Greek omega with psili and perispomeni). Darkening is
+ * 25. Pair 667,747 initially conflicts in design space with top edge
+ * 660. This is because 667 maps to 7.87, and the top edge was
+ * captured by a zone at 8.0. The pair is later successfully inserted
+ * in a zone without the top edge. In this zone it is adjusted to 8.0,
+ * and no longer conflicts with the top edge in design space. This
+ * means it can be included in yet a later zone which does have the top
+ * edge hint. This produces a small mismatch between the first and
+ * last points of this path, even though the hint masks are the same.
+ * The density map difference is tiny (1/256).
+ *
+ */
+
if ( indexInsert > 0 )
{
/* we are inserting after an existing edge */
@@ -670,10 +698,10 @@
/* make room to insert */
{
- CF2_Int iSrc = hintmap->count - 1;
- CF2_Int iDst = isPair ? hintmap->count + 1 : hintmap->count;
+ CF2_UInt iSrc = hintmap->count - 1;
+ CF2_UInt iDst = isPair ? hintmap->count + 1 : hintmap->count;
- CF2_Int count = hintmap->count - indexInsert;
+ CF2_UInt count = hintmap->count - indexInsert;
if ( iDst >= CF2_MAX_HINT_EDGES )
@@ -752,6 +780,8 @@
cf2_hintmask_setAll( hintMask,
cf2_arrstack_size( hStemHintArray ) +
cf2_arrstack_size( vStemHintArray ) );
+ if ( !cf2_hintmask_isValid( hintMask ) )
+ return; /* too many stem hints */
}
/* begin by clearing the map */
@@ -763,9 +793,12 @@
maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
/* use the hStem hints only, which are first in the mask */
- /* TODO: compare this to cffhintmaskGetBitCount */
bitCount = cf2_arrstack_size( hStemHintArray );
+ /* Defense-in-depth. Should never return here. */
+ if ( bitCount > hintMask->bitCount )
+ return;
+
/* synthetic embox hints get highest priority */
if ( font->blues.doEmBoxHints )
{
@@ -1034,6 +1067,7 @@
glyphpath->moveIsPending = TRUE;
glyphpath->pathIsOpen = FALSE;
+ glyphpath->pathIsClosing = FALSE;
glyphpath->elemIsQueued = FALSE;
}
@@ -1174,12 +1208,16 @@
/*
* Push the cached element (glyphpath->prevElem*) to the outline
* consumer. When a darkening offset is used, the end point of the
- * cached element may be adjusted to an intersection point or it may be
- * connected by a line to the current element. This calculation must
- * use a HintMap that was valid at the time the element was saved. For
- * the first point in a subpath, that is a saved HintMap. For most
- * elements, it just means the caller has delayed building a HintMap
- * from the current HintMask.
+ * cached element may be adjusted to an intersection point or we may
+ * synthesize a connecting line to the current element. If we are
+ * closing a subpath, we may also generate a connecting line to the start
+ * point.
+ *
+ * This is where Character Space (CS) is converted to Device Space (DS)
+ * using a hint map. This calculation must use a HintMap that was valid
+ * at the time the element was saved. For the first point in a subpath,
+ * that is a saved HintMap. For most elements, it just means the caller
+ * has delayed building a HintMap from the current HintMask.
*
* Transform each point with outerTransform and call the outline
* callbacks. This is a general 3x3 transform:
@@ -1249,16 +1287,32 @@
params.op = CF2_PathOpLineTo;
/* note: pt2 and pt3 are unused */
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- ¶ms.pt1,
- glyphpath->prevElemP1.x,
- glyphpath->prevElemP1.y );
- glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms );
+ if ( close )
+ {
+ /* use first hint map if closing */
+ cf2_glyphpath_hintPoint( glyphpath,
+ &glyphpath->firstHintMap,
+ ¶ms.pt1,
+ glyphpath->prevElemP1.x,
+ glyphpath->prevElemP1.y );
+ }
+ else
+ {
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ ¶ms.pt1,
+ glyphpath->prevElemP1.x,
+ glyphpath->prevElemP1.y );
+ }
- glyphpath->currentDS = params.pt1;
+ /* output only non-zero length lines */
+ if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
+ {
+ glyphpath->callbacks->lineTo( glyphpath->callbacks, ¶ms );
+ glyphpath->currentDS = params.pt1;
+ }
break;
case CF2_PathOpCubeTo:
@@ -1295,11 +1349,24 @@
/* note: at the end of a subpath, we might do both, so use `nextP0' */
/* before we change it, below */
- cf2_glyphpath_hintPoint( glyphpath,
- hintmap,
- ¶ms.pt1,
- nextP0->x,
- nextP0->y );
+ if ( close )
+ {
+ /* if we are closing the subpath, then nextP0 is in the first */
+ /* hint zone */
+ cf2_glyphpath_hintPoint( glyphpath,
+ &glyphpath->firstHintMap,
+ ¶ms.pt1,
+ nextP0->x,
+ nextP0->y );
+ }
+ else
+ {
+ cf2_glyphpath_hintPoint( glyphpath,
+ hintmap,
+ ¶ms.pt1,
+ nextP0->x,
+ nextP0->y );
+ }
if ( params.pt1.x != glyphpath->currentDS.x ||
params.pt1.y != glyphpath->currentDS.y )
@@ -1495,7 +1562,7 @@
{
/* -y */
*x = -glyphpath->xOffset;
- *y = glyphpath->xOffset;
+ *y = glyphpath->yOffset;
}
else
{
@@ -1510,6 +1577,16 @@
}
+ /*
+ * The functions cf2_glyphpath_{moveTo,lineTo,curveTo,closeOpenPath} are
+ * called by the interpreter with Character Space (CS) coordinates. Each
+ * path element is placed into a queue of length one to await the
+ * calculation of the following element. At that time, the darkening
+ * offset of the following element is known and joins can be computed,
+ * including possible modification of this element, before mapping to
+ * Device Space (DS) and passing it on to the outline consumer.
+ *
+ */
FT_LOCAL_DEF( void )
cf2_glyphpath_moveTo( CF2_GlyphPath glyphpath,
CF2_Fixed x,
@@ -1547,10 +1624,46 @@
{
CF2_Fixed xOffset, yOffset;
FT_Vector P0, P1;
+ FT_Bool newHintMap;
+ /*
+ * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
+ * In case this is a synthesized closing line, any new hints should be
+ * delayed until this path is closed (`cf2_hintmask_isNew' will be
+ * called again before the next line or curve).
+ */
- /* can't compute offset of zero length line, so ignore them */
- if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y )
+ /* true if new hint map not on close */
+ newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
+ !glyphpath->pathIsClosing;
+
+ /*
+ * Zero-length lines may occur in the charstring. Because we cannot
+ * compute darkening offsets or intersections from zero-length lines,
+ * it is best to remove them and avoid artifacts. However, zero-length
+ * lines in CS at the start of a new hint map can generate non-zero
+ * lines in DS due to hint substitution. We detect a change in hint
+ * map here and pass those zero-length lines along.
+ */
+
+ /*
+ * Note: Find explicitly closed paths here with a conditional
+ * breakpoint using
+ *
+ * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
+ *
+ */
+
+ if ( glyphpath->currentCS.x == x &&
+ glyphpath->currentCS.y == y &&
+ !newHintMap )
+ /*
+ * Ignore zero-length lines in CS where the hint map is the same
+ * because the line in DS will also be zero length.
+ *
+ * Ignore zero-length lines when we synthesize a closing line because
+ * the close will be handled in cf2_glyphPath_pushPrevElem.
+ */
return;
cf2_glyphpath_computeOffset( glyphpath,
@@ -1580,7 +1693,8 @@
if ( glyphpath->elemIsQueued )
{
- FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+ FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+ glyphpath->hintMap.count == 0 );
cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap,
@@ -1596,7 +1710,7 @@
glyphpath->prevElemP1 = P1;
/* update current map */
- if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
+ if ( newHintMap )
cf2_hintmap_build( &glyphpath->hintMap,
glyphpath->hStemHintArray,
glyphpath->vStemHintArray,
@@ -1666,7 +1780,8 @@
if ( glyphpath->elemIsQueued )
{
- FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+ FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+ glyphpath->hintMap.count == 0 );
cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap,
@@ -1702,29 +1817,29 @@
{
if ( glyphpath->pathIsOpen )
{
- FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) );
+ /*
+ * A closing line in Character Space line is always generated below
+ * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns
+ * out to be zero length in Device Space.
+ */
+ glyphpath->pathIsClosing = TRUE;
- /* since we need to apply an offset to the implicit lineto, we make */
- /* it explicit here */
cf2_glyphpath_lineTo( glyphpath,
glyphpath->start.x,
glyphpath->start.y );
- /* Draw previous element (the explicit LineTo we just created, */
- /* above) and connect it to the start point, but with the offset we */
- /* saved from the first element. */
- /* Use the saved HintMap, too. */
- FT_ASSERT( glyphpath->elemIsQueued );
-
- cf2_glyphpath_pushPrevElem( glyphpath,
- &glyphpath->firstHintMap,
- &glyphpath->offsetStart0,
- glyphpath->offsetStart1,
- TRUE );
+ /* empty the final element from the queue and close the path */
+ if ( glyphpath->elemIsQueued )
+ cf2_glyphpath_pushPrevElem( glyphpath,
+ &glyphpath->hintMap,
+ &glyphpath->offsetStart0,
+ glyphpath->offsetStart1,
+ TRUE );
/* reset state machine */
glyphpath->moveIsPending = TRUE;
glyphpath->pathIsOpen = FALSE;
+ glyphpath->pathIsClosing = FALSE;
glyphpath->elemIsQueued = FALSE;
}
}
diff --git a/src/cff/cf2hints.h b/src/cff/cf2hints.h
index c4fa922..f25d91b 100644
--- a/src/cff/cf2hints.h
+++ b/src/cff/cf2hints.h
@@ -204,6 +204,7 @@
#endif
FT_Bool pathIsOpen; /* true after MoveTo */
+ FT_Bool pathIsClosing; /* true when synthesizing closepath line */
FT_Bool darken; /* true if stem darkening */
FT_Bool moveIsPending; /* true between MoveTo and offset MoveTo */
@@ -229,7 +230,8 @@
FT_Vector currentCS;
/* current point, device space */
FT_Vector currentDS;
- FT_Vector start; /* start point of subpath */
+ /* start point of subpath, character space */
+ FT_Vector start;
/* the following members constitute the `queue' of one element */
FT_Bool elemIsQueued;
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
index 5b73e60..1910f1b 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -4,7 +4,7 @@
/* */
/* Adobe's CFF Interpreter (body). */
/* */
-/* Copyright 2007-2013 Adobe Systems Incorporated. */
+/* Copyright 2007-2014 Adobe Systems Incorporated. */
/* */
/* This software, and all works of authorship, whether in source or */
/* object code form as indicated by the copyright notice(s) included */
@@ -43,6 +43,7 @@
#include "cf2font.h"
#include "cf2stack.h"
#include "cf2hints.h"
+#include "cf2intrp.h"
#include "cf2error.h"
@@ -183,7 +184,7 @@
return;
FT_ASSERT( hintmask->byteCount > 0 );
- FT_ASSERT( hintmask->byteCount <
+ FT_ASSERT( hintmask->byteCount <=
sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
/* set mask to all ones */
@@ -287,7 +288,7 @@
{
CF2_UInt i;
CF2_UInt count = cf2_stack_count( opStack );
- FT_Bool hasWidthArg = count & 1;
+ FT_Bool hasWidthArg = (FT_Bool)( count & 1 );
/* variable accumulates delta values from operand stack */
CF2_Fixed position = hintOffset;
@@ -357,8 +358,8 @@
if ( doConditionalLastRead )
{
- FT_Bool lastIsX = cf2_fixedAbs( vals[10] - *curX ) >
- cf2_fixedAbs( vals[11] - *curY );
+ FT_Bool lastIsX = (FT_Bool)( cf2_fixedAbs( vals[10] - *curX ) >
+ cf2_fixedAbs( vals[11] - *curY ) );
CF2_Fixed lastVal = cf2_stack_getReal( opStack, index );
@@ -593,8 +594,11 @@
/* never add hints after the mask is computed */
if ( cf2_hintmask_isValid( &hintMask ) )
+ {
FT_TRACE4(( "cf2_interpT2CharString:"
" invalid horizontal hint mask\n" ));
+ break;
+ }
cf2_doStems( font,
opStack,
@@ -614,8 +618,11 @@
/* never add hints after the mask is computed */
if ( cf2_hintmask_isValid( &hintMask ) )
+ {
FT_TRACE4(( "cf2_interpT2CharString:"
" invalid vertical hint mask\n" ));
+ break;
+ }
cf2_doStems( font,
opStack,
@@ -739,7 +746,7 @@
case cf2_cmdCALLGSUBR:
case cf2_cmdCALLSUBR:
{
- CF2_UInt subrIndex;
+ CF2_Int subrNum;
FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
@@ -754,19 +761,22 @@
/* push our current CFF charstring region on subrStack */
charstring = (CF2_Buffer)
- cf2_arrstack_getPointer( &subrStack,
- charstringIndex + 1 );
+ cf2_arrstack_getPointer(
+ &subrStack,
+ (size_t)charstringIndex + 1 );
/* set up the new CFF region and pointer */
- subrIndex = cf2_stack_popInt( opStack );
+ subrNum = cf2_stack_popInt( opStack );
switch ( op1 )
{
case cf2_cmdCALLGSUBR:
- FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
+ FT_TRACE4(( " (idx %d, entering level %d)\n",
+ subrNum + decoder->globals_bias,
+ charstringIndex + 1 ));
if ( cf2_initGlobalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -776,10 +786,12 @@
default:
/* cf2_cmdCALLSUBR */
- FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
+ FT_TRACE4(( " (idx %d, entering level %d)\n",
+ subrNum + decoder->locals_bias,
+ charstringIndex + 1 ));
if ( cf2_initLocalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -792,7 +804,7 @@
continue; /* do not clear the stack */
case cf2_cmdRETURN:
- FT_TRACE4(( " return\n" ));
+ FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
if ( charstringIndex < 1 )
{
@@ -803,8 +815,9 @@
/* restore position in previous charstring */
charstring = (CF2_Buffer)
- cf2_arrstack_getPointer( &subrStack,
- --charstringIndex );
+ cf2_arrstack_getPointer(
+ &subrStack,
+ (CF2_UInt)--charstringIndex );
continue; /* do not clear the stack */
case cf2_cmdESC:
@@ -1082,8 +1095,8 @@
/* must be either 4 or 5 -- */
/* this is a (deprecated) implied `seac' operator */
- CF2_UInt achar;
- CF2_UInt bchar;
+ CF2_Int achar;
+ CF2_Int bchar;
CF2_BufferRec component;
CF2_Fixed dummyWidth; /* ignore component width */
FT_Error error2;
@@ -1141,15 +1154,16 @@
/* `cf2_hintmask_read' (which also traces the mask bytes) */
FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
- /* if there are arguments on the stack, there this is an */
- /* implied cf2_cmdVSTEMHM */
- if ( cf2_stack_count( opStack ) != 0 )
+ /* never add hints after the mask is computed */
+ if ( cf2_stack_count( opStack ) > 1 &&
+ cf2_hintmask_isValid( &hintMask ) )
{
- /* never add hints after the mask is computed */
- if ( cf2_hintmask_isValid( &hintMask ) )
- FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+ FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+ break;
}
+ /* if there are arguments on the stack, there this is an */
+ /* implied cf2_cmdVSTEMHM */
cf2_doStems( font,
opStack,
&vStemHintArray,
@@ -1284,10 +1298,16 @@
case cf2_cmdVVCURVETO:
{
- CF2_UInt count = cf2_stack_count( opStack );
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
CF2_UInt index = 0;
+ /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ index += count1 - count;
+
FT_TRACE4(( " vvcurveto\n" ));
while ( index < count )
@@ -1323,10 +1343,16 @@
case cf2_cmdHHCURVETO:
{
- CF2_UInt count = cf2_stack_count( opStack );
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
CF2_UInt index = 0;
+ /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
+ /* we enforce it by clearing the second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ index += count1 - count;
+
FT_TRACE4(( " hhcurveto\n" ));
while ( index < count )
@@ -1363,12 +1389,19 @@
case cf2_cmdVHCURVETO:
case cf2_cmdHVCURVETO:
{
- CF2_UInt count = cf2_stack_count( opStack );
+ CF2_UInt count, count1 = cf2_stack_count( opStack );
CF2_UInt index = 0;
FT_Bool alternate = op1 == cf2_cmdHVCURVETO;
+ /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
+ /* 8n+4, or 8n+5, we enforce it by clearing the */
+ /* second bit */
+ /* (and sorting the stack indexing to suit) */
+ count = count1 & ~2U;
+ index += count1 - count;
+
FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
while ( index < count )
diff --git a/src/cff/cf2read.c b/src/cff/cf2read.c
index cb671ec..2b429e3 100644
--- a/src/cff/cf2read.c
+++ b/src/cff/cf2read.c
@@ -105,7 +105,7 @@
FT_LOCAL_DEF( FT_Bool )
cf2_buf_isEnd( CF2_Buffer buf )
{
- return buf->ptr >= buf->end;
+ return (FT_Bool)( buf->ptr >= buf->end );
}
diff --git a/src/cff/cff.c b/src/cff/cff.c
index c3840b5..bb2cfb5 100644
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -4,7 +4,7 @@
/* */
/* FreeType OpenType driver component (body only). */
/* */
-/* Copyright 1996-2001, 2002, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index f6e03c6..e7538e9 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
-/* Copyright 2002-2007, 2010, 2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -33,12 +33,15 @@
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
- cff_cmap_encoding_init( CFF_CMapStd cmap )
+ cff_cmap_encoding_init( CFF_CMapStd cmap,
+ FT_Pointer pointer )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Encoding encoding = &cff->encoding;
+ FT_UNUSED( pointer );
+
cmap->gids = encoding->codes;
@@ -135,7 +138,8 @@
FT_CALLBACK_DEF( FT_Error )
- cff_cmap_unicode_init( PS_Unicodes unicodes )
+ cff_cmap_unicode_init( PS_Unicodes unicodes,
+ FT_Pointer pointer )
{
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
@@ -143,6 +147,8 @@
CFF_Charset charset = &cff->charset;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
+ FT_UNUSED( pointer );
+
/* can't build Unicode map for CID-keyed font */
/* because we don't know glyph names. */
diff --git a/src/cff/cffcmap.h b/src/cff/cffcmap.h
index 3f7f67b..6eaed63 100644
--- a/src/cff/cffcmap.h
+++ b/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
-/* Copyright 2002, 2003, 2006 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index c8ca96b..9a06b7c 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
/* */
/* OpenType font driver implementation (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -35,7 +35,7 @@
#include "cfferrs.h"
#include "cffpic.h"
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
#include FT_SERVICE_GLYPH_DICT_H
#include FT_SERVICE_PROPERTIES_H
#include FT_CFF_DRIVER_H
@@ -64,11 +64,6 @@
/*************************************************************************/
-#undef PAIR_TAG
-#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
- (FT_ULong)right )
-
-
/*************************************************************************/
/* */
/* <Function> */
@@ -121,9 +116,6 @@
}
-#undef PAIR_TAG
-
-
/*************************************************************************/
/* */
/* <Function> */
@@ -164,6 +156,8 @@
if ( !slot )
return FT_THROW( Invalid_Slot_Handle );
+ FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
+
/* check whether we want a scaled outline or bitmap */
if ( !size )
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
@@ -201,6 +195,68 @@
FT_GlyphSlot slot = face->glyph;
+ if ( FT_IS_SFNT( face ) )
+ {
+ /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
+ /* it is no longer necessary that those values are identical to */
+ /* the values in the `CFF' table */
+
+ TT_Face ttface = (TT_Face)face;
+ FT_Short dummy;
+
+
+ if ( flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ /* check whether we have data from the `vmtx' table at all; */
+ /* otherwise we extract the info from the CFF glyphstrings */
+ /* (instead of synthesizing a global value using the `OS/2' */
+ /* table) */
+ if ( !ttface->vertical_info )
+ goto Missing_Table;
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_UShort ah;
+
+
+ ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+ 1,
+ start + nn,
+ &dummy,
+ &ah );
+
+ FT_TRACE5(( " idx %d: advance height %d font units\n",
+ start + nn, ah ));
+ advances[nn] = ah;
+ }
+ }
+ else
+ {
+ /* check whether we have data from the `hmtx' table at all */
+ if ( !ttface->horizontal.number_Of_HMetrics )
+ goto Missing_Table;
+
+ for ( nn = 0; nn < count; nn++ )
+ {
+ FT_UShort aw;
+
+
+ ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
+ 0,
+ start + nn,
+ &dummy,
+ &aw );
+
+ FT_TRACE5(( " idx %d: advance width %d font units\n",
+ start + nn, aw ));
+ advances[nn] = aw;
+ }
+ }
+
+ return error;
+ }
+
+ Missing_Table:
flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
for ( nn = 0; nn < count; nn++ )
@@ -302,8 +358,8 @@
FT_DEFINE_SERVICE_GLYPHDICTREC(
cff_service_glyph_dict,
- (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
- (FT_GlyphDict_NameIndexFunc)cff_get_name_index
+ (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */
+ (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */
)
@@ -350,7 +406,7 @@
font_info->italic_angle = dict->italic_angle;
font_info->is_fixed_pitch = dict->is_fixed_pitch;
font_info->underline_position = (FT_Short)dict->underline_position;
- font_info->underline_thickness = (FT_Short)dict->underline_thickness;
+ font_info->underline_thickness = (FT_UShort)dict->underline_thickness;
cff->font_info = font_info;
}
@@ -365,11 +421,13 @@
FT_DEFINE_SERVICE_PSINFOREC(
cff_service_ps_info,
- (PS_GetFontInfoFunc) cff_ps_get_font_info,
- (PS_GetFontExtraFunc) NULL,
- (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
- (PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */
- (PS_GetFontValueFunc) NULL /* not implemented */
+ (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */
+ (PS_GetFontExtraFunc) NULL, /* ps_get_font_extra */
+ (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */
+ /* unsupported with CFF fonts */
+ (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */
+ /* not implemented */
+ (PS_GetFontValueFunc) NULL /* ps_get_font_value */
)
@@ -381,16 +439,34 @@
static const char*
cff_get_ps_name( CFF_Face face )
{
- CFF_Font cff = (CFF_Font)face->extra.data;
+ CFF_Font cff = (CFF_Font)face->extra.data;
+ SFNT_Service sfnt = (SFNT_Service)face->sfnt;
+ /* following the OpenType specification 1.7, we return the name stored */
+ /* in the `name' table for a CFF wrapped into an SFNT container */
+
+ if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
+ {
+ FT_Library library = FT_FACE_LIBRARY( face );
+ FT_Module sfnt_module = FT_Get_Module( library, "sfnt" );
+ FT_Service_PsFontName service =
+ (FT_Service_PsFontName)ft_module_get_service(
+ sfnt_module,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
+
+
+ if ( service && service->get_ps_font_name )
+ return service->get_ps_font_name( FT_FACE( face ) );
+ }
+
return (const char*)cff->font_name;
}
FT_DEFINE_SERVICE_PSFONTNAMEREC(
cff_service_ps_name,
- (FT_PsName_GetFunc)cff_get_ps_name
+ (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */
)
@@ -437,7 +513,7 @@
FT_DEFINE_SERVICE_TTCMAPSREC(
cff_service_get_cmap_info,
- (TT_CMap_Info_GetFunc)cff_get_cmap_info
+ (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */
)
@@ -567,9 +643,12 @@
FT_DEFINE_SERVICE_CIDREC(
cff_service_cid_info,
- (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
- (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid,
- (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index
+ (FT_CID_GetRegistryOrderingSupplementFunc)
+ cff_get_ros, /* get_ros */
+ (FT_CID_GetIsInternallyCIDKeyedFunc)
+ cff_get_is_cid, /* get_is_cid */
+ (FT_CID_GetCIDFromGlyphIndexFunc)
+ cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */
)
@@ -586,7 +665,38 @@
CFF_Driver driver = (CFF_Driver)module;
- if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+ {
+ FT_Int* darken_params = (FT_Int*)value;
+
+ FT_Int x1 = darken_params[0];
+ FT_Int y1 = darken_params[1];
+ FT_Int x2 = darken_params[2];
+ FT_Int y2 = darken_params[3];
+ FT_Int x3 = darken_params[4];
+ FT_Int y3 = darken_params[5];
+ FT_Int x4 = darken_params[6];
+ FT_Int y4 = darken_params[7];
+
+
+ if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
+ y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
+ x1 > x2 || x2 > x3 || x3 > x4 ||
+ y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
+ return FT_THROW( Invalid_Argument );
+
+ driver->darken_params[0] = x1;
+ driver->darken_params[1] = y1;
+ driver->darken_params[2] = x2;
+ driver->darken_params[3] = y2;
+ driver->darken_params[4] = x3;
+ driver->darken_params[5] = y3;
+ driver->darken_params[6] = x4;
+ driver->darken_params[7] = y4;
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
FT_UInt* hinting_engine = (FT_UInt*)value;
@@ -624,13 +734,28 @@
FT_Error error = FT_Err_Ok;
CFF_Driver driver = (CFF_Driver)module;
- FT_UInt hinting_engine = driver->hinting_engine;
- FT_Bool no_stem_darkening = driver->no_stem_darkening;
-
- if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
- FT_UInt* val = (FT_UInt*)value;
+ FT_Int* darken_params = driver->darken_params;
+ FT_Int* val = (FT_Int*)value;
+
+
+ val[0] = darken_params[0];
+ val[1] = darken_params[1];
+ val[2] = darken_params[2];
+ val[3] = darken_params[3];
+ val[4] = darken_params[4];
+ val[5] = darken_params[5];
+ val[6] = darken_params[6];
+ val[7] = darken_params[7];
+
+ return error;
+ }
+ else if ( !ft_strcmp( property_name, "hinting-engine" ) )
+ {
+ FT_UInt hinting_engine = driver->hinting_engine;
+ FT_UInt* val = (FT_UInt*)value;
*val = hinting_engine;
@@ -639,7 +764,8 @@
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
- FT_Bool* val = (FT_Bool*)value;
+ FT_Bool no_stem_darkening = driver->no_stem_darkening;
+ FT_Bool* val = (FT_Bool*)value;
*val = no_stem_darkening;
@@ -655,8 +781,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
cff_service_properties,
- (FT_Properties_SetFunc)cff_property_set,
- (FT_Properties_GetFunc)cff_property_get )
+ (FT_Properties_SetFunc)cff_property_set, /* set_property */
+ (FT_Properties_GetFunc)cff_property_get ) /* get_property */
/*************************************************************************/
@@ -674,7 +800,7 @@
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
FT_DEFINE_SERVICEDESCREC7(
cff_services,
- FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
@@ -685,7 +811,7 @@
#else
FT_DEFINE_SERVICEDESCREC6(
cff_services,
- FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF,
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
@@ -704,7 +830,7 @@
FT_Module_Interface result;
- /* CFF_SERVICES_GET derefers `library' in PIC mode */
+ /* CFF_SERVICES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
if ( !driver )
return NULL;
@@ -744,9 +870,10 @@
FT_DEFINE_DRIVER(
cff_driver_class,
- FT_MODULE_FONT_DRIVER |
- FT_MODULE_DRIVER_SCALABLE |
- FT_MODULE_DRIVER_HAS_HINTER,
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER |
+ FT_MODULE_DRIVER_HINTS_LIGHTLY,
sizeof ( CFF_DriverRec ),
"cff",
@@ -755,31 +882,29 @@
0, /* module-specific interface */
- cff_driver_init,
- cff_driver_done,
- cff_get_interface,
+ cff_driver_init, /* FT_Module_Constructor module_init */
+ cff_driver_done, /* FT_Module_Destructor module_done */
+ cff_get_interface, /* FT_Module_Requester get_interface */
- /* now the specific driver fields */
sizeof ( TT_FaceRec ),
sizeof ( CFF_SizeRec ),
sizeof ( CFF_GlyphSlotRec ),
- cff_face_init,
- cff_face_done,
- cff_size_init,
- cff_size_done,
- cff_slot_init,
- cff_slot_done,
+ cff_face_init, /* FT_Face_InitFunc init_face */
+ cff_face_done, /* FT_Face_DoneFunc done_face */
+ cff_size_init, /* FT_Size_InitFunc init_size */
+ cff_size_done, /* FT_Size_DoneFunc done_size */
+ cff_slot_init, /* FT_Slot_InitFunc init_slot */
+ cff_slot_done, /* FT_Slot_DoneFunc done_slot */
- cff_glyph_load,
+ cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */
- cff_get_kerning,
- 0, /* FT_Face_AttachFunc */
- cff_get_advances,
+ cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
+ 0, /* FT_Face_AttachFunc attach_file */
+ cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
- cff_size_request,
-
- CFF_SIZE_SELECT
+ cff_size_request, /* FT_Size_RequestFunc request_size */
+ CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */
)
diff --git a/src/cff/cffdrivr.h b/src/cff/cffdrivr.h
index 50e8138..9527f5e 100644
--- a/src/cff/cffdrivr.h
+++ b/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
/* */
/* High-level OpenType driver interface (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cfferrs.h b/src/cff/cfferrs.h
index 801d73e..543bdb0 100644
--- a/src/cff/cfferrs.h
+++ b/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
/* */
/* CFF error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 1904ca0..5f57403 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -273,8 +273,8 @@
builder->current = &loader->current.outline;
FT_GlyphLoader_Rewind( loader );
- builder->hints_globals = 0;
- builder->hints_funcs = 0;
+ builder->hints_globals = NULL;
+ builder->hints_funcs = NULL;
if ( hinting && size )
{
@@ -434,7 +434,7 @@
goto Exit;
}
- FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index ));
+ FT_TRACE3(( " in subfont %d:\n", fd_index ));
sub = cff->subfonts[fd_index];
@@ -447,10 +447,6 @@
builder->hints_globals = (void *)internal->subfonts[fd_index];
}
}
-#ifdef FT_DEBUG_LEVEL_TRACE
- else
- FT_TRACE3(( "glyph index %d:\n", glyph_index ));
-#endif
decoder->num_locals = sub->local_subrs_index.count;
decoder->locals = sub->local_subrs;
@@ -650,7 +646,7 @@
for ( n = 0; n < cff->num_glyphs; n++ )
{
if ( cff->charset.sids[n] == glyph_sid )
- return n;
+ return (FT_Int)n;
}
return -1;
@@ -676,7 +672,7 @@
*pointer = (FT_Byte*)data.pointer;
- *length = data.length;
+ *length = (FT_ULong)data.length;
return error;
}
@@ -707,11 +703,11 @@
/* callback function. */
if ( face->root.internal->incremental_interface )
{
- FT_Data data;
+ FT_Data data;
data.pointer = *pointer;
- data.length = length;
+ data.length = (FT_Int)length;
face->root.internal->incremental_interface->funcs->free_glyph_data(
face->root.internal->incremental_interface->object, &data );
@@ -823,7 +819,7 @@
FT_GlyphLoader_Prepare( builder->loader );
/* First load `bchar' in builder */
- error = cff_get_glyph_data( face, bchar_index,
+ error = cff_get_glyph_data( face, (FT_UInt)bchar_index,
&charstring, &charstring_len );
if ( !error )
{
@@ -853,7 +849,7 @@
builder->pos_y = ady;
/* Now load `achar' on top of the base outline. */
- error = cff_get_glyph_data( face, achar_index,
+ error = cff_get_glyph_data( face, (FT_UInt)achar_index,
&charstring, &charstring_len );
if ( !error )
{
@@ -926,10 +922,10 @@
decoder->read_width = 1;
/* compute random seed from stack address of parameter */
- seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
- (FT_PtrDist)(char*)&decoder ^
- (FT_PtrDist)(char*)&charstring_base ) &
- FT_ULONG_MAX ) ;
+ seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^
+ (FT_Offset)(char*)&decoder ^
+ (FT_Offset)(char*)&charstring_base ) &
+ FT_ULONG_MAX );
seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
if ( seed == 0 )
seed = 0x7384;
@@ -1377,12 +1373,12 @@
{
if ( op == cff_op_hintmask )
hinter->hintmask( hinter->hints,
- builder->current->n_points,
- decoder->num_hints,
+ (FT_UInt)builder->current->n_points,
+ (FT_UInt)decoder->num_hints,
ip );
else
hinter->counter( hinter->hints,
- decoder->num_hints,
+ (FT_UInt)decoder->num_hints,
ip );
}
@@ -1993,23 +1989,22 @@
}
else
{
- if ( !error )
- error = FT_Err_Ok;
-
cff_builder_close_contour( builder );
/* close hints recording session */
if ( hinter )
{
if ( hinter->close( hinter->hints,
- builder->current->n_points ) )
+ (FT_UInt)builder->current->n_points ) )
goto Syntax_Error;
/* apply hints to the loaded glyph outline now */
- hinter->apply( hinter->hints,
- builder->current,
- (PSH_Globals)builder->hints_globals,
- decoder->hint_mode );
+ error = hinter->apply( hinter->hints,
+ builder->current,
+ (PSH_Globals)builder->hints_globals,
+ decoder->hint_mode );
+ if ( error )
+ goto Fail;
}
/* add current outline to the glyph slot */
@@ -2394,7 +2389,9 @@
decoder->locals_bias );
- FT_TRACE4(( " callsubr(%d)\n", idx ));
+ FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
+ idx,
+ zone - decoder->zones + 1 ));
if ( idx >= decoder->num_locals )
{
@@ -2436,7 +2433,9 @@
decoder->globals_bias );
- FT_TRACE4(( " callgsubr(%d)\n", idx ));
+ FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
+ idx,
+ zone - decoder->zones + 1 ));
if ( idx >= decoder->num_globals )
{
@@ -2473,7 +2472,8 @@
break;
case cff_op_return:
- FT_TRACE4(( " return\n" ));
+ FT_TRACE4(( " return (leaving level %d)\n",
+ decoder->zone - decoder->zones ));
if ( decoder->zone <= decoder->zones )
{
@@ -2674,7 +2674,7 @@
error = sfnt->load_sbit_image( face,
size->strike_index,
glyph_index,
- (FT_Int)load_flags,
+ (FT_UInt)load_flags,
stream,
&glyph->root.bitmap,
&metrics );
@@ -2715,23 +2715,23 @@
/* compute linear advance widths */
- ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
- glyph_index,
- &dummy,
- &advance );
+ (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+ glyph_index,
+ &dummy,
+ &advance );
glyph->root.linearHoriAdvance = advance;
has_vertical_info = FT_BOOL(
face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
- /* get the vertical metrics from the vtmx table if we have one */
+ /* get the vertical metrics from the vmtx table if we have one */
if ( has_vertical_info )
{
- ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
- glyph_index,
- &dummy,
- &advance );
+ (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
+ glyph_index,
+ &dummy,
+ &advance );
glyph->root.linearVertAdvance = advance;
}
else
@@ -2762,16 +2762,16 @@
/* this scaling is only relevant if the PS hinter isn't active */
if ( cff->num_subfonts )
{
- FT_ULong top_upm, sub_upm;
- FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,
- glyph_index );
+ FT_Long top_upm, sub_upm;
+ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,
+ glyph_index );
if ( fd_index >= cff->num_subfonts )
fd_index = (FT_Byte)( cff->num_subfonts - 1 );
- top_upm = cff->top_font.font_dict.units_per_em;
- sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
+ top_upm = (FT_Long)cff->top_font.font_dict.units_per_em;
+ sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em;
font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
@@ -2849,7 +2849,16 @@
/* as a consequence, glyphs larger than 2000ppem get rejected */
if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
{
- /* XXX to be implemented */
+ /* this time, we retry unhinted and scale up the glyph later on */
+ /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
+ /* 0x400 for both `x_scale' and `y_scale' in this case) */
+ hinting = FALSE;
+ force_scaling = TRUE;
+ glyph->hint = hinting;
+
+ error = cf2_decoder_parse_charstrings( &decoder,
+ charstring,
+ charstring_len );
}
}
@@ -2863,7 +2872,7 @@
/* fonts. */
if ( face->root.internal->incremental_interface )
{
- glyph->root.control_data = 0;
+ glyph->root.control_data = NULL;
glyph->root.control_len = 0;
}
else
@@ -2880,7 +2889,7 @@
{
glyph->root.control_data = csindex->bytes +
csindex->offsets[glyph_index] - 1;
- glyph->root.control_len = charstring_len;
+ glyph->root.control_len = (FT_Long)charstring_len;
}
}
@@ -2940,19 +2949,36 @@
{
FT_BBox cbox;
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
- FT_Vector advance;
FT_Bool has_vertical_info;
- /* copy the _unscaled_ advance width */
- metrics->horiAdvance = decoder.glyph_width;
- glyph->root.linearHoriAdvance = decoder.glyph_width;
+ if ( face->horizontal.number_Of_HMetrics )
+ {
+ FT_Short horiBearingX = 0;
+ FT_UShort horiAdvance = 0;
+
+
+ ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+ glyph_index,
+ &horiBearingX,
+ &horiAdvance );
+ metrics->horiAdvance = horiAdvance;
+ metrics->horiBearingX = horiBearingX;
+ glyph->root.linearHoriAdvance = horiAdvance;
+ }
+ else
+ {
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.glyph_width;
+ glyph->root.linearHoriAdvance = decoder.glyph_width;
+ }
+
glyph->root.internal->glyph_transformed = 0;
has_vertical_info = FT_BOOL( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 );
- /* get the vertical metrics from the vtmx table if we have one */
+ /* get the vertical metrics from the vmtx table if we have one */
if ( has_vertical_info )
{
FT_Short vertBearingY = 0;
@@ -2987,26 +3013,27 @@
glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
- if ( !( font_matrix.xx == 0x10000L &&
- font_matrix.yy == 0x10000L &&
- font_matrix.xy == 0 &&
- font_matrix.yx == 0 ) )
+ /* apply the font matrix, if any */
+ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
+ font_matrix.xy != 0 || font_matrix.yx != 0 )
+ {
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
- if ( !( font_offset.x == 0 &&
- font_offset.y == 0 ) )
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
+ font_matrix.xx );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
+ font_matrix.yy );
+ }
+
+ if ( font_offset.x || font_offset.y )
+ {
FT_Outline_Translate( &glyph->root.outline,
- font_offset.x, font_offset.y );
+ font_offset.x,
+ font_offset.y );
- advance.x = metrics->horiAdvance;
- advance.y = 0;
- FT_Vector_Transform( &advance, &font_matrix );
- metrics->horiAdvance = advance.x + font_offset.x;
-
- advance.x = 0;
- advance.y = metrics->vertAdvance;
- FT_Vector_Transform( &advance, &font_matrix );
- metrics->vertAdvance = advance.y + font_offset.y;
+ metrics->horiAdvance += font_offset.x;
+ metrics->vertAdvance += font_offset.y;
+ }
if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
{
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 41df7db..5f2655f 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2004, 2006-2009, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,7 +29,12 @@
#define CFF_MAX_OPERANDS 48
-#define CFF_MAX_SUBRS_CALLS 32
+#define CFF_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */
+ /* only 10 are allowed but there exist */
+ /* fonts like `HiraKakuProN-W3.ttf' */
+ /* (Hiragino Kaku Gothic ProN W3; */
+ /* 8.2d6e1; 2014-12-19) that exceed */
+ /* this limit */
#define CFF_MAX_TRANS_ELEMENTS 32
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 64b4971..c61222d 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType and CFF data/program tables loader (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -357,7 +357,7 @@
case 3:
for ( ; p < p_end; p += 3, poff++ )
- poff[0] = FT_PEEK_OFF3( p );
+ poff[0] = FT_PEEK_UOFF3( p );
break;
default:
@@ -414,7 +414,7 @@
cur_offset = idx->offsets[0] - 1;
/* sanity check */
- if ( cur_offset >= idx->data_size )
+ if ( cur_offset != 0 )
{
FT_TRACE0(( "cff_index_get_pointers:"
" invalid first offset value %d set to zero\n",
@@ -432,11 +432,11 @@
FT_ULong next_offset = idx->offsets[n] - 1;
- /* empty slot + two sanity checks for invalid offset tables */
- if ( next_offset == 0 ||
- next_offset < cur_offset ||
- ( next_offset >= idx->data_size && n < idx->count ) )
+ /* two sanity checks for invalid offset tables */
+ if ( next_offset < cur_offset )
next_offset = cur_offset;
+ else if ( next_offset > idx->data_size )
+ next_offset = idx->data_size;
if ( !pool )
t[n] = org_bytes + next_offset;
@@ -689,6 +689,13 @@
if ( FT_READ_USHORT( num_ranges ) )
goto Exit;
+ if ( !num_ranges )
+ {
+ FT_TRACE0(( "CFF_Load_FD_Select: empty FDSelect array\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
fdselect->data_size = num_ranges * 3 + 2;
Load_Data:
@@ -719,7 +726,7 @@
break;
case 3:
- /* first, compare to cache */
+ /* first, compare to the cache */
if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
fdselect->cache_count )
{
@@ -727,7 +734,7 @@
break;
}
- /* then, lookup the ranges array */
+ /* then, look up the ranges array */
{
FT_Byte* p = fdselect->data;
FT_Byte* p_limit = p + fdselect->data_size;
@@ -750,7 +757,7 @@
/* update cache */
fdselect->cache_first = first;
- fdselect->cache_count = limit-first;
+ fdselect->cache_count = limit - first;
fdselect->cache_fd = fd2;
break;
}
@@ -802,7 +809,7 @@
/* When multiple GIDs map to the same CID, we choose the lowest */
/* GID. This is not described in any spec, but it matches the */
/* behaviour of recent Acroread versions. */
- for ( j = num_glyphs - 1; j >= 0 ; j-- )
+ for ( j = (FT_Long)num_glyphs - 1; j >= 0 ; j-- )
charset->cids[charset->sids[j]] = (FT_UShort)j;
charset->max_cid = max_cid;
@@ -1440,7 +1447,7 @@
FT_ULong base_offset;
CFF_FontRecDict dict;
CFF_IndexRec string_index;
- FT_Int subfont_index;
+ FT_UInt subfont_index;
FT_ZERO( font );
@@ -1488,9 +1495,9 @@
if ( pure_cff )
{
/* well, we don't really forget the `disabled' fonts... */
- subfont_index = face_index;
+ subfont_index = (FT_UInt)( face_index & 0xFFFF );
- if ( subfont_index >= (FT_Int)font->name_index.count )
+ if ( face_index > 0 && subfont_index >= font->name_index.count )
{
FT_ERROR(( "cff_font_load:"
" invalid subfont index for pure CFF font (%d)\n",
diff --git a/src/cff/cffload.h b/src/cff/cffload.h
index 8049619..459e7b0 100644
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType & CFF data/program tables loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index dd750d1..d628b68 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -226,8 +226,8 @@
CFF_Font font = (CFF_Font)face->extra.data;
CFF_Internal internal = (CFF_Internal)size->internal;
- FT_ULong top_upm = font->top_font.font_dict.units_per_em;
- FT_UInt i;
+ FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em;
+ FT_UInt i;
funcs->set_scale( internal->topfont,
@@ -237,7 +237,7 @@
for ( i = font->num_subfonts; i > 0; i-- )
{
CFF_SubFont sub = font->subfonts[i - 1];
- FT_ULong sub_upm = sub->font_dict.units_per_em;
+ FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em;
FT_Pos x_scale, y_scale;
@@ -298,8 +298,8 @@
CFF_Font font = (CFF_Font)cffface->extra.data;
CFF_Internal internal = (CFF_Internal)size->internal;
- FT_ULong top_upm = font->top_font.font_dict.units_per_em;
- FT_UInt i;
+ FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em;
+ FT_UInt i;
funcs->set_scale( internal->topfont,
@@ -309,7 +309,7 @@
for ( i = font->num_subfonts; i > 0; i-- )
{
CFF_SubFont sub = font->subfonts[i - 1];
- FT_ULong sub_upm = sub->font_dict.units_per_em;
+ FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em;
FT_Pos x_scale, y_scale;
@@ -342,7 +342,7 @@
FT_LOCAL_DEF( void )
cff_slot_done( FT_GlyphSlot slot )
{
- slot->internal->glyph_hints = 0;
+ slot->internal->glyph_hints = NULL;
}
@@ -583,16 +583,21 @@
if ( error )
goto Exit;
+ /* if we are performing a simple font format check, exit immediately */
+ /* (this is here for pure CFF) */
+ if ( face_index < 0 )
+ return FT_Err_Ok;
+
cff->pshinter = pshinter;
cff->psnames = psnames;
- cffface->face_index = face_index;
+ cffface->face_index = face_index & 0xFFFF;
/* Complement the root flags with some interesting information. */
/* Note that this is only necessary for pure CFF and CEF fonts; */
/* SFNT based fonts use the `name' table instead. */
- cffface->num_glyphs = cff->num_glyphs;
+ cffface->num_glyphs = (FT_Long)cff->num_glyphs;
dict = &cff->top_font.font_dict;
@@ -629,7 +634,7 @@
if ( !dict->has_font_matrix )
dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
- /* Normalize the font matrix so that `matrix->xx' is 1; the */
+ /* Normalize the font matrix so that `matrix->yy' is 1; the */
/* scaling is done with `units_per_em' then (at this point, */
/* it already contains the scaling factor, but without */
/* normalization of the matrix). */
@@ -646,7 +651,7 @@
if ( temp != 0x10000L )
{
- *upm = FT_DivFix( *upm, temp );
+ *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
matrix->xx = FT_DivFix( matrix->xx, temp );
matrix->yx = FT_DivFix( matrix->yx, temp );
@@ -682,7 +687,8 @@
if ( top->has_font_matrix )
{
if ( top->units_per_em > 1 && sub->units_per_em > 1 )
- scaling = FT_MIN( top->units_per_em, sub->units_per_em );
+ scaling = (FT_Long)FT_MIN( top->units_per_em,
+ sub->units_per_em );
else
scaling = 1;
@@ -693,9 +699,10 @@
&top->font_matrix,
scaling );
- sub->units_per_em = FT_MulDiv( sub->units_per_em,
- top->units_per_em,
- scaling );
+ sub->units_per_em = (FT_ULong)
+ FT_MulDiv( (FT_Long)sub->units_per_em,
+ (FT_Long)top->units_per_em,
+ scaling );
}
}
else
@@ -713,7 +720,7 @@
if ( temp != 0x10000L )
{
- *upm = FT_DivFix( *upm, temp );
+ *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
matrix->xx = FT_DivFix( matrix->xx, temp );
matrix->yx = FT_DivFix( matrix->yx, temp );
@@ -733,13 +740,13 @@
/* set up num_faces */
- cffface->num_faces = cff->num_faces;
+ cffface->num_faces = (FT_Long)cff->num_faces;
/* compute number of glyphs */
if ( dict->cid_registry != 0xFFFFU )
- cffface->num_glyphs = cff->charset.max_cid + 1;
+ cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 );
else
- cffface->num_glyphs = cff->charstrings_index.count;
+ cffface->num_glyphs = (FT_Long)cff->charstrings_index.count;
/* set global bbox, as well as EM size */
cffface->bbox.xMin = dict->font_bbox.xMin >> 16;
@@ -763,7 +770,9 @@
(FT_Short)( dict->underline_thickness >> 16 );
/* retrieve font family & style name */
- cffface->family_name = cff_index_get_name( cff, face_index );
+ cffface->family_name = cff_index_get_name(
+ cff,
+ (FT_UInt)( face_index & 0xFFFF ) );
if ( cffface->family_name )
{
char* full = cff_index_get_sid_string( cff,
@@ -866,7 +875,7 @@
flags |= FT_FACE_FLAG_KERNING;
#endif
- cffface->face_flags = flags;
+ cffface->face_flags |= flags;
/*******************************************************************/
/* */
@@ -943,16 +952,6 @@
if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
goto Exit;
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "cff_face_init: no Unicode cmap is found, "
- "and too many subtables (%d) to add synthesized cmap\n",
- nn ));
- goto Exit;
- }
-#endif
-
/* we didn't find a Unicode charmap -- synthesize one */
cmaprec.face = cffface;
cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
@@ -973,15 +972,6 @@
cffface->charmap = cffface->charmaps[nn];
Skip_Unicode:
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( nn > FT_MAX_CHARMAP_CACHEABLE )
- {
- FT_ERROR(( "cff_face_init: Unicode cmap is found, "
- "but too many preceding subtables (%d) to access\n",
- nn - 1 ));
- goto Exit;
- }
-#endif
if ( encoding->count > 0 )
{
FT_CMap_Class clazz;
@@ -1055,13 +1045,23 @@
CFF_Driver driver = (CFF_Driver)module;
- /* set default property values */
+ /* set default property values, cf. `ftcffdrv.h' */
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
- driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
+ driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
#else
- driver->hinting_engine = FT_CFF_HINTING_ADOBE;
+ driver->hinting_engine = FT_CFF_HINTING_ADOBE;
#endif
- driver->no_stem_darkening = FALSE;
+
+ driver->no_stem_darkening = TRUE;
+
+ driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
+ driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
+ driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
+ driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
+ driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
+ driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
+ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
+ driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
return FT_Err_Ok;
}
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index b375c20..3cc9531 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (specification). */
/* */
-/* Copyright 1996-2004, 2006-2008, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -121,6 +121,8 @@
FT_UInt hinting_engine;
FT_Bool no_stem_darkening;
+ FT_Int darken_params[8];
+
} CFF_DriverRec;
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 9622212..063b351 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (body) */
/* */
-/* Copyright 1996-2004, 2007-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -66,7 +66,6 @@
goto Bad;
val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] );
- p += 2;
}
else if ( v == 29 )
{
@@ -77,7 +76,6 @@
( (FT_ULong)p[1] << 16 ) |
( (FT_ULong)p[2] << 8 ) |
(FT_ULong)p[3] );
- p += 4;
}
else if ( v < 247 )
{
@@ -89,7 +87,6 @@
goto Bad;
val = ( v - 247 ) * 256 + p[0] + 108;
- p++;
}
else
{
@@ -97,7 +94,6 @@
goto Bad;
val = -( v - 251 ) * 256 - p[0] - 108;
- p++;
}
Exit:
@@ -133,7 +129,7 @@
FT_Long* scaling )
{
FT_Byte* p = start;
- FT_UInt nib;
+ FT_Int nib;
FT_UInt phase;
FT_Long result, number, exponent;
@@ -170,7 +166,7 @@
}
/* Get the nibble. */
- nib = ( p[0] >> phase ) & 0xF;
+ nib = (FT_Int)( p[0] >> phase ) & 0xF;
phase = 4 - phase;
if ( nib == 0xE )
@@ -192,7 +188,7 @@
}
/* Read fraction part, if any. */
- if ( nib == 0xa )
+ if ( nib == 0xA )
for (;;)
{
/* If we entered this iteration with phase == 4, we need */
@@ -563,7 +559,7 @@
offset->x = cff_parse_fixed_scaled( data++, scaling );
offset->y = cff_parse_fixed_scaled( data, scaling );
- *upm = power_tens[scaling];
+ *upm = (FT_ULong)power_tens[scaling];
FT_TRACE4(( " [%f %f %f %f %f %f]\n",
(double)matrix->xx / *upm / 65536,
@@ -621,14 +617,34 @@
if ( parser->top >= parser->stack + 2 )
{
- dict->private_size = cff_parse_num( data++ );
- dict->private_offset = cff_parse_num( data );
+ FT_Long tmp;
+
+
+ tmp = cff_parse_num( data++ );
+ if ( tmp < 0 )
+ {
+ FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Fail;
+ }
+ dict->private_size = (FT_ULong)tmp;
+
+ tmp = cff_parse_num( data );
+ if ( tmp < 0 )
+ {
+ FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Fail;
+ }
+ dict->private_offset = (FT_ULong)tmp;
+
FT_TRACE4(( " %lu %lu\n",
dict->private_size, dict->private_offset ));
error = FT_Err_Ok;
}
+ Fail:
return error;
}
diff --git a/src/cff/cffparse.h b/src/cff/cffparse.h
index 61d91ed..8ad02ea 100644
--- a/src/cff/cffparse.h
+++ b/src/cff/cffparse.h
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (specification) */
/* */
-/* Copyright 1996-2003, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffpic.c b/src/cff/cffpic.c
index f22e4f0..d40dec5 100644
--- a/src/cff/cffpic.c
+++ b/src/cff/cffpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cffpic.h b/src/cff/cffpic.h
index 50bab4c..9a221a7 100644
--- a/src/cff/cffpic.h
+++ b/src/cff/cffpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,8 +20,6 @@
#define __CFFPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -49,6 +47,8 @@
#include FT_SERVICE_PROPERTIES_H
+FT_BEGIN_HEADER
+
typedef struct CffModulePIC_
{
FT_ServiceDescRec* cff_services;
@@ -96,12 +96,12 @@
FT_Error
cff_driver_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __CFFPIC_H__ */
diff --git a/src/cff/cfftoken.h b/src/cff/cfftoken.h
index bcb4276..5b32076 100644
--- a/src/cff/cfftoken.h
+++ b/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
/* */
/* CFF token definitions (specification only). */
/* */
-/* Copyright 1996-2003, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index 8727446..de8a5ee 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
/* Basic OpenType/CFF type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2003, 2006-2008, 2010-2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/gzip/adler32.c b/src/gzip/adler32.c
new file mode 100644
index 0000000..c53f9dd
--- /dev/null
+++ b/src/gzip/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+ZEXPORT(uLong) adler32( /* adler, buf, len) */
+ uLong adler,
+ const Bytef *buf,
+ uInt len )
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
new file mode 100644
index 0000000..27c6254
--- /dev/null
+++ b/src/gzip/ftgzip.c
@@ -0,0 +1,804 @@
+/***************************************************************************/
+/* */
+/* ftgzip.c */
+/* */
+/* FreeType support for .gz compressed files. */
+/* */
+/* This optional component relies on zlib. It should mainly be used to */
+/* parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2002-2015 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 <ft2build.h>
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_GZIP_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef FT_ERR_PREFIX
+#define FT_ERR_PREFIX Gzip_Err_
+#define FT_ERR_BASE FT_Mod_Err_Gzip
+
+#include FT_ERRORS_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "gzip code does not support PIC yet"
+#endif
+
+#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
+
+#include <zlib.h>
+
+#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+ /* In this case, we include our own modified sources of the ZLib */
+ /* within the "ftgzip" component. The modifications were necessary */
+ /* to #include all files without conflicts, as well as preventing */
+ /* the definition of "extern" functions that may cause linking */
+ /* conflicts when a program is linked with both FreeType and the */
+ /* original ZLib. */
+
+#ifndef USE_ZLIB_ZCALLOC
+#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */
+#endif
+
+#include "zlib.h"
+
+#undef SLOW
+#define SLOW 1 /* we can't use asm-optimized sources here! */
+
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+ /* We disable the warning `conversion from XXX to YYY, */
+ /* possible loss of data' in order to compile cleanly with */
+ /* the maximum level of warnings: zlib is non-FreeType */
+ /* code. */
+#pragma warning( push )
+#pragma warning( disable : 4244 )
+#endif /* _MSC_VER */
+
+ /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like
+ this. We temporarily disable it and load all necessary header files. */
+#define NO_INFLATE_MASK
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#undef NO_INFLATE_MASK
+
+ /* infutil.c must be included before infcodes.c */
+#include "zutil.c"
+#include "inftrees.c"
+#include "infutil.c"
+#include "infcodes.c"
+#include "infblock.c"
+#include "inflate.c"
+#include "adler32.c"
+
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
+#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** Z L I B M E M O R Y M A N A G E M E N T *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ /* it is better to use FreeType memory routines instead of raw
+ 'malloc/free' */
+
+ static voidpf
+ ft_gzip_alloc( FT_Memory memory,
+ uInt items,
+ uInt size )
+ {
+ FT_ULong sz = (FT_ULong)size * items;
+ FT_Error error;
+ FT_Pointer p = NULL;
+
+
+ (void)FT_ALLOC( p, sz );
+ return p;
+ }
+
+
+ static void
+ ft_gzip_free( FT_Memory memory,
+ voidpf address )
+ {
+ FT_MEM_FREE( address );
+ }
+
+
+#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC )
+
+ local voidpf
+ zcalloc ( voidpf opaque,
+ unsigned items,
+ unsigned size )
+ {
+ return ft_gzip_alloc( (FT_Memory)opaque, items, size );
+ }
+
+ local void
+ zcfree( voidpf opaque,
+ voidpf ptr )
+ {
+ ft_gzip_free( (FT_Memory)opaque, ptr );
+ }
+
+#endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** Z L I B F I L E D E S C R I P T O R *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_GZIP_BUFFER_SIZE 4096
+
+ typedef struct FT_GZipFileRec_
+ {
+ FT_Stream source; /* parent/source stream */
+ FT_Stream stream; /* embedding stream */
+ FT_Memory memory; /* memory allocator */
+ z_stream zstream; /* zlib input stream */
+
+ FT_ULong start; /* starting position, after .gz header */
+ FT_Byte input[FT_GZIP_BUFFER_SIZE]; /* input read buffer */
+
+ FT_Byte buffer[FT_GZIP_BUFFER_SIZE]; /* output buffer */
+ FT_ULong pos; /* position in output */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+
+ } FT_GZipFileRec, *FT_GZipFile;
+
+
+ /* gzip flag byte */
+#define FT_GZIP_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define FT_GZIP_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define FT_GZIP_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define FT_GZIP_ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define FT_GZIP_COMMENT 0x10 /* bit 4 set: file comment present */
+#define FT_GZIP_RESERVED 0xE0 /* bits 5..7: reserved */
+
+
+ /* check and skip .gz header - we don't support `transparent' compression */
+ static FT_Error
+ ft_gzip_check_header( FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Byte head[4];
+
+
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ( head, 4 ) )
+ goto Exit;
+
+ /* head[0] && head[1] are the magic numbers; */
+ /* head[2] is the method, and head[3] the flags */
+ if ( head[0] != 0x1F ||
+ head[1] != 0x8B ||
+ head[2] != Z_DEFLATED ||
+ (head[3] & FT_GZIP_RESERVED) )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /* skip time, xflags and os code */
+ (void)FT_STREAM_SKIP( 6 );
+
+ /* skip the extra field */
+ if ( head[3] & FT_GZIP_EXTRA_FIELD )
+ {
+ FT_UInt len;
+
+
+ if ( FT_READ_USHORT_LE( len ) ||
+ FT_STREAM_SKIP( len ) )
+ goto Exit;
+ }
+
+ /* skip original file name */
+ if ( head[3] & FT_GZIP_ORIG_NAME )
+ for (;;)
+ {
+ FT_UInt c;
+
+
+ if ( FT_READ_BYTE( c ) )
+ goto Exit;
+
+ if ( c == 0 )
+ break;
+ }
+
+ /* skip .gz comment */
+ if ( head[3] & FT_GZIP_COMMENT )
+ for (;;)
+ {
+ FT_UInt c;
+
+
+ if ( FT_READ_BYTE( c ) )
+ goto Exit;
+
+ if ( c == 0 )
+ break;
+ }
+
+ /* skip CRC */
+ if ( head[3] & FT_GZIP_HEAD_CRC )
+ if ( FT_STREAM_SKIP( 2 ) )
+ goto Exit;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_init( FT_GZipFile zip,
+ FT_Stream stream,
+ FT_Stream source )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Error error = FT_Err_Ok;
+
+
+ zip->stream = stream;
+ zip->source = source;
+ zip->memory = stream->memory;
+
+ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ /* check and skip .gz header */
+ {
+ stream = source;
+
+ error = ft_gzip_check_header( stream );
+ if ( error )
+ goto Exit;
+
+ zip->start = FT_STREAM_POS();
+ }
+
+ /* initialize zlib -- there is no zlib header in the compressed stream */
+ zstream->zalloc = (alloc_func)ft_gzip_alloc;
+ zstream->zfree = (free_func) ft_gzip_free;
+ zstream->opaque = stream->memory;
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->buffer;
+
+ if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
+ zstream->next_in == NULL )
+ error = FT_THROW( Invalid_File_Format );
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_gzip_file_done( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+
+
+ inflateEnd( zstream );
+
+ /* clear the rest */
+ zstream->zalloc = NULL;
+ zstream->zfree = NULL;
+ zstream->opaque = NULL;
+ zstream->next_in = NULL;
+ zstream->next_out = NULL;
+ zstream->avail_in = 0;
+ zstream->avail_out = 0;
+
+ zip->memory = NULL;
+ zip->source = NULL;
+ zip->stream = NULL;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_reset( FT_GZipFile zip )
+ {
+ FT_Stream stream = zip->source;
+ FT_Error error;
+
+
+ if ( !FT_STREAM_SEEK( zip->start ) )
+ {
+ z_stream* zstream = &zip->zstream;
+
+
+ inflateReset( zstream );
+
+ zstream->avail_in = 0;
+ zstream->next_in = zip->input;
+ zstream->avail_out = 0;
+ zstream->next_out = zip->buffer;
+
+ zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_fill_input( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Stream stream = zip->source;
+ FT_ULong size;
+
+
+ if ( stream->read )
+ {
+ size = stream->read( stream, stream->pos, zip->input,
+ FT_GZIP_BUFFER_SIZE );
+ if ( size == 0 )
+ {
+ zip->limit = zip->cursor;
+ return FT_THROW( Invalid_Stream_Operation );
+ }
+ }
+ else
+ {
+ size = stream->size - stream->pos;
+ if ( size > FT_GZIP_BUFFER_SIZE )
+ size = FT_GZIP_BUFFER_SIZE;
+
+ if ( size == 0 )
+ {
+ zip->limit = zip->cursor;
+ return FT_THROW( Invalid_Stream_Operation );
+ }
+
+ FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
+ }
+ stream->pos += size;
+
+ zstream->next_in = zip->input;
+ zstream->avail_in = size;
+
+ return FT_Err_Ok;
+ }
+
+
+ static FT_Error
+ ft_gzip_file_fill_output( FT_GZipFile zip )
+ {
+ z_stream* zstream = &zip->zstream;
+ FT_Error error = FT_Err_Ok;
+
+
+ zip->cursor = zip->buffer;
+ zstream->next_out = zip->cursor;
+ zstream->avail_out = FT_GZIP_BUFFER_SIZE;
+
+ while ( zstream->avail_out > 0 )
+ {
+ int err;
+
+
+ if ( zstream->avail_in == 0 )
+ {
+ error = ft_gzip_file_fill_input( zip );
+ if ( error )
+ break;
+ }
+
+ err = inflate( zstream, Z_NO_FLUSH );
+
+ if ( err == Z_STREAM_END )
+ {
+ zip->limit = zstream->next_out;
+ if ( zip->limit == zip->cursor )
+ error = FT_THROW( Invalid_Stream_Operation );
+ break;
+ }
+ else if ( err != Z_OK )
+ {
+ zip->limit = zip->cursor;
+ error = FT_THROW( Invalid_Stream_Operation );
+ break;
+ }
+ }
+
+ return error;
+ }
+
+
+ /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */
+ static FT_Error
+ ft_gzip_file_skip_output( FT_GZipFile zip,
+ FT_ULong count )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_ULong delta;
+
+
+ for (;;)
+ {
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_gzip_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ return error;
+ }
+
+
+ static FT_ULong
+ ft_gzip_file_io( FT_GZipFile zip,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong result = 0;
+ FT_Error error;
+
+
+ /* Reset inflate stream if we're seeking backwards. */
+ /* Yes, that is not too efficient, but it saves memory :-) */
+ if ( pos < zip->pos )
+ {
+ error = ft_gzip_file_reset( zip );
+ if ( error )
+ goto Exit;
+ }
+
+ /* skip unwanted bytes */
+ if ( pos > zip->pos )
+ {
+ error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( count == 0 )
+ goto Exit;
+
+ /* now read the data */
+ for (;;)
+ {
+ FT_ULong delta;
+
+
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ FT_MEM_COPY( buffer, zip->cursor, delta );
+ buffer += delta;
+ result += delta;
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_gzip_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** G Z E M B E D D I N G S T R E A M *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ static void
+ ft_gzip_stream_close( FT_Stream stream )
+ {
+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
+ FT_Memory memory = stream->memory;
+
+
+ if ( zip )
+ {
+ /* finalize gzip file descriptor */
+ ft_gzip_file_done( zip );
+
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+ }
+
+ if ( !stream->read )
+ FT_FREE( stream->base );
+ }
+
+
+ static unsigned long
+ ft_gzip_stream_io( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count )
+ {
+ FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
+
+
+ return ft_gzip_file_io( zip, offset, buffer, count );
+ }
+
+
+ static FT_ULong
+ ft_gzip_get_uncompressed_size( FT_Stream stream )
+ {
+ FT_Error error;
+ FT_ULong old_pos;
+ FT_ULong result = 0;
+
+
+ old_pos = stream->pos;
+ if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
+ {
+ result = FT_Stream_ReadULongLE( stream, &error );
+ if ( error )
+ result = 0;
+
+ (void)FT_Stream_Seek( stream, old_pos );
+ }
+
+ return result;
+ }
+
+
+ /* documentation is in ftgzip.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_GZipFile zip = NULL;
+
+
+ if ( !stream || !source )
+ {
+ error = FT_THROW( Invalid_Stream_Handle );
+ goto Exit;
+ }
+
+ memory = source->memory;
+
+ /*
+ * check the header right now; this prevents allocating un-necessary
+ * objects when we don't need them
+ */
+ error = ft_gzip_check_header( source );
+ if ( error )
+ goto Exit;
+
+ FT_ZERO( stream );
+ stream->memory = memory;
+
+ if ( !FT_QNEW( zip ) )
+ {
+ error = ft_gzip_file_init( zip, stream, source );
+ if ( error )
+ {
+ FT_FREE( zip );
+ goto Exit;
+ }
+
+ stream->descriptor.pointer = zip;
+ }
+
+ /*
+ * We use the following trick to try to dramatically improve the
+ * performance while dealing with small files. If the original stream
+ * size is less than a certain threshold, we try to load the whole font
+ * file into memory. This saves us from using the 32KB buffer needed
+ * to inflate the file, plus the two 4KB intermediate input/output
+ * buffers used in the `FT_GZipFile' structure.
+ */
+ {
+ FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );
+
+
+ if ( zip_size != 0 && zip_size < 40 * 1024 )
+ {
+ FT_Byte* zip_buff = NULL;
+
+
+ if ( !FT_ALLOC( zip_buff, zip_size ) )
+ {
+ FT_ULong count;
+
+
+ count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
+ if ( count == zip_size )
+ {
+ ft_gzip_file_done( zip );
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+
+ stream->size = zip_size;
+ stream->pos = 0;
+ stream->base = zip_buff;
+ stream->read = NULL;
+ stream->close = ft_gzip_stream_close;
+
+ goto Exit;
+ }
+
+ ft_gzip_file_io( zip, 0, NULL, 0 );
+ FT_FREE( zip_buff );
+ }
+ error = FT_Err_Ok;
+ }
+
+ if ( zip_size )
+ stream->size = zip_size;
+ else
+ stream->size = 0x7FFFFFFFL; /* don't know the real size! */
+ }
+
+ stream->pos = 0;
+ stream->base = NULL;
+ stream->read = ft_gzip_stream_io;
+ stream->close = ft_gzip_stream_close;
+
+ Exit:
+ return error;
+ }
+
+
+ /* documentation is in ftgzip.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Gzip_Uncompress( FT_Memory memory,
+ FT_Byte* output,
+ FT_ULong* output_len,
+ const FT_Byte* input,
+ FT_ULong input_len )
+ {
+ z_stream stream;
+ int err;
+
+
+ /* check for `input' delayed to `inflate' */
+
+ if ( !memory || ! output_len || !output )
+ return FT_THROW( Invalid_Argument );
+
+ /* this function is modeled after zlib's `uncompress' function */
+
+ stream.next_in = (Bytef*)input;
+ stream.avail_in = (uInt)input_len;
+
+ stream.next_out = output;
+ stream.avail_out = (uInt)*output_len;
+
+ stream.zalloc = (alloc_func)ft_gzip_alloc;
+ stream.zfree = (free_func) ft_gzip_free;
+ stream.opaque = memory;
+
+ err = inflateInit2( &stream, MAX_WBITS );
+ if ( err != Z_OK )
+ return FT_THROW( Invalid_Argument );
+
+ err = inflate( &stream, Z_FINISH );
+ if ( err != Z_STREAM_END )
+ {
+ inflateEnd( &stream );
+ if ( err == Z_OK )
+ err = Z_BUF_ERROR;
+ }
+ else
+ {
+ *output_len = stream.total_out;
+
+ err = inflateEnd( &stream );
+ }
+
+ if ( err == Z_MEM_ERROR )
+ return FT_THROW( Out_Of_Memory );
+
+ if ( err == Z_BUF_ERROR )
+ return FT_THROW( Array_Too_Large );
+
+ if ( err == Z_DATA_ERROR )
+ return FT_THROW( Invalid_Table );
+
+ return FT_Err_Ok;
+ }
+
+
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_UNUSED( stream );
+ FT_UNUSED( source );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Gzip_Uncompress( FT_Memory memory,
+ FT_Byte* output,
+ FT_ULong* output_len,
+ const FT_Byte* input,
+ FT_ULong input_len )
+ {
+ FT_UNUSED( memory );
+ FT_UNUSED( output );
+ FT_UNUSED( output_len );
+ FT_UNUSED( input );
+ FT_UNUSED( input_len );
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+
+/* END */
diff --git a/src/gzip/infblock.c b/src/gzip/infblock.c
new file mode 100644
index 0000000..d6e2dc2
--- /dev/null
+++ b/src/gzip/infblock.c
@@ -0,0 +1,387 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset( /* s, z, c) */
+inflate_blocks_statef *s,
+z_streamp z,
+uLongf *c )
+{
+ if (c != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens);
+ if (s->mode == CODES)
+ inflate_codes_free(s->sub.decode.codes, z);
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+ Tracev((stderr, "inflate: blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */
+z_streamp z,
+check_func c,
+uInt w )
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->hufts =
+ (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Tracev((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, Z_NULL);
+ return s;
+}
+
+
+local int inflate_blocks( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Tracev((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl,
+ (const inflate_huft**)&td, z);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, s->hufts, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ }
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->bits;
+ c = h->base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td,
+ s->hufts, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ }
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok\n"));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ }
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return 0;
+#endif
+}
+
+
+local int inflate_blocks_free( /* s, z) */
+inflate_blocks_statef *s,
+z_streamp z )
+{
+ inflate_blocks_reset(s, z, Z_NULL);
+ ZFREE(z, s->window);
+ ZFREE(z, s->hufts);
+ ZFREE(z, s);
+ Tracev((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+
diff --git a/src/gzip/infblock.h b/src/gzip/infblock.h
new file mode 100644
index 0000000..c2535a1
--- /dev/null
+++ b/src/gzip/infblock.h
@@ -0,0 +1,36 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFBLOCK_H
+#define _INFBLOCK_H
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+local int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+local void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+local int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp));
+
+#endif /* _INFBLOCK_H */
diff --git a/src/gzip/infcodes.c b/src/gzip/infcodes.c
new file mode 100644
index 0000000..f7bfd58
--- /dev/null
+++ b/src/gzip/infcodes.c
@@ -0,0 +1,250 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ inflate_codes_mode mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */
+uInt bl, uInt bd,
+inflate_huft *tl,
+inflate_huft *td, /* need separate declaration for Borland C++ */
+z_streamp z )
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+local int inflate_codes( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+ f = q - c->sub.copy.dist;
+ while (f < s->window) /* modulo window size-"while" instead */
+ f += s->end - s->window; /* of "if" handles invalid distances */
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+local void inflate_codes_free( /* c, z) */
+inflate_codes_statef *c,
+z_streamp z )
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
diff --git a/src/gzip/infcodes.h b/src/gzip/infcodes.h
new file mode 100644
index 0000000..154d7f8
--- /dev/null
+++ b/src/gzip/infcodes.h
@@ -0,0 +1,31 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFCODES_H
+#define _INFCODES_H
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+local int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+local void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
+#endif /* _INFCODES_H */
diff --git a/src/gzip/inffixed.h b/src/gzip/inffixed.h
new file mode 100644
index 0000000..4d4760e
--- /dev/null
+++ b/src/gzip/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local const uInt fixed_bl = 9;
+local const uInt fixed_bd = 5;
+local const inflate_huft fixed_tl[] = {
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+ };
+local const inflate_huft fixed_td[] = {
+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+ };
diff --git a/src/gzip/inflate.c b/src/gzip/inflate.c
new file mode 100644
index 0000000..8877fa3
--- /dev/null
+++ b/src/gzip/inflate.c
@@ -0,0 +1,273 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+#define DONE INFLATE_DONE
+#define BAD INFLATE_BAD
+
+typedef enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ inflate_mode mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+ZEXPORT(int) inflateReset( /* z) */
+z_streamp z )
+{
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+ZEXPORT(int) inflateEnd( /* z) */
+z_streamp z )
+{
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */
+z_streamp z,
+int w,
+const char *version,
+int stream_size )
+{
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Tracev((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+
+#undef NEEDBYTE
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+
+#undef NEXTBYTE
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+
+ZEXPORT(int) inflate( /* z, f) */
+z_streamp z,
+int f )
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r == Z_OK)
+ r = f;
+ if (r != Z_STREAM_END)
+ return r;
+ r = f;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Tracev((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
diff --git a/src/gzip/inftrees.c b/src/gzip/inftrees.c
new file mode 100644
index 0000000..56f52b1
--- /dev/null
+++ b/src/gzip/inftrees.c
@@ -0,0 +1,468 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#if !defined(BUILDFIXED) && !defined(STDC)
+# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
+#endif
+
+
+#if 0
+local const char inflate_copyright[] =
+ " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
+#endif
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ const uIntf *, /* list of base values for non-simple codes */
+ const uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ inflate_huft *, /* space for trees */
+ uInt *, /* hufts used in space */
+ uIntf * )); /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+
+local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */
+uIntf *b, /* code lengths in bits (all assumed <= BMAX) */
+uInt n, /* number of codes (assumed <= 288) */
+uInt s, /* number of simple-valued codes (0..s-1) */
+const uIntf *d, /* list of base values for non-simple codes */
+const uIntf *e, /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t, /* result: starting table */
+uIntf *m, /* maximum lookup bits, returns actual */
+inflate_huft *hp, /* space for trees */
+uInt *hn, /* hufts used in space */
+uIntf *v /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), or Z_DATA_ERROR if the input is invalid. */
+)
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ uInt i; /* counter, current code */
+ uInt j; /* counter */
+ int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
+ uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Make compiler happy */
+ r.base = 0;
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate new table */
+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
+ return Z_DATA_ERROR; /* overflow of MANY */
+ u[h] = q = hp + *hn;
+ *hn += z;
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ j = i >> (w - l);
+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ else
+ *t = q; /* first table is returned result */
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */
+ while ((i & mask) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits( /* c, bb, tb, hp, z) */
+uIntf *c, /* 19 code lengths */
+uIntf *bb, /* bits tree desired/actual depth */
+inflate_huft * FAR *tb, /* bits tree result */
+inflate_huft *hp, /* space for trees */
+z_streamp z /* for messages */
+)
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+ tb, bb, hp, &hn, v);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+}
+
+
+local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */
+uInt nl, /* number of literal/length codes */
+uInt nd, /* number of distance codes */
+uIntf *c, /* that many (total) code lengths */
+uIntf *bl, /* literal desired/actual bit depth */
+uIntf *bd, /* distance desired/actual bit depth */
+inflate_huft * FAR *tl, /* literal/length tree result */
+inflate_huft * FAR *td, /* distance tree result */
+inflate_huft *hp, /* space for trees */
+z_streamp z /* for messages */
+)
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate work area */
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+ if (r != Z_OK || (*bd == 0 && nl > 257))
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed distance tree";
+ else if (r == Z_BUF_ERROR) {
+#if 0
+ {
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ z->msg = (char*)"incomplete distance tree";
+ r = Z_DATA_ERROR;
+ }
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"empty distance tree with lengths";
+ r = Z_DATA_ERROR;
+ }
+ ZFREE(z, v);
+ return r;
+#endif
+ }
+
+ /* done */
+ ZFREE(z, v);
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#ifdef BUILDFIXED
+local int fixed_built = 0;
+#define FIXEDH 544 /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+#else
+#include "inffixed.h"
+#endif
+
+
+local int inflate_trees_fixed( /* bl, bd, tl, td, z) */
+uIntf *bl, /* literal desired/actual bit depth */
+uIntf *bd, /* distance desired/actual bit depth */
+const inflate_huft * FAR *tl, /* literal/length tree result */
+const inflate_huft * FAR *td, /* distance tree result */
+z_streamp z /* for memory allocation */
+)
+{
+#ifdef BUILDFIXED
+ /* build fixed tables if not already */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ uInt f = 0; /* number of hufts used in fixed_mem */
+ uIntf *c; /* length list for huft_build */
+ uIntf *v; /* work area for huft_build */
+
+ /* allocate memory */
+ if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ return Z_MEM_ERROR;
+ if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+ {
+ ZFREE(z, c);
+ return Z_MEM_ERROR;
+ }
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 9;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
+ fixed_mem, &f, v);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
+ fixed_mem, &f, v);
+
+ /* done */
+ ZFREE(z, v);
+ ZFREE(z, c);
+ fixed_built = 1;
+ }
+#else
+ FT_UNUSED(z);
+#endif
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
diff --git a/src/gzip/inftrees.h b/src/gzip/inftrees.h
new file mode 100644
index 0000000..07bf2aa
--- /dev/null
+++ b/src/gzip/inftrees.h
@@ -0,0 +1,63 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit int's) */
+ uInt base; /* literal, length base, distance base,
+ or table offset */
+};
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1004 huft structures (850 for length/literals
+ and 154 for distances, the latter actually the result of an
+ exhaustive search). The actual maximum is not known, but the
+ value below is more than safe. */
+#define MANY 1440
+
+local int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+local int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+local int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ const inflate_huft * FAR *, /* literal/length tree result */
+ const inflate_huft * FAR *, /* distance tree result */
+ z_streamp)); /* for memory allocation */
+
+#endif /* _INFTREES_H */
diff --git a/src/gzip/infutil.c b/src/gzip/infutil.c
new file mode 100644
index 0000000..6087b40
--- /dev/null
+++ b/src/gzip/infutil.c
@@ -0,0 +1,86 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+
+/* And'ing with mask[n] masks the lower n bits */
+local const uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush( /* s, z, r) */
+inflate_blocks_statef *s,
+z_streamp z,
+int r )
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/src/gzip/infutil.h b/src/gzip/infutil.h
new file mode 100644
index 0000000..7174b6d
--- /dev/null
+++ b/src/gzip/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ inflate_huft *hufts; /* single malloc for tree space */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+#ifndef NO_INFLATE_MASK
+local uInt inflate_mask[17];
+#endif
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+#endif
diff --git a/src/gzip/zconf.h b/src/gzip/zconf.h
new file mode 100644
index 0000000..3abf0ba
--- /dev/null
+++ b/src/gzip/zconf.h
@@ -0,0 +1,284 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define compress2 z_compress2
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/* WinCE doesn't have errno.h */
+#ifdef _WIN32_WCE
+# define NO_ERRNO_H
+#endif
+
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
+# define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+# ifndef STDC
+# define STDC
+# endif
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C and LCC incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+# define NEED_DUMMY_RETURN
+#endif
+
+#if defined(__LCC__)
+# define NEED_DUMMY_RETURN
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR _far
+# endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+# if defined(_WINDOWS) || defined(WINDOWS)
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+# define ZEXPORT(x) x WINAPI
+# ifdef WIN32
+# define ZEXPORTVA(x) x WINAPIV
+# else
+# define ZEXPORTVA(x) x FAR _cdecl _export
+# endif
+# endif
+# if defined (__BORLANDC__)
+# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+# include <windows.h>
+# define ZEXPORT(x) x __declspec(dllexport) WINAPI
+# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV
+# else
+# if defined (_Windows) && defined (__DLL__)
+# define ZEXPORT(x) x _export
+# define ZEXPORTVA(x) x _export
+# endif
+# endif
+# endif
+#endif
+
+
+#ifndef ZEXPORT
+# define ZEXPORT(x) static x
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA(x) static x
+#endif
+#ifndef ZEXTERN
+# define ZEXTERN(x) static x
+#endif
+#ifndef ZEXTERNDEF
+# define ZEXTERNDEF(x) static x
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(inflate_blocks,"INBL")
+# pragma map(inflate_blocks_new,"INBLNE")
+# pragma map(inflate_blocks_free,"INBLFR")
+# pragma map(inflate_blocks_reset,"INBLRE")
+# pragma map(inflate_codes_free,"INCOFR")
+# pragma map(inflate_codes,"INCO")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_flush,"INFLU")
+# pragma map(inflate_mask,"INMA")
+# pragma map(inflate_set_dictionary,"INSEDI2")
+# pragma map(inflate_copyright,"INCOPY")
+# pragma map(inflate_trees_bits,"INTRBI")
+# pragma map(inflate_trees_dynamic,"INTRDY")
+# pragma map(inflate_trees_fixed,"INTRFI")
+# pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/src/gzip/zlib.h b/src/gzip/zlib.h
new file mode 100644
index 0000000..50d0d3f
--- /dev/null
+++ b/src/gzip/zlib.h
@@ -0,0 +1,830 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.4, March 11th, 2002
+
+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+
+ /* basic functions */
+
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN(int) deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN(int) inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN(int) inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+ZEXTERN(int) inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN(int) deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN(int) inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN(int) inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h". (See the description
+ of deflateInit2 for more information about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/src/gzip/zutil.c b/src/gzip/zutil.c
new file mode 100644
index 0000000..7ad0c1f
--- /dev/null
+++ b/src/gzip/zutil.c
@@ -0,0 +1,181 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC )
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* MSDOS && __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC )
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp ft_scalloc OF((uInt items, uInt size));
+extern void ft_sfree OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return (voidpf)ft_scalloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ ft_sfree(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/src/gzip/zutil.h b/src/gzip/zutil.h
new file mode 100644
index 0000000..c9688cd
--- /dev/null
+++ b/src/gzip/zutil.h
@@ -0,0 +1,215 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#ifdef MSDOS
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# endif
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+# define OS_CODE 0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0F
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# define fdopen(fd,type) _fdopen(fd,type)
+#endif
+
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) ft_fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#ifdef HAVE_STRERROR
+ extern char *strerror OF((int));
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy ft_memcpy
+# define zmemcmp ft_memcmp
+# define zmemzero(dest, len) ft_memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Bytef *buf,
+ uInt len));
+local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+local void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
deleted file mode 100644
index c19fceb..0000000
--- a/src/pfr/pfrload.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/***************************************************************************/
-/* */
-/* pfrload.c */
-/* */
-/* FreeType PFR loader (body). */
-/* */
-/* Copyright 2002-2005, 2007, 2009, 2010, 2013 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 "pfrload.h"
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-
-#include "pfrerror.h"
-
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_pfr
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** EXTRA ITEMS *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_extra_items_skip( FT_Byte* *pp,
- FT_Byte* limit )
- {
- return pfr_extra_items_parse( pp, limit, NULL, NULL );
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_extra_items_parse( FT_Byte* *pp,
- FT_Byte* limit,
- PFR_ExtraItem item_list,
- FT_Pointer item_data )
- {
- FT_Error error = FT_Err_Ok;
- FT_Byte* p = *pp;
- FT_UInt num_items, item_type, item_size;
-
-
- PFR_CHECK( 1 );
- num_items = PFR_NEXT_BYTE( p );
-
- for ( ; num_items > 0; num_items-- )
- {
- PFR_CHECK( 2 );
- item_size = PFR_NEXT_BYTE( p );
- item_type = PFR_NEXT_BYTE( p );
-
- PFR_CHECK( item_size );
-
- if ( item_list )
- {
- PFR_ExtraItem extra = item_list;
-
-
- for ( extra = item_list; extra->parser != NULL; extra++ )
- {
- if ( extra->type == item_type )
- {
- error = extra->parser( p, p + item_size, item_data );
- if ( error ) goto Exit;
-
- break;
- }
- }
- }
-
- p += item_size;
- }
-
- Exit:
- *pp = p;
- return error;
-
- Too_Short:
- FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
- error = FT_THROW( Invalid_Table );
- goto Exit;
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** PFR HEADER *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
- static const FT_Frame_Field pfr_header_fields[] =
- {
-#undef FT_STRUCTURE
-#define FT_STRUCTURE PFR_HeaderRec
-
- FT_FRAME_START( 58 ),
- FT_FRAME_ULONG ( signature ),
- FT_FRAME_USHORT( version ),
- FT_FRAME_USHORT( signature2 ),
- FT_FRAME_USHORT( header_size ),
-
- FT_FRAME_USHORT( log_dir_size ),
- FT_FRAME_USHORT( log_dir_offset ),
-
- FT_FRAME_USHORT( log_font_max_size ),
- FT_FRAME_UOFF3 ( log_font_section_size ),
- FT_FRAME_UOFF3 ( log_font_section_offset ),
-
- FT_FRAME_USHORT( phy_font_max_size ),
- FT_FRAME_UOFF3 ( phy_font_section_size ),
- FT_FRAME_UOFF3 ( phy_font_section_offset ),
-
- FT_FRAME_USHORT( gps_max_size ),
- FT_FRAME_UOFF3 ( gps_section_size ),
- FT_FRAME_UOFF3 ( gps_section_offset ),
-
- FT_FRAME_BYTE ( max_blue_values ),
- FT_FRAME_BYTE ( max_x_orus ),
- FT_FRAME_BYTE ( max_y_orus ),
-
- FT_FRAME_BYTE ( phy_font_max_size_high ),
- FT_FRAME_BYTE ( color_flags ),
-
- FT_FRAME_UOFF3 ( bct_max_size ),
- FT_FRAME_UOFF3 ( bct_set_max_size ),
- FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
-
- FT_FRAME_USHORT( num_phy_fonts ),
- FT_FRAME_BYTE ( max_vert_stem_snap ),
- FT_FRAME_BYTE ( max_horz_stem_snap ),
- FT_FRAME_USHORT( max_chars ),
- FT_FRAME_END
- };
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_header_load( PFR_Header header,
- FT_Stream stream )
- {
- FT_Error error;
-
-
- /* read header directly */
- if ( !FT_STREAM_SEEK( 0 ) &&
- !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
- {
- /* make a few adjustments to the header */
- header->phy_font_max_size +=
- (FT_UInt32)header->phy_font_max_size_high << 16;
- }
-
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_Bool )
- pfr_header_check( PFR_Header header )
- {
- FT_Bool result = 1;
-
-
- /* check signature and header size */
- if ( header->signature != 0x50465230L || /* "PFR0" */
- header->version > 4 ||
- header->header_size < 58 ||
- header->signature2 != 0x0d0a ) /* CR/LF */
- {
- result = 0;
- }
- return result;
- }
-
-
- /***********************************************************************/
- /***********************************************************************/
- /***** *****/
- /***** PFR LOGICAL FONTS *****/
- /***** *****/
- /***********************************************************************/
- /***********************************************************************/
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_log_font_count( FT_Stream stream,
- FT_UInt32 section_offset,
- FT_UInt *acount )
- {
- FT_Error error;
- FT_UInt count;
- FT_UInt result = 0;
-
-
- if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
- goto Exit;
-
- result = count;
-
- Exit:
- *acount = result;
- return error;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_log_font_load( PFR_LogFont log_font,
- FT_Stream stream,
- FT_UInt idx,
- FT_UInt32 section_offset,
- FT_Bool size_increment )
- {
- FT_UInt num_log_fonts;
- FT_UInt flags;
- FT_UInt32 offset;
- FT_UInt32 size;
- FT_Error error;
-
-
- if ( FT_STREAM_SEEK( section_offset ) ||
- FT_READ_USHORT( num_log_fonts ) )
- goto Exit;
-
- if ( idx >= num_log_fonts )
- return FT_THROW( Invalid_Argument );
-
- if ( FT_STREAM_SKIP( idx * 5 ) ||
- FT_READ_USHORT( size ) ||
- FT_READ_UOFF3 ( offset ) )
- goto Exit;
-
- /* save logical font size and offset */
- log_font->size = size;
- log_font->offset = offset;
-
- /* now, check the rest of the table before loading it */
- {
- FT_Byte* p;
- FT_Byte* limit;
- FT_UInt local;
-
-
- if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
- goto Exit;
-
- p = stream->cursor;
- limit = p + size;
-
- PFR_CHECK(13);
-
- log_font->matrix[0] = PFR_NEXT_LONG( p );
- log_font->matrix[1] = PFR_NEXT_LONG( p );
- log_font->matrix[2] = PFR_NEXT_LONG( p );
- log_font->matrix[3] = PFR_NEXT_LONG( p );
-
- flags = PFR_NEXT_BYTE( p );
-
- local = 0;
- if ( flags & PFR_LOG_STROKE )
- {
- local++;
- if ( flags & PFR_LOG_2BYTE_STROKE )
- local++;
-
- if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
- local += 3;
- }
- if ( flags & PFR_LOG_BOLD )
- {
- local++;
- if ( flags & PFR_LOG_2BYTE_BOLD )
- local++;
- }
-
- PFR_CHECK( local );
-
- if ( flags & PFR_LOG_STROKE )
- {
- log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
- ? PFR_NEXT_SHORT( p )
- : PFR_NEXT_BYTE( p );
-
- if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
- log_font->miter_limit = PFR_NEXT_LONG( p );
- }
-
- if ( flags & PFR_LOG_BOLD )
- {
- log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
- ? PFR_NEXT_SHORT( p )
- : PFR_NEXT_BYTE( p );
- }
-
- if ( flags & PFR_LOG_EXTRA_ITEMS )
- {
- error = pfr_extra_items_skip( &p, limit );
- if (error) goto Fail;
- }
-
- PFR_CHECK(5);
- log_font->phys_size = PFR_NEXT_USHORT( p );
- log_font->phys_offset = PFR_NEXT_ULONG( p );
- if ( size_increment )
- {
- PFR_CHECK( 1 );
- log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
- }
- }
-
- Fail:
- FT_FRAME_EXIT();
-
- Exit:
- return error;
-
- Too_Short:
- FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
- error = FT_THROW( Invalid_Table );
- goto Fail;
- }
-
-
- /***********************************************************************/
- /***********************************************************************/
- /***** *****/
- /***** PFR PHYSICAL FONTS *****/
- /***** *****/
- /***********************************************************************/
- /***********************************************************************/
-
-
- /* load bitmap strikes lists */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_bitmap_info( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_Memory memory = phy_font->memory;
- PFR_Strike strike;
- FT_UInt flags0;
- FT_UInt n, count, size1;
- FT_Error error = FT_Err_Ok;
-
-
- PFR_CHECK( 5 );
-
- p += 3; /* skip bctSize */
- flags0 = PFR_NEXT_BYTE( p );
- count = PFR_NEXT_BYTE( p );
-
- /* re-allocate when needed */
- if ( phy_font->num_strikes + count > phy_font->max_strikes )
- {
- FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
-
-
- if ( FT_RENEW_ARRAY( phy_font->strikes,
- phy_font->num_strikes,
- new_max ) )
- goto Exit;
-
- phy_font->max_strikes = new_max;
- }
-
- size1 = 1 + 1 + 1 + 2 + 2 + 1;
- if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
- size1++;
-
- if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
- size1++;
-
- if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
- size1++;
-
- if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
- size1++;
-
- if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
- size1++;
-
- strike = phy_font->strikes + phy_font->num_strikes;
-
- PFR_CHECK( count * size1 );
-
- for ( n = 0; n < count; n++, strike++ )
- {
- strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- strike->flags = PFR_NEXT_BYTE( p );
-
- strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
-
- strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
-
- strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
- }
-
- phy_font->num_strikes += count;
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_extra_item_load_bitmap_info:"
- " invalid bitmap info table\n" ));
- goto Exit;
- }
-
-
- /* Load font ID. This is a so-called "unique" name that is rather
- * long and descriptive (like "Tiresias ScreenFont v7.51").
- *
- * Note that a PFR font's family name is contained in an *undocumented*
- * string of the "auxiliary data" portion of a physical font record. This
- * may also contain the "real" style name!
- *
- * If no family name is present, the font ID is used instead for the
- * family.
- */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_font_id( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
- FT_PtrDist len = limit - p;
-
-
- if ( phy_font->font_id != NULL )
- goto Exit;
-
- if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
- goto Exit;
-
- /* copy font ID name, and terminate it for safety */
- FT_MEM_COPY( phy_font->font_id, p, len );
- phy_font->font_id[len] = 0;
-
- Exit:
- return error;
- }
-
-
- /* load stem snap tables */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_stem_snaps( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- FT_UInt count, num_vert, num_horz;
- FT_Int* snaps = NULL;
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
-
-
- if ( phy_font->vertical.stem_snaps != NULL )
- goto Exit;
-
- PFR_CHECK( 1 );
- count = PFR_NEXT_BYTE( p );
-
- num_vert = count & 15;
- num_horz = count >> 4;
- count = num_vert + num_horz;
-
- PFR_CHECK( count * 2 );
-
- if ( FT_NEW_ARRAY( snaps, count ) )
- goto Exit;
-
- phy_font->vertical.stem_snaps = snaps;
- phy_font->horizontal.stem_snaps = snaps + num_vert;
-
- for ( ; count > 0; count--, snaps++ )
- *snaps = FT_NEXT_SHORT( p );
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
- " invalid stem snaps table\n" ));
- goto Exit;
- }
-
-
-
- /* load kerning pair data */
- FT_CALLBACK_DEF( FT_Error )
- pfr_extra_item_load_kerning_pairs( FT_Byte* p,
- FT_Byte* limit,
- PFR_PhyFont phy_font )
- {
- PFR_KernItem item = NULL;
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = phy_font->memory;
-
-
- FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
-
- if ( FT_NEW( item ) )
- goto Exit;
-
- PFR_CHECK( 4 );
-
- item->pair_count = PFR_NEXT_BYTE( p );
- item->base_adj = PFR_NEXT_SHORT( p );
- item->flags = PFR_NEXT_BYTE( p );
- item->offset = phy_font->offset + ( p - phy_font->cursor );
-
-#ifndef PFR_CONFIG_NO_CHECKS
- item->pair_size = 3;
-
- if ( item->flags & PFR_KERN_2BYTE_CHAR )
- item->pair_size += 2;
-
- if ( item->flags & PFR_KERN_2BYTE_ADJ )
- item->pair_size += 1;
-
- PFR_CHECK( item->pair_count * item->pair_size );
-#endif
-
- /* load first and last pairs into the item to speed up */
- /* lookup later... */
- if ( item->pair_count > 0 )
- {
- FT_UInt char1, char2;
- FT_Byte* q;
-
-
- if ( item->flags & PFR_KERN_2BYTE_CHAR )
- {
- q = p;
- char1 = PFR_NEXT_USHORT( q );
- char2 = PFR_NEXT_USHORT( q );
-
- item->pair1 = PFR_KERN_INDEX( char1, char2 );
-
- q = p + item->pair_size * ( item->pair_count - 1 );
- char1 = PFR_NEXT_USHORT( q );
- char2 = PFR_NEXT_USHORT( q );
-
- item->pair2 = PFR_KERN_INDEX( char1, char2 );
- }
- else
- {
- q = p;
- char1 = PFR_NEXT_BYTE( q );
- char2 = PFR_NEXT_BYTE( q );
-
- item->pair1 = PFR_KERN_INDEX( char1, char2 );
-
- q = p + item->pair_size * ( item->pair_count - 1 );
- char1 = PFR_NEXT_BYTE( q );
- char2 = PFR_NEXT_BYTE( q );
-
- item->pair2 = PFR_KERN_INDEX( char1, char2 );
- }
-
- /* add new item to the current list */
- item->next = NULL;
- *phy_font->kern_items_tail = item;
- phy_font->kern_items_tail = &item->next;
- phy_font->num_kern_pairs += item->pair_count;
- }
- else
- {
- /* empty item! */
- FT_FREE( item );
- }
-
- Exit:
- return error;
-
- Too_Short:
- FT_FREE( item );
-
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_extra_item_load_kerning_pairs:"
- " invalid kerning pairs table\n" ));
- goto Exit;
- }
-
-
-
- static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
- {
- { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
- { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
- { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
- { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
- { 0, NULL }
- };
-
-
- /* Loads a name from the auxiliary data. Since this extracts undocumented
- * strings from the font file, we need to be careful here.
- */
- static FT_Error
- pfr_aux_name_load( FT_Byte* p,
- FT_UInt len,
- FT_Memory memory,
- FT_String* *astring )
- {
- FT_Error error = FT_Err_Ok;
- FT_String* result = NULL;
- FT_UInt n, ok;
-
-
- if ( len > 0 && p[len - 1] == 0 )
- len--;
-
- /* check that each character is ASCII for making sure not to
- load garbage
- */
- ok = ( len > 0 );
- for ( n = 0; n < len; n++ )
- if ( p[n] < 32 || p[n] > 127 )
- {
- ok = 0;
- break;
- }
-
- if ( ok )
- {
- if ( FT_ALLOC( result, len + 1 ) )
- goto Exit;
-
- FT_MEM_COPY( result, p, len );
- result[len] = 0;
- }
- Exit:
- *astring = result;
- return error;
- }
-
-
- FT_LOCAL_DEF( void )
- pfr_phy_font_done( PFR_PhyFont phy_font,
- FT_Memory memory )
- {
- FT_FREE( phy_font->font_id );
- FT_FREE( phy_font->family_name );
- FT_FREE( phy_font->style_name );
-
- FT_FREE( phy_font->vertical.stem_snaps );
- phy_font->vertical.num_stem_snaps = 0;
-
- phy_font->horizontal.stem_snaps = NULL;
- phy_font->horizontal.num_stem_snaps = 0;
-
- FT_FREE( phy_font->strikes );
- phy_font->num_strikes = 0;
- phy_font->max_strikes = 0;
-
- FT_FREE( phy_font->chars );
- phy_font->num_chars = 0;
- phy_font->chars_offset = 0;
-
- FT_FREE( phy_font->blue_values );
- phy_font->num_blue_values = 0;
-
- {
- PFR_KernItem item, next;
-
-
- item = phy_font->kern_items;
- while ( item )
- {
- next = item->next;
- FT_FREE( item );
- item = next;
- }
- phy_font->kern_items = NULL;
- phy_font->kern_items_tail = NULL;
- }
-
- phy_font->num_kern_pairs = 0;
- }
-
-
- FT_LOCAL_DEF( FT_Error )
- pfr_phy_font_load( PFR_PhyFont phy_font,
- FT_Stream stream,
- FT_UInt32 offset,
- FT_UInt32 size )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_UInt flags;
- FT_ULong num_aux;
- FT_Byte* p;
- FT_Byte* limit;
-
-
- phy_font->memory = memory;
- phy_font->offset = offset;
-
- phy_font->kern_items = NULL;
- phy_font->kern_items_tail = &phy_font->kern_items;
-
- if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
- goto Exit;
-
- phy_font->cursor = stream->cursor;
-
- p = stream->cursor;
- limit = p + size;
-
- PFR_CHECK( 15 );
- phy_font->font_ref_number = PFR_NEXT_USHORT( p );
- phy_font->outline_resolution = PFR_NEXT_USHORT( p );
- phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
- phy_font->bbox.xMin = PFR_NEXT_SHORT( p );
- phy_font->bbox.yMin = PFR_NEXT_SHORT( p );
- phy_font->bbox.xMax = PFR_NEXT_SHORT( p );
- phy_font->bbox.yMax = PFR_NEXT_SHORT( p );
- phy_font->flags = flags = PFR_NEXT_BYTE( p );
-
- /* get the standard advance for non-proportional fonts */
- if ( !(flags & PFR_PHY_PROPORTIONAL) )
- {
- PFR_CHECK( 2 );
- phy_font->standard_advance = PFR_NEXT_SHORT( p );
- }
-
- /* load the extra items when present */
- if ( flags & PFR_PHY_EXTRA_ITEMS )
- {
- error = pfr_extra_items_parse( &p, limit,
- pfr_phy_font_extra_items, phy_font );
-
- if ( error )
- goto Fail;
- }
-
- /* In certain fonts, the auxiliary bytes contain interesting */
- /* information. These are not in the specification but can be */
- /* guessed by looking at the content of a few PFR0 fonts. */
- PFR_CHECK( 3 );
- num_aux = PFR_NEXT_ULONG( p );
-
- if ( num_aux > 0 )
- {
- FT_Byte* q = p;
- FT_Byte* q2;
-
-
- PFR_CHECK( num_aux );
- p += num_aux;
-
- while ( num_aux > 0 )
- {
- FT_UInt length, type;
-
-
- if ( q + 4 > p )
- break;
-
- length = PFR_NEXT_USHORT( q );
- if ( length < 4 || length > num_aux )
- break;
-
- q2 = q + length - 2;
- type = PFR_NEXT_USHORT( q );
-
- switch ( type )
- {
- case 1:
- /* this seems to correspond to the font's family name,
- * padded to 16-bits with one zero when necessary
- */
- error = pfr_aux_name_load( q, length - 4U, memory,
- &phy_font->family_name );
- if ( error )
- goto Exit;
- break;
-
- case 2:
- if ( q + 32 > q2 )
- break;
-
- q += 10;
- phy_font->ascent = PFR_NEXT_SHORT( q );
- phy_font->descent = PFR_NEXT_SHORT( q );
- phy_font->leading = PFR_NEXT_SHORT( q );
- q += 16;
- break;
-
- case 3:
- /* this seems to correspond to the font's style name,
- * padded to 16-bits with one zero when necessary
- */
- error = pfr_aux_name_load( q, length - 4U, memory,
- &phy_font->style_name );
- if ( error )
- goto Exit;
- break;
-
- default:
- ;
- }
-
- q = q2;
- num_aux -= length;
- }
- }
-
- /* read the blue values */
- {
- FT_UInt n, count;
-
-
- PFR_CHECK( 1 );
- phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
-
- PFR_CHECK( count * 2 );
-
- if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
- goto Fail;
-
- for ( n = 0; n < count; n++ )
- phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
- }
-
- PFR_CHECK( 8 );
- phy_font->blue_fuzz = PFR_NEXT_BYTE( p );
- phy_font->blue_scale = PFR_NEXT_BYTE( p );
-
- phy_font->vertical.standard = PFR_NEXT_USHORT( p );
- phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
-
- /* read the character descriptors */
- {
- FT_UInt n, count, Size;
-
-
- phy_font->num_chars = count = PFR_NEXT_USHORT( p );
- phy_font->chars_offset = offset + ( p - stream->cursor );
-
- if ( FT_NEW_ARRAY( phy_font->chars, count ) )
- goto Fail;
-
- Size = 1 + 1 + 2;
- if ( flags & PFR_PHY_2BYTE_CHARCODE )
- Size += 1;
-
- if ( flags & PFR_PHY_PROPORTIONAL )
- Size += 2;
-
- if ( flags & PFR_PHY_ASCII_CODE )
- Size += 1;
-
- if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
- Size += 1;
-
- if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
- Size += 1;
-
- PFR_CHECK( count * Size );
-
- for ( n = 0; n < count; n++ )
- {
- PFR_Char cur = &phy_font->chars[n];
-
-
- cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- cur->advance = ( flags & PFR_PHY_PROPORTIONAL )
- ? PFR_NEXT_SHORT( p )
- : (FT_Int) phy_font->standard_advance;
-
-#if 0
- cur->ascii = ( flags & PFR_PHY_ASCII_CODE )
- ? PFR_NEXT_BYTE( p )
- : 0;
-#else
- if ( flags & PFR_PHY_ASCII_CODE )
- p += 1;
-#endif
- cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
- ? PFR_NEXT_USHORT( p )
- : PFR_NEXT_BYTE( p );
-
- cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
- ? PFR_NEXT_ULONG( p )
- : PFR_NEXT_USHORT( p );
- }
- }
-
- /* that's it! */
-
- Fail:
- FT_FRAME_EXIT();
-
- /* save position of bitmap info */
- phy_font->bct_offset = FT_STREAM_POS();
- phy_font->cursor = NULL;
-
- Exit:
- return error;
-
- Too_Short:
- error = FT_THROW( Invalid_Table );
- FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
- goto Fail;
- }
-
-
-/* END */
diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c
index 6a40e11..3ad44ec 100644
--- a/src/psaux/afmparse.c
+++ b/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
/* */
/* AFM parser (body). */
/* */
-/* Copyright 2006-2010, 2012, 2013 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -75,8 +75,8 @@
#define AFM_STREAM_KEY_BEGIN( stream ) \
(char*)( (stream)->cursor - 1 )
-#define AFM_STREAM_KEY_LEN( stream, key ) \
- ( (char*)(stream)->cursor - key - 1 )
+#define AFM_STREAM_KEY_LEN( stream, key ) \
+ (FT_Offset)( (char*)(stream)->cursor - key - 1 )
#define AFM_STATUS_EOC( stream ) \
( (stream)->status >= AFM_STREAM_STATUS_EOC )
@@ -369,11 +369,11 @@
FT_LOCAL_DEF( FT_Int )
afm_parser_read_vals( AFM_Parser parser,
AFM_Value vals,
- FT_UInt n )
+ FT_Int n )
{
AFM_Stream stream = parser->stream;
char* str;
- FT_UInt i;
+ FT_Int i;
if ( n > AFM_MAX_ARGUMENTS )
@@ -446,7 +446,7 @@
FT_Offset* len )
{
AFM_Stream stream = parser->stream;
- char* key = 0; /* make stupid compiler happy */
+ char* key = NULL; /* make stupid compiler happy */
if ( line )
@@ -562,7 +562,7 @@
}
- FT_LOCAL_DEF( FT_Error )
+ static FT_Error
afm_parser_read_int( AFM_Parser parser,
FT_Int* aint )
{
@@ -590,11 +590,17 @@
char* key;
FT_Offset len;
int n = -1;
+ FT_Int tmp;
- if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
+ if ( afm_parser_read_int( parser, &tmp ) )
goto Fail;
+ if ( tmp < 0 )
+ goto Fail;
+
+ fi->NumTrackKern = (FT_UInt)tmp;
+
if ( fi->NumTrackKern )
{
FT_Memory memory = parser->memory;
@@ -615,7 +621,7 @@
case AFM_TOKEN_TRACKKERN:
n++;
- if ( n >= fi->NumTrackKern )
+ if ( n >= (int)fi->NumTrackKern )
goto Fail;
tk = fi->TrackKerns + n;
@@ -639,7 +645,7 @@
case AFM_TOKEN_ENDTRACKKERN:
case AFM_TOKEN_ENDKERNDATA:
case AFM_TOKEN_ENDFONTMETRICS:
- fi->NumTrackKern = n + 1;
+ fi->NumTrackKern = (FT_UInt)( n + 1 );
return FT_Err_Ok;
case AFM_TOKEN_UNKNOWN:
@@ -688,11 +694,17 @@
char* key;
FT_Offset len;
int n = -1;
+ FT_Int tmp;
- if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
+ if ( afm_parser_read_int( parser, &tmp ) )
goto Fail;
+ if ( tmp < 0 )
+ goto Fail;
+
+ fi->NumKernPair = (FT_UInt)tmp;
+
if ( fi->NumKernPair )
{
FT_Memory memory = parser->memory;
@@ -720,7 +732,7 @@
n++;
- if ( n >= fi->NumKernPair )
+ if ( n >= (int)fi->NumKernPair )
goto Fail;
kp = fi->KernPairs + n;
@@ -733,8 +745,9 @@
if ( r < 3 )
goto Fail;
- kp->index1 = shared_vals[0].u.i;
- kp->index2 = shared_vals[1].u.i;
+ /* index values can't be negative */
+ kp->index1 = shared_vals[0].u.u;
+ kp->index2 = shared_vals[1].u.u;
if ( token == AFM_TOKEN_KPY )
{
kp->x = 0;
@@ -752,7 +765,7 @@
case AFM_TOKEN_ENDKERNPAIRS:
case AFM_TOKEN_ENDKERNDATA:
case AFM_TOKEN_ENDFONTMETRICS:
- fi->NumKernPair = n + 1;
+ fi->NumKernPair = (FT_UInt)( n + 1 );
ft_qsort( fi->KernPairs, fi->NumKernPair,
sizeof ( AFM_KernPairRec ),
afm_compare_kern_pairs );
@@ -815,7 +828,7 @@
static FT_Error
afm_parser_skip_section( AFM_Parser parser,
- FT_UInt n,
+ FT_Int n,
AFM_Token end_section )
{
char* key;
diff --git a/src/psaux/afmparse.h b/src/psaux/afmparse.h
index 35d9604..f922c4e 100644
--- a/src/psaux/afmparse.h
+++ b/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
/* */
/* AFM parser (specification). */
/* */
-/* Copyright 2006 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -61,6 +61,7 @@
char* s;
FT_Fixed f;
FT_Int i;
+ FT_UInt u;
FT_Bool b;
} u;
@@ -72,7 +73,7 @@
FT_LOCAL( FT_Int )
afm_parser_read_vals( AFM_Parser parser,
AFM_Value vals,
- FT_UInt n );
+ FT_Int n );
/* read the next key from the next line or column */
FT_LOCAL( char* )
diff --git a/src/psaux/psaux.c b/src/psaux/psaux.c
index a4b9c5c..7f1d9aa 100644
--- a/src/psaux/psaux.c
+++ b/src/psaux/psaux.c
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript driver component (body only). */
/* */
-/* Copyright 1996-2001, 2002, 2006 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/psauxerr.h b/src/psaux/psauxerr.h
index d52375f..97712f0 100644
--- a/src/psaux/psauxerr.h
+++ b/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
/* */
/* PS auxiliary module error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/psauxmod.c b/src/psaux/psauxmod.c
index 4b1249d..06fcab0 100644
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript module implementation (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2006 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/psauxmod.h b/src/psaux/psauxmod.h
index 1217236..ae6a8f9 100644
--- a/src/psaux/psauxmod.h
+++ b/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
/* */
/* FreeType auxiliary PostScript module implementation (specification). */
/* */
-/* Copyright 2000-2001 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
index d0d8861..aca7412 100644
--- a/src/psaux/psconv.c
+++ b/src/psaux/psconv.c
@@ -4,7 +4,7 @@
/* */
/* Some convenience conversions (body). */
/* */
-/* Copyright 2006, 2008, 2009, 2012-2013 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -124,7 +124,7 @@
if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
break;
- c = ft_char_table[*p & 0x7f];
+ c = ft_char_table[*p & 0x7F];
if ( c < 0 || c >= base )
break;
@@ -245,12 +245,13 @@
if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
break;
- c = ft_char_table[*p & 0x7f];
+ c = ft_char_table[*p & 0x7F];
if ( c < 0 || c >= 10 )
break;
- if ( decimal < 0xCCCCCCCL )
+ /* only add digit if we don't overflow */
+ if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
{
decimal = decimal * 10 + c;
@@ -488,8 +489,8 @@
if ( c OP 0x80 )
break;
- c = ft_char_table[c & 0x7F];
- if ( (unsigned)c >= 16 )
+ c = (FT_UInt)ft_char_table[c & 0x7F];
+ if ( c >= 16 )
break;
pad = ( pad << 4 ) | c;
@@ -520,7 +521,7 @@
if ( *p OP 0x80 )
break;
- c = ft_char_table[*p & 0x7f];
+ c = ft_char_table[*p & 0x7F];
if ( (unsigned)c >= 16 )
break;
diff --git a/src/psaux/psconv.h b/src/psaux/psconv.h
index d91c762..10f1ff7 100644
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -4,7 +4,7 @@
/* */
/* Some convenience conversions (specification). */
/* */
-/* Copyright 2006, 2012 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index dd976d3..1d3c7e6 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -81,7 +81,7 @@
table->max_elems = count;
table->init = 0xDEADBEEFUL;
table->num_elems = 0;
- table->block = 0;
+ table->block = NULL;
table->capacity = 0;
table->cursor = 0;
@@ -165,10 +165,10 @@
/* reallocation fails. */
/* */
FT_LOCAL_DEF( FT_Error )
- ps_table_add( PS_Table table,
- FT_Int idx,
- void* object,
- FT_PtrDist length )
+ ps_table_add( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_UInt length )
{
if ( idx < 0 || idx >= table->max_elems )
{
@@ -176,12 +176,6 @@
return FT_THROW( Invalid_Argument );
}
- if ( length < 0 )
- {
- FT_ERROR(( "ps_table_add: invalid length\n" ));
- return FT_THROW( Invalid_Argument );
- }
-
/* grow the base block if needed */
if ( table->cursor + length > table->capacity )
{
@@ -600,6 +594,9 @@
error = FT_THROW( Invalid_File_Format );
}
+ if ( cur > limit )
+ cur = limit;
+
parser->error = error;
parser->cursor = cur;
}
@@ -625,8 +622,8 @@
token->type = T1_TOKEN_TYPE_NONE;
- token->start = 0;
- token->limit = 0;
+ token->start = NULL;
+ token->limit = NULL;
/* first of all, skip leading whitespace */
ps_parser_skip_spaces( parser );
@@ -707,7 +704,7 @@
if ( !token->limit )
{
- token->start = 0;
+ token->start = NULL;
token->type = T1_TOKEN_TYPE_NONE;
}
@@ -847,6 +844,8 @@
/* first character must be a delimiter or a part of a number */
/* NB: `values' can be NULL if we just want to skip the */
/* array; in this case we ignore `max_values' */
+ /* */
+ /* return number of successfully parsed values */
static FT_Int
ps_tofixedarray( FT_Byte* *acur,
@@ -930,7 +929,7 @@
FT_Memory memory )
{
FT_Byte* cur = *cursor;
- FT_PtrDist len = 0;
+ FT_UInt len = 0;
FT_Int count;
FT_String* result;
FT_Error error;
@@ -970,7 +969,7 @@
}
}
- len = cur - *cursor;
+ len = (FT_UInt)( cur - *cursor );
if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
return 0;
@@ -1200,7 +1199,7 @@
result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
- if ( result < 0 )
+ if ( result < 4 )
{
FT_ERROR(( "ps_parser_load_field:"
" expected four integers in bounding box\n" ));
@@ -1228,20 +1227,22 @@
for ( i = 0; i < 4; i++ )
{
- result = ps_tofixedarray( &cur, limit, max_objects,
+ result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects,
temp + i * max_objects, 0 );
- if ( result < 0 )
+ if ( result < 0 || (FT_UInt)result < max_objects )
{
FT_ERROR(( "ps_parser_load_field:"
- " expected %d integers in the %s subarray\n"
+ " expected %d integer%s in the %s subarray\n"
" "
" of /FontBBox in the /Blend dictionary\n",
- max_objects,
+ max_objects, max_objects > 1 ? "s" : "",
i == 0 ? "first"
: ( i == 1 ? "second"
: ( i == 2 ? "third"
: "fourth" ) ) ));
error = FT_THROW( Invalid_File_Format );
+
+ FT_FREE( temp );
goto Exit;
}
@@ -1319,7 +1320,7 @@
goto Exit;
}
if ( (FT_UInt)num_elements > field->array_max )
- num_elements = field->array_max;
+ num_elements = (FT_Int)field->array_max;
old_cursor = parser->cursor;
old_limit = parser->limit;
@@ -1336,7 +1337,15 @@
{
parser->cursor = token->start;
parser->limit = token->limit;
- ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
+
+ error = ps_parser_load_field( parser,
+ &fieldrec,
+ objects,
+ max_objects,
+ 0 );
+ if ( error )
+ break;
+
fieldrec.offset += fieldrec.size;
}
@@ -1369,7 +1378,7 @@
ps_parser_to_bytes( PS_Parser parser,
FT_Byte* bytes,
FT_Offset max_bytes,
- FT_Long* pnum_bytes,
+ FT_ULong* pnum_bytes,
FT_Bool delimiters )
{
FT_Error error = FT_Err_Ok;
@@ -1543,7 +1552,7 @@
FT_GlyphLoader_Rewind( loader );
builder->hints_globals = size->internal;
- builder->hints_funcs = 0;
+ builder->hints_funcs = NULL;
if ( hinting )
builder->hints_funcs = glyph->internal->glyph_hints;
diff --git a/src/psaux/psobjs.h b/src/psaux/psobjs.h
index e380c60..bf879c1 100644
--- a/src/psaux/psobjs.h
+++ b/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,10 +52,10 @@
FT_Memory memory );
FT_LOCAL( FT_Error )
- ps_table_add( PS_Table table,
- FT_Int idx,
- void* object,
- FT_PtrDist length );
+ ps_table_add( PS_Table table,
+ FT_Int idx,
+ void* object,
+ FT_UInt length );
FT_LOCAL( void )
ps_table_done( PS_Table table );
@@ -112,7 +112,7 @@
ps_parser_to_bytes( PS_Parser parser,
FT_Byte* bytes,
FT_Offset max_bytes,
- FT_Long* pnum_bytes,
+ FT_ULong* pnum_bytes,
FT_Bool delimiters );
diff --git a/src/psaux/t1cmap.c b/src/psaux/t1cmap.c
index 9e5bd34..2e2d433 100644
--- a/src/psaux/t1cmap.c
+++ b/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
/* */
/* Type 1 character map support (body). */
/* */
-/* Copyright 2002, 2003, 2006, 2007, 2012 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -39,7 +39,7 @@
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
- cmap->num_glyphs = face->type1.num_glyphs;
+ cmap->num_glyphs = (FT_UInt)face->type1.num_glyphs;
cmap->glyph_names = (const char* const*)face->type1.glyph_names;
cmap->sid_to_string = psnames->adobe_std_strings;
cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding
@@ -120,8 +120,12 @@
FT_CALLBACK_DEF( FT_Error )
- t1_cmap_standard_init( T1_CMapStd cmap )
+ t1_cmap_standard_init( T1_CMapStd cmap,
+ FT_Pointer pointer )
{
+ FT_UNUSED( pointer );
+
+
t1_cmap_std_init( cmap, 0 );
return 0;
}
@@ -142,8 +146,12 @@
FT_CALLBACK_DEF( FT_Error )
- t1_cmap_expert_init( T1_CMapStd cmap )
+ t1_cmap_expert_init( T1_CMapStd cmap,
+ FT_Pointer pointer )
{
+ FT_UNUSED( pointer );
+
+
t1_cmap_std_init( cmap, 1 );
return 0;
}
@@ -172,14 +180,17 @@
FT_CALLBACK_DEF( FT_Error )
- t1_cmap_custom_init( T1_CMapCustom cmap )
+ t1_cmap_custom_init( T1_CMapCustom cmap,
+ FT_Pointer pointer )
{
T1_Face face = (T1_Face)FT_CMAP_FACE( cmap );
T1_Encoding encoding = &face->type1.encoding;
+ FT_UNUSED( pointer );
- cmap->first = encoding->code_first;
- cmap->count = (FT_UInt)( encoding->code_last - cmap->first );
+
+ cmap->first = (FT_UInt)encoding->code_first;
+ cmap->count = (FT_UInt)encoding->code_last - cmap->first;
cmap->indices = encoding->char_index;
FT_ASSERT( cmap->indices != NULL );
@@ -272,16 +283,19 @@
FT_CALLBACK_DEF( FT_Error )
- t1_cmap_unicode_init( PS_Unicodes unicodes )
+ t1_cmap_unicode_init( PS_Unicodes unicodes,
+ FT_Pointer pointer )
{
T1_Face face = (T1_Face)FT_CMAP_FACE( unicodes );
FT_Memory memory = FT_FACE_MEMORY( face );
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames;
+ FT_UNUSED( pointer );
+
return psnames->unicodes_init( memory,
unicodes,
- face->type1.num_glyphs,
+ (FT_UInt)face->type1.num_glyphs,
(PS_GetGlyphNameFunc)&psaux_get_glyph_name,
(PS_FreeGlyphNameFunc)NULL,
(FT_Pointer)face );
diff --git a/src/psaux/t1cmap.h b/src/psaux/t1cmap.h
index 7ae65d2..b8ba06c 100644
--- a/src/psaux/t1cmap.h
+++ b/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
/* */
/* Type 1 character map support (specification). */
/* */
-/* Copyright 2002, 2003, 2006 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 6ce370b..5811fcb 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
/* */
/* PostScript Type 1 decoding routines (body). */
/* */
-/* Copyright 2000-2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -150,7 +150,7 @@
if ( name &&
name[0] == glyph_name[0] &&
ft_strcmp( name, glyph_name ) == 0 )
- return n;
+ return (FT_Int)n;
}
return -1;
@@ -298,7 +298,7 @@
/* the seac operator must not be nested */
decoder->seac = TRUE;
- error = t1_decoder_parse_glyph( decoder, bchar_index );
+ error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
decoder->seac = FALSE;
if ( error )
goto Exit;
@@ -320,7 +320,7 @@
/* the seac operator must not be nested */
decoder->seac = TRUE;
- error = t1_decoder_parse_glyph( decoder, achar_index );
+ error = t1_decoder_parse_glyph( decoder, (FT_UInt)achar_index );
decoder->seac = FALSE;
if ( error )
goto Exit;
@@ -381,10 +381,10 @@
/* compute random seed from stack address of parameter */
- seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
- (FT_PtrDist)(char*)&decoder ^
- (FT_PtrDist)(char*)&charstring_base ) &
- FT_ULONG_MAX ) ;
+ seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^
+ (FT_Offset)(char*)&decoder ^
+ (FT_Offset)(char*)&charstring_base ) &
+ FT_ULONG_MAX );
seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
if ( seed == 0 )
seed = 0x7384;
@@ -512,7 +512,7 @@
break;
case 12:
- if ( ip > limit )
+ if ( ip >= limit )
{
FT_ERROR(( "t1_decoder_parse_charstrings:"
" invalid escape (12+EOF)\n" ));
@@ -669,7 +669,7 @@
if ( large_int )
FT_TRACE4(( " %ld", value ));
else
- FT_TRACE4(( " %ld", Fix2Int( value ) ));
+ FT_TRACE4(( " %ld", value / 65536 ));
#endif
*top++ = value;
@@ -796,7 +796,8 @@
known_othersubr_result_cnt = 1;
if ( hinter )
- hinter->reset( hinter->hints, builder->current->n_points );
+ hinter->reset( hinter->hints,
+ (FT_UInt)builder->current->n_points );
break;
case 12:
@@ -861,7 +862,7 @@
*values++ = tmp;
}
- known_othersubr_result_cnt = num_points;
+ known_othersubr_result_cnt = (FT_Int)num_points;
break;
}
@@ -879,8 +880,8 @@
idx = Fix2Int( top[0] );
- if ( idx < 0 ||
- idx + blend->num_designs > decoder->len_buildchar )
+ if ( idx < 0 ||
+ (FT_UInt)idx + blend->num_designs > decoder->len_buildchar )
goto Unexpected_OtherSubr;
ft_memcpy( &decoder->buildchar[idx],
@@ -1094,14 +1095,17 @@
/* close hints recording session */
if ( hinter )
{
- if ( hinter->close( hinter->hints, builder->current->n_points ) )
+ if ( hinter->close( hinter->hints,
+ (FT_UInt)builder->current->n_points ) )
goto Syntax_Error;
/* apply hints to the loaded glyph outline now */
- hinter->apply( hinter->hints,
- builder->current,
- (PSH_Globals)builder->hints_globals,
- decoder->hint_mode );
+ error = hinter->apply( hinter->hints,
+ builder->current,
+ (PSH_Globals)builder->hints_globals,
+ decoder->hint_mode );
+ if ( error )
+ goto Fail;
}
/* add current outline to the glyph slot */
@@ -1344,7 +1348,7 @@
FT_TRACE4(( " callsubr" ));
idx = Fix2Int( top[0] );
- if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
+ if ( idx < 0 || idx >= decoder->num_subrs )
{
FT_ERROR(( "t1_decoder_parse_charstrings:"
" invalid subrs index\n" ));
@@ -1577,7 +1581,7 @@
/* retrieve PSNames interface from list of current modules */
{
- FT_Service_PsCMaps psnames = 0;
+ FT_Service_PsCMaps psnames;
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
diff --git a/src/psaux/t1decode.h b/src/psaux/t1decode.h
index 00728db..e83078f 100644
--- a/src/psaux/t1decode.h
+++ b/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
/* */
/* PostScript Type 1 decoding routines (specification). */
/* */
-/* Copyright 2000-2001, 2002, 2003 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index 343472d..6e654cb 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
/* */
/* PostScript hinting algorithm (body). */
/* */
-/* Copyright 2001-2010, 2012, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -30,16 +30,14 @@
#ifdef DEBUG_HINTER
- PSH_Hint_Table ps_debug_hint_table = 0;
- PSH_HintFunc ps_debug_hint_func = 0;
- PSH_Glyph ps_debug_glyph = 0;
+ PSH_Hint_Table ps_debug_hint_table = NULL;
+ PSH_HintFunc ps_debug_hint_func = NULL;
+ PSH_Glyph ps_debug_glyph = NULL;
#endif
#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */
/* and similar glyphs */
-#define STRONGER /* slightly increase the contrast of smooth */
- /* hinting */
/*************************************************************************/
@@ -67,13 +65,13 @@
{
FT_FREE( table->zones );
table->num_zones = 0;
- table->zone = 0;
+ table->zone = NULL;
FT_FREE( table->sort );
FT_FREE( table->hints );
table->num_hints = 0;
table->max_hints = 0;
- table->sort_global = 0;
+ table->sort_global = NULL;
}
@@ -121,7 +119,7 @@
PSH_Hint hint2;
- hint->parent = 0;
+ hint->parent = NULL;
for ( ; count > 0; count--, sorted++ )
{
hint2 = sorted[0];
@@ -194,7 +192,7 @@
table->sort_global = table->sort + count;
table->num_hints = 0;
table->num_zones = 0;
- table->zone = 0;
+ table->zone = NULL;
/* initialize the `table->hints' array */
{
@@ -890,9 +888,6 @@
/*************************************************************************/
/*************************************************************************/
-#define PSH_ZONE_MIN -3200000L
-#define PSH_ZONE_MAX +3200000L
-
#define xxDEBUG_ZONES
@@ -910,10 +905,6 @@
zone->max );
}
-#else
-
-#define psh_print_zone( x ) do { } while ( 0 )
-
#endif /* DEBUG_ZONES */
@@ -925,103 +916,9 @@
/*************************************************************************/
/*************************************************************************/
-#if 1
-
#define psh_corner_is_flat ft_corner_is_flat
#define psh_corner_orientation ft_corner_orientation
-#else
-
- FT_LOCAL_DEF( FT_Int )
- psh_corner_is_flat( FT_Pos x_in,
- FT_Pos y_in,
- FT_Pos x_out,
- FT_Pos y_out )
- {
- FT_Pos ax = x_in;
- FT_Pos ay = y_in;
-
- FT_Pos d_in, d_out, d_corner;
-
-
- if ( ax < 0 )
- ax = -ax;
- if ( ay < 0 )
- ay = -ay;
- d_in = ax + ay;
-
- ax = x_out;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out;
- if ( ay < 0 )
- ay = -ay;
- d_out = ax + ay;
-
- ax = x_out + x_in;
- if ( ax < 0 )
- ax = -ax;
- ay = y_out + y_in;
- if ( ay < 0 )
- ay = -ay;
- d_corner = ax + ay;
-
- return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
- }
-
- static FT_Int
- psh_corner_orientation( FT_Pos in_x,
- FT_Pos in_y,
- FT_Pos out_x,
- FT_Pos out_y )
- {
- FT_Int result;
-
-
- /* deal with the trivial cases quickly */
- if ( in_y == 0 )
- {
- if ( in_x >= 0 )
- result = out_y;
- else
- result = -out_y;
- }
- else if ( in_x == 0 )
- {
- if ( in_y >= 0 )
- result = -out_x;
- else
- result = out_x;
- }
- else if ( out_y == 0 )
- {
- if ( out_x >= 0 )
- result = in_y;
- else
- result = -in_y;
- }
- else if ( out_x == 0 )
- {
- if ( out_y >= 0 )
- result = -in_x;
- else
- result = in_x;
- }
- else /* general case */
- {
- long long delta = (long long)in_x * out_y - (long long)in_y * out_x;
-
- if ( delta == 0 )
- result = 0;
- else
- result = 1 - 2 * ( delta < 0 );
- }
-
- return result;
- }
-
-#endif /* !1 */
-
#ifdef COMPUTE_INFLEXS
@@ -1149,7 +1046,7 @@
glyph->num_points = 0;
glyph->num_contours = 0;
- glyph->memory = 0;
+ glyph->memory = NULL;
}
@@ -1274,8 +1171,8 @@
FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
goto Exit;
- glyph->num_points = outline->n_points;
- glyph->num_contours = outline->n_contours;
+ glyph->num_points = (FT_UInt)outline->n_points;
+ glyph->num_contours = (FT_UInt)outline->n_contours;
{
FT_UInt first = 0, next, n;
@@ -1285,15 +1182,15 @@
for ( n = 0; n < glyph->num_contours; n++ )
{
- FT_Int count;
+ FT_UInt count;
PSH_Point point;
- next = outline->contours[n] + 1;
+ next = (FT_UInt)outline->contours[n] + 1;
count = next - first;
contour->start = points + first;
- contour->count = (FT_UInt)count;
+ contour->count = count;
if ( count > 0 )
{
@@ -1406,7 +1303,6 @@
point = first;
before = point;
- after = point;
do
{
@@ -1697,16 +1593,12 @@
mask++;
for ( ; num_masks > 1; num_masks--, mask++ )
{
- FT_UInt next;
- FT_Int count;
+ FT_UInt next = FT_MIN( mask->end_point, glyph->num_points );
- next = mask->end_point > glyph->num_points
- ? glyph->num_points
- : mask->end_point;
- count = next - first;
- if ( count > 0 )
+ if ( next > first )
{
+ FT_UInt count = next - first;
PSH_Point point = glyph->points + first;
@@ -2049,7 +1941,7 @@
/* count the number of strong points in this contour */
next = start + contour->count;
fit_count = 0;
- first = 0;
+ first = NULL;
for ( point = start; point < next; point++ )
if ( psh_point_is_fitted( point ) )
@@ -2079,8 +1971,6 @@
start = first;
do
{
- point = first;
-
/* skip consecutive fitted points */
for (;;)
{
diff --git a/src/pshinter/pshalgo.h b/src/pshinter/pshalgo.h
index c70f31e..8373e5e 100644
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinting algorithm (specification). */
/* */
-/* Copyright 2001-2003, 2008, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -30,15 +30,12 @@
/* handle to Hint structure */
typedef struct PSH_HintRec_* PSH_Hint;
- /* hint bit-flags */
- typedef enum PSH_Hint_Flags_
- {
- PSH_HINT_GHOST = PS_HINT_FLAG_GHOST,
- PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
- PSH_HINT_ACTIVE = 4,
- PSH_HINT_FITTED = 8
- } PSH_Hint_Flags;
+ /* hint bit-flags */
+#define PSH_HINT_GHOST PS_HINT_FLAG_GHOST
+#define PSH_HINT_BOTTOM PS_HINT_FLAG_BOTTOM
+#define PSH_HINT_ACTIVE 4U
+#define PSH_HINT_FITTED 8U
#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )
@@ -49,6 +46,7 @@
#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE
#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED
+
/* hint structure */
typedef struct PSH_HintRec_
{
@@ -112,14 +110,12 @@
#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
- /* the following bit-flags are computed once by the glyph */
- /* analyzer, for both dimensions */
- enum
- {
- PSH_POINT_OFF = 1, /* point is off the curve */
- PSH_POINT_SMOOTH = 2, /* point is smooth */
- PSH_POINT_INFLEX = 4 /* point is inflection */
- };
+ /* the following bit-flags are computed once by the glyph */
+ /* analyzer, for both dimensions */
+#define PSH_POINT_OFF 1U /* point is off the curve */
+#define PSH_POINT_SMOOTH 2U /* point is smooth */
+#define PSH_POINT_INFLEX 4U /* point is inflection */
+
#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH )
#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF )
@@ -129,17 +125,16 @@
#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF
#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX
+
/* the following bit-flags are re-computed for each dimension */
- enum
- {
- PSH_POINT_STRONG = 16, /* point is strong */
- PSH_POINT_FITTED = 32, /* point is already fitted */
- PSH_POINT_EXTREMUM = 64, /* point is local extremum */
- PSH_POINT_POSITIVE = 128, /* extremum has positive contour flow */
- PSH_POINT_NEGATIVE = 256, /* extremum has negative contour flow */
- PSH_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */
- PSH_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */
- };
+#define PSH_POINT_STRONG 16U /* point is strong */
+#define PSH_POINT_FITTED 32U /* point is already fitted */
+#define PSH_POINT_EXTREMUM 64U /* point is local extremum */
+#define PSH_POINT_POSITIVE 128U /* extremum has positive contour flow */
+#define PSH_POINT_NEGATIVE 256U /* extremum has negative contour flow */
+#define PSH_POINT_EDGE_MIN 512U /* point is aligned to left/bottom stem edge */
+#define PSH_POINT_EDGE_MAX 1024U /* point is aligned to top/right stem edge */
+
#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG )
#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED )
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 9285efc..4616bdc 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
/* PostScript hinter global hinting management (body). */
/* Inspired by the new auto-hinter module. */
/* */
-/* Copyright 2001-2004, 2006, 2010, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -23,7 +23,7 @@
#include "pshglob.h"
#ifdef DEBUG_HINTER
- PSH_Globals ps_debug_globals = 0;
+ PSH_Globals ps_debug_globals = NULL;
#endif
@@ -240,7 +240,7 @@
FT_Int family )
{
PSH_Blue_Table top_table, bot_table;
- FT_Int count_top, count_bot;
+ FT_UInt count_top, count_bot;
if ( family )
@@ -339,7 +339,7 @@
bot = zone[1].org_bottom;
delta = bot - top;
- if ( delta < 2 * fuzz )
+ if ( delta / 2 < fuzz )
zone[0].org_top = zone[1].org_bottom = top + delta / 2;
else
{
@@ -369,7 +369,7 @@
{
FT_UInt count;
FT_UInt num;
- PSH_Blue_Table table = 0;
+ PSH_Blue_Table table = NULL;
/* */
/* Determine whether we need to suppress overshoots or */
@@ -635,7 +635,7 @@
FT_FREE( globals );
#ifdef DEBUG_HINTER
- ps_debug_globals = 0;
+ ps_debug_globals = NULL;
#endif
}
}
@@ -750,14 +750,14 @@
}
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
psh_globals_set_scale( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed y_scale,
FT_Fixed x_delta,
FT_Fixed y_delta )
{
- PSH_Dimension dim = &globals->dimension[0];
+ PSH_Dimension dim;
dim = &globals->dimension[0];
@@ -780,8 +780,6 @@
psh_globals_scale_widths( globals, 1 );
psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
}
-
- return 0;
}
diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h
index c511626..c376df7 100644
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinter global hinting management. */
/* */
-/* Copyright 2001, 2002, 2003 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -167,7 +167,7 @@
FT_Int org_width );
#endif
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
psh_globals_set_scale( PSH_Globals globals,
FT_Fixed x_scale,
FT_Fixed y_scale,
diff --git a/src/pshinter/pshinter.c b/src/pshinter/pshinter.c
index b35a2a9..9e65fe2 100644
--- a/src/pshinter/pshinter.c
+++ b/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript Hinting module */
/* */
-/* Copyright 2001, 2003 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshmod.c b/src/pshinter/pshmod.c
index cdeaca1..961b468 100644
--- a/src/pshinter/pshmod.c
+++ b/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript hinter module implementation (body). */
/* */
-/* Copyright 2001, 2002, 2007, 2009, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshmod.h b/src/pshinter/pshmod.h
index 0ae7e96..a58d856 100644
--- a/src/pshinter/pshmod.h
+++ b/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
/* */
/* PostScript hinter module interface (specification). */
/* */
-/* Copyright 2001 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshnterr.h b/src/pshinter/pshnterr.h
index 7cc180f..ce790a8 100644
--- a/src/pshinter/pshnterr.h
+++ b/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
/* */
/* PS Hinter error codes (specification only). */
/* */
-/* Copyright 2003, 2012 by */
+/* Copyright 2003-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshpic.c b/src/pshinter/pshpic.c
index 568f4ac..afd8fb9 100644
--- a/src/pshinter/pshpic.c
+++ b/src/pshinter/pshpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/pshinter/pshpic.h b/src/pshinter/pshpic.h
index b46f853..ca35cd6 100644
--- a/src/pshinter/pshpic.h
+++ b/src/pshinter/pshpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for pshinter module. */
/* */
-/* Copyright 2009, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,8 +20,6 @@
#define __PSHPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -33,6 +31,8 @@
#include FT_INTERNAL_POSTSCRIPT_HINTS_H
+FT_BEGIN_HEADER
+
typedef struct PSHinterPIC_
{
PSHinter_Interface pshinter_interface;
@@ -51,12 +51,12 @@
FT_Error
pshinter_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __PSHPIC_H__ */
diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c
index cd66ea8..f8895fc 100644
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PostScript hints recorder (body). */
/* */
-/* Copyright 2001-2004, 2007, 2009, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,7 +31,7 @@
#define FT_COMPONENT trace_pshrec
#ifdef DEBUG_HINTER
- PS_Hints ps_debug_hints = 0;
+ PS_Hints ps_debug_hints = NULL;
int ps_debug_no_horz_hints = 0;
int ps_debug_no_vert_hints = 0;
#endif
@@ -85,7 +85,7 @@
{
FT_Error error = FT_Err_Ok;
FT_UInt count;
- PS_Hint hint = 0;
+ PS_Hint hint = NULL;
count = table->num_hints;
@@ -167,12 +167,12 @@
/* clear a given bit */
static void
ps_mask_clear_bit( PS_Mask mask,
- FT_Int idx )
+ FT_UInt idx )
{
FT_Byte* p;
- if ( (FT_UInt)idx >= mask->num_bits )
+ if ( idx >= mask->num_bits )
return;
p = mask->bytes + ( idx >> 3 );
@@ -183,17 +183,14 @@
/* set a given bit, possibly grow the mask */
static FT_Error
ps_mask_set_bit( PS_Mask mask,
- FT_Int idx,
+ FT_UInt idx,
FT_Memory memory )
{
FT_Error error = FT_Err_Ok;
FT_Byte* p;
- if ( idx < 0 )
- goto Exit;
-
- if ( (FT_UInt)idx >= mask->num_bits )
+ if ( idx >= mask->num_bits )
{
error = ps_mask_ensure( mask, idx + 1, memory );
if ( error )
@@ -257,7 +254,7 @@
{
FT_UInt count;
FT_Error error = FT_Err_Ok;
- PS_Mask mask = 0;
+ PS_Mask mask = NULL;
count = table->num_masks;
@@ -372,8 +369,8 @@
/* test whether two masks in a table intersect */
static FT_Int
ps_mask_table_test_intersect( PS_Mask_Table table,
- FT_Int index1,
- FT_Int index2 )
+ FT_UInt index1,
+ FT_UInt index2 )
{
PS_Mask mask1 = table->masks + index1;
PS_Mask mask2 = table->masks + index2;
@@ -404,23 +401,25 @@
/* merge two masks, used by ps_mask_table_merge_all */
static FT_Error
ps_mask_table_merge( PS_Mask_Table table,
- FT_Int index1,
- FT_Int index2,
+ FT_UInt index1,
+ FT_UInt index2,
FT_Memory memory )
{
- FT_UInt temp;
FT_Error error = FT_Err_Ok;
/* swap index1 and index2 so that index1 < index2 */
if ( index1 > index2 )
{
+ FT_UInt temp;
+
+
temp = index1;
index1 = index2;
index2 = temp;
}
- if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
+ if ( index1 < index2 && index2 < table->num_masks )
{
/* we need to merge the bitsets of index1 and index2 with a */
/* simple union */
@@ -453,7 +452,7 @@
/* merge (unite) the bitsets */
read = mask2->bytes;
write = mask1->bytes;
- pos = (FT_UInt)( ( count2 + 7 ) >> 3 );
+ pos = ( count2 + 7 ) >> 3;
for ( ; pos > 0; pos-- )
{
@@ -468,14 +467,17 @@
mask2->num_bits = 0;
mask2->end_point = 0;
- delta = table->num_masks - 1 - index2; /* number of masks to move */
+ /* number of masks to move */
+ delta = (FT_Int)( table->num_masks - 1 - index2 );
if ( delta > 0 )
{
/* move to end of table for reuse */
PS_MaskRec dummy = *mask2;
- ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
+ ft_memmove( mask2,
+ mask2 + 1,
+ (FT_UInt)delta * sizeof ( PS_MaskRec ) );
mask2[delta] = dummy;
}
@@ -502,13 +504,19 @@
FT_Error error = FT_Err_Ok;
- for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
+ /* both loops go down to 0, thus FT_Int for index1 and index2 */
+ for ( index1 = (FT_Int)table->num_masks - 1; index1 > 0; index1-- )
{
for ( index2 = index1 - 1; index2 >= 0; index2-- )
{
- if ( ps_mask_table_test_intersect( table, index1, index2 ) )
+ if ( ps_mask_table_test_intersect( table,
+ (FT_UInt)index1,
+ (FT_UInt)index2 ) )
{
- error = ps_mask_table_merge( table, index2, index1, memory );
+ error = ps_mask_table_merge( table,
+ (FT_UInt)index2,
+ (FT_UInt)index1,
+ memory );
if ( error )
goto Exit;
@@ -670,8 +678,8 @@
{
PS_Mask mask;
FT_UInt idx;
- FT_UInt max = dim->hints.num_hints;
- PS_Hint hint = dim->hints.hints;
+ FT_UInt max = dim->hints.num_hints;
+ PS_Hint hint = dim->hints.hints;
for ( idx = 0; idx < max; idx++, hint++ )
@@ -742,17 +750,26 @@
}
/* now, set the bits for our hints in the counter mask */
- error = ps_mask_set_bit( counter, hint1, memory );
- if ( error )
- goto Exit;
+ if ( hint1 >= 0 )
+ {
+ error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory );
+ if ( error )
+ goto Exit;
+ }
- error = ps_mask_set_bit( counter, hint2, memory );
- if ( error )
- goto Exit;
+ if ( hint2 >= 0 )
+ {
+ error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory );
+ if ( error )
+ goto Exit;
+ }
- error = ps_mask_set_bit( counter, hint3, memory );
- if ( error )
- goto Exit;
+ if ( hint3 >= 0 )
+ {
+ error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory );
+ if ( error )
+ goto Exit;
+ }
Exit:
return error;
@@ -793,17 +810,16 @@
ps_dimension_done( &hints->dimension[1], memory );
hints->error = FT_Err_Ok;
- hints->memory = 0;
+ hints->memory = NULL;
}
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
ps_hints_init( PS_Hints hints,
FT_Memory memory )
{
FT_MEM_ZERO( hints, sizeof ( *hints ) );
hints->memory = memory;
- return FT_Err_Ok;
}
@@ -812,78 +828,57 @@
ps_hints_open( PS_Hints hints,
PS_Hint_Type hint_type )
{
- switch ( hint_type )
- {
- case PS_HINT_TYPE_1:
- case PS_HINT_TYPE_2:
- hints->error = FT_Err_Ok;
- hints->hint_type = hint_type;
+ hints->error = FT_Err_Ok;
+ hints->hint_type = hint_type;
- ps_dimension_init( &hints->dimension[0] );
- ps_dimension_init( &hints->dimension[1] );
- break;
-
- default:
- hints->error = FT_THROW( Invalid_Argument );
- hints->hint_type = hint_type;
-
- FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));
- break;
- }
+ ps_dimension_init( &hints->dimension[0] );
+ ps_dimension_init( &hints->dimension[1] );
}
/* add one or more stems to the current hints table */
static void
ps_hints_stem( PS_Hints hints,
- FT_Int dimension,
- FT_UInt count,
+ FT_UInt dimension,
+ FT_Int count,
FT_Long* stems )
{
- if ( !hints->error )
+ PS_Dimension dim;
+
+
+ if ( hints->error )
+ return;
+
+ /* limit "dimension" to 0..1 */
+ if ( dimension > 1 )
{
- /* limit "dimension" to 0..1 */
- if ( dimension < 0 || dimension > 1 )
+ FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
+ dimension ));
+ dimension = ( dimension != 0 );
+ }
+
+ /* record the stems in the current hints/masks table */
+ /* (Type 1 & 2's `hstem' or `vstem' operators) */
+ dim = &hints->dimension[dimension];
+
+ for ( ; count > 0; count--, stems += 2 )
+ {
+ FT_Error error;
+ FT_Memory memory = hints->memory;
+
+
+ error = ps_dimension_add_t1stem( dim,
+ (FT_Int)stems[0],
+ (FT_Int)stems[1],
+ memory,
+ NULL );
+ if ( error )
{
- FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
- dimension ));
- dimension = ( dimension != 0 );
- }
+ FT_ERROR(( "ps_hints_stem: could not add stem"
+ " (%d,%d) to hints table\n", stems[0], stems[1] ));
- /* record the stems in the current hints/masks table */
- switch ( hints->hint_type )
- {
- case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */
- case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */
- {
- PS_Dimension dim = &hints->dimension[dimension];
-
-
- for ( ; count > 0; count--, stems += 2 )
- {
- FT_Error error;
- FT_Memory memory = hints->memory;
-
-
- error = ps_dimension_add_t1stem(
- dim, (FT_Int)stems[0], (FT_Int)stems[1],
- memory, NULL );
- if ( error )
- {
- FT_ERROR(( "ps_hints_stem: could not add stem"
- " (%d,%d) to hints table\n", stems[0], stems[1] ));
-
- hints->error = error;
- return;
- }
- }
- break;
- }
-
- default:
- FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n",
- hints->hint_type ));
- break;
+ hints->error = error;
+ return;
}
}
}
@@ -892,7 +887,7 @@
/* add one Type1 counter stem to the current hints table */
static void
ps_hints_t1stem3( PS_Hints hints,
- FT_Int dimension,
+ FT_UInt dimension,
FT_Fixed* stems )
{
FT_Error error = FT_Err_Ok;
@@ -907,7 +902,7 @@
/* limit "dimension" to 0..1 */
- if ( dimension < 0 || dimension > 1 )
+ if ( dimension > 1 )
{
FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
dimension ));
@@ -1129,7 +1124,7 @@
static void
t1_hints_stem( T1_Hints hints,
- FT_Int dimension,
+ FT_UInt dimension,
FT_Fixed* coords )
{
FT_Pos stems[2];
@@ -1173,12 +1168,12 @@
static void
t2_hints_stems( T2_Hints hints,
- FT_Int dimension,
+ FT_UInt dimension,
FT_Int count,
FT_Fixed* coords )
{
- FT_Pos stems[32], y, n;
- FT_Int total = count;
+ FT_Pos stems[32], y;
+ FT_Int total = count, n;
y = 0;
diff --git a/src/pshinter/pshrec.h b/src/pshinter/pshrec.h
index dcb3197..2b1ad94 100644
--- a/src/pshinter/pshrec.h
+++ b/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
/* */
/* Postscript (Type1/Type2) hints recorder (specification). */
/* */
-/* Copyright 2001, 2002, 2003, 2006, 2008 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -61,12 +61,8 @@
/* hint flags */
- typedef enum PS_Hint_Flags_
- {
- PS_HINT_FLAG_GHOST = 1,
- PS_HINT_FLAG_BOTTOM = 2
-
- } PS_Hint_Flags;
+#define PS_HINT_FLAG_GHOST 1U
+#define PS_HINT_FLAG_BOTTOM 2U
/* hint descriptor */
@@ -141,7 +137,7 @@
/* */
/* initialize hints recorder */
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
ps_hints_init( PS_Hints hints,
FT_Memory memory );
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index 0a5bcb7..5406098 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
/* */
/* PSNames module implementation (body). */
/* */
-/* Copyright 1996-2003, 2005-2008, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -312,7 +312,7 @@
/* we first allocate the table */
table->num_maps = 0;
- table->maps = 0;
+ table->maps = NULL;
if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
{
@@ -525,31 +525,31 @@
FT_DEFINE_SERVICE_PSCMAPSREC(
pscmaps_interface,
- (PS_Unicode_ValueFunc) ps_unicode_value,
- (PS_Unicodes_InitFunc) ps_unicodes_init,
- (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
- (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
+ (PS_Unicode_ValueFunc) ps_unicode_value, /* unicode_value */
+ (PS_Unicodes_InitFunc) ps_unicodes_init, /* unicodes_init */
+ (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, /* unicodes_char_index */
+ (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, /* unicodes_char_next */
- (PS_Macintosh_NameFunc) ps_get_macintosh_name,
- (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
- t1_standard_encoding,
- t1_expert_encoding )
+ t1_standard_encoding, /* adobe_std_encoding */
+ t1_expert_encoding ) /* adobe_expert_encoding */
#else
FT_DEFINE_SERVICE_PSCMAPSREC(
pscmaps_interface,
- NULL,
- NULL,
- NULL,
- NULL,
+ NULL, /* unicode_value */
+ NULL, /* unicodes_init */
+ NULL, /* unicodes_char_index */
+ NULL, /* unicodes_char_next */
- (PS_Macintosh_NameFunc) ps_get_macintosh_name,
- (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name, /* macintosh_name */
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings */
- t1_standard_encoding,
- t1_expert_encoding )
+ t1_standard_encoding, /* adobe_std_encoding */
+ t1_expert_encoding ) /* adobe_expert_encoding */
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
@@ -563,7 +563,7 @@
psnames_get_service( FT_Module module,
const char* service_id )
{
- /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
+ /* PSCMAPS_SERVICES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
FT_Library library;
diff --git a/src/psnames/psmodule.h b/src/psnames/psmodule.h
index 28fa148..f85f322 100644
--- a/src/psnames/psmodule.h
+++ b/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
/* */
/* High-level PSNames module interface (specification). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psnames/psnamerr.h b/src/psnames/psnamerr.h
index acda7f9..09cc247 100644
--- a/src/psnames/psnamerr.h
+++ b/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
/* */
/* PS names module error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psnames/psnames.c b/src/psnames/psnames.c
index 1ede225..a438596 100644
--- a/src/psnames/psnames.c
+++ b/src/psnames/psnames.c
@@ -4,7 +4,7 @@
/* */
/* FreeType PSNames module component (body only). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psnames/pspic.c b/src/psnames/pspic.c
index 3820f65..1394f97 100644
--- a/src/psnames/pspic.c
+++ b/src/psnames/pspic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for psnames module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/psnames/pspic.h b/src/psnames/pspic.h
index 6ff002c..443225a 100644
--- a/src/psnames/pspic.h
+++ b/src/psnames/pspic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for psnames module. */
/* */
-/* Copyright 2009, 2012 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,10 +20,9 @@
#define __PSPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
#define PSCMAPS_SERVICES_GET pscmaps_services
@@ -33,6 +32,9 @@
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+FT_BEGIN_HEADER
+
typedef struct PSModulePIC_
{
FT_ServiceDescRec* pscmaps_services;
@@ -54,12 +56,12 @@
FT_Error
psnames_module_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __PSPIC_H__ */
diff --git a/src/psnames/pstables.h b/src/psnames/pstables.h
index 0a6637f..3f31c31 100644
--- a/src/psnames/pstables.h
+++ b/src/psnames/pstables.h
@@ -4,7 +4,7 @@
/* */
/* PostScript glyph names. */
/* */
-/* Copyright 2005, 2008, 2011 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 703155a..b87e0b6 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
/* Miscellaneous macros for stand-alone rasterizer (specification */
/* only). */
/* */
-/* Copyright 2005, 2009, 2010 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
@@ -37,7 +37,7 @@
#define FT_LOCAL_DEF( x ) static x
- /* from include/freetype2/fttypes.h */
+ /* from include/freetype/fttypes.h */
typedef unsigned char FT_Byte;
typedef signed int FT_Int;
@@ -54,7 +54,7 @@
(FT_ULong)_x4 )
- /* from include/freetype2/ftsystem.h */
+ /* from include/freetype/ftsystem.h */
typedef struct FT_MemoryRec_* FT_Memory;
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index 4865994..e4bab98 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (body). */
/* */
-/* Copyright 1996-2003, 2005, 2007-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,8 +24,8 @@
/* */
/* - copy `src/raster/ftraster.c' (this file) to your current directory */
/* */
- /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' */
- /* to your current directory */
+ /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
+ /* current directory */
/* */
/* - compile `ftraster' with the _STANDALONE_ macro defined, as in */
/* */
@@ -49,6 +49,10 @@
#ifdef _STANDALONE_
+ /* The size in bytes of the render pool used by the scan-line converter */
+ /* to do all of its work. */
+#define FT_RENDER_POOL_SIZE 16384L
+
#define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h>
#include <string.h> /* for memset */
@@ -150,14 +154,6 @@
/* define DEBUG_RASTER if you want to compile a debugging version */
/* #define DEBUG_RASTER */
- /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
- /* 5-levels anti-aliasing */
-/* #define FT_RASTER_OPTION_ANTI_ALIASING */
-
- /* The size of the two-lines intermediate bitmap used */
- /* for anti-aliasing, in bytes. */
-#define RASTER_GRAY_LINES 2048
-
/*************************************************************************/
/*************************************************************************/
@@ -183,6 +179,8 @@
#define FT_ERR_XCAT( x, y ) x ## y
#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
+#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+
/* This macro is used to indicate that a function parameter is unused. */
/* Its purpose is simply to reduce compiler warnings. Note also that */
/* simply defining it as `(void)x' doesn't avoid warnings with certain */
@@ -199,6 +197,7 @@
#define FT_TRACE( x ) do { } while ( 0 ) /* nothing */
#define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */
#define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */
+#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
#endif
#ifndef FT_THROW
@@ -318,7 +317,7 @@
typedef union Alignment_
{
- long l;
+ Long l;
void* p;
void (*f)(void);
@@ -334,9 +333,9 @@
/* values for the `flags' bit field */
-#define Flow_Up 0x8
-#define Overshoot_Top 0x10
-#define Overshoot_Bottom 0x20
+#define Flow_Up 0x08U
+#define Overshoot_Top 0x10U
+#define Overshoot_Bottom 0x20U
/* States of each line, arc, and profile */
@@ -358,14 +357,14 @@
FT_F26Dot6 X; /* current coordinate during sweep */
PProfile link; /* link to next profile (various purposes) */
PLong offset; /* start of profile's data in render pool */
- unsigned flags; /* Bit 0-2: drop-out mode */
+ UShort flags; /* Bit 0-2: drop-out mode */
/* Bit 3: profile orientation (up/down) */
/* Bit 4: is top profile? */
/* Bit 5: is bottom profile? */
- long height; /* profile's height in scanlines */
- long start; /* profile's starting scanline */
+ Long height; /* profile's height in scanlines */
+ Long start; /* profile's starting scanline */
- unsigned countL; /* number of lines to step before this */
+ Int countL; /* number of lines to step before this */
/* profile becomes drawable */
PProfile next; /* next profile in same contour, used */
@@ -387,7 +386,7 @@
#define AlignProfileSize \
- ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
+ ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
#undef RAS_ARG
@@ -451,10 +450,14 @@
#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
#define TRUNC( x ) ( (Long)(x) >> ras.precision_bits )
#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x ) ( ( (ULong)(x) << ras.scale_shift ) - ras.precision_half )
+#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << ras.scale_shift ) \
+ : ( (x) << ras.scale_shift ) ) \
+ - ras.precision_half )
-#define IS_BOTTOM_OVERSHOOT( x ) ( CEILING( x ) - x >= ras.precision_half )
-#define IS_TOP_OVERSHOOT( x ) ( x - FLOOR( x ) >= ras.precision_half )
+#define IS_BOTTOM_OVERSHOOT( x ) \
+ (Bool)( CEILING( x ) - x >= ras.precision_half )
+#define IS_TOP_OVERSHOOT( x ) \
+ (Bool)( x - FLOOR( x ) >= ras.precision_half )
/* The most used variables are positioned at the top of the structure. */
/* Thus, their offset can be coded with less opcodes, resulting in a */
@@ -512,9 +515,6 @@
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;
@@ -527,45 +527,19 @@
Bool second_pass; /* indicates whether 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. */
+ /* Render_Glyph. */
TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
black_TBand band_stack[16]; /* band stack used for sub-banding */
Int band_top; /* band stack top */
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- Byte* grays;
-
- Byte gray_lines[RASTER_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'. */
-
-#endif /* FT_RASTER_ANTI_ALIASING */
-
};
typedef struct black_TRaster_
{
- char* buffer;
- long buffer_size;
void* memory;
- black_PWorker worker;
- Byte grays[5];
- Short gray_width;
} black_TRaster, *black_PRaster;
@@ -581,70 +555,6 @@
#endif /* !FT_STATIC_RASTER */
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- /* A lookup table used to quickly count set bits in four gray 2x2 */
- /* cells. The values of the table have been produced with the */
- /* following code: */
- /* */
- /* 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; */
- /* } */
- /* printf( "0x%04X", l ); */
- /* } */
- /* */
-
- static const short count_table[256] =
- {
- 0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
- 0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
- 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
- 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
- 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
- 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
- 0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
- 0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
- 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
- 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
- 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
- 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
- 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
- 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
- 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
- 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
- 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
- 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
- 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
- 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
- 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
- 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
- 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
- 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
- 0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
- 0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
- 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
- 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
- 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
- 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
- 0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
- 0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
- };
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
-
/*************************************************************************/
/*************************************************************************/
/** **/
@@ -675,11 +585,11 @@
* approximating it as a straight segment. The default value of 32 (for
* low accuracy) corresponds to
*
- * 32 / 64 == 0.5 pixels ,
+ * 32 / 64 == 0.5 pixels,
*
* while for the high accuracy case we have
*
- * 256/ (1 << 12) = 0.0625 pixels .
+ * 256 / (1 << 12) = 0.0625 pixels.
*
* `precision_jitter' is an epsilon threshold used in
* `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
@@ -762,13 +672,13 @@
if ( overshoot )
ras.cProfile->flags |= Overshoot_Bottom;
- FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));
+ FT_TRACE6(( " new ascending profile = %p\n", ras.cProfile ));
break;
case Descending_State:
if ( overshoot )
ras.cProfile->flags |= Overshoot_Top;
- FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
+ FT_TRACE6(( " new descending profile = %p\n", ras.cProfile ));
break;
default:
@@ -823,7 +733,7 @@
PProfile oldProfile;
- FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
+ FT_TRACE6(( " ending profile %p, start = %ld, height = %ld\n",
ras.cProfile, ras.cProfile->start, h ));
ras.cProfile->height = h;
@@ -891,15 +801,14 @@
/* if it is <, simply insert it, ignore if == */
if ( n >= 0 && y > y_turns[n] )
- while ( n >= 0 )
+ do
{
Int y2 = (Int)y_turns[n];
y_turns[n] = y;
y = y2;
- n--;
- }
+ } while ( --n >= 0 );
if ( n < 0 )
{
@@ -940,7 +849,7 @@
if ( n > 1 && p )
{
- while ( n > 0 )
+ do
{
Int bottom, top;
@@ -968,8 +877,7 @@
return FAILURE;
p = p->link;
- n--;
- }
+ } while ( --n );
}
else
ras.fProfile = NULL;
@@ -1340,7 +1248,7 @@
start_arc = arc;
- while ( arc >= start_arc && e <= e2 )
+ do
{
ras.joint = FALSE;
@@ -1373,7 +1281,7 @@
}
arc -= degree;
}
- }
+ } while ( arc >= start_arc && e <= e2 );
Fin:
ras.top = top;
@@ -1811,7 +1719,7 @@
static Bool
Decompose_Curve( RAS_ARGS UShort first,
UShort last,
- int flipped )
+ Int flipped )
{
FT_Vector v_last;
FT_Vector v_control;
@@ -1822,7 +1730,7 @@
FT_Vector* limit;
char* tags;
- unsigned tag; /* current point's state */
+ UInt tag; /* current point's state */
points = ras.outline.points;
@@ -1872,7 +1780,7 @@
v_start.x = ( v_start.x + v_last.x ) / 2;
v_start.y = ( v_start.y + v_last.y ) / 2;
- v_last = v_start;
+ /* v_last = v_start; */
}
point--;
tags--;
@@ -2033,10 +1941,10 @@
/* rendering. */
/* */
static Bool
- Convert_Glyph( RAS_ARGS int flipped )
+ Convert_Glyph( RAS_ARGS Int flipped )
{
- int i;
- unsigned start;
+ Int i;
+ UInt start;
ras.fProfile = NULL;
@@ -2062,12 +1970,12 @@
ras.state = Unknown_State;
ras.gProfile = NULL;
- if ( Decompose_Curve( RAS_VARS (unsigned short)start,
- ras.outline.contours[i],
+ if ( Decompose_Curve( RAS_VARS (UShort)start,
+ (UShort)ras.outline.contours[i],
flipped ) )
return FAILURE;
- start = ras.outline.contours[i] + 1;
+ start = (UShort)ras.outline.contours[i] + 1;
/* we must now check whether the extreme arcs join or not */
if ( FRAC( ras.lastY ) == 0 &&
@@ -2081,7 +1989,8 @@
/* to be drawn. */
lastProfile = ras.cProfile;
- if ( ras.cProfile->flags & Flow_Up )
+ if ( ras.top != ras.cProfile->offset &&
+ ( ras.cProfile->flags & Flow_Up ) )
o = IS_TOP_OVERSHOOT( ras.lastY );
else
o = IS_BOTTOM_OVERSHOOT( ras.lastY );
@@ -2205,7 +2114,7 @@
while ( current )
{
current->X = *current->offset;
- current->offset += current->flags & Flow_Up ? 1 : -1;
+ current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
current->height--;
current = current->link;
}
@@ -2265,10 +2174,7 @@
ras.traceIncr = (Short)-pitch;
ras.traceOfs = -*min * pitch;
if ( pitch > 0 )
- ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
-
- ras.gray_min_x = 0;
- ras.gray_max_x = 0;
+ ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
}
@@ -2282,23 +2188,34 @@
Long e1, e2;
Byte* target;
+ Int dropOutControl = left->flags & 7;
+
FT_UNUSED( y );
FT_UNUSED( left );
FT_UNUSED( right );
+ /* in high-precision mode, we need 12 digits after the comma to */
+ /* represent multiples of 1/(1<<12) = 1/4096 */
+ FT_TRACE7(( " y=%d x=[%.12f;%.12f], drop-out=%d",
+ y,
+ x1 / (double)ras.precision,
+ x2 / (double)ras.precision,
+ dropOutControl ));
+
/* Drop-out control */
e1 = TRUNC( CEILING( x1 ) );
- if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+ if ( dropOutControl != 2 &&
+ x2 - x1 - ras.precision <= ras.precision_jitter )
e2 = e1;
else
e2 = TRUNC( FLOOR( x2 ) );
if ( e2 >= 0 && e1 < ras.bWidth )
{
- int c1, c2;
+ Int c1, c2;
Byte f1, f2;
@@ -2307,17 +2224,14 @@
if ( e2 >= ras.bWidth )
e2 = ras.bWidth - 1;
+ FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
+
c1 = (Short)( e1 >> 3 );
c2 = (Short)( e2 >> 3 );
f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
- if ( ras.gray_min_x > c1 )
- ras.gray_min_x = (short)c1;
- if ( ras.gray_max_x < c2 )
- ras.gray_max_x = (short)c2;
-
target = ras.bTarget + ras.traceOfs + c1;
c2 -= c1;
@@ -2339,6 +2253,8 @@
else
*target |= ( f1 & f2 );
}
+
+ FT_TRACE7(( "\n" ));
}
@@ -2353,6 +2269,11 @@
Short c1, f1;
+ FT_TRACE7(( " y=%d x=[%.12f;%.12f]",
+ y,
+ x1 / (double)ras.precision,
+ x2 / (double)ras.precision ));
+
/* Drop-out control */
/* e2 x2 x1 e1 */
@@ -2385,6 +2306,8 @@
Int dropOutControl = left->flags & 7;
+ FT_TRACE7(( ", drop-out=%d", dropOutControl ));
+
if ( e1 == e2 + ras.precision )
{
switch ( dropOutControl )
@@ -2431,14 +2354,14 @@
left->height <= 0 &&
!( left->flags & Overshoot_Top &&
x2 - x1 >= ras.precision_half ) )
- return;
+ goto Exit;
/* lower stub test */
if ( right->next == left &&
left->start == y &&
!( left->flags & Overshoot_Bottom &&
x2 - x1 >= ras.precision_half ) )
- return;
+ goto Exit;
if ( dropOutControl == 1 )
pxl = e2;
@@ -2447,7 +2370,7 @@
break;
default: /* modes 2, 3, 6, 7 */
- return; /* no drop-out control */
+ goto Exit; /* no drop-out control */
}
/* undocumented but confirmed: If the drop-out would result in a */
@@ -2468,26 +2391,26 @@
if ( e1 >= 0 && e1 < ras.bWidth &&
ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
- return;
+ goto Exit;
}
else
- return;
+ goto Exit;
}
e1 = TRUNC( pxl );
if ( e1 >= 0 && e1 < ras.bWidth )
{
+ FT_TRACE7(( " -> x=%d (drop-out)", e1 ));
+
c1 = (Short)( e1 >> 3 );
f1 = (Short)( 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 );
}
+
+ Exit:
+ FT_TRACE7(( "\n" ));
}
@@ -2534,32 +2457,39 @@
Long e1, e2;
+ FT_TRACE7(( " x=%d y=[%.12f;%.12f]",
+ y,
+ x1 / (double)ras.precision,
+ x2 / (double)ras.precision ));
+
e1 = CEILING( x1 );
e2 = FLOOR ( x2 );
if ( e1 == e2 )
{
- Byte f1;
- PByte bits;
-
-
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
-
e1 = TRUNC( e1 );
- if ( e1 >= 0 && e1 < ras.target.rows )
+ if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
{
+ Byte f1;
+ PByte bits;
PByte p;
- p = bits - e1 * ras.target.pitch;
+ FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+ p = bits - e1 * ras.target.pitch;
+
if ( ras.target.pitch > 0 )
- p += ( ras.target.rows - 1 ) * ras.target.pitch;
+ p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
p[0] |= f1;
}
}
+
+ FT_TRACE7(( "\n" ));
}
}
@@ -2576,6 +2506,11 @@
Byte f1;
+ FT_TRACE7(( " x=%d y=[%.12f;%.12f]",
+ y,
+ x1 / (double)ras.precision,
+ x2 / (double)ras.precision ));
+
/* During the horizontal sweep, we only take care of drop-outs */
/* e1 + <-- pixel center */
@@ -2597,6 +2532,8 @@
Int dropOutControl = left->flags & 7;
+ FT_TRACE7(( ", dropout=%d", dropOutControl ));
+
if ( e1 == e2 + ras.precision )
{
switch ( dropOutControl )
@@ -2618,14 +2555,14 @@
left->height <= 0 &&
!( left->flags & Overshoot_Top &&
x2 - x1 >= ras.precision_half ) )
- return;
+ goto Exit;
/* leftmost stub test */
if ( right->next == left &&
left->start == y &&
!( left->flags & Overshoot_Bottom &&
x2 - x1 >= ras.precision_half ) )
- return;
+ goto Exit;
if ( dropOutControl == 1 )
pxl = e2;
@@ -2634,7 +2571,7 @@
break;
default: /* modes 2, 3, 6, 7 */
- return; /* no drop-out control */
+ goto Exit; /* no drop-out control */
}
/* undocumented but confirmed: If the drop-out would result in a */
@@ -2642,7 +2579,7 @@
/* bounding box instead */
if ( pxl < 0 )
pxl = e1;
- else if ( TRUNC( pxl ) >= ras.target.rows )
+ else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
pxl = e2;
/* check that the other pixel isn't set */
@@ -2655,30 +2592,35 @@
bits -= e1 * ras.target.pitch;
if ( ras.target.pitch > 0 )
- bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+ bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
- if ( e1 >= 0 &&
- e1 < ras.target.rows &&
- *bits & f1 )
- return;
+ if ( e1 >= 0 &&
+ (ULong)e1 < ras.target.rows &&
+ *bits & f1 )
+ goto Exit;
}
else
- return;
+ goto Exit;
}
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
-
e1 = TRUNC( pxl );
- if ( e1 >= 0 && e1 < ras.target.rows )
+ if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
{
+ FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
bits -= e1 * ras.target.pitch;
+
if ( ras.target.pitch > 0 )
- bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+ bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
bits[0] |= f1;
}
+
+ Exit:
+ FT_TRACE7(( "\n" ));
}
@@ -2690,249 +2632,6 @@
}
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-
- /*************************************************************************/
- /* */
- /* 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 )
- {
- Long pitch, byte_len;
-
-
- *min = *min & -2;
- *max = ( *max + 3 ) & -2;
-
- ras.traceOfs = 0;
- pitch = ras.target.pitch;
- byte_len = -pitch;
- ras.traceIncr = (Short)byte_len;
- ras.traceG = ( *min / 2 ) * byte_len;
-
- if ( pitch > 0 )
- {
- ras.traceG += ( ras.target.rows - 1 ) * pitch;
- byte_len = -byte_len;
- }
-
- ras.gray_min_x = (Short)byte_len;
- ras.gray_max_x = -(Short)byte_len;
- }
-
-
- static void
- Vertical_Gray_Sweep_Step( RAS_ARG )
- {
- short* count = (short*)count_table;
- Byte* grays;
-
-
- ras.traceOfs += ras.gray_width;
-
- if ( ras.traceOfs > ras.gray_width )
- {
- PByte pix;
-
-
- pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
- grays = ras.grays;
-
- if ( ras.gray_max_x >= 0 )
- {
- Long last_pixel = ras.target.width - 1;
- Int last_cell = last_pixel >> 2;
- Int last_bit = last_pixel & 3;
- Bool over = 0;
-
- Int c1, c2;
- PByte bit, bit2;
-
-
- if ( ras.gray_max_x >= last_cell && last_bit != 3 )
- {
- ras.gray_max_x = last_cell - 1;
- over = 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 >> 12) & 0x000F];
- pix[1] = grays[(c2 >> 8 ) & 0x000F];
- pix[2] = grays[(c2 >> 4 ) & 0x000F];
- pix[3] = grays[ c2 & 0x000F];
-
- *bit = 0;
- *bit2 = 0;
- }
-
- bit++;
- bit2++;
- pix += 4;
- c1--;
- }
-
- if ( over )
- {
- c2 = count[*bit] + count[*bit2];
- if ( c2 )
- {
- switch ( last_bit )
- {
- case 2:
- pix[2] = grays[(c2 >> 4 ) & 0x000F];
- case 1:
- pix[1] = grays[(c2 >> 8 ) & 0x000F];
- default:
- pix[0] = grays[(c2 >> 12) & 0x000F];
- }
-
- *bit = 0;
- *bit2 = 0;
- }
- }
- }
-
- ras.traceOfs = 0;
- ras.traceG += ras.traceIncr;
-
- ras.gray_min_x = 32000;
- ras.gray_max_x = -32000;
- }
- }
-
-
- static void
- Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- /* nothing, really */
- FT_UNUSED_RASTER;
- FT_UNUSED( y );
- FT_UNUSED( x1 );
- FT_UNUSED( x2 );
- FT_UNUSED( left );
- FT_UNUSED( right );
- }
-
-
- static void
- Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- PByte pixel;
-
-
- /* During the horizontal sweep, we only take care of drop-outs */
-
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
-
- if ( e1 > e2 )
- {
- Int dropOutControl = left->flags & 7;
-
-
- if ( e1 == e2 + ras.precision )
- {
- switch ( dropOutControl )
- {
- case 0: /* simple drop-outs including stubs */
- e1 = e2;
- break;
-
- case 4: /* smart drop-outs including stubs */
- e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
- break;
-
- case 1: /* simple drop-outs excluding stubs */
- case 5: /* smart drop-outs excluding stubs */
- /* see Vertical_Sweep_Drop for details */
-
- /* rightmost stub test */
- if ( left->next == right && left->height <= 0 )
- return;
-
- /* leftmost stub test */
- if ( right->next == left && left->start == y )
- return;
-
- if ( dropOutControl == 1 )
- e1 = e2;
- else
- e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
-
- break;
-
- default: /* modes 2, 3, 6, 7 */
- return; /* no drop-out control */
- }
- }
- else
- return;
- }
-
- if ( e1 >= 0 )
- {
- Byte color;
-
-
- if ( x2 - x1 >= ras.precision_half )
- color = ras.grays[2];
- else
- color = ras.grays[1];
-
- e1 = TRUNC( e1 ) / 2;
- if ( e1 < ras.target.rows )
- {
- pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
- if ( ras.target.pitch > 0 )
- pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
-
- if ( pixel[0] == ras.grays[0] )
- pixel[0] = color;
- }
- }
- }
-
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
/*************************************************************************/
/* */
/* Generic Sweep Drawing routine */
@@ -3002,7 +2701,7 @@
while ( P )
{
- P->countL = (UShort)( P->start - min_Y );
+ P->countL = P->start - min_Y;
P = P->link;
}
@@ -3265,7 +2964,7 @@
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
- FT_LOCAL_DEF( FT_Error )
+ static FT_Error
Render_Glyph( RAS_ARG )
{
FT_Error error;
@@ -3288,10 +2987,12 @@
ras.dropOutControl += 1;
}
- ras.second_pass = (FT_Byte)( !( ras.outline.flags &
- FT_OUTLINE_SINGLE_PASS ) );
+ ras.second_pass = (Bool)( !( ras.outline.flags &
+ FT_OUTLINE_SINGLE_PASS ) );
/* Vertical Sweep */
+ FT_TRACE7(( "Vertical pass (ftraster)\n" ));
+
ras.Proc_Sweep_Init = Vertical_Sweep_Init;
ras.Proc_Sweep_Span = Vertical_Sweep_Span;
ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
@@ -3299,9 +3000,9 @@
ras.band_top = 0;
ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
+ ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
- ras.bWidth = (unsigned short)ras.target.width;
+ ras.bWidth = (UShort)ras.target.width;
ras.bTarget = (Byte*)ras.target.buffer;
if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
@@ -3310,6 +3011,8 @@
/* Horizontal Sweep */
if ( ras.second_pass && ras.dropOutControl != 2 )
{
+ FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
+
ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
@@ -3317,7 +3020,7 @@
ras.band_top = 0;
ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
+ ras.band_stack[0].y_max = (Short)( ras.target.width - 1 );
if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
return error;
@@ -3327,118 +3030,10 @@
}
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Gray_Glyph */
- /* */
- /* <Description> */
- /* Render a glyph with grayscaling. Sub-banding if needed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
- Render_Gray_Glyph( RAS_ARG )
- {
- Long pixel_width;
- FT_Error error;
-
-
- Set_High_Precision( RAS_VARS ras.outline.flags &
- FT_OUTLINE_HIGH_PRECISION );
- ras.scale_shift = ras.precision_shift + 1;
-
- if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
- ras.dropOutControl = 2;
- else
- {
- if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
- ras.dropOutControl = 4;
- else
- ras.dropOutControl = 0;
-
- if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
- ras.dropOutControl += 1;
- }
-
- ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_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;
- pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
-
- if ( ras.bWidth > pixel_width )
- ras.bWidth = pixel_width;
-
- ras.bWidth = ras.bWidth * 8;
- ras.bTarget = (Byte*)ras.gray_lines;
- ras.gTarget = (Byte*)ras.target.buffer;
-
- 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 != 2 )
- {
- 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 Raster_Err_None;
- }
-
-#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
-
- FT_LOCAL_DEF( FT_Error )
- Render_Gray_Glyph( RAS_ARG )
- {
- FT_UNUSED_RASTER;
-
- return FT_THROW( Unsupported );
- }
-
-#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
-
-
static void
ft_black_init( black_PRaster raster )
{
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
- FT_UInt n;
-
-
- /* set default 5-levels gray palette */
- for ( n = 0; n < 5; n++ )
- raster->grays[n] = n * 255 / 4;
-
- raster->gray_width = RASTER_GRAY_LINES / 2;
-#else
FT_UNUSED( raster );
-#endif
}
@@ -3513,54 +3108,24 @@
static void
ft_black_reset( black_PRaster raster,
char* pool_base,
- long pool_size )
+ Long pool_size )
{
- if ( raster )
- {
- if ( pool_base && pool_size >= (long)sizeof ( black_TWorker ) + 2048 )
- {
- black_PWorker worker = (black_PWorker)pool_base;
-
-
- raster->buffer = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );
- raster->buffer_size = (long)( pool_base + pool_size -
- (char*)raster->buffer );
- raster->worker = worker;
- }
- else
- {
- raster->buffer = NULL;
- raster->buffer_size = 0;
- raster->worker = NULL;
- }
- }
+ FT_UNUSED( raster );
+ FT_UNUSED( pool_base );
+ FT_UNUSED( pool_size );
}
- static void
+ static int
ft_black_set_mode( black_PRaster raster,
- unsigned long mode,
+ ULong mode,
const char* palette )
{
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
- {
- /* set 5-levels gray palette */
- raster->grays[0] = palette[0];
- raster->grays[1] = palette[1];
- raster->grays[2] = palette[2];
- raster->grays[3] = palette[3];
- raster->grays[4] = palette[4];
- }
-
-#else
-
FT_UNUSED( raster );
FT_UNUSED( mode );
FT_UNUSED( palette );
-#endif
+ return 0;
}
@@ -3570,10 +3135,13 @@
{
const FT_Outline* outline = (const FT_Outline*)params->source;
const FT_Bitmap* target_map = params->target;
- black_PWorker worker;
+
+ black_TWorker worker[1];
+
+ Long buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( Long )];
- if ( !raster || !raster->buffer || !raster->buffer_size )
+ if ( !raster )
return FT_THROW( Not_Ini );
if ( !outline )
@@ -3590,12 +3158,13 @@
outline->contours[outline->n_contours - 1] + 1 )
return FT_THROW( Invalid );
- worker = raster->worker;
-
/* this version of the raster does not support direct rendering, sorry */
if ( params->flags & FT_RASTER_FLAG_DIRECT )
return FT_THROW( Unsupported );
+ if ( params->flags & FT_RASTER_FLAG_AA )
+ return FT_THROW( Unsupported );
+
if ( !target_map )
return FT_THROW( Invalid );
@@ -3609,30 +3178,23 @@
ras.outline = *outline;
ras.target = *target_map;
- worker->buff = (PLong) raster->buffer;
- worker->sizeBuff = worker->buff +
- raster->buffer_size / sizeof ( Long );
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
- worker->grays = raster->grays;
- worker->gray_width = raster->gray_width;
+ worker->buff = buffer;
+ worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
- FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
-#endif
-
- return ( params->flags & FT_RASTER_FLAG_AA )
- ? Render_Gray_Glyph( RAS_VAR )
- : Render_Glyph( RAS_VAR );
+ return Render_Glyph( RAS_VAR );
}
- FT_DEFINE_RASTER_FUNCS( ft_standard_raster,
+ FT_DEFINE_RASTER_FUNCS(
+ ft_standard_raster,
+
FT_GLYPH_FORMAT_OUTLINE,
+
(FT_Raster_New_Func) ft_black_new,
(FT_Raster_Reset_Func) ft_black_reset,
(FT_Raster_Set_Mode_Func)ft_black_set_mode,
(FT_Raster_Render_Func) ft_black_render,
- (FT_Raster_Done_Func) ft_black_done
- )
+ (FT_Raster_Done_Func) ft_black_done )
/* END */
diff --git a/src/raster/ftraster.h b/src/raster/ftraster.h
index 80fe46d..a270d48 100644
--- a/src/raster/ftraster.h
+++ b/src/raster/ftraster.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (specification). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used */
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index aa7f6d5..f314392 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer interface (body). */
/* */
-/* Copyright 1996-2003, 2005, 2006, 2011, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -104,7 +104,7 @@
{
FT_Error error;
FT_Outline* outline;
- FT_BBox cbox;
+ FT_BBox cbox, cbox0;
FT_UInt width, height, pitch;
FT_Bitmap* bitmap;
FT_Memory memory;
@@ -120,38 +120,11 @@
}
/* check rendering mode */
-#ifndef FT_CONFIG_OPTION_PIC
if ( mode != FT_RENDER_MODE_MONO )
{
/* raster1 is only capable of producing monochrome bitmaps */
- if ( render->clazz == &ft_raster1_renderer_class )
- return FT_THROW( Cannot_Render_Glyph );
+ return FT_THROW( Cannot_Render_Glyph );
}
- else
- {
- /* raster5 is only capable of producing 5-gray-levels bitmaps */
- if ( render->clazz == &ft_raster5_renderer_class )
- return FT_THROW( Cannot_Render_Glyph );
- }
-#else /* FT_CONFIG_OPTION_PIC */
- /* When PIC is enabled, we cannot get to the class object */
- /* so instead we check the final character in the class name */
- /* ("raster5" or "raster1"). Yes this is a hack. */
- /* The "correct" thing to do is have different render function */
- /* for each of the classes. */
- if ( mode != FT_RENDER_MODE_MONO )
- {
- /* raster1 is only capable of producing monochrome bitmaps */
- if ( render->clazz->root.module_name[6] == '1' )
- return FT_THROW( Cannot_Render_Glyph );
- }
- else
- {
- /* raster5 is only capable of producing 5-gray-levels bitmaps */
- if ( render->clazz->root.module_name[6] == '5' )
- return FT_THROW( Cannot_Render_Glyph );
- }
-#endif /* FT_CONFIG_OPTION_PIC */
outline = &slot->outline;
@@ -160,14 +133,14 @@
FT_Outline_Translate( outline, origin->x, origin->y );
/* compute the control box, and grid fit it */
- FT_Outline_Get_CBox( outline, &cbox );
+ FT_Outline_Get_CBox( outline, &cbox0 );
/* undocumented but confirmed: bbox values get rounded */
#if 1
- cbox.xMin = FT_PIX_ROUND( cbox.xMin );
- cbox.yMin = FT_PIX_ROUND( cbox.yMin );
- cbox.xMax = FT_PIX_ROUND( cbox.xMax );
- cbox.yMax = FT_PIX_ROUND( cbox.yMax );
+ cbox.xMin = FT_PIX_ROUND( cbox0.xMin );
+ cbox.yMin = FT_PIX_ROUND( cbox0.yMin );
+ cbox.xMax = FT_PIX_ROUND( cbox0.xMax );
+ cbox.yMax = FT_PIX_ROUND( cbox0.yMax );
#else
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
@@ -175,8 +148,28 @@
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
#endif
+ /* If either `width' or `height' round to 0, try */
+ /* explicitly rounding up/down. In the case of */
+ /* glyphs containing only one very narrow feature, */
+ /* this gives the drop-out compensation in the scan */
+ /* conversion code a chance to do its stuff. */
width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+ if ( width == 0 )
+ {
+ cbox.xMin = FT_PIX_FLOOR( cbox0.xMin );
+ cbox.xMax = FT_PIX_CEIL( cbox0.xMax );
+
+ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+ }
+
height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+ if ( height == 0 )
+ {
+ cbox.yMin = FT_PIX_FLOOR( cbox0.yMin );
+ cbox.yMax = FT_PIX_CEIL( cbox0.yMax );
+
+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+ }
if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
{
@@ -194,23 +187,12 @@
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
- /* allocate new one, depends on pixel format */
- if ( !( mode & FT_RENDER_MODE_MONO ) )
- {
- /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
- pitch = FT_PAD_CEIL( width, 4 );
- bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap->num_grays = 256;
- }
- else
- {
- pitch = ( ( width + 15 ) >> 4 ) << 1;
- bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
- }
+ pitch = ( ( width + 15 ) >> 4 ) << 1;
+ bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
bitmap->width = width;
bitmap->rows = height;
- bitmap->pitch = pitch;
+ bitmap->pitch = (int)pitch;
if ( FT_ALLOC_MULT( bitmap->buffer, pitch, height ) )
goto Exit;
@@ -225,9 +207,6 @@
params.source = outline;
params.flags = 0;
- if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY )
- params.flags |= FT_RASTER_FLAG_AA;
-
/* render outline into the bitmap */
error = render->raster_render( render->raster, ¶ms );
@@ -272,35 +251,4 @@
)
- /* This renderer is _NOT_ part of the default modules; you will need */
- /* to register it by hand in your application. It should only be */
- /* used for backwards-compatibility with FT 1.x anyway. */
- /* */
- FT_DEFINE_RENDERER( ft_raster5_renderer_class,
-
- FT_MODULE_RENDERER,
- sizeof ( FT_RendererRec ),
-
- "raster5",
- 0x10000L,
- 0x20000L,
-
- 0, /* module specific interface */
-
- (FT_Module_Constructor)ft_raster1_init,
- (FT_Module_Destructor) 0,
- (FT_Module_Requester) 0
- ,
-
- FT_GLYPH_FORMAT_OUTLINE,
-
- (FT_Renderer_RenderFunc) ft_raster1_render,
- (FT_Renderer_TransformFunc)ft_raster1_transform,
- (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox,
- (FT_Renderer_SetModeFunc) ft_raster1_set_mode,
-
- (FT_Raster_Funcs*) &FT_STANDARD_RASTER_GET
- )
-
-
/* END */
diff --git a/src/raster/ftrend1.h b/src/raster/ftrend1.h
index 4cf1286..edc5d13 100644
--- a/src/raster/ftrend1.h
+++ b/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer interface (specification). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,12 +29,6 @@
FT_DECLARE_RENDERER( ft_raster1_renderer_class )
- /* this renderer is _NOT_ part of the default modules, you'll need */
- /* to register it by hand in your application. It should only be */
- /* used for backwards-compatibility with FT 1.x anyway. */
- /* */
- FT_DECLARE_RENDERER( ft_raster5_renderer_class )
-
FT_END_HEADER
diff --git a/src/raster/raster.c b/src/raster/raster.c
index 1202a11..21bb16d 100644
--- a/src/raster/raster.c
+++ b/src/raster/raster.c
@@ -4,7 +4,7 @@
/* */
/* FreeType monochrome rasterer module component (body only). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/raster/rasterrs.h b/src/raster/rasterrs.h
index ab85c00..e7f00bc 100644
--- a/src/raster/rasterrs.h
+++ b/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
/* */
/* monochrome renderer error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/raster/rastpic.c b/src/raster/rastpic.c
index 5e9f7cc..77e7ec3 100644
--- a/src/raster/rastpic.c
+++ b/src/raster/rastpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for raster module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -59,8 +59,9 @@
FT_Memory memory = library->memory;
- /* since this function also serves raster5 renderer, */
- /* it implements reference counting */
+ /* XXX: since this function also served the no longer available */
+ /* raster5 renderer it uses reference counting, which could */
+ /* be removed now */
if ( pic_container->raster )
{
((RasterPIC*)pic_container->raster)->ref_count++;
@@ -82,21 +83,6 @@
return error;
}
-
- /* re-route these init and free functions to the above functions */
- FT_Error
- ft_raster5_renderer_class_pic_init( FT_Library library )
- {
- return ft_raster1_renderer_class_pic_init( library );
- }
-
-
- void
- ft_raster5_renderer_class_pic_free( FT_Library library )
- {
- ft_raster1_renderer_class_pic_free( library );
- }
-
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/src/raster/rastpic.h b/src/raster/rastpic.h
index e0ddba6..408996a 100644
--- a/src/raster/rastpic.h
+++ b/src/raster/rastpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for raster module. */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,11 +20,11 @@
#define __RASTPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+FT_BEGIN_HEADER
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_STANDARD_RASTER_GET ft_standard_raster
@@ -48,15 +48,9 @@
void
ft_raster1_renderer_class_pic_free( FT_Library library );
- void
- ft_raster5_renderer_class_pic_free( FT_Library library );
-
FT_Error
ft_raster1_renderer_class_pic_init( FT_Library library );
- FT_Error
- ft_raster5_renderer_class_pic_init( FT_Library library );
-
#endif /* FT_CONFIG_OPTION_PIC */
/* */
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index 408f879..ea60452 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -4,7 +4,8 @@
/* */
/* PNG Bitmap glyph support. */
/* */
-/* Copyright 2013 by Google, Inc. */
+/* Copyright 2013-2015 by */
+/* Google, Inc. */
/* Written by Stuart Gill and Behdad Esfahbod. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -36,11 +37,11 @@
/* This code is freely based on cairo-png.c. There's so many ways */
/* to call libpng, and the way cairo does it is defacto standard. */
- static int
- multiply_alpha( int alpha,
- int color )
+ static unsigned int
+ multiply_alpha( unsigned int alpha,
+ unsigned int color )
{
- int temp = ( alpha * color ) + 0x80;
+ unsigned int temp = alpha * color + 0x80;
return ( temp + ( temp >> 8 ) ) >> 8;
@@ -81,10 +82,10 @@
blue = multiply_alpha( alpha, blue );
}
- base[0] = blue;
- base[1] = green;
- base[2] = red;
- base[3] = alpha;
+ base[0] = (unsigned char)blue;
+ base[1] = (unsigned char)green;
+ base[2] = (unsigned char)red;
+ base[3] = (unsigned char)alpha;
}
}
}
@@ -109,9 +110,9 @@
unsigned int blue = base[2];
- base[0] = blue;
- base[1] = green;
- base[2] = red;
+ base[0] = (unsigned char)blue;
+ base[1] = (unsigned char)green;
+ base[2] = (unsigned char)red;
base[3] = 0xFF;
}
}
@@ -122,14 +123,14 @@
error_callback( png_structp png,
png_const_charp error_msg )
{
- FT_Error* error = png_get_error_ptr( png );
+ FT_Error* error = (FT_Error*)png_get_error_ptr( png );
FT_UNUSED( error_msg );
*error = FT_THROW( Out_Of_Memory );
#ifdef PNG_SETJMP_SUPPORTED
- longjmp( png_jmpbuf( png ), 1 );
+ ft_longjmp( png_jmpbuf( png ), 1 );
#endif
/* if we get here, then we have no choice but to abort ... */
}
@@ -159,7 +160,7 @@
if ( FT_FRAME_ENTER( length ) )
{
- FT_Error* e = png_get_error_ptr( png );
+ FT_Error* e = (FT_Error*)png_get_error_ptr( png );
*e = FT_THROW( Invalid_Stream_Read );
@@ -174,16 +175,18 @@
}
- static FT_Error
- Load_SBit_Png( FT_Bitmap* map,
+ FT_LOCAL_DEF( FT_Error )
+ Load_SBit_Png( FT_GlyphSlot slot,
FT_Int x_offset,
FT_Int y_offset,
FT_Int pix_bits,
TT_SBit_Metrics metrics,
FT_Memory memory,
FT_Byte* data,
- FT_UInt png_len )
+ FT_UInt png_len,
+ FT_Bool populate_map_and_metrics )
{
+ FT_Bitmap *map = &slot->bitmap;
FT_Error error = FT_Err_Ok;
FT_StreamRec stream;
@@ -193,12 +196,21 @@
int bitdepth, color_type, interlace;
FT_Int i;
- png_byte* *rows;
+ png_byte* *rows = NULL; /* pacify compiler */
- if ( x_offset < 0 || x_offset + metrics->width > map->width ||
- y_offset < 0 || y_offset + metrics->height > map->rows ||
- pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA )
+ if ( x_offset < 0 ||
+ y_offset < 0 )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ if ( !populate_map_and_metrics &&
+ ( (FT_UInt)x_offset + metrics->width > map->width ||
+ (FT_UInt)y_offset + metrics->height > map->rows ||
+ pix_bits != 32 ||
+ map->pixel_mode != FT_PIXEL_MODE_BGRA ) )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
@@ -238,11 +250,41 @@
&bitdepth, &color_type, &interlace,
NULL, NULL );
- if ( error != FT_Err_Ok ||
- (FT_Int)imgWidth != metrics->width ||
- (FT_Int)imgHeight != metrics->height )
+ if ( error ||
+ ( !populate_map_and_metrics &&
+ ( (FT_Int)imgWidth != metrics->width ||
+ (FT_Int)imgHeight != metrics->height ) ) )
goto DestroyExit;
+ if ( populate_map_and_metrics )
+ {
+ FT_ULong size;
+
+
+ metrics->width = (FT_UShort)imgWidth;
+ metrics->height = (FT_UShort)imgHeight;
+
+ map->width = metrics->width;
+ map->rows = metrics->height;
+ map->pixel_mode = FT_PIXEL_MODE_BGRA;
+ map->pitch = (int)( map->width * 4 );
+ map->num_grays = 256;
+
+ /* reject too large bitmaps similarly to the rasterizer */
+ if ( map->rows > 0x7FFF || map->width > 0x7FFF )
+ {
+ error = FT_THROW( Array_Too_Large );
+ goto DestroyExit;
+ }
+
+ /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
+ size = map->rows * (FT_ULong)map->pitch;
+
+ error = ft_glyphslot_alloc_bitmap( slot, size );
+ if ( error )
+ goto DestroyExit;
+ }
+
/* convert palette/gray image to rgb */
if ( color_type == PNG_COLOR_TYPE_PALETTE )
png_set_palette_to_rgb( png );
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
index 8a2e69c..4cc5c2b 100644
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -4,7 +4,8 @@
/* */
/* PNG Bitmap glyph support. */
/* */
-/* Copyright 2013 by Google, Inc. */
+/* Copyright 2013-2015 by */
+/* Google, Inc. */
/* Written by Stuart Gill and Behdad Esfahbod. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,14 +30,15 @@
#ifdef FT_CONFIG_OPTION_USE_PNG
FT_LOCAL( FT_Error )
- Load_SBit_Png( FT_Bitmap* map,
+ Load_SBit_Png( FT_GlyphSlot slot,
FT_Int x_offset,
FT_Int y_offset,
FT_Int pix_bits,
TT_SBit_Metrics metrics,
FT_Memory memory,
FT_Byte* data,
- FT_UInt png_len );
+ FT_UInt png_len,
+ FT_Bool populate_map_and_metrics );
#endif
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index a368b8c..5dd8449 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (body). */
/* */
-/* Copyright 1996-2007, 2009-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -75,36 +75,36 @@
switch ( tag )
{
- case ft_sfnt_head:
+ case FT_SFNT_HEAD:
table = &face->header;
break;
- case ft_sfnt_hhea:
+ case FT_SFNT_HHEA:
table = &face->horizontal;
break;
- case ft_sfnt_vhea:
- table = face->vertical_info ? &face->vertical : 0;
+ case FT_SFNT_VHEA:
+ table = face->vertical_info ? &face->vertical : NULL;
break;
- case ft_sfnt_os2:
- table = face->os2.version == 0xFFFFU ? 0 : &face->os2;
+ case FT_SFNT_OS2:
+ table = face->os2.version == 0xFFFFU ? NULL : &face->os2;
break;
- case ft_sfnt_post:
+ case FT_SFNT_POST:
table = &face->postscript;
break;
- case ft_sfnt_maxp:
+ case FT_SFNT_MAXP:
table = &face->max_profile;
break;
- case ft_sfnt_pclt:
- table = face->pclt.Version ? &face->pclt : 0;
+ case FT_SFNT_PCLT:
+ table = face->pclt.Version ? &face->pclt : NULL;
break;
default:
- table = 0;
+ table = NULL;
}
return table;
@@ -139,9 +139,9 @@
FT_DEFINE_SERVICE_SFNT_TABLEREC(
sfnt_service_sfnt_table,
- (FT_SFNT_TableLoadFunc)tt_face_load_any,
- (FT_SFNT_TableGetFunc) get_sfnt_table,
- (FT_SFNT_TableInfoFunc)sfnt_table_info )
+ (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */
+ (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */
+ (FT_SFNT_TableInfoFunc)sfnt_table_info ) /* table_info */
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -205,8 +205,8 @@
FT_DEFINE_SERVICE_GLYPHDICTREC(
sfnt_service_glyph_dict,
- (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,
- (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
+ (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */
+ (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index ) /* name_index */
#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -266,7 +266,7 @@
{
FT_Stream stream = face->name_table.stream;
FT_String* r = (FT_String*)result;
- FT_Byte* p = (FT_Byte*)name->string;
+ FT_Char* p;
if ( FT_STREAM_SEEK( name->stringOffset ) ||
@@ -280,11 +280,11 @@
goto Exit;
}
- p = (FT_Byte*)stream->cursor;
+ p = (FT_Char*)stream->cursor;
for ( ; len > 0; len--, p += 2 )
{
- if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
+ if ( p[0] == 0 && p[1] >= 32 )
*r++ = p[1];
}
*r = '\0';
@@ -330,7 +330,7 @@
FT_DEFINE_SERVICE_PSFONTNAMEREC(
sfnt_service_ps_name,
- (FT_PsName_GetFunc)sfnt_get_ps_name )
+ (FT_PsName_GetFunc)sfnt_get_ps_name ) /* get_ps_font_name */
/*
@@ -338,7 +338,7 @@
*/
FT_DEFINE_SERVICE_TTCMAPSREC(
tt_service_get_cmap_info,
- (TT_CMap_Info_GetFunc)tt_get_cmap_info )
+ (TT_CMap_Info_GetFunc)tt_get_cmap_info ) /* get_cmap_info */
#ifdef TT_CONFIG_OPTION_BDF
@@ -381,8 +381,8 @@
FT_DEFINE_SERVICE_BDFRec(
sfnt_service_bdf,
- (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
- (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
+ (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */
+ (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop ) /* get_property */
#endif /* TT_CONFIG_OPTION_BDF */
@@ -427,7 +427,7 @@
sfnt_get_interface( FT_Module module,
const char* module_interface )
{
- /* SFNT_SERVICES_GET derefers `library' in PIC mode */
+ /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
FT_Library library;
@@ -499,13 +499,15 @@
tt_face_load_hmtx,
/* see `ttsbit.h' and `sfnt.h' */
- PUT_EMBEDDED_BITMAPS( tt_face_load_eblc ),
- PUT_EMBEDDED_BITMAPS( tt_face_free_eblc ),
+ PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
+ PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
- tt_face_get_metrics
+ tt_face_get_metrics,
+
+ tt_face_get_name
)
diff --git a/src/sfnt/sfdriver.h b/src/sfnt/sfdriver.h
index 5de25d5..944119c 100644
--- a/src/sfnt/sfdriver.h
+++ b/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (specification). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/sferrors.h b/src/sfnt/sferrors.h
index e981e1d..e3bef3f 100644
--- a/src/sfnt/sferrors.h
+++ b/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
/* */
/* SFNT error codes (specification only). */
/* */
-/* Copyright 2001, 2004, 2012, 2013 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c
index d62ed4e..0b8b5f4 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
/* */
/* Single object library component. */
/* */
-/* Copyright 1996-2006, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/sfntpic.c b/src/sfnt/sfntpic.c
index b3fb24b..2aaf4bc 100644
--- a/src/sfnt/sfntpic.c
+++ b/src/sfnt/sfntpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for sfnt module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/sfntpic.h b/src/sfnt/sfntpic.h
index b09a914..d99be6a 100644
--- a/src/sfnt/sfntpic.h
+++ b/src/sfnt/sfntpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for sfnt module. */
/* */
-/* Copyright 2009, 2012 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,8 +20,6 @@
#define __SFNTPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
@@ -31,7 +29,6 @@
#define SFNT_SERVICE_GLYPH_DICT_GET sfnt_service_glyph_dict
#define SFNT_SERVICE_PS_NAME_GET sfnt_service_ps_name
#define TT_SERVICE_CMAP_INFO_GET tt_service_get_cmap_info
-#define SFNT_SERVICES_GET sfnt_services
#define TT_CMAP_CLASSES_GET tt_cmap_classes
#define SFNT_SERVICE_SFNT_TABLE_GET sfnt_service_sfnt_table
#define SFNT_SERVICE_BDF_GET sfnt_service_bdf
@@ -56,6 +53,8 @@
#include "ttcmap.h"
+FT_BEGIN_HEADER
+
typedef struct sfntModulePIC_
{
FT_ServiceDescRec* sfnt_services;
@@ -83,8 +82,6 @@
( GET_PIC( library )->sfnt_service_ps_name )
#define TT_SERVICE_CMAP_INFO_GET \
( GET_PIC( library )->tt_service_get_cmap_info )
-#define SFNT_SERVICES_GET \
- ( GET_PIC( library )->sfnt_services )
#define TT_CMAP_CLASSES_GET \
( GET_PIC( library )->tt_cmap_classes )
#define SFNT_SERVICE_SFNT_TABLE_GET \
@@ -102,12 +99,13 @@
FT_Error
sfnt_module_class_pic_init( FT_Library library );
+
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-FT_END_HEADER
-
#endif /* __SFNTPIC_H__ */
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index f975e71..de030ea 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (base). */
/* */
-/* Copyright 1996-2008, 2010-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,6 +27,7 @@
#include FT_TRUETYPE_TAGS_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_SFNT_NAMES_H
+#include FT_GZIP_H
#include "sferrors.h"
#ifdef TT_CONFIG_OPTION_BDF
@@ -119,27 +120,9 @@
FT_Memory memory );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* tt_face_get_name */
- /* */
- /* <Description> */
- /* Returns a given ENGLISH name record in ASCII. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* nameid :: The name id of the name record to return. */
- /* */
- /* <InOut> */
- /* name :: The address of a string pointer. NULL if no name is */
- /* present. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static FT_Error
+ /* documentation is in sfnt.h */
+
+ FT_LOCAL_DEF( FT_Error )
tt_face_get_name( TT_Face face,
FT_UShort nameid,
FT_String** name )
@@ -347,6 +330,403 @@
}
+#define WRITE_USHORT( p, v ) \
+ do \
+ { \
+ *(p)++ = (FT_Byte)( (v) >> 8 ); \
+ *(p)++ = (FT_Byte)( (v) >> 0 ); \
+ \
+ } while ( 0 )
+
+#define WRITE_ULONG( p, v ) \
+ do \
+ { \
+ *(p)++ = (FT_Byte)( (v) >> 24 ); \
+ *(p)++ = (FT_Byte)( (v) >> 16 ); \
+ *(p)++ = (FT_Byte)( (v) >> 8 ); \
+ *(p)++ = (FT_Byte)( (v) >> 0 ); \
+ \
+ } while ( 0 )
+
+
+ static void
+ sfnt_stream_close( FT_Stream stream )
+ {
+ FT_Memory memory = stream->memory;
+
+
+ FT_FREE( stream->base );
+
+ stream->size = 0;
+ stream->base = NULL;
+ stream->close = NULL;
+ }
+
+
+ FT_CALLBACK_DEF( int )
+ compare_offsets( const void* a,
+ const void* b )
+ {
+ WOFF_Table table1 = *(WOFF_Table*)a;
+ WOFF_Table table2 = *(WOFF_Table*)b;
+
+ FT_ULong offset1 = table1->Offset;
+ FT_ULong offset2 = table2->Offset;
+
+
+ if ( offset1 > offset2 )
+ return 1;
+ else if ( offset1 < offset2 )
+ return -1;
+ else
+ return 0;
+ }
+
+
+ /* Replace `face->root.stream' with a stream containing the extracted */
+ /* SFNT of a WOFF font. */
+
+ static FT_Error
+ woff_open_font( FT_Stream stream,
+ TT_Face face )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error = FT_Err_Ok;
+
+ WOFF_HeaderRec woff;
+ WOFF_Table tables = NULL;
+ WOFF_Table* indices = NULL;
+
+ FT_ULong woff_offset;
+
+ FT_Byte* sfnt = NULL;
+ FT_Stream sfnt_stream = NULL;
+
+ FT_Byte* sfnt_header;
+ FT_ULong sfnt_offset;
+
+ FT_Int nn;
+ FT_ULong old_tag = 0;
+
+ static const FT_Frame_Field woff_header_fields[] =
+ {
+#undef FT_STRUCTURE
+#define FT_STRUCTURE WOFF_HeaderRec
+
+ FT_FRAME_START( 44 ),
+ FT_FRAME_ULONG ( signature ),
+ FT_FRAME_ULONG ( flavor ),
+ FT_FRAME_ULONG ( length ),
+ FT_FRAME_USHORT( num_tables ),
+ FT_FRAME_USHORT( reserved ),
+ FT_FRAME_ULONG ( totalSfntSize ),
+ FT_FRAME_USHORT( majorVersion ),
+ FT_FRAME_USHORT( minorVersion ),
+ FT_FRAME_ULONG ( metaOffset ),
+ FT_FRAME_ULONG ( metaLength ),
+ FT_FRAME_ULONG ( metaOrigLength ),
+ FT_FRAME_ULONG ( privOffset ),
+ FT_FRAME_ULONG ( privLength ),
+ FT_FRAME_END
+ };
+
+
+ FT_ASSERT( stream == face->root.stream );
+ FT_ASSERT( FT_STREAM_POS() == 0 );
+
+ if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) )
+ return error;
+
+ /* Make sure we don't recurse back here or hit TTC code. */
+ if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf )
+ return FT_THROW( Invalid_Table );
+
+ /* Miscellaneous checks. */
+ if ( woff.length != stream->size ||
+ woff.num_tables == 0 ||
+ 44 + woff.num_tables * 20UL >= woff.length ||
+ 12 + woff.num_tables * 16UL >= woff.totalSfntSize ||
+ ( woff.totalSfntSize & 3 ) != 0 ||
+ ( woff.metaOffset == 0 && ( woff.metaLength != 0 ||
+ woff.metaOrigLength != 0 ) ) ||
+ ( woff.metaLength != 0 && woff.metaOrigLength == 0 ) ||
+ ( woff.privOffset == 0 && woff.privLength != 0 ) )
+ {
+ FT_ERROR(( "woff_font_open: invalid WOFF header\n" ));
+ return FT_THROW( Invalid_Table );
+ }
+
+ /* Don't trust `totalSfntSize' before thorough checks. */
+ if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
+ FT_NEW( sfnt_stream ) )
+ goto Exit;
+
+ sfnt_header = sfnt;
+
+ /* Write sfnt header. */
+ {
+ FT_UInt searchRange, entrySelector, rangeShift, x;
+
+
+ x = woff.num_tables;
+ entrySelector = 0;
+ while ( x )
+ {
+ x >>= 1;
+ entrySelector += 1;
+ }
+ entrySelector--;
+
+ searchRange = ( 1 << entrySelector ) * 16;
+ rangeShift = woff.num_tables * 16 - searchRange;
+
+ WRITE_ULONG ( sfnt_header, woff.flavor );
+ WRITE_USHORT( sfnt_header, woff.num_tables );
+ WRITE_USHORT( sfnt_header, searchRange );
+ WRITE_USHORT( sfnt_header, entrySelector );
+ WRITE_USHORT( sfnt_header, rangeShift );
+ }
+
+ /* While the entries in the sfnt header must be sorted by the */
+ /* tag value, the tables themselves are not. We thus have to */
+ /* sort them by offset and check that they don't overlap. */
+
+ if ( FT_NEW_ARRAY( tables, woff.num_tables ) ||
+ FT_NEW_ARRAY( indices, woff.num_tables ) )
+ goto Exit;
+
+ FT_TRACE2(( "\n"
+ " tag offset compLen origLen checksum\n"
+ " -------------------------------------------\n" ));
+
+ if ( FT_FRAME_ENTER( 20L * woff.num_tables ) )
+ goto Exit;
+
+ for ( nn = 0; nn < woff.num_tables; nn++ )
+ {
+ WOFF_Table table = tables + nn;
+
+ table->Tag = FT_GET_TAG4();
+ table->Offset = FT_GET_ULONG();
+ table->CompLength = FT_GET_ULONG();
+ table->OrigLength = FT_GET_ULONG();
+ table->CheckSum = FT_GET_ULONG();
+
+ FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx %08lx\n",
+ (FT_Char)( table->Tag >> 24 ),
+ (FT_Char)( table->Tag >> 16 ),
+ (FT_Char)( table->Tag >> 8 ),
+ (FT_Char)( table->Tag ),
+ table->Offset,
+ table->CompLength,
+ table->OrigLength,
+ table->CheckSum ));
+
+ if ( table->Tag <= old_tag )
+ {
+ FT_FRAME_EXIT();
+
+ FT_ERROR(( "woff_font_open: table tags are not sorted\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ old_tag = table->Tag;
+ indices[nn] = table;
+ }
+
+ FT_FRAME_EXIT();
+
+ /* Sort by offset. */
+
+ ft_qsort( indices,
+ woff.num_tables,
+ sizeof ( WOFF_Table ),
+ compare_offsets );
+
+ /* Check offsets and lengths. */
+
+ woff_offset = 44 + woff.num_tables * 20L;
+ sfnt_offset = 12 + woff.num_tables * 16L;
+
+ for ( nn = 0; nn < woff.num_tables; nn++ )
+ {
+ WOFF_Table table = indices[nn];
+
+
+ if ( table->Offset != woff_offset ||
+ table->CompLength > woff.length ||
+ table->Offset > woff.length - table->CompLength ||
+ table->OrigLength > woff.totalSfntSize ||
+ sfnt_offset > woff.totalSfntSize - table->OrigLength ||
+ table->CompLength > table->OrigLength )
+ {
+ FT_ERROR(( "woff_font_open: invalid table offsets\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ table->OrigOffset = sfnt_offset;
+
+ /* The offsets must be multiples of 4. */
+ woff_offset += ( table->CompLength + 3 ) & ~3U;
+ sfnt_offset += ( table->OrigLength + 3 ) & ~3U;
+ }
+
+ /*
+ * Final checks!
+ *
+ * We don't decode and check the metadata block.
+ * We don't check table checksums either.
+ * But other than those, I think we implement all
+ * `MUST' checks from the spec.
+ */
+
+ if ( woff.metaOffset )
+ {
+ if ( woff.metaOffset != woff_offset ||
+ woff.metaOffset + woff.metaLength > woff.length )
+ {
+ FT_ERROR(( "woff_font_open:"
+ " invalid `metadata' offset or length\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* We have padding only ... */
+ woff_offset += woff.metaLength;
+ }
+
+ if ( woff.privOffset )
+ {
+ /* ... if it isn't the last block. */
+ woff_offset = ( woff_offset + 3 ) & ~3U;
+
+ if ( woff.privOffset != woff_offset ||
+ woff.privOffset + woff.privLength > woff.length )
+ {
+ FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* No padding for the last block. */
+ woff_offset += woff.privLength;
+ }
+
+ if ( sfnt_offset != woff.totalSfntSize ||
+ woff_offset != woff.length )
+ {
+ FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* Now use `totalSfntSize'. */
+ if ( FT_REALLOC( sfnt,
+ 12 + woff.num_tables * 16UL,
+ woff.totalSfntSize ) )
+ goto Exit;
+
+ sfnt_header = sfnt + 12;
+
+ /* Write the tables. */
+
+ for ( nn = 0; nn < woff.num_tables; nn++ )
+ {
+ WOFF_Table table = tables + nn;
+
+
+ /* Write SFNT table entry. */
+ WRITE_ULONG( sfnt_header, table->Tag );
+ WRITE_ULONG( sfnt_header, table->CheckSum );
+ WRITE_ULONG( sfnt_header, table->OrigOffset );
+ WRITE_ULONG( sfnt_header, table->OrigLength );
+
+ /* Write table data. */
+ if ( FT_STREAM_SEEK( table->Offset ) ||
+ FT_FRAME_ENTER( table->CompLength ) )
+ goto Exit;
+
+ if ( table->CompLength == table->OrigLength )
+ {
+ /* Uncompressed data; just copy. */
+ ft_memcpy( sfnt + table->OrigOffset,
+ stream->cursor,
+ table->OrigLength );
+ }
+ else
+ {
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+ /* Uncompress with zlib. */
+ FT_ULong output_len = table->OrigLength;
+
+
+ error = FT_Gzip_Uncompress( memory,
+ sfnt + table->OrigOffset, &output_len,
+ stream->cursor, table->CompLength );
+ if ( error )
+ goto Exit;
+ if ( output_len != table->OrigLength )
+ {
+ FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+ error = FT_THROW( Unimplemented_Feature );
+ goto Exit;
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+ }
+
+ FT_FRAME_EXIT();
+
+ /* We don't check whether the padding bytes in the WOFF file are */
+ /* actually '\0'. For the output, however, we do set them properly. */
+ sfnt_offset = table->OrigOffset + table->OrigLength;
+ while ( sfnt_offset & 3 )
+ {
+ sfnt[sfnt_offset] = '\0';
+ sfnt_offset++;
+ }
+ }
+
+ /* Ok! Finally ready. Swap out stream and return. */
+ FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize );
+ sfnt_stream->memory = stream->memory;
+ sfnt_stream->close = sfnt_stream_close;
+
+ FT_Stream_Free(
+ face->root.stream,
+ ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
+
+ face->root.stream = sfnt_stream;
+
+ face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+
+ Exit:
+ FT_FREE( tables );
+ FT_FREE( indices );
+
+ if ( error )
+ {
+ FT_FREE( sfnt );
+ FT_Stream_Close( sfnt_stream );
+ FT_FREE( sfnt_stream );
+ }
+
+ return error;
+ }
+
+
+#undef WRITE_USHORT
+#undef WRITE_ULONG
+
+
/* Fill in face->ttc_header. If the font is not a TTC, it is */
/* synthesized into a TTC with one offset table. */
static FT_Error
@@ -373,11 +753,28 @@
face->ttc_header.version = 0;
face->ttc_header.count = 0;
+ retry:
offset = FT_STREAM_POS();
if ( FT_READ_ULONG( tag ) )
return error;
+ if ( tag == TTAG_wOFF )
+ {
+ FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
+
+ if ( FT_STREAM_SEEK( offset ) )
+ return error;
+
+ error = woff_open_font( stream, face );
+ if ( error )
+ return error;
+
+ /* Swap out stream and retry! */
+ stream = face->root.stream;
+ goto retry;
+ }
+
if ( tag != 0x00010000UL &&
tag != TTAG_ttcf &&
tag != TTAG_OTTO &&
@@ -444,13 +841,14 @@
FT_LOCAL_DEF( FT_Error )
sfnt_init_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params )
{
- FT_Error error;
- FT_Library library = face->root.driver->root.library;
- SFNT_Service sfnt;
+ FT_Error error;
+ FT_Library library = face->root.driver->root.library;
+ SFNT_Service sfnt;
+ FT_Int face_index;
/* for now, parameters are unused */
@@ -480,22 +878,100 @@
if ( error )
return error;
- FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
+ /* Stream may have changed in sfnt_open_font. */
+ stream = face->root.stream;
- if ( face_index < 0 )
- face_index = 0;
+ FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index ));
+
+ face_index = FT_ABS( face_instance_index ) & 0xFFFF;
if ( face_index >= face->ttc_header.count )
- return FT_THROW( Invalid_Argument );
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ face_index = 0;
+ }
if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
return error;
- /* check that we have a valid TrueType file */
+ /* check whether we have a valid TrueType file */
error = sfnt->load_font_dir( face, stream );
if ( error )
return error;
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ {
+ FT_ULong fvar_len;
+
+ FT_ULong version;
+ FT_ULong offset;
+
+ FT_UShort num_axes;
+ FT_UShort axis_size;
+ FT_UShort num_instances;
+ FT_UShort instance_size;
+
+ FT_Int instance_index;
+
+
+ instance_index = FT_ABS( face_instance_index ) >> 16;
+
+ /* test whether current face is a GX font with named instances */
+ if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
+ fvar_len < 20 ||
+ FT_READ_ULONG( version ) ||
+ FT_READ_USHORT( offset ) ||
+ FT_STREAM_SKIP( 2 ) ||
+ FT_READ_USHORT( num_axes ) ||
+ FT_READ_USHORT( axis_size ) ||
+ FT_READ_USHORT( num_instances ) ||
+ FT_READ_USHORT( instance_size ) )
+ {
+ version = 0;
+ offset = 0;
+ num_axes = 0;
+ axis_size = 0;
+ num_instances = 0;
+ instance_size = 0;
+ }
+
+ /* check that the data is bound by the table length; */
+ /* based on similar code in function `TT_Get_MM_Var' */
+ if ( version != 0x00010000UL ||
+ axis_size != 20 ||
+ num_axes > 0x3FFE ||
+ instance_size != 4 + 4 * num_axes ||
+ num_instances > 0x7EFF ||
+ offset +
+ axis_size * num_axes +
+ instance_size * num_instances > fvar_len )
+ num_instances = 0;
+
+ /* we support at most 2^15 - 1 instances */
+ if ( num_instances >= ( 1U << 15 ) - 1 )
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ num_instances = 0;
+ }
+
+ /* instance indices in `face_instance_index' start with index 1, */
+ /* thus `>' and not `>=' */
+ if ( instance_index > num_instances )
+ {
+ if ( face_instance_index >= 0 )
+ return FT_THROW( Invalid_Argument );
+ else
+ num_instances = 0;
+ }
+
+ face->root.style_flags = (FT_Long)num_instances << 16;
+ }
+#endif
+
face->root.num_faces = face->ttc_header.count;
face->root.face_index = face_index;
@@ -504,7 +980,8 @@
#define LOAD_( x ) \
- do { \
+ do \
+ { \
FT_TRACE2(( "`" #x "' " )); \
FT_TRACE3(( "-->\n" )); \
\
@@ -519,7 +996,8 @@
} while ( 0 )
#define LOADM_( x, vertical ) \
- do { \
+ do \
+ { \
FT_TRACE2(( "`%s" #x "' ", \
vertical ? "vertical " : "" )); \
FT_TRACE3(( "-->\n" )); \
@@ -535,7 +1013,8 @@
} while ( 0 )
#define GET_NAME( id, field ) \
- do { \
+ do \
+ { \
error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
if ( error ) \
goto Exit; \
@@ -545,7 +1024,7 @@
FT_LOCAL_DEF( FT_Error )
sfnt_load_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params )
{
@@ -555,12 +1034,13 @@
#endif
FT_Bool has_outline;
FT_Bool is_apple_sbit;
+ FT_Bool is_apple_sbix;
FT_Bool ignore_preferred_family = FALSE;
FT_Bool ignore_preferred_subfamily = FALSE;
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
- FT_UNUSED( face_index );
+ FT_UNUSED( face_instance_index );
/* Check parameters */
@@ -608,6 +1088,13 @@
#endif
is_apple_sbit = 0;
+ is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
+
+ /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
+ * outline rendered on top. We don't support that yet, so just ignore
+ * the 'glyf' outline and advertise it as a bitmap-only font. */
+ if ( is_apple_sbix )
+ has_outline = FALSE;
/* if this font doesn't contain outlines, we try to load */
/* a `bhed' table */
@@ -619,7 +1106,7 @@
/* load the font header (`head' table) if this isn't an Apple */
/* sbit font file */
- if ( !is_apple_sbit )
+ if ( !is_apple_sbit || is_apple_sbix )
{
LOAD_( head );
if ( error )
@@ -803,6 +1290,10 @@
/* */
/* Compute face flags. */
/* */
+ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
+ face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
+ flags |= FT_FACE_FLAG_COLOR; /* color glyphs */
+
if ( has_outline == TRUE )
flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
@@ -871,7 +1362,7 @@
flags |= FT_STYLE_FLAG_ITALIC;
}
- root->style_flags = flags;
+ root->style_flags |= flags;
/*********************************************************************/
/* */
@@ -931,7 +1422,7 @@
if ( em_size == 0 || face->os2.version == 0xFFFFU )
{
- avgwidth = 0;
+ avgwidth = 1;
em_size = 1;
}
@@ -1018,8 +1509,8 @@
root->ascender = face->horizontal.Ascender;
root->descender = face->horizontal.Descender;
- root->height = (FT_Short)( root->ascender - root->descender +
- face->horizontal.Line_Gap );
+ root->height = root->ascender - root->descender +
+ face->horizontal.Line_Gap;
if ( !( root->ascender || root->descender ) )
{
@@ -1030,23 +1521,24 @@
root->ascender = face->os2.sTypoAscender;
root->descender = face->os2.sTypoDescender;
- root->height = (FT_Short)( root->ascender - root->descender +
- face->os2.sTypoLineGap );
+ root->height = root->ascender - root->descender +
+ face->os2.sTypoLineGap;
}
else
{
root->ascender = (FT_Short)face->os2.usWinAscent;
root->descender = -(FT_Short)face->os2.usWinDescent;
- root->height = (FT_UShort)( root->ascender - root->descender );
+ root->height = root->ascender - root->descender;
}
}
}
- root->max_advance_width = face->horizontal.advance_Width_Max;
- root->max_advance_height = (FT_Short)( face->vertical_info
- ? face->vertical.advance_Height_Max
- : root->height );
+ root->max_advance_width =
+ (FT_Short)face->horizontal.advance_Width_Max;
+ root->max_advance_height =
+ (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
+ : root->height );
/* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
/* Adjust underline position from top edge to centre of */
@@ -1156,7 +1648,7 @@
FT_FREE( face->postscript_name );
- face->sfnt = 0;
+ face->sfnt = NULL;
}
diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h
index 6241c93..455f867 100644
--- a/src/sfnt/sfobjs.h
+++ b/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,20 +31,25 @@
FT_LOCAL( FT_Error )
sfnt_init_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( FT_Error )
sfnt_load_face( FT_Stream stream,
TT_Face face,
- FT_Int face_index,
+ FT_Int face_instance_index,
FT_Int num_params,
FT_Parameter* params );
FT_LOCAL( void )
sfnt_done_face( TT_Face face );
+ FT_LOCAL( FT_Error )
+ tt_face_get_name( TT_Face face,
+ FT_UShort nameid,
+ FT_String** name );
+
FT_END_HEADER
diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c
index 9401dae..098b781 100644
--- a/src/sfnt/ttbdf.c
+++ b/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded BDF properties (body). */
/* */
-/* Copyright 2005, 2006, 2010, 2013 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttbdf.h b/src/sfnt/ttbdf.h
index 48a10d6..fe4ba48 100644
--- a/src/sfnt/ttbdf.h
+++ b/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded BDF properties (specification). */
/* */
-/* Copyright 2005 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 1507202..2b1337f 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
/* */
/* TrueType character mapping table (cmap) support (body). */
/* */
-/* Copyright 2002-2010, 2012, 2013 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -51,6 +51,13 @@
#define TT_NEXT_ULONG FT_NEXT_ULONG
+ /* Too large glyph index return values are caught in `FT_Get_Char_Index' */
+ /* and `FT_Get_Next_Char' (the latter calls the internal `next' function */
+ /* again in this case). To mark character code return values as invalid */
+ /* it is sufficient to set the corresponding glyph index return value to */
+ /* zero. */
+
+
FT_CALLBACK_DEF( FT_Error )
tt_cmap_init( TT_CMap cmap,
FT_Byte* table )
@@ -88,10 +95,16 @@
tt_cmap0_validate( FT_Byte* table,
FT_Validator valid )
{
- FT_Byte* p = table + 2;
- FT_UInt length = TT_NEXT_USHORT( p );
+ FT_Byte* p;
+ FT_UInt length;
+ if ( table + 2 + 2 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ p = table + 2; /* skip format */
+ length = TT_NEXT_USHORT( p );
+
if ( table + length > valid->limit || length < 262 )
FT_INVALID_TOO_SHORT;
@@ -193,7 +206,7 @@
/***** FORMAT 2 *****/
/***** *****/
/***** This is used for certain CJK encodings that encode text in a *****/
- /***** mixed 8/16 bits encoding along the following lines: *****/
+ /***** mixed 8/16 bits encoding along the following lines. *****/
/***** *****/
/***** * Certain byte values correspond to an 8-bit character code *****/
/***** (typically in the range 0..127 for ASCII compatibility). *****/
@@ -203,19 +216,19 @@
/***** second byte of a 2-byte character). *****/
/***** *****/
/***** The following charmap lookup and iteration functions all *****/
- /***** assume that the value "charcode" correspond to following: *****/
+ /***** assume that the value `charcode' fulfills the following. *****/
/***** *****/
- /***** - For one byte characters, "charcode" is simply the *****/
+ /***** - For one byte characters, `charcode' is simply the *****/
/***** character code. *****/
/***** *****/
- /***** - For two byte characters, "charcode" is the 2-byte *****/
- /***** character code in big endian format. More exactly: *****/
+ /***** - For two byte characters, `charcode' is the 2-byte *****/
+ /***** character code in big endian format. More precisely: *****/
/***** *****/
/***** (charcode >> 8) is the first byte value *****/
/***** (charcode & 0xFF) is the second byte value *****/
/***** *****/
- /***** Note that not all values of "charcode" are valid according *****/
- /***** to these rules, and the function moderately check the *****/
+ /***** Note that not all values of `charcode' are valid according *****/
+ /***** to these rules, and the function moderately checks the *****/
/***** arguments. *****/
/***** *****/
/*************************************************************************/
@@ -243,7 +256,7 @@
/* table, i.e., it is the corresponding sub-header index multiplied */
/* by 8. */
/* */
- /* Each sub-header has the following format: */
+ /* Each sub-header has the following format. */
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
@@ -258,11 +271,11 @@
/* according to the specification. */
/* */
/* If a character code is contained within a given sub-header, then */
- /* mapping it to a glyph index is done as follows: */
+ /* mapping it to a glyph index is done as follows. */
/* */
/* * The value of `offset' is read. This is a _byte_ distance from the */
/* location of the `offset' field itself into a slice of the */
- /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */
+ /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[], too). */
/* */
/* * The value `slice[char.lo - first]' is read. If it is 0, there is */
/* no glyph for the charcode. Otherwise, the value of `delta' is */
@@ -279,13 +292,20 @@
tt_cmap2_validate( FT_Byte* table,
FT_Validator valid )
{
- FT_Byte* p = table + 2; /* skip format */
- FT_UInt length = TT_PEEK_USHORT( p );
- FT_UInt n, max_subs;
- FT_Byte* keys; /* keys table */
- FT_Byte* subs; /* sub-headers */
- FT_Byte* glyph_ids; /* glyph ID array */
+ FT_Byte* p;
+ FT_UInt length;
+ FT_UInt n, max_subs;
+ FT_Byte* keys; /* keys table */
+ FT_Byte* subs; /* sub-headers */
+ FT_Byte* glyph_ids; /* glyph ID array */
+
+
+ if ( table + 2 + 2 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ p = table + 2; /* skip format */
+ length = TT_NEXT_USHORT( p );
if ( table + length > valid->limit || length < 6 + 512 )
FT_INVALID_TOO_SHORT;
@@ -313,16 +333,15 @@
FT_ASSERT( p == table + 518 );
subs = p;
- glyph_ids = subs + (max_subs + 1) * 8;
+ glyph_ids = subs + ( max_subs + 1 ) * 8;
if ( glyph_ids > valid->limit )
FT_INVALID_TOO_SHORT;
/* parse sub-headers */
for ( n = 0; n <= max_subs; n++ )
{
- FT_UInt first_code, code_count, offset;
- FT_Int delta;
- FT_Byte* ids;
+ FT_UInt first_code, code_count, offset;
+ FT_Int delta;
first_code = TT_NEXT_USHORT( p );
@@ -344,8 +363,11 @@
/* check offset */
if ( offset != 0 )
{
+ FT_Byte* ids;
+
+
ids = p - 2 + offset;
- if ( ids < glyph_ids || ids + code_count*2 > table + length )
+ if ( ids < glyph_ids || ids + code_count * 2 > table + length )
FT_INVALID_OFFSET;
/* check glyph IDs */
@@ -360,7 +382,7 @@
idx = TT_NEXT_USHORT( p );
if ( idx != 0 )
{
- idx = ( idx + delta ) & 0xFFFFU;
+ idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
FT_INVALID_GLYPH_ID;
}
@@ -421,6 +443,7 @@
}
result = sub;
}
+
Exit:
return result;
}
@@ -457,9 +480,10 @@
idx = TT_PEEK_USHORT( p );
if ( idx != 0 )
- result = (FT_UInt)( idx + delta ) & 0xFFFFU;
+ result = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
}
}
+
return result;
}
@@ -509,7 +533,7 @@
if ( idx != 0 )
{
- gindex = ( idx + delta ) & 0xFFFFU;
+ gindex = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
if ( gindex != 0 )
{
result = charcode;
@@ -750,7 +774,7 @@
if ( charcode < cmap->cur_start )
charcode = cmap->cur_start;
- for ( ;; )
+ for (;;)
{
FT_Byte* values = cmap->cur_values;
FT_UInt end = cmap->cur_end;
@@ -771,7 +795,7 @@
if ( gindex != 0 )
{
- gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
+ gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
if ( gindex != 0 )
{
cmap->cur_charcode = charcode;
@@ -785,7 +809,7 @@
{
do
{
- FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
+ FT_UInt gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
if ( gindex != 0 )
@@ -816,16 +840,20 @@
tt_cmap4_validate( FT_Byte* table,
FT_Validator valid )
{
- FT_Byte* p = table + 2; /* skip format */
- FT_UInt length = TT_NEXT_USHORT( p );
+ FT_Byte* p;
+ FT_UInt length;
+
FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
FT_UInt num_segs;
FT_Error error = FT_Err_Ok;
- if ( length < 16 )
+ if ( table + 2 + 2 > valid->limit )
FT_INVALID_TOO_SHORT;
+ p = table + 2; /* skip format */
+ length = TT_NEXT_USHORT( p );
+
/* in certain fonts, the `length' field is invalid and goes */
/* out of bound. We try to correct this here... */
if ( table + length > valid->limit )
@@ -836,6 +864,9 @@
length = (FT_UInt)( valid->limit - table );
}
+ if ( length < 16 )
+ FT_INVALID_TOO_SHORT;
+
p = table + 6;
num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
@@ -951,7 +982,7 @@
/* segment if it contains only a single character. */
/* */
/* We thus omit the test here, delaying it to the */
- /* routines which actually access the cmap. */
+ /* routines that actually access the cmap. */
else if ( n != num_segs - 1 ||
!( start == 0xFFFFU && end == 0xFFFFU ) )
{
@@ -971,7 +1002,7 @@
idx = FT_NEXT_USHORT( p );
if ( idx != 0 )
{
- idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
+ idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU;
if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
FT_INVALID_GLYPH_ID;
@@ -1004,12 +1035,17 @@
FT_UInt32* pcharcode,
FT_Bool next )
{
+ TT_Face face = (TT_Face)cmap->cmap.charmap.face;
+ FT_Byte* limit = face->cmap_table + face->cmap_size;
+
+
FT_UInt num_segs2, start, end, offset;
FT_Int delta;
FT_UInt i, num_segs;
FT_UInt32 charcode = *pcharcode;
FT_UInt gindex = 0;
FT_Byte* p;
+ FT_Byte* q;
p = cmap->data + 6;
@@ -1023,65 +1059,106 @@
if ( next )
charcode++;
+ if ( charcode > 0xFFFFU )
+ return 0;
+
/* linear search */
- for ( ; charcode <= 0xFFFFU; charcode++ )
+ p = cmap->data + 14; /* ends table */
+ q = cmap->data + 16 + num_segs2; /* starts table */
+
+ for ( i = 0; i < num_segs; i++ )
{
- FT_Byte* q;
+ end = TT_NEXT_USHORT( p );
+ start = TT_NEXT_USHORT( q );
-
- p = cmap->data + 14; /* ends table */
- q = cmap->data + 16 + num_segs2; /* starts table */
-
- for ( i = 0; i < num_segs; i++ )
+ if ( charcode < start )
{
- end = TT_NEXT_USHORT( p );
- start = TT_NEXT_USHORT( q );
-
- if ( charcode >= start && charcode <= end )
- {
- p = q - 2 + num_segs2;
- delta = TT_PEEK_SHORT( p );
- p += num_segs2;
- offset = TT_PEEK_USHORT( p );
-
- /* some fonts have an incorrect last segment; */
- /* we have to catch it */
- if ( i >= num_segs - 1 &&
- start == 0xFFFFU && end == 0xFFFFU )
- {
- TT_Face face = (TT_Face)cmap->cmap.charmap.face;
- FT_Byte* limit = face->cmap_table + face->cmap_size;
-
-
- if ( offset && p + offset + 2 > limit )
- {
- delta = 1;
- offset = 0;
- }
- }
-
- if ( offset == 0xFFFFU )
- continue;
-
- if ( offset )
- {
- p += offset + ( charcode - start ) * 2;
- gindex = TT_PEEK_USHORT( p );
- if ( gindex != 0 )
- gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
- }
- else
- gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
-
+ if ( next )
+ charcode = start;
+ else
break;
- }
}
- if ( !next || gindex )
+ Again:
+ if ( charcode <= end )
+ {
+ FT_Byte* r;
+
+
+ r = q - 2 + num_segs2;
+ delta = TT_PEEK_SHORT( r );
+ r += num_segs2;
+ offset = TT_PEEK_USHORT( r );
+
+ /* some fonts have an incorrect last segment; */
+ /* we have to catch it */
+ if ( i >= num_segs - 1 &&
+ start == 0xFFFFU && end == 0xFFFFU )
+ {
+ if ( offset && r + offset + 2 > limit )
+ {
+ delta = 1;
+ offset = 0;
+ }
+ }
+
+ if ( offset == 0xFFFFU )
+ continue;
+
+ if ( offset )
+ {
+ r += offset + ( charcode - start ) * 2;
+
+ /* if r > limit, the whole segment is invalid */
+ if ( next && r > limit )
+ continue;
+
+ gindex = TT_PEEK_USHORT( r );
+ if ( gindex )
+ {
+ gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
+ if ( gindex >= (FT_UInt)face->root.num_glyphs )
+ gindex = 0;
+ }
+ }
+ else
+ {
+ gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
+
+ if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
+ {
+ /* we have an invalid glyph index; if there is an overflow, */
+ /* we can adjust `charcode', otherwise the whole segment is */
+ /* invalid */
+ gindex = 0;
+
+ if ( (FT_Int)charcode + delta < 0 &&
+ (FT_Int)end + delta >= 0 )
+ charcode = (FT_UInt)( -delta );
+
+ else if ( (FT_Int)charcode + delta < 0x10000L &&
+ (FT_Int)end + delta >= 0x10000L )
+ charcode = (FT_UInt)( 0x10000L - delta );
+
+ else
+ continue;
+ }
+ }
+
+ if ( next && !gindex )
+ {
+ if ( charcode >= 0xFFFFU )
+ break;
+
+ charcode++;
+ goto Again;
+ }
+
break;
+ }
}
- if ( next && gindex )
+ if ( next )
*pcharcode = charcode;
return gindex;
@@ -1272,10 +1349,10 @@
p += offset + ( charcode - start ) * 2;
gindex = TT_PEEK_USHORT( p );
if ( gindex != 0 )
- gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
+ gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
}
else
- gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
+ gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
break;
}
@@ -1288,7 +1365,6 @@
/* if `charcode' is not in any segment, then `mid' is */
/* the segment nearest to `charcode' */
- /* */
if ( charcode > end )
{
@@ -1421,7 +1497,7 @@
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
- /* format 0 USHORT must be 4 */
+ /* format 0 USHORT must be 6 */
/* length 2 USHORT table length in bytes */
/* language 4 USHORT Mac language code */
/* */
@@ -1489,6 +1565,7 @@
p += 2 * idx;
result = TT_PEEK_USHORT( p );
}
+
return result;
}
@@ -1509,7 +1586,7 @@
if ( char_code >= 0x10000UL )
- goto Exit;
+ return 0;
if ( char_code < start )
char_code = start;
@@ -1525,10 +1602,13 @@
result = char_code;
break;
}
+
+ if ( char_code >= 0xFFFFU )
+ return 0;
+
char_code++;
}
- Exit:
*pchar_code = result;
return gindex;
}
@@ -1580,7 +1660,7 @@
/***** *****/
/***** The purpose of this format is to easily map UTF-16 text to *****/
/***** glyph indices. Basically, the `char_code' must be in one of *****/
- /***** the following formats: *****/
+ /***** the following formats. *****/
/***** *****/
/***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
/***** Area (i.e. U+D800-U+DFFF). *****/
@@ -1593,7 +1673,7 @@
/***** The `is32' table embedded in the charmap indicates whether a *****/
/***** given 16-bit value is in the surrogates area or not. *****/
/***** *****/
- /***** So, for any given `char_code', we can assert the following: *****/
+ /***** So, for any given `char_code', we can assert the following. *****/
/***** *****/
/***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
/***** *****/
@@ -1647,7 +1727,8 @@
p = is32 + 8192; /* skip `is32' array */
num_groups = TT_NEXT_ULONG( p );
- if ( p + num_groups * 12 > valid->limit )
+ /* p + num_groups * 12 > valid->limit ? */
+ if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 )
FT_INVALID_TOO_SHORT;
/* check groups, they must be in increasing order */
@@ -1672,7 +1753,12 @@
if ( valid->level >= FT_VALIDATE_TIGHT )
{
- if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_UInt32 d = end - start;
+
+
+ /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
+ if ( d > TT_VALID_GLYPH_COUNT( valid ) ||
+ start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
FT_INVALID_GLYPH_ID;
count = (FT_UInt32)( end - start + 1 );
@@ -1742,7 +1828,10 @@
if ( char_code <= end )
{
- result = (FT_UInt)( start_id + char_code - start );
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ return 0;
+
+ result = (FT_UInt)( start_id + ( char_code - start ) );
break;
}
}
@@ -1754,8 +1843,9 @@
tt_cmap8_char_next( TT_CMap cmap,
FT_UInt32 *pchar_code )
{
+ FT_Face face = cmap->cmap.charmap.face;
FT_UInt32 result = 0;
- FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt32 char_code;
FT_UInt gindex = 0;
FT_Byte* table = cmap->data;
FT_Byte* p = table + 8204;
@@ -1763,6 +1853,11 @@
FT_UInt32 start, end, start_id;
+ if ( *pchar_code >= 0xFFFFFFFFUL )
+ return 0;
+
+ char_code = *pchar_code + 1;
+
p = table + 8208;
for ( ; num_groups > 0; num_groups-- )
@@ -1774,18 +1869,38 @@
if ( char_code < start )
char_code = start;
+ Again:
if ( char_code <= end )
{
- gindex = (FT_UInt)( char_code - start + start_id );
- if ( gindex != 0 )
+ /* ignore invalid group */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ continue;
+
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+ /* does first element of group point to `.notdef' glyph? */
+ if ( gindex == 0 )
{
- result = char_code;
- goto Exit;
+ if ( char_code >= 0xFFFFFFFFUL )
+ break;
+
+ char_code++;
+ goto Again;
}
+
+ /* if `gindex' is invalid, the remaining values */
+ /* in this group are invalid, too */
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ {
+ gindex = 0;
+ continue;
+ }
+
+ result = char_code;
+ break;
}
}
- Exit:
*pchar_code = result;
return gindex;
}
@@ -1870,7 +1985,9 @@
count = TT_NEXT_ULONG( p );
if ( length > (FT_ULong)( valid->limit - table ) ||
- length < 20 + count * 2 )
+ /* length < 20 + count * 2 ? */
+ length < 20 ||
+ ( length - 20 ) / 2 < count )
FT_INVALID_TOO_SHORT;
/* check glyph indices */
@@ -1900,14 +2017,20 @@
FT_Byte* p = table + 12;
FT_UInt32 start = TT_NEXT_ULONG( p );
FT_UInt32 count = TT_NEXT_ULONG( p );
- FT_UInt32 idx = (FT_ULong)( char_code - start );
+ FT_UInt32 idx;
+ if ( char_code < start )
+ return 0;
+
+ idx = char_code - start;
+
if ( idx < count )
{
p += 2 * idx;
result = TT_PEEK_USHORT( p );
}
+
return result;
}
@@ -1917,7 +2040,7 @@
FT_UInt32 *pchar_code )
{
FT_Byte* table = cmap->data;
- FT_UInt32 char_code = *pchar_code + 1;
+ FT_UInt32 char_code;
FT_UInt gindex = 0;
FT_Byte* p = table + 12;
FT_UInt32 start = TT_NEXT_ULONG( p );
@@ -1925,10 +2048,15 @@
FT_UInt32 idx;
+ if ( *pchar_code >= 0xFFFFFFFFUL )
+ return 0;
+
+ char_code = *pchar_code + 1;
+
if ( char_code < start )
char_code = start;
- idx = (FT_UInt32)( char_code - start );
+ idx = char_code - start;
p += 2 * idx;
for ( ; idx < count; idx++ )
@@ -1936,6 +2064,10 @@
gindex = TT_NEXT_USHORT( p );
if ( gindex != 0 )
break;
+
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
}
@@ -2042,9 +2174,9 @@
tt_cmap12_validate( FT_Byte* table,
FT_Validator valid )
{
- FT_Byte* p;
- FT_ULong length;
- FT_ULong num_groups;
+ FT_Byte* p;
+ FT_ULong length;
+ FT_ULong num_groups;
if ( table + 16 > valid->limit )
@@ -2057,7 +2189,9 @@
num_groups = TT_NEXT_ULONG( p );
if ( length > (FT_ULong)( valid->limit - table ) ||
- length < 16 + 12 * num_groups )
+ /* length < 16 + 12 * num_groups ? */
+ length < 16 ||
+ ( length - 16 ) / 12 < num_groups )
FT_INVALID_TOO_SHORT;
/* check groups, they must be in increasing order */
@@ -2079,7 +2213,12 @@
if ( valid->level >= FT_VALIDATE_TIGHT )
{
- if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
+ FT_UInt32 d = end - start;
+
+
+ /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */
+ if ( d > TT_VALID_GLYPH_COUNT( valid ) ||
+ start_id >= TT_VALID_GLYPH_COUNT( valid ) - d )
FT_INVALID_GLYPH_ID;
}
@@ -2097,6 +2236,7 @@
static void
tt_cmap12_next( TT_CMap12 cmap )
{
+ FT_Face face = cmap->cmap.cmap.charmap.face;
FT_Byte* p;
FT_ULong start, end, start_id, char_code;
FT_ULong n;
@@ -2108,8 +2248,6 @@
char_code = cmap->cur_charcode + 1;
- n = cmap->cur_group;
-
for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
{
p = cmap->cmap.data + 16 + 12 * n;
@@ -2120,18 +2258,38 @@
if ( char_code < start )
char_code = start;
- for ( ; char_code <= end; char_code++ )
+ Again:
+ if ( char_code <= end )
{
- gindex = (FT_UInt)( start_id + char_code - start );
+ /* ignore invalid group */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ continue;
- if ( gindex )
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
+
+ /* does first element of group point to `.notdef' glyph? */
+ if ( gindex == 0 )
{
- cmap->cur_charcode = char_code;;
- cmap->cur_gindex = gindex;
- cmap->cur_group = n;
+ if ( char_code >= 0xFFFFFFFFUL )
+ goto Fail;
- return;
+ char_code++;
+ goto Again;
}
+
+ /* if `gindex' is invalid, the remaining values */
+ /* in this group are invalid, too */
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ {
+ gindex = 0;
+ continue;
+ }
+
+ cmap->cur_charcode = char_code;
+ cmap->cur_gindex = gindex;
+ cmap->cur_group = n;
+
+ return;
}
}
@@ -2161,7 +2319,12 @@
end = 0xFFFFFFFFUL;
if ( next )
+ {
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
+ }
min = 0;
max = num_groups;
@@ -2182,20 +2345,24 @@
else
{
start_id = TT_PEEK_ULONG( p );
- gindex = (FT_UInt)( start_id + char_code - start );
+ /* reject invalid glyph index */
+ if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) )
+ gindex = 0;
+ else
+ gindex = (FT_UInt)( start_id + ( char_code - start ) );
break;
}
}
if ( next )
{
+ FT_Face face = cmap->cmap.charmap.face;
TT_CMap12 cmap12 = (TT_CMap12)cmap;
/* if `char_code' is not in any group, then `mid' is */
/* the group nearest to `char_code' */
- /* */
if ( char_code > end )
{
@@ -2208,6 +2375,9 @@
cmap12->cur_charcode = char_code;
cmap12->cur_group = mid;
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ gindex = 0;
+
if ( !gindex )
{
tt_cmap12_next( cmap12 );
@@ -2218,8 +2388,7 @@
else
cmap12->cur_gindex = gindex;
- if ( gindex )
- *pchar_code = cmap12->cur_charcode;
+ *pchar_code = cmap12->cur_charcode;
}
return gindex;
@@ -2239,23 +2408,17 @@
FT_UInt32 *pchar_code )
{
TT_CMap12 cmap12 = (TT_CMap12)cmap;
- FT_ULong gindex;
+ FT_UInt gindex;
- if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
- return 0;
-
/* no need to search */
if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
{
tt_cmap12_next( cmap12 );
if ( cmap12->valid )
{
- gindex = cmap12->cur_gindex;
-
- /* XXX: check cur_charcode overflow is expected */
- if ( gindex )
- *pchar_code = (FT_UInt32)cmap12->cur_charcode;
+ gindex = cmap12->cur_gindex;
+ *pchar_code = (FT_UInt32)cmap12->cur_charcode;
}
else
gindex = 0;
@@ -2263,8 +2426,7 @@
else
gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
- /* XXX: check gindex overflow is expected */
- return (FT_UInt32)gindex;
+ return gindex;
}
@@ -2381,7 +2543,9 @@
num_groups = TT_NEXT_ULONG( p );
if ( length > (FT_ULong)( valid->limit - table ) ||
- length < 16 + 12 * num_groups )
+ /* length < 16 + 12 * num_groups ? */
+ length < 16 ||
+ ( length - 16 ) / 12 < num_groups )
FT_INVALID_TOO_SHORT;
/* check groups, they must be in increasing order */
@@ -2421,6 +2585,7 @@
static void
tt_cmap13_next( TT_CMap13 cmap )
{
+ FT_Face face = cmap->cmap.cmap.charmap.face;
FT_Byte* p;
FT_ULong start, end, glyph_id, char_code;
FT_ULong n;
@@ -2432,8 +2597,6 @@
char_code = cmap->cur_charcode + 1;
- n = cmap->cur_group;
-
for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
{
p = cmap->cmap.data + 16 + 12 * n;
@@ -2448,9 +2611,9 @@
{
gindex = (FT_UInt)glyph_id;
- if ( gindex )
+ if ( gindex && gindex < (FT_UInt)face->num_glyphs )
{
- cmap->cur_charcode = char_code;;
+ cmap->cur_charcode = char_code;
cmap->cur_gindex = gindex;
cmap->cur_group = n;
@@ -2485,7 +2648,12 @@
end = 0xFFFFFFFFUL;
if ( next )
+ {
+ if ( char_code >= 0xFFFFFFFFUL )
+ return 0;
+
char_code++;
+ }
min = 0;
max = num_groups;
@@ -2513,6 +2681,7 @@
if ( next )
{
+ FT_Face face = cmap->cmap.charmap.face;
TT_CMap13 cmap13 = (TT_CMap13)cmap;
@@ -2530,6 +2699,9 @@
cmap13->cur_charcode = char_code;
cmap13->cur_group = mid;
+ if ( gindex >= (FT_UInt)face->num_glyphs )
+ gindex = 0;
+
if ( !gindex )
{
tt_cmap13_next( cmap13 );
@@ -2540,8 +2712,7 @@
else
cmap13->cur_gindex = gindex;
- if ( gindex )
- *pchar_code = cmap13->cur_charcode;
+ *pchar_code = cmap13->cur_charcode;
}
return gindex;
@@ -2564,18 +2735,14 @@
FT_UInt gindex;
- if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
- return 0;
-
/* no need to search */
if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
{
tt_cmap13_next( cmap13 );
if ( cmap13->valid )
{
- gindex = cmap13->cur_gindex;
- if ( gindex )
- *pchar_code = cmap13->cur_charcode;
+ gindex = cmap13->cur_gindex;
+ *pchar_code = cmap13->cur_charcode;
}
else
gindex = 0;
@@ -2756,13 +2923,22 @@
tt_cmap14_validate( FT_Byte* table,
FT_Validator valid )
{
- FT_Byte* p = table + 2;
- FT_ULong length = TT_NEXT_ULONG( p );
- FT_ULong num_selectors = TT_NEXT_ULONG( p );
+ FT_Byte* p;
+ FT_ULong length;
+ FT_ULong num_selectors;
+ if ( table + 2 + 4 + 4 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ p = table + 2;
+ length = TT_NEXT_ULONG( p );
+ num_selectors = TT_NEXT_ULONG( p );
+
if ( length > (FT_ULong)( valid->limit - table ) ||
- length < 10 + 11 * num_selectors )
+ /* length < 10 + 11 * num_selectors ? */
+ length < 10 ||
+ ( length - 10 ) / 11 < num_selectors )
FT_INVALID_TOO_SHORT;
/* check selectors, they must be in increasing order */
@@ -2792,13 +2968,19 @@
/* through the normal Unicode cmap, no GIDs, just check order) */
if ( defOff != 0 )
{
- FT_Byte* defp = table + defOff;
- FT_ULong numRanges = TT_NEXT_ULONG( defp );
+ FT_Byte* defp = table + defOff;
+ FT_ULong numRanges;
FT_ULong i;
- FT_ULong lastBase = 0;
+ FT_ULong lastBase = 0;
- if ( defp + numRanges * 4 > valid->limit )
+ if ( defp + 4 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ numRanges = TT_NEXT_ULONG( defp );
+
+ /* defp + numRanges * 4 > valid->limit ? */
+ if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 )
FT_INVALID_TOO_SHORT;
for ( i = 0; i < numRanges; ++i )
@@ -2820,12 +3002,18 @@
/* and the non-default table (these glyphs are specified here) */
if ( nondefOff != 0 )
{
- FT_Byte* ndp = table + nondefOff;
- FT_ULong numMappings = TT_NEXT_ULONG( ndp );
- FT_ULong i, lastUni = 0;
+ FT_Byte* ndp = table + nondefOff;
+ FT_ULong numMappings;
+ FT_ULong i, lastUni = 0;
- if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
+ if ( ndp + 4 > valid->limit )
+ FT_INVALID_TOO_SHORT;
+
+ numMappings = TT_NEXT_ULONG( ndp );
+
+ /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */
+ if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 )
FT_INVALID_TOO_SHORT;
for ( i = 0; i < numMappings; ++i )
@@ -3208,7 +3396,6 @@
{
FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6,
variantSelector );
- FT_UInt32 *ret;
FT_Int i;
FT_ULong defOff;
FT_ULong nondefOff;
@@ -3242,6 +3429,8 @@
FT_Byte* dp;
FT_UInt di, ni, k;
+ FT_UInt32 *ret;
+
p = cmap->data + nondefOff;
dp = cmap->data + defOff;
@@ -3269,7 +3458,7 @@
ni = 1;
i = 0;
- for ( ;; )
+ for (;;)
{
if ( nuni > duni + dcnt )
{
@@ -3447,23 +3636,14 @@
/* only recognize format 0 */
if ( TT_NEXT_USHORT( p ) != 0 )
{
- p -= 2;
FT_ERROR(( "tt_face_build_cmaps:"
" unsupported `cmap' table format = %d\n",
- TT_PEEK_USHORT( p ) ));
+ TT_PEEK_USHORT( p - 2 ) ));
return FT_THROW( Invalid_Table );
}
num_cmaps = TT_NEXT_USHORT( p );
-#ifdef FT_MAX_CHARMAP_CACHEABLE
- if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
- FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
- " subtable #%d and higher are loaded"
- " but cannot be searched\n",
- num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
-#endif
-
for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
{
FT_CharMapRec charmap;
diff --git a/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h
index 0fde167..b7ea8ee 100644
--- a/src/sfnt/ttcmap.h
+++ b/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
/* */
/* TrueType character mapping table (cmap) support (specification). */
/* */
-/* Copyright 2002-2005, 2009, 2012 by */
+/* Copyright 2002-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttcmapc.h b/src/sfnt/ttcmapc.h
index 2ea2043..4a48940 100644
--- a/src/sfnt/ttcmapc.h
+++ b/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
/* */
/* TT CMAP classes definitions (specification only). */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c
index 60ee546..4fccc53 100644
--- a/src/sfnt/ttkern.c
+++ b/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
/* Load the basic TrueType kerning table. This doesn't handle */
/* kerning data within the GPOS table at the moment. */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -99,7 +99,7 @@
length = FT_NEXT_USHORT( p );
coverage = FT_NEXT_USHORT( p );
- if ( length <= 6 )
+ if ( length <= 6 + 8 )
break;
p_next += length;
@@ -108,8 +108,8 @@
p_next = p_limit;
/* only use horizontal kerning tables */
- if ( ( coverage & ~8 ) != 0x0001 ||
- p + 8 > p_limit )
+ if ( ( coverage & ~8U ) != 0x0001 ||
+ p + 8 > p_limit )
goto NextTable;
num_pairs = FT_NEXT_USHORT( p );
@@ -183,7 +183,7 @@
FT_UInt right_glyph )
{
FT_Int result = 0;
- FT_UInt count, mask = 1;
+ FT_UInt count, mask;
FT_Byte* p = face->kern_table;
FT_Byte* p_limit = p + face->kern_table_size;
@@ -196,7 +196,7 @@
count--, mask <<= 1 )
{
FT_Byte* base = p;
- FT_Byte* next = base;
+ FT_Byte* next;
FT_UInt version = FT_NEXT_USHORT( p );
FT_UInt length = FT_NEXT_USHORT( p );
FT_UInt coverage = FT_NEXT_USHORT( p );
diff --git a/src/sfnt/ttkern.h b/src/sfnt/ttkern.h
index df1da9b..89cb24f 100644
--- a/src/sfnt/ttkern.h
+++ b/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
/* Load the basic TrueType kerning table. This doesn't handle */
/* kerning data within the GPOS table at the moment. */
/* */
-/* Copyright 1996-2001, 2002, 2005, 2007 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index fbe70f7..c1bd7f0 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
/* Load the basic TrueType tables, i.e., tables that can be either in */
/* TTF or OTF fonts (body). */
/* */
-/* Copyright 1996-2010, 2012, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -151,7 +151,8 @@
/* Here, we */
/* */
- /* - check that `num_tables' is valid (and adjust it if necessary) */
+ /* - check that `num_tables' is valid (and adjust it if necessary); */
+ /* also return the number of valid table entries */
/* */
/* - look for a `head' table, check its size, and parse it to check */
/* whether its `magic' field is correctly set */
@@ -167,7 +168,8 @@
/* */
static FT_Error
check_table_dir( SFNT_Header sfnt,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_UShort* valid )
{
FT_Error error;
FT_UShort nn, valid_entries = 0;
@@ -207,11 +209,28 @@
}
/* we ignore invalid tables */
- if ( table.Offset + table.Length > stream->size )
+
+ if ( table.Offset > stream->size )
{
FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
continue;
}
+ else if ( table.Length > stream->size - table.Offset )
+ {
+ /* Some tables have such a simple structure that clipping its */
+ /* contents is harmless. This also makes FreeType less sensitive */
+ /* to invalid table lengths (which programs like Acroread seem to */
+ /* ignore in general). */
+
+ if ( table.Tag == TTAG_hmtx ||
+ table.Tag == TTAG_vmtx )
+ valid_entries++;
+ else
+ {
+ FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
+ continue;
+ }
+ }
else
valid_entries++;
@@ -236,7 +255,8 @@
*/
if ( table.Length < 0x36 )
{
- FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
+ FT_TRACE2(( "check_table_dir:"
+ " `head' or `bhed' table too small\n" ));
error = FT_THROW( Table_Missing );
goto Exit;
}
@@ -246,12 +266,8 @@
goto Exit;
if ( magic != 0x5F0F3CF5UL )
- {
FT_TRACE2(( "check_table_dir:"
- " no magic number found in `head' table\n"));
- error = FT_THROW( Table_Missing );
- goto Exit;
- }
+ " invalid magic number in `head' or `bhed' table\n"));
if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
goto Exit;
@@ -262,11 +278,11 @@
has_meta = 1;
}
- sfnt->num_tables = valid_entries;
+ *valid = valid_entries;
- if ( sfnt->num_tables == 0 )
+ if ( !valid_entries )
{
- FT_TRACE2(( "check_table_dir: no tables found\n" ));
+ FT_TRACE2(( "check_table_dir: no valid tables found\n" ));
error = FT_THROW( Unknown_File_Format );
goto Exit;
}
@@ -322,8 +338,7 @@
SFNT_HeaderRec sfnt;
FT_Error error;
FT_Memory memory = stream->memory;
- TT_TableRec* entry;
- FT_Int nn;
+ FT_UShort nn, valid_entries;
static const FT_Frame_Field offset_table_fields[] =
{
@@ -364,56 +379,114 @@
if ( sfnt.format_tag != TTAG_OTTO )
{
/* check first */
- error = check_table_dir( &sfnt, stream );
+ error = check_table_dir( &sfnt, stream, &valid_entries );
if ( error )
{
FT_TRACE2(( "tt_face_load_font_dir:"
" invalid table directory for TrueType\n" ));
-
goto Exit;
}
}
+ else
+ valid_entries = sfnt.num_tables;
- face->num_tables = sfnt.num_tables;
+ face->num_tables = valid_entries;
face->format_tag = sfnt.format_tag;
if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
goto Exit;
- if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
- FT_FRAME_ENTER( face->num_tables * 16L ) )
+ if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
+ FT_FRAME_ENTER( sfnt.num_tables * 16L ) )
goto Exit;
- entry = face->dir_tables;
-
FT_TRACE2(( "\n"
" tag offset length checksum\n"
" ----------------------------------\n" ));
+ valid_entries = 0;
for ( nn = 0; nn < sfnt.num_tables; nn++ )
{
- entry->Tag = FT_GET_TAG4();
- entry->CheckSum = FT_GET_ULONG();
- entry->Offset = FT_GET_LONG();
- entry->Length = FT_GET_LONG();
+ TT_TableRec entry;
+ FT_UShort i;
+ FT_Bool duplicate;
- /* ignore invalid tables */
- if ( entry->Offset + entry->Length > stream->size )
+
+ entry.Tag = FT_GET_TAG4();
+ entry.CheckSum = FT_GET_ULONG();
+ entry.Offset = FT_GET_ULONG();
+ entry.Length = FT_GET_ULONG();
+
+ /* ignore invalid tables that can't be sanitized */
+
+ if ( entry.Offset > stream->size )
continue;
+ else if ( entry.Length > stream->size - entry.Offset )
+ {
+ if ( entry.Tag == TTAG_hmtx ||
+ entry.Tag == TTAG_vmtx )
+ {
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_ULong old_length = entry.Length;
+#endif
+
+
+ /* make metrics table length a multiple of 4 */
+ entry.Length = ( stream->size - entry.Offset ) & ~3U;
+
+ FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx"
+ " (sanitized; original length %08lx)",
+ (FT_Char)( entry.Tag >> 24 ),
+ (FT_Char)( entry.Tag >> 16 ),
+ (FT_Char)( entry.Tag >> 8 ),
+ (FT_Char)( entry.Tag ),
+ entry.Offset,
+ entry.Length,
+ entry.CheckSum,
+ old_length ));
+ }
+ else
+ continue;
+ }
+#ifdef FT_DEBUG_LEVEL_TRACE
+ else
+ FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx",
+ (FT_Char)( entry.Tag >> 24 ),
+ (FT_Char)( entry.Tag >> 16 ),
+ (FT_Char)( entry.Tag >> 8 ),
+ (FT_Char)( entry.Tag ),
+ entry.Offset,
+ entry.Length,
+ entry.CheckSum ));
+#endif
+
+ /* ignore duplicate tables – the first one wins */
+ duplicate = 0;
+ for ( i = 0; i < valid_entries; i++ )
+ {
+ if ( face->dir_tables[i].Tag == entry.Tag )
+ {
+ duplicate = 1;
+ break;
+ }
+ }
+ if ( duplicate )
+ {
+ FT_TRACE2(( " (duplicate, ignored)\n" ));
+ continue;
+ }
else
{
- FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx\n",
- (FT_Char)( entry->Tag >> 24 ),
- (FT_Char)( entry->Tag >> 16 ),
- (FT_Char)( entry->Tag >> 8 ),
- (FT_Char)( entry->Tag ),
- entry->Offset,
- entry->Length,
- entry->CheckSum ));
- entry++;
+ FT_TRACE2(( "\n" ));
+
+ /* we finally have a valid entry */
+ face->dir_tables[valid_entries++] = entry;
}
}
+ /* final adjustment to number of tables */
+ face->num_tables = valid_entries;
+
FT_FRAME_EXIT();
FT_TRACE2(( "table directory loaded\n\n" ));
@@ -1006,7 +1079,8 @@
FT_FRAME_END
};
- static const FT_Frame_Field os2_fields_extra[] =
+ /* `OS/2' version 1 and newer */
+ static const FT_Frame_Field os2_fields_extra1[] =
{
FT_FRAME_START( 8 ),
FT_FRAME_ULONG( ulCodePageRange1 ),
@@ -1014,6 +1088,7 @@
FT_FRAME_END
};
+ /* `OS/2' version 2 and newer */
static const FT_Frame_Field os2_fields_extra2[] =
{
FT_FRAME_START( 10 ),
@@ -1025,6 +1100,15 @@
FT_FRAME_END
};
+ /* `OS/2' version 5 and newer */
+ static const FT_Frame_Field os2_fields_extra5[] =
+ {
+ FT_FRAME_START( 4 ),
+ FT_FRAME_USHORT( usLowerOpticalPointSize ),
+ FT_FRAME_USHORT( usUpperOpticalPointSize ),
+ FT_FRAME_END
+ };
+
/* We now support old Mac fonts where the OS/2 table doesn't */
/* exist. Simply put, we set the `version' field to 0xFFFF */
@@ -1038,18 +1122,20 @@
if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
goto Exit;
- os2->ulCodePageRange1 = 0;
- os2->ulCodePageRange2 = 0;
- os2->sxHeight = 0;
- os2->sCapHeight = 0;
- os2->usDefaultChar = 0;
- os2->usBreakChar = 0;
- os2->usMaxContext = 0;
+ os2->ulCodePageRange1 = 0;
+ os2->ulCodePageRange2 = 0;
+ os2->sxHeight = 0;
+ os2->sCapHeight = 0;
+ os2->usDefaultChar = 0;
+ os2->usBreakChar = 0;
+ os2->usMaxContext = 0;
+ os2->usLowerOpticalPointSize = 0;
+ os2->usUpperOpticalPointSize = 0xFFFF;
if ( os2->version >= 0x0001 )
{
/* only version 1 tables */
- if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra1, os2 ) )
goto Exit;
if ( os2->version >= 0x0002 )
@@ -1057,6 +1143,13 @@
/* only version 2 tables */
if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
goto Exit;
+
+ if ( os2->version >= 0x0005 )
+ {
+ /* only version 5 tables */
+ if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) )
+ goto Exit;
+ }
}
}
@@ -1164,6 +1257,7 @@
FT_FRAME_USHORT( Style ),
FT_FRAME_USHORT( TypeFamily ),
FT_FRAME_USHORT( CapHeight ),
+ FT_FRAME_USHORT( SymbolSet ),
FT_FRAME_BYTES ( TypeFace, 16 ),
FT_FRAME_BYTES ( CharacterComplement, 8 ),
FT_FRAME_BYTES ( FileName, 6 ),
diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h
index 49a1aee..a6d91c5 100644
--- a/src/sfnt/ttload.h
+++ b/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
/* Load the basic TrueType tables, i.e., tables that can be either in */
/* TTF or OTF fonts (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2005, 2006 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 371a9ed..58309aa 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
/* */
/* Load the metrics tables common to TTF and OTF fonts (body). */
/* */
-/* Copyright 2006-2009, 2011-2013 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -183,22 +183,25 @@
/* tt_face_get_metrics */
/* */
/* <Description> */
- /* Returns the 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). */
+ /* Return the horizontal or vertical metrics in font units for a */
+ /* given glyph. The values are the left side bearing (top side */
+ /* bearing for vertical metrics) and advance width (advance height */
+ /* for vertical metrics). */
/* */
/* <Input> */
- /* header :: A pointer to either the horizontal or vertical metrics */
- /* structure. */
+ /* face :: A pointer to the TrueType face structure. */
/* */
- /* idx :: The glyph index. */
+ /* vertical :: If set to TRUE, get vertical metrics. */
+ /* */
+ /* gindex :: The glyph index. */
/* */
/* <Output> */
- /* bearing :: The bearing, either left side or top side. */
+ /* abearing :: The bearing, either left side or top side. */
/* */
- /* advance :: The advance width resp. advance height. */
+ /* aadvance :: The advance width or advance height, depending on */
+ /* the `vertical' flag. */
/* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
tt_face_get_metrics( TT_Face face,
FT_Bool vertical,
FT_UInt gindex,
@@ -271,8 +274,6 @@
*abearing = 0;
*aadvance = 0;
}
-
- return FT_Err_Ok;
}
diff --git a/src/sfnt/ttmtx.h b/src/sfnt/ttmtx.h
index 8b91a11..096ee06 100644
--- a/src/sfnt/ttmtx.h
+++ b/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
/* */
/* Load the metrics tables common to TTF and OTF fonts (specification). */
/* */
-/* Copyright 2006 by */
+/* Copyright 2006-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -40,7 +40,7 @@
FT_Bool vertical );
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
tt_face_get_metrics( TT_Face face,
FT_Bool vertical,
FT_UInt gindex,
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index 47a85c0..8d29d1e 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
/* Postcript name table processing for TrueType and OpenType fonts */
/* (body). */
/* */
-/* Copyright 1996-2003, 2006-2010, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -52,7 +52,7 @@
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
-#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) )
+#define MAC_NAME( x ) (FT_String*)psnames->macintosh_name( (FT_UInt)(x) )
#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
@@ -62,14 +62,14 @@
/* table of Mac names. Thus, it is possible to build a version of */
/* FreeType without the Type 1 driver & PSNames module. */
-#define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] )
+#define MAC_NAME( x ) (FT_String*)tt_post_default_names[x]
- /* the 258 default Mac PS glyph names */
+ /* the 258 default Mac PS glyph names; see file `tools/glnames.py' */
static const FT_String* const tt_post_default_names[258] =
{
/* 0 */
- ".notdef", ".null", "CR", "space", "exclam",
+ ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
"quotedbl", "numbersign", "dollar", "percent", "ampersand",
/* 10 */
"quotesingle", "parenleft", "parenright", "asterisk", "plus",
@@ -120,7 +120,7 @@
"ae", "oslash", "questiondown", "exclamdown", "logicalnot",
"radical", "florin", "approxequal", "Delta", "guillemotleft",
/* 170 */
- "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
+ "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
"Otilde", "OE", "oe", "endash", "emdash",
/* 180 */
"quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
@@ -144,8 +144,8 @@
"multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
"onequarter", "threequarters", "franc", "Gbreve", "gbreve",
/* 250 */
- "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
- "Ccaron", "ccaron", "dmacron",
+ "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
+ "Ccaron", "ccaron", "dcroat",
};
@@ -155,7 +155,7 @@
static FT_Error
load_format_20( TT_Face face,
FT_Stream stream,
- FT_Long post_limit )
+ FT_ULong post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -163,8 +163,8 @@
FT_Int num_glyphs;
FT_UShort num_names;
- FT_UShort* glyph_indices = 0;
- FT_Char** name_strings = 0;
+ FT_UShort* glyph_indices = NULL;
+ FT_Char** name_strings = NULL;
if ( FT_READ_USHORT( num_glyphs ) )
@@ -243,14 +243,17 @@
goto Fail1;
}
- if ( (FT_Int)len > post_limit ||
- FT_STREAM_POS() > post_limit - (FT_Int)len )
+ if ( len > post_limit ||
+ FT_STREAM_POS() > post_limit - len )
{
+ FT_Int d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS();
+
+
FT_ERROR(( "load_format_20:"
" exceeding string length (%d),"
" truncating at end of post table (%d byte left)\n",
- len, post_limit - FT_STREAM_POS() ));
- len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
+ len, d ));
+ len = (FT_UInt)FT_MAX( 0, d );
}
if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
@@ -307,13 +310,13 @@
static FT_Error
load_format_25( TT_Face face,
FT_Stream stream,
- FT_Long post_limit )
+ FT_ULong post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
FT_Int num_glyphs;
- FT_Char* offset_table = 0;
+ FT_Char* offset_table = NULL;
FT_UNUSED( post_limit );
@@ -377,7 +380,7 @@
FT_Error error;
FT_Fixed format;
FT_ULong post_len;
- FT_Long post_limit;
+ FT_ULong post_limit;
/* get a stream for the face's resource */
@@ -547,10 +550,7 @@
}
if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */
- {
- idx += table->offsets[idx];
- *PSname = MAC_NAME( idx );
- }
+ *PSname = MAC_NAME( (FT_Int)idx + table->offsets[idx] );
}
/* nothing to do for format == 0x00030000L */
diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h
index 6f06d75..e3eca02 100644
--- a/src/sfnt/ttpost.h
+++ b/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
/* Postcript name table processing for TrueType and OpenType fonts */
/* (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index cd3e5a4..09260b8 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded bitmap support (body). */
/* */
-/* Copyright 2005-2009, 2013 by */
+/* Copyright 2005-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* Copyright 2013 by Google, Inc. */
@@ -28,6 +28,7 @@
#include "sferrors.h"
+#include "ttmtx.h"
#include "pngshim.h"
@@ -42,25 +43,36 @@
FT_LOCAL_DEF( FT_Error )
- tt_face_load_eblc( TT_Face face,
+ tt_face_load_sbit( TT_Face face,
FT_Stream stream )
{
- FT_Error error = FT_Err_Ok;
- FT_Fixed version;
- FT_ULong num_strikes, table_size;
- FT_Byte* p;
- FT_Byte* p_limit;
- FT_UInt count;
+ FT_Error error;
+ FT_ULong table_size;
+ face->sbit_table = NULL;
+ face->sbit_table_size = 0;
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
face->sbit_num_strikes = 0;
- /* this table is optional */
error = face->goto_table( face, TTAG_CBLC, stream, &table_size );
- if ( error )
+ if ( !error )
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_CBLC;
+ else
+ {
error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
+ if ( error )
+ error = face->goto_table( face, TTAG_bloc, stream, &table_size );
+ if ( !error )
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_EBLC;
+ }
+
if ( error )
- error = face->goto_table( face, TTAG_bloc, stream, &table_size );
+ {
+ error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+ if ( !error )
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_SBIX;
+ }
if ( error )
goto Exit;
@@ -71,53 +83,144 @@
goto Exit;
}
- if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
- goto Exit;
-
- face->sbit_table_size = table_size;
-
- p = face->sbit_table;
- p_limit = p + table_size;
-
- version = FT_NEXT_ULONG( p );
- num_strikes = FT_NEXT_ULONG( p );
-
- if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
+ switch ( (FT_UInt)face->sbit_table_type )
{
- FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
- error = FT_THROW( Invalid_File_Format );
- goto Fail;
+ case TT_SBIT_TABLE_TYPE_EBLC:
+ case TT_SBIT_TABLE_TYPE_CBLC:
+ {
+ FT_Byte* p;
+ FT_Fixed version;
+ FT_ULong num_strikes;
+ FT_UInt count;
+
+
+ if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
+ goto Exit;
+
+ face->sbit_table_size = table_size;
+
+ p = face->sbit_table;
+
+ version = FT_NEXT_LONG( p );
+ num_strikes = FT_NEXT_ULONG( p );
+
+ if ( ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00020000UL &&
+ ( (FT_ULong)version & 0xFFFF0000UL ) != 0x00030000UL )
+ {
+ error = FT_THROW( Unknown_File_Format );
+ goto Exit;
+ }
+
+ if ( num_strikes >= 0x10000UL )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /*
+ * Count the number of strikes available in the table. We are a bit
+ * paranoid there and don't trust the data.
+ */
+ count = (FT_UInt)num_strikes;
+ if ( 8 + 48UL * count > table_size )
+ count = (FT_UInt)( ( table_size - 8 ) / 48 );
+
+ face->sbit_num_strikes = count;
+ }
+ break;
+
+ case TT_SBIT_TABLE_TYPE_SBIX:
+ {
+ FT_UShort version;
+ FT_UShort flags;
+ FT_ULong num_strikes;
+ FT_UInt count;
+
+
+ if ( FT_FRAME_ENTER( 8 ) )
+ goto Exit;
+
+ version = FT_GET_USHORT();
+ flags = FT_GET_USHORT();
+ num_strikes = FT_GET_ULONG();
+
+ FT_FRAME_EXIT();
+
+ if ( version < 1 )
+ {
+ error = FT_THROW( Unknown_File_Format );
+ goto Exit;
+ }
+
+ /* Bit 0 must always be `1'. */
+ /* Bit 1 controls the overlay of bitmaps with outlines. */
+ /* All other bits should be zero. */
+ if ( !( flags == 1 || flags == 3 ) ||
+ num_strikes >= 0x10000UL )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /* we currently don't support bit 1; however, it is better to */
+ /* draw at least something... */
+ if ( flags == 3 )
+ FT_TRACE1(( "tt_face_load_sbit_strikes:"
+ " sbix overlay not supported yet\n"
+ " "
+ " expect bad rendering results\n" ));
+
+ /*
+ * Count the number of strikes available in the table. We are a bit
+ * paranoid there and don't trust the data.
+ */
+ count = (FT_UInt)num_strikes;
+ if ( 8 + 4UL * count > table_size )
+ count = (FT_UInt)( ( table_size - 8 ) / 4 );
+
+ if ( FT_STREAM_SEEK( FT_STREAM_POS() - 8 ) )
+ goto Exit;
+
+ face->sbit_table_size = 8 + count * 4;
+ if ( FT_FRAME_EXTRACT( face->sbit_table_size, face->sbit_table ) )
+ goto Exit;
+
+ face->sbit_num_strikes = count;
+ }
+ break;
+
+ default:
+ error = FT_THROW( Unknown_File_Format );
+ break;
}
- /*
- * Count the number of strikes available in the table. We are a bit
- * paranoid there and don't trust the data.
- */
- count = (FT_UInt)num_strikes;
- if ( 8 + 48UL * count > table_size )
- count = (FT_UInt)( ( p_limit - p ) / 48 );
+ if ( !error )
+ FT_TRACE3(( "sbit_num_strikes: %u\n", face->sbit_num_strikes ));
- face->sbit_num_strikes = count;
+ return FT_Err_Ok;
- FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
Exit:
- return error;
+ if ( error )
+ {
+ if ( face->sbit_table )
+ FT_FRAME_RELEASE( face->sbit_table );
+ face->sbit_table_size = 0;
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
+ }
- Fail:
- FT_FRAME_RELEASE( face->sbit_table );
- face->sbit_table_size = 0;
- goto Exit;
+ return error;
}
FT_LOCAL_DEF( void )
- tt_face_free_eblc( TT_Face face )
+ tt_face_free_sbit( TT_Face face )
{
FT_Stream stream = face->root.stream;
FT_FRAME_RELEASE( face->sbit_table );
face->sbit_table_size = 0;
+ face->sbit_table_type = TT_SBIT_TABLE_TYPE_NONE;
face->sbit_num_strikes = 0;
}
@@ -136,28 +239,151 @@
FT_ULong strike_index,
FT_Size_Metrics* metrics )
{
- FT_Byte* strike;
-
-
if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
return FT_THROW( Invalid_Argument );
- strike = face->sbit_table + 8 + strike_index * 48;
+ switch ( (FT_UInt)face->sbit_table_type )
+ {
+ case TT_SBIT_TABLE_TYPE_EBLC:
+ case TT_SBIT_TABLE_TYPE_CBLC:
+ {
+ FT_Byte* strike;
+ FT_Char max_before_bl;
+ FT_Char min_after_bl;
- metrics->x_ppem = (FT_UShort)strike[44];
- metrics->y_ppem = (FT_UShort)strike[45];
- metrics->ascender = (FT_Char)strike[16] << 6; /* hori.ascender */
- metrics->descender = (FT_Char)strike[17] << 6; /* hori.descender */
- metrics->height = metrics->ascender - metrics->descender;
+ strike = face->sbit_table + 8 + strike_index * 48;
- /* XXX: Is this correct? */
- metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
- strike[18] + /* max_width */
- (FT_Char)strike[23] /* min_advance_SB */
- ) << 6;
+ metrics->x_ppem = (FT_UShort)strike[44];
+ metrics->y_ppem = (FT_UShort)strike[45];
- return FT_Err_Ok;
+ metrics->ascender = (FT_Char)strike[16] * 64; /* hori.ascender */
+ metrics->descender = (FT_Char)strike[17] * 64; /* hori.descender */
+
+ /* Due to fuzzy wording in the EBLC documentation, we find both */
+ /* positive and negative values for `descender'. Additionally, */
+ /* many fonts have both `ascender' and `descender' set to zero */
+ /* (which is definitely wrong). MS Windows simply ignores all */
+ /* those values... For these reasons we apply some heuristics */
+ /* to get a reasonable, non-zero value for the height. */
+
+ max_before_bl = (FT_Char)strike[24];
+ min_after_bl = (FT_Char)strike[25];
+
+ if ( metrics->descender > 0 )
+ {
+ /* compare sign of descender with `min_after_bl' */
+ if ( min_after_bl < 0 )
+ metrics->descender = -metrics->descender;
+ }
+
+ else if ( metrics->descender == 0 )
+ {
+ if ( metrics->ascender == 0 )
+ {
+ FT_TRACE2(( "tt_face_load_strike_metrics:"
+ " sanitizing invalid ascender and descender\n"
+ " "
+ " values for strike (%d, %d)\n",
+ metrics->x_ppem, metrics->y_ppem ));
+
+ /* sanitize buggy ascender and descender values */
+ if ( max_before_bl || min_after_bl )
+ {
+ metrics->ascender = max_before_bl * 64;
+ metrics->descender = min_after_bl * 64;
+ }
+ else
+ {
+ metrics->ascender = metrics->y_ppem * 64;
+ metrics->descender = 0;
+ }
+ }
+ }
+
+#if 0
+ else
+ ; /* if we have a negative descender, simply use it */
+#endif
+
+ metrics->height = metrics->ascender - metrics->descender;
+ if ( metrics->height == 0 )
+ {
+ FT_TRACE2(( "tt_face_load_strike_metrics:"
+ " sanitizing invalid height value\n"
+ " "
+ " for strike (%d, %d)\n",
+ metrics->x_ppem, metrics->y_ppem ));
+ metrics->height = metrics->y_ppem * 64;
+ metrics->descender = metrics->ascender - metrics->height;
+ }
+
+ /* Is this correct? */
+ metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB */
+ strike[18] + /* max_width */
+ (FT_Char)strike[23] /* min_advance_SB */
+ ) * 64;
+ return FT_Err_Ok;
+ }
+
+ case TT_SBIT_TABLE_TYPE_SBIX:
+ {
+ FT_Stream stream = face->root.stream;
+ FT_UInt offset;
+ FT_UShort upem, ppem, resolution;
+ TT_HoriHeader *hori;
+ FT_ULong table_size;
+ FT_Pos ppem_; /* to reduce casts */
+
+ FT_Error error;
+ FT_Byte* p;
+
+
+ p = face->sbit_table + 8 + 4 * strike_index;
+ offset = FT_NEXT_ULONG( p );
+
+ error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+ if ( error )
+ return error;
+
+ if ( offset + 4 > table_size )
+ return FT_THROW( Invalid_File_Format );
+
+ if ( FT_STREAM_SEEK( FT_STREAM_POS() + offset ) ||
+ FT_FRAME_ENTER( 4 ) )
+ return error;
+
+ ppem = FT_GET_USHORT();
+ resolution = FT_GET_USHORT();
+
+ FT_UNUSED( resolution ); /* What to do with this? */
+
+ FT_FRAME_EXIT();
+
+ upem = face->header.Units_Per_EM;
+ hori = &face->horizontal;
+
+ metrics->x_ppem = ppem;
+ metrics->y_ppem = ppem;
+
+ ppem_ = (FT_Pos)ppem;
+
+ metrics->ascender =
+ FT_MulDiv( hori->Ascender, ppem_ * 64, upem );
+ metrics->descender =
+ FT_MulDiv( hori->Descender, ppem_ * 64, upem );
+ metrics->height =
+ FT_MulDiv( hori->Ascender - hori->Descender + hori->Line_Gap,
+ ppem_ * 64, upem );
+ metrics->max_advance =
+ FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem );
+
+ return error;
+ }
+
+ default:
+ return FT_THROW( Unknown_File_Format );
+ }
}
@@ -234,9 +460,11 @@
p += 34;
decoder->bit_depth = *p;
- if ( decoder->strike_index_array > face->sbit_table_size ||
- decoder->strike_index_array + 8 * decoder->strike_index_count >
- face->sbit_table_size )
+ /* decoder->strike_index_array + */
+ /* 8 * decoder->strike_index_count > face->sbit_table_size ? */
+ if ( decoder->strike_index_array > face->sbit_table_size ||
+ decoder->strike_index_count >
+ ( face->sbit_table_size - decoder->strike_index_array ) / 8 )
error = FT_THROW( Invalid_File_Format );
}
@@ -253,13 +481,12 @@
static FT_Error
- tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder,
- FT_UInt load_flags )
+ tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder decoder )
{
FT_Error error = FT_Err_Ok;
FT_UInt width, height;
FT_Bitmap* map = decoder->bitmap;
- FT_Long size;
+ FT_ULong size;
if ( !decoder->metrics_loaded )
@@ -271,48 +498,39 @@
width = decoder->metrics->width;
height = decoder->metrics->height;
- map->width = (int)width;
- map->rows = (int)height;
+ map->width = width;
+ map->rows = height;
switch ( decoder->bit_depth )
{
case 1:
map->pixel_mode = FT_PIXEL_MODE_MONO;
- map->pitch = ( map->width + 7 ) >> 3;
+ map->pitch = (int)( ( map->width + 7 ) >> 3 );
map->num_grays = 2;
break;
case 2:
map->pixel_mode = FT_PIXEL_MODE_GRAY2;
- map->pitch = ( map->width + 3 ) >> 2;
+ map->pitch = (int)( ( map->width + 3 ) >> 2 );
map->num_grays = 4;
break;
case 4:
map->pixel_mode = FT_PIXEL_MODE_GRAY4;
- map->pitch = ( map->width + 1 ) >> 1;
+ map->pitch = (int)( ( map->width + 1 ) >> 1 );
map->num_grays = 16;
break;
case 8:
map->pixel_mode = FT_PIXEL_MODE_GRAY;
- map->pitch = map->width;
+ map->pitch = (int)( map->width );
map->num_grays = 256;
break;
case 32:
- if ( load_flags & FT_LOAD_COLOR )
- {
- map->pixel_mode = FT_PIXEL_MODE_BGRA;
- map->pitch = map->width * 4;
- map->num_grays = 256;
- }
- else
- {
- map->pixel_mode = FT_PIXEL_MODE_GRAY;
- map->pitch = map->width;
- map->num_grays = 256;
- }
+ map->pixel_mode = FT_PIXEL_MODE_BGRA;
+ map->pitch = (int)( map->width * 4 );
+ map->num_grays = 256;
break;
default:
@@ -320,7 +538,7 @@
goto Exit;
}
- size = map->rows * map->pitch;
+ size = map->rows * (FT_ULong)map->pitch;
/* check that there is no empty image */
if ( size == 0 )
@@ -368,13 +586,20 @@
p += 3;
}
+ else
+ {
+ /* avoid uninitialized data in case there is no vertical info -- */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+ }
decoder->metrics_loaded = 1;
*pp = p;
return FT_Err_Ok;
Fail:
- FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" ));
+ FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table\n" ));
return FT_THROW( Invalid_Argument );
}
@@ -382,33 +607,35 @@
/* forward declaration */
static FT_Error
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_UInt glyph_index,
FT_Int x_pos,
- FT_Int y_pos );
+ FT_Int y_pos,
+ FT_UInt recurse_count );
- typedef FT_Error (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder decoder,
- FT_UInt load_flags,
- FT_Byte* p,
- FT_Byte* plimit,
- FT_Int x_pos,
- FT_Int y_pos );
+ typedef FT_Error (*TT_SBitDecoder_LoadFunc)(
+ TT_SBitDecoder decoder,
+ FT_Byte* p,
+ FT_Byte* plimit,
+ FT_Int x_pos,
+ FT_Int y_pos,
+ FT_UInt recurse_count );
static FT_Error
tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_Byte* line;
- FT_Int bit_height, bit_width, pitch, width, height, line_bits, h;
+ FT_Int pitch, width, height, line_bits, h;
+ FT_UInt bit_height, bit_width;
FT_Bitmap* bitmap;
- FT_UNUSED( load_flags );
+ FT_UNUSED( recurse_count );
/* check that we can write the glyph into the bitmap */
@@ -423,8 +650,8 @@
line_bits = width * decoder->bit_depth;
- if ( x_pos < 0 || x_pos + width > bit_width ||
- y_pos < 0 || y_pos + height > bit_height )
+ if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width ||
+ y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height )
{
FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:"
" invalid bitmap dimensions\n" ));
@@ -538,19 +765,20 @@
static FT_Error
tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_Byte* line;
- FT_Int bit_height, bit_width, pitch, width, height, line_bits, h, nbits;
+ FT_Int pitch, width, height, line_bits, h, nbits;
+ FT_UInt bit_height, bit_width;
FT_Bitmap* bitmap;
FT_UShort rval;
- FT_UNUSED( load_flags );
+ FT_UNUSED( recurse_count );
/* check that we can write the glyph into the bitmap */
@@ -565,8 +793,8 @@
line_bits = width * decoder->bit_depth;
- if ( x_pos < 0 || x_pos + width > bit_width ||
- y_pos < 0 || y_pos + height > bit_height )
+ if ( x_pos < 0 || (FT_UInt)( x_pos + width ) > bit_width ||
+ y_pos < 0 || (FT_UInt)( y_pos + height ) > bit_height )
{
FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:"
" invalid bitmap dimensions\n" ));
@@ -581,6 +809,12 @@
goto Exit;
}
+ if ( !line_bits || !height )
+ {
+ /* nothing to do */
+ goto Exit;
+ }
+
/* now do the blit */
/* adjust `line' to point to the first byte of the bitmap */
@@ -664,21 +898,21 @@
static FT_Error
tt_sbit_decoder_load_compound( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_UInt num_components, nn;
- FT_Char horiBearingX = decoder->metrics->horiBearingX;
- FT_Char horiBearingY = decoder->metrics->horiBearingY;
- FT_Byte horiAdvance = decoder->metrics->horiAdvance;
- FT_Char vertBearingX = decoder->metrics->vertBearingX;
- FT_Char vertBearingY = decoder->metrics->vertBearingY;
- FT_Byte vertAdvance = decoder->metrics->vertAdvance;
+ FT_Char horiBearingX = (FT_Char)decoder->metrics->horiBearingX;
+ FT_Char horiBearingY = (FT_Char)decoder->metrics->horiBearingY;
+ FT_Byte horiAdvance = (FT_Byte)decoder->metrics->horiAdvance;
+ FT_Char vertBearingX = (FT_Char)decoder->metrics->vertBearingX;
+ FT_Char vertBearingY = (FT_Char)decoder->metrics->vertBearingY;
+ FT_Byte vertAdvance = (FT_Byte)decoder->metrics->vertAdvance;
if ( p + 2 > limit )
@@ -702,8 +936,11 @@
/* NB: a recursive call */
- error = tt_sbit_decoder_load_image( decoder, load_flags, gindex,
- x_pos + dx, y_pos + dy );
+ error = tt_sbit_decoder_load_image( decoder,
+ gindex,
+ x_pos + dx,
+ y_pos + dy,
+ recurse_count + 1 );
if ( error )
break;
}
@@ -732,16 +969,16 @@
static FT_Error
tt_sbit_decoder_load_png( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_Byte* p,
FT_Byte* limit,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error = FT_Err_Ok;
FT_ULong png_len;
- FT_UNUSED( load_flags );
+ FT_UNUSED( recurse_count );
if ( limit - p < 4 )
@@ -759,14 +996,15 @@
goto Exit;
}
- error = Load_SBit_Png( decoder->bitmap,
+ error = Load_SBit_Png( decoder->face->root.glyph,
x_pos,
y_pos,
decoder->bit_depth,
decoder->metrics,
decoder->stream->memory,
p,
- png_len );
+ png_len,
+ FALSE );
Exit:
if ( !error )
@@ -779,12 +1017,12 @@
static FT_Error
tt_sbit_decoder_load_bitmap( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_UInt glyph_format,
FT_ULong glyph_start,
FT_ULong glyph_size,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
FT_Error error;
FT_Stream stream = decoder->stream;
@@ -794,7 +1032,8 @@
/* seek into the EBDT table now */
- if ( glyph_start + glyph_size > decoder->ebdt_size )
+ if ( !glyph_size ||
+ glyph_start + glyph_size > decoder->ebdt_size )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
@@ -843,8 +1082,36 @@
break;
case 2:
- case 5:
case 7:
+ {
+ /* Don't trust `glyph_format'. For example, Apple's main Korean */
+ /* system font, `AppleMyungJo.ttf' (version 7.0d2e6), uses glyph */
+ /* format 7, but the data is format 6. We check whether we have */
+ /* an excessive number of bytes in the image: If it is equal to */
+ /* the value for a byte-aligned glyph, use the other loading */
+ /* routine. */
+ /* */
+ /* Note that for some (width,height) combinations, where the */
+ /* width is not a multiple of 8, the sizes for bit- and */
+ /* byte-aligned data are equal, for example (7,7) or (15,6). We */
+ /* then prefer what `glyph_format' specifies. */
+
+ FT_UInt width = decoder->metrics->width;
+ FT_UInt height = decoder->metrics->height;
+
+ FT_UInt bit_size = ( width * height + 7 ) >> 3;
+ FT_UInt byte_size = height * ( ( width + 7 ) >> 3 );
+
+
+ if ( bit_size < byte_size &&
+ byte_size == (FT_UInt)( p_limit - p ) )
+ loader = tt_sbit_decoder_load_byte_aligned;
+ else
+ loader = tt_sbit_decoder_load_bit_aligned;
+ }
+ break;
+
+ case 5:
loader = tt_sbit_decoder_load_bit_aligned;
break;
@@ -859,12 +1126,15 @@
loader = tt_sbit_decoder_load_compound;
break;
-#ifdef FT_CONFIG_OPTION_USE_PNG
case 17: /* small metrics, PNG image data */
case 18: /* big metrics, PNG image data */
case 19: /* metrics in EBLC, PNG image data */
+#ifdef FT_CONFIG_OPTION_USE_PNG
loader = tt_sbit_decoder_load_png;
break;
+#else
+ error = FT_THROW( Unimplemented_Feature );
+ goto Fail;
#endif /* FT_CONFIG_OPTION_USE_PNG */
default:
@@ -874,64 +1144,12 @@
if ( !decoder->bitmap_allocated )
{
- error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags );
+ error = tt_sbit_decoder_alloc_bitmap( decoder );
if ( error )
goto Fail;
}
- if ( decoder->bit_depth == 32 &&
- decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA )
- {
- /* Flatten color bitmaps if color was not requested. */
-
- FT_Library library = decoder->face->root.glyph->library;
- FT_Memory memory = decoder->stream->memory;
-
- FT_Bitmap color, *orig;
-
-
- if ( decoder->bitmap->pixel_mode != FT_PIXEL_MODE_GRAY ||
- x_pos != 0 || y_pos != 0 )
- {
- /* Shouldn't happen. */
- error = FT_THROW( Invalid_Table );
- goto Fail;
- }
-
- FT_Bitmap_New( &color );
-
- color.rows = decoder->bitmap->rows;
- color.width = decoder->bitmap->width;
- color.pitch = color.width * 4;
- color.pixel_mode = FT_PIXEL_MODE_BGRA;
-
- if ( FT_ALLOC( color.buffer, color.rows * color.pitch ) )
- goto Fail;
-
- orig = decoder->bitmap;
- decoder->bitmap = &color;
-
- error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
-
- decoder->bitmap = orig;
-
- /* explicitly test against FT_Err_Ok to avoid compiler warnings */
- /* (we do an assignment within a conditional) */
- if ( error ||
- ( error = FT_Bitmap_Convert( library,
- &color,
- decoder->bitmap,
- 1 ) ) != FT_Err_Ok )
- {
- FT_Bitmap_Done( library, &color );
- goto Fail;
- }
-
- FT_Bitmap_Done( library, &color );
- }
-
- else
- error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
+ error = loader( decoder, p, p_limit, x_pos, y_pos, recurse_count );
}
Fail:
@@ -944,16 +1162,11 @@
static FT_Error
tt_sbit_decoder_load_image( TT_SBitDecoder decoder,
- FT_UInt load_flags,
FT_UInt glyph_index,
FT_Int x_pos,
- FT_Int y_pos )
+ FT_Int y_pos,
+ FT_UInt recurse_count )
{
- /*
- * First, we find the correct strike range that applies to this
- * glyph index.
- */
-
FT_Byte* p = decoder->eblc_base + decoder->strike_index_array;
FT_Byte* p_limit = decoder->eblc_limit;
FT_ULong num_ranges = decoder->strike_index_count;
@@ -961,6 +1174,17 @@
FT_ULong image_start = 0, image_end = 0, image_offset;
+ /* arbitrary recursion limit */
+ if ( recurse_count > 100 )
+ {
+ FT_TRACE4(( "tt_sbit_decoder_load_image:"
+ " recursion depth exceeded\n" ));
+ goto Failure;
+ }
+
+
+ /* First, we find the correct strike range that applies to this */
+ /* glyph index. */
for ( ; num_ranges > 0; num_ranges-- )
{
start = FT_NEXT_USHORT( p );
@@ -993,17 +1217,15 @@
switch ( index_format )
{
case 1: /* 4-byte offsets relative to `image_offset' */
- {
- p += 4 * ( glyph_index - start );
- if ( p + 8 > p_limit )
- goto NoBitmap;
+ p += 4 * ( glyph_index - start );
+ if ( p + 8 > p_limit )
+ goto NoBitmap;
- image_start = FT_NEXT_ULONG( p );
- image_end = FT_NEXT_ULONG( p );
+ image_start = FT_NEXT_ULONG( p );
+ image_end = FT_NEXT_ULONG( p );
- if ( image_start == image_end ) /* missing glyph */
- goto NoBitmap;
- }
+ if ( image_start == image_end ) /* missing glyph */
+ goto NoBitmap;
break;
case 2: /* big metrics, constant image size */
@@ -1025,17 +1247,15 @@
break;
case 3: /* 2-byte offsets relative to 'image_offset' */
- {
- p += 2 * ( glyph_index - start );
- if ( p + 4 > p_limit )
- goto NoBitmap;
+ p += 2 * ( glyph_index - start );
+ if ( p + 4 > p_limit )
+ goto NoBitmap;
- image_start = FT_NEXT_USHORT( p );
- image_end = FT_NEXT_USHORT( p );
+ image_start = FT_NEXT_USHORT( p );
+ image_end = FT_NEXT_USHORT( p );
- if ( image_start == image_end ) /* missing glyph */
- goto NoBitmap;
- }
+ if ( image_start == image_end ) /* missing glyph */
+ goto NoBitmap;
break;
case 4: /* sparse glyph array with (glyph,offset) pairs */
@@ -1049,7 +1269,8 @@
num_glyphs = FT_NEXT_ULONG( p );
/* overflow check for p + ( num_glyphs + 1 ) * 4 */
- if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
+ if ( p + 4 > p_limit ||
+ num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
goto NoBitmap;
for ( mm = 0; mm < num_glyphs; mm++ )
@@ -1124,12 +1345,12 @@
image_format, glyph_index ));
return tt_sbit_decoder_load_bitmap( decoder,
- load_flags,
image_format,
image_start,
image_end,
x_pos,
- y_pos );
+ y_pos,
+ recurse_count );
Failure:
return FT_THROW( Invalid_Table );
@@ -1142,6 +1363,130 @@
}
+ static FT_Error
+ tt_face_load_sbix_image( TT_Face face,
+ FT_ULong strike_index,
+ FT_UInt glyph_index,
+ FT_Stream stream,
+ FT_Bitmap *map,
+ TT_SBit_MetricsRec *metrics )
+ {
+ FT_UInt sbix_pos, strike_offset, glyph_start, glyph_end;
+ FT_ULong table_size;
+ FT_Int originOffsetX, originOffsetY;
+ FT_Tag graphicType;
+ FT_Int recurse_depth = 0;
+
+ FT_Error error;
+ FT_Byte* p;
+
+ FT_UNUSED( map );
+
+
+ metrics->width = 0;
+ metrics->height = 0;
+
+ p = face->sbit_table + 8 + 4 * strike_index;
+ strike_offset = FT_NEXT_ULONG( p );
+
+ error = face->goto_table( face, TTAG_sbix, stream, &table_size );
+ if ( error )
+ return error;
+ sbix_pos = FT_STREAM_POS();
+
+ retry:
+ if ( glyph_index > (FT_UInt)face->root.num_glyphs )
+ return FT_THROW( Invalid_Argument );
+
+ if ( strike_offset >= table_size ||
+ table_size - strike_offset < 4 + glyph_index * 4 + 8 )
+ return FT_THROW( Invalid_File_Format );
+
+ if ( FT_STREAM_SEEK( sbix_pos + strike_offset + 4 + glyph_index * 4 ) ||
+ FT_FRAME_ENTER( 8 ) )
+ return error;
+
+ glyph_start = FT_GET_ULONG();
+ glyph_end = FT_GET_ULONG();
+
+ FT_FRAME_EXIT();
+
+ if ( glyph_start == glyph_end )
+ return FT_THROW( Invalid_Argument );
+ if ( glyph_start > glyph_end ||
+ glyph_end - glyph_start < 8 ||
+ table_size - strike_offset < glyph_end )
+ return FT_THROW( Invalid_File_Format );
+
+ if ( FT_STREAM_SEEK( sbix_pos + strike_offset + glyph_start ) ||
+ FT_FRAME_ENTER( glyph_end - glyph_start ) )
+ return error;
+
+ originOffsetX = FT_GET_SHORT();
+ originOffsetY = FT_GET_SHORT();
+
+ graphicType = FT_GET_TAG4();
+
+ switch ( graphicType )
+ {
+ case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ):
+ if ( recurse_depth < 4 )
+ {
+ glyph_index = FT_GET_USHORT();
+ FT_FRAME_EXIT();
+ recurse_depth++;
+ goto retry;
+ }
+ error = FT_THROW( Invalid_File_Format );
+ break;
+
+ case FT_MAKE_TAG( 'p', 'n', 'g', ' ' ):
+#ifdef FT_CONFIG_OPTION_USE_PNG
+ error = Load_SBit_Png( face->root.glyph,
+ 0,
+ 0,
+ 32,
+ metrics,
+ stream->memory,
+ stream->cursor,
+ glyph_end - glyph_start - 8,
+ TRUE );
+#else
+ error = FT_THROW( Unimplemented_Feature );
+#endif
+ break;
+
+ case FT_MAKE_TAG( 'j', 'p', 'g', ' ' ):
+ case FT_MAKE_TAG( 't', 'i', 'f', 'f' ):
+ case FT_MAKE_TAG( 'r', 'g', 'b', 'l' ): /* used on iOS 7.1 */
+ error = FT_THROW( Unknown_File_Format );
+ break;
+
+ default:
+ error = FT_THROW( Unimplemented_Feature );
+ break;
+ }
+
+ FT_FRAME_EXIT();
+
+ if ( !error )
+ {
+ FT_Short abearing;
+ FT_UShort aadvance;
+
+
+ tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
+
+ metrics->horiBearingX = (FT_Short)originOffsetX;
+ metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height );
+ metrics->horiAdvance = (FT_UShort)( aadvance *
+ face->root.size->metrics.x_ppem /
+ face->header.Units_Per_EM );
+ }
+
+ return error;
+ }
+
FT_LOCAL( FT_Error )
tt_face_load_sbit_image( TT_Face face,
FT_ULong strike_index,
@@ -1151,23 +1496,68 @@
FT_Bitmap *map,
TT_SBit_MetricsRec *metrics )
{
- TT_SBitDecoderRec decoder[1];
- FT_Error error;
-
- FT_UNUSED( load_flags );
- FT_UNUSED( stream );
- FT_UNUSED( map );
+ FT_Error error = FT_Err_Ok;
- error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
- if ( !error )
+ switch ( (FT_UInt)face->sbit_table_type )
{
- error = tt_sbit_decoder_load_image( decoder,
- load_flags,
- glyph_index,
- 0,
- 0 );
- tt_sbit_decoder_done( decoder );
+ case TT_SBIT_TABLE_TYPE_EBLC:
+ case TT_SBIT_TABLE_TYPE_CBLC:
+ {
+ TT_SBitDecoderRec decoder[1];
+
+
+ error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
+ if ( !error )
+ {
+ error = tt_sbit_decoder_load_image( decoder,
+ glyph_index,
+ 0,
+ 0,
+ 0 );
+ tt_sbit_decoder_done( decoder );
+ }
+ }
+ break;
+
+ case TT_SBIT_TABLE_TYPE_SBIX:
+ error = tt_face_load_sbix_image( face,
+ strike_index,
+ glyph_index,
+ stream,
+ map,
+ metrics );
+ break;
+
+ default:
+ error = FT_THROW( Unknown_File_Format );
+ break;
+ }
+
+ /* Flatten color bitmaps if color was not requested. */
+ if ( !error &&
+ !( load_flags & FT_LOAD_COLOR ) &&
+ map->pixel_mode == FT_PIXEL_MODE_BGRA )
+ {
+ FT_Bitmap new_map;
+ FT_Library library = face->root.glyph->library;
+
+
+ FT_Bitmap_Init( &new_map );
+
+ /* Convert to 8bit grayscale. */
+ error = FT_Bitmap_Convert( library, map, &new_map, 1 );
+ if ( error )
+ FT_Bitmap_Done( library, &new_map );
+ else
+ {
+ map->pixel_mode = new_map.pixel_mode;
+ map->pitch = new_map.pitch;
+ map->num_grays = new_map.num_grays;
+
+ ft_glyphslot_set_bitmap( face->root.glyph, new_map.buffer );
+ face->root.glyph->internal->flags |= FT_GLYPH_OWN_BITMAP;
+ }
}
return error;
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index ea0b5f8..d4e13ae 100644
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
/* */
/* TrueType and OpenType embedded bitmap support (specification). */
/* */
-/* Copyright 1996-2008, 2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -28,11 +28,11 @@
FT_LOCAL( FT_Error )
- tt_face_load_eblc( TT_Face face,
+ tt_face_load_sbit( TT_Face face,
FT_Stream stream );
FT_LOCAL( void )
- tt_face_free_eblc( TT_Face face );
+ tt_face_free_sbit( TT_Face face );
FT_LOCAL( FT_Error )
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index d2158e7..9a43c07 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2003, 2005-2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -94,10 +94,33 @@
#ifdef _STANDALONE_
+ /* The size in bytes of the render pool used by the scan-line converter */
+ /* to do all of its work. */
+#define FT_RENDER_POOL_SIZE 16384L
+
+
/* Auxiliary macros for token concatenation. */
#define FT_ERR_XCAT( x, y ) x ## y
#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
+#define FT_BEGIN_STMNT do {
+#define FT_END_STMNT } while ( 0 )
+
+#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
+
+
+ /*
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+ * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
+ * largest error less than 7% compared to the exact value.
+ */
+#define FT_HYPOT( x, y ) \
+ ( x = FT_ABS( x ), \
+ y = FT_ABS( y ), \
+ x > y ? x + ( 3 * y >> 3 ) \
+ : y + ( 3 * x >> 3 ) )
+
/* define this to dump debugging information */
/* #define FT_DEBUG_LEVEL_TRACE */
@@ -112,8 +135,10 @@
#include <string.h>
#include <setjmp.h>
#include <limits.h>
-#define FT_UINT_MAX UINT_MAX
-#define FT_INT_MAX INT_MAX
+#define FT_CHAR_BIT CHAR_BIT
+#define FT_UINT_MAX UINT_MAX
+#define FT_INT_MAX INT_MAX
+#define FT_ULONG_MAX ULONG_MAX
#define ft_memset memset
@@ -294,7 +319,6 @@
#undef SCALED
#define ONE_PIXEL ( 1L << PIXEL_BITS )
-#define PIXEL_MASK ( -1L << PIXEL_BITS )
#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS )
#define FLOOR( x ) ( (x) & -ONE_PIXEL )
@@ -310,6 +334,49 @@
#endif
+ /* Compute `dividend / divisor' and return both its quotient and */
+ /* remainder, cast to a specific type. This macro also ensures that */
+ /* the remainder is always positive. */
+#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+ FT_BEGIN_STMNT \
+ (quotient) = (type)( (dividend) / (divisor) ); \
+ (remainder) = (type)( (dividend) % (divisor) ); \
+ if ( (remainder) < 0 ) \
+ { \
+ (quotient)--; \
+ (remainder) += (type)(divisor); \
+ } \
+ FT_END_STMNT
+
+#ifdef __arm__
+ /* Work around a bug specific to GCC which make the compiler fail to */
+ /* optimize a division and modulo operation on the same parameters */
+ /* into a single call to `__aeabi_idivmod'. See */
+ /* */
+ /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
+#undef FT_DIV_MOD
+#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+ FT_BEGIN_STMNT \
+ (quotient) = (type)( (dividend) / (divisor) ); \
+ (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \
+ if ( (remainder) < 0 ) \
+ { \
+ (quotient)--; \
+ (remainder) += (type)(divisor); \
+ } \
+ FT_END_STMNT
+#endif /* __arm__ */
+
+
+ /* These macros speed up repetitive divisions by replacing them */
+ /* with multiplications and right shifts. */
+#define FT_UDIVPREP( b ) \
+ long b ## _r = (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define FT_UDIV( a, b ) \
+ ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
+ ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
+
+
/*************************************************************************/
/* */
/* TYPE DEFINITIONS */
@@ -358,8 +425,18 @@
} TCell;
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+ /* We disable the warning `structure was padded due to */
+ /* __declspec(align())' in order to compile cleanly with */
+ /* the maximum level of warnings. */
+#pragma warning( push )
+#pragma warning( disable : 4324 )
+#endif /* _MSC_VER */
+
typedef struct gray_TWorker_
{
+ ft_jmp_buf jump_buffer;
+
TCoord ex, ey;
TPos min_ex, max_ex;
TPos min_ey, max_ey;
@@ -373,11 +450,8 @@
FT_PtrDist max_cells;
FT_PtrDist num_cells;
- TCoord cx, cy;
TPos x, y;
- TPos last_ey;
-
FT_Vector bez_stack[32 * 3 + 1];
int lev_stack[32];
@@ -395,8 +469,6 @@
int band_size;
int band_shoot;
- ft_jmp_buf jump_buffer;
-
void* buffer;
long buffer_size;
@@ -405,6 +477,10 @@
} gray_TWorker, *gray_PWorker;
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
#ifndef FT_STATIC_RASTER
#define ras (*worker)
@@ -415,11 +491,7 @@
typedef struct gray_TRaster_
{
- void* buffer;
- long buffer_size;
- int band_size;
void* memory;
- gray_PWorker worker;
} gray_TRaster, *gray_PRaster;
@@ -431,7 +503,7 @@
/* */
static void
gray_init_cells( RAS_ARG_ void* buffer,
- long byte_size )
+ long byte_size )
{
ras.buffer = buffer;
ras.buffer_size = byte_size;
@@ -536,7 +608,7 @@
static void
gray_record_cell( RAS_ARG )
{
- if ( !ras.invalid && ( ras.area | ras.cover ) )
+ if ( ras.area | ras.cover )
{
PCell cell = gray_find_cell( RAS_VAR );
@@ -585,12 +657,12 @@
ras.area = 0;
ras.cover = 0;
+ ras.ex = ex;
+ ras.ey = ey;
}
- ras.ex = ex;
- ras.ey = ey;
- ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
- ex >= ras.count_ex );
+ ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey ||
+ ex >= ras.count_ex );
}
@@ -612,12 +684,12 @@
ras.cover = 0;
ras.ex = ex - ras.min_ex;
ras.ey = ey - ras.min_ey;
- ras.last_ey = SUBPIXELS( ey );
ras.invalid = 0;
gray_set_cell( RAS_VAR_ ex, ey );
}
+#if 0
/*************************************************************************/
/* */
@@ -674,13 +746,7 @@
dx = -dx;
}
- delta = (TCoord)( p / dx );
- mod = (TCoord)( p % dx );
- if ( mod < 0 )
- {
- delta--;
- mod += (TCoord)dx;
- }
+ FT_DIV_MOD( TCoord, p, dx, delta, mod );
ras.area += (TArea)(( fx1 + first ) * delta);
ras.cover += delta;
@@ -694,18 +760,12 @@
TCoord lift, rem;
- p = ONE_PIXEL * ( y2 - y1 + delta );
- lift = (TCoord)( p / dx );
- rem = (TCoord)( p % dx );
- if ( rem < 0 )
- {
- lift--;
- rem += (TCoord)dx;
- }
+ p = ONE_PIXEL * ( y2 - y1 + delta );
+ FT_DIV_MOD( TCoord, p, dx, lift, rem );
mod -= (int)dx;
- while ( ex1 != ex2 )
+ do
{
delta = lift;
mod += rem;
@@ -720,7 +780,7 @@
y1 += delta;
ex1 += incr;
gray_set_cell( RAS_VAR_ ex1, ey );
- }
+ } while ( ex1 != ex2 );
}
delta = y2 - y1;
@@ -743,32 +803,18 @@
int delta, rem, lift, incr;
- ey1 = TRUNC( ras.last_ey );
+ ey1 = TRUNC( ras.y );
ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
- fy1 = (TCoord)( ras.y - ras.last_ey );
+ fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
dx = to_x - ras.x;
dy = to_y - ras.y;
- /* XXX: we should do something about the trivial case where dx == 0, */
- /* as it happens very often! */
-
/* perform vertical clipping */
- {
- TCoord min, max;
-
-
- min = ey1;
- max = ey2;
- if ( ey1 > ey2 )
- {
- min = ey2;
- max = ey1;
- }
- if ( min >= ras.max_ey || max < ras.min_ey )
- goto End;
- }
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
/* everything is on a single scanline */
if ( ey1 == ey2 )
@@ -832,13 +878,7 @@
dy = -dy;
}
- delta = (int)( p / dy );
- mod = (int)( p % dy );
- if ( mod < 0 )
- {
- delta--;
- mod += (TCoord)dy;
- }
+ FT_DIV_MOD( int, p, dy, delta, mod );
x = ras.x + delta;
gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
@@ -849,16 +889,10 @@
if ( ey1 != ey2 )
{
p = ONE_PIXEL * dx;
- lift = (int)( p / dy );
- rem = (int)( p % dy );
- if ( rem < 0 )
- {
- lift--;
- rem += (int)dy;
- }
+ FT_DIV_MOD( int, p, dy, lift, rem );
mod -= (int)dy;
- while ( ey1 != ey2 )
+ do
{
delta = lift;
mod += rem;
@@ -876,7 +910,7 @@
ey1 += incr;
gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
- }
+ } while ( ey1 != ey2 );
}
gray_render_scanline( RAS_VAR_ ey1, x,
@@ -886,9 +920,145 @@
End:
ras.x = to_x;
ras.y = to_y;
- ras.last_ey = SUBPIXELS( ey2 );
}
+#else
+
+ /*************************************************************************/
+ /* */
+ /* Render a straight line across multiple cells in any direction. */
+ /* */
+ static void
+ gray_render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TPos dx, dy, fx1, fy1, fx2, fy2;
+ TCoord ex1, ex2, ey1, ey2;
+
+
+ ex1 = TRUNC( ras.x );
+ ex2 = TRUNC( to_x );
+ ey1 = TRUNC( ras.y );
+ ey2 = TRUNC( to_y );
+
+ /* perform vertical clipping */
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ fx1 = ras.x - SUBPIXELS( ex1 );
+ fy1 = ras.y - SUBPIXELS( ey1 );
+
+ if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
+ ;
+ else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
+ {
+ ex1 = ex2;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ }
+ else if ( dx == 0 )
+ {
+ if ( dy > 0 ) /* vertical line up */
+ do
+ {
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = 0;
+ ey1++;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ else /* vertical line down */
+ do
+ {
+ fy2 = 0;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ }
+ else /* any other line */
+ {
+ TArea prod = dx * fy1 - dy * fx1;
+ FT_UDIVPREP( dx );
+ FT_UDIVPREP( dy );
+
+
+ /* The fundamental value `prod' determines which side and the */
+ /* exact coordinate where the line exits current cell. It is */
+ /* also easily updated when moving from one cell to the next. */
+ do
+ {
+ if ( prod <= 0 &&
+ prod - dx * ONE_PIXEL > 0 ) /* left */
+ {
+ fx2 = 0;
+ fy2 = (TPos)FT_UDIV( -prod, -dx );
+ prod -= dy * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = ONE_PIXEL;
+ fy1 = fy2;
+ ex1--;
+ }
+ else if ( prod - dx * ONE_PIXEL <= 0 &&
+ prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
+ {
+ prod -= dx * ONE_PIXEL;
+ fx2 = (TPos)FT_UDIV( -prod, dy );
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = 0;
+ ey1++;
+ }
+ else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
+ prod + dy * ONE_PIXEL >= 0 ) /* right */
+ {
+ prod += dy * ONE_PIXEL;
+ fx2 = ONE_PIXEL;
+ fy2 = (TPos)FT_UDIV( prod, dx );
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = 0;
+ fy1 = fy2;
+ ex1++;
+ }
+ else /* ( prod + dy * ONE_PIXEL < 0 &&
+ prod > 0 ) down */
+ {
+ fx2 = (TPos)FT_UDIV( prod, -dy );
+ fy2 = 0;
+ prod += dx * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ }
+
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ex1 != ex2 || ey1 != ey2 );
+ }
+
+ fx2 = to_x - SUBPIXELS( ex2 );
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ }
+
+#endif
static void
gray_split_conic( FT_Vector* base )
@@ -1069,37 +1239,10 @@
/* dx and dy are x and y components of the P0-P3 chord vector. */
- dx = arc[3].x - arc[0].x;
- dy = arc[3].y - arc[0].y;
+ dx = dx_ = arc[3].x - arc[0].x;
+ dy = dy_ = arc[3].y - arc[0].y;
- /* L is an (under)estimate of the Euclidean distance P0-P3. */
- /* */
- /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated */
- /* with least maximum error by */
- /* */
- /* r_upperbound = dx + (sqrt(2) - 1) * dy , */
- /* */
- /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
- /* error of no more than 8.4%. */
- /* */
- /* Similarly, some elementary calculus shows that r can be */
- /* underestimated with least maximum error by */
- /* */
- /* r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx */
- /* + sqrt(2 - sqrt(2)) / 2 * dy . */
- /* */
- /* 236/256 and 97/256 are (under)estimates of the two algebraic */
- /* numbers, giving an error of no more than 8.1%. */
-
- dx_ = FT_ABS( dx );
- dy_ = FT_ABS( dy );
-
- /* This is the same as */
- /* */
- /* L = ( 236 * FT_MAX( dx_, dy_ ) */
- /* + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
- L = ( dx_ > dy_ ? 236 * dx_ + 97 * dy_
- : 97 * dx_ + 236 * dy_ ) >> 8;
+ L = FT_HYPOT( dx_, dy_ );
/* Avoid possible arithmetic overflow below by splitting. */
if ( L > 32767 )
@@ -1159,7 +1302,8 @@
/* record current cell, if any */
- gray_record_cell( RAS_VAR );
+ if ( !ras.invalid )
+ gray_record_cell( RAS_VAR );
/* start to a new position */
x = UPSCALE( to->x );
@@ -1216,7 +1360,7 @@
/* first of all, compute the scanline offset */
p = (unsigned char*)map->buffer - y * map->pitch;
if ( map->pitch >= 0 )
- p += (unsigned)( ( map->rows - 1 ) * map->pitch );
+ p += ( map->rows - 1 ) * (unsigned int)map->pitch;
for ( ; count > 0; count--, spans++ )
{
@@ -1344,7 +1488,6 @@
ras.num_gray_spans = 0;
ras.span_y = (int)y;
- count = 0;
span = ras.gray_spans;
}
else
@@ -1520,7 +1663,10 @@
TPos delta;
- if ( !outline || !func_interface )
+ if ( !outline )
+ return FT_THROW( Invalid_Outline );
+
+ if ( !func_interface )
return FT_THROW( Invalid_Argument );
shift = func_interface->shift;
@@ -1746,14 +1892,17 @@
} gray_TBand;
- FT_DEFINE_OUTLINE_FUNCS(func_interface,
- (FT_Outline_MoveTo_Func) gray_move_to,
- (FT_Outline_LineTo_Func) gray_line_to,
- (FT_Outline_ConicTo_Func)gray_conic_to,
- (FT_Outline_CubicTo_Func)gray_cubic_to,
- 0,
- 0
- )
+
+ FT_DEFINE_OUTLINE_FUNCS(
+ func_interface,
+
+ (FT_Outline_MoveTo_Func) gray_move_to,
+ (FT_Outline_LineTo_Func) gray_line_to,
+ (FT_Outline_ConicTo_Func)gray_conic_to,
+ (FT_Outline_CubicTo_Func)gray_cubic_to,
+ 0,
+ 0 )
+
static int
gray_convert_glyph_inner( RAS_ARG )
@@ -1769,7 +1918,8 @@
if ( ft_setjmp( ras.jump_buffer ) == 0 )
{
error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
- gray_record_cell( RAS_VAR );
+ if ( !ras.invalid )
+ gray_record_cell( RAS_VAR );
}
else
error = FT_THROW( Memory_Overflow );
@@ -1829,7 +1979,7 @@
bands[0].max = max;
band = bands;
- while ( band >= bands )
+ do
{
TPos bottom, top, middle;
int error;
@@ -1843,13 +1993,13 @@
ras.ycells = (PCell*)ras.buffer;
ras.ycount = band->max - band->min;
- cell_start = sizeof ( PCell ) * ras.ycount;
- cell_mod = cell_start % sizeof ( TCell );
+ cell_start = (long)sizeof ( PCell ) * ras.ycount;
+ cell_mod = cell_start % (long)sizeof ( TCell );
if ( cell_mod > 0 )
- cell_start += sizeof ( TCell ) - cell_mod;
+ cell_start += (long)sizeof ( TCell ) - cell_mod;
cell_end = ras.buffer_size;
- cell_end -= cell_end % sizeof ( TCell );
+ cell_end -= cell_end % (long)sizeof ( TCell );
cells_max = (PCell)( (char*)ras.buffer + cell_end );
ras.cells = (PCell)( (char*)ras.buffer + cell_start );
@@ -1905,7 +2055,7 @@
band[0].min = middle;
band[0].max = top;
band++;
- }
+ } while ( band >= bands );
}
if ( ras.band_shoot > 8 && ras.band_size > 16 )
@@ -1919,12 +2069,18 @@
gray_raster_render( gray_PRaster raster,
const FT_Raster_Params* params )
{
- const FT_Outline* outline = (const FT_Outline*)params->source;
- const FT_Bitmap* target_map = params->target;
- gray_PWorker worker;
+ const FT_Outline* outline = (const FT_Outline*)params->source;
+ const FT_Bitmap* target_map = params->target;
+
+ gray_TWorker worker[1];
+
+ TCell buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )];
+ long buffer_size = sizeof ( buffer );
+ int band_size = (int)( buffer_size /
+ (long)( sizeof ( TCell ) * 8 ) );
- if ( !raster || !raster->buffer || !raster->buffer_size )
+ if ( !raster )
return FT_THROW( Invalid_Argument );
if ( !outline )
@@ -1941,8 +2097,6 @@
outline->contours[outline->n_contours - 1] + 1 )
return FT_THROW( Invalid_Outline );
- worker = raster->worker;
-
/* if direct mode is not set, we must have a target bitmap */
if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
{
@@ -1967,8 +2121,8 @@
/* compute clip box from target pixmap */
ras.clip_box.xMin = 0;
ras.clip_box.yMin = 0;
- ras.clip_box.xMax = target_map->width;
- ras.clip_box.yMax = target_map->rows;
+ ras.clip_box.xMax = (FT_Pos)target_map->width;
+ ras.clip_box.yMax = (FT_Pos)target_map->rows;
}
else if ( params->flags & FT_RASTER_FLAG_CLIP )
ras.clip_box = params->clip_box;
@@ -1980,13 +2134,14 @@
ras.clip_box.yMax = 32767L;
}
- gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
+ gray_init_cells( RAS_VAR_ buffer, buffer_size );
ras.outline = *outline;
ras.num_cells = 0;
ras.invalid = 1;
- ras.band_size = raster->band_size;
+ ras.band_size = band_size;
ras.num_gray_spans = 0;
+ ras.span_y = 0;
if ( params->flags & FT_RASTER_FLAG_DIRECT )
{
@@ -2070,46 +2225,36 @@
char* pool_base,
long pool_size )
{
- gray_PRaster rast = (gray_PRaster)raster;
-
-
- if ( raster )
- {
- if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
- {
- gray_PWorker worker = (gray_PWorker)pool_base;
-
-
- rast->worker = worker;
- rast->buffer = pool_base +
- ( ( sizeof ( gray_TWorker ) +
- sizeof ( TCell ) - 1 ) &
- ~( sizeof ( TCell ) - 1 ) );
- rast->buffer_size = (long)( ( pool_base + pool_size ) -
- (char*)rast->buffer ) &
- ~( sizeof ( TCell ) - 1 );
- rast->band_size = (int)( rast->buffer_size /
- ( sizeof ( TCell ) * 8 ) );
- }
- else
- {
- rast->buffer = NULL;
- rast->buffer_size = 0;
- rast->worker = NULL;
- }
- }
+ FT_UNUSED( raster );
+ FT_UNUSED( pool_base );
+ FT_UNUSED( pool_size );
}
- FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
+ static int
+ gray_raster_set_mode( FT_Raster raster,
+ unsigned long mode,
+ void* args )
+ {
+ FT_UNUSED( raster );
+ FT_UNUSED( mode );
+ FT_UNUSED( args );
+
+
+ return 0; /* nothing to do */
+ }
+
+
+ FT_DEFINE_RASTER_FUNCS(
+ ft_grays_raster,
+
FT_GLYPH_FORMAT_OUTLINE,
(FT_Raster_New_Func) gray_raster_new,
(FT_Raster_Reset_Func) gray_raster_reset,
- (FT_Raster_Set_Mode_Func)0,
+ (FT_Raster_Set_Mode_Func)gray_raster_set_mode,
(FT_Raster_Render_Func) gray_raster_render,
- (FT_Raster_Done_Func) gray_raster_done
- )
+ (FT_Raster_Done_Func) gray_raster_done )
/* END */
diff --git a/src/smooth/ftgrays.h b/src/smooth/ftgrays.h
index f20f55f..1b57603 100644
--- a/src/smooth/ftgrays.h
+++ b/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
/* */
/* FreeType smooth renderer declaration */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/smooth/ftsmerrs.h b/src/smooth/ftsmerrs.h
index 413d2f1..cc38aa1 100644
--- a/src/smooth/ftsmerrs.h
+++ b/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
/* */
/* smooth renderer error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 89088cd..3620550 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (body). */
/* */
-/* Copyright 2000-2006, 2009-2013 by */
+/* Copyright 2000-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -103,25 +103,24 @@
FT_Render_Mode required_mode )
{
FT_Error error;
- FT_Outline* outline = NULL;
+ FT_Outline* outline = &slot->outline;
+ FT_Bitmap* bitmap = &slot->bitmap;
+ FT_Memory memory = render->root.memory;
FT_BBox cbox;
+ FT_Pos x_shift = 0;
+ FT_Pos y_shift = 0;
+ FT_Pos x_left, y_top;
FT_Pos width, height, pitch;
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_Pos height_org, width_org;
#endif
- FT_Bitmap* bitmap = &slot->bitmap;
- FT_Memory memory = render->root.memory;
FT_Int hmul = mode == FT_RENDER_MODE_LCD;
FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
- FT_Pos x_shift = 0;
- FT_Pos y_shift = 0;
- FT_Pos x_left, y_top;
FT_Raster_Params params;
- FT_Bool have_translated_origin = FALSE;
- FT_Bool have_outline_shifted = FALSE;
- FT_Bool have_buffer = FALSE;
+ FT_Bool have_outline_shifted = FALSE;
+ FT_Bool have_buffer = FALSE;
/* check glyph image format */
@@ -138,73 +137,45 @@
goto Exit;
}
- outline = &slot->outline;
-
- /* translate the outline to the new origin if needed */
if ( origin )
{
- FT_Outline_Translate( outline, origin->x, origin->y );
- have_translated_origin = TRUE;
+ x_shift = origin->x;
+ y_shift = origin->y;
}
/* compute the control box, and grid fit it */
+ /* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox );
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.xMax = FT_PIX_CEIL( cbox.xMax );
- cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+ cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
+ cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
+ cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
+ cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
- if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
- {
- FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- " xMin = %d, xMax = %d\n",
- cbox.xMin >> 6, cbox.xMax >> 6 ));
- error = FT_THROW( Raster_Overflow );
- goto Exit;
- }
- else
- width = ( cbox.xMax - cbox.xMin ) >> 6;
+ x_shift -= cbox.xMin;
+ y_shift -= cbox.yMin;
- if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
- {
- FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
- " yMin = %d, yMax = %d\n",
- cbox.yMin >> 6, cbox.yMax >> 6 ));
- error = FT_THROW( Raster_Overflow );
- goto Exit;
- }
- else
- height = ( cbox.yMax - cbox.yMin ) >> 6;
+ x_left = cbox.xMin >> 6;
+ y_top = cbox.yMax >> 6;
+
+ width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
+ height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
width_org = width;
height_org = height;
#endif
- /* release old bitmap buffer */
- if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
- {
- FT_FREE( bitmap->buffer );
- slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
- }
-
- /* allocate new one */
pitch = width;
if ( hmul )
{
- width = width * 3;
- pitch = FT_PAD_CEIL( width, 4 );
+ width *= 3;
+ pitch = FT_PAD_CEIL( width, 4 );
}
if ( vmul )
height *= 3;
- x_shift = (FT_Int) cbox.xMin;
- y_shift = (FT_Int) cbox.yMin;
- x_left = (FT_Int)( cbox.xMin >> 6 );
- y_top = (FT_Int)( cbox.yMax >> 6 );
-
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
if ( slot->library->lcd_filter_func )
@@ -214,23 +185,32 @@
if ( hmul )
{
- x_shift -= 64 * ( extra >> 1 );
+ x_shift += 64 * ( extra >> 1 );
+ x_left -= extra >> 1;
width += 3 * extra;
pitch = FT_PAD_CEIL( width, 4 );
- x_left -= extra >> 1;
}
if ( vmul )
{
- y_shift -= 64 * ( extra >> 1 );
- height += 3 * extra;
+ y_shift += 64 * ( extra >> 1 );
y_top += extra >> 1;
+ height += 3 * extra;
}
}
#endif
-#if FT_UINT_MAX > 0xFFFFU
+ /*
+ * XXX: on 16bit system, we return an error for huge bitmap
+ * to prevent an overflow.
+ */
+ if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
+ x_left < FT_INT_MIN || y_top < FT_INT_MIN )
+ {
+ error = FT_THROW( Invalid_Pixel_Size );
+ goto Exit;
+ }
/* Required check is (pitch * height < FT_ULONG_MAX), */
/* but we care realistic cases only. Always pitch <= width. */
@@ -242,25 +222,38 @@
goto Exit;
}
-#endif
+ /* release old bitmap buffer */
+ if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+ {
+ FT_FREE( bitmap->buffer );
+ slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+ }
- bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap->num_grays = 256;
- bitmap->width = width;
- bitmap->rows = height;
- bitmap->pitch = pitch;
-
- /* translate outline to render it into the bitmap */
- FT_Outline_Translate( outline, -x_shift, -y_shift );
- have_outline_shifted = TRUE;
-
- if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+ /* allocate new one */
+ if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
goto Exit;
else
have_buffer = TRUE;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
+ slot->bitmap_left = (FT_Int)x_left;
+ slot->bitmap_top = (FT_Int)y_top;
+
+ bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+ bitmap->num_grays = 256;
+ bitmap->width = (unsigned int)width;
+ bitmap->rows = (unsigned int)height;
+ bitmap->pitch = pitch;
+
+ /* translate outline to render it into the bitmap */
+ if ( x_shift || y_shift )
+ {
+ FT_Outline_Translate( outline, x_shift, y_shift );
+ have_outline_shifted = TRUE;
+ }
+
/* set up parameters */
params.target = bitmap;
params.source = outline;
@@ -366,20 +359,6 @@
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
- /*
- * XXX: on 16bit system, we return an error for huge bitmap
- * to prevent an overflow.
- */
- if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
- {
- error = FT_THROW( Invalid_Pixel_Size );
- goto Exit;
- }
-
- slot->format = FT_GLYPH_FORMAT_BITMAP;
- slot->bitmap_left = (FT_Int)x_left;
- slot->bitmap_top = (FT_Int)y_top;
-
/* everything is fine; don't deallocate buffer */
have_buffer = FALSE;
@@ -387,9 +366,7 @@
Exit:
if ( have_outline_shifted )
- FT_Outline_Translate( outline, x_shift, y_shift );
- if ( have_translated_origin )
- FT_Outline_Translate( outline, -origin->x, -origin->y );
+ FT_Outline_Translate( outline, -x_shift, -y_shift );
if ( have_buffer )
{
FT_FREE( bitmap->buffer );
diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h
index 3708790..765018c 100644
--- a/src/smooth/ftsmooth.h
+++ b/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (specification). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/smooth/ftspic.c b/src/smooth/ftspic.c
index 67a2b83..8e6ed57 100644
--- a/src/smooth/ftspic.c
+++ b/src/smooth/ftspic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for smooth module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/smooth/ftspic.h b/src/smooth/ftspic.h
index 334b51c..071afcf 100644
--- a/src/smooth/ftspic.h
+++ b/src/smooth/ftspic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for smooth module. */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,10 +20,11 @@
#define __FTSPIC_H__
-FT_BEGIN_HEADER
-
#include FT_INTERNAL_PIC_H
+
+FT_BEGIN_HEADER
+
#ifndef FT_CONFIG_OPTION_PIC
#define FT_GRAYS_RASTER_GET ft_grays_raster
diff --git a/src/smooth/smooth.c b/src/smooth/smooth.c
index a8ac51f..4ca4344 100644
--- a/src/smooth/smooth.c
+++ b/src/smooth/smooth.c
@@ -4,7 +4,7 @@
/* */
/* FreeType anti-aliasing rasterer module component (body only). */
/* */
-/* Copyright 1996-2001 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/truetype.c b/src/truetype/truetype.c
index 576912b..f929437 100644
--- a/src/truetype/truetype.c
+++ b/src/truetype/truetype.c
@@ -4,7 +4,7 @@
/* */
/* FreeType TrueType driver component (body only). */
/* */
-/* Copyright 1996-2001, 2004, 2006, 2012 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index fb25706..1ba71f0 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
/* */
/* TrueType font driver implementation (body). */
/* */
-/* Copyright 1996-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,7 +20,7 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
-#include FT_SERVICE_XFREE86_NAME_H
+#include FT_SERVICE_FONT_FORMAT_H
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_MULTIPLE_MASTERS_H
@@ -117,8 +117,8 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
tt_service_properties,
- (FT_Properties_SetFunc)tt_property_set,
- (FT_Properties_GetFunc)tt_property_get )
+ (FT_Properties_SetFunc)tt_property_set, /* set_property */
+ (FT_Properties_GetFunc)tt_property_get ) /* get_property */
/*************************************************************************/
@@ -134,11 +134,6 @@
/*************************************************************************/
-#undef PAIR_TAG
-#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
- (FT_ULong)right )
-
-
/*************************************************************************/
/* */
/* <Function> */
@@ -191,9 +186,6 @@
}
-#undef PAIR_TAG
-
-
static FT_Error
tt_get_advances( FT_Face ttface,
FT_UInt start,
@@ -215,7 +207,8 @@
FT_UShort ah;
- TT_Get_VMetrics( face, start + nn, &tsb, &ah );
+ /* since we don't need `tsb', we use zero for `yMax' parameter */
+ TT_Get_VMetrics( face, start + nn, 0, &tsb, &ah );
advances[nn] = ah;
}
}
@@ -266,7 +259,7 @@
/* use the scaled metrics, even when tt_size_reset fails */
FT_Select_Metrics( size->face, strike_index );
- tt_size_reset( ttsize );
+ tt_size_reset( ttsize ); /* ignore return value */
}
else
{
@@ -369,7 +362,7 @@
return FT_THROW( Invalid_Size_Handle );
if ( !face )
- return FT_THROW( Invalid_Argument );
+ return FT_THROW( Invalid_Face_Handle );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
if ( glyph_index >= (FT_UInt)face->num_glyphs &&
@@ -424,13 +417,14 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_DEFINE_SERVICE_MULTIMASTERSREC(
tt_service_gx_multi_masters,
- (FT_Get_MM_Func) NULL,
- (FT_Set_MM_Design_Func) NULL,
- (FT_Set_MM_Blend_Func) TT_Set_MM_Blend,
- (FT_Get_MM_Var_Func) TT_Get_MM_Var,
- (FT_Set_Var_Design_Func)TT_Set_Var_Design )
+ (FT_Get_MM_Func) NULL, /* get_mm */
+ (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, /* set_mm_blend */
+ (FT_Get_MM_Var_Func) TT_Get_MM_Var, /* get_mm_var */
+ (FT_Set_Var_Design_Func)TT_Set_Var_Design ) /* set_var_design */
#endif
+
static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine =
{
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -448,14 +442,16 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
};
+
FT_DEFINE_SERVICE_TTGLYFREC(
tt_service_truetype_glyf,
- (TT_Glyf_GetLocationFunc)tt_face_get_location )
+ (TT_Glyf_GetLocationFunc)tt_face_get_location ) /* get_location */
+
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_DEFINE_SERVICEDESCREC5(
tt_services,
- FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE,
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
FT_SERVICE_ID_MULTI_MASTERS, &TT_SERVICE_GX_MULTI_MASTERS_GET,
FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
@@ -463,7 +459,7 @@
#else
FT_DEFINE_SERVICEDESCREC4(
tt_services,
- FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE,
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE,
FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
FT_SERVICE_ID_TT_GLYF, &TT_SERVICE_TRUETYPE_GLYF_GET,
FT_SERVICE_ID_PROPERTIES, &TT_SERVICE_PROPERTIES_GET )
@@ -480,7 +476,7 @@
SFNT_Service sfnt;
- /* TT_SERVICES_GET derefers `library' in PIC mode */
+ /* TT_SERVICES_GET dereferences `library' in PIC mode */
#ifdef FT_CONFIG_OPTION_PIC
if ( !driver )
return NULL;
@@ -541,31 +537,31 @@
0x10000L, /* driver version == 1.0 */
0x20000L, /* driver requires FreeType 2.0 or above */
- (void*)0, /* driver specific interface */
+ 0, /* module-specific interface */
- tt_driver_init,
- tt_driver_done,
- tt_get_interface,
+ tt_driver_init, /* FT_Module_Constructor module_init */
+ tt_driver_done, /* FT_Module_Destructor module_done */
+ tt_get_interface, /* FT_Module_Requester get_interface */
sizeof ( TT_FaceRec ),
sizeof ( TT_SizeRec ),
sizeof ( FT_GlyphSlotRec ),
- tt_face_init,
- tt_face_done,
- tt_size_init,
- tt_size_done,
- tt_slot_init,
- 0, /* FT_Slot_DoneFunc */
+ tt_face_init, /* FT_Face_InitFunc init_face */
+ tt_face_done, /* FT_Face_DoneFunc done_face */
+ tt_size_init, /* FT_Size_InitFunc init_size */
+ tt_size_done, /* FT_Size_DoneFunc done_size */
+ tt_slot_init, /* FT_Slot_InitFunc init_slot */
+ 0, /* FT_Slot_DoneFunc done_slot */
- tt_glyph_load,
+ tt_glyph_load, /* FT_Slot_LoadFunc load_glyph */
- tt_get_kerning,
- 0, /* FT_Face_AttachFunc */
- tt_get_advances,
+ tt_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
+ 0, /* FT_Face_AttachFunc attach_file */
+ tt_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
- tt_size_request,
- TT_SIZE_SELECT
+ tt_size_request, /* FT_Size_RequestFunc request_size */
+ TT_SIZE_SELECT /* FT_Size_SelectFunc select_size */
)
diff --git a/src/truetype/ttdriver.h b/src/truetype/ttdriver.h
index aae00f2..6cacd60 100644
--- a/src/truetype/ttdriver.h
+++ b/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
/* */
/* High-level TrueType driver interface (specification). */
/* */
-/* Copyright 1996-2001, 2002 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/tterrors.h b/src/truetype/tterrors.h
index 78d138f..ba32cf7 100644
--- a/src/truetype/tterrors.h
+++ b/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
/* */
/* TrueType error codes (specification only). */
/* */
-/* Copyright 2001, 2012 by */
+/* Copyright 2001-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index f640a6c..d94fc92 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2013 */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,6 +24,7 @@
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_DRIVER_H
+#include FT_LIST_H
#include "ttgload.h"
#include "ttpload.h"
@@ -85,84 +86,84 @@
/*************************************************************************/
/* */
/* Return the vertical metrics in font units for a given glyph. */
- /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
- /* table, typoAscender/Descender from the `OS/2' table would be used */
- /* instead, and if there were no `OS/2' table, use ascender/descender */
- /* from the `hhea' table. But that is not what Microsoft's rasterizer */
- /* apparently does: It uses the ppem value as the advance height, and */
- /* sets the top side bearing to be zero. */
+ /* See macro `TT_LOADER_SET_PP' below for explanations. */
/* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
+ FT_Pos yMax,
FT_Short* tsb,
FT_UShort* ah )
{
if ( face->vertical_info )
( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
-#if 1 /* Empirically determined, at variance with what MS said */
-
- else
- {
- *tsb = 0;
- *ah = face->root.units_per_EM;
- }
-
-#else /* This is what MS said to do. It isn't what they do, however. */
-
else if ( face->os2.version != 0xFFFFU )
{
- *tsb = face->os2.sTypoAscender;
- *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
- }
- else
- {
- *tsb = face->horizontal.Ascender;
- *ah = face->horizontal.Ascender - face->horizontal.Descender;
+ *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
+ *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
+ face->os2.sTypoDescender );
}
-#endif
+ else
+ {
+ *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
+ *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender -
+ face->horizontal.Descender );
+ }
FT_TRACE5(( " advance height (font units): %d\n", *ah ));
FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
}
- static void
+ static FT_Error
tt_get_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
+ FT_Error error;
+ FT_Stream stream = loader->stream;
+
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
+ /* we must preserve the stream position */
+ /* (which gets altered by the metrics functions) */
+ FT_ULong pos = FT_STREAM_POS();
+
TT_Get_HMetrics( face, glyph_index,
&left_bearing,
&advance_width );
TT_Get_VMetrics( face, glyph_index,
+ loader->bbox.yMax,
&top_bearing,
&advance_height );
+ if ( FT_STREAM_SEEK( pos ) )
+ return error;
+
loader->left_bearing = left_bearing;
loader->advance = advance_width;
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ loader->exec )
{
- if ( loader->exec )
- loader->exec->sph_tweak_flags = 0;
+ loader->exec->sph_tweak_flags = 0;
- /* this may not be the right place for this, but it works */
- if ( loader->exec && loader->exec->ignore_x_mode )
- sph_set_tweaks( loader, glyph_index );
+ /* This may not be the right place for this, but it works... */
+ /* Note that we have to unconditionally load the tweaks since */
+ /* it is possible that glyphs individually switch ClearType's */
+ /* backwards compatibility mode on and off. */
+ sph_set_tweaks( loader, glyph_index );
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -171,6 +172,8 @@
loader->linear_def = 1;
loader->linear = advance_width;
}
+
+ return FT_Err_Ok;
}
@@ -180,7 +183,7 @@
tt_get_metrics_incr_overrides( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
@@ -248,29 +251,6 @@
/*************************************************************************/
/* */
- /* Translates an array of coordinates. */
- /* */
- static void
- translate_array( FT_UInt n,
- FT_Vector* coords,
- FT_Pos delta_x,
- FT_Pos delta_y )
- {
- FT_UInt 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;
- }
-
-
- /*************************************************************************/
- /* */
/* The following functions are used by default with TrueType fonts. */
/* However, they can be replaced by alternatives if we need to support */
/* TrueType-compressed formats (like MicroType) in the future. */
@@ -350,9 +330,9 @@
FT_GlyphLoader gloader = load->gloader;
FT_Int n_contours = load->n_contours;
FT_Outline* outline;
- TT_Face face = (TT_Face)load->face;
FT_UShort n_ins;
FT_Int n_points;
+ FT_ULong tmp;
FT_Byte *flag, *flag_limit;
FT_Byte c, count;
@@ -409,7 +389,7 @@
/* reading the bytecode instructions */
load->glyph->control_len = 0;
- load->glyph->control_data = 0;
+ load->glyph->control_data = NULL;
if ( p + 2 > limit )
goto Invalid_Outline;
@@ -418,14 +398,7 @@
FT_TRACE5(( " Instructions size: %u\n", n_ins ));
- if ( n_ins > face->max_profile.maxSizeOfInstructions )
- {
- FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
- n_ins ));
- error = FT_THROW( Too_Many_Hints );
- goto Fail;
- }
-
+ /* check it */
if ( ( limit - p ) < n_ins )
{
FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
@@ -437,6 +410,20 @@
if ( IS_HINTED( load->load_flags ) )
{
+ /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
+ /* and thus update the bytecode array size by ourselves */
+
+ tmp = load->exec->glyphSize;
+ error = Update_Max( load->exec->memory,
+ &tmp,
+ sizeof ( FT_Byte ),
+ (void*)&load->exec->glyphIns,
+ n_ins );
+
+ load->exec->glyphSize = (FT_UShort)tmp;
+ if ( error )
+ return error;
+
load->glyph->control_len = n_ins;
load->glyph->control_data = load->exec->glyphIns;
@@ -550,8 +537,8 @@
*flag = (FT_Byte)( f & FT_CURVE_TAG_ON );
}
- outline->n_points = (FT_UShort)n_points;
- outline->n_contours = (FT_Short) n_contours;
+ outline->n_points = (FT_Short)n_points;
+ outline->n_contours = (FT_Short)n_contours;
load->cursor = p;
@@ -614,15 +601,31 @@
goto Invalid_Composite;
/* read arguments */
- if ( subglyph->flags & ARGS_ARE_WORDS )
+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )
{
- subglyph->arg1 = FT_NEXT_SHORT( p );
- subglyph->arg2 = FT_NEXT_SHORT( p );
+ if ( subglyph->flags & ARGS_ARE_WORDS )
+ {
+ subglyph->arg1 = FT_NEXT_SHORT( p );
+ subglyph->arg2 = FT_NEXT_SHORT( p );
+ }
+ else
+ {
+ subglyph->arg1 = FT_NEXT_CHAR( p );
+ subglyph->arg2 = FT_NEXT_CHAR( p );
+ }
}
else
{
- subglyph->arg1 = FT_NEXT_CHAR( p );
- subglyph->arg2 = FT_NEXT_CHAR( p );
+ if ( subglyph->flags & ARGS_ARE_WORDS )
+ {
+ subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
+ subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
+ }
+ else
+ {
+ subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
+ subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
+ }
}
/* read transform */
@@ -631,20 +634,20 @@
if ( subglyph->flags & WE_HAVE_A_SCALE )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
yy = xx;
}
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
}
else if ( subglyph->flags & WE_HAVE_A_2X2 )
{
- xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
- yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
+ xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
+ yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
}
subglyph->transform.xx = xx;
@@ -657,6 +660,7 @@
} while ( subglyph->flags & MORE_COMPONENTS );
gloader->current.num_subglyphs = num_subglyphs;
+ FT_TRACE5(( " %d components\n", num_subglyphs ));
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -702,9 +706,10 @@
FT_UInt start_point,
FT_UInt start_contour )
{
- zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
- zone->n_contours = (FT_Short) ( load->outline.n_contours -
- start_contour );
+ zone->n_points = (FT_UShort)load->outline.n_points -
+ (FT_UShort)start_point;
+ zone->n_contours = load->outline.n_contours -
+ (FT_Short)start_contour;
zone->org = load->extra_points + start_point;
zone->cur = load->outline.points + start_point;
zone->orus = load->extra_points2 + start_point;
@@ -728,15 +733,14 @@
FT_Bool is_composite )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
TT_GlyphZone zone = &loader->zone;
- FT_Pos origin;
#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_UInt n_ins;
+ FT_Long n_ins;
#else
FT_UNUSED( is_composite );
#endif
@@ -745,25 +749,18 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
if ( loader->glyph->control_len > 0xFFFFL )
{
- FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
- FT_TRACE1(( "(0x%lx byte) is truncated\n",
+ FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
+ FT_TRACE1(( " (0x%lx byte) is truncated\n",
loader->glyph->control_len ));
}
- n_ins = (FT_UInt)( loader->glyph->control_len );
-#endif
+ n_ins = loader->glyph->control_len;
- origin = zone->cur[zone->n_points - 4].x;
- origin = FT_PIX_ROUND( origin ) - origin;
- if ( origin )
- translate_array( zone->n_points, zone->cur, origin, 0 );
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
/* save original point position in org */
if ( n_ins > 0 )
FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
/* Reset graphics state. */
- loader->exec->GS = ((TT_Size)loader->size)->GS;
+ loader->exec->GS = loader->size->GS;
/* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
/* completely refer to the (already) hinted subglyphs. */
@@ -776,16 +773,18 @@
}
else
{
- loader->exec->metrics.x_scale =
- ((TT_Size)loader->size)->metrics.x_scale;
- loader->exec->metrics.y_scale =
- ((TT_Size)loader->size)->metrics.y_scale;
+ loader->exec->metrics.x_scale = loader->size->metrics.x_scale;
+ loader->exec->metrics.y_scale = loader->size->metrics.y_scale;
}
#endif
- /* round pp2 and pp4 */
+ /* round phantom points */
+ zone->cur[zone->n_points - 4].x =
+ FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
zone->cur[zone->n_points - 3].x =
FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
+ zone->cur[zone->n_points - 2].y =
+ FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
zone->cur[zone->n_points - 1].y =
FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
@@ -793,25 +792,19 @@
if ( n_ins > 0 )
{
- FT_Bool debug;
FT_Error error;
FT_GlyphLoader gloader = loader->gloader;
FT_Outline current_outline = gloader->current.outline;
- error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
- loader->exec->glyphIns, n_ins );
- if ( error )
- return error;
+ TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
+ loader->exec->glyphIns, n_ins );
loader->exec->is_composite = is_composite;
loader->exec->pts = *zone;
- debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
- ((TT_Size)loader->size)->debug );
-
- error = TT_Run_Context( loader->exec, debug );
+ error = TT_Run_Context( loader->exec );
if ( error && loader->exec->pedantic_hinting )
return error;
@@ -823,13 +816,10 @@
#endif
/* save glyph phantom points */
- if ( !loader->preserve_pps )
- {
- loader->pp1 = zone->cur[zone->n_points - 4];
- loader->pp2 = zone->cur[zone->n_points - 3];
- loader->pp3 = zone->cur[zone->n_points - 2];
- loader->pp4 = zone->cur[zone->n_points - 1];
- }
+ loader->pp1 = zone->cur[zone->n_points - 4];
+ loader->pp2 = zone->cur[zone->n_points - 3];
+ loader->pp3 = zone->cur[zone->n_points - 2];
+ loader->pp4 = zone->cur[zone->n_points - 1];
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
@@ -884,28 +874,15 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( ((TT_Face)loader->face)->doblend )
+ if ( loader->face->doblend )
{
/* Deltas apply to the unscaled data. */
- FT_Vector* deltas;
- FT_Memory memory = loader->face->memory;
- FT_Int i;
-
-
- error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
- loader->glyph_index,
- &deltas,
- n_points );
+ error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+ loader->glyph_index,
+ outline,
+ (FT_UInt)n_points );
if ( error )
return error;
-
- for ( i = 0; i < n_points; ++i )
- {
- outline->points[i].x += deltas[i].x;
- outline->points[i].y += deltas[i].y;
- }
-
- FT_FREE( deltas );
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -920,13 +897,13 @@
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_String* family = face->root.family_name;
- FT_Int ppem = loader->size->metrics.x_ppem;
+ FT_UInt ppem = loader->size->metrics.x_ppem;
FT_String* style = face->root.style_name;
- FT_Int x_scale_factor = 1000;
+ FT_UInt x_scale_factor = 1000;
#endif
FT_Vector* vec = outline->points;
@@ -953,9 +930,9 @@
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
x_scale_factor != 1000 )
{
- x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale,
- x_scale_factor, 1000 );
- y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ x_scale = FT_MulDiv( loader->size->metrics.x_scale,
+ (FT_Long)x_scale_factor, 1000 );
+ y_scale = loader->size->metrics.y_scale;
/* compensate for any scaling by de/emboldening; */
/* the amount was determined via experimentation */
@@ -975,8 +952,8 @@
/* scale the glyph */
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ x_scale = loader->size->metrics.x_scale;
+ y_scale = loader->size->metrics.y_scale;
do_scale = TRUE;
}
@@ -1023,32 +1000,31 @@
FT_UInt start_point,
FT_UInt num_base_points )
{
- FT_GlyphLoader gloader = loader->gloader;
- FT_Vector* base_vec = gloader->base.outline.points;
- FT_UInt num_points = gloader->base.outline.n_points;
+ FT_GlyphLoader gloader = loader->gloader;
+ FT_Outline current;
FT_Bool have_scale;
FT_Pos x, y;
+ current.points = gloader->base.outline.points +
+ num_base_points;
+ current.n_points = gloader->base.outline.n_points -
+ (short)num_base_points;
+
have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
WE_HAVE_AN_XY_SCALE |
WE_HAVE_A_2X2 ) );
/* perform the transform required for this subglyph */
if ( have_scale )
- {
- FT_UInt i;
-
-
- for ( i = num_base_points; i < num_points; i++ )
- FT_Vector_Transform( base_vec + i, &subglyph->transform );
- }
+ FT_Outline_Transform( ¤t, &subglyph->transform );
/* get offset */
if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
{
- FT_UInt k = subglyph->arg1;
- FT_UInt l = subglyph->arg2;
+ FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
+ FT_UInt k = (FT_UInt)subglyph->arg1;
+ FT_UInt l = (FT_UInt)subglyph->arg2;
FT_Vector* p1;
FT_Vector* p2;
@@ -1077,9 +1053,9 @@
if ( !x && !y )
return FT_Err_Ok;
- /* Use a default value dependent on */
- /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
- /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
+ /* Use a default value dependent on */
+ /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */
+ /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */
if ( have_scale &&
#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -1091,10 +1067,10 @@
#if 0
- /*************************************************************************/
- /* */
- /* This algorithm is what Apple documents. But it doesn't work. */
- /* */
+ /*******************************************************************/
+ /* */
+ /* This algorithm is what Apple documents. But it doesn't work. */
+ /* */
int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
: -subglyph->transform.xx;
int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
@@ -1114,12 +1090,12 @@
x = FT_MulFix( x, m );
y = FT_MulFix( y, n );
-#else /* 0 */
+#else /* 1 */
- /*************************************************************************/
- /* */
- /* This algorithm is a guess and works much better than the above. */
- /* */
+ /*******************************************************************/
+ /* */
+ /* This algorithm is a guess and works much better than the above. */
+ /* */
FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
subglyph->transform.xy );
FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
@@ -1129,14 +1105,14 @@
x = FT_MulFix( x, mac_xscale );
y = FT_MulFix( y, mac_yscale );
-#endif /* 0 */
+#endif /* 1 */
}
if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
{
- FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ FT_Fixed x_scale = loader->size->metrics.x_scale;
+ FT_Fixed y_scale = loader->size->metrics.y_scale;
x = FT_MulFix( x, x_scale );
@@ -1151,9 +1127,7 @@
}
if ( x || y )
- translate_array( num_points - num_base_points,
- base_vec + num_base_points,
- x, y );
+ FT_Outline_Translate( ¤t, x, y );
return FT_Err_Ok;
}
@@ -1215,24 +1189,26 @@
FT_TRACE5(( " Instructions size = %d\n", n_ins ));
/* check it */
- max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
+ max_ins = loader->face->max_profile.maxSizeOfInstructions;
if ( n_ins > max_ins )
{
- /* acroread ignores this field, so we only do a rough safety check */
+ /* don't trust `maxSizeOfInstructions'; */
+ /* only do a rough safety check */
if ( (FT_Int)n_ins > loader->byte_len )
{
- FT_TRACE1(( "TT_Process_Composite_Glyph: "
- "too many instructions (%d) for glyph with length %d\n",
+ FT_TRACE1(( "TT_Process_Composite_Glyph:"
+ " too many instructions (%d) for glyph with length %d\n",
n_ins, loader->byte_len ));
return FT_THROW( Too_Many_Hints );
}
- tmp = loader->exec->glyphSize;
+ tmp = loader->exec->glyphSize;
error = Update_Max( loader->exec->memory,
&tmp,
sizeof ( FT_Byte ),
(void*)&loader->exec->glyphIns,
n_ins );
+
loader->exec->glyphSize = (FT_UShort)tmp;
if ( error )
return error;
@@ -1254,7 +1230,7 @@
/* Some points are likely touched during execution of */
/* instructions on components. So let's untouch them. */
- for ( i = start_point; i < loader->zone.n_points; i++ )
+ for ( i = 0; i < loader->zone.n_points; i++ )
loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
loader->zone.n_points += 4;
@@ -1263,21 +1239,134 @@
}
- /* Calculate the four phantom points. */
- /* The first two stand for horizontal origin and advance. */
- /* The last two stand for vertical origin and advance. */
+ /*
+ * Calculate the phantom points
+ *
+ * Defining the right side bearing (rsb) as
+ *
+ * rsb = aw - (lsb + xmax - xmin)
+ *
+ * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
+ * and `xmax' the glyph's minimum and maximum x value), the OpenType
+ * specification defines the initial position of horizontal phantom points
+ * as
+ *
+ * pp1 = (round(xmin - lsb), 0) ,
+ * pp2 = (round(pp1 + aw), 0) .
+ *
+ * Note that the rounding to the grid (in the device space) is not
+ * documented currently in the specification.
+ *
+ * However, the specification lacks the precise definition of vertical
+ * phantom points. Greg Hitchcock provided the following explanation.
+ *
+ * - a `vmtx' table is present
+ *
+ * For any glyph, the minimum and maximum y values (`ymin' and `ymax')
+ * are given in the `glyf' table, the top side bearing (tsb) and advance
+ * height (ah) are given in the `vmtx' table. The bottom side bearing
+ * (bsb) is then calculated as
+ *
+ * bsb = ah - (tsb + ymax - ymin) ,
+ *
+ * and the initial position of vertical phantom points is
+ *
+ * pp3 = (x, round(ymax + tsb)) ,
+ * pp4 = (x, round(pp3 - ah)) .
+ *
+ * See below for value `x'.
+ *
+ * - no `vmtx' table in the font
+ *
+ * If there is an `OS/2' table, we set
+ *
+ * DefaultAscender = sTypoAscender ,
+ * DefaultDescender = sTypoDescender ,
+ *
+ * otherwise we use data from the `hhea' table:
+ *
+ * DefaultAscender = Ascender ,
+ * DefaultDescender = Descender .
+ *
+ * With these two variables we can now set
+ *
+ * ah = DefaultAscender - sDefaultDescender ,
+ * tsb = DefaultAscender - yMax ,
+ *
+ * and proceed as if a `vmtx' table was present.
+ *
+ * Usually we have
+ *
+ * x = aw / 2 , (1)
+ *
+ * but there is one compatibility case where it can be set to
+ *
+ * x = -DefaultDescender -
+ * ((DefaultAscender - DefaultDescender - aw) / 2) . (2)
+ *
+ * and another one with
+ *
+ * x = 0 . (3)
+ *
+ * In Windows, the history of those values is quite complicated,
+ * depending on the hinting engine (that is, the graphics framework).
+ *
+ * framework from to formula
+ * ----------------------------------------------------------
+ * GDI Windows 98 current (1)
+ * (Windows 2000 for NT)
+ * GDI+ Windows XP Windows 7 (2)
+ * GDI+ Windows 8 current (3)
+ * DWrite Windows 7 current (3)
+ *
+ * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
+ * (3) for everything else.
+ *
+ */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
#define TT_LOADER_SET_PP( loader ) \
- do { \
+ do \
+ { \
+ FT_Bool subpixel_hinting_ = loader->exec \
+ ? loader->exec->subpixel_hinting \
+ : 0; \
+ FT_Bool grayscale_ = loader->exec \
+ ? loader->exec->grayscale \
+ : 0; \
+ FT_Bool use_aw_2_ = (FT_Bool)( subpixel_hinting_ && \
+ grayscale_ ); \
+ \
+ \
(loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
(loader)->pp1.y = 0; \
(loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
(loader)->pp2.y = 0; \
+ \
+ (loader)->pp3.x = use_aw_2_ ? (loader)->advance / 2 : 0; \
+ (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \
+ (loader)->pp4.x = use_aw_2_ ? (loader)->advance / 2 : 0; \
+ (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
+ } while ( 0 )
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+#define TT_LOADER_SET_PP( loader ) \
+ do \
+ { \
+ (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
+ (loader)->pp1.y = 0; \
+ (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
+ (loader)->pp2.y = 0; \
+ \
(loader)->pp3.x = 0; \
- (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
+ (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \
(loader)->pp4.x = 0; \
(loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
} while ( 0 )
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
/*************************************************************************/
/* */
@@ -1297,14 +1386,10 @@
FT_Error error = FT_Err_Ok;
FT_Fixed x_scale, y_scale;
FT_ULong offset;
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_GlyphLoader gloader = loader->gloader;
FT_Bool opened_frame = 0;
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- FT_Vector* deltas = NULL;
-#endif
-
#ifdef FT_CONFIG_OPTION_INCREMENTAL
FT_StreamRec inc_stream;
FT_Data glyph_data;
@@ -1312,6 +1397,11 @@
#endif
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( recurse_count )
+ FT_TRACE5(( " nesting level: %d\n", recurse_count ));
+#endif
+
/* some fonts have an incorrect value of `maxComponentDepth', */
/* thus we allow depth 1 to catch the majority of them */
if ( recurse_count > 1 &&
@@ -1321,19 +1411,21 @@
goto Exit;
}
+#ifndef FT_CONFIG_OPTION_INCREMENTAL
/* check glyph index */
if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
{
error = FT_THROW( Invalid_Glyph_Index );
goto Exit;
}
+#endif
loader->glyph_index = glyph_index;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = ((TT_Size)loader->size)->metrics.x_scale;
- y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+ x_scale = loader->size->metrics.x_scale;
+ y_scale = loader->size->metrics.y_scale;
}
else
{
@@ -1341,8 +1433,6 @@
y_scale = 0x10000L;
}
- tt_get_metrics( loader, glyph_index );
-
/* Set `offset' to the start of the glyph relative to the start of */
/* the `glyf' table, and `byte_len' to the length of the glyph in */
/* bytes. */
@@ -1366,7 +1456,8 @@
FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
FT_Stream_OpenMemory( &inc_stream,
- glyph_data.pointer, glyph_data.length );
+ glyph_data.pointer,
+ (FT_ULong)glyph_data.length );
loader->stream = &inc_stream;
}
@@ -1394,7 +1485,7 @@
error = face->access_glyph_frame( loader, glyph_index,
loader->glyf_offset + offset,
- loader->byte_len );
+ (FT_UInt)loader->byte_len );
if ( error )
goto Exit;
@@ -1402,7 +1493,17 @@
/* read glyph header first */
error = face->read_glyph_header( loader );
- if ( error || header_only )
+ if ( error )
+ goto Exit;
+
+ /* the metrics must be computed after loading the glyph header */
+ /* since we need the glyph's `yMax' value in case the vertical */
+ /* metrics must be emulated */
+ error = tt_get_metrics( loader, glyph_index );
+ if ( error )
+ goto Exit;
+
+ if ( header_only )
goto Exit;
}
@@ -1413,6 +1514,10 @@
loader->bbox.yMin = 0;
loader->bbox.yMax = 0;
+ error = tt_get_metrics( loader, glyph_index );
+ if ( error )
+ goto Exit;
+
if ( header_only )
goto Exit;
@@ -1426,32 +1531,64 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( ((TT_Face)(loader->face))->doblend )
+ if ( loader->face->doblend )
{
+ /* a small outline structure with four elements for */
+ /* communication with `TT_Vary_Apply_Glyph_Deltas' */
+ FT_Vector points[4];
+ char tags[4] = { 1, 1, 1, 1 };
+ short contours[4] = { 0, 1, 2, 3 };
+ FT_Outline outline;
+
+
+ points[0].x = loader->pp1.x;
+ points[0].y = loader->pp1.y;
+ points[1].x = loader->pp2.x;
+ points[1].y = loader->pp2.y;
+
+ points[2].x = loader->pp3.x;
+ points[2].y = loader->pp3.y;
+ points[3].x = loader->pp4.x;
+ points[3].y = loader->pp4.y;
+
+ outline.n_points = 4;
+ outline.n_contours = 4;
+ outline.points = points;
+ outline.tags = tags;
+ outline.contours = contours;
+
/* this must be done before scaling */
- FT_Memory memory = loader->face->memory;
-
-
- error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
- glyph_index, &deltas, 4 );
+ error = TT_Vary_Apply_Glyph_Deltas( loader->face,
+ glyph_index,
+ &outline,
+ (FT_UInt)outline.n_points );
if ( error )
goto Exit;
- loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
- loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
- loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
- loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
+ loader->pp1.x = points[0].x;
+ loader->pp1.y = points[0].y;
+ loader->pp2.x = points[1].x;
+ loader->pp2.y = points[1].y;
- FT_FREE( deltas );
+ loader->pp3.x = points[2].x;
+ loader->pp3.y = points[2].y;
+ loader->pp4.x = points[3].x;
+ loader->pp4.y = points[3].y;
}
-#endif
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+ /* scale phantom points, if necessary; */
+ /* they get rounded in `TT_Hint_Glyph' */
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ /* pp1.y and pp2.y are always zero */
+
+ loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+ loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
@@ -1459,8 +1596,8 @@
goto Exit;
}
- /* must initialize points before (possibly) overriding */
- /* glyph metrics from the incremental interface */
+ /* must initialize phantom points before (possibly) overriding */
+ /* glyph metrics from the incremental interface */
TT_LOADER_SET_PP( loader );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -1497,13 +1634,42 @@
/* otherwise, load a composite! */
else if ( loader->n_contours == -1 )
{
+ FT_Memory memory = face->root.memory;
+
FT_UInt start_point;
FT_UInt start_contour;
FT_ULong ins_pos; /* position of composite instructions, if any */
- start_point = gloader->base.outline.n_points;
- start_contour = gloader->base.outline.n_contours;
+ /*
+ * We store the glyph index directly in the `node->data' pointer,
+ * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
+ * double cast to make this portable. Note, however, that this needs
+ * pointers with a width of at least 32 bits.
+ */
+
+ /* check whether we already have a composite glyph with this index */
+ if ( FT_List_Find( &loader->composites,
+ (void*)(unsigned long)glyph_index ) )
+ {
+ FT_TRACE1(( "TT_Load_Composite_Glyph:"
+ " infinite recursion detected\n" ));
+ error = FT_THROW( Invalid_Composite );
+ goto Exit;
+ }
+ else
+ {
+ FT_ListNode node = NULL;
+
+
+ if ( FT_NEW( node ) )
+ goto Exit;
+ node->data = (void*)(unsigned long)glyph_index;
+ FT_List_Add( &loader->composites, node );
+ }
+
+ start_point = (FT_UInt)gloader->base.outline.n_points;
+ start_contour = (FT_UInt)gloader->base.outline.n_contours;
/* for each subglyph, read composite header */
error = face->read_composite_glyph( loader );
@@ -1521,51 +1687,119 @@
if ( face->doblend )
{
- FT_Int i, limit;
+ short i, limit;
FT_SubGlyph subglyph;
- FT_Memory memory = face->root.memory;
+
+ FT_Outline outline;
+ FT_Vector* points = NULL;
+ char* tags = NULL;
+ short* contours = NULL;
- /* this provides additional offsets */
- /* for each component's translation */
+ limit = (short)gloader->current.num_subglyphs;
- if ( ( error = TT_Vary_Get_Glyph_Deltas(
- face,
- glyph_index,
- &deltas,
- gloader->current.num_subglyphs + 4 )) != 0 )
- goto Exit;
+ /* construct an outline structure for */
+ /* communication with `TT_Vary_Apply_Glyph_Deltas' */
+ outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
+ outline.n_contours = outline.n_points;
- subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
- limit = gloader->current.num_subglyphs;
+ if ( FT_NEW_ARRAY( points, outline.n_points ) ||
+ FT_NEW_ARRAY( tags, outline.n_points ) ||
+ FT_NEW_ARRAY( contours, outline.n_points ) )
+ goto Exit1;
- for ( i = 0; i < limit; ++i, ++subglyph )
+ subglyph = gloader->current.subglyphs;
+
+ for ( i = 0; i < limit; i++, subglyph++ )
{
- if ( subglyph->flags & ARGS_ARE_XY_VALUES )
- {
- /* XXX: overflow check for subglyph->{arg1,arg2}. */
- /* deltas[i].{x,y} must be within signed 16-bit, */
- /* but the restriction of summed delta is not clear */
- subglyph->arg1 += (FT_Int16)deltas[i].x;
- subglyph->arg2 += (FT_Int16)deltas[i].y;
- }
+ /* applying deltas for anchor points doesn't make sense, */
+ /* but we don't have to specially check this since */
+ /* unused delta values are zero anyways */
+ points[i].x = subglyph->arg1;
+ points[i].y = subglyph->arg2;
+ tags[i] = 1;
+ contours[i] = i;
}
- loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
- loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
- loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
- loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
+ points[i].x = loader->pp1.x;
+ points[i].y = loader->pp1.y;
+ tags[i] = 1;
+ contours[i] = i;
- FT_FREE( deltas );
+ i++;
+ points[i].x = loader->pp2.x;
+ points[i].y = loader->pp2.y;
+ tags[i] = 1;
+ contours[i] = i;
+
+ i++;
+ points[i].x = loader->pp3.x;
+ points[i].y = loader->pp3.y;
+ tags[i] = 1;
+ contours[i] = i;
+
+ i++;
+ points[i].x = loader->pp4.x;
+ points[i].y = loader->pp4.y;
+ tags[i] = 1;
+ contours[i] = i;
+
+ outline.points = points;
+ outline.tags = tags;
+ outline.contours = contours;
+
+ /* this call provides additional offsets */
+ /* for each component's translation */
+ if ( ( error = TT_Vary_Apply_Glyph_Deltas(
+ face,
+ glyph_index,
+ &outline,
+ (FT_UInt)outline.n_points ) ) != 0 )
+ goto Exit1;
+
+ subglyph = gloader->current.subglyphs;
+
+ for ( i = 0; i < limit; i++, subglyph++ )
+ {
+ /* XXX: overflow check for subglyph->{arg1,arg2}. */
+ /* Deltas must be within signed 16-bit, */
+ /* but the restriction of summed deltas is not clear */
+ subglyph->arg1 = (FT_Int16)points[i].x;
+ subglyph->arg2 = (FT_Int16)points[i].y;
+ }
+
+ loader->pp1.x = points[i + 0].x;
+ loader->pp1.y = points[i + 0].y;
+ loader->pp2.x = points[i + 1].x;
+ loader->pp2.y = points[i + 1].y;
+
+ loader->pp3.x = points[i + 2].x;
+ loader->pp3.y = points[i + 2].y;
+ loader->pp4.x = points[i + 3].x;
+ loader->pp4.y = points[i + 3].y;
+
+ Exit1:
+ FT_FREE( outline.points );
+ FT_FREE( outline.tags );
+ FT_FREE( outline.contours );
+
+ if ( error )
+ goto Exit;
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+ /* scale phantom points, if necessary; */
+ /* they get rounded in `TT_Hint_Glyph' */
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ /* pp1.y and pp2.y are always zero */
+
+ loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
+ loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
@@ -1586,7 +1820,7 @@
{
FT_UInt n, num_base_points;
- FT_SubGlyph subglyph = 0;
+ FT_SubGlyph subglyph = NULL;
FT_UInt num_points = start_point;
FT_UInt num_subglyphs = gloader->current.num_subglyphs;
@@ -1615,16 +1849,19 @@
pp[2] = loader->pp3;
pp[3] = loader->pp4;
- num_base_points = gloader->base.outline.n_points;
+ num_base_points = (FT_UInt)gloader->base.outline.n_points;
- error = load_truetype_glyph( loader, subglyph->index,
- recurse_count + 1, FALSE );
+ error = load_truetype_glyph( loader,
+ (FT_UInt)subglyph->index,
+ recurse_count + 1,
+ FALSE );
if ( error )
goto Exit;
/* restore subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + n;
+ /* restore phantom points if necessary */
if ( !( subglyph->flags & USE_MY_METRICS ) )
{
loader->pp1 = pp[0];
@@ -1633,7 +1870,7 @@
loader->pp4 = pp[3];
}
- num_points = gloader->base.outline.n_points;
+ num_points = (FT_UInt)gloader->base.outline.n_points;
if ( num_points == num_base_points )
continue;
@@ -1644,8 +1881,12 @@
/* (1): exists from the beginning */
/* (2): components that have been loaded so far */
/* (3): the newly loaded component */
- TT_Process_Composite_Component( loader, subglyph, start_point,
- num_base_points );
+ error = TT_Process_Composite_Component( loader,
+ subglyph,
+ start_point,
+ num_base_points );
+ if ( error )
+ goto Exit;
}
loader->stream = old_stream;
@@ -1654,16 +1895,17 @@
/* process the glyph */
loader->ins_pos = ins_pos;
if ( IS_HINTED( loader->load_flags ) &&
-
#ifdef TT_USE_BYTECODE_INTERPRETER
-
subglyph->flags & WE_HAVE_INSTR &&
-
#endif
-
num_points > start_point )
- TT_Process_Composite_Glyph( loader, start_point, start_contour );
-
+ {
+ error = TT_Process_Composite_Glyph( loader,
+ start_point,
+ start_contour );
+ if ( error )
+ goto Exit;
+ }
}
}
else
@@ -1699,7 +1941,7 @@
compute_glyph_metrics( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -1707,7 +1949,7 @@
FT_BBox bbox;
FT_Fixed y_scale;
TT_GlyphSlot glyph = loader->glyph;
- TT_Size size = (TT_Size)loader->size;
+ TT_Size size = loader->size;
y_scale = 0x10000L;
@@ -1728,8 +1970,10 @@
glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
/* adjust advance width to the value contained in the hdmx table */
- if ( !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) )
+ /* unless FT_LOAD_COMPUTE_METRICS is set */
+ if ( !face->postscript.isFixedPitch &&
+ IS_HINTED( loader->load_flags ) &&
+ !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
{
FT_Byte* widthp;
@@ -1752,7 +1996,7 @@
( ( ignore_x_mode && loader->exec->compatible_widths ) ||
!ignore_x_mode ||
SPH_OPTION_BITMAP_WIDTHS ) )
- glyph->metrics.horiAdvance = *widthp << 6;
+ glyph->metrics.horiAdvance = *widthp * 64;
}
else
@@ -1760,7 +2004,7 @@
{
if ( widthp )
- glyph->metrics.horiAdvance = *widthp << 6;
+ glyph->metrics.horiAdvance = *widthp * 64;
}
}
@@ -1891,7 +2135,7 @@
error = sfnt->load_sbit_image( face,
size->strike_index,
glyph_index,
- (FT_Int)load_flags,
+ (FT_UInt)load_flags,
stream,
&glyph->bitmap,
&metrics );
@@ -1900,16 +2144,16 @@
glyph->outline.n_points = 0;
glyph->outline.n_contours = 0;
- glyph->metrics.width = (FT_Pos)metrics.width << 6;
- glyph->metrics.height = (FT_Pos)metrics.height << 6;
+ glyph->metrics.width = (FT_Pos)metrics.width * 64;
+ glyph->metrics.height = (FT_Pos)metrics.height * 64;
- glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
- glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
- glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+ glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
+ glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
+ glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64;
- glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
- glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
- glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+ glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
+ glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
+ glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64;
glyph->format = FT_GLYPH_FORMAT_BITMAP;
@@ -1938,6 +2182,8 @@
FT_Int32 load_flags,
FT_Bool glyf_table_only )
{
+ FT_Error error;
+
TT_Face face;
FT_Stream stream;
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -1961,33 +2207,35 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
- FT_Bool subpixel_hinting = FALSE;
- FT_Bool grayscale_hinting = TRUE;
+ FT_Bool subpixel_hinting = FALSE;
#if 0
/* not used yet */
FT_Bool compatible_widths;
FT_Bool symmetrical_smoothing;
FT_Bool bgr;
+ FT_Bool vertical_lcd;
FT_Bool subpixel_positioned;
+ FT_Bool gray_cleartype;
#endif
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
FT_Bool reexecute = FALSE;
- if ( !size->cvt_ready )
+ if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
{
- FT_Error error = tt_size_ready_bytecode( size, pedantic );
-
-
+ error = tt_size_ready_bytecode( size, pedantic );
if ( error )
return error;
}
+ else if ( size->bytecode_ready )
+ return size->bytecode_ready;
+ else if ( size->cvt_ready )
+ return size->cvt_ready;
/* query new execution context */
- exec = size->debug ? size->context
- : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+ exec = size->context;
if ( !exec )
return FT_THROW( Could_Not_Find_Context );
@@ -1995,33 +2243,35 @@
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
- subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags )
- != FT_RENDER_MODE_MONO ) &&
- SPH_OPTION_SET_SUBPIXEL );
+ subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO ) &&
+ SPH_OPTION_SET_SUBPIXEL );
if ( subpixel_hinting )
- grayscale = grayscale_hinting = FALSE;
+ grayscale = FALSE;
else if ( SPH_OPTION_SET_GRAYSCALE )
{
- grayscale = grayscale_hinting = TRUE;
- subpixel_hinting = FALSE;
+ grayscale = TRUE;
+ subpixel_hinting = FALSE;
}
else
- grayscale = grayscale_hinting = FALSE;
+ grayscale = FALSE;
if ( FT_IS_TRICKY( glyph->face ) )
- subpixel_hinting = grayscale_hinting = FALSE;
+ subpixel_hinting = FALSE;
- exec->ignore_x_mode = subpixel_hinting || grayscale_hinting;
+ exec->ignore_x_mode = subpixel_hinting || grayscale;
exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
#if 1
exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
- exec->symmetrical_smoothing = FALSE;
+ exec->symmetrical_smoothing = TRUE;
exec->bgr = FALSE;
+ exec->vertical_lcd = FALSE;
exec->subpixel_positioned = TRUE;
+ exec->gray_cleartype = FALSE;
#else /* 0 */
exec->compatible_widths =
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
@@ -2032,9 +2282,15 @@
exec->bgr =
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
TT_LOAD_BGR );
+ exec->vertical_lcd =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_VERTICAL_LCD );
exec->subpixel_positioned =
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
TT_LOAD_SUBPIXEL_POSITIONED );
+ exec->gray_cleartype =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ TT_LOAD_GRAY_CLEARTYPE );
#endif /* 0 */
}
@@ -2047,7 +2303,9 @@
FT_RENDER_MODE_MONO );
}
- TT_Load_Context( exec, face, size );
+ error = TT_Load_Context( exec, face, size );
+ if ( error )
+ return error;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
@@ -2066,13 +2324,13 @@
/* a change from mono to grayscale rendering (and vice versa) */
/* requires a re-execution of the CVT program */
- if ( grayscale != exec->grayscale_hinting )
+ if ( grayscale != exec->grayscale )
{
FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
" re-executing `prep' table\n" ));
- exec->grayscale_hinting = grayscale_hinting;
- reexecute = TRUE;
+ exec->grayscale = grayscale;
+ reexecute = TRUE;
}
}
else
@@ -2084,7 +2342,7 @@
/* requires a re-execution of the CVT program */
if ( grayscale != exec->grayscale )
{
- FT_TRACE4(( "tt_loader_init: grayscale change,"
+ FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
" re-executing `prep' table\n" ));
exec->grayscale = grayscale;
@@ -2099,10 +2357,12 @@
for ( i = 0; i < size->cvt_size; i++ )
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size, pedantic );
+ error = tt_size_run_prep( size, pedantic );
+ if ( error )
+ return error;
}
- /* see whether the cvt program has disabled hinting */
+ /* check whether the cvt program has disabled hinting */
if ( exec->GS.instruct_control & 1 )
load_flags |= FT_LOAD_NO_HINTING;
@@ -2110,6 +2370,13 @@
if ( exec->GS.instruct_control & 2 )
exec->GS = tt_default_graphics_state;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /* check whether we have a font hinted for ClearType -- */
+ /* note that this flag can also be modified in a glyph's bytecode */
+ if ( exec->GS.instruct_control & 4 )
+ exec->ignore_x_mode = 0;
+#endif
+
exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
loader->exec = exec;
loader->instructions = exec->glyphIns;
@@ -2130,8 +2397,7 @@
#endif
{
- FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
-
+ error = face->goto_table( face, TTAG_glyf, stream, 0 );
if ( FT_ERR_EQ( error, Table_Missing ) )
loader->glyf_offset = 0;
@@ -2154,17 +2420,30 @@
loader->gloader = gloader;
}
- loader->load_flags = load_flags;
+ loader->load_flags = (FT_ULong)load_flags;
- loader->face = (FT_Face)face;
- loader->size = (FT_Size)size;
+ loader->face = face;
+ loader->size = size;
loader->glyph = (FT_GlyphSlot)glyph;
loader->stream = stream;
+ loader->composites.head = NULL;
+ loader->composites.tail = NULL;
+
return FT_Err_Ok;
}
+ static void
+ tt_loader_done( TT_Loader loader )
+ {
+ FT_List_Finalize( &loader->composites,
+ NULL,
+ loader->face->root.memory,
+ NULL );
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -2202,7 +2481,7 @@
TT_LoaderRec loader;
- error = FT_Err_Ok;
+ FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
@@ -2221,16 +2500,20 @@
/* for the bbox we need the header only */
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
+ tt_loader_done( &loader );
glyph->linearHoriAdvance = loader.linear;
- glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
- loader.vadvance;
+ glyph->linearVertAdvance = loader.vadvance;
- /* sanity check: if `horiAdvance' in the sbit metric */
- /* structure isn't set, use `linearHoriAdvance' */
+ /* sanity checks: if `xxxAdvance' in the sbit metric */
+ /* structure isn't set, use `linearXXXAdvance' */
if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
glyph->metrics.horiAdvance =
FT_MulFix( glyph->linearHoriAdvance,
size->root.metrics.x_scale );
+ if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
+ glyph->metrics.vertAdvance =
+ FT_MulFix( glyph->linearVertAdvance,
+ size->root.metrics.y_scale );
}
return FT_Err_Ok;
@@ -2310,9 +2593,11 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
- compute_glyph_metrics( &loader, glyph_index );
+ error = compute_glyph_metrics( &loader, glyph_index );
}
+ tt_loader_done( &loader );
+
/* Set the `high precision' bit flag. */
/* This is _critical_ to get correct output for monochrome */
/* TrueType glyphs at all sizes using the bytecode interpreter. */
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 05f7588..8e3255e 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2006, 2008, 2011 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -43,6 +43,7 @@
FT_LOCAL( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
+ FT_Pos yMax,
FT_Short* tsb,
FT_UShort* ah );
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 7899d36..5d4384e 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
/* */
/* TrueType GX Font Variation loader */
/* */
-/* Copyright 2004-2013 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,7 +20,7 @@
/* */
/* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */
/* */
- /* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */
+ /* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */
/* */
/* The documentation for `fvar' is inconsistent. At one point it says */
/* that `countSizePairs' should be 3, at another point 2. It should */
@@ -60,9 +60,9 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#define FT_Stream_FTell( stream ) \
+#define FT_Stream_FTell( stream ) \
(FT_ULong)( (stream)->cursor - (stream)->base )
-#define FT_Stream_SeekSet( stream, off ) \
+#define FT_Stream_SeekSet( stream, off ) \
( (stream)->cursor = (stream)->base + (off) )
@@ -96,8 +96,8 @@
#define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0
-#define GX_PT_POINTS_ARE_WORDS 0x80
-#define GX_PT_POINT_RUN_COUNT_MASK 0x7F
+#define GX_PT_POINTS_ARE_WORDS 0x80U
+#define GX_PT_POINT_RUN_COUNT_MASK 0x7FU
/*************************************************************************/
@@ -112,6 +112,8 @@
/* <Input> */
/* stream :: The data stream. */
/* */
+ /* size :: The size of the table holding the data. */
+ /* */
/* <Output> */
/* point_cnt :: The number of points read. A zero value means that */
/* all points in the glyph will be affected, without */
@@ -123,55 +125,77 @@
/* */
static FT_UShort*
ft_var_readpackedpoints( FT_Stream stream,
+ FT_ULong size,
FT_UInt *point_cnt )
{
FT_UShort *points = NULL;
- FT_Int n;
- FT_Int runcnt;
- FT_Int i;
- FT_Int j;
- FT_Int first;
+ FT_UInt n;
+ FT_UInt runcnt;
+ FT_UInt i, j;
+ FT_UShort first;
FT_Memory memory = stream->memory;
FT_Error error = FT_Err_Ok;
FT_UNUSED( error );
- *point_cnt = n = FT_GET_BYTE();
+ *point_cnt = 0;
+
+ n = FT_GET_BYTE();
if ( n == 0 )
return ALL_POINTS;
if ( n & GX_PT_POINTS_ARE_WORDS )
- n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );
+ {
+ n &= GX_PT_POINT_RUN_COUNT_MASK;
+ n <<= 8;
+ n |= FT_GET_BYTE();
+ }
+
+ if ( n > size )
+ {
+ FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
+ return NULL;
+ }
if ( FT_NEW_ARRAY( points, n ) )
return NULL;
+ *point_cnt = n;
+
i = 0;
while ( i < n )
{
runcnt = FT_GET_BYTE();
if ( runcnt & GX_PT_POINTS_ARE_WORDS )
{
- runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
- first = points[i++] = FT_GET_USHORT();
+ runcnt &= GX_PT_POINT_RUN_COUNT_MASK;
+ first = FT_GET_USHORT();
+ points[i++] = first;
- if ( runcnt < 1 || i + runcnt >= n )
+ if ( runcnt < 1 || i + runcnt > n )
goto Exit;
- /* first point not included in runcount */
- for ( j = 0; j < runcnt; ++j )
- points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
+ /* first point not included in run count */
+ for ( j = 0; j < runcnt; j++ )
+ {
+ first += FT_GET_USHORT();
+ points[i++] = first;
+ }
}
else
{
- first = points[i++] = FT_GET_BYTE();
+ first = FT_GET_BYTE();
+ points[i++] = first;
- if ( runcnt < 1 || i + runcnt >= n )
+ if ( runcnt < 1 || i + runcnt > n )
goto Exit;
- for ( j = 0; j < runcnt; ++j )
- points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
+ for ( j = 0; j < runcnt; j++ )
+ {
+ first += FT_GET_BYTE();
+ points[i++] = first;
+ }
}
}
@@ -180,12 +204,9 @@
}
- enum
- {
- GX_DT_DELTAS_ARE_ZERO = 0x80,
- GX_DT_DELTAS_ARE_WORDS = 0x40,
- GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
- };
+#define GX_DT_DELTAS_ARE_ZERO 0x80U
+#define GX_DT_DELTAS_ARE_WORDS 0x40U
+#define GX_DT_DELTA_RUN_COUNT_MASK 0x3FU
/*************************************************************************/
@@ -200,7 +221,9 @@
/* <Input> */
/* stream :: The data stream. */
/* */
- /* delta_cnt :: The number of to be read. */
+ /* size :: The size of the table holding the data. */
+ /* */
+ /* delta_cnt :: The number of deltas to be read. */
/* */
/* <Return> */
/* An array of FT_Short containing the deltas for the affected */
@@ -210,18 +233,24 @@
/* */
static FT_Short*
ft_var_readpackeddeltas( FT_Stream stream,
- FT_Offset delta_cnt )
+ FT_ULong size,
+ FT_UInt delta_cnt )
{
FT_Short *deltas = NULL;
- FT_UInt runcnt;
- FT_Offset i;
- FT_UInt j;
+ FT_UInt runcnt, cnt;
+ FT_UInt i, j;
FT_Memory memory = stream->memory;
FT_Error error = FT_Err_Ok;
FT_UNUSED( error );
+ if ( delta_cnt > size )
+ {
+ FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
+ return NULL;
+ }
+
if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
return NULL;
@@ -229,34 +258,30 @@
while ( i < delta_cnt )
{
runcnt = FT_GET_BYTE();
+ cnt = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
+
if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
{
- /* runcnt zeroes get added */
- for ( j = 0;
- j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
- ++j )
+ /* `runcnt' zeroes get added */
+ for ( j = 0; j <= cnt && i < delta_cnt; j++ )
deltas[i++] = 0;
}
else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
{
- /* runcnt shorts from the stack */
- for ( j = 0;
- j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
- ++j )
+ /* `runcnt' shorts from the stack */
+ for ( j = 0; j <= cnt && i < delta_cnt; j++ )
deltas[i++] = FT_GET_SHORT();
}
else
{
- /* runcnt signed bytes from the stack */
- for ( j = 0;
- j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
- ++j )
+ /* `runcnt' signed bytes from the stack */
+ for ( j = 0; j <= cnt && i < delta_cnt; j++ )
deltas[i++] = FT_GET_CHAR();
}
- if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )
+ if ( j <= cnt )
{
- /* Bad format */
+ /* bad format */
FT_FREE( deltas );
return NULL;
}
@@ -281,12 +306,12 @@
static void
ft_var_load_avar( TT_Face face )
{
- FT_Stream stream = FT_FACE_STREAM(face);
+ FT_Stream stream = FT_FACE_STREAM( face );
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
GX_AVarSegment segment;
FT_Error error = FT_Err_Ok;
- FT_ULong version;
+ FT_Long version;
FT_Long axisCount;
FT_Int i, j;
FT_ULong table_len;
@@ -294,9 +319,15 @@
FT_UNUSED( error );
+ FT_TRACE2(( "AVAR " ));
+
blend->avar_checked = TRUE;
- if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )
+ error = face->goto_table( face, TTAG_avar, stream, &table_len );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing\n" ));
return;
+ }
if ( FT_FRAME_ENTER( table_len ) )
return;
@@ -304,23 +335,37 @@
version = FT_GET_LONG();
axisCount = FT_GET_LONG();
- if ( version != 0x00010000L ||
- axisCount != (FT_Long)blend->mmvar->num_axis )
+ if ( version != 0x00010000L )
+ {
+ FT_TRACE2(( "bad table version\n" ));
goto Exit;
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ if ( axisCount != (FT_Long)blend->mmvar->num_axis )
+ {
+ FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n"
+ " table are different\n" ));
+ goto Exit;
+ }
if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
goto Exit;
segment = &blend->avar_segment[0];
- for ( i = 0; i < axisCount; ++i, ++segment )
+ for ( i = 0; i < axisCount; i++, segment++ )
{
+ FT_TRACE5(( " axis %d:\n", i ));
+
segment->pairCount = FT_GET_USHORT();
- if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
+ if ( (FT_ULong)segment->pairCount * 4 > table_len ||
+ FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
{
/* Failure. Free everything we have done so far. We must do */
/* it right now since loading the `avar' table is optional. */
- for ( j = i - 1; j >= 0; --j )
+ for ( j = i - 1; j >= 0; j-- )
FT_FREE( blend->avar_segment[j].correspondence );
FT_FREE( blend->avar_segment );
@@ -328,13 +373,18 @@
goto Exit;
}
- for ( j = 0; j < segment->pairCount; ++j )
+ for ( j = 0; j < segment->pairCount; j++ )
{
- segment->correspondence[j].fromCoord =
- FT_GET_SHORT() << 2; /* convert to Fixed */
- segment->correspondence[j].toCoord =
- FT_GET_SHORT()<<2; /* convert to Fixed */
+ /* convert to Fixed */
+ segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
+ segment->correspondence[j].toCoord = FT_GET_SHORT() * 4;
+
+ FT_TRACE5(( " mapping %.4f to %.4f\n",
+ segment->correspondence[j].fromCoord / 65536.0,
+ segment->correspondence[j].toCoord / 65536.0 ));
}
+
+ FT_TRACE5(( "\n" ));
}
Exit:
@@ -361,8 +411,8 @@
/* ft_var_load_gvar */
/* */
/* <Description> */
- /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */
- /* had better be there too. */
+ /* Parse the `gvar' table if present. If `fvar' is there, `gvar' had */
+ /* better be there too. */
/* */
/* <InOut> */
/* face :: The font face. */
@@ -373,7 +423,7 @@
static FT_Error
ft_var_load_gvar( TT_Face face )
{
- FT_Stream stream = FT_FACE_STREAM(face);
+ FT_Stream stream = FT_FACE_STREAM( face );
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
FT_Error error;
@@ -400,23 +450,66 @@
FT_FRAME_END
};
- if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )
+
+ FT_TRACE2(( "GVAR " ));
+
+ if ( ( error = face->goto_table( face,
+ TTAG_gvar,
+ stream,
+ &table_len ) ) != 0 )
+ {
+ FT_TRACE2(( "is missing\n" ));
goto Exit;
+ }
gvar_start = FT_STREAM_POS( );
if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
goto Exit;
+ if ( gvar_head.version != 0x00010000L )
+ {
+ FT_TRACE1(( "bad table version\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
+ {
+ FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
+ " table are different\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* rough sanity check, ignoring offsets */
+ if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
+ table_len / 2 )
+ {
+ FT_TRACE1(( "ft_var_load_gvar:"
+ " invalid number of global coordinates\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ /* rough sanity check: offsets can be either 2 or 4 bytes, */
+ /* and a single variation needs at least 4 bytes per glyph */
+ if ( (FT_ULong)gvar_head.glyphCount *
+ ( ( gvar_head.flags & 1 ) ? 8 : 6 ) > table_len )
+ {
+ FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ FT_TRACE2(( "loaded\n" ));
+
+ blend->gvar_size = table_len;
blend->tuplecount = gvar_head.globalCoordCount;
blend->gv_glyphcnt = gvar_head.glyphCount;
offsetToData = gvar_start + gvar_head.offsetToData;
- if ( gvar_head.version != (FT_Long)0x00010000L ||
- gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
- {
- error = FT_THROW( Invalid_Table );
- goto Exit;
- }
+ FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
+ blend->tuplecount ));
if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
goto Exit;
@@ -427,8 +520,8 @@
if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
goto Exit;
- for ( i = 0; i <= blend->gv_glyphcnt; ++i )
- blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();
+ for ( i = 0; i <= blend->gv_glyphcnt; i++ )
+ blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
FT_FRAME_EXIT();
}
@@ -438,9 +531,9 @@
if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
goto Exit;
- for ( i = 0; i <= blend->gv_glyphcnt; ++i )
+ for ( i = 0; i <= blend->gv_glyphcnt; i++ )
blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
- /* XXX: Undocumented: `*2'! */
+ /* XXX: Undocumented: `*2'! */
FT_FRAME_EXIT();
}
@@ -451,14 +544,24 @@
gvar_head.axisCount * blend->tuplecount ) )
goto Exit;
- if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
- FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
+ if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
+ FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
goto Exit;
- for ( i = 0; i < blend->tuplecount; ++i )
- for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j )
+ for ( i = 0; i < blend->tuplecount; i++ )
+ {
+ FT_TRACE5(( " [ " ));
+ for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
+ {
blend->tuplecoords[i * gvar_head.axisCount + j] =
- FT_GET_SHORT() << 2; /* convert to FT_Fixed */
+ FT_GET_SHORT() * 4; /* convert to FT_Fixed */
+ FT_TRACE5(( "%.4f ",
+ blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
+ }
+ FT_TRACE5(( "]\n" ));
+ }
+
+ FT_TRACE5(( "\n" ));
FT_FRAME_EXIT();
}
@@ -506,48 +609,83 @@
FT_Fixed apply = 0x10000L;
- for ( i = 0; i < blend->num_axis; ++i )
+ for ( i = 0; i < blend->num_axis; i++ )
{
- if ( tuple_coords[i] == 0 )
- /* It's not clear why (for intermediate tuples) we don't need */
- /* to check against start/end -- the documentation says we don't. */
- /* Similarly, it's unclear why we don't need to scale along the */
- /* axis. */
- continue;
+ FT_TRACE6(( " axis coordinate %d (%.4f):\n",
+ i, blend->normalizedcoords[i] / 65536.0 ));
- else if ( blend->normalizedcoords[i] == 0 ||
- ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
+ /* It's not clear why (for intermediate tuples) we don't need */
+ /* to check against start/end -- the documentation says we don't. */
+ /* Similarly, it's unclear why we don't need to scale along the */
+ /* axis. */
+
+ if ( tuple_coords[i] == 0 )
+ {
+ FT_TRACE6(( " tuple coordinate is zero, ignored\n", i ));
+ continue;
+ }
+
+ else if ( blend->normalizedcoords[i] == 0 )
+ {
+ FT_TRACE6(( " axis coordinate is zero, stop\n" ));
+ apply = 0;
+ break;
+ }
+
+ else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
{
+ FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n",
+ tuple_coords[i] / 65536.0 ));
apply = 0;
break;
}
else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+ {
+ FT_TRACE6(( " tuple coordinate value %.4f fits\n",
+ tuple_coords[i] / 65536.0 ));
/* not an intermediate tuple */
apply = FT_MulFix( apply,
blend->normalizedcoords[i] > 0
? blend->normalizedcoords[i]
: -blend->normalizedcoords[i] );
+ }
- else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
- blend->normalizedcoords[i] >= im_end_coords[i] )
+ else if ( blend->normalizedcoords[i] < im_start_coords[i] ||
+ blend->normalizedcoords[i] > im_end_coords[i] )
{
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded,"
+ " stop\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = 0;
break;
}
else if ( blend->normalizedcoords[i] < tuple_coords[i] )
+ {
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
blend->normalizedcoords[i] - im_start_coords[i],
tuple_coords[i] - im_start_coords[i] );
+ }
else
+ {
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
im_end_coords[i] - blend->normalizedcoords[i],
im_end_coords[i] - tuple_coords[i] );
+ }
}
+ FT_TRACE6(( " apply factor is %.4f\n", apply / 65536.0 ));
+
return apply;
}
@@ -577,9 +715,9 @@
typedef struct fvar_axis_
{
FT_ULong axisTag;
- FT_ULong minValue;
- FT_ULong defaultValue;
- FT_ULong maxValue;
+ FT_Fixed minValue;
+ FT_Fixed defaultValue;
+ FT_Fixed maxValue;
FT_UShort flags;
FT_UShort nameID;
@@ -600,7 +738,8 @@
/* TT_Get_MM_Var initializes the blend structure. */
/* */
/* <Output> */
- /* master :: The `fvar' data (must be freed by caller). */
+ /* master :: The `fvar' data (must be freed by caller). Can be NULL, */
+ /* which makes this function simply load MM support. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -647,25 +786,37 @@
FT_FRAME_START( 20 ),
FT_FRAME_ULONG ( axisTag ),
- FT_FRAME_ULONG ( minValue ),
- FT_FRAME_ULONG ( defaultValue ),
- FT_FRAME_ULONG ( maxValue ),
+ FT_FRAME_LONG ( minValue ),
+ FT_FRAME_LONG ( defaultValue ),
+ FT_FRAME_LONG ( maxValue ),
FT_FRAME_USHORT( flags ),
FT_FRAME_USHORT( nameID ),
FT_FRAME_END
};
+ /* read the font data and set up the internal representation */
+ /* if not already done */
+
if ( face->blend == NULL )
{
- /* both `fvar' and `gvar' must be present */
- if ( (error = face->goto_table( face, TTAG_gvar,
- stream, &table_len )) != 0 )
- goto Exit;
+ FT_TRACE2(( "FVAR " ));
- if ( (error = face->goto_table( face, TTAG_fvar,
- stream, &table_len )) != 0 )
+ /* both `fvar' and `gvar' must be present */
+ if ( ( error = face->goto_table( face, TTAG_gvar,
+ stream, &table_len ) ) != 0 )
+ {
+ FT_TRACE1(( "\n"
+ "TT_Get_MM_Var: `gvar' table is missing\n" ));
goto Exit;
+ }
+
+ if ( ( error = face->goto_table( face, TTAG_fvar,
+ stream, &table_len ) ) != 0 )
+ {
+ FT_TRACE1(( "is missing\n" ));
+ goto Exit;
+ }
fvar_start = FT_STREAM_POS( );
@@ -673,7 +824,12 @@
goto Exit;
if ( fvar_head.version != (FT_Long)0x00010000L ||
+#if 0
+ /* fonts like `JamRegular.ttf' have an incorrect value for */
+ /* `countSizePairs'; since value 2 is hard-coded in `fvar' */
+ /* version 1.0, we simply ignore it */
fvar_head.countSizePairs != 2 ||
+#endif
fvar_head.axisSize != 20 ||
/* axisCount limit implied by 16-bit instanceSize */
fvar_head.axisCount > 0x3FFE ||
@@ -683,10 +839,16 @@
fvar_head.offsetToData + fvar_head.axisCount * 20U +
fvar_head.instanceCount * fvar_head.instanceSize > table_len )
{
+ FT_TRACE1(( "\n"
+ "TT_Get_MM_Var: invalid `fvar' header\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
+ FT_TRACE2(( "loaded\n" ));
+
+ FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
+
if ( FT_NEW( face->blend ) )
goto Exit;
@@ -702,6 +864,9 @@
goto Exit;
face->blend->mmvar = mmvar;
+ /* set up pointers and offsets into the `mmvar' array; */
+ /* the data gets filled in later on */
+
mmvar->num_axis =
fvar_head.axisCount;
mmvar->num_designs =
@@ -711,30 +876,32 @@
mmvar->num_namedstyles =
fvar_head.instanceCount;
mmvar->axis =
- (FT_Var_Axis*)&(mmvar[1]);
+ (FT_Var_Axis*)&( mmvar[1] );
mmvar->namedstyle =
- (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);
+ (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
next_coords =
- (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);
- for ( i = 0; i < fvar_head.instanceCount; ++i )
+ (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] );
+ for ( i = 0; i < fvar_head.instanceCount; i++ )
{
mmvar->namedstyle[i].coords = next_coords;
next_coords += fvar_head.axisCount;
}
next_name = (FT_String*)next_coords;
- for ( i = 0; i < fvar_head.axisCount; ++i )
+ for ( i = 0; i < fvar_head.axisCount; i++ )
{
mmvar->axis[i].name = next_name;
next_name += 5;
}
+ /* now fill in the data */
+
if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
goto Exit;
a = mmvar->axis;
- for ( i = 0; i < fvar_head.axisCount; ++i )
+ for ( i = 0; i < fvar_head.axisCount; i++ )
{
GX_FVar_Axis axis_rec;
@@ -742,22 +909,30 @@
if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
goto Exit;
a->tag = axis_rec.axisTag;
- a->minimum = axis_rec.minValue; /* A Fixed */
- a->def = axis_rec.defaultValue; /* A Fixed */
- a->maximum = axis_rec.maxValue; /* A Fixed */
+ a->minimum = axis_rec.minValue;
+ a->def = axis_rec.defaultValue;
+ a->maximum = axis_rec.maxValue;
a->strid = axis_rec.nameID;
a->name[0] = (FT_String)( a->tag >> 24 );
a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF );
a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
- a->name[4] = 0;
+ a->name[4] = '\0';
- ++a;
+ FT_TRACE5(( " \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n",
+ a->name,
+ a->minimum / 65536.0,
+ a->def / 65536.0,
+ a->maximum / 65536.0 ));
+
+ a++;
}
+ FT_TRACE5(( "\n" ));
+
ns = mmvar->namedstyle;
- for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns )
+ for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
{
if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
goto Exit;
@@ -765,13 +940,15 @@
ns->strid = FT_GET_USHORT();
(void) /* flags = */ FT_GET_USHORT();
- for ( j = 0; j < fvar_head.axisCount; ++j )
- ns->coords[j] = FT_GET_ULONG(); /* A Fixed */
+ for ( j = 0; j < fvar_head.axisCount; j++ )
+ ns->coords[j] = FT_GET_LONG();
FT_FRAME_EXIT();
}
}
+ /* fill the output array if requested */
+
if ( master != NULL )
{
FT_UInt n;
@@ -782,36 +959,36 @@
FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
mmvar->axis =
- (FT_Var_Axis*)&(mmvar[1]);
+ (FT_Var_Axis*)&( mmvar[1] );
mmvar->namedstyle =
- (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);
+ (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
next_coords =
- (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);
+ (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
- for ( n = 0; n < mmvar->num_namedstyles; ++n )
+ for ( n = 0; n < mmvar->num_namedstyles; n++ )
{
mmvar->namedstyle[n].coords = next_coords;
next_coords += mmvar->num_axis;
}
- a = mmvar->axis;
+ a = mmvar->axis;
next_name = (FT_String*)next_coords;
- for ( n = 0; n < mmvar->num_axis; ++n )
+ for ( n = 0; n < mmvar->num_axis; n++ )
{
a->name = next_name;
/* standard PostScript names for some standard apple tags */
if ( a->tag == TTAG_wght )
- a->name = (char *)"Weight";
+ a->name = (char*)"Weight";
else if ( a->tag == TTAG_wdth )
- a->name = (char *)"Width";
+ a->name = (char*)"Width";
else if ( a->tag == TTAG_opsz )
- a->name = (char *)"OpticalSize";
+ a->name = (char*)"OpticalSize";
else if ( a->tag == TTAG_slnt )
- a->name = (char *)"Slant";
+ a->name = (char*)"Slant";
next_name += 5;
- ++a;
+ a++;
}
*master = mmvar;
@@ -837,9 +1014,12 @@
/* Initialize the blend structure with `gvar' data. */
/* */
/* <Input> */
- /* num_coords :: Must be the axis count of the font. */
+ /* num_coords :: The number of available coordinates. If it is */
+ /* larger than the number of axes, ignore the excess */
+ /* values. If it is smaller than the number of axes, */
+ /* use the default value (0) for the remaining axes. */
/* */
- /* coords :: An array of num_coords, each between [-1,1]. */
+ /* coords :: An array of `num_coords', each between [-1,1]. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -868,33 +1048,44 @@
if ( face->blend == NULL )
{
- if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )
+ if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
goto Exit;
}
blend = face->blend;
mmvar = blend->mmvar;
- if ( num_coords != mmvar->num_axis )
+ if ( num_coords > mmvar->num_axis )
{
- error = FT_THROW( Invalid_Argument );
- goto Exit;
+ FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n",
+ mmvar->num_axis, num_coords ));
+ num_coords = mmvar->num_axis;
}
- for ( i = 0; i < num_coords; ++i )
+ FT_TRACE5(( "normalized design coordinates:\n" ));
+
+ for ( i = 0; i < num_coords; i++ )
+ {
+ FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
{
+ FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n"
+ " is out of range [-1;1]\n",
+ coords[i] / 65536.0 ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
+ }
+
+ FT_TRACE5(( "\n" ));
if ( blend->glyphoffsets == NULL )
- if ( (error = ft_var_load_gvar( face )) != 0 )
+ if ( ( error = ft_var_load_gvar( face ) ) != 0 )
goto Exit;
if ( blend->normalizedcoords == NULL )
{
- if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )
+ if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) )
goto Exit;
manageCvt = mcvt_modify;
@@ -906,7 +1097,8 @@
else
{
manageCvt = mcvt_retain;
- for ( i = 0; i < num_coords; ++i )
+
+ for ( i = 0; i < num_coords; i++ )
{
if ( blend->normalizedcoords[i] != coords[i] )
{
@@ -915,13 +1107,22 @@
}
}
+ for ( ; i < mmvar->num_axis; i++ )
+ {
+ if ( blend->normalizedcoords[i] != 0 )
+ {
+ manageCvt = mcvt_load;
+ break;
+ }
+ }
+
/* If we don't change the blend coords then we don't need to do */
/* anything to the cvt table. It will be correct. Otherwise we */
/* no longer have the original cvt (it was modified when we set */
/* the blend last time), so we must reload and then modify it. */
}
- blend->num_axis = num_coords;
+ blend->num_axis = mmvar->num_axis;
FT_MEM_COPY( blend->normalizedcoords,
coords,
num_coords * sizeof ( FT_Fixed ) );
@@ -938,13 +1139,13 @@
FT_FREE( face->cvt );
face->cvt = NULL;
- tt_face_load_cvt( face, face->root.stream );
+ error = tt_face_load_cvt( face, face->root.stream );
break;
case mcvt_modify:
/* The original cvt table is in memory. All we need to do is */
/* apply the `cvar' table (if any). */
- tt_face_vary_cvt( face, face->root.stream );
+ error = tt_face_vary_cvt( face, face->root.stream );
break;
case mcvt_retain:
@@ -973,7 +1174,10 @@
/* Initialize the blend struct with `gvar' data. */
/* */
/* <Input> */
- /* num_coords :: This must be the axis count of the font. */
+ /* num_coords :: The number of available coordinates. If it is */
+ /* larger than the number of axes, ignore the excess */
+ /* values. If it is smaller than the number of axes, */
+ /* use the default values for the remaining axes. */
/* */
/* coords :: A coordinate array with `num_coords' elements. */
/* */
@@ -997,17 +1201,19 @@
if ( face->blend == NULL )
{
- if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )
+ if ( ( error = TT_Get_MM_Var( face, NULL ) ) != 0 )
goto Exit;
}
blend = face->blend;
mmvar = blend->mmvar;
- if ( num_coords != mmvar->num_axis )
+ if ( num_coords > mmvar->num_axis )
{
- error = FT_THROW( Invalid_Argument );
- goto Exit;
+ FT_TRACE2(( "TT_Set_Var_Design:"
+ " only using first %d of %d coordinates\n",
+ mmvar->num_axis, num_coords ));
+ num_coords = mmvar->num_axis;
}
/* Axis normalization is a two stage process. First we normalize */
@@ -1017,32 +1223,52 @@
if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
goto Exit;
+ FT_TRACE5(( "design coordinates:\n" ));
+
a = mmvar->axis;
- for ( i = 0; i < mmvar->num_axis; ++i, ++a )
+ for ( i = 0; i < num_coords; i++, a++ )
{
+ FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
if ( coords[i] > a->maximum || coords[i] < a->minimum )
{
+ FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n"
+ " is out of range [%.4f;%.4f]\n",
+ coords[i] / 65536.0,
+ a->minimum / 65536.0,
+ a->maximum / 65536.0 ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
if ( coords[i] < a->def )
- normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def );
+ normalized[i] = -FT_DivFix( coords[i] - a->def,
+ a->minimum - a->def );
else if ( a->maximum == a->def )
normalized[i] = 0;
else
- normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def );
+ normalized[i] = FT_DivFix( coords[i] - a->def,
+ a->maximum - a->def );
}
+ FT_TRACE5(( "\n" ));
+
+ for ( ; i < mmvar->num_axis; i++ )
+ normalized[i] = 0;
+
if ( !blend->avar_checked )
ft_var_load_avar( face );
if ( blend->avar_segment != NULL )
{
+ FT_TRACE5(( "normalized design coordinates"
+ " before applying `avar' data:\n" ));
+
av = blend->avar_segment;
- for ( i = 0; i < mmvar->num_axis; ++i, ++av )
+ for ( i = 0; i < mmvar->num_axis; i++, av++ )
{
- for ( j = 1; j < (FT_UInt)av->pairCount; ++j )
+ for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
+ {
+ FT_TRACE5(( " %.4f\n", normalized[i] / 65536.0 ));
if ( normalized[i] < av->correspondence[j].fromCoord )
{
normalized[i] =
@@ -1054,10 +1280,11 @@
av->correspondence[j - 1].toCoord;
break;
}
+ }
}
}
- error = TT_Set_MM_Blend( face, num_coords, normalized );
+ error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized );
Exit:
FT_FREE( normalized );
@@ -1120,16 +1347,16 @@
if ( blend == NULL )
{
- FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-
+ FT_TRACE2(( "\n"
+ "tt_face_vary_cvt: no blend specified\n" ));
error = FT_Err_Ok;
goto Exit;
}
if ( face->cvt == NULL )
{
- FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-
+ FT_TRACE2(( "\n"
+ "tt_face_vary_cvt: no `cvt ' table\n" ));
error = FT_Err_Ok;
goto Exit;
}
@@ -1158,25 +1385,43 @@
goto FExit;
}
+ FT_TRACE2(( "loaded\n" ));
+
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
goto FExit;
tupleCount = FT_GET_USHORT();
- offsetToData = table_start + FT_GET_USHORT();
+ offsetToData = FT_GET_USHORT();
- /* The documentation implies there are flags packed into the */
- /* tuplecount, but John Jenkins says that shared points don't apply */
- /* to `cvar', and no other flags are defined. */
+ /* rough sanity test */
+ if ( offsetToData + tupleCount * 4 > table_len )
+ {
+ FT_TRACE2(( "tt_face_vary_cvt:"
+ " invalid CVT variation array header\n" ));
- for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
+ error = FT_THROW( Invalid_Table );
+ goto FExit;
+ }
+
+ offsetToData += table_start;
+
+ /* The documentation implies there are flags packed into */
+ /* `tupleCount', but John Jenkins says that shared points don't apply */
+ /* to `cvar', and no other flags are defined. */
+
+ FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
+
+ for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
{
FT_UInt tupleDataSize;
FT_UInt tupleIndex;
FT_Fixed apply;
+ FT_TRACE6(( " tuple %d:\n", i ));
+
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
@@ -1185,8 +1430,8 @@
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
- for ( j = 0; j < blend->num_axis; ++j )
- tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ for ( j = 0; j < blend->num_axis; j++ )
+ tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
/* short frac to fixed */
}
else
@@ -1194,7 +1439,7 @@
/* skip this tuple; it makes no sense */
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
- for ( j = 0; j < 2 * blend->num_axis; ++j )
+ for ( j = 0; j < 2 * blend->num_axis; j++ )
(void)FT_GET_SHORT();
offsetToData += tupleDataSize;
@@ -1203,10 +1448,10 @@
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
- for ( j = 0; j < blend->num_axis; ++j )
- im_start_coords[j] = FT_GET_SHORT() << 2;
- for ( j = 0; j < blend->num_axis; ++j )
- im_end_coords[j] = FT_GET_SHORT() << 2;
+ for ( j = 0; j < blend->num_axis; j++ )
+ im_start_coords[j] = FT_GET_SHORT() * 4;
+ for ( j = 0; j < blend->num_axis; j++ )
+ im_end_coords[j] = FT_GET_SHORT() * 4;
}
apply = ft_var_apply_tuple( blend,
@@ -1228,30 +1473,82 @@
FT_Stream_SeekSet( stream, offsetToData );
- localpoints = ft_var_readpackedpoints( stream, &point_count );
+ localpoints = ft_var_readpackedpoints( stream,
+ table_len,
+ &point_count );
deltas = ft_var_readpackeddeltas( stream,
+ table_len,
point_count == 0 ? face->cvt_size
: point_count );
if ( localpoints == NULL || deltas == NULL )
- /* failure, ignore it */;
+ ; /* failure, ignore it */
else if ( localpoints == ALL_POINTS )
{
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
+
+
+ FT_TRACE7(( " CVT deltas:\n" ));
+
/* this means that there are deltas for every entry in cvt */
- for ( j = 0; j < face->cvt_size; ++j )
- face->cvt[j] = (FT_Short)( face->cvt[j] +
+ for ( j = 0; j < face->cvt_size; j++ )
+ {
+ FT_Long orig_cvt = face->cvt[j];
+
+
+ face->cvt[j] = (FT_Short)( orig_cvt +
FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( orig_cvt != face->cvt[j] )
+ {
+ FT_TRACE7(( " %d: %d -> %d\n",
+ j, orig_cvt, face->cvt[j] ));
+ count++;
+ }
+#endif
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
else
{
- for ( j = 0; j < point_count; ++j )
- {
- int pindex = localpoints[j];
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
- face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
+
+ FT_TRACE7(( " CVT deltas:\n" ));
+
+ for ( j = 0; j < point_count; j++ )
+ {
+ int pindex = localpoints[j];
+ FT_Long orig_cvt = face->cvt[pindex];
+
+
+ face->cvt[pindex] = (FT_Short)( orig_cvt +
FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( orig_cvt != face->cvt[pindex] )
+ {
+ FT_TRACE7(( " %d: %d -> %d\n",
+ pindex, orig_cvt, face->cvt[pindex] ));
+ count++;
+ }
+#endif
}
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
if ( localpoints != ALL_POINTS )
@@ -1263,6 +1560,8 @@
FT_Stream_SeekSet( stream, here );
}
+ FT_TRACE5(( "\n" ));
+
FExit:
FT_FRAME_EXIT();
@@ -1275,13 +1574,230 @@
}
+ /* Shift the original coordinates of all points between indices `p1' */
+ /* and `p2', using the same difference as given by index `ref'. */
+
+ /* modeled after `af_iup_shift' */
+
+ static void
+ tt_delta_shift( int p1,
+ int p2,
+ int ref,
+ FT_Vector* in_points,
+ FT_Vector* out_points )
+ {
+ int p;
+ FT_Vector delta;
+
+
+ delta.x = out_points[ref].x - in_points[ref].x;
+ delta.y = out_points[ref].y - in_points[ref].y;
+
+ if ( delta.x == 0 && delta.y == 0 )
+ return;
+
+ for ( p = p1; p < ref; p++ )
+ {
+ out_points[p].x += delta.x;
+ out_points[p].y += delta.y;
+ }
+
+ for ( p = ref + 1; p <= p2; p++ )
+ {
+ out_points[p].x += delta.x;
+ out_points[p].y += delta.y;
+ }
+ }
+
+
+ /* Interpolate the original coordinates of all points with indices */
+ /* between `p1' and `p2', using `ref1' and `ref2' as the reference */
+ /* point indices. */
+
+ /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
+ /* `Ins_IUP' */
+
+ static void
+ tt_delta_interpolate( int p1,
+ int p2,
+ int ref1,
+ int ref2,
+ FT_Vector* in_points,
+ FT_Vector* out_points )
+ {
+ int p, i;
+
+ FT_Pos out, in1, in2, out1, out2, d1, d2;
+
+
+ if ( p1 > p2 )
+ return;
+
+ /* handle both horizontal and vertical coordinates */
+ for ( i = 0; i <= 1; i++ )
+ {
+ /* shift array pointers so that we can access `foo.y' as `foo.x' */
+ in_points = (FT_Vector*)( (FT_Pos*)in_points + i );
+ out_points = (FT_Vector*)( (FT_Pos*)out_points + i );
+
+ if ( in_points[ref1].x > in_points[ref2].x )
+ {
+ p = ref1;
+ ref1 = ref2;
+ ref2 = p;
+ }
+
+ in1 = in_points[ref1].x;
+ in2 = in_points[ref2].x;
+ out1 = out_points[ref1].x;
+ out2 = out_points[ref2].x;
+ d1 = out1 - in1;
+ d2 = out2 - in2;
+
+ if ( out1 == out2 || in1 == in2 )
+ {
+ for ( p = p1; p <= p2; p++ )
+ {
+ out = in_points[p].x;
+
+ if ( out <= in1 )
+ out += d1;
+ else if ( out >= in2 )
+ out += d2;
+ else
+ out = out1;
+
+ out_points[p].x = out;
+ }
+ }
+ else
+ {
+ FT_Fixed scale = FT_DivFix( out2 - out1, in2 - in1 );
+
+
+ for ( p = p1; p <= p2; p++ )
+ {
+ out = in_points[p].x;
+
+ if ( out <= in1 )
+ out += d1;
+ else if ( out >= in2 )
+ out += d2;
+ else
+ out = out1 + FT_MulFix( out - in1, scale );
+
+ out_points[p].x = out;
+ }
+ }
+ }
+ }
+
+
+ /* Interpolate points without delta values, similar to */
+ /* the `IUP' hinting instruction. */
+
+ /* modeled after `Ins_IUP */
+
+ static void
+ tt_handle_deltas( FT_Outline* outline,
+ FT_Vector* in_points,
+ FT_Bool* has_delta )
+ {
+ FT_Vector* out_points;
+
+ FT_Int first_point;
+ FT_Int end_point;
+
+ FT_Int first_delta;
+ FT_Int cur_delta;
+
+ FT_Int point;
+ FT_Short contour;
+
+
+ /* ignore empty outlines */
+ if ( !outline->n_contours )
+ return;
+
+ out_points = outline->points;
+
+ contour = 0;
+ point = 0;
+
+ do
+ {
+ end_point = outline->contours[contour];
+ first_point = point;
+
+ /* search first point that has a delta */
+ while ( point <= end_point && !has_delta[point] )
+ point++;
+
+ if ( point <= end_point )
+ {
+ first_delta = point;
+ cur_delta = point;
+
+ point++;
+
+ while ( point <= end_point )
+ {
+ /* search next point that has a delta */
+ /* and interpolate intermediate points */
+ if ( has_delta[point] )
+ {
+ tt_delta_interpolate( cur_delta + 1,
+ point - 1,
+ cur_delta,
+ point,
+ in_points,
+ out_points );
+ cur_delta = point;
+ }
+
+ point++;
+ }
+
+ /* shift contour if we only have a single delta */
+ if ( cur_delta == first_delta )
+ tt_delta_shift( first_point,
+ end_point,
+ cur_delta,
+ in_points,
+ out_points );
+ else
+ {
+ /* otherwise handle remaining points */
+ /* at the end and beginning of the contour */
+ tt_delta_interpolate( cur_delta + 1,
+ end_point,
+ cur_delta,
+ first_delta,
+ in_points,
+ out_points );
+
+ if ( first_delta > 0 )
+ tt_delta_interpolate( first_point,
+ first_delta - 1,
+ cur_delta,
+ first_delta,
+ in_points,
+ out_points );
+ }
+ }
+ contour++;
+
+ } while ( contour < outline->n_contours );
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
- /* TT_Vary_Get_Glyph_Deltas */
+ /* TT_Vary_Apply_Glyph_Deltas */
/* */
/* <Description> */
- /* Load the appropriate deltas for the current glyph. */
+ /* Apply the appropriate deltas to the current glyph. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
@@ -1291,22 +1807,24 @@
/* n_points :: The number of the points in the glyph, including */
/* phantom points. */
/* */
- /* <Output> */
- /* deltas :: The array of points to change. */
+ /* <InOut> */
+ /* outline :: The outline to change. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- TT_Vary_Get_Glyph_Deltas( TT_Face face,
- FT_UInt glyph_index,
- FT_Vector* *deltas,
- FT_UInt n_points )
+ TT_Vary_Apply_Glyph_Deltas( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Outline* outline,
+ FT_UInt n_points )
{
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
- FT_Vector* delta_xy = NULL;
+
+ FT_Vector* points_org = NULL;
+ FT_Bool* has_delta = NULL;
FT_Error error;
FT_ULong glyph_start;
@@ -1327,15 +1845,18 @@
if ( !face->doblend || blend == NULL )
return FT_THROW( Invalid_Argument );
- /* to be freed by the caller */
- if ( FT_NEW_ARRAY( delta_xy, n_points ) )
- goto Exit;
- *deltas = delta_xy;
-
if ( glyph_index >= blend->gv_glyphcnt ||
blend->glyphoffsets[glyph_index] ==
blend->glyphoffsets[glyph_index + 1] )
- return FT_Err_Ok; /* no variation data for this glyph */
+ {
+ FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+ " no variation data for this glyph\n" ));
+ return FT_Err_Ok;
+ }
+
+ if ( FT_NEW_ARRAY( points_org, n_points ) ||
+ FT_NEW_ARRAY( has_delta, n_points ) )
+ goto Fail1;
if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
@@ -1353,7 +1874,19 @@
goto Fail2;
tupleCount = FT_GET_USHORT();
- offsetToData = glyph_start + FT_GET_USHORT();
+ offsetToData = FT_GET_USHORT();
+
+ /* rough sanity test */
+ if ( offsetToData + tupleCount * 4 > blend->gvar_size )
+ {
+ FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+ " invalid glyph variation array header\n" ));
+
+ error = FT_THROW( Invalid_Table );
+ goto Fail2;
+ }
+
+ offsetToData += glyph_start;
if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
{
@@ -1361,47 +1894,55 @@
FT_Stream_SeekSet( stream, offsetToData );
- sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+ sharedpoints = ft_var_readpackedpoints( stream,
+ blend->gvar_size,
+ &spoint_count );
offsetToData = FT_Stream_FTell( stream );
FT_Stream_SeekSet( stream, here );
}
- for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
+ FT_TRACE5(( "gvar: there are %d tuples:\n",
+ tupleCount & GX_TC_TUPLE_COUNT_MASK ));
+
+ for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
{
FT_UInt tupleDataSize;
FT_UInt tupleIndex;
FT_Fixed apply;
+ FT_TRACE6(( " tuple %d:\n", i ));
+
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
- for ( j = 0; j < blend->num_axis; ++j )
- tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
+ for ( j = 0; j < blend->num_axis; j++ )
+ tuple_coords[j] = FT_GET_SHORT() * 4; /* convert from */
/* short frac to fixed */
}
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
{
+ FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+ " invalid tuple index\n" ));
+
error = FT_THROW( Invalid_Table );
- goto Fail3;
+ goto Fail2;
}
else
- {
FT_MEM_COPY(
tuple_coords,
- &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
+ &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
blend->num_axis * sizeof ( FT_Fixed ) );
- }
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
- for ( j = 0; j < blend->num_axis; ++j )
- im_start_coords[j] = FT_GET_SHORT() << 2;
- for ( j = 0; j < blend->num_axis; ++j )
- im_end_coords[j] = FT_GET_SHORT() << 2;
+ for ( j = 0; j < blend->num_axis; j++ )
+ im_start_coords[j] = FT_GET_SHORT() * 4;
+ for ( j = 0; j < blend->num_axis; j++ )
+ im_end_coords[j] = FT_GET_SHORT() * 4;
}
apply = ft_var_apply_tuple( blend,
@@ -1422,7 +1963,9 @@
{
FT_Stream_SeekSet( stream, offsetToData );
- localpoints = ft_var_readpackedpoints( stream, &point_count );
+ localpoints = ft_var_readpackedpoints( stream,
+ blend->gvar_size,
+ &point_count );
points = localpoints;
}
else
@@ -1432,9 +1975,11 @@
}
deltas_x = ft_var_readpackeddeltas( stream,
+ blend->gvar_size,
point_count == 0 ? n_points
: point_count );
deltas_y = ft_var_readpackeddeltas( stream,
+ blend->gvar_size,
point_count == 0 ? n_points
: point_count );
@@ -1443,24 +1988,104 @@
else if ( points == ALL_POINTS )
{
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
+
+
+ FT_TRACE7(( " point deltas:\n" ));
+
/* this means that there are deltas for every point in the glyph */
- for ( j = 0; j < n_points; ++j )
+ for ( j = 0; j < n_points; j++ )
{
- delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
- delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_Vector point_org = outline->points[j];
+#endif
+
+
+ outline->points[j].x += FT_MulFix( deltas_x[j], apply );
+ outline->points[j].y += FT_MulFix( deltas_y[j], apply );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( ( point_org.x != outline->points[j].x ) ||
+ ( point_org.y != outline->points[j].y ) )
+ {
+ FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
+ j,
+ point_org.x,
+ point_org.y,
+ outline->points[j].x,
+ outline->points[j].y ));
+ count++;
+ }
+#endif
}
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
+ else if ( localpoints == NULL )
+ ; /* failure, ignore it */
+
else
{
- for ( j = 0; j < point_count; ++j )
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
+
+
+ /* we have to interpolate the missing deltas similar to the */
+ /* IUP bytecode instruction */
+ for ( j = 0; j < n_points; j++ )
{
- if ( localpoints[j] >= n_points )
+ points_org[j] = outline->points[j];
+ has_delta[j] = FALSE;
+ }
+
+ for ( j = 0; j < point_count; j++ )
+ {
+ FT_UShort idx = localpoints[j];
+
+
+ if ( idx >= n_points )
continue;
- delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
- delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
+ has_delta[idx] = TRUE;
+
+ outline->points[idx].x += FT_MulFix( deltas_x[j], apply );
+ outline->points[idx].y += FT_MulFix( deltas_y[j], apply );
}
+
+ /* no need to handle phantom points here, */
+ /* since solitary points can't be interpolated */
+ tt_handle_deltas( outline,
+ points_org,
+ has_delta );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_TRACE7(( " point deltas:\n" ));
+
+ for ( j = 0; j < n_points; j++)
+ {
+ if ( ( points_org[j].x != outline->points[j].x ) ||
+ ( points_org[j].y != outline->points[j].y ) )
+ {
+ FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n",
+ j,
+ points_org[j].x,
+ points_org[j].y,
+ outline->points[j].x,
+ outline->points[j].y ));
+ count++;
+ }
+ }
+
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
if ( localpoints != ALL_POINTS )
@@ -1473,22 +2098,21 @@
FT_Stream_SeekSet( stream, here );
}
- Fail3:
+ FT_TRACE5(( "\n" ));
+
+ Fail2:
+ if ( sharedpoints != ALL_POINTS )
+ FT_FREE( sharedpoints );
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
- Fail2:
FT_FRAME_EXIT();
Fail1:
- if ( error )
- {
- FT_FREE( delta_xy );
- *deltas = NULL;
- }
+ FT_FREE( points_org );
+ FT_FREE( has_delta );
- Exit:
return error;
}
@@ -1499,7 +2123,7 @@
/* tt_done_blend */
/* */
/* <Description> */
- /* Frees the blend internal data structure. */
+ /* Free the blend internal data structure. */
/* */
FT_LOCAL_DEF( void )
tt_done_blend( FT_Memory memory,
@@ -1515,7 +2139,7 @@
if ( blend->avar_segment != NULL )
{
- for ( i = 0; i < blend->num_axis; ++i )
+ for ( i = 0; i < blend->num_axis; i++ )
FT_FREE( blend->avar_segment[i].correspondence );
FT_FREE( blend->avar_segment );
}
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 82dfc44..dd1411f 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
/* */
/* TrueType GX Font Variation loader (specification) */
/* */
-/* Copyright 2004 by */
+/* Copyright 2004-2015 by */
/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -95,6 +95,8 @@
FT_UInt gv_glyphcnt;
FT_ULong* glyphoffsets;
+ FT_ULong gvar_size;
+
} GX_BlendRec;
@@ -162,10 +164,10 @@
FT_LOCAL( FT_Error )
- TT_Vary_Get_Glyph_Deltas( TT_Face face,
- FT_UInt glyph_index,
- FT_Vector* *deltas,
- FT_UInt n_points );
+ TT_Vary_Apply_Glyph_Deltas( TT_Face face,
+ FT_UInt glyph_index,
+ FT_Outline* outline,
+ FT_UInt n_points );
FT_LOCAL( void )
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 798d4a9..1c1d7de 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,8 +4,8 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2013 */
-/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* Copyright 1996-2015 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 */
@@ -44,186 +44,31 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttinterp
- /*************************************************************************/
- /* */
- /* In order to detect infinite loops in the code, we set up a counter */
- /* within the run loop. A single stroke of interpretation is now */
- /* limited to a maximum number of opcodes defined below. */
- /* */
-#define MAX_RUNNABLE_OPCODES 1000000L
-
- /*************************************************************************/
- /* */
- /* There are two kinds of implementations: */
- /* */
- /* 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 fully re-entrant. */
- /* */
- /* The idea is that an indirect implementation may be slower to execute */
- /* on low-end processors that are used in some systems (like 386s or */
- /* even 486s). */
- /* */
- /* 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 code used for */
- /* development. */
- /* */
- /* - It's much more readable that way! */
- /* */
- /* - It's still open to experimentation and tuning. */
- /* */
- /*************************************************************************/
-
-
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
-
-#define CUR (*exc) /* see ttobjs.h */
-
- /*************************************************************************/
- /* */
- /* This macro is used whenever `exec' is unused in a function, to avoid */
- /* stupid warnings from pedantic compilers. */
- /* */
-#define FT_UNUSED_EXEC FT_UNUSED( exc )
-
-#else /* static implementation */
-
-#define CUR cur
-
-#define FT_UNUSED_EXEC int __dummy = __dummy
-
- static
- TT_ExecContextRec 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 */
-
-
- /*************************************************************************/
- /* */
- /* The instruction argument stack. */
- /* */
-#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */
-
-
- /*************************************************************************/
- /* */
- /* This macro is used whenever `args' is unused in a function, to avoid */
- /* stupid warnings from pedantic compilers. */
- /* */
-#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args )
-
-
-#define SUBPIXEL_HINTING \
- ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
+#define SUBPIXEL_HINTING \
+ ( ((TT_Driver)FT_FACE_DRIVER( exc->face ))->interpreter_version == \
TT_INTERPRETER_VERSION_38 )
- /*************************************************************************/
- /* */
- /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */
- /* increase readability of the code. */
- /* */
- /*************************************************************************/
+#define PROJECT( v1, v2 ) \
+ exc->func_project( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
+#define DUALPROJ( v1, v2 ) \
+ exc->func_dualproj( exc, (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-#define SKIP_Code() \
- SkipCode( EXEC_ARG )
+#define FAST_PROJECT( v ) \
+ exc->func_project( exc, (v)->x, (v)->y )
-#define GET_ShortIns() \
- GetShortIns( EXEC_ARG )
-
-#define NORMalize( x, y, v ) \
- Normalize( EXEC_ARG_ x, y, v )
-
-#define SET_SuperRound( scale, flags ) \
- SetSuperRound( EXEC_ARG_ scale, flags )
-
-#define ROUND_None( d, c ) \
- Round_None( EXEC_ARG_ d, c )
-
-#define INS_Goto_CodeRange( range, ip ) \
- Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
-
-#define CUR_Func_move( z, p, d ) \
- CUR.func_move( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_move_orig( z, p, d ) \
- CUR.func_move_orig( EXEC_ARG_ z, p, d )
-
-#define CUR_Func_round( d, c ) \
- CUR.func_round( EXEC_ARG_ d, c )
-
-#define CUR_Func_read_cvt( index ) \
- CUR.func_read_cvt( EXEC_ARG_ index )
-
-#define CUR_Func_write_cvt( index, val ) \
- CUR.func_write_cvt( EXEC_ARG_ index, val )
-
-#define CUR_Func_move_cvt( index, val ) \
- CUR.func_move_cvt( EXEC_ARG_ index, val )
-
-#define CURRENT_Ratio() \
- Current_Ratio( EXEC_ARG )
-
-#define CURRENT_Ppem() \
- Current_Ppem( EXEC_ARG )
-
-#define CUR_Ppem() \
- Cur_PPEM( EXEC_ARG )
-
-#define INS_SxVTL( a, b, c, d ) \
- Ins_SxVTL( EXEC_ARG_ a, b, c, d )
-
-#define COMPUTE_Funcs() \
- Compute_Funcs( EXEC_ARG )
-
-#define COMPUTE_Round( a ) \
- Compute_Round( EXEC_ARG_ a )
-
-#define COMPUTE_Point_Displacement( a, b, c, d ) \
- Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
-
-#define MOVE_Zp2_Point( a, b, c, t ) \
- Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
-
-
-#define CUR_Func_project( v1, v2 ) \
- CUR.func_project( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_Func_dualproj( v1, v2 ) \
- CUR.func_dualproj( EXEC_ARG_ (v1)->x - (v2)->x, (v1)->y - (v2)->y )
-
-#define CUR_fast_project( v ) \
- CUR.func_project( EXEC_ARG_ (v)->x, (v)->y )
-
-#define CUR_fast_dualproj( v ) \
- CUR.func_dualproj( EXEC_ARG_ (v)->x, (v)->y )
+#define FAST_DUALPROJ( v ) \
+ exc->func_dualproj( exc, (v)->x, (v)->y )
/*************************************************************************/
/* */
/* Instruction dispatch function, as used by the interpreter. */
/* */
- typedef void (*TInstruction_Function)( INS_ARG );
+ typedef void (*TInstruction_Function)( TT_ExecContext exc,
+ FT_Long* args );
/*************************************************************************/
@@ -233,13 +78,6 @@
#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) )
#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) )
- /*************************************************************************/
- /* */
- /* This macro computes (a*2^14)/b and complements TT_MulFix14. */
- /* */
-#define TT_DivFix14( a, b ) \
- FT_DivFix( a, (b) << 2 )
-
#undef SUCCESS
#define SUCCESS 0
@@ -248,16 +86,20 @@
#define FAILURE 1
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define GUESS_VECTOR( V ) \
- if ( CUR.face->unpatented_hinting ) \
- { \
- CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \
- CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \
- }
+#define GUESS_VECTOR( V ) \
+ do \
+ { \
+ if ( exc->face->unpatented_hinting ) \
+ { \
+ exc->GS.V.x = (FT_F2Dot14)( exc->GS.both_x_axis ? 0x4000 : 0 ); \
+ exc->GS.V.y = (FT_F2Dot14)( exc->GS.both_x_axis ? 0 : 0x4000 ); \
+ } \
+ } while (0)
#else
-#define GUESS_VECTOR( V )
+#define GUESS_VECTOR( V ) do { } while (0)
#endif
+
/*************************************************************************/
/* */
/* CODERANGE FUNCTIONS */
@@ -282,10 +124,7 @@
/* <InOut> */
/* exec :: The target execution context. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
TT_Goto_CodeRange( TT_ExecContext exec,
FT_Int range,
FT_Long IP )
@@ -303,14 +142,12 @@
/* which will return to the first byte *after* the code */
/* range, we test for IP <= Size instead of IP < Size. */
/* */
- FT_ASSERT( (FT_ULong)IP <= coderange->size );
+ FT_ASSERT( IP <= coderange->size );
exec->code = coderange->base;
exec->codeSize = coderange->size;
exec->IP = IP;
exec->curRange = range;
-
- return FT_Err_Ok;
}
@@ -332,10 +169,7 @@
/* <InOut> */
/* exec :: The target execution context. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
TT_Set_CodeRange( TT_ExecContext exec,
FT_Int range,
void* base,
@@ -345,8 +179,6 @@
exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
exec->codeRangeTable[range - 1].size = length;
-
- return FT_Err_Ok;
}
@@ -364,13 +196,7 @@
/* <InOut> */
/* exec :: The target execution context. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Does not set the Error variable. */
- /* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
TT_Clear_CodeRange( TT_ExecContext exec,
FT_Int range )
{
@@ -378,8 +204,6 @@
exec->codeRangeTable[range - 1].base = NULL;
exec->codeRangeTable[range - 1].size = 0;
-
- return FT_Err_Ok;
}
@@ -403,13 +227,10 @@
/* */
/* memory :: A handle to the parent memory object. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
/* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
TT_Done_Context( TT_ExecContext exec )
{
FT_Memory memory = exec->memory;
@@ -436,8 +257,6 @@
exec->face = NULL;
FT_FREE( exec );
-
- return FT_Err_Ok;
}
@@ -524,7 +343,7 @@
FT_LOCAL_DEF( FT_Error )
Update_Max( FT_Memory memory,
FT_ULong* size,
- FT_Long multiplier,
+ FT_ULong multiplier,
void* _pbuff,
FT_ULong new_max )
{
@@ -617,13 +436,13 @@
/* XXX: We reserve a little more elements on the stack to deal safely */
/* with broken fonts like arialbs, courbs, timesbs, etc. */
- tmp = exec->stackSize;
+ tmp = (FT_ULong)exec->stackSize;
error = Update_Max( exec->memory,
&tmp,
sizeof ( FT_F26Dot6 ),
(void*)&exec->stack,
maxp->maxStackElements + 32 );
- exec->stackSize = (FT_UInt)tmp;
+ exec->stackSize = (FT_Long)tmp;
if ( error )
return error;
@@ -664,13 +483,10 @@
/* <InOut> */
/* size :: A handle to the target size object. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
/* */
- FT_LOCAL_DEF( FT_Error )
+ FT_LOCAL_DEF( void )
TT_Save_Context( TT_ExecContext exec,
TT_Size size )
{
@@ -688,8 +504,6 @@
for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
size->codeRangeTable[i] = exec->codeRangeTable[i];
-
- return FT_Err_Ok;
}
@@ -714,19 +528,10 @@
/* <Return> */
/* TrueType error code. 0 means success. */
/* */
- /* <Note> */
- /* Only the glyph loader and debugger should call this function. */
- /* */
FT_LOCAL_DEF( FT_Error )
- TT_Run_Context( TT_ExecContext exec,
- FT_Bool debug )
+ TT_Run_Context( TT_ExecContext exec )
{
- FT_Error error;
-
-
- if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
- != FT_Err_Ok )
- return error;
+ TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 );
exec->zp0 = exec->pts;
exec->zp1 = exec->pts;
@@ -754,16 +559,7 @@
exec->top = 0;
exec->callTop = 0;
-#if 1
- FT_UNUSED( debug );
-
return exec->face->interpreter( exec );
-#else
- if ( !debug )
- return TT_RunIns( exec );
- else
- return FT_Err_Ok;
-#endif
}
@@ -796,32 +592,27 @@
FT_EXPORT_DEF( TT_ExecContext )
TT_New_Context( TT_Driver driver )
{
- TT_ExecContext exec;
- FT_Memory memory;
+ FT_Memory memory;
+ FT_Error error;
+ TT_ExecContext exec = NULL;
+
+
+ if ( !driver )
+ goto Fail;
memory = driver->root.root.memory;
- exec = driver->context;
- if ( !driver->context )
- {
- FT_Error error;
+ /* allocate object */
+ if ( FT_NEW( exec ) )
+ goto Fail;
+ /* initialize it; in case of error this deallocates `exec' too */
+ error = Init_Context( exec, memory );
+ if ( error )
+ goto Fail;
- /* allocate object */
- if ( FT_NEW( exec ) )
- goto Fail;
-
- /* initialize it; in case of error this deallocates `exec' too */
- error = Init_Context( exec, memory );
- if ( error )
- goto Fail;
-
- /* store it into the driver */
- driver->context = exec;
- }
-
- return driver->context;
+ return exec;
Fail:
return NULL;
@@ -868,8 +659,8 @@
/* SFvTL + */ PACK( 2, 0 ),
/* SPvFS */ PACK( 2, 0 ),
/* SFvFS */ PACK( 2, 0 ),
- /* GPV */ PACK( 0, 2 ),
- /* GFV */ PACK( 0, 2 ),
+ /* GPv */ PACK( 0, 2 ),
+ /* GFv */ PACK( 0, 2 ),
/* SFvTPv */ PACK( 0, 0 ),
/* ISECT */ PACK( 5, 0 ),
@@ -998,8 +789,8 @@
/* INS_$83 */ PACK( 0, 0 ),
/* INS_$84 */ PACK( 0, 0 ),
/* ScanCTRL */ PACK( 1, 0 ),
- /* SDPVTL[0] */ PACK( 2, 0 ),
- /* SDPVTL[1] */ PACK( 2, 0 ),
+ /* SDPvTL[0] */ PACK( 2, 0 ),
+ /* SDPvTL[1] */ PACK( 2, 0 ),
/* GetINFO */ PACK( 1, 1 ),
/* IDEF */ PACK( 1, 0 ),
/* ROLL */ PACK( 3, 3 ),
@@ -1132,280 +923,284 @@
#ifdef FT_DEBUG_LEVEL_TRACE
+ /* the first hex digit gives the length of the opcode name; the space */
+ /* after the digit is here just to increase readability of the source */
+ /* code */
+
static
const char* const opcode_name[256] =
{
- "SVTCA y",
- "SVTCA x",
- "SPvTCA y",
- "SPvTCA x",
- "SFvTCA y",
- "SFvTCA x",
- "SPvTL ||",
- "SPvTL +",
- "SFvTL ||",
- "SFvTL +",
- "SPvFS",
- "SFvFS",
- "GPV",
- "GFV",
- "SFvTPv",
- "ISECT",
+ "7 SVTCA y",
+ "7 SVTCA x",
+ "8 SPvTCA y",
+ "8 SPvTCA x",
+ "8 SFvTCA y",
+ "8 SFvTCA x",
+ "8 SPvTL ||",
+ "7 SPvTL +",
+ "8 SFvTL ||",
+ "7 SFvTL +",
+ "5 SPvFS",
+ "5 SFvFS",
+ "3 GPv",
+ "3 GFv",
+ "6 SFvTPv",
+ "5 ISECT",
- "SRP0",
- "SRP1",
- "SRP2",
- "SZP0",
- "SZP1",
- "SZP2",
- "SZPS",
- "SLOOP",
- "RTG",
- "RTHG",
- "SMD",
- "ELSE",
- "JMPR",
- "SCvTCi",
- "SSwCi",
- "SSW",
+ "4 SRP0",
+ "4 SRP1",
+ "4 SRP2",
+ "4 SZP0",
+ "4 SZP1",
+ "4 SZP2",
+ "4 SZPS",
+ "5 SLOOP",
+ "3 RTG",
+ "4 RTHG",
+ "3 SMD",
+ "4 ELSE",
+ "4 JMPR",
+ "6 SCvTCi",
+ "5 SSwCi",
+ "3 SSW",
- "DUP",
- "POP",
- "CLEAR",
- "SWAP",
- "DEPTH",
- "CINDEX",
- "MINDEX",
- "AlignPTS",
- "INS_$28",
- "UTP",
- "LOOPCALL",
- "CALL",
- "FDEF",
- "ENDF",
- "MDAP[0]",
- "MDAP[1]",
+ "3 DUP",
+ "3 POP",
+ "5 CLEAR",
+ "4 SWAP",
+ "5 DEPTH",
+ "6 CINDEX",
+ "6 MINDEX",
+ "8 AlignPTS",
+ "7 INS_$28",
+ "3 UTP",
+ "8 LOOPCALL",
+ "4 CALL",
+ "4 FDEF",
+ "4 ENDF",
+ "7 MDAP[0]",
+ "7 MDAP[1]",
- "IUP[0]",
- "IUP[1]",
- "SHP[0]",
- "SHP[1]",
- "SHC[0]",
- "SHC[1]",
- "SHZ[0]",
- "SHZ[1]",
- "SHPIX",
- "IP",
- "MSIRP[0]",
- "MSIRP[1]",
- "AlignRP",
- "RTDG",
- "MIAP[0]",
- "MIAP[1]",
+ "6 IUP[0]",
+ "6 IUP[1]",
+ "6 SHP[0]",
+ "6 SHP[1]",
+ "6 SHC[0]",
+ "6 SHC[1]",
+ "6 SHZ[0]",
+ "6 SHZ[1]",
+ "5 SHPIX",
+ "2 IP",
+ "8 MSIRP[0]",
+ "8 MSIRP[1]",
+ "7 AlignRP",
+ "4 RTDG",
+ "7 MIAP[0]",
+ "7 MIAP[1]",
- "NPushB",
- "NPushW",
- "WS",
- "RS",
- "WCvtP",
- "RCvt",
- "GC[0]",
- "GC[1]",
- "SCFS",
- "MD[0]",
- "MD[1]",
- "MPPEM",
- "MPS",
- "FlipON",
- "FlipOFF",
- "DEBUG",
+ "6 NPushB",
+ "6 NPushW",
+ "2 WS",
+ "2 RS",
+ "5 WCvtP",
+ "4 RCvt",
+ "5 GC[0]",
+ "5 GC[1]",
+ "4 SCFS",
+ "5 MD[0]",
+ "5 MD[1]",
+ "5 MPPEM",
+ "3 MPS",
+ "6 FlipON",
+ "7 FlipOFF",
+ "5 DEBUG",
- "LT",
- "LTEQ",
- "GT",
- "GTEQ",
- "EQ",
- "NEQ",
- "ODD",
- "EVEN",
- "IF",
- "EIF",
- "AND",
- "OR",
- "NOT",
- "DeltaP1",
- "SDB",
- "SDS",
+ "2 LT",
+ "4 LTEQ",
+ "2 GT",
+ "4 GTEQ",
+ "2 EQ",
+ "3 NEQ",
+ "3 ODD",
+ "4 EVEN",
+ "2 IF",
+ "3 EIF",
+ "3 AND",
+ "2 OR",
+ "3 NOT",
+ "7 DeltaP1",
+ "3 SDB",
+ "3 SDS",
- "ADD",
- "SUB",
- "DIV",
- "MUL",
- "ABS",
- "NEG",
- "FLOOR",
- "CEILING",
- "ROUND[0]",
- "ROUND[1]",
- "ROUND[2]",
- "ROUND[3]",
- "NROUND[0]",
- "NROUND[1]",
- "NROUND[2]",
- "NROUND[3]",
+ "3 ADD",
+ "3 SUB",
+ "3 DIV",
+ "3 MUL",
+ "3 ABS",
+ "3 NEG",
+ "5 FLOOR",
+ "7 CEILING",
+ "8 ROUND[0]",
+ "8 ROUND[1]",
+ "8 ROUND[2]",
+ "8 ROUND[3]",
+ "9 NROUND[0]",
+ "9 NROUND[1]",
+ "9 NROUND[2]",
+ "9 NROUND[3]",
- "WCvtF",
- "DeltaP2",
- "DeltaP3",
- "DeltaCn[0]",
- "DeltaCn[1]",
- "DeltaCn[2]",
- "SROUND",
- "S45Round",
- "JROT",
- "JROF",
- "ROFF",
- "INS_$7B",
- "RUTG",
- "RDTG",
- "SANGW",
- "AA",
+ "5 WCvtF",
+ "7 DeltaP2",
+ "7 DeltaP3",
+ "A DeltaCn[0]",
+ "A DeltaCn[1]",
+ "A DeltaCn[2]",
+ "6 SROUND",
+ "8 S45Round",
+ "4 JROT",
+ "4 JROF",
+ "4 ROFF",
+ "7 INS_$7B",
+ "4 RUTG",
+ "4 RDTG",
+ "5 SANGW",
+ "2 AA",
- "FlipPT",
- "FlipRgON",
- "FlipRgOFF",
- "INS_$83",
- "INS_$84",
- "ScanCTRL",
- "SDVPTL[0]",
- "SDVPTL[1]",
- "GetINFO",
- "IDEF",
- "ROLL",
- "MAX",
- "MIN",
- "ScanTYPE",
- "InstCTRL",
- "INS_$8F",
+ "6 FlipPT",
+ "8 FlipRgON",
+ "9 FlipRgOFF",
+ "7 INS_$83",
+ "7 INS_$84",
+ "8 ScanCTRL",
+ "9 SDPvTL[0]",
+ "9 SDPvTL[1]",
+ "7 GetINFO",
+ "4 IDEF",
+ "4 ROLL",
+ "3 MAX",
+ "3 MIN",
+ "8 ScanTYPE",
+ "8 InstCTRL",
+ "7 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",
+ "7 INS_$90",
+ "7 INS_$91",
+ "7 INS_$92",
+ "7 INS_$93",
+ "7 INS_$94",
+ "7 INS_$95",
+ "7 INS_$96",
+ "7 INS_$97",
+ "7 INS_$98",
+ "7 INS_$99",
+ "7 INS_$9A",
+ "7 INS_$9B",
+ "7 INS_$9C",
+ "7 INS_$9D",
+ "7 INS_$9E",
+ "7 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",
+ "7 INS_$A0",
+ "7 INS_$A1",
+ "7 INS_$A2",
+ "7 INS_$A3",
+ "7 INS_$A4",
+ "7 INS_$A5",
+ "7 INS_$A6",
+ "7 INS_$A7",
+ "7 INS_$A8",
+ "7 INS_$A9",
+ "7 INS_$AA",
+ "7 INS_$AB",
+ "7 INS_$AC",
+ "7 INS_$AD",
+ "7 INS_$AE",
+ "7 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]",
+ "8 PushB[0]",
+ "8 PushB[1]",
+ "8 PushB[2]",
+ "8 PushB[3]",
+ "8 PushB[4]",
+ "8 PushB[5]",
+ "8 PushB[6]",
+ "8 PushB[7]",
+ "8 PushW[0]",
+ "8 PushW[1]",
+ "8 PushW[2]",
+ "8 PushW[3]",
+ "8 PushW[4]",
+ "8 PushW[5]",
+ "8 PushW[6]",
+ "8 PushW[7]",
- "MDRP[00]",
- "MDRP[01]",
- "MDRP[02]",
- "MDRP[03]",
- "MDRP[04]",
- "MDRP[05]",
- "MDRP[06]",
- "MDRP[07]",
- "MDRP[08]",
- "MDRP[09]",
- "MDRP[10]",
- "MDRP[11]",
- "MDRP[12]",
- "MDRP[13]",
- "MDRP[14]",
- "MDRP[15]",
+ "8 MDRP[00]",
+ "8 MDRP[01]",
+ "8 MDRP[02]",
+ "8 MDRP[03]",
+ "8 MDRP[04]",
+ "8 MDRP[05]",
+ "8 MDRP[06]",
+ "8 MDRP[07]",
+ "8 MDRP[08]",
+ "8 MDRP[09]",
+ "8 MDRP[10]",
+ "8 MDRP[11]",
+ "8 MDRP[12]",
+ "8 MDRP[13]",
+ "8 MDRP[14]",
+ "8 MDRP[15]",
- "MDRP[16]",
- "MDRP[17]",
- "MDRP[18]",
- "MDRP[19]",
- "MDRP[20]",
- "MDRP[21]",
- "MDRP[22]",
- "MDRP[23]",
- "MDRP[24]",
- "MDRP[25]",
- "MDRP[26]",
- "MDRP[27]",
- "MDRP[28]",
- "MDRP[29]",
- "MDRP[30]",
- "MDRP[31]",
+ "8 MDRP[16]",
+ "8 MDRP[17]",
+ "8 MDRP[18]",
+ "8 MDRP[19]",
+ "8 MDRP[20]",
+ "8 MDRP[21]",
+ "8 MDRP[22]",
+ "8 MDRP[23]",
+ "8 MDRP[24]",
+ "8 MDRP[25]",
+ "8 MDRP[26]",
+ "8 MDRP[27]",
+ "8 MDRP[28]",
+ "8 MDRP[29]",
+ "8 MDRP[30]",
+ "8 MDRP[31]",
- "MIRP[00]",
- "MIRP[01]",
- "MIRP[02]",
- "MIRP[03]",
- "MIRP[04]",
- "MIRP[05]",
- "MIRP[06]",
- "MIRP[07]",
- "MIRP[08]",
- "MIRP[09]",
- "MIRP[10]",
- "MIRP[11]",
- "MIRP[12]",
- "MIRP[13]",
- "MIRP[14]",
- "MIRP[15]",
+ "8 MIRP[00]",
+ "8 MIRP[01]",
+ "8 MIRP[02]",
+ "8 MIRP[03]",
+ "8 MIRP[04]",
+ "8 MIRP[05]",
+ "8 MIRP[06]",
+ "8 MIRP[07]",
+ "8 MIRP[08]",
+ "8 MIRP[09]",
+ "8 MIRP[10]",
+ "8 MIRP[11]",
+ "8 MIRP[12]",
+ "8 MIRP[13]",
+ "8 MIRP[14]",
+ "8 MIRP[15]",
- "MIRP[16]",
- "MIRP[17]",
- "MIRP[18]",
- "MIRP[19]",
- "MIRP[20]",
- "MIRP[21]",
- "MIRP[22]",
- "MIRP[23]",
- "MIRP[24]",
- "MIRP[25]",
- "MIRP[26]",
- "MIRP[27]",
- "MIRP[28]",
- "MIRP[29]",
- "MIRP[30]",
- "MIRP[31]"
+ "8 MIRP[16]",
+ "8 MIRP[17]",
+ "8 MIRP[18]",
+ "8 MIRP[19]",
+ "8 MIRP[20]",
+ "8 MIRP[21]",
+ "8 MIRP[22]",
+ "8 MIRP[23]",
+ "8 MIRP[24]",
+ "8 MIRP[25]",
+ "8 MIRP[26]",
+ "8 MIRP[27]",
+ "8 MIRP[28]",
+ "8 MIRP[29]",
+ "8 MIRP[30]",
+ "8 MIRP[31]"
};
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1437,8 +1232,107 @@
#undef PACK
-#if 1
+#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
+
+#if defined( __arm__ ) && \
+ ( defined( __thumb2__ ) || !defined( __thumb__ ) )
+
+#define TT_MulFix14 TT_MulFix14_arm
+
+ static FT_Int32
+ TT_MulFix14_arm( FT_Int32 a,
+ FT_Int b )
+ {
+ FT_Int32 t, t2;
+
+
+#if defined( __CC_ARM ) || defined( __ARMCC__ )
+
+ __asm
+ {
+ smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
+ mov a, t, asr #31 /* a = (hi >> 31) */
+ add a, a, #0x2000 /* a += 0x2000 */
+ adds t2, t2, a /* t2 += a */
+ adc t, t, #0 /* t += carry */
+ mov a, t2, lsr #14 /* a = t2 >> 14 */
+ orr a, a, t, lsl #18 /* a |= t << 18 */
+ }
+
+#elif defined( __GNUC__ )
+
+ __asm__ __volatile__ (
+ "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
+ "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
+#if defined( __clang__ ) && defined( __thumb2__ )
+ "add.w %0, %0, #0x2000\n\t" /* %0 += 0x2000 */
+#else
+ "add %0, %0, #0x2000\n\t" /* %0 += 0x2000 */
+#endif
+ "adds %1, %1, %0\n\t" /* %1 += %0 */
+ "adc %2, %2, #0\n\t" /* %2 += carry */
+ "mov %0, %1, lsr #14\n\t" /* %0 = %1 >> 16 */
+ "orr %0, %0, %2, lsl #18\n\t" /* %0 |= %2 << 16 */
+ : "=r"(a), "=&r"(t2), "=&r"(t)
+ : "r"(a), "r"(b)
+ : "cc" );
+
+#endif
+
+ return a;
+ }
+
+#endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */
+
+#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+
+#if defined( __GNUC__ ) && \
+ ( defined( __i386__ ) || defined( __x86_64__ ) )
+
+#define TT_MulFix14 TT_MulFix14_long_long
+
+ /* Temporarily disable the warning that C90 doesn't support `long long'. */
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wlong-long"
+
+ /* This is declared `noinline' because inlining the function results */
+ /* in slower code. The `pure' attribute indicates that the result */
+ /* only depends on the parameters. */
+ static __attribute__(( noinline ))
+ __attribute__(( pure )) FT_Int32
+ TT_MulFix14_long_long( FT_Int32 a,
+ FT_Int b )
+ {
+
+ long long ret = (long long)a * b;
+
+ /* The following line assumes that right shifting of signed values */
+ /* will actually preserve the sign bit. The exact behaviour is */
+ /* undefined, but this is true on x86 and x86_64. */
+ long long tmp = ret >> 63;
+
+
+ ret += 0x2000 + tmp;
+
+ return (FT_Int32)( ret >> 14 );
+ }
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic pop
+#endif
+
+#endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */
+
+
+#ifndef TT_MulFix14
+
+ /* Compute (a*b)/2^14 with maximum accuracy and rounding. */
+ /* This is optimized to be faster than calling FT_MulFix() */
+ /* for platforms where sizeof(int) == 2. */
static FT_Int32
TT_MulFix14( FT_Int32 a,
FT_Int b )
@@ -1470,37 +1364,50 @@
return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid;
}
-#else
+#endif /* !TT_MulFix14 */
- /* compute (a*b)/2^14 with maximum accuracy and rounding */
- static FT_Int32
- TT_MulFix14( FT_Int32 a,
- FT_Int b )
+
+#if defined( __GNUC__ ) && \
+ ( defined( __i386__ ) || \
+ defined( __x86_64__ ) || \
+ defined( __arm__ ) )
+
+#define TT_DotFix14 TT_DotFix14_long_long
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wlong-long"
+
+ static __attribute__(( pure )) FT_Int32
+ TT_DotFix14_long_long( FT_Int32 ax,
+ FT_Int32 ay,
+ FT_Int bx,
+ FT_Int by )
{
- FT_Int32 m, s, hi;
- FT_UInt32 l, lo;
+ /* Temporarily disable the warning that C90 doesn't support */
+ /* `long long'. */
+
+ long long temp1 = (long long)ax * bx;
+ long long temp2 = (long long)ay * by;
- /* compute ax*bx as 64-bit value */
- l = (FT_UInt32)( ( a & 0xFFFFU ) * b );
- m = ( a >> 16 ) * b;
+ temp1 += temp2;
+ temp2 = temp1 >> 63;
+ temp1 += 0x2000 + temp2;
- lo = l + ( (FT_UInt32)m << 16 );
- hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
+ return (FT_Int32)( temp1 >> 14 );
- /* divide the result by 2^14 with rounding */
- s = hi >> 31;
- l = lo + (FT_UInt32)s;
- hi += s + ( l < lo );
- lo = l;
-
- l = lo + 0x2000U;
- hi += l < lo;
-
- return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
}
+
+#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406
+#pragma GCC diagnostic pop
#endif
+#endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */
+
+
+#ifndef TT_DotFix14
/* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
static FT_Int32
@@ -1543,6 +1450,8 @@
return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
}
+#endif /* TT_DotFix14 */
+
/*************************************************************************/
/* */
@@ -1557,48 +1466,55 @@
/* The aspect ratio in 16.16 format, always <= 1.0 . */
/* */
static FT_Long
- Current_Ratio( EXEC_OP )
+ Current_Ratio( TT_ExecContext exc )
{
- if ( !CUR.tt_metrics.ratio )
+ if ( !exc->tt_metrics.ratio )
{
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
- if ( CUR.GS.both_x_axis )
- CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+ if ( exc->GS.both_x_axis )
+ exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
else
- CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+ exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
}
else
#endif
{
- if ( CUR.GS.projVector.y == 0 )
- CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+ if ( exc->GS.projVector.y == 0 )
+ exc->tt_metrics.ratio = exc->tt_metrics.x_ratio;
- else if ( CUR.GS.projVector.x == 0 )
- CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+ else if ( exc->GS.projVector.x == 0 )
+ exc->tt_metrics.ratio = exc->tt_metrics.y_ratio;
else
{
FT_F26Dot6 x, y;
- x = TT_MulFix14( CUR.tt_metrics.x_ratio,
- CUR.GS.projVector.x );
- y = TT_MulFix14( CUR.tt_metrics.y_ratio,
- CUR.GS.projVector.y );
- CUR.tt_metrics.ratio = FT_Hypot( x, y );
+ x = TT_MulFix14( exc->tt_metrics.x_ratio,
+ exc->GS.projVector.x );
+ y = TT_MulFix14( exc->tt_metrics.y_ratio,
+ exc->GS.projVector.y );
+ exc->tt_metrics.ratio = FT_Hypot( x, y );
}
}
}
- return CUR.tt_metrics.ratio;
+ return exc->tt_metrics.ratio;
}
- static FT_Long
- Current_Ppem( EXEC_OP )
+ FT_CALLBACK_DEF( FT_Long )
+ Current_Ppem( TT_ExecContext exc )
{
- return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+ return exc->tt_metrics.ppem;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Long )
+ Current_Ppem_Stretched( TT_ExecContext exc )
+ {
+ return FT_MulFix( exc->tt_metrics.ppem, Current_Ratio( exc ) );
}
@@ -1610,48 +1526,54 @@
FT_CALLBACK_DEF( FT_F26Dot6 )
- Read_CVT( EXEC_OP_ FT_ULong idx )
+ Read_CVT( TT_ExecContext exc,
+ FT_ULong idx )
{
- return CUR.cvt[idx];
+ return exc->cvt[idx];
}
FT_CALLBACK_DEF( FT_F26Dot6 )
- Read_CVT_Stretched( EXEC_OP_ FT_ULong idx )
+ Read_CVT_Stretched( TT_ExecContext exc,
+ FT_ULong idx )
{
- return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
+ return FT_MulFix( exc->cvt[idx], Current_Ratio( exc ) );
}
FT_CALLBACK_DEF( void )
- Write_CVT( EXEC_OP_ FT_ULong idx,
- FT_F26Dot6 value )
+ Write_CVT( TT_ExecContext exc,
+ FT_ULong idx,
+ FT_F26Dot6 value )
{
- CUR.cvt[idx] = value;
+ exc->cvt[idx] = value;
}
FT_CALLBACK_DEF( void )
- Write_CVT_Stretched( EXEC_OP_ FT_ULong idx,
- FT_F26Dot6 value )
+ Write_CVT_Stretched( TT_ExecContext exc,
+ FT_ULong idx,
+ FT_F26Dot6 value )
{
- CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() );
+ exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
}
FT_CALLBACK_DEF( void )
- Move_CVT( EXEC_OP_ FT_ULong idx,
- FT_F26Dot6 value )
+ Move_CVT( TT_ExecContext exc,
+ FT_ULong idx,
+ FT_F26Dot6 value )
{
- CUR.cvt[idx] += value;
+ exc->cvt[idx] += value;
}
FT_CALLBACK_DEF( void )
- Move_CVT_Stretched( EXEC_OP_ FT_ULong idx,
- FT_F26Dot6 value )
+ Move_CVT_Stretched( TT_ExecContext exc,
+ FT_ULong idx,
+ FT_F26Dot6 value )
{
- CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() );
+ exc->cvt[idx] += FT_DivFix( value, Current_Ratio( exc ) );
}
@@ -1671,12 +1593,12 @@
/* This one could become a macro. */
/* */
static FT_Short
- GetShortIns( EXEC_OP )
+ GetShortIns( TT_ExecContext exc )
{
/* Reading a byte stream so there is no endianess (DaveP) */
- CUR.IP += 2;
- return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
- CUR.code[CUR.IP - 1] );
+ exc->IP += 2;
+ return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) +
+ exc->code[exc->IP - 1] );
}
@@ -1697,23 +1619,24 @@
/* SUCCESS or FAILURE. */
/* */
static FT_Bool
- Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange,
- FT_ULong aIP )
+ Ins_Goto_CodeRange( TT_ExecContext exc,
+ FT_Int aRange,
+ FT_Long aIP )
{
TT_CodeRange* range;
if ( aRange < 1 || aRange > 3 )
{
- CUR.error = FT_THROW( Bad_Argument );
+ exc->error = FT_THROW( Bad_Argument );
return FAILURE;
}
- range = &CUR.codeRangeTable[aRange - 1];
+ range = &exc->codeRangeTable[aRange - 1];
if ( range->base == NULL ) /* invalid coderange */
{
- CUR.error = FT_THROW( Invalid_CodeRange );
+ exc->error = FT_THROW( Invalid_CodeRange );
return FAILURE;
}
@@ -1723,14 +1646,14 @@
if ( aIP > range->size )
{
- CUR.error = FT_THROW( Code_Overflow );
+ exc->error = FT_THROW( Code_Overflow );
return FAILURE;
}
- CUR.code = range->base;
- CUR.codeSize = range->size;
- CUR.IP = aIP;
- CUR.curRange = aRange;
+ exc->code = range->base;
+ exc->codeSize = range->size;
+ exc->IP = aIP;
+ exc->curRange = aRange;
return SUCCESS;
}
@@ -1754,36 +1677,37 @@
/* zone :: The affected glyph zone. */
/* */
static void
- Direct_Move( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
FT_F26Dot6 v;
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- FT_ASSERT( !CUR.face->unpatented_hinting );
+ FT_ASSERT( !exc->face->unpatented_hinting );
#endif
- v = CUR.GS.freeVector.x;
+ v = exc->GS.freeVector.x;
if ( v != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !SUBPIXEL_HINTING ||
- ( !CUR.ignore_x_mode ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !exc->ignore_x_mode ||
+ ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
+ zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
- v = CUR.GS.freeVector.y;
+ v = exc->GS.freeVector.y;
if ( v != 0 )
{
- zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
+ zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
@@ -1808,26 +1732,27 @@
/* zone :: The affected glyph zone. */
/* */
static void
- Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move_Orig( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
FT_F26Dot6 v;
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- FT_ASSERT( !CUR.face->unpatented_hinting );
+ FT_ASSERT( !exc->face->unpatented_hinting );
#endif
- v = CUR.GS.freeVector.x;
+ v = exc->GS.freeVector.x;
if ( v != 0 )
- zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
+ zone->org[point].x += FT_MulDiv( distance, v, exc->F_dot_P );
- v = CUR.GS.freeVector.y;
+ v = exc->GS.freeVector.y;
if ( v != 0 )
- zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
+ zone->org[point].y += FT_MulDiv( distance, v, exc->F_dot_P );
}
@@ -1842,15 +1767,16 @@
static void
- Direct_Move_X( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move_X( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( !SUBPIXEL_HINTING ||
- !CUR.ignore_x_mode )
+ if ( !SUBPIXEL_HINTING ||
+ !exc->ignore_x_mode )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
zone->cur[point].x += distance;
@@ -1859,11 +1785,12 @@
static void
- Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move_Y( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
zone->cur[point].y += distance;
zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
@@ -1881,22 +1808,24 @@
static void
- Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move_Orig_X( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
zone->org[point].x += distance;
}
static void
- Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance )
+ Direct_Move_Orig_Y( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
zone->org[point].y += distance;
}
@@ -1925,18 +1854,19 @@
/* before rounding. */
/* */
static FT_F26Dot6
- Round_None( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_None( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
val = distance + compensation;
- if ( distance && val < 0 )
+ if ( val < 0 )
val = 0;
}
else
@@ -1966,20 +1896,19 @@
/* Rounded distance. */
/* */
static FT_F26Dot6
- Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_To_Grid( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
- val = distance + compensation + 32;
- if ( distance && val > 0 )
- val &= ~63;
- else
+ val = FT_PIX_ROUND( distance + compensation );
+ if ( val < 0 )
val = 0;
}
else
@@ -1989,7 +1918,7 @@
val = 0;
}
- return val;
+ return val;
}
@@ -2010,25 +1939,26 @@
/* Rounded distance. */
/* */
static FT_F26Dot6
- Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_To_Half_Grid( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
val = FT_PIX_FLOOR( distance + compensation ) + 32;
- if ( distance && val < 0 )
- val = 0;
+ if ( val < 0 )
+ val = 32;
}
else
{
val = -( FT_PIX_FLOOR( compensation - distance ) + 32 );
if ( val > 0 )
- val = 0;
+ val = -32;
}
return val;
@@ -2052,25 +1982,24 @@
/* Rounded distance. */
/* */
static FT_F26Dot6
- Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_Down_To_Grid( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
- val = distance + compensation;
- if ( distance && val > 0 )
- val &= ~63;
- else
+ val = FT_PIX_FLOOR( distance + compensation );
+ if ( val < 0 )
val = 0;
}
else
{
- val = -( ( compensation - distance ) & -64 );
+ val = -FT_PIX_FLOOR( compensation - distance );
if ( val > 0 )
val = 0;
}
@@ -2096,20 +2025,19 @@
/* Rounded distance. */
/* */
static FT_F26Dot6
- Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_Up_To_Grid( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
- val = distance + compensation + 63;
- if ( distance && val > 0 )
- val &= ~63;
- else
+ val = FT_PIX_CEIL( distance + compensation );
+ if ( val < 0 )
val = 0;
}
else
@@ -2140,20 +2068,19 @@
/* Rounded distance. */
/* */
static FT_F26Dot6
- Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_To_Double_Grid( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
if ( distance >= 0 )
{
- val = distance + compensation + 16;
- if ( distance && val > 0 )
- val &= ~31;
- else
+ val = FT_PAD_ROUND( distance + compensation, 32 );
+ if ( val < 0 )
val = 0;
}
else
@@ -2190,27 +2117,28 @@
/* before rounding. */
/* */
static FT_F26Dot6
- Round_Super( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_Super( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
if ( distance >= 0 )
{
- val = ( distance - CUR.phase + CUR.threshold + compensation ) &
- -CUR.period;
- if ( distance && val < 0 )
- val = 0;
- val += CUR.phase;
+ val = ( distance - exc->phase + exc->threshold + compensation ) &
+ -exc->period;
+ val += exc->phase;
+ if ( val < 0 )
+ val = exc->phase;
}
else
{
- val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
- -CUR.period );
+ val = -( ( exc->threshold - exc->phase - distance + compensation ) &
+ -exc->period );
+ val -= exc->phase;
if ( val > 0 )
- val = 0;
- val -= CUR.phase;
+ val = -exc->phase;
}
return val;
@@ -2238,27 +2166,28 @@
/* greater precision. */
/* */
static FT_F26Dot6
- Round_Super_45( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation )
+ Round_Super_45( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation )
{
FT_F26Dot6 val;
if ( distance >= 0 )
{
- val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
- CUR.period ) * CUR.period;
- if ( distance && val < 0 )
- val = 0;
- val += CUR.phase;
+ val = ( ( distance - exc->phase + exc->threshold + compensation ) /
+ exc->period ) * exc->period;
+ val += exc->phase;
+ if ( val < 0 )
+ val = exc->phase;
}
else
{
- val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
- CUR.period ) * CUR.period );
+ val = -( ( ( exc->threshold - exc->phase - distance + compensation ) /
+ exc->period ) * exc->period );
+ val -= exc->phase;
if ( val > 0 )
- val = 0;
- val -= CUR.phase;
+ val = -exc->phase;
}
return val;
@@ -2277,40 +2206,41 @@
/* round_mode :: The rounding mode to be used. */
/* */
static void
- Compute_Round( EXEC_OP_ FT_Byte round_mode )
+ Compute_Round( TT_ExecContext exc,
+ FT_Byte round_mode )
{
switch ( round_mode )
{
case TT_Round_Off:
- CUR.func_round = (TT_Round_Func)Round_None;
+ exc->func_round = (TT_Round_Func)Round_None;
break;
case TT_Round_To_Grid:
- CUR.func_round = (TT_Round_Func)Round_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Grid;
break;
case TT_Round_Up_To_Grid:
- CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
break;
case TT_Round_Down_To_Grid:
- CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
break;
case TT_Round_To_Half_Grid:
- CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
break;
case TT_Round_To_Double_Grid:
- CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
break;
case TT_Round_Super:
- CUR.func_round = (TT_Round_Func)Round_Super;
+ exc->func_round = (TT_Round_Func)Round_Super;
break;
case TT_Round_Super_45:
- CUR.func_round = (TT_Round_Func)Round_Super_45;
+ exc->func_round = (TT_Round_Func)Round_Super_45;
break;
}
}
@@ -2330,57 +2260,58 @@
/* selector :: The SROUND opcode. */
/* */
static void
- SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod,
- FT_Long selector )
+ SetSuperRound( TT_ExecContext exc,
+ FT_F2Dot14 GridPeriod,
+ FT_Long selector )
{
switch ( (FT_Int)( selector & 0xC0 ) )
{
case 0:
- CUR.period = GridPeriod / 2;
+ exc->period = GridPeriod / 2;
break;
case 0x40:
- CUR.period = GridPeriod;
+ exc->period = GridPeriod;
break;
case 0x80:
- CUR.period = GridPeriod * 2;
+ exc->period = GridPeriod * 2;
break;
/* This opcode is reserved, but... */
-
case 0xC0:
- CUR.period = GridPeriod;
+ exc->period = GridPeriod;
break;
}
switch ( (FT_Int)( selector & 0x30 ) )
{
case 0:
- CUR.phase = 0;
+ exc->phase = 0;
break;
case 0x10:
- CUR.phase = CUR.period / 4;
+ exc->phase = exc->period / 4;
break;
case 0x20:
- CUR.phase = CUR.period / 2;
+ exc->phase = exc->period / 2;
break;
case 0x30:
- CUR.phase = CUR.period * 3 / 4;
+ exc->phase = exc->period * 3 / 4;
break;
}
if ( ( selector & 0x0F ) == 0 )
- CUR.threshold = CUR.period - 1;
+ exc->threshold = exc->period - 1;
else
- CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+ exc->threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * exc->period / 8;
- CUR.period /= 256;
- CUR.phase /= 256;
- CUR.threshold /= 256;
+ /* convert to F26Dot6 format */
+ exc->period >>= 8;
+ exc->phase >>= 8;
+ exc->threshold >>= 8;
}
@@ -2401,16 +2332,17 @@
/* The distance in F26dot6 format. */
/* */
static FT_F26Dot6
- Project( EXEC_OP_ FT_Pos dx,
- FT_Pos dy )
+ Project( TT_ExecContext exc,
+ FT_Pos dx,
+ FT_Pos dy )
{
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- FT_ASSERT( !CUR.face->unpatented_hinting );
+ FT_ASSERT( !exc->face->unpatented_hinting );
#endif
- return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
- CUR.GS.projVector.x,
- CUR.GS.projVector.y );
+ return TT_DotFix14( dx, dy,
+ exc->GS.projVector.x,
+ exc->GS.projVector.y );
}
@@ -2431,12 +2363,13 @@
/* The distance in F26dot6 format. */
/* */
static FT_F26Dot6
- Dual_Project( EXEC_OP_ FT_Pos dx,
- FT_Pos dy )
+ Dual_Project( TT_ExecContext exc,
+ FT_Pos dx,
+ FT_Pos dy )
{
- return TT_DotFix14( (FT_UInt32)dx, (FT_UInt32)dy,
- CUR.GS.dualVector.x,
- CUR.GS.dualVector.y );
+ return TT_DotFix14( dx, dy,
+ exc->GS.dualVector.x,
+ exc->GS.dualVector.y );
}
@@ -2457,10 +2390,11 @@
/* The distance in F26dot6 format. */
/* */
static FT_F26Dot6
- Project_x( EXEC_OP_ FT_Pos dx,
- FT_Pos dy )
+ Project_x( TT_ExecContext exc,
+ FT_Pos dx,
+ FT_Pos dy )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
FT_UNUSED( dy );
return dx;
@@ -2484,10 +2418,11 @@
/* The distance in F26dot6 format. */
/* */
static FT_F26Dot6
- Project_y( EXEC_OP_ FT_Pos dx,
- FT_Pos dy )
+ Project_y( TT_ExecContext exc,
+ FT_Pos dx,
+ FT_Pos dy )
{
- FT_UNUSED_EXEC;
+ FT_UNUSED( exc );
FT_UNUSED( dx );
return dy;
@@ -2504,101 +2439,101 @@
/* to the current graphics state. */
/* */
static void
- Compute_Funcs( EXEC_OP )
+ Compute_Funcs( TT_ExecContext exc )
{
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
- /* If both vectors point rightwards along the x axis, set */
- /* `both-x-axis' true, otherwise set it false. The x values only */
- /* need be tested because the vector has been normalised to a unit */
- /* vector of length 0x4000 = unity. */
- CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 &&
- CUR.GS.freeVector.x == 0x4000 );
+ /* If both vectors point rightwards along the x axis, set */
+ /* `both-x-axis' true, otherwise set it false. The x values only */
+ /* need be tested because the vector has been normalised to a unit */
+ /* vector of length 0x4000 = unity. */
+ exc->GS.both_x_axis = (FT_Bool)( exc->GS.projVector.x == 0x4000 &&
+ exc->GS.freeVector.x == 0x4000 );
/* Throw away projection and freedom vector information */
/* because the patents don't allow them to be stored. */
/* The relevant US Patents are 5155805 and 5325479. */
- CUR.GS.projVector.x = 0;
- CUR.GS.projVector.y = 0;
- CUR.GS.freeVector.x = 0;
- CUR.GS.freeVector.y = 0;
+ exc->GS.projVector.x = 0;
+ exc->GS.projVector.y = 0;
+ exc->GS.freeVector.x = 0;
+ exc->GS.freeVector.y = 0;
- if ( CUR.GS.both_x_axis )
+ if ( exc->GS.both_x_axis )
{
- CUR.func_project = Project_x;
- CUR.func_move = Direct_Move_X;
- CUR.func_move_orig = Direct_Move_Orig_X;
+ exc->func_project = Project_x;
+ exc->func_move = Direct_Move_X;
+ exc->func_move_orig = Direct_Move_Orig_X;
}
else
{
- CUR.func_project = Project_y;
- CUR.func_move = Direct_Move_Y;
- CUR.func_move_orig = Direct_Move_Orig_Y;
+ exc->func_project = Project_y;
+ exc->func_move = Direct_Move_Y;
+ exc->func_move_orig = Direct_Move_Orig_Y;
}
- if ( CUR.GS.dualVector.x == 0x4000 )
- CUR.func_dualproj = Project_x;
- else if ( CUR.GS.dualVector.y == 0x4000 )
- CUR.func_dualproj = Project_y;
+ if ( exc->GS.dualVector.x == 0x4000 )
+ exc->func_dualproj = Project_x;
+ else if ( exc->GS.dualVector.y == 0x4000 )
+ exc->func_dualproj = Project_y;
else
- CUR.func_dualproj = Dual_Project;
+ exc->func_dualproj = Dual_Project;
/* Force recalculation of cached aspect ratio */
- CUR.tt_metrics.ratio = 0;
+ exc->tt_metrics.ratio = 0;
return;
}
#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
- if ( CUR.GS.freeVector.x == 0x4000 )
- CUR.F_dot_P = CUR.GS.projVector.x;
- else if ( CUR.GS.freeVector.y == 0x4000 )
- CUR.F_dot_P = CUR.GS.projVector.y;
+ if ( exc->GS.freeVector.x == 0x4000 )
+ exc->F_dot_P = exc->GS.projVector.x;
+ else if ( exc->GS.freeVector.y == 0x4000 )
+ exc->F_dot_P = exc->GS.projVector.y;
else
- CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
- (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
- 14;
+ exc->F_dot_P =
+ ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x +
+ (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14;
- if ( CUR.GS.projVector.x == 0x4000 )
- CUR.func_project = (TT_Project_Func)Project_x;
- else if ( CUR.GS.projVector.y == 0x4000 )
- CUR.func_project = (TT_Project_Func)Project_y;
+ if ( exc->GS.projVector.x == 0x4000 )
+ exc->func_project = (TT_Project_Func)Project_x;
+ else if ( exc->GS.projVector.y == 0x4000 )
+ exc->func_project = (TT_Project_Func)Project_y;
else
- CUR.func_project = (TT_Project_Func)Project;
+ exc->func_project = (TT_Project_Func)Project;
- if ( CUR.GS.dualVector.x == 0x4000 )
- CUR.func_dualproj = (TT_Project_Func)Project_x;
- else if ( CUR.GS.dualVector.y == 0x4000 )
- CUR.func_dualproj = (TT_Project_Func)Project_y;
+ if ( exc->GS.dualVector.x == 0x4000 )
+ exc->func_dualproj = (TT_Project_Func)Project_x;
+ else if ( exc->GS.dualVector.y == 0x4000 )
+ exc->func_dualproj = (TT_Project_Func)Project_y;
else
- CUR.func_dualproj = (TT_Project_Func)Dual_Project;
+ exc->func_dualproj = (TT_Project_Func)Dual_Project;
- CUR.func_move = (TT_Move_Func)Direct_Move;
- CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
+ exc->func_move = (TT_Move_Func)Direct_Move;
+ exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig;
- if ( CUR.F_dot_P == 0x4000L )
+ if ( exc->F_dot_P == 0x4000L )
{
- if ( CUR.GS.freeVector.x == 0x4000 )
+ if ( exc->GS.freeVector.x == 0x4000 )
{
- CUR.func_move = (TT_Move_Func)Direct_Move_X;
- CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
+ exc->func_move = (TT_Move_Func)Direct_Move_X;
+ exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
}
- else if ( CUR.GS.freeVector.y == 0x4000 )
+ else if ( exc->GS.freeVector.y == 0x4000 )
{
- CUR.func_move = (TT_Move_Func)Direct_Move_Y;
- CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
+ exc->func_move = (TT_Move_Func)Direct_Move_Y;
+ exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
}
}
/* at small sizes, F_dot_P can become too small, resulting */
/* in overflows and `spikes' in a number of glyphs like `w'. */
- if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
- CUR.F_dot_P = 0x4000L;
+ if ( FT_ABS( exc->F_dot_P ) < 0x400L )
+ exc->F_dot_P = 0x4000L;
/* Disable cached aspect ratio */
- CUR.tt_metrics.ratio = 0;
+ exc->tt_metrics.ratio = 0;
}
@@ -2621,36 +2556,31 @@
/* Returns FAILURE if a vector parameter is zero. */
/* */
/* <Note> */
- /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */
+ /* In case Vx and Vy are both zero, `Normalize' returns SUCCESS, and */
/* R is undefined. */
/* */
static FT_Bool
- Normalize( EXEC_OP_ FT_F26Dot6 Vx,
- FT_F26Dot6 Vy,
- FT_UnitVector* R )
+ Normalize( FT_F26Dot6 Vx,
+ FT_F26Dot6 Vy,
+ FT_UnitVector* R )
{
- FT_F26Dot6 W;
-
- FT_UNUSED_EXEC;
+ FT_Vector V;
- if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
+ if ( Vx == 0 && Vy == 0 )
{
- if ( Vx == 0 && Vy == 0 )
- {
- /* XXX: UNDOCUMENTED! It seems that it is possible to try */
- /* to normalize the vector (0,0). Return immediately. */
- return SUCCESS;
- }
-
- Vx *= 0x4000;
- Vy *= 0x4000;
+ /* XXX: UNDOCUMENTED! It seems that it is possible to try */
+ /* to normalize the vector (0,0). Return immediately. */
+ return SUCCESS;
}
- W = FT_Hypot( Vx, Vy );
+ V.x = Vx;
+ V.y = Vy;
- R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
- R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
+ FT_Vector_NormLen( &V );
+
+ R->x = (FT_F2Dot14)( V.x / 4 );
+ R->y = (FT_F2Dot14)( V.y / 4 );
return SUCCESS;
}
@@ -2663,1062 +2593,12 @@
/*************************************************************************/
- static FT_Bool
- Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1,
- FT_UShort aIdx2,
- FT_Int aOpc,
- FT_UnitVector* Vec )
- {
- FT_Long A, B, C;
- FT_Vector* p1;
- FT_Vector* p2;
-
-
- if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
- BOUNDS( aIdx2, CUR.zp1.n_points ) )
- {
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( 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 p1 == p2, SPVTL and SFVTL behave the same as */
- /* SPVTCA[X] and SFVTCA[X], respectively. */
- /* */
- /* Confirmed by Greg Hitchcock. */
-
- if ( A == 0 && B == 0 )
- {
- A = 0x4000;
- aOpc = 0;
- }
-
- if ( ( aOpc & 1 ) != 0 )
- {
- C = B; /* counter clockwise 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 are all defined there. */
-
-#define DO_SVTCA \
- { \
- FT_Short A, B; \
- \
- \
- A = (FT_Short)( CUR.opcode & 1 ) << 14; \
- B = A ^ (FT_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 \
- { \
- FT_Short A, B; \
- \
- \
- A = (FT_Short)( CUR.opcode & 1 ) << 14; \
- B = A ^ (FT_Short)0x4000; \
- \
- CUR.GS.projVector.x = A; \
- CUR.GS.dualVector.x = A; \
- \
- CUR.GS.projVector.y = B; \
- CUR.GS.dualVector.y = B; \
- \
- GUESS_VECTOR( freeVector ); \
- \
- COMPUTE_Funcs(); \
- }
-
-
-#define DO_SFVTCA \
- { \
- FT_Short A, B; \
- \
- \
- A = (FT_Short)( CUR.opcode & 1 ) << 14; \
- B = A ^ (FT_Short)0x4000; \
- \
- CUR.GS.freeVector.x = A; \
- CUR.GS.freeVector.y = B; \
- \
- GUESS_VECTOR( projVector ); \
- \
- COMPUTE_Funcs(); \
- }
-
-
-#define DO_SPVTL \
- if ( INS_SxVTL( (FT_UShort)args[1], \
- (FT_UShort)args[0], \
- CUR.opcode, \
- &CUR.GS.projVector ) == SUCCESS ) \
- { \
- CUR.GS.dualVector = CUR.GS.projVector; \
- GUESS_VECTOR( freeVector ); \
- COMPUTE_Funcs(); \
- }
-
-
-#define DO_SFVTL \
- if ( INS_SxVTL( (FT_UShort)args[1], \
- (FT_UShort)args[0], \
- CUR.opcode, \
- &CUR.GS.freeVector ) == SUCCESS ) \
- { \
- GUESS_VECTOR( projVector ); \
- COMPUTE_Funcs(); \
- }
-
-
-#define DO_SFVTPV \
- GUESS_VECTOR( projVector ); \
- CUR.GS.freeVector = CUR.GS.projVector; \
- COMPUTE_Funcs();
-
-
-#define DO_SPVFS \
- { \
- FT_Short S; \
- FT_Long X, Y; \
- \
- \
- /* Only use low 16bits, then sign extend */ \
- S = (FT_Short)args[1]; \
- Y = (FT_Long)S; \
- S = (FT_Short)args[0]; \
- X = (FT_Long)S; \
- \
- NORMalize( X, Y, &CUR.GS.projVector ); \
- \
- CUR.GS.dualVector = CUR.GS.projVector; \
- GUESS_VECTOR( freeVector ); \
- COMPUTE_Funcs(); \
- }
-
-
-#define DO_SFVFS \
- { \
- FT_Short S; \
- FT_Long X, Y; \
- \
- \
- /* Only use low 16bits, then sign extend */ \
- S = (FT_Short)args[1]; \
- Y = (FT_Long)S; \
- S = (FT_Short)args[0]; \
- X = S; \
- \
- NORMalize( X, Y, &CUR.GS.freeVector ); \
- GUESS_VECTOR( projVector ); \
- COMPUTE_Funcs(); \
- }
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GPV \
- if ( CUR.face->unpatented_hinting ) \
- { \
- args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
- args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
- } \
- else \
- { \
- args[0] = CUR.GS.projVector.x; \
- args[1] = CUR.GS.projVector.y; \
- }
-#else
-#define DO_GPV \
- args[0] = CUR.GS.projVector.x; \
- args[1] = CUR.GS.projVector.y;
-#endif
-
-
-#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
-#define DO_GFV \
- if ( CUR.face->unpatented_hinting ) \
- { \
- args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \
- args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \
- } \
- else \
- { \
- args[0] = CUR.GS.freeVector.x; \
- args[1] = CUR.GS.freeVector.y; \
- }
-#else
-#define DO_GFV \
- args[0] = CUR.GS.freeVector.x; \
- args[1] = CUR.GS.freeVector.y;
-#endif
-
-
-#define DO_SRP0 \
- CUR.GS.rp0 = (FT_UShort)args[0];
-
-
-#define DO_SRP1 \
- CUR.GS.rp1 = (FT_UShort)args[0];
-
-
-#define DO_SRP2 \
- CUR.GS.rp2 = (FT_UShort)args[0];
-
-
-#define DO_RTHG \
- CUR.GS.round_state = TT_Round_To_Half_Grid; \
- CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
-
-
-#define DO_RTG \
- CUR.GS.round_state = TT_Round_To_Grid; \
- CUR.func_round = (TT_Round_Func)Round_To_Grid;
-
-
-#define DO_RTDG \
- CUR.GS.round_state = TT_Round_To_Double_Grid; \
- CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
-
-
-#define DO_RUTG \
- CUR.GS.round_state = TT_Round_Up_To_Grid; \
- CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
-
-
-#define DO_RDTG \
- CUR.GS.round_state = TT_Round_Down_To_Grid; \
- CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
-
-
-#define DO_ROFF \
- CUR.GS.round_state = TT_Round_Off; \
- CUR.func_round = (TT_Round_Func)Round_None;
-
-
-#define DO_SROUND \
- SET_SuperRound( 0x4000, args[0] ); \
- CUR.GS.round_state = TT_Round_Super; \
- CUR.func_round = (TT_Round_Func)Round_Super;
-
-
-#define DO_S45ROUND \
- SET_SuperRound( 0x2D41, args[0] ); \
- CUR.GS.round_state = TT_Round_Super_45; \
- CUR.func_round = (TT_Round_Func)Round_Super_45;
-
-
-#define DO_SLOOP \
- if ( args[0] < 0 ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- else \
- CUR.GS.loop = args[0];
-
-
-#define DO_SMD \
- CUR.GS.minimum_distance = args[0];
-
-
-#define DO_SCVTCI \
- CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
-
-
-#define DO_SSWCI \
- CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
-
-
-#define DO_SSW \
- CUR.GS.single_width_value = FT_MulFix( args[0], \
- CUR.tt_metrics.scale );
-
-
-#define DO_FLIPON \
- CUR.GS.auto_flip = TRUE;
-
-
-#define DO_FLIPOFF \
- CUR.GS.auto_flip = FALSE;
-
-
-#define DO_SDB \
- CUR.GS.delta_base = (FT_Short)args[0];
-
-
-#define DO_SDS \
- CUR.GS.delta_shift = (FT_Short)args[0];
-
-
-#define DO_MD /* nothing */
-
-
-#define DO_MPPEM \
- args[0] = CURRENT_Ppem();
-
-
- /* Note: The pointSize should be irrelevant in a given font program; */
- /* we thus decide to return only the ppem. */
-#if 0
-
-#define DO_MPS \
- args[0] = CUR.metrics.pointSize;
-
-#else
-
-#define DO_MPS \
- args[0] = CURRENT_Ppem();
-
-#endif /* 0 */
-
-
-#define DO_DUP \
- args[1] = args[0];
-
-
-#define DO_CLEAR \
- CUR.new_top = 0;
-
-
-#define DO_SWAP \
- { \
- FT_Long L; \
- \
- \
- L = args[0]; \
- args[0] = args[1]; \
- args[1] = L; \
- }
-
-
-#define DO_DEPTH \
- args[0] = CUR.top;
-
-
-#define DO_CINDEX \
- { \
- FT_Long L; \
- \
- \
- L = args[0]; \
- \
- if ( L <= 0 || L > CUR.args ) \
- { \
- if ( CUR.pedantic_hinting ) \
- CUR.error = FT_THROW( Invalid_Reference ); \
- args[0] = 0; \
- } \
- else \
- args[0] = CUR.stack[CUR.args - L]; \
- }
-
-
-#define DO_JROT \
- if ( args[1] != 0 ) \
- { \
- if ( args[0] == 0 && CUR.args == 0 ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 || \
- ( CUR.callTop > 0 && \
- CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- CUR.step_ins = FALSE; \
- }
-
-
-#define DO_JMPR \
- if ( args[0] == 0 && CUR.args == 0 ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 || \
- ( CUR.callTop > 0 && \
- CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- CUR.step_ins = FALSE;
-
-
-#define DO_JROF \
- if ( args[1] == 0 ) \
- { \
- if ( args[0] == 0 && CUR.args == 0 ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 || \
- ( CUR.callTop > 0 && \
- CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) ) \
- CUR.error = FT_THROW( Bad_Argument ); \
- 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 = FT_THROW( Divide_By_Zero ); \
- else \
- args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
-
-
-#define DO_MUL \
- args[0] = FT_MulDiv( args[0], args[1], 64L );
-
-
-#define DO_ABS \
- args[0] = FT_ABS( args[0] );
-
-
-#define DO_NEG \
- args[0] = -args[0];
-
-
-#define DO_FLOOR \
- args[0] = FT_PIX_FLOOR( args[0] );
-
-
-#define DO_CEILING \
- args[0] = FT_PIX_CEIL( args[0] );
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
-
-#define DO_RS \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( I, CUR.storeSize ) ) \
- { \
- if ( CUR.pedantic_hinting ) \
- ARRAY_BOUND_ERROR; \
- else \
- args[0] = 0; \
- } \
- else \
- { \
- /* subpixel hinting - avoid Typeman Dstroke and */ \
- /* IStroke and Vacuform rounds */ \
- \
- if ( SUBPIXEL_HINTING && \
- CUR.ignore_x_mode && \
- ( ( I == 24 && \
- ( CUR.face->sph_found_func_flags & \
- ( SPH_FDEF_SPACING_1 | \
- SPH_FDEF_SPACING_2 ) ) ) || \
- ( I == 22 && \
- ( CUR.sph_in_func_flags & \
- SPH_FDEF_TYPEMAN_STROKES ) ) || \
- ( I == 8 && \
- ( CUR.face->sph_found_func_flags & \
- SPH_FDEF_VACUFORM_ROUND_1 ) && \
- CUR.iup_called ) ) ) \
- args[0] = 0; \
- else \
- args[0] = CUR.storage[I]; \
- } \
- }
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-#define DO_RS \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( I, CUR.storeSize ) ) \
- { \
- if ( CUR.pedantic_hinting ) \
- { \
- ARRAY_BOUND_ERROR; \
- } \
- else \
- args[0] = 0; \
- } \
- else \
- args[0] = CUR.storage[I]; \
- }
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-
-#define DO_WS \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( I, CUR.storeSize ) ) \
- { \
- if ( CUR.pedantic_hinting ) \
- { \
- ARRAY_BOUND_ERROR; \
- } \
- } \
- else \
- CUR.storage[I] = args[1]; \
- }
-
-
-#define DO_RCVT \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( 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 \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( I, CUR.cvtSize ) ) \
- { \
- if ( CUR.pedantic_hinting ) \
- { \
- ARRAY_BOUND_ERROR; \
- } \
- } \
- else \
- CUR_Func_write_cvt( I, args[1] ); \
- }
-
-
-#define DO_WCVTF \
- { \
- FT_ULong I = (FT_ULong)args[0]; \
- \
- \
- if ( BOUNDSL( I, CUR.cvtSize ) ) \
- { \
- if ( CUR.pedantic_hinting ) \
- { \
- ARRAY_BOUND_ERROR; \
- } \
- } \
- else \
- CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \
- }
-
-
-#define DO_DEBUG \
- CUR.error = FT_THROW( Debug_OpCode );
-
-
-#define DO_ROUND \
- args[0] = CUR_Func_round( \
- args[0], \
- CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
-
-
-#define DO_NROUND \
- args[0] = ROUND_None( args[0], \
- CUR.tt_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 = FT_THROW( Invalid_Reference ); \
- return; \
- }
-
-
- /*************************************************************************/
- /* */
- /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
- /* Opcode range: 0x00-0x01 */
- /* Stack: --> */
- /* */
- static void
- Ins_SVTCA( INS_ARG )
- {
- DO_SVTCA
- }
-
-
- /*************************************************************************/
- /* */
- /* SPVTCA[a]: Set PVector to Coordinate Axis */
- /* Opcode range: 0x02-0x03 */
- /* Stack: --> */
- /* */
- static void
- Ins_SPVTCA( INS_ARG )
- {
- DO_SPVTCA
- }
-
-
- /*************************************************************************/
- /* */
- /* SFVTCA[a]: Set FVector to Coordinate Axis */
- /* Opcode range: 0x04-0x05 */
- /* Stack: --> */
- /* */
- static void
- Ins_SFVTCA( INS_ARG )
- {
- DO_SFVTCA
- }
-
-
- /*************************************************************************/
- /* */
- /* SPVTL[a]: Set PVector To Line */
- /* Opcode range: 0x06-0x07 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SPVTL( INS_ARG )
- {
- DO_SPVTL
- }
-
-
- /*************************************************************************/
- /* */
- /* SFVTL[a]: Set FVector To Line */
- /* Opcode range: 0x08-0x09 */
- /* Stack: uint32 uint32 --> */
- /* */
- static void
- Ins_SFVTL( INS_ARG )
- {
- DO_SFVTL
- }
-
-
- /*************************************************************************/
- /* */
- /* SFVTPV[]: Set FVector To PVector */
- /* Opcode range: 0x0E */
- /* Stack: --> */
- /* */
- static void
- Ins_SFVTPV( INS_ARG )
- {
- DO_SFVTPV
- }
-
-
- /*************************************************************************/
- /* */
- /* SPVFS[]: Set PVector From Stack */
- /* Opcode range: 0x0A */
- /* Stack: f2.14 f2.14 --> */
- /* */
- static void
- Ins_SPVFS( INS_ARG )
- {
- DO_SPVFS
- }
-
-
- /*************************************************************************/
- /* */
- /* SFVFS[]: Set FVector From Stack */
- /* Opcode range: 0x0B */
- /* Stack: f2.14 f2.14 --> */
- /* */
- static void
- Ins_SFVFS( INS_ARG )
- {
- DO_SFVFS
- }
-
-
- /*************************************************************************/
- /* */
- /* GPV[]: Get Projection Vector */
- /* Opcode range: 0x0C */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
- static void
- Ins_GPV( INS_ARG )
- {
- DO_GPV
- }
-
-
- /*************************************************************************/
- /* GFV[]: Get Freedom Vector */
- /* Opcode range: 0x0D */
- /* Stack: ef2.14 --> ef2.14 */
- /* */
- static void
- Ins_GFV( INS_ARG )
- {
- DO_GFV
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP0[]: Set Reference Point 0 */
- /* Opcode range: 0x10 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP0( INS_ARG )
- {
- DO_SRP0
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP1[]: Set Reference Point 1 */
- /* Opcode range: 0x11 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP1( INS_ARG )
- {
- DO_SRP1
- }
-
-
- /*************************************************************************/
- /* */
- /* SRP2[]: Set Reference Point 2 */
- /* Opcode range: 0x12 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SRP2( INS_ARG )
- {
- DO_SRP2
- }
-
-
- /*************************************************************************/
- /* */
- /* RTHG[]: Round To Half Grid */
- /* Opcode range: 0x19 */
- /* Stack: --> */
- /* */
- static void
- Ins_RTHG( INS_ARG )
- {
- DO_RTHG
- }
-
-
- /*************************************************************************/
- /* */
- /* RTG[]: Round To Grid */
- /* Opcode range: 0x18 */
- /* Stack: --> */
- /* */
- static void
- Ins_RTG( INS_ARG )
- {
- DO_RTG
- }
-
-
- /*************************************************************************/
- /* RTDG[]: Round To Double Grid */
- /* Opcode range: 0x3D */
- /* Stack: --> */
- /* */
- static void
- Ins_RTDG( INS_ARG )
- {
- DO_RTDG
- }
-
-
- /*************************************************************************/
- /* RUTG[]: Round Up To Grid */
- /* Opcode range: 0x7C */
- /* Stack: --> */
- /* */
- static void
- Ins_RUTG( INS_ARG )
- {
- DO_RUTG
- }
-
-
- /*************************************************************************/
- /* */
- /* RDTG[]: Round Down To Grid */
- /* Opcode range: 0x7D */
- /* Stack: --> */
- /* */
- static void
- Ins_RDTG( INS_ARG )
- {
- DO_RDTG
- }
-
-
- /*************************************************************************/
- /* */
- /* ROFF[]: Round OFF */
- /* Opcode range: 0x7A */
- /* Stack: --> */
- /* */
- static void
- Ins_ROFF( INS_ARG )
- {
- DO_ROFF
- }
-
-
- /*************************************************************************/
- /* */
- /* SROUND[]: Super ROUND */
- /* Opcode range: 0x76 */
- /* Stack: Eint8 --> */
- /* */
- static void
- Ins_SROUND( INS_ARG )
- {
- DO_SROUND
- }
-
-
- /*************************************************************************/
- /* */
- /* S45ROUND[]: Super ROUND 45 degrees */
- /* Opcode range: 0x77 */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_S45ROUND( INS_ARG )
- {
- DO_S45ROUND
- }
-
-
- /*************************************************************************/
- /* */
- /* SLOOP[]: Set LOOP variable */
- /* Opcode range: 0x17 */
- /* Stack: int32? --> */
- /* */
- static void
- Ins_SLOOP( INS_ARG )
- {
- DO_SLOOP
- }
-
-
- /*************************************************************************/
- /* */
- /* SMD[]: Set Minimum Distance */
- /* Opcode range: 0x1A */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SMD( INS_ARG )
- {
- DO_SMD
- }
-
-
- /*************************************************************************/
- /* */
- /* SCVTCI[]: Set Control Value Table Cut In */
- /* Opcode range: 0x1D */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SCVTCI( INS_ARG )
- {
- DO_SCVTCI
- }
-
-
- /*************************************************************************/
- /* */
- /* SSWCI[]: Set Single Width Cut In */
- /* Opcode range: 0x1E */
- /* Stack: f26.6 --> */
- /* */
- static void
- Ins_SSWCI( INS_ARG )
- {
- DO_SSWCI
- }
-
-
- /*************************************************************************/
- /* */
- /* SSW[]: Set Single Width */
- /* Opcode range: 0x1F */
- /* Stack: int32? --> */
- /* */
- static void
- Ins_SSW( INS_ARG )
- {
- DO_SSW
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPON[]: Set auto-FLIP to ON */
- /* Opcode range: 0x4D */
- /* Stack: --> */
- /* */
- static void
- Ins_FLIPON( INS_ARG )
- {
- DO_FLIPON
- }
-
-
- /*************************************************************************/
- /* */
- /* FLIPOFF[]: Set auto-FLIP to OFF */
- /* Opcode range: 0x4E */
- /* Stack: --> */
- /* */
- static void
- Ins_FLIPOFF( INS_ARG )
- {
- DO_FLIPOFF
- }
-
-
- /*************************************************************************/
- /* */
- /* SANGW[]: Set ANGle Weight */
- /* Opcode range: 0x7E */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SANGW( INS_ARG )
- {
- /* instruction not supported anymore */
- }
-
-
- /*************************************************************************/
- /* */
- /* SDB[]: Set Delta Base */
- /* Opcode range: 0x5E */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SDB( INS_ARG )
- {
- DO_SDB
- }
-
-
- /*************************************************************************/
- /* */
- /* SDS[]: Set Delta Shift */
- /* Opcode range: 0x5F */
- /* Stack: uint32 --> */
- /* */
- static void
- Ins_SDS( INS_ARG )
- {
- DO_SDS
- }
+#define ARRAY_BOUND_ERROR \
+ do \
+ { \
+ exc->error = FT_THROW( Invalid_Reference ); \
+ return; \
+ } while (0)
/*************************************************************************/
@@ -3728,9 +2608,10 @@
/* Stack: --> Euint16 */
/* */
static void
- Ins_MPPEM( INS_ARG )
+ Ins_MPPEM( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_MPPEM
+ args[0] = exc->func_cur_ppem( exc );
}
@@ -3741,22 +2622,29 @@
/* Stack: --> Euint16 */
/* */
static void
- Ins_MPS( INS_ARG )
+ Ins_MPS( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_MPS
+ /* Note: The point size should be irrelevant in a given font program; */
+ /* we thus decide to return only the PPEM value. */
+#if 0
+ args[0] = exc->metrics.pointSize;
+#else
+ args[0] = exc->func_cur_ppem( exc );
+#endif
}
/*************************************************************************/
/* */
- /* DUP[]: DUPlicate the top stack's element */
+ /* DUP[]: DUPlicate the stack's top element */
/* Opcode range: 0x20 */
/* Stack: StkElt --> StkElt StkElt */
/* */
static void
- Ins_DUP( INS_ARG )
+ Ins_DUP( FT_Long* args )
{
- DO_DUP
+ args[1] = args[0];
}
@@ -3767,7 +2655,7 @@
/* Stack: StkElt --> */
/* */
static void
- Ins_POP( INS_ARG )
+ Ins_POP( void )
{
/* nothing to do */
}
@@ -3780,9 +2668,9 @@
/* Stack: StkElt... --> */
/* */
static void
- Ins_CLEAR( INS_ARG )
+ Ins_CLEAR( TT_ExecContext exc )
{
- DO_CLEAR
+ exc->new_top = 0;
}
@@ -3793,9 +2681,14 @@
/* Stack: 2 * StkElt --> 2 * StkElt */
/* */
static void
- Ins_SWAP( INS_ARG )
+ Ins_SWAP( FT_Long* args )
{
- DO_SWAP
+ FT_Long L;
+
+
+ L = args[0];
+ args[0] = args[1];
+ args[1] = L;
}
@@ -3806,74 +2699,10 @@
/* Stack: --> uint32 */
/* */
static void
- Ins_DEPTH( INS_ARG )
+ Ins_DEPTH( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_DEPTH
- }
-
-
- /*************************************************************************/
- /* */
- /* CINDEX[]: Copy INDEXed element */
- /* Opcode range: 0x25 */
- /* Stack: int32 --> StkElt */
- /* */
- static void
- Ins_CINDEX( INS_ARG )
- {
- DO_CINDEX
- }
-
-
- /*************************************************************************/
- /* */
- /* EIF[]: End IF */
- /* Opcode range: 0x59 */
- /* Stack: --> */
- /* */
- static void
- Ins_EIF( INS_ARG )
- {
- /* nothing to do */
- }
-
-
- /*************************************************************************/
- /* */
- /* JROT[]: Jump Relative On True */
- /* Opcode range: 0x78 */
- /* Stack: StkElt int32 --> */
- /* */
- static void
- Ins_JROT( INS_ARG )
- {
- DO_JROT
- }
-
-
- /*************************************************************************/
- /* */
- /* JMPR[]: JuMP Relative */
- /* Opcode range: 0x1C */
- /* Stack: int32 --> */
- /* */
- static void
- Ins_JMPR( INS_ARG )
- {
- DO_JMPR
- }
-
-
- /*************************************************************************/
- /* */
- /* JROF[]: Jump Relative On False */
- /* Opcode range: 0x79 */
- /* Stack: StkElt int32 --> */
- /* */
- static void
- Ins_JROF( INS_ARG )
- {
- DO_JROF
+ args[0] = exc->top;
}
@@ -3884,9 +2713,9 @@
/* Stack: int32? int32? --> bool */
/* */
static void
- Ins_LT( INS_ARG )
+ Ins_LT( FT_Long* args )
{
- DO_LT
+ args[0] = ( args[0] < args[1] );
}
@@ -3897,9 +2726,9 @@
/* Stack: int32? int32? --> bool */
/* */
static void
- Ins_LTEQ( INS_ARG )
+ Ins_LTEQ( FT_Long* args )
{
- DO_LTEQ
+ args[0] = ( args[0] <= args[1] );
}
@@ -3910,9 +2739,9 @@
/* Stack: int32? int32? --> bool */
/* */
static void
- Ins_GT( INS_ARG )
+ Ins_GT( FT_Long* args )
{
- DO_GT
+ args[0] = ( args[0] > args[1] );
}
@@ -3923,9 +2752,9 @@
/* Stack: int32? int32? --> bool */
/* */
static void
- Ins_GTEQ( INS_ARG )
+ Ins_GTEQ( FT_Long* args )
{
- DO_GTEQ
+ args[0] = ( args[0] >= args[1] );
}
@@ -3936,9 +2765,9 @@
/* Stack: StkElt StkElt --> bool */
/* */
static void
- Ins_EQ( INS_ARG )
+ Ins_EQ( FT_Long* args )
{
- DO_EQ
+ args[0] = ( args[0] == args[1] );
}
@@ -3949,9 +2778,9 @@
/* Stack: StkElt StkElt --> bool */
/* */
static void
- Ins_NEQ( INS_ARG )
+ Ins_NEQ( FT_Long* args )
{
- DO_NEQ
+ args[0] = ( args[0] != args[1] );
}
@@ -3962,9 +2791,10 @@
/* Stack: f26.6 --> bool */
/* */
static void
- Ins_ODD( INS_ARG )
+ Ins_ODD( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_ODD
+ args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 64 );
}
@@ -3975,9 +2805,10 @@
/* Stack: f26.6 --> bool */
/* */
static void
- Ins_EVEN( INS_ARG )
+ Ins_EVEN( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_EVEN
+ args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 127 ) == 0 );
}
@@ -3988,9 +2819,9 @@
/* Stack: uint32 uint32 --> uint32 */
/* */
static void
- Ins_AND( INS_ARG )
+ Ins_AND( FT_Long* args )
{
- DO_AND
+ args[0] = ( args[0] && args[1] );
}
@@ -4001,9 +2832,9 @@
/* Stack: uint32 uint32 --> uint32 */
/* */
static void
- Ins_OR( INS_ARG )
+ Ins_OR( FT_Long* args )
{
- DO_OR
+ args[0] = ( args[0] || args[1] );
}
@@ -4014,9 +2845,9 @@
/* Stack: StkElt --> uint32 */
/* */
static void
- Ins_NOT( INS_ARG )
+ Ins_NOT( FT_Long* args )
{
- DO_NOT
+ args[0] = !args[0];
}
@@ -4027,9 +2858,9 @@
/* Stack: f26.6 f26.6 --> f26.6 */
/* */
static void
- Ins_ADD( INS_ARG )
+ Ins_ADD( FT_Long* args )
{
- DO_ADD
+ args[0] += args[1];
}
@@ -4040,9 +2871,9 @@
/* Stack: f26.6 f26.6 --> f26.6 */
/* */
static void
- Ins_SUB( INS_ARG )
+ Ins_SUB( FT_Long* args )
{
- DO_SUB
+ args[0] -= args[1];
}
@@ -4053,9 +2884,13 @@
/* Stack: f26.6 f26.6 --> f26.6 */
/* */
static void
- Ins_DIV( INS_ARG )
+ Ins_DIV( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_DIV
+ if ( args[1] == 0 )
+ exc->error = FT_THROW( Divide_By_Zero );
+ else
+ args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
}
@@ -4066,9 +2901,9 @@
/* Stack: f26.6 f26.6 --> f26.6 */
/* */
static void
- Ins_MUL( INS_ARG )
+ Ins_MUL( FT_Long* args )
{
- DO_MUL
+ args[0] = FT_MulDiv( args[0], args[1], 64L );
}
@@ -4079,9 +2914,9 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_ABS( INS_ARG )
+ Ins_ABS( FT_Long* args )
{
- DO_ABS
+ args[0] = FT_ABS( args[0] );
}
@@ -4092,9 +2927,9 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_NEG( INS_ARG )
+ Ins_NEG( FT_Long* args )
{
- DO_NEG
+ args[0] = -args[0];
}
@@ -4105,9 +2940,9 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_FLOOR( INS_ARG )
+ Ins_FLOOR( FT_Long* args )
{
- DO_FLOOR
+ args[0] = FT_PIX_FLOOR( args[0] );
}
@@ -4118,9 +2953,9 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_CEILING( INS_ARG )
+ Ins_CEILING( FT_Long* args )
{
- DO_CEILING
+ args[0] = FT_PIX_CEIL( args[0] );
}
@@ -4131,9 +2966,59 @@
/* Stack: uint32 --> uint32 */
/* */
static void
- Ins_RS( INS_ARG )
+ Ins_RS( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_RS
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->storeSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ else
+ args[0] = 0;
+ }
+ else
+ {
+ /* subpixel hinting - avoid Typeman Dstroke and */
+ /* IStroke and Vacuform rounds */
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ ( ( I == 24 &&
+ ( exc->face->sph_found_func_flags &
+ ( SPH_FDEF_SPACING_1 |
+ SPH_FDEF_SPACING_2 ) ) ) ||
+ ( I == 22 &&
+ ( exc->sph_in_func_flags &
+ SPH_FDEF_TYPEMAN_STROKES ) ) ||
+ ( I == 8 &&
+ ( exc->face->sph_found_func_flags &
+ SPH_FDEF_VACUFORM_ROUND_1 ) &&
+ exc->iup_called ) ) )
+ args[0] = 0;
+ else
+ args[0] = exc->storage[I];
+ }
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->storeSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ else
+ args[0] = 0;
+ }
+ else
+ args[0] = exc->storage[I];
+
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
}
@@ -4144,9 +3029,19 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_WS( INS_ARG )
+ Ins_WS( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_WS
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->storeSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ }
+ else
+ exc->storage[I] = args[1];
}
@@ -4157,9 +3052,19 @@
/* Stack: f26.6 uint32 --> */
/* */
static void
- Ins_WCVTP( INS_ARG )
+ Ins_WCVTP( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_WCVTP
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->cvtSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ }
+ else
+ exc->func_write_cvt( exc, I, args[1] );
}
@@ -4170,9 +3075,19 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_WCVTF( INS_ARG )
+ Ins_WCVTF( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_WCVTF
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->cvtSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ }
+ else
+ exc->cvt[I] = FT_MulFix( args[1], exc->tt_metrics.scale );
}
@@ -4183,9 +3098,21 @@
/* Stack: uint32 --> f26.6 */
/* */
static void
- Ins_RCVT( INS_ARG )
+ Ins_RCVT( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_RCVT
+ FT_ULong I = (FT_ULong)args[0];
+
+
+ if ( BOUNDSL( I, exc->cvtSize ) )
+ {
+ if ( exc->pedantic_hinting )
+ ARRAY_BOUND_ERROR;
+ else
+ args[0] = 0;
+ }
+ else
+ args[0] = exc->func_read_cvt( exc, I );
}
@@ -4196,7 +3123,7 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_AA( INS_ARG )
+ Ins_AA( void )
{
/* intentionally no longer supported */
}
@@ -4211,9 +3138,9 @@
/* Note: The original instruction pops a value from the stack. */
/* */
static void
- Ins_DEBUG( INS_ARG )
+ Ins_DEBUG( TT_ExecContext exc )
{
- DO_DEBUG
+ exc->error = FT_THROW( Debug_OpCode );
}
@@ -4224,9 +3151,13 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_ROUND( INS_ARG )
+ Ins_ROUND( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_ROUND
+ args[0] = exc->func_round(
+ exc,
+ args[0],
+ exc->tt_metrics.compensations[exc->opcode - 0x68] );
}
@@ -4237,9 +3168,13 @@
/* Stack: f26.6 --> f26.6 */
/* */
static void
- Ins_NROUND( INS_ARG )
+ Ins_NROUND( TT_ExecContext exc,
+ FT_Long* args )
{
- DO_NROUND
+ args[0] = Round_None(
+ exc,
+ args[0],
+ exc->tt_metrics.compensations[exc->opcode - 0x6C] );
}
@@ -4250,9 +3185,10 @@
/* Stack: int32? int32? --> int32 */
/* */
static void
- Ins_MAX( INS_ARG )
+ Ins_MAX( FT_Long* args )
{
- DO_MAX
+ if ( args[1] > args[0] )
+ args[0] = args[1];
}
@@ -4263,22 +3199,13 @@
/* Stack: int32? int32? --> int32 */
/* */
static void
- Ins_MIN( INS_ARG )
+ Ins_MIN( FT_Long* args )
{
- DO_MIN
+ if ( args[1] < args[0] )
+ args[0] = args[1];
}
-#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
- /*************************************************************************/
- /* */
- /* The following functions are called as is within the switch statement. */
- /* */
- /*************************************************************************/
-
-
/*************************************************************************/
/* */
/* MINDEX[]: Move INDEXed element */
@@ -4286,44 +3213,69 @@
/* Stack: int32? --> StkElt */
/* */
static void
- Ins_MINDEX( INS_ARG )
+ Ins_MINDEX( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Long L, K;
L = args[0];
- if ( L <= 0 || L > CUR.args )
+ if ( L <= 0 || L > exc->args )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
}
else
{
- K = CUR.stack[CUR.args - L];
+ K = exc->stack[exc->args - L];
- FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
- &CUR.stack[CUR.args - L + 1],
+ FT_ARRAY_MOVE( &exc->stack[exc->args - L ],
+ &exc->stack[exc->args - L + 1],
( L - 1 ) );
- CUR.stack[CUR.args - 1] = K;
+ exc->stack[exc->args - 1] = K;
}
}
/*************************************************************************/
/* */
+ /* CINDEX[]: Copy INDEXed element */
+ /* Opcode range: 0x25 */
+ /* Stack: int32 --> StkElt */
+ /* */
+ static void
+ Ins_CINDEX( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ FT_Long L;
+
+
+ L = args[0];
+
+ if ( L <= 0 || L > exc->args )
+ {
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
+ args[0] = 0;
+ }
+ else
+ args[0] = exc->stack[exc->args - L];
+ }
+
+
+ /*************************************************************************/
+ /* */
/* ROLL[]: ROLL top three elements */
/* Opcode range: 0x8A */
/* Stack: 3 * StkElt --> 3 * StkElt */
/* */
static void
- Ins_ROLL( INS_ARG )
+ Ins_ROLL( FT_Long* args )
{
FT_Long A, B, C;
- FT_UNUSED_EXEC;
-
A = args[2];
B = args[1];
@@ -4339,34 +3291,49 @@
/* */
/* MANAGING THE FLOW OF CONTROL */
/* */
- /* Instructions appear in the specification's order. */
- /* */
/*************************************************************************/
- static FT_Bool
- SkipCode( EXEC_OP )
+ /*************************************************************************/
+ /* */
+ /* SLOOP[]: Set LOOP variable */
+ /* Opcode range: 0x17 */
+ /* Stack: int32? --> */
+ /* */
+ static void
+ Ins_SLOOP( TT_ExecContext exc,
+ FT_Long* args )
{
- CUR.IP += CUR.length;
+ if ( args[0] < 0 )
+ exc->error = FT_THROW( Bad_Argument );
+ else
+ exc->GS.loop = args[0];
+ }
- if ( CUR.IP < CUR.codeSize )
+
+ static FT_Bool
+ SkipCode( TT_ExecContext exc )
+ {
+ exc->IP += exc->length;
+
+ if ( exc->IP < exc->codeSize )
{
- CUR.opcode = CUR.code[CUR.IP];
+ exc->opcode = exc->code[exc->IP];
- CUR.length = opcode_length[CUR.opcode];
- if ( CUR.length < 0 )
+ exc->length = opcode_length[exc->opcode];
+ if ( exc->length < 0 )
{
- if ( CUR.IP + 1 >= CUR.codeSize )
+ if ( exc->IP + 1 >= exc->codeSize )
goto Fail_Overflow;
- CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+ exc->length = 2 - exc->length * exc->code[exc->IP + 1];
}
- if ( CUR.IP + CUR.length <= CUR.codeSize )
+ if ( exc->IP + exc->length <= exc->codeSize )
return SUCCESS;
}
Fail_Overflow:
- CUR.error = FT_THROW( Code_Overflow );
+ exc->error = FT_THROW( Code_Overflow );
return FAILURE;
}
@@ -4378,7 +3345,8 @@
/* Stack: StkElt --> */
/* */
static void
- Ins_IF( INS_ARG )
+ Ins_IF( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Int nIfs;
FT_Bool Out;
@@ -4392,10 +3360,10 @@
do
{
- if ( SKIP_Code() == FAILURE )
+ if ( SkipCode( exc ) == FAILURE )
return;
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x58: /* IF */
nIfs++;
@@ -4421,21 +3389,19 @@
/* Stack: --> */
/* */
static void
- Ins_ELSE( INS_ARG )
+ Ins_ELSE( TT_ExecContext exc )
{
FT_Int nIfs;
- FT_UNUSED_ARG;
-
nIfs = 1;
do
{
- if ( SKIP_Code() == FAILURE )
+ if ( SkipCode( exc ) == FAILURE )
return;
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x58: /* IF */
nIfs++;
@@ -4451,9 +3417,71 @@
/*************************************************************************/
/* */
- /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
+ /* EIF[]: End IF */
+ /* Opcode range: 0x59 */
+ /* Stack: --> */
/* */
- /* Instructions appear in the specification's order. */
+ static void
+ Ins_EIF( void )
+ {
+ /* nothing to do */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JMPR[]: JuMP Relative */
+ /* Opcode range: 0x1C */
+ /* Stack: int32 --> */
+ /* */
+ static void
+ Ins_JMPR( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( args[0] == 0 && exc->args == 0 )
+ exc->error = FT_THROW( Bad_Argument );
+ exc->IP += args[0];
+ if ( exc->IP < 0 ||
+ ( exc->callTop > 0 &&
+ exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
+ exc->error = FT_THROW( Bad_Argument );
+ exc->step_ins = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROT[]: Jump Relative On True */
+ /* Opcode range: 0x78 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static void
+ Ins_JROT( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( args[1] != 0 )
+ Ins_JMPR( exc, args );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* JROF[]: Jump Relative On False */
+ /* Opcode range: 0x79 */
+ /* Stack: StkElt int32 --> */
+ /* */
+ static void
+ Ins_JROF( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( args[1] == 0 )
+ Ins_JMPR( exc, args );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */
/* */
/*************************************************************************/
@@ -4465,7 +3493,8 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_FDEF( INS_ARG )
+ Ins_FDEF( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong n;
TT_DefRecord* rec;
@@ -4575,9 +3604,9 @@
/* some font programs are broken enough to redefine functions! */
/* We will then parse the current table. */
- rec = CUR.FDefs;
- limit = rec + CUR.numFDefs;
- n = args[0];
+ rec = exc->FDefs;
+ limit = rec + exc->numFDefs;
+ n = (FT_ULong)args[0];
for ( ; rec < limit; rec++ )
{
@@ -4588,31 +3617,31 @@
if ( rec == limit )
{
/* check that there is enough room for new functions */
- if ( CUR.numFDefs >= CUR.maxFDefs )
+ if ( exc->numFDefs >= exc->maxFDefs )
{
- CUR.error = FT_THROW( Too_Many_Function_Defs );
+ exc->error = FT_THROW( Too_Many_Function_Defs );
return;
}
- CUR.numFDefs++;
+ exc->numFDefs++;
}
/* Although FDEF takes unsigned 32-bit integer, */
/* func # must be within unsigned 16-bit integer */
if ( n > 0xFFFFU )
{
- CUR.error = FT_THROW( Too_Many_Function_Defs );
+ exc->error = FT_THROW( Too_Many_Function_Defs );
return;
}
- rec->range = CUR.curRange;
+ rec->range = exc->curRange;
rec->opc = (FT_UInt16)n;
- rec->start = CUR.IP + 1;
+ rec->start = exc->IP + 1;
rec->active = TRUE;
rec->inline_delta = FALSE;
rec->sph_fdef_flags = 0x0000;
- if ( n > CUR.maxFunc )
- CUR.maxFunc = (FT_UInt16)n;
+ if ( n > exc->maxFunc )
+ exc->maxFunc = (FT_UInt16)n;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* We don't know for sure these are typeman functions, */
@@ -4624,7 +3653,7 @@
/* Now skip the whole function definition. */
/* We don't allow nested IDEFS & FDEFs. */
- while ( SKIP_Code() == SUCCESS )
+ while ( SkipCode( exc ) == SUCCESS )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
@@ -4633,28 +3662,28 @@
{
for ( i = 0; i < opcode_patterns; i++ )
{
- if ( opcode_pointer[i] < opcode_size[i] &&
- CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+ if ( opcode_pointer[i] < opcode_size[i] &&
+ exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
{
opcode_pointer[i] += 1;
if ( opcode_pointer[i] == opcode_size[i] )
{
- FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
+ FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
i, n,
- CUR.face->root.family_name,
- CUR.face->root.style_name ));
+ exc->face->root.family_name,
+ exc->face->root.style_name ));
switch ( i )
{
case 0:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
+ rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_1;
+ exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
break;
case 1:
- rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
- CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
+ rec->sph_fdef_flags |= SPH_FDEF_INLINE_DELTA_2;
+ exc->face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
break;
case 2:
@@ -4662,8 +3691,8 @@
{
/* needs to be implemented still */
case 58:
- rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
- CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
+ rec->sph_fdef_flags |= SPH_FDEF_DIAGONAL_STROKE;
+ exc->face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
}
break;
@@ -4671,15 +3700,15 @@
switch ( n )
{
case 0:
- rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+ rec->sph_fdef_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+ exc->face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
}
break;
case 4:
/* probably not necessary to detect anymore */
- rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
+ rec->sph_fdef_flags |= SPH_FDEF_TTFAUTOHINT_1;
+ exc->face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
break;
case 5:
@@ -4691,8 +3720,8 @@
case 4:
case 7:
case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
- CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
+ rec->sph_fdef_flags |= SPH_FDEF_SPACING_1;
+ exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
}
break;
@@ -4705,20 +3734,20 @@
case 4:
case 7:
case 8:
- rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
- CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
+ rec->sph_fdef_flags |= SPH_FDEF_SPACING_2;
+ exc->face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
}
break;
case 7:
- rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
- CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+ rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+ exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
break;
case 8:
#if 0
- rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
- CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+ rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+ exc->face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
#endif
break;
}
@@ -4731,22 +3760,22 @@
}
/* Set sph_compatibility_mode only when deltas are detected */
- CUR.face->sph_compatibility_mode =
- ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
- ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
+ exc->face->sph_compatibility_mode =
+ ( ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
+ ( exc->face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x89: /* IDEF */
case 0x2C: /* FDEF */
- CUR.error = FT_THROW( Nested_DEFS );
+ exc->error = FT_THROW( Nested_DEFS );
return;
case 0x2D: /* ENDF */
- rec->end = CUR.IP;
+ rec->end = exc->IP;
return;
}
}
@@ -4760,40 +3789,37 @@
/* Stack: --> */
/* */
static void
- Ins_ENDF( INS_ARG )
+ Ins_ENDF( TT_ExecContext exc )
{
TT_CallRec* pRec;
- FT_UNUSED_ARG;
-
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- CUR.sph_in_func_flags = 0x0000;
+ exc->sph_in_func_flags = 0x0000;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */
+ if ( exc->callTop <= 0 ) /* We encountered an ENDF without a call */
{
- CUR.error = FT_THROW( ENDF_In_Exec_Stream );
+ exc->error = FT_THROW( ENDF_In_Exec_Stream );
return;
}
- CUR.callTop--;
+ exc->callTop--;
- pRec = &CUR.callStack[CUR.callTop];
+ pRec = &exc->callStack[exc->callTop];
pRec->Cur_Count--;
- CUR.step_ins = FALSE;
+ exc->step_ins = FALSE;
if ( pRec->Cur_Count > 0 )
{
- CUR.callTop++;
- CUR.IP = pRec->Cur_Restart;
+ exc->callTop++;
+ exc->IP = pRec->Def->start;
}
else
/* Loop through the current function */
- INS_Goto_CodeRange( pRec->Caller_Range,
- pRec->Caller_IP );
+ Ins_Goto_CodeRange( exc, pRec->Caller_Range, pRec->Caller_IP );
/* Exit the current call frame. */
@@ -4812,7 +3838,8 @@
/* Stack: uint32? --> */
/* */
static void
- Ins_CALL( INS_ARG )
+ Ins_CALL( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong F;
TT_CallRec* pCrec;
@@ -4821,28 +3848,28 @@
/* first of all, check the index */
- F = args[0];
- if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
+ F = (FT_ULong)args[0];
+ if ( BOUNDSL( F, exc->maxFunc + 1 ) )
goto Fail;
/* Except for some old Apple fonts, all functions in a TrueType */
/* font are defined in increasing order, starting from 0. This */
/* means that we normally have */
/* */
- /* CUR.maxFunc+1 == CUR.numFDefs */
- /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* exc->maxFunc+1 == exc->numFDefs */
+ /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */
/* */
/* If this isn't true, we need to look up the function table. */
- def = CUR.FDefs + F;
- if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ def = exc->FDefs + F;
+ if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
{
/* look up the FDefs table */
TT_DefRecord* limit;
- def = CUR.FDefs;
- limit = def + CUR.numFDefs;
+ def = exc->FDefs;
+ limit = def + exc->numFDefs;
while ( def < limit && def->opc != F )
def++;
@@ -4856,42 +3883,40 @@
goto Fail;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- ( ( CUR.iup_called &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
- ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ ( ( exc->iup_called &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
+ ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) ) )
goto Fail;
else
- CUR.sph_in_func_flags = def->sph_fdef_flags;
+ exc->sph_in_func_flags = def->sph_fdef_flags;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* check the call stack */
- if ( CUR.callTop >= CUR.callSize )
+ if ( exc->callTop >= exc->callSize )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
- pCrec = CUR.callStack + CUR.callTop;
+ pCrec = exc->callStack + exc->callTop;
- pCrec->Caller_Range = CUR.curRange;
- pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Caller_Range = exc->curRange;
+ pCrec->Caller_IP = exc->IP + 1;
pCrec->Cur_Count = 1;
- pCrec->Cur_Restart = def->start;
- pCrec->Cur_End = def->end;
+ pCrec->Def = def;
- CUR.callTop++;
+ exc->callTop++;
- INS_Goto_CodeRange( def->range,
- def->start );
+ Ins_Goto_CodeRange( exc, def->range, def->start );
- CUR.step_ins = FALSE;
+ exc->step_ins = FALSE;
return;
Fail:
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
}
@@ -4902,7 +3927,8 @@
/* Stack: uint32? Eint16? --> */
/* */
static void
- Ins_LOOPCALL( INS_ARG )
+ Ins_LOOPCALL( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong F;
TT_CallRec* pCrec;
@@ -4910,28 +3936,28 @@
/* first of all, check the index */
- F = args[1];
- if ( BOUNDSL( F, CUR.maxFunc + 1 ) )
+ F = (FT_ULong)args[1];
+ if ( BOUNDSL( F, exc->maxFunc + 1 ) )
goto Fail;
/* Except for some old Apple fonts, all functions in a TrueType */
/* font are defined in increasing order, starting from 0. This */
/* means that we normally have */
/* */
- /* CUR.maxFunc+1 == CUR.numFDefs */
- /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */
+ /* exc->maxFunc+1 == exc->numFDefs */
+ /* exc->FDefs[n].opc == n for n in 0..exc->maxFunc */
/* */
/* If this isn't true, we need to look up the function table. */
- def = CUR.FDefs + F;
- if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+ def = exc->FDefs + F;
+ if ( exc->maxFunc + 1 != exc->numFDefs || def->opc != F )
{
/* look up the FDefs table */
TT_DefRecord* limit;
- def = CUR.FDefs;
- limit = def + CUR.numFDefs;
+ def = exc->FDefs;
+ limit = def + exc->numFDefs;
while ( def < limit && def->opc != F )
def++;
@@ -4946,41 +3972,40 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
+ exc->ignore_x_mode &&
( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
goto Fail;
else
- CUR.sph_in_func_flags = def->sph_fdef_flags;
+ exc->sph_in_func_flags = def->sph_fdef_flags;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* check stack */
- if ( CUR.callTop >= CUR.callSize )
+ if ( exc->callTop >= exc->callSize )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
if ( args[0] > 0 )
{
- pCrec = CUR.callStack + CUR.callTop;
+ pCrec = exc->callStack + exc->callTop;
- pCrec->Caller_Range = CUR.curRange;
- pCrec->Caller_IP = CUR.IP + 1;
+ pCrec->Caller_Range = exc->curRange;
+ pCrec->Caller_IP = exc->IP + 1;
pCrec->Cur_Count = (FT_Int)args[0];
- pCrec->Cur_Restart = def->start;
- pCrec->Cur_End = def->end;
+ pCrec->Def = def;
- CUR.callTop++;
+ exc->callTop++;
- INS_Goto_CodeRange( def->range, def->start );
+ Ins_Goto_CodeRange( exc, def->range, def->start );
- CUR.step_ins = FALSE;
+ exc->step_ins = FALSE;
}
return;
Fail:
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
}
@@ -4991,7 +4016,8 @@
/* Stack: Eint8 --> */
/* */
static void
- Ins_IDEF( INS_ARG )
+ Ins_IDEF( TT_ExecContext exc,
+ FT_Long* args )
{
TT_DefRecord* def;
TT_DefRecord* limit;
@@ -4999,8 +4025,8 @@
/* First of all, look for the same function in our table */
- def = CUR.IDefs;
- limit = def + CUR.numIDefs;
+ def = exc->IDefs;
+ limit = def + exc->numIDefs;
for ( ; def < limit; def++ )
if ( def->opc == (FT_ULong)args[0] )
@@ -5009,39 +4035,39 @@
if ( def == limit )
{
/* check that there is enough room for a new instruction */
- if ( CUR.numIDefs >= CUR.maxIDefs )
+ if ( exc->numIDefs >= exc->maxIDefs )
{
- CUR.error = FT_THROW( Too_Many_Instruction_Defs );
+ exc->error = FT_THROW( Too_Many_Instruction_Defs );
return;
}
- CUR.numIDefs++;
+ exc->numIDefs++;
}
/* opcode must be unsigned 8-bit integer */
if ( 0 > args[0] || args[0] > 0x00FF )
{
- CUR.error = FT_THROW( Too_Many_Instruction_Defs );
+ exc->error = FT_THROW( Too_Many_Instruction_Defs );
return;
}
def->opc = (FT_Byte)args[0];
- def->start = CUR.IP + 1;
- def->range = CUR.curRange;
+ def->start = exc->IP + 1;
+ def->range = exc->curRange;
def->active = TRUE;
- if ( (FT_ULong)args[0] > CUR.maxIns )
- CUR.maxIns = (FT_Byte)args[0];
+ if ( (FT_ULong)args[0] > exc->maxIns )
+ exc->maxIns = (FT_Byte)args[0];
/* Now skip the whole function definition. */
/* We don't allow nested IDEFs & FDEFs. */
- while ( SKIP_Code() == SUCCESS )
+ while ( SkipCode( exc ) == SUCCESS )
{
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x89: /* IDEF */
case 0x2C: /* FDEF */
- CUR.error = FT_THROW( Nested_DEFS );
+ exc->error = FT_THROW( Nested_DEFS );
return;
case 0x2D: /* ENDF */
return;
@@ -5054,8 +4080,6 @@
/* */
/* PUSHING DATA ONTO THE INTERPRETER STACK */
/* */
- /* Instructions appear in the specification's order. */
- /* */
/*************************************************************************/
@@ -5066,23 +4090,24 @@
/* Stack: --> uint32... */
/* */
static void
- Ins_NPUSHB( INS_ARG )
+ Ins_NPUSHB( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort L, K;
- L = (FT_UShort)CUR.code[CUR.IP + 1];
+ L = (FT_UShort)exc->code[exc->IP + 1];
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
for ( K = 1; K <= L; K++ )
- args[K - 1] = CUR.code[CUR.IP + K + 1];
+ args[K - 1] = exc->code[exc->IP + K + 1];
- CUR.new_top += L;
+ exc->new_top += L;
}
@@ -5093,26 +4118,27 @@
/* Stack: --> int32... */
/* */
static void
- Ins_NPUSHW( INS_ARG )
+ Ins_NPUSHW( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort L, K;
- L = (FT_UShort)CUR.code[CUR.IP + 1];
+ L = (FT_UShort)exc->code[exc->IP + 1];
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
- CUR.IP += 2;
+ exc->IP += 2;
for ( K = 0; K < L; K++ )
- args[K] = GET_ShortIns();
+ args[K] = GetShortIns( exc );
- CUR.step_ins = FALSE;
- CUR.new_top += L;
+ exc->step_ins = FALSE;
+ exc->new_top += L;
}
@@ -5123,21 +4149,22 @@
/* Stack: --> uint32... */
/* */
static void
- Ins_PUSHB( INS_ARG )
+ Ins_PUSHB( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort L, K;
- L = (FT_UShort)( CUR.opcode - 0xB0 + 1 );
+ L = (FT_UShort)( exc->opcode - 0xB0 + 1 );
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
for ( K = 1; K <= L; K++ )
- args[K - 1] = CUR.code[CUR.IP + K];
+ args[K - 1] = exc->code[exc->IP + K];
}
@@ -5148,25 +4175,26 @@
/* Stack: --> int32... */
/* */
static void
- Ins_PUSHW( INS_ARG )
+ Ins_PUSHW( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort L, K;
- L = (FT_UShort)( CUR.opcode - 0xB8 + 1 );
+ L = (FT_UShort)( exc->opcode - 0xB8 + 1 );
- if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+ if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
- CUR.IP++;
+ exc->IP++;
for ( K = 0; K < L; K++ )
- args[K] = GET_ShortIns();
+ args[K] = GetShortIns( exc );
- CUR.step_ins = FALSE;
+ exc->step_ins = FALSE;
}
@@ -5174,11 +4202,561 @@
/* */
/* MANAGING THE GRAPHICS STATE */
/* */
- /* Instructions appear in the specs' order. */
- /* */
/*************************************************************************/
+ static FT_Bool
+ Ins_SxVTL( TT_ExecContext exc,
+ FT_UShort aIdx1,
+ FT_UShort aIdx2,
+ FT_UnitVector* Vec )
+ {
+ FT_Long A, B, C;
+ FT_Vector* p1;
+ FT_Vector* p2;
+
+ FT_Byte opcode = exc->opcode;
+
+
+ if ( BOUNDS( aIdx1, exc->zp2.n_points ) ||
+ BOUNDS( aIdx2, exc->zp1.n_points ) )
+ {
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
+ return FAILURE;
+ }
+
+ p1 = exc->zp1.cur + aIdx2;
+ p2 = exc->zp2.cur + aIdx1;
+
+ A = p1->x - p2->x;
+ B = p1->y - p2->y;
+
+ /* If p1 == p2, SPvTL and SFvTL behave the same as */
+ /* SPvTCA[X] and SFvTCA[X], respectively. */
+ /* */
+ /* Confirmed by Greg Hitchcock. */
+
+ if ( A == 0 && B == 0 )
+ {
+ A = 0x4000;
+ opcode = 0;
+ }
+
+ if ( ( opcode & 1 ) != 0 )
+ {
+ C = B; /* counter clockwise rotation */
+ B = A;
+ A = -C;
+ }
+
+ Normalize( A, B, Vec );
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */
+ /* Opcode range: 0x00-0x01 */
+ /* Stack: --> */
+ /* */
+ /* SPvTCA[a]: Set PVector to Coordinate Axis */
+ /* Opcode range: 0x02-0x03 */
+ /* Stack: --> */
+ /* */
+ /* SFvTCA[a]: Set FVector to Coordinate Axis */
+ /* Opcode range: 0x04-0x05 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SxyTCA( TT_ExecContext exc )
+ {
+ FT_Short AA, BB;
+
+ FT_Byte opcode = exc->opcode;
+
+
+ AA = (FT_Short)( ( opcode & 1 ) << 14 );
+ BB = (FT_Short)( AA ^ 0x4000 );
+
+ if ( opcode < 4 )
+ {
+ exc->GS.projVector.x = AA;
+ exc->GS.projVector.y = BB;
+
+ exc->GS.dualVector.x = AA;
+ exc->GS.dualVector.y = BB;
+ }
+ else
+ GUESS_VECTOR( projVector );
+
+ if ( ( opcode & 2 ) == 0 )
+ {
+ exc->GS.freeVector.x = AA;
+ exc->GS.freeVector.y = BB;
+ }
+ else
+ GUESS_VECTOR( freeVector );
+
+ Compute_Funcs( exc );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPvTL[a]: Set PVector To Line */
+ /* Opcode range: 0x06-0x07 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_SPVTL( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( Ins_SxVTL( exc,
+ (FT_UShort)args[1],
+ (FT_UShort)args[0],
+ &exc->GS.projVector ) == SUCCESS )
+ {
+ exc->GS.dualVector = exc->GS.projVector;
+ GUESS_VECTOR( freeVector );
+ Compute_Funcs( exc );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFvTL[a]: Set FVector To Line */
+ /* Opcode range: 0x08-0x09 */
+ /* Stack: uint32 uint32 --> */
+ /* */
+ static void
+ Ins_SFVTL( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( Ins_SxVTL( exc,
+ (FT_UShort)args[1],
+ (FT_UShort)args[0],
+ &exc->GS.freeVector ) == SUCCESS )
+ {
+ GUESS_VECTOR( projVector );
+ Compute_Funcs( exc );
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFvTPv[]: Set FVector To PVector */
+ /* Opcode range: 0x0E */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_SFVTPV( TT_ExecContext exc )
+ {
+ GUESS_VECTOR( projVector );
+ exc->GS.freeVector = exc->GS.projVector;
+ Compute_Funcs( exc );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SPvFS[]: Set PVector From Stack */
+ /* Opcode range: 0x0A */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static void
+ Ins_SPVFS( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ FT_Short S;
+ FT_Long X, Y;
+
+
+ /* Only use low 16bits, then sign extend */
+ S = (FT_Short)args[1];
+ Y = (FT_Long)S;
+ S = (FT_Short)args[0];
+ X = (FT_Long)S;
+
+ Normalize( X, Y, &exc->GS.projVector );
+
+ exc->GS.dualVector = exc->GS.projVector;
+ GUESS_VECTOR( freeVector );
+ Compute_Funcs( exc );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SFvFS[]: Set FVector From Stack */
+ /* Opcode range: 0x0B */
+ /* Stack: f2.14 f2.14 --> */
+ /* */
+ static void
+ Ins_SFVFS( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ FT_Short S;
+ FT_Long X, Y;
+
+
+ /* Only use low 16bits, then sign extend */
+ S = (FT_Short)args[1];
+ Y = (FT_Long)S;
+ S = (FT_Short)args[0];
+ X = S;
+
+ Normalize( X, Y, &exc->GS.freeVector );
+ GUESS_VECTOR( projVector );
+ Compute_Funcs( exc );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GPv[]: Get Projection Vector */
+ /* Opcode range: 0x0C */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static void
+ Ins_GPV( TT_ExecContext exc,
+ FT_Long* args )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( exc->face->unpatented_hinting )
+ {
+ args[0] = exc->GS.both_x_axis ? 0x4000 : 0;
+ args[1] = exc->GS.both_x_axis ? 0 : 0x4000;
+ }
+ else
+ {
+ args[0] = exc->GS.projVector.x;
+ args[1] = exc->GS.projVector.y;
+ }
+#else
+ args[0] = exc->GS.projVector.x;
+ args[1] = exc->GS.projVector.y;
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* GFv[]: Get Freedom Vector */
+ /* Opcode range: 0x0D */
+ /* Stack: ef2.14 --> ef2.14 */
+ /* */
+ static void
+ Ins_GFV( TT_ExecContext exc,
+ FT_Long* args )
+ {
+#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
+ if ( exc->face->unpatented_hinting )
+ {
+ args[0] = exc->GS.both_x_axis ? 0x4000 : 0;
+ args[1] = exc->GS.both_x_axis ? 0 : 0x4000;
+ }
+ else
+ {
+ args[0] = exc->GS.freeVector.x;
+ args[1] = exc->GS.freeVector.y;
+ }
+#else
+ args[0] = exc->GS.freeVector.x;
+ args[1] = exc->GS.freeVector.y;
+#endif
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP0[]: Set Reference Point 0 */
+ /* Opcode range: 0x10 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP0( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.rp0 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP1[]: Set Reference Point 1 */
+ /* Opcode range: 0x11 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP1( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.rp1 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SRP2[]: Set Reference Point 2 */
+ /* Opcode range: 0x12 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SRP2( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.rp2 = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SMD[]: Set Minimum Distance */
+ /* Opcode range: 0x1A */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SMD( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.minimum_distance = args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SCVTCI[]: Set Control Value Table Cut In */
+ /* Opcode range: 0x1D */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SCVTCI( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.control_value_cutin = (FT_F26Dot6)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSWCI[]: Set Single Width Cut In */
+ /* Opcode range: 0x1E */
+ /* Stack: f26.6 --> */
+ /* */
+ static void
+ Ins_SSWCI( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.single_width_cutin = (FT_F26Dot6)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SSW[]: Set Single Width */
+ /* Opcode range: 0x1F */
+ /* Stack: int32? --> */
+ /* */
+ static void
+ Ins_SSW( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.single_width_value = FT_MulFix( args[0],
+ exc->tt_metrics.scale );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPON[]: Set auto-FLIP to ON */
+ /* Opcode range: 0x4D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_FLIPON( TT_ExecContext exc )
+ {
+ exc->GS.auto_flip = TRUE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* FLIPOFF[]: Set auto-FLIP to OFF */
+ /* Opcode range: 0x4E */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_FLIPOFF( TT_ExecContext exc )
+ {
+ exc->GS.auto_flip = FALSE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SANGW[]: Set ANGle Weight */
+ /* Opcode range: 0x7E */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SANGW( void )
+ {
+ /* instruction not supported anymore */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDB[]: Set Delta Base */
+ /* Opcode range: 0x5E */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SDB( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ exc->GS.delta_base = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SDS[]: Set Delta Shift */
+ /* Opcode range: 0x5F */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_SDS( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ if ( (FT_ULong)args[0] > 6UL )
+ exc->error = FT_THROW( Bad_Argument );
+ else
+ exc->GS.delta_shift = (FT_UShort)args[0];
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTHG[]: Round To Half Grid */
+ /* Opcode range: 0x19 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTHG( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_To_Half_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Half_Grid;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RTG[]: Round To Grid */
+ /* Opcode range: 0x18 */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTG( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Grid;
+ }
+
+
+ /*************************************************************************/
+ /* RTDG[]: Round To Double Grid */
+ /* Opcode range: 0x3D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RTDG( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_To_Double_Grid;
+ exc->func_round = (TT_Round_Func)Round_To_Double_Grid;
+ }
+
+
+ /*************************************************************************/
+ /* RUTG[]: Round Up To Grid */
+ /* Opcode range: 0x7C */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RUTG( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_Up_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_Up_To_Grid;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* RDTG[]: Round Down To Grid */
+ /* Opcode range: 0x7D */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_RDTG( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_Down_To_Grid;
+ exc->func_round = (TT_Round_Func)Round_Down_To_Grid;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* ROFF[]: Round OFF */
+ /* Opcode range: 0x7A */
+ /* Stack: --> */
+ /* */
+ static void
+ Ins_ROFF( TT_ExecContext exc )
+ {
+ exc->GS.round_state = TT_Round_Off;
+ exc->func_round = (TT_Round_Func)Round_None;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* SROUND[]: Super ROUND */
+ /* Opcode range: 0x76 */
+ /* Stack: Eint8 --> */
+ /* */
+ static void
+ Ins_SROUND( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ SetSuperRound( exc, 0x4000, args[0] );
+
+ exc->GS.round_state = TT_Round_Super;
+ exc->func_round = (TT_Round_Func)Round_Super;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* S45ROUND[]: Super ROUND 45 degrees */
+ /* Opcode range: 0x77 */
+ /* Stack: uint32 --> */
+ /* */
+ static void
+ Ins_S45ROUND( TT_ExecContext exc,
+ FT_Long* args )
+ {
+ SetSuperRound( exc, 0x2D41, args[0] );
+
+ exc->GS.round_state = TT_Round_Super_45;
+ exc->func_round = (TT_Round_Func)Round_Super_45;
+ }
+
+
/*************************************************************************/
/* */
/* GC[a]: Get Coordinate projected onto */
@@ -5189,7 +4767,8 @@
/* along the dual projection vector! */
/* */
static void
- Ins_GC( INS_ARG )
+ Ins_GC( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong L;
FT_F26Dot6 R;
@@ -5197,18 +4776,18 @@
L = (FT_ULong)args[0];
- if ( BOUNDSL( L, CUR.zp2.n_points ) )
+ if ( BOUNDSL( L, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
R = 0;
}
else
{
- if ( CUR.opcode & 1 )
- R = CUR_fast_dualproj( &CUR.zp2.org[L] );
+ if ( exc->opcode & 1 )
+ R = FAST_DUALPROJ( &exc->zp2.org[L] );
else
- R = CUR_fast_project( &CUR.zp2.cur[L] );
+ R = FAST_PROJECT( &exc->zp2.cur[L] );
}
args[0] = R;
@@ -5226,7 +4805,8 @@
/* OA := OA + ( value - OA.p )/( f.p ) * f */
/* */
static void
- Ins_SCFS( INS_ARG )
+ Ins_SCFS( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Long K;
FT_UShort L;
@@ -5234,21 +4814,21 @@
L = (FT_UShort)args[0];
- if ( BOUNDS( L, CUR.zp2.n_points ) )
+ if ( BOUNDS( L, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- K = CUR_fast_project( &CUR.zp2.cur[L] );
+ K = FAST_PROJECT( &exc->zp2.cur[L] );
- CUR_Func_move( &CUR.zp2, L, args[1] - K );
+ exc->func_move( exc, &exc->zp2, L, args[1] - K );
/* UNDOCUMENTED! The MS rasterizer does that with */
/* twilight points (confirmed by Greg Hitchcock) */
- if ( CUR.GS.gep2 == 0 )
- CUR.zp2.org[L] = CUR.zp2.cur[L];
+ if ( exc->GS.gep2 == 0 )
+ exc->zp2.org[L] = exc->zp2.cur[L];
}
@@ -5268,7 +4848,8 @@
/* XXX: UNDOCUMENTED: `zp0 - zp1', and not `zp2 - zp1! */
/* */
static void
- Ins_MD( INS_ARG )
+ Ins_MD( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort K, L;
FT_F26Dot6 D;
@@ -5277,50 +4858,50 @@
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
- if ( BOUNDS( L, CUR.zp0.n_points ) ||
- BOUNDS( K, CUR.zp1.n_points ) )
+ if ( BOUNDS( L, exc->zp0.n_points ) ||
+ BOUNDS( K, exc->zp1.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
D = 0;
}
else
{
- if ( CUR.opcode & 1 )
- D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+ if ( exc->opcode & 1 )
+ D = PROJECT( exc->zp0.cur + L, exc->zp1.cur + K );
else
{
/* XXX: UNDOCUMENTED: twilight zone special case */
- if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
+ if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
{
- FT_Vector* vec1 = CUR.zp0.org + L;
- FT_Vector* vec2 = CUR.zp1.org + K;
+ FT_Vector* vec1 = exc->zp0.org + L;
+ FT_Vector* vec2 = exc->zp1.org + K;
- D = CUR_Func_dualproj( vec1, vec2 );
+ D = DUALPROJ( vec1, vec2 );
}
else
{
- FT_Vector* vec1 = CUR.zp0.orus + L;
- FT_Vector* vec2 = CUR.zp1.orus + K;
+ FT_Vector* vec1 = exc->zp0.orus + L;
+ FT_Vector* vec2 = exc->zp1.orus + K;
- if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+ if ( exc->metrics.x_scale == exc->metrics.y_scale )
{
/* this should be faster */
- D = CUR_Func_dualproj( vec1, vec2 );
- D = FT_MulFix( D, CUR.metrics.x_scale );
+ D = DUALPROJ( vec1, vec2 );
+ D = FT_MulFix( D, exc->metrics.x_scale );
}
else
{
FT_Vector vec;
- vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
+ vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
+ vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
- D = CUR_fast_dualproj( &vec );
+ D = FAST_DUALPROJ( &vec );
}
}
}
@@ -5328,8 +4909,9 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode && FT_ABS( D ) == 64 )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ FT_ABS( D ) == 64 )
D += 1;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -5339,61 +4921,63 @@
/*************************************************************************/
/* */
- /* SDPVTL[a]: Set Dual PVector to Line */
+ /* SDPvTL[a]: Set Dual PVector to Line */
/* Opcode range: 0x86-0x87 */
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_SDPVTL( INS_ARG )
+ Ins_SDPVTL( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Long A, B, C;
FT_UShort p1, p2; /* was FT_Int in pas type ERROR */
- FT_Int aOpc = CUR.opcode;
+
+ FT_Byte opcode = exc->opcode;
p1 = (FT_UShort)args[1];
p2 = (FT_UShort)args[0];
- if ( BOUNDS( p2, CUR.zp1.n_points ) ||
- BOUNDS( p1, CUR.zp2.n_points ) )
+ if ( BOUNDS( p2, exc->zp1.n_points ) ||
+ BOUNDS( p1, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
{
- FT_Vector* v1 = CUR.zp1.org + p2;
- FT_Vector* v2 = CUR.zp2.org + p1;
+ FT_Vector* v1 = exc->zp1.org + p2;
+ FT_Vector* v2 = exc->zp2.org + p1;
A = v1->x - v2->x;
B = v1->y - v2->y;
- /* If v1 == v2, SDPVTL behaves the same as */
+ /* If v1 == v2, SDPvTL behaves the same as */
/* SVTCA[X], respectively. */
/* */
/* Confirmed by Greg Hitchcock. */
if ( A == 0 && B == 0 )
{
- A = 0x4000;
- aOpc = 0;
+ A = 0x4000;
+ opcode = 0;
}
}
- if ( ( aOpc & 1 ) != 0 )
+ if ( ( opcode & 1 ) != 0 )
{
C = B; /* counter clockwise rotation */
B = A;
A = -C;
}
- NORMalize( A, B, &CUR.GS.dualVector );
+ Normalize( A, B, &exc->GS.dualVector );
{
- FT_Vector* v1 = CUR.zp1.cur + p2;
- FT_Vector* v2 = CUR.zp2.cur + p1;
+ FT_Vector* v1 = exc->zp1.cur + p2;
+ FT_Vector* v2 = exc->zp2.cur + p1;
A = v1->x - v2->x;
@@ -5401,23 +4985,21 @@
if ( A == 0 && B == 0 )
{
- A = 0x4000;
- aOpc = 0;
+ A = 0x4000;
+ opcode = 0;
}
}
- if ( ( aOpc & 1 ) != 0 )
+ if ( ( opcode & 1 ) != 0 )
{
C = B; /* counter clockwise rotation */
B = A;
A = -C;
}
- NORMalize( A, B, &CUR.GS.projVector );
-
+ Normalize( A, B, &exc->GS.projVector );
GUESS_VECTOR( freeVector );
-
- COMPUTE_Funcs();
+ Compute_Funcs( exc );
}
@@ -5428,25 +5010,26 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_SZP0( INS_ARG )
+ Ins_SZP0( TT_ExecContext exc,
+ FT_Long* args )
{
switch ( (FT_Int)args[0] )
{
case 0:
- CUR.zp0 = CUR.twilight;
+ exc->zp0 = exc->twilight;
break;
case 1:
- CUR.zp0 = CUR.pts;
+ exc->zp0 = exc->pts;
break;
default:
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- CUR.GS.gep0 = (FT_UShort)args[0];
+ exc->GS.gep0 = (FT_UShort)args[0];
}
@@ -5457,25 +5040,26 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_SZP1( INS_ARG )
+ Ins_SZP1( TT_ExecContext exc,
+ FT_Long* args )
{
switch ( (FT_Int)args[0] )
{
case 0:
- CUR.zp1 = CUR.twilight;
+ exc->zp1 = exc->twilight;
break;
case 1:
- CUR.zp1 = CUR.pts;
+ exc->zp1 = exc->pts;
break;
default:
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- CUR.GS.gep1 = (FT_UShort)args[0];
+ exc->GS.gep1 = (FT_UShort)args[0];
}
@@ -5486,25 +5070,26 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_SZP2( INS_ARG )
+ Ins_SZP2( TT_ExecContext exc,
+ FT_Long* args )
{
switch ( (FT_Int)args[0] )
{
case 0:
- CUR.zp2 = CUR.twilight;
+ exc->zp2 = exc->twilight;
break;
case 1:
- CUR.zp2 = CUR.pts;
+ exc->zp2 = exc->pts;
break;
default:
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- CUR.GS.gep2 = (FT_UShort)args[0];
+ exc->GS.gep2 = (FT_UShort)args[0];
}
@@ -5515,60 +5100,82 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_SZPS( INS_ARG )
+ Ins_SZPS( TT_ExecContext exc,
+ FT_Long* args )
{
switch ( (FT_Int)args[0] )
{
case 0:
- CUR.zp0 = CUR.twilight;
+ exc->zp0 = exc->twilight;
break;
case 1:
- CUR.zp0 = CUR.pts;
+ exc->zp0 = exc->pts;
break;
default:
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- CUR.zp1 = CUR.zp0;
- CUR.zp2 = CUR.zp0;
+ exc->zp1 = exc->zp0;
+ exc->zp2 = exc->zp0;
- CUR.GS.gep0 = (FT_UShort)args[0];
- CUR.GS.gep1 = (FT_UShort)args[0];
- CUR.GS.gep2 = (FT_UShort)args[0];
+ exc->GS.gep0 = (FT_UShort)args[0];
+ exc->GS.gep1 = (FT_UShort)args[0];
+ exc->GS.gep2 = (FT_UShort)args[0];
}
/*************************************************************************/
/* */
/* INSTCTRL[]: INSTruction ConTRoL */
- /* Opcode range: 0x8e */
+ /* Opcode range: 0x8E */
/* Stack: int32 int32 --> */
/* */
static void
- Ins_INSTCTRL( INS_ARG )
+ Ins_INSTCTRL( TT_ExecContext exc,
+ FT_Long* args )
{
- FT_Long K, L;
+ FT_ULong K, L, Kf;
- K = args[1];
- L = args[0];
+ K = (FT_ULong)args[1];
+ L = (FT_ULong)args[0];
- if ( K < 1 || K > 2 )
+ /* selector values cannot be `OR'ed; */
+ /* they are indices starting with index 1, not flags */
+ if ( K < 1 || K > 3 )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- if ( L != 0 )
- L = K;
+ /* convert index to flag value */
+ Kf = 1 << ( K - 1 );
- CUR.GS.instruct_control = FT_BOOL(
- ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
+ if ( L != 0 )
+ {
+ /* arguments to selectors look like flag values */
+ if ( L != Kf )
+ {
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
+ return;
+ }
+ }
+
+ exc->GS.instruct_control &= ~(FT_Byte)Kf;
+ exc->GS.instruct_control |= (FT_Byte)L;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ /* INSTCTRL modifying flag 3 also has an effect */
+ /* outside of the CVT program */
+ if ( K == 3 )
+ exc->ignore_x_mode = FT_BOOL( L == 4 );
+#endif
}
@@ -5579,7 +5186,8 @@
/* Stack: uint32? --> */
/* */
static void
- Ins_SCANCTRL( INS_ARG )
+ Ins_SCANCTRL( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Int A;
@@ -5589,32 +5197,32 @@
if ( A == 0xFF )
{
- CUR.GS.scan_control = TRUE;
+ exc->GS.scan_control = TRUE;
return;
}
else if ( A == 0 )
{
- CUR.GS.scan_control = FALSE;
+ exc->GS.scan_control = FALSE;
return;
}
- if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem <= A )
- CUR.GS.scan_control = TRUE;
+ if ( ( args[0] & 0x100 ) != 0 && exc->tt_metrics.ppem <= A )
+ exc->GS.scan_control = TRUE;
- if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
- CUR.GS.scan_control = TRUE;
+ if ( ( args[0] & 0x200 ) != 0 && exc->tt_metrics.rotated )
+ exc->GS.scan_control = TRUE;
- if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
- CUR.GS.scan_control = TRUE;
+ if ( ( args[0] & 0x400 ) != 0 && exc->tt_metrics.stretched )
+ exc->GS.scan_control = TRUE;
- if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem > A )
- CUR.GS.scan_control = FALSE;
+ if ( ( args[0] & 0x800 ) != 0 && exc->tt_metrics.ppem > A )
+ exc->GS.scan_control = FALSE;
- if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
- CUR.GS.scan_control = FALSE;
+ if ( ( args[0] & 0x1000 ) != 0 && exc->tt_metrics.rotated )
+ exc->GS.scan_control = FALSE;
- if ( ( args[0] & 0x2000 ) != 0 && CUR.tt_metrics.stretched )
- CUR.GS.scan_control = FALSE;
+ if ( ( args[0] & 0x2000 ) != 0 && exc->tt_metrics.stretched )
+ exc->GS.scan_control = FALSE;
}
@@ -5625,10 +5233,11 @@
/* Stack: uint32? --> */
/* */
static void
- Ins_SCANTYPE( INS_ARG )
+ Ins_SCANTYPE( TT_ExecContext exc,
+ FT_Long* args )
{
if ( args[0] >= 0 )
- CUR.GS.scan_type = (FT_Int)args[0];
+ exc->GS.scan_type = (FT_Int)args[0];
}
@@ -5636,8 +5245,6 @@
/* */
/* MANAGING OUTLINES */
/* */
- /* Instructions appear in the specification's order. */
- /* */
/*************************************************************************/
@@ -5648,43 +5255,41 @@
/* Stack: uint32... --> */
/* */
static void
- Ins_FLIPPT( INS_ARG )
+ Ins_FLIPPT( TT_ExecContext exc )
{
FT_UShort point;
- FT_UNUSED_ARG;
-
- if ( CUR.top < CUR.GS.loop )
+ if ( exc->top < exc->GS.loop )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Too_Few_Arguments );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Too_Few_Arguments );
goto Fail;
}
- while ( CUR.GS.loop > 0 )
+ while ( exc->GS.loop > 0 )
{
- CUR.args--;
+ exc->args--;
- point = (FT_UShort)CUR.stack[CUR.args];
+ point = (FT_UShort)exc->stack[exc->args];
- if ( BOUNDS( point, CUR.pts.n_points ) )
+ if ( BOUNDS( point, exc->pts.n_points ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
}
else
- CUR.pts.tags[point] ^= FT_CURVE_TAG_ON;
+ exc->pts.tags[point] ^= FT_CURVE_TAG_ON;
- CUR.GS.loop--;
+ exc->GS.loop--;
}
Fail:
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
+ exc->GS.loop = 1;
+ exc->new_top = exc->args;
}
@@ -5695,7 +5300,8 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_FLIPRGON( INS_ARG )
+ Ins_FLIPRGON( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort I, K, L;
@@ -5703,16 +5309,16 @@
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
+ if ( BOUNDS( K, exc->pts.n_points ) ||
+ BOUNDS( L, exc->pts.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
for ( I = L; I <= K; I++ )
- CUR.pts.tags[I] |= FT_CURVE_TAG_ON;
+ exc->pts.tags[I] |= FT_CURVE_TAG_ON;
}
@@ -5723,7 +5329,8 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_FLIPRGOFF( INS_ARG )
+ Ins_FLIPRGOFF( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort I, K, L;
@@ -5731,45 +5338,46 @@
K = (FT_UShort)args[1];
L = (FT_UShort)args[0];
- if ( BOUNDS( K, CUR.pts.n_points ) ||
- BOUNDS( L, CUR.pts.n_points ) )
+ if ( BOUNDS( K, exc->pts.n_points ) ||
+ BOUNDS( L, exc->pts.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
for ( I = L; I <= K; I++ )
- CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON;
+ exc->pts.tags[I] &= ~FT_CURVE_TAG_ON;
}
static FT_Bool
- Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x,
- FT_F26Dot6* y,
- TT_GlyphZone zone,
- FT_UShort* refp )
+ Compute_Point_Displacement( TT_ExecContext exc,
+ FT_F26Dot6* x,
+ FT_F26Dot6* y,
+ TT_GlyphZone zone,
+ FT_UShort* refp )
{
TT_GlyphZoneRec zp;
FT_UShort p;
FT_F26Dot6 d;
- if ( CUR.opcode & 1 )
+ if ( exc->opcode & 1 )
{
- zp = CUR.zp0;
- p = CUR.GS.rp1;
+ zp = exc->zp0;
+ p = exc->GS.rp1;
}
else
{
- zp = CUR.zp1;
- p = CUR.GS.rp2;
+ zp = exc->zp1;
+ p = exc->GS.rp2;
}
if ( BOUNDS( p, zp.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
*refp = 0;
return FAILURE;
}
@@ -5777,12 +5385,12 @@
*zone = zp;
*refp = p;
- d = CUR_Func_project( zp.cur + p, zp.org + p );
+ d = PROJECT( zp.cur + p, zp.org + p );
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
- if ( CUR.GS.both_x_axis )
+ if ( exc->GS.both_x_axis )
{
*x = d;
*y = 0;
@@ -5796,8 +5404,8 @@
else
#endif
{
- *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P );
- *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P );
+ *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P );
+ *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P );
}
return SUCCESS;
@@ -5805,42 +5413,43 @@
static void
- Move_Zp2_Point( EXEC_OP_ FT_UShort point,
- FT_F26Dot6 dx,
- FT_F26Dot6 dy,
- FT_Bool touch )
+ Move_Zp2_Point( TT_ExecContext exc,
+ FT_UShort point,
+ FT_F26Dot6 dx,
+ FT_F26Dot6 dy,
+ FT_Bool touch )
{
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
- if ( CUR.GS.both_x_axis )
+ if ( exc->GS.both_x_axis )
{
- CUR.zp2.cur[point].x += dx;
+ exc->zp2.cur[point].x += dx;
if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
else
{
- CUR.zp2.cur[point].y += dy;
+ exc->zp2.cur[point].y += dy;
if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
return;
}
#endif
- if ( CUR.GS.freeVector.x != 0 )
+ if ( exc->GS.freeVector.x != 0 )
{
- CUR.zp2.cur[point].x += dx;
+ exc->zp2.cur[point].x += dx;
if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X;
}
- if ( CUR.GS.freeVector.y != 0 )
+ if ( exc->GS.freeVector.y != 0 )
{
- CUR.zp2.cur[point].y += dy;
+ exc->zp2.cur[point].y += dy;
if ( touch )
- CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y;
}
}
@@ -5852,57 +5461,54 @@
/* Stack: uint32... --> */
/* */
static void
- Ins_SHP( INS_ARG )
+ Ins_SHP( TT_ExecContext exc )
{
TT_GlyphZoneRec zp;
FT_UShort refp;
- FT_F26Dot6 dx,
- dy;
+ FT_F26Dot6 dx, dy;
FT_UShort point;
- FT_UNUSED_ARG;
-
- if ( CUR.top < CUR.GS.loop )
+ if ( exc->top < exc->GS.loop )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
return;
- while ( CUR.GS.loop > 0 )
+ while ( exc->GS.loop > 0 )
{
- CUR.args--;
- point = (FT_UShort)CUR.stack[CUR.args];
+ exc->args--;
+ point = (FT_UShort)exc->stack[exc->args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
+ if ( BOUNDS( point, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
}
else
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* doesn't follow Cleartype spec but produces better result */
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode )
- MOVE_Zp2_Point( point, 0, dy, TRUE );
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode )
+ Move_Zp2_Point( exc, point, 0, dy, TRUE );
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- MOVE_Zp2_Point( point, dx, dy, TRUE );
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
- CUR.GS.loop--;
+ exc->GS.loop--;
}
Fail:
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
+ exc->GS.loop = 1;
+ exc->new_top = exc->args;
}
@@ -5917,7 +5523,8 @@
/* zero which includes all points of it. */
/* */
static void
- Ins_SHC( INS_ARG )
+ Ins_SHC( TT_ExecContext exc,
+ FT_Long* args )
{
TT_GlyphZoneRec zp;
FT_UShort refp;
@@ -5927,36 +5534,36 @@
FT_UShort start, limit, i;
- contour = (FT_UShort)args[0];
- bounds = ( CUR.GS.gep2 == 0 ) ? 1 : CUR.zp2.n_contours;
+ contour = (FT_Short)args[0];
+ bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
if ( BOUNDS( contour, bounds ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
return;
if ( contour == 0 )
start = 0;
else
- start = (FT_UShort)( CUR.zp2.contours[contour - 1] + 1 -
- CUR.zp2.first_point );
+ start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
+ exc->zp2.first_point );
/* we use the number of points if in the twilight zone */
- if ( CUR.GS.gep2 == 0 )
- limit = CUR.zp2.n_points;
+ if ( exc->GS.gep2 == 0 )
+ limit = exc->zp2.n_points;
else
- limit = (FT_UShort)( CUR.zp2.contours[contour] -
- CUR.zp2.first_point + 1 );
+ limit = (FT_UShort)( exc->zp2.contours[contour] -
+ exc->zp2.first_point + 1 );
for ( i = start; i < limit; i++ )
{
- if ( zp.cur != CUR.zp2.cur || refp != i )
- MOVE_Zp2_Point( i, dx, dy, TRUE );
+ if ( zp.cur != exc->zp2.cur || refp != i )
+ Move_Zp2_Point( exc, i, dx, dy, TRUE );
}
}
@@ -5968,7 +5575,8 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_SHZ( INS_ARG )
+ Ins_SHZ( TT_ExecContext exc,
+ FT_Long* args )
{
TT_GlyphZoneRec zp;
FT_UShort refp;
@@ -5980,30 +5588,30 @@
if ( BOUNDS( args[0], 2 ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+ if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) )
return;
/* XXX: UNDOCUMENTED! SHZ doesn't move the phantom points. */
/* Twilight zone has no real contours, so use `n_points'. */
/* Normal zone's `n_points' includes phantoms, so must */
/* use end of last contour. */
- if ( CUR.GS.gep2 == 0 )
- limit = (FT_UShort)CUR.zp2.n_points;
- else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
- limit = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] + 1 );
+ if ( exc->GS.gep2 == 0 )
+ limit = (FT_UShort)exc->zp2.n_points;
+ else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
+ limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
else
limit = 0;
/* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
for ( i = 0; i < limit; i++ )
{
- if ( zp.cur != CUR.zp2.cur || refp != i )
- MOVE_Zp2_Point( i, dx, dy, FALSE );
+ if ( zp.cur != exc->zp2.cur || refp != i )
+ Move_Zp2_Point( exc, i, dx, dy, FALSE );
}
}
@@ -6015,7 +5623,8 @@
/* Stack: f26.6 uint32... --> */
/* */
static void
- Ins_SHPIX( INS_ARG )
+ Ins_SHPIX( TT_ExecContext exc,
+ FT_Long* args )
{
FT_F26Dot6 dx, dy;
FT_UShort point;
@@ -6024,17 +5633,17 @@
#endif
- if ( CUR.top < CUR.GS.loop + 1 )
+ if ( exc->top < exc->GS.loop + 1 )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
- if ( CUR.GS.both_x_axis )
+ if ( exc->GS.both_x_axis )
{
dx = (FT_UInt32)args[0];
dy = 0;
@@ -6048,115 +5657,115 @@
else
#endif
{
- dx = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.x );
- dy = TT_MulFix14( (FT_UInt32)args[0], CUR.GS.freeVector.y );
+ dx = TT_MulFix14( args[0], exc->GS.freeVector.x );
+ dy = TT_MulFix14( args[0], exc->GS.freeVector.y );
}
- while ( CUR.GS.loop > 0 )
+ while ( exc->GS.loop > 0 )
{
- CUR.args--;
+ exc->args--;
- point = (FT_UShort)CUR.stack[CUR.args];
+ point = (FT_UShort)exc->stack[exc->args];
- if ( BOUNDS( point, CUR.zp2.n_points ) )
+ if ( BOUNDS( point, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
}
else
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
{
- /* If not using ignore_x_mode rendering, allow ZP2 move. */
- /* If inline deltas aren't allowed, skip ZP2 move. */
- /* If using ignore_x_mode rendering, allow ZP2 point move if: */
- /* - freedom vector is y and sph_compatibility_mode is off */
- /* - the glyph is composite and the move is in the Y direction */
- /* - the glyph is specifically set to allow SHPIX moves */
- /* - the move is on a previously Y-touched point */
+ /* If not using ignore_x_mode rendering, allow ZP2 move. */
+ /* If inline deltas aren't allowed, skip ZP2 move. */
+ /* If using ignore_x_mode rendering, allow ZP2 point move if: */
+ /* - freedom vector is y and sph_compatibility_mode is off */
+ /* - the glyph is composite and the move is in the Y direction */
+ /* - the glyph is specifically set to allow SHPIX moves */
+ /* - the move is on a previously Y-touched point */
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode )
{
/* save point for later comparison */
- if ( CUR.GS.freeVector.y != 0 )
- B1 = CUR.zp2.cur[point].y;
+ if ( exc->GS.freeVector.y != 0 )
+ B1 = exc->zp2.cur[point].y;
else
- B1 = CUR.zp2.cur[point].x;
+ B1 = exc->zp2.cur[point].x;
- if ( !CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 )
+ if ( !exc->face->sph_compatibility_mode &&
+ exc->GS.freeVector.y != 0 )
{
- MOVE_Zp2_Point( point, dx, dy, TRUE );
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
/* save new point */
- if ( CUR.GS.freeVector.y != 0 )
+ if ( exc->GS.freeVector.y != 0 )
{
- B2 = CUR.zp2.cur[point].y;
+ B2 = exc->zp2.cur[point].y;
/* reverse any disallowed moves */
- if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- ( B1 & 63 ) != 0 &&
- ( B2 & 63 ) != 0 &&
- B1 != B2 )
- MOVE_Zp2_Point( point, -dx, -dy, TRUE );
+ if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ ( B1 & 63 ) != 0 &&
+ ( B2 & 63 ) != 0 &&
+ B1 != B2 )
+ Move_Zp2_Point( exc, point, -dx, -dy, TRUE );
}
}
- else if ( CUR.face->sph_compatibility_mode )
+ else if ( exc->face->sph_compatibility_mode )
{
- if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+ if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
{
dx = FT_PIX_ROUND( B1 + dx ) - B1;
dy = FT_PIX_ROUND( B1 + dy ) - B1;
}
/* skip post-iup deltas */
- if ( CUR.iup_called &&
- ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
- ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
+ if ( exc->iup_called &&
+ ( ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
+ ( exc->sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
goto Skip;
- if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
- ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
- ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) )
- MOVE_Zp2_Point( point, 0, dy, TRUE );
+ if ( !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
+ ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) ||
+ ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ||
+ ( exc->sph_tweak_flags & SPH_TWEAK_DO_SHPIX ) ) )
+ Move_Zp2_Point( exc, point, 0, dy, TRUE );
/* save new point */
- if ( CUR.GS.freeVector.y != 0 )
+ if ( exc->GS.freeVector.y != 0 )
{
- B2 = CUR.zp2.cur[point].y;
+ B2 = exc->zp2.cur[point].y;
/* reverse any disallowed moves */
if ( ( B1 & 63 ) == 0 &&
( B2 & 63 ) != 0 &&
B1 != B2 )
- MOVE_Zp2_Point( point, 0, -dy, TRUE );
+ Move_Zp2_Point( exc, point, 0, -dy, TRUE );
}
}
- else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
- MOVE_Zp2_Point( point, dx, dy, TRUE );
+ else if ( exc->sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
}
else
- MOVE_Zp2_Point( point, dx, dy, TRUE );
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
}
Skip:
#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- MOVE_Zp2_Point( point, dx, dy, TRUE );
+ Move_Zp2_Point( exc, point, dx, dy, TRUE );
#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR.GS.loop--;
+ exc->GS.loop--;
}
Fail:
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
+ exc->GS.loop = 1;
+ exc->new_top = exc->args;
}
@@ -6167,22 +5776,23 @@
/* Stack: f26.6 uint32 --> */
/* */
static void
- Ins_MSIRP( INS_ARG )
+ Ins_MSIRP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point;
FT_F26Dot6 distance;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_F26Dot6 control_value_cutin;
+ FT_F26Dot6 control_value_cutin = 0; /* pacify compiler */
if ( SUBPIXEL_HINTING )
{
- control_value_cutin = CUR.GS.control_value_cutin;
+ control_value_cutin = exc->GS.control_value_cutin;
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ if ( exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = 0;
}
@@ -6190,42 +5800,41 @@
point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ if ( BOUNDS( point, exc->zp1.n_points ) ||
+ BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
/* UNDOCUMENTED! The MS rasterizer does that with */
/* twilight points (confirmed by Greg Hitchcock) */
- if ( CUR.GS.gep1 == 0 )
+ if ( exc->GS.gep1 == 0 )
{
- CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
- CUR_Func_move_orig( &CUR.zp1, point, args[1] );
- CUR.zp1.cur[point] = CUR.zp1.org[point];
+ exc->zp1.org[point] = exc->zp0.org[exc->GS.rp0];
+ exc->func_move_orig( exc, &exc->zp1, point, args[1] );
+ exc->zp1.cur[point] = exc->zp1.org[point];
}
- distance = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
+ distance = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* subpixel hinting - make MSIRP respect CVT cut-in; */
if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
FT_ABS( distance - args[1] ) >= control_value_cutin )
distance = args[1];
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+ exc->func_move( exc, &exc->zp1, point, args[1] - distance );
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
+ exc->GS.rp1 = exc->GS.rp0;
+ exc->GS.rp2 = point;
- if ( ( CUR.opcode & 1 ) != 0 )
- CUR.GS.rp0 = point;
+ if ( ( exc->opcode & 1 ) != 0 )
+ exc->GS.rp0 = point;
}
@@ -6236,7 +5845,8 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_MDAP( INS_ARG )
+ Ins_MDAP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point;
FT_F26Dot6 cur_dist;
@@ -6245,36 +5855,38 @@
point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp0.n_points ) )
+ if ( BOUNDS( point, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- if ( ( CUR.opcode & 1 ) != 0 )
+ if ( ( exc->opcode & 1 ) != 0 )
{
- cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
+ cur_dist = FAST_PROJECT( &exc->zp0.cur[point] );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 )
- distance = ROUND_None(
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 )
+ distance = Round_None(
+ exc,
cur_dist,
- CUR.tt_metrics.compensations[0] ) - cur_dist;
+ exc->tt_metrics.compensations[0] ) - cur_dist;
else
#endif
- distance = CUR_Func_round(
+ distance = exc->func_round(
+ exc,
cur_dist,
- CUR.tt_metrics.compensations[0] ) - cur_dist;
+ exc->tt_metrics.compensations[0] ) - cur_dist;
}
else
distance = 0;
- CUR_Func_move( &CUR.zp0, point, distance );
+ exc->func_move( exc, &exc->zp0, point, distance );
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
+ exc->GS.rp0 = point;
+ exc->GS.rp1 = point;
}
@@ -6285,7 +5897,8 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_MIAP( INS_ARG )
+ Ins_MIAP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong cvtEntry;
FT_UShort point;
@@ -6294,24 +5907,24 @@
FT_F26Dot6 control_value_cutin;
- control_value_cutin = CUR.GS.control_value_cutin;
+ control_value_cutin = exc->GS.control_value_cutin;
cvtEntry = (FT_ULong)args[1];
point = (FT_UShort)args[0];
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
- CUR.GS.freeVector.y == 0 &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ exc->GS.freeVector.y == 0 &&
+ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- if ( BOUNDS( point, CUR.zp0.n_points ) ||
- BOUNDSL( cvtEntry, CUR.cvtSize ) )
+ if ( BOUNDS( point, exc->zp0.n_points ) ||
+ BOUNDSL( cvtEntry, exc->cvtSize ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
@@ -6335,56 +5948,58 @@
/* */
/* Confirmed by Greg Hitchcock. */
- distance = CUR_Func_read_cvt( cvtEntry );
+ distance = exc->func_read_cvt( exc, cvtEntry );
- if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */
+ if ( exc->GS.gep0 == 0 ) /* If in twilight zone */
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
/* Determined via experimentation and may be incorrect... */
- if ( !SUBPIXEL_HINTING ||
- ( !CUR.ignore_x_mode ||
- !CUR.face->sph_compatibility_mode ) )
+ if ( !SUBPIXEL_HINTING ||
+ ( !exc->ignore_x_mode ||
+ !exc->face->sph_compatibility_mode ) )
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
- CUR.GS.freeVector.x );
- CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
- CUR.GS.freeVector.y ),
- CUR.zp0.cur[point] = CUR.zp0.org[point];
+ exc->zp0.org[point].x = TT_MulFix14( distance,
+ exc->GS.freeVector.x );
+ exc->zp0.org[point].y = TT_MulFix14( distance,
+ exc->GS.freeVector.y ),
+ exc->zp0.cur[point] = exc->zp0.org[point];
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
- distance > 0 &&
- CUR.GS.freeVector.y != 0 )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
+ distance > 0 &&
+ exc->GS.freeVector.y != 0 )
distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
+ org_dist = FAST_PROJECT( &exc->zp0.cur[point] );
- if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
+ if ( ( exc->opcode & 1 ) != 0 ) /* rounding and control cut-in flag */
{
if ( FT_ABS( distance - org_dist ) > control_value_cutin )
distance = org_dist;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 )
- distance = ROUND_None( distance,
- CUR.tt_metrics.compensations[0] );
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 )
+ distance = Round_None( exc,
+ distance,
+ exc->tt_metrics.compensations[0] );
else
#endif
- distance = CUR_Func_round( distance,
- CUR.tt_metrics.compensations[0] );
+ distance = exc->func_round( exc,
+ distance,
+ exc->tt_metrics.compensations[0] );
}
- CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp0, point, distance - org_dist );
Fail:
- CUR.GS.rp0 = point;
- CUR.GS.rp1 = point;
+ exc->GS.rp0 = point;
+ exc->GS.rp1 = point;
}
@@ -6395,29 +6010,30 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_MDRP( INS_ARG )
+ Ins_MDRP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point;
FT_F26Dot6 org_dist, distance, minimum_distance;
- minimum_distance = CUR.GS.minimum_distance;
+ minimum_distance = exc->GS.minimum_distance;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ if ( BOUNDS( point, exc->zp1.n_points ) ||
+ BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
@@ -6426,74 +6042,77 @@
/* XXX: UNDOCUMENTED: twilight zone special case */
- if ( CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 )
+ if ( exc->GS.gep0 == 0 || exc->GS.gep1 == 0 )
{
- FT_Vector* vec1 = &CUR.zp1.org[point];
- FT_Vector* vec2 = &CUR.zp0.org[CUR.GS.rp0];
+ FT_Vector* vec1 = &exc->zp1.org[point];
+ FT_Vector* vec2 = &exc->zp0.org[exc->GS.rp0];
- org_dist = CUR_Func_dualproj( vec1, vec2 );
+ org_dist = DUALPROJ( vec1, vec2 );
}
else
{
- FT_Vector* vec1 = &CUR.zp1.orus[point];
- FT_Vector* vec2 = &CUR.zp0.orus[CUR.GS.rp0];
+ FT_Vector* vec1 = &exc->zp1.orus[point];
+ FT_Vector* vec2 = &exc->zp0.orus[exc->GS.rp0];
- if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
+ if ( exc->metrics.x_scale == exc->metrics.y_scale )
{
/* this should be faster */
- org_dist = CUR_Func_dualproj( vec1, vec2 );
- org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale );
+ org_dist = DUALPROJ( vec1, vec2 );
+ org_dist = FT_MulFix( org_dist, exc->metrics.x_scale );
}
else
{
FT_Vector vec;
- vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
- vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
+ vec.x = FT_MulFix( vec1->x - vec2->x, exc->metrics.x_scale );
+ vec.y = FT_MulFix( vec1->y - vec2->y, exc->metrics.y_scale );
- org_dist = CUR_fast_dualproj( &vec );
+ org_dist = FAST_DUALPROJ( &vec );
}
}
/* single width cut-in test */
- if ( FT_ABS( org_dist - CUR.GS.single_width_value ) <
- CUR.GS.single_width_cutin )
+ if ( FT_ABS( org_dist - exc->GS.single_width_value ) <
+ exc->GS.single_width_cutin )
{
if ( org_dist >= 0 )
- org_dist = CUR.GS.single_width_value;
+ org_dist = exc->GS.single_width_value;
else
- org_dist = -CUR.GS.single_width_value;
+ org_dist = -exc->GS.single_width_value;
}
/* round flag */
- if ( ( CUR.opcode & 4 ) != 0 )
+ if ( ( exc->opcode & 4 ) != 0 )
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 )
- distance = ROUND_None(
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 )
+ distance = Round_None(
+ exc,
org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ exc->tt_metrics.compensations[exc->opcode & 3] );
else
#endif
- distance = CUR_Func_round(
- org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ distance = exc->func_round(
+ exc,
+ org_dist,
+ exc->tt_metrics.compensations[exc->opcode & 3] );
}
else
- distance = ROUND_None(
+ distance = Round_None(
+ exc,
org_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ exc->tt_metrics.compensations[exc->opcode & 3] );
/* minimum distance flag */
- if ( ( CUR.opcode & 8 ) != 0 )
+ if ( ( exc->opcode & 8 ) != 0 )
{
if ( org_dist >= 0 )
{
@@ -6509,17 +6128,16 @@
/* now move the point */
- org_dist = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
+ org_dist = PROJECT( exc->zp1.cur + point, exc->zp0.cur + exc->GS.rp0 );
- CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+ exc->func_move( exc, &exc->zp1, point, distance - org_dist );
Fail:
- CUR.GS.rp1 = CUR.GS.rp0;
- CUR.GS.rp2 = point;
+ exc->GS.rp1 = exc->GS.rp0;
+ exc->GS.rp2 = point;
- if ( ( CUR.opcode & 16 ) != 0 )
- CUR.GS.rp0 = point;
+ if ( ( exc->opcode & 16 ) != 0 )
+ exc->GS.rp0 = point;
}
@@ -6530,7 +6148,8 @@
/* Stack: int32? uint32 --> */
/* */
static void
- Ins_MIRP( INS_ARG )
+ Ins_MIRP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point;
FT_ULong cvtEntry;
@@ -6542,83 +6161,81 @@
control_value_cutin,
minimum_distance;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- FT_Int B1;
- FT_Int B2;
+ FT_Int B1 = 0; /* pacify compiler */
+ FT_Int B2 = 0;
FT_Bool reverse_move = FALSE;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- minimum_distance = CUR.GS.minimum_distance;
- control_value_cutin = CUR.GS.control_value_cutin;
+ minimum_distance = exc->GS.minimum_distance;
+ control_value_cutin = exc->GS.control_value_cutin;
point = (FT_UShort)args[0];
cvtEntry = (FT_ULong)( args[1] + 1 );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.x != 0 &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.x != 0 &&
+ !( exc->sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
control_value_cutin = minimum_distance = 0;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
/* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
- if ( BOUNDS( point, CUR.zp1.n_points ) ||
- BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ if ( BOUNDS( point, exc->zp1.n_points ) ||
+ BOUNDSL( cvtEntry, exc->cvtSize + 1 ) ||
+ BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
if ( !cvtEntry )
cvt_dist = 0;
else
- cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+ cvt_dist = exc->func_read_cvt( exc, cvtEntry - 1 );
/* single width test */
- if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) <
- CUR.GS.single_width_cutin )
+ if ( FT_ABS( cvt_dist - exc->GS.single_width_value ) <
+ exc->GS.single_width_cutin )
{
if ( cvt_dist >= 0 )
- cvt_dist = CUR.GS.single_width_value;
+ cvt_dist = exc->GS.single_width_value;
else
- cvt_dist = -CUR.GS.single_width_value;
+ cvt_dist = -exc->GS.single_width_value;
}
/* UNDOCUMENTED! The MS rasterizer does that with */
/* twilight points (confirmed by Greg Hitchcock) */
- if ( CUR.GS.gep1 == 0 )
+ if ( exc->GS.gep1 == 0 )
{
- CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
- TT_MulFix14( (FT_UInt32)cvt_dist,
- CUR.GS.freeVector.x );
- CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
- TT_MulFix14( (FT_UInt32)cvt_dist,
- CUR.GS.freeVector.y );
- CUR.zp1.cur[point] = CUR.zp1.org[point];
+ exc->zp1.org[point].x = exc->zp0.org[exc->GS.rp0].x +
+ TT_MulFix14( cvt_dist,
+ exc->GS.freeVector.x );
+ exc->zp1.org[point].y = exc->zp0.org[exc->GS.rp0].y +
+ TT_MulFix14( cvt_dist,
+ exc->GS.freeVector.y );
+ exc->zp1.cur[point] = exc->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] );
+ org_dist = DUALPROJ( &exc->zp1.org[point], &exc->zp0.org[exc->GS.rp0] );
+ cur_dist = PROJECT ( &exc->zp1.cur[point], &exc->zp0.cur[exc->GS.rp0] );
/* auto-flip test */
- if ( CUR.GS.auto_flip )
+ if ( exc->GS.auto_flip )
{
if ( ( org_dist ^ cvt_dist ) < 0 )
cvt_dist = -cvt_dist;
}
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.freeVector.y != 0 &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
{
if ( cur_dist < -64 )
cvt_dist -= 16;
@@ -6629,12 +6246,12 @@
/* control value cut-in and round */
- if ( ( CUR.opcode & 4 ) != 0 )
+ if ( ( exc->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 ( exc->GS.gep0 == exc->GS.gep1 )
{
/* XXX: According to Greg Hitchcock, the following wording is */
/* the right one: */
@@ -6652,32 +6269,34 @@
cvt_dist = org_dist;
}
- distance = CUR_Func_round(
+ distance = exc->func_round(
+ exc,
cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ exc->tt_metrics.compensations[exc->opcode & 3] );
}
else
{
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
/* do cvt cut-in always in MIRP for sph */
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.GS.gep0 == CUR.GS.gep1 )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->GS.gep0 == exc->GS.gep1 )
{
if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
cvt_dist = org_dist;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- distance = ROUND_None(
+ distance = Round_None(
+ exc,
cvt_dist,
- CUR.tt_metrics.compensations[CUR.opcode & 3] );
+ exc->tt_metrics.compensations[exc->opcode & 3] );
}
/* minimum distance test */
- if ( ( CUR.opcode & 8 ) != 0 )
+ if ( ( exc->opcode & 8 ) != 0 )
{
if ( org_dist >= 0 )
{
@@ -6694,59 +6313,59 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( SUBPIXEL_HINTING )
{
- B1 = CUR.zp1.cur[point].y;
+ B1 = exc->zp1.cur[point].y;
/* Round moves if necessary */
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
+ if ( exc->ignore_x_mode &&
+ exc->GS.freeVector.y != 0 &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
- if ( CUR.ignore_x_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( CUR.opcode & 16 ) == 0 &&
- ( CUR.opcode & 8 ) == 0 &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
+ if ( exc->ignore_x_mode &&
+ exc->GS.freeVector.y != 0 &&
+ ( exc->opcode & 16 ) == 0 &&
+ ( exc->opcode & 8 ) == 0 &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
distance += 64;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+ exc->func_move( exc, &exc->zp1, point, distance - cur_dist );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
if ( SUBPIXEL_HINTING )
{
- B2 = CUR.zp1.cur[point].y;
+ B2 = exc->zp1.cur[point].y;
/* Reverse move if necessary */
- if ( CUR.ignore_x_mode )
+ if ( exc->ignore_x_mode )
{
- if ( CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 &&
- ( B1 & 63 ) == 0 &&
- ( B2 & 63 ) != 0 )
+ if ( exc->face->sph_compatibility_mode &&
+ exc->GS.freeVector.y != 0 &&
+ ( B1 & 63 ) == 0 &&
+ ( B2 & 63 ) != 0 )
reverse_move = TRUE;
- if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
- CUR.GS.freeVector.y != 0 &&
- ( B2 & 63 ) != 0 &&
- ( B1 & 63 ) != 0 )
+ if ( ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+ exc->GS.freeVector.y != 0 &&
+ ( B2 & 63 ) != 0 &&
+ ( B1 & 63 ) != 0 )
reverse_move = TRUE;
}
if ( reverse_move )
- CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
+ exc->func_move( exc, &exc->zp1, point, -( distance - cur_dist ) );
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
Fail:
- CUR.GS.rp1 = CUR.GS.rp0;
+ exc->GS.rp1 = exc->GS.rp0;
- if ( ( CUR.opcode & 16 ) != 0 )
- CUR.GS.rp0 = point;
+ if ( ( exc->opcode & 16 ) != 0 )
+ exc->GS.rp0 = point;
- CUR.GS.rp2 = point;
+ exc->GS.rp2 = point;
}
@@ -6757,61 +6376,59 @@
/* Stack: uint32 uint32... --> */
/* */
static void
- Ins_ALIGNRP( INS_ARG )
+ Ins_ALIGNRP( TT_ExecContext exc )
{
FT_UShort point;
FT_F26Dot6 distance;
- FT_UNUSED_ARG;
-
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.iup_called &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->iup_called &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- if ( CUR.top < CUR.GS.loop ||
- BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+ if ( exc->top < exc->GS.loop ||
+ BOUNDS( exc->GS.rp0, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
- while ( CUR.GS.loop > 0 )
+ while ( exc->GS.loop > 0 )
{
- CUR.args--;
+ exc->args--;
- point = (FT_UShort)CUR.stack[CUR.args];
+ point = (FT_UShort)exc->stack[exc->args];
- if ( BOUNDS( point, CUR.zp1.n_points ) )
+ if ( BOUNDS( point, exc->zp1.n_points ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
}
else
{
- distance = CUR_Func_project( CUR.zp1.cur + point,
- CUR.zp0.cur + CUR.GS.rp0 );
+ distance = PROJECT( exc->zp1.cur + point,
+ exc->zp0.cur + exc->GS.rp0 );
- CUR_Func_move( &CUR.zp1, point, -distance );
+ exc->func_move( exc, &exc->zp1, point, -distance );
}
- CUR.GS.loop--;
+ exc->GS.loop--;
}
Fail:
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
+ exc->GS.loop = 1;
+ exc->new_top = exc->args;
}
@@ -6822,7 +6439,8 @@
/* Stack: 5 * uint32 --> */
/* */
static void
- Ins_ISECT( INS_ARG )
+ Ins_ISECT( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point,
a0, a1,
@@ -6846,29 +6464,27 @@
b0 = (FT_UShort)args[3];
b1 = (FT_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 ( BOUNDS( b0, exc->zp0.n_points ) ||
+ BOUNDS( b1, exc->zp0.n_points ) ||
+ BOUNDS( a0, exc->zp1.n_points ) ||
+ BOUNDS( a1, exc->zp1.n_points ) ||
+ BOUNDS( point, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
/* Cramer's rule */
- dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
- dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+ dbx = exc->zp0.cur[b1].x - exc->zp0.cur[b0].x;
+ dby = exc->zp0.cur[b1].y - exc->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;
+ dax = exc->zp1.cur[a1].x - exc->zp1.cur[a0].x;
+ day = exc->zp1.cur[a1].y - exc->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.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
+ dx = exc->zp0.cur[b0].x - exc->zp1.cur[a0].x;
+ dy = exc->zp0.cur[b0].y - exc->zp1.cur[a0].y;
discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
FT_MulDiv( day, dbx, 0x40 );
@@ -6890,22 +6506,24 @@
R.x = FT_MulDiv( val, dax, discriminant );
R.y = FT_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;
+ exc->zp2.cur[point].x = exc->zp1.cur[a0].x + R.x;
+ exc->zp2.cur[point].y = exc->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;
+ exc->zp2.cur[point].x = ( exc->zp1.cur[a0].x +
+ exc->zp1.cur[a1].x +
+ exc->zp0.cur[b0].x +
+ exc->zp0.cur[b1].x ) / 4;
+ exc->zp2.cur[point].y = ( exc->zp1.cur[a0].y +
+ exc->zp1.cur[a1].y +
+ exc->zp0.cur[b0].y +
+ exc->zp0.cur[b1].y ) / 4;
}
+
+ exc->zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
}
@@ -6916,7 +6534,8 @@
/* Stack: uint32 uint32 --> */
/* */
static void
- Ins_ALIGNPTS( INS_ARG )
+ Ins_ALIGNPTS( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort p1, p2;
FT_F26Dot6 distance;
@@ -6925,19 +6544,18 @@
p1 = (FT_UShort)args[0];
p2 = (FT_UShort)args[1];
- if ( BOUNDS( p1, CUR.zp1.n_points ) ||
- BOUNDS( p2, CUR.zp0.n_points ) )
+ if ( BOUNDS( p1, exc->zp1.n_points ) ||
+ BOUNDS( p2, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
- distance = CUR_Func_project( CUR.zp0.cur + p2,
- CUR.zp1.cur + p1 ) / 2;
+ distance = PROJECT( exc->zp0.cur + p2, exc->zp1.cur + p1 ) / 2;
- CUR_Func_move( &CUR.zp1, p1, distance );
- CUR_Func_move( &CUR.zp0, p2, -distance );
+ exc->func_move( exc, &exc->zp1, p1, distance );
+ exc->func_move( exc, &exc->zp0, p2, -distance );
}
@@ -6951,50 +6569,48 @@
/* SOMETIMES, DUMBER CODE IS BETTER CODE */
static void
- Ins_IP( INS_ARG )
+ Ins_IP( TT_ExecContext exc )
{
FT_F26Dot6 old_range, cur_range;
FT_Vector* orus_base;
FT_Vector* cur_base;
FT_Int twilight;
- FT_UNUSED_ARG;
-
- if ( CUR.top < CUR.GS.loop )
+ if ( exc->top < exc->GS.loop )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
/*
* We need to deal in a special way with the twilight zone.
- * Otherwise, by definition, the value of CUR.twilight.orus[n] is (0,0),
+ * Otherwise, by definition, the value of exc->twilight.orus[n] is (0,0),
* for every n.
*/
- twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
+ twilight = exc->GS.gep0 == 0 || exc->GS.gep1 == 0 || exc->GS.gep2 == 0;
- if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
+ if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
goto Fail;
}
if ( twilight )
- orus_base = &CUR.zp0.org[CUR.GS.rp1];
+ orus_base = &exc->zp0.org[exc->GS.rp1];
else
- orus_base = &CUR.zp0.orus[CUR.GS.rp1];
+ orus_base = &exc->zp0.orus[exc->GS.rp1];
- cur_base = &CUR.zp0.cur[CUR.GS.rp1];
+ cur_base = &exc->zp0.cur[exc->GS.rp1];
/* 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 ) )
+ if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ||
+ BOUNDS( exc->GS.rp2, exc->zp1.n_points ) )
{
old_range = 0;
cur_range = 0;
@@ -7002,62 +6618,60 @@
else
{
if ( twilight )
- old_range = CUR_Func_dualproj( &CUR.zp1.org[CUR.GS.rp2],
- orus_base );
- else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
- old_range = CUR_Func_dualproj( &CUR.zp1.orus[CUR.GS.rp2],
- orus_base );
+ old_range = DUALPROJ( &exc->zp1.org[exc->GS.rp2], orus_base );
+ else if ( exc->metrics.x_scale == exc->metrics.y_scale )
+ old_range = DUALPROJ( &exc->zp1.orus[exc->GS.rp2], orus_base );
else
{
FT_Vector vec;
- vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
- CUR.metrics.x_scale );
- vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
- CUR.metrics.y_scale );
+ vec.x = FT_MulFix( exc->zp1.orus[exc->GS.rp2].x - orus_base->x,
+ exc->metrics.x_scale );
+ vec.y = FT_MulFix( exc->zp1.orus[exc->GS.rp2].y - orus_base->y,
+ exc->metrics.y_scale );
- old_range = CUR_fast_dualproj( &vec );
+ old_range = FAST_DUALPROJ( &vec );
}
- cur_range = CUR_Func_project ( &CUR.zp1.cur[CUR.GS.rp2], cur_base );
+ cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base );
}
- for ( ; CUR.GS.loop > 0; --CUR.GS.loop )
+ for ( ; exc->GS.loop > 0; --exc->GS.loop )
{
- FT_UInt point = (FT_UInt)CUR.stack[--CUR.args];
+ FT_UInt point = (FT_UInt)exc->stack[--exc->args];
FT_F26Dot6 org_dist, cur_dist, new_dist;
/* check point bounds */
- if ( BOUNDS( point, CUR.zp2.n_points ) )
+ if ( BOUNDS( point, exc->zp2.n_points ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
continue;
}
if ( twilight )
- org_dist = CUR_Func_dualproj( &CUR.zp2.org[point], orus_base );
- else if ( CUR.metrics.x_scale == CUR.metrics.y_scale )
- org_dist = CUR_Func_dualproj( &CUR.zp2.orus[point], orus_base );
+ org_dist = DUALPROJ( &exc->zp2.org[point], orus_base );
+ else if ( exc->metrics.x_scale == exc->metrics.y_scale )
+ org_dist = DUALPROJ( &exc->zp2.orus[point], orus_base );
else
{
FT_Vector vec;
- vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x,
- CUR.metrics.x_scale );
- vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y,
- CUR.metrics.y_scale );
+ vec.x = FT_MulFix( exc->zp2.orus[point].x - orus_base->x,
+ exc->metrics.x_scale );
+ vec.y = FT_MulFix( exc->zp2.orus[point].y - orus_base->y,
+ exc->metrics.y_scale );
- org_dist = CUR_fast_dualproj( &vec );
+ org_dist = FAST_DUALPROJ( &vec );
}
- cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
+ cur_dist = PROJECT( &exc->zp2.cur[point], cur_base );
if ( org_dist )
{
@@ -7068,25 +6682,34 @@
/* This is the same as what MS does for the invalid case: */
/* */
/* delta = (Original_Pt - Original_RP1) - */
- /* (Current_Pt - Current_RP1) */
+ /* (Current_Pt - Current_RP1) ; */
/* */
/* In FreeType speak: */
/* */
- /* new_dist = cur_dist - */
- /* org_dist - cur_dist; */
+ /* delta = org_dist - cur_dist . */
+ /* */
+ /* We move `point' by `new_dist - cur_dist' after leaving */
+ /* this block, thus we have */
+ /* */
+ /* new_dist - cur_dist = delta , */
+ /* new_dist - cur_dist = org_dist - cur_dist , */
+ /* new_dist = org_dist . */
- new_dist = -org_dist;
+ new_dist = org_dist;
}
}
else
new_dist = 0;
- CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
+ exc->func_move( exc,
+ &exc->zp2,
+ (FT_UShort)point,
+ new_dist - cur_dist );
}
Fail:
- CUR.GS.loop = 1;
- CUR.new_top = CUR.args;
+ exc->GS.loop = 1;
+ exc->new_top = exc->args;
}
@@ -7097,7 +6720,8 @@
/* Stack: uint32 --> */
/* */
static void
- Ins_UTP( INS_ARG )
+ Ins_UTP( TT_ExecContext exc,
+ FT_Long* args )
{
FT_UShort point;
FT_Byte mask;
@@ -7105,22 +6729,22 @@
point = (FT_UShort)args[0];
- if ( BOUNDS( point, CUR.zp0.n_points ) )
+ if ( BOUNDS( point, exc->zp0.n_points ) )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
mask = 0xFF;
- if ( CUR.GS.freeVector.x != 0 )
+ if ( exc->GS.freeVector.x != 0 )
mask &= ~FT_CURVE_TAG_TOUCH_X;
- if ( CUR.GS.freeVector.y != 0 )
+ if ( exc->GS.freeVector.y != 0 )
mask &= ~FT_CURVE_TAG_TOUCH_Y;
- CUR.zp0.tags[point] &= mask;
+ exc->zp0.tags[point] &= mask;
}
@@ -7165,7 +6789,7 @@
FT_UInt ref2 )
{
FT_UInt i;
- FT_F26Dot6 orus1, orus2, org1, org2, delta1, delta2;
+ FT_F26Dot6 orus1, orus2, org1, org2, cur1, cur2, delta1, delta2;
if ( p1 > p2 )
@@ -7195,12 +6819,15 @@
org1 = worker->orgs[ref1].x;
org2 = worker->orgs[ref2].x;
- delta1 = worker->curs[ref1].x - org1;
- delta2 = worker->curs[ref2].x - org2;
+ cur1 = worker->curs[ref1].x;
+ cur2 = worker->curs[ref2].x;
+ delta1 = cur1 - org1;
+ delta2 = cur2 - org2;
- if ( orus1 == orus2 )
+ if ( cur1 == cur2 || orus1 == orus2 )
{
- /* simple shift of untouched points */
+
+ /* trivial snap or shift of untouched points */
for ( i = p1; i <= p2; i++ )
{
FT_F26Dot6 x = worker->orgs[i].x;
@@ -7208,9 +6835,13 @@
if ( x <= org1 )
x += delta1;
- else
+
+ else if ( x >= org2 )
x += delta2;
+ else
+ x = cur1;
+
worker->curs[i].x = x;
}
}
@@ -7237,12 +6868,10 @@
if ( !scale_valid )
{
scale_valid = 1;
- scale = FT_DivFix( org2 + delta2 - ( org1 + delta1 ),
- orus2 - orus1 );
+ scale = FT_DivFix( cur2 - cur1, orus2 - orus1 );
}
- x = ( org1 + delta1 ) +
- FT_MulFix( worker->orus[i].x - orus1, scale );
+ x = cur1 + FT_MulFix( worker->orus[i].x - orus1, scale );
}
worker->curs[i].x = x;
}
@@ -7257,7 +6886,7 @@
/* Stack: --> */
/* */
static void
- Ins_IUP( INS_ARG )
+ Ins_IUP( TT_ExecContext exc )
{
IUP_WorkerRec V;
FT_Byte mask;
@@ -7271,51 +6900,49 @@
FT_UInt point; /* current point */
FT_Short contour; /* current contour */
- FT_UNUSED_ARG;
-
/* ignore empty outlines */
- if ( CUR.pts.n_contours == 0 )
+ if ( exc->pts.n_contours == 0 )
return;
- if ( CUR.opcode & 1 )
+ if ( exc->opcode & 1 )
{
mask = FT_CURVE_TAG_TOUCH_X;
- V.orgs = CUR.pts.org;
- V.curs = CUR.pts.cur;
- V.orus = CUR.pts.orus;
+ V.orgs = exc->pts.org;
+ V.curs = exc->pts.cur;
+ V.orus = exc->pts.orus;
}
else
{
mask = FT_CURVE_TAG_TOUCH_Y;
- V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
- V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
- V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 );
+ V.orgs = (FT_Vector*)( (FT_Pos*)exc->pts.org + 1 );
+ V.curs = (FT_Vector*)( (FT_Pos*)exc->pts.cur + 1 );
+ V.orus = (FT_Vector*)( (FT_Pos*)exc->pts.orus + 1 );
}
- V.max_points = CUR.pts.n_points;
+ V.max_points = exc->pts.n_points;
contour = 0;
point = 0;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode )
{
- CUR.iup_called = TRUE;
- if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
+ exc->iup_called = TRUE;
+ if ( exc->sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
return;
}
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
do
{
- end_point = CUR.pts.contours[contour] - CUR.pts.first_point;
+ end_point = exc->pts.contours[contour] - exc->pts.first_point;
first_point = point;
- if ( BOUNDS ( end_point, CUR.pts.n_points ) )
- end_point = CUR.pts.n_points - 1;
+ if ( BOUNDS( end_point, exc->pts.n_points ) )
+ end_point = exc->pts.n_points - 1;
- while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 )
+ while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 )
point++;
if ( point <= end_point )
@@ -7327,7 +6954,7 @@
while ( point <= end_point )
{
- if ( ( CUR.pts.tags[point] & mask ) != 0 )
+ if ( ( exc->pts.tags[point] & mask ) != 0 )
{
_iup_worker_interpolate( &V,
cur_touched + 1,
@@ -7359,7 +6986,7 @@
}
}
contour++;
- } while ( contour < CUR.pts.n_contours );
+ } while ( contour < exc->pts.n_contours );
}
@@ -7370,61 +6997,63 @@
/* Stack: uint32 (2 * uint32)... --> */
/* */
static void
- Ins_DELTAP( INS_ARG )
+ Ins_DELTAP( TT_ExecContext exc,
+ FT_Long* args )
{
- FT_ULong k, nump;
+ FT_ULong nump, k;
FT_UShort A;
- FT_ULong C;
+ FT_ULong C, P;
FT_Long B;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
FT_UShort B1, B2;
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.iup_called &&
- ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
+ if ( SUBPIXEL_HINTING &&
+ exc->ignore_x_mode &&
+ exc->iup_called &&
+ ( exc->sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
goto Fail;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
/* Delta hinting is covered by US Patent 5159668. */
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
FT_Long n = args[0] * 2;
- if ( CUR.args < n )
+ if ( exc->args < n )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Too_Few_Arguments );
- n = CUR.args;
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Too_Few_Arguments );
+ n = exc->args;
}
- CUR.args -= n;
- CUR.new_top = CUR.args;
+ exc->args -= n;
+ exc->new_top = exc->args;
return;
}
#endif
+ P = (FT_ULong)exc->func_cur_ppem( exc );
nump = (FT_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 )
+ if ( exc->args < 2 )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Too_Few_Arguments );
- CUR.args = 0;
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Too_Few_Arguments );
+ exc->args = 0;
goto Fail;
}
- CUR.args -= 2;
+ exc->args -= 2;
- A = (FT_UShort)CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
+ A = (FT_UShort)exc->stack[exc->args + 1];
+ B = exc->stack[exc->args];
/* XXX: Because some popular fonts contain some invalid DeltaP */
/* instructions, we simply ignore them when the stacked */
@@ -7432,11 +7061,11 @@
/* 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 ) )
+ if ( !BOUNDS( A, exc->zp0.n_points ) )
{
C = ( (FT_ULong)B & 0xF0 ) >> 4;
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x5D:
break;
@@ -7450,14 +7079,14 @@
break;
}
- C += CUR.GS.delta_base;
+ C += exc->GS.delta_base;
- if ( CURRENT_Ppem() == (FT_Long)C )
+ if ( P == C )
{
B = ( (FT_ULong)B & 0xF ) - 8;
if ( B >= 0 )
B++;
- B = B * 64 / ( 1L << CUR.GS.delta_shift );
+ B *= 1L << ( 6 - exc->GS.delta_shift );
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
@@ -7466,79 +7095,70 @@
/*
* Allow delta move if
*
- * - not using ignore_x_mode rendering
- * - glyph is specifically set to allow it
- * - glyph is composite and freedom vector is not subpixel
- * vector
+ * - not using ignore_x_mode rendering,
+ * - glyph is specifically set to allow it, or
+ * - glyph is composite and freedom vector is not in subpixel
+ * direction.
*/
- if ( !CUR.ignore_x_mode ||
- ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
- ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) )
- CUR_Func_move( &CUR.zp0, A, B );
+ if ( !exc->ignore_x_mode ||
+ ( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
+ ( exc->is_composite && exc->GS.freeVector.y != 0 ) )
+ exc->func_move( exc, &exc->zp0, A, B );
- /* Otherwise apply subpixel hinting and */
- /* compatibility mode rules */
- else if ( CUR.ignore_x_mode )
+ /* Otherwise, apply subpixel hinting and compatibility mode */
+ /* rules, always skipping deltas in subpixel direction. */
+ else if ( exc->ignore_x_mode && exc->GS.freeVector.y != 0 )
{
- if ( CUR.GS.freeVector.y != 0 )
- B1 = CUR.zp0.cur[A].y;
- else
- B1 = CUR.zp0.cur[A].x;
+ /* save the y value of the point now; compare after move */
+ B1 = (FT_UShort)exc->zp0.cur[A].y;
-#if 0
- /* Standard Subpixel Hinting: Allow y move. */
- /* This messes up dejavu and may not be needed... */
- if ( !CUR.face->sph_compatibility_mode &&
- CUR.GS.freeVector.y != 0 )
- CUR_Func_move( &CUR.zp0, A, B );
- else
-#endif /* 0 */
+ /* Standard subpixel hinting: Allow y move for y-touched */
+ /* points. This messes up DejaVu ... */
+ if ( !exc->face->sph_compatibility_mode &&
+ ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+ exc->func_move( exc, &exc->zp0, A, B );
- /* Compatibility Mode: Allow x or y move if point touched in */
- /* Y direction. */
- if ( CUR.face->sph_compatibility_mode &&
- !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+ /* compatibility mode */
+ else if ( exc->face->sph_compatibility_mode &&
+ !( exc->sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
{
- /* save the y value of the point now; compare after move */
- B1 = CUR.zp0.cur[A].y;
-
- if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+ if ( exc->sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
B = FT_PIX_ROUND( B1 + B ) - B1;
/* Allow delta move if using sph_compatibility_mode, */
/* IUP has not been called, and point is touched on Y. */
- if ( !CUR.iup_called &&
- ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
- CUR_Func_move( &CUR.zp0, A, B );
+ if ( !exc->iup_called &&
+ ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+ exc->func_move( exc, &exc->zp0, A, B );
}
- B2 = CUR.zp0.cur[A].y;
+ B2 = (FT_UShort)exc->zp0.cur[A].y;
/* Reverse this move if it results in a disallowed move */
- if ( CUR.GS.freeVector.y != 0 &&
- ( ( CUR.face->sph_compatibility_mode &&
+ if ( exc->GS.freeVector.y != 0 &&
+ ( ( exc->face->sph_compatibility_mode &&
( B1 & 63 ) == 0 &&
( B2 & 63 ) != 0 ) ||
- ( ( CUR.sph_tweak_flags &
+ ( ( exc->sph_tweak_flags &
SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
( B1 & 63 ) != 0 &&
( B2 & 63 ) != 0 ) ) )
- CUR_Func_move( &CUR.zp0, A, -B );
+ exc->func_move( exc, &exc->zp0, A, -B );
}
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- CUR_Func_move( &CUR.zp0, A, B );
+ exc->func_move( exc, &exc->zp0, A, B );
}
}
else
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Invalid_Reference );
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
}
Fail:
- CUR.new_top = CUR.args;
+ exc->new_top = exc->args;
}
@@ -7549,55 +7169,57 @@
/* Stack: uint32 (2 * uint32)... --> */
/* */
static void
- Ins_DELTAC( INS_ARG )
+ Ins_DELTAC( TT_ExecContext exc,
+ FT_Long* args )
{
FT_ULong nump, k;
- FT_ULong A, C;
+ FT_ULong A, C, P;
FT_Long B;
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
/* Delta hinting is covered by US Patent 5159668. */
- if ( CUR.face->unpatented_hinting )
+ if ( exc->face->unpatented_hinting )
{
FT_Long n = args[0] * 2;
- if ( CUR.args < n )
+ if ( exc->args < n )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Too_Few_Arguments );
- n = CUR.args;
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Too_Few_Arguments );
+ n = exc->args;
}
- CUR.args -= n;
- CUR.new_top = CUR.args;
+ exc->args -= n;
+ exc->new_top = exc->args;
return;
}
#endif
+ P = (FT_ULong)exc->func_cur_ppem( exc );
nump = (FT_ULong)args[0];
for ( k = 1; k <= nump; k++ )
{
- if ( CUR.args < 2 )
+ if ( exc->args < 2 )
{
- if ( CUR.pedantic_hinting )
- CUR.error = FT_THROW( Too_Few_Arguments );
- CUR.args = 0;
+ if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Too_Few_Arguments );
+ exc->args = 0;
goto Fail;
}
- CUR.args -= 2;
+ exc->args -= 2;
- A = (FT_ULong)CUR.stack[CUR.args + 1];
- B = CUR.stack[CUR.args];
+ A = (FT_ULong)exc->stack[exc->args + 1];
+ B = exc->stack[exc->args];
- if ( BOUNDSL( A, CUR.cvtSize ) )
+ if ( BOUNDSL( A, exc->cvtSize ) )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
return;
}
}
@@ -7605,7 +7227,7 @@
{
C = ( (FT_ULong)B & 0xF0 ) >> 4;
- switch ( CUR.opcode )
+ switch ( exc->opcode )
{
case 0x73:
break;
@@ -7619,22 +7241,22 @@
break;
}
- C += CUR.GS.delta_base;
+ C += exc->GS.delta_base;
- if ( CURRENT_Ppem() == (FT_Long)C )
+ if ( P == C )
{
B = ( (FT_ULong)B & 0xF ) - 8;
if ( B >= 0 )
B++;
- B = B * 64 / ( 1L << CUR.GS.delta_shift );
+ B *= 1L << ( 6 - exc->GS.delta_shift );
- CUR_Func_move_cvt( A, B );
+ exc->func_move_cvt( exc, A, B );
}
}
}
Fail:
- CUR.new_top = CUR.args;
+ exc->new_top = exc->args;
}
@@ -7651,8 +7273,17 @@
/* Opcode range: 0x88 */
/* Stack: uint32 --> uint32 */
/* */
+ /* XXX: UNDOCUMENTED: Selector bits higher than 9 are currently (May */
+ /* 2015) not documented in the OpenType specification. */
+ /* */
+ /* Selector bit 11 is incorrectly described as bit 8, while the */
+ /* real meaning of bit 8 (vertical LCD subpixels) stays */
+ /* undocumented. The same mistake can be found in Greg Hitchcock's */
+ /* whitepaper. */
+ /* */
static void
- Ins_GETINFO( INS_ARG )
+ Ins_GETINFO( TT_ExecContext exc,
+ FT_Long* args )
{
FT_Long K;
@@ -7665,13 +7296,20 @@
/* Selector Bit: 0 */
/* Return Bit(s): 0-7 */
/* */
- if ( SUBPIXEL_HINTING &&
- ( args[0] & 1 ) != 0 &&
- CUR.ignore_x_mode )
+ if ( SUBPIXEL_HINTING &&
+ ( args[0] & 1 ) != 0 &&
+ exc->subpixel_hinting )
{
- K = CUR.rasterizer_version;
- FT_TRACE7(( "Setting rasterizer version %d\n",
- CUR.rasterizer_version ));
+ if ( exc->ignore_x_mode )
+ {
+ /* if in ClearType backwards compatibility mode, */
+ /* we sometimes change the TrueType version dynamically */
+ K = exc->rasterizer_version;
+ FT_TRACE6(( "Setting rasterizer version %d\n",
+ exc->rasterizer_version ));
+ }
+ else
+ K = TT_INTERPRETER_VERSION_38;
}
else
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
@@ -7683,7 +7321,7 @@
/* Selector Bit: 1 */
/* Return Bit(s): 8 */
/* */
- if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
+ if ( ( args[0] & 2 ) != 0 && exc->tt_metrics.rotated )
K |= 0x80;
/********************************/
@@ -7691,7 +7329,7 @@
/* Selector Bit: 2 */
/* Return Bit(s): 9 */
/* */
- if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
+ if ( ( args[0] & 4 ) != 0 && exc->tt_metrics.stretched )
K |= 1 << 8;
/********************************/
@@ -7699,35 +7337,24 @@
/* Selector Bit: 5 */
/* Return Bit(s): 12 */
/* */
- if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
+ if ( ( args[0] & 32 ) != 0 && exc->grayscale )
K |= 1 << 12;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- if ( SUBPIXEL_HINTING &&
- CUR.ignore_x_mode &&
- CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
+ if ( SUBPIXEL_HINTING &&
+ exc->rasterizer_version >= TT_INTERPRETER_VERSION_35 )
{
- /********************************/
- /* HINTING FOR GRAYSCALE */
- /* Selector Bit: 5 */
- /* Return Bit(s): 12 */
- /* */
- if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting )
- K |= 1 << 12;
- /********************************/
- /* HINTING FOR SUBPIXEL */
- /* Selector Bit: 6 */
- /* Return Bit(s): 13 */
- /* */
- if ( ( args[0] & 64 ) != 0 &&
- CUR.subpixel_hinting &&
- CUR.rasterizer_version >= 37 )
+ if ( exc->rasterizer_version >= 37 )
{
- K |= 1 << 13;
-
- /* the stuff below is irrelevant if subpixel_hinting is not set */
+ /********************************/
+ /* HINTING FOR SUBPIXEL */
+ /* Selector Bit: 6 */
+ /* Return Bit(s): 13 */
+ /* */
+ if ( ( args[0] & 64 ) != 0 && exc->subpixel_hinting )
+ K |= 1 << 13;
/********************************/
/* COMPATIBLE WIDTHS ENABLED */
@@ -7735,16 +7362,16 @@
/* Return Bit(s): 14 */
/* */
/* Functionality still needs to be added */
- if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths )
+ if ( ( args[0] & 128 ) != 0 && exc->compatible_widths )
K |= 1 << 14;
/********************************/
- /* SYMMETRICAL SMOOTHING */
+ /* VERTICAL LCD SUBPIXELS? */
/* Selector Bit: 8 */
/* Return Bit(s): 15 */
/* */
/* Functionality still needs to be added */
- if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing )
+ if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd )
K |= 1 << 15;
/********************************/
@@ -7753,10 +7380,10 @@
/* Return Bit(s): 16 */
/* */
/* Functionality still needs to be added */
- if ( ( args[0] & 512 ) != 0 && CUR.bgr )
+ if ( ( args[0] & 512 ) != 0 && exc->bgr )
K |= 1 << 16;
- if ( CUR.rasterizer_version >= 38 )
+ if ( exc->rasterizer_version >= 38 )
{
/********************************/
/* SUBPIXEL POSITIONED? */
@@ -7764,8 +7391,26 @@
/* Return Bit(s): 17 */
/* */
/* Functionality still needs to be added */
- if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned )
+ if ( ( args[0] & 1024 ) != 0 && exc->subpixel_positioned )
K |= 1 << 17;
+
+ /********************************/
+ /* SYMMETRICAL SMOOTHING */
+ /* Selector Bit: 11 */
+ /* Return Bit(s): 18 */
+ /* */
+ /* Functionality still needs to be added */
+ if ( ( args[0] & 2048 ) != 0 && exc->symmetrical_smoothing )
+ K |= 1 << 18;
+
+ /********************************/
+ /* GRAY CLEARTYPE */
+ /* Selector Bit: 12 */
+ /* Return Bit(s): 19 */
+ /* */
+ /* Functionality still needs to be added */
+ if ( ( args[0] & 4096 ) != 0 && exc->gray_cleartype )
+ K |= 1 << 19;
}
}
}
@@ -7777,332 +7422,43 @@
static void
- Ins_UNKNOWN( INS_ARG )
+ Ins_UNKNOWN( TT_ExecContext exc )
{
- TT_DefRecord* def = CUR.IDefs;
- TT_DefRecord* limit = def + CUR.numIDefs;
-
- FT_UNUSED_ARG;
+ TT_DefRecord* def = exc->IDefs;
+ TT_DefRecord* limit = def + exc->numIDefs;
for ( ; def < limit; def++ )
{
- if ( (FT_Byte)def->opc == CUR.opcode && def->active )
+ if ( (FT_Byte)def->opc == exc->opcode && def->active )
{
TT_CallRec* call;
- if ( CUR.callTop >= CUR.callSize )
+ if ( exc->callTop >= exc->callSize )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
return;
}
- call = CUR.callStack + CUR.callTop++;
+ call = exc->callStack + exc->callTop++;
- call->Caller_Range = CUR.curRange;
- call->Caller_IP = CUR.IP + 1;
+ call->Caller_Range = exc->curRange;
+ call->Caller_IP = exc->IP + 1;
call->Cur_Count = 1;
- call->Cur_Restart = def->start;
- call->Cur_End = def->end;
+ call->Def = def;
- INS_Goto_CodeRange( def->range, def->start );
+ Ins_Goto_CodeRange( exc, def->range, def->start );
- CUR.step_ins = FALSE;
+ exc->step_ins = FALSE;
return;
}
}
- CUR.error = FT_THROW( Invalid_Opcode );
+ exc->error = FT_THROW( 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_0x28 */ 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_0x7B */ Ins_UNKNOWN,
- /* RUTG */ Ins_RUTG,
- /* RDTG */ Ins_RDTG,
- /* SANGW */ Ins_SANGW,
- /* AA */ Ins_AA,
-
- /* FlipPT */ Ins_FLIPPT,
- /* FlipRgON */ Ins_FLIPRGON,
- /* FlipRgOFF */ Ins_FLIPRGOFF,
- /* INS_0x83 */ Ins_UNKNOWN,
- /* INS_0x84 */ 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_0x8F */ Ins_UNKNOWN,
-
- /* INS_0x90 */ Ins_UNKNOWN,
- /* INS_0x91 */ Ins_UNKNOWN,
- /* INS_0x92 */ Ins_UNKNOWN,
- /* INS_0x93 */ Ins_UNKNOWN,
- /* INS_0x94 */ Ins_UNKNOWN,
- /* INS_0x95 */ Ins_UNKNOWN,
- /* INS_0x96 */ Ins_UNKNOWN,
- /* INS_0x97 */ Ins_UNKNOWN,
- /* INS_0x98 */ Ins_UNKNOWN,
- /* INS_0x99 */ Ins_UNKNOWN,
- /* INS_0x9A */ Ins_UNKNOWN,
- /* INS_0x9B */ Ins_UNKNOWN,
- /* INS_0x9C */ Ins_UNKNOWN,
- /* INS_0x9D */ Ins_UNKNOWN,
- /* INS_0x9E */ Ins_UNKNOWN,
- /* INS_0x9F */ Ins_UNKNOWN,
-
- /* INS_0xA0 */ Ins_UNKNOWN,
- /* INS_0xA1 */ Ins_UNKNOWN,
- /* INS_0xA2 */ Ins_UNKNOWN,
- /* INS_0xA3 */ Ins_UNKNOWN,
- /* INS_0xA4 */ Ins_UNKNOWN,
- /* INS_0xA5 */ Ins_UNKNOWN,
- /* INS_0xA6 */ Ins_UNKNOWN,
- /* INS_0xA7 */ Ins_UNKNOWN,
- /* INS_0xA8 */ Ins_UNKNOWN,
- /* INS_0xA9 */ Ins_UNKNOWN,
- /* INS_0xAA */ Ins_UNKNOWN,
- /* INS_0xAB */ Ins_UNKNOWN,
- /* INS_0xAC */ Ins_UNKNOWN,
- /* INS_0xAD */ Ins_UNKNOWN,
- /* INS_0xAE */ Ins_UNKNOWN,
- /* INS_0xAF */ 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 /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
-
/*************************************************************************/
/* */
/* RUN */
@@ -8130,8 +7486,6 @@
/* */
/* THIS IS THE INTERPRETER'S MAIN LOOP. */
/* */
- /* Instructions appear in the specification's order. */
- /* */
/*************************************************************************/
@@ -8157,85 +7511,100 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
- cur = *exc;
-#endif
-
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- CUR.iup_called = FALSE;
+ exc->iup_called = FALSE;
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
- /* set CVT functions */
- CUR.tt_metrics.ratio = 0;
- if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+ /* set PPEM and CVT functions */
+ exc->tt_metrics.ratio = 0;
+ if ( exc->metrics.x_ppem != exc->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;
+ exc->func_cur_ppem = Current_Ppem_Stretched;
+ exc->func_read_cvt = Read_CVT_Stretched;
+ exc->func_write_cvt = Write_CVT_Stretched;
+ exc->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;
+ exc->func_cur_ppem = Current_Ppem;
+ exc->func_read_cvt = Read_CVT;
+ exc->func_write_cvt = Write_CVT;
+ exc->func_move_cvt = Move_CVT;
}
- COMPUTE_Funcs();
- COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+ Compute_Funcs( exc );
+ Compute_Round( exc, (FT_Byte)exc->GS.round_state );
do
{
- CUR.opcode = CUR.code[CUR.IP];
+ exc->opcode = exc->code[exc->IP];
- FT_TRACE7(( " " ));
- FT_TRACE7(( opcode_name[CUR.opcode] ));
- FT_TRACE7(( "\n" ));
-
- if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+#ifdef FT_DEBUG_LEVEL_TRACE
{
- if ( CUR.IP + 1 >= CUR.codeSize )
+ FT_Long cnt = FT_MIN( 8, exc->top );
+ FT_Long n;
+
+
+ /* if tracing level is 7, show current code position */
+ /* and the first few stack elements also */
+ FT_TRACE6(( " " ));
+ FT_TRACE7(( "%06d ", exc->IP ));
+ FT_TRACE6(( opcode_name[exc->opcode] + 2 ));
+ FT_TRACE7(( "%*s", *opcode_name[exc->opcode] == 'A'
+ ? 2
+ : 12 - ( *opcode_name[exc->opcode] - '0' ),
+ "#" ));
+ for ( n = 1; n <= cnt; n++ )
+ FT_TRACE7(( " %d", exc->stack[exc->top - n] ));
+ FT_TRACE6(( "\n" ));
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+ if ( ( exc->length = opcode_length[exc->opcode] ) < 0 )
+ {
+ if ( exc->IP + 1 >= exc->codeSize )
goto LErrorCodeOverflow_;
- CUR.length = 2 - CUR.length * CUR.code[CUR.IP + 1];
+ exc->length = 2 - exc->length * exc->code[exc->IP + 1];
}
- if ( CUR.IP + CUR.length > CUR.codeSize )
+ if ( exc->IP + exc->length > exc->codeSize )
goto LErrorCodeOverflow_;
/* First, let's check for empty stack and overflow */
- CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+ 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. */
- if ( CUR.args < 0 )
+ if ( exc->args < 0 )
{
- if ( CUR.pedantic_hinting )
+ if ( exc->pedantic_hinting )
{
- CUR.error = FT_THROW( Too_Few_Arguments );
+ exc->error = FT_THROW( Too_Few_Arguments );
goto LErrorLabel_;
}
/* push zeroes onto the stack */
- for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
- CUR.stack[i] = 0;
- CUR.args = 0;
+ for ( i = 0; i < Pop_Push_Count[exc->opcode] >> 4; i++ )
+ exc->stack[i] = 0;
+ exc->args = 0;
}
- CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+ exc->new_top = exc->args + ( Pop_Push_Count[exc->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 )
+ if ( exc->new_top > exc->stackSize )
{
- CUR.error = FT_THROW( Stack_Overflow );
+ exc->error = FT_THROW( Stack_Overflow );
goto LErrorLabel_;
}
- CUR.step_ins = TRUE;
- CUR.error = FT_Err_Ok;
+ exc->step_ins = TRUE;
+ exc->error = FT_Err_Ok;
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
@@ -8243,17 +7612,17 @@
{
for ( i = 0; i < opcode_patterns; i++ )
{
- if ( opcode_pointer[i] < opcode_size[i] &&
- CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+ if ( opcode_pointer[i] < opcode_size[i] &&
+ exc->opcode == opcode_pattern[i][opcode_pointer[i]] )
{
opcode_pointer[i] += 1;
if ( opcode_pointer[i] == opcode_size[i] )
{
- FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n",
+ FT_TRACE6(( "sph: opcode ptrn: %d, %s %s\n",
i,
- CUR.face->root.family_name,
- CUR.face->root.style_name ));
+ exc->face->root.family_name,
+ exc->face->root.style_name ));
switch ( i )
{
@@ -8270,15 +7639,9 @@
#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
-
{
- FT_Long* args = CUR.stack + CUR.args;
- FT_Byte opcode = CUR.opcode;
-
-
-#undef ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref
+ FT_Long* args = exc->stack + exc->args;
+ FT_Byte opcode = exc->opcode;
switch ( opcode )
@@ -8289,581 +7652,543 @@
case 0x03: /* SPvTCA x */
case 0x04: /* SFvTCA y */
case 0x05: /* SFvTCA x */
- {
- FT_Short AA, BB;
-
-
- AA = (FT_Short)( ( opcode & 1 ) << 14 );
- BB = (FT_Short)( AA ^ 0x4000 );
-
- if ( opcode < 4 )
- {
- CUR.GS.projVector.x = AA;
- CUR.GS.projVector.y = BB;
-
- CUR.GS.dualVector.x = AA;
- CUR.GS.dualVector.y = BB;
- }
- else
- {
- GUESS_VECTOR( projVector );
- }
-
- if ( ( opcode & 2 ) == 0 )
- {
- CUR.GS.freeVector.x = AA;
- CUR.GS.freeVector.y = BB;
- }
- else
- {
- GUESS_VECTOR( freeVector );
- }
-
- COMPUTE_Funcs();
- }
+ Ins_SxyTCA( exc );
break;
case 0x06: /* SPvTL // */
case 0x07: /* SPvTL + */
- DO_SPVTL
+ Ins_SPVTL( exc, args );
break;
case 0x08: /* SFvTL // */
case 0x09: /* SFvTL + */
- DO_SFVTL
+ Ins_SFVTL( exc, args );
break;
case 0x0A: /* SPvFS */
- DO_SPVFS
+ Ins_SPVFS( exc, args );
break;
case 0x0B: /* SFvFS */
- DO_SFVFS
+ Ins_SFVFS( exc, args );
break;
- case 0x0C: /* GPV */
- DO_GPV
+ case 0x0C: /* GPv */
+ Ins_GPV( exc, args );
break;
- case 0x0D: /* GFV */
- DO_GFV
+ case 0x0D: /* GFv */
+ Ins_GFV( exc, args );
break;
case 0x0E: /* SFvTPv */
- DO_SFVTPV
+ Ins_SFVTPV( exc );
break;
case 0x0F: /* ISECT */
- Ins_ISECT( EXEC_ARG_ args );
+ Ins_ISECT( exc, args );
break;
case 0x10: /* SRP0 */
- DO_SRP0
+ Ins_SRP0( exc, args );
break;
case 0x11: /* SRP1 */
- DO_SRP1
+ Ins_SRP1( exc, args );
break;
case 0x12: /* SRP2 */
- DO_SRP2
+ Ins_SRP2( exc, args );
break;
case 0x13: /* SZP0 */
- Ins_SZP0( EXEC_ARG_ args );
+ Ins_SZP0( exc, args );
break;
case 0x14: /* SZP1 */
- Ins_SZP1( EXEC_ARG_ args );
+ Ins_SZP1( exc, args );
break;
case 0x15: /* SZP2 */
- Ins_SZP2( EXEC_ARG_ args );
+ Ins_SZP2( exc, args );
break;
case 0x16: /* SZPS */
- Ins_SZPS( EXEC_ARG_ args );
+ Ins_SZPS( exc, args );
break;
case 0x17: /* SLOOP */
- DO_SLOOP
+ Ins_SLOOP( exc, args );
break;
case 0x18: /* RTG */
- DO_RTG
+ Ins_RTG( exc );
break;
case 0x19: /* RTHG */
- DO_RTHG
+ Ins_RTHG( exc );
break;
case 0x1A: /* SMD */
- DO_SMD
+ Ins_SMD( exc, args );
break;
case 0x1B: /* ELSE */
- Ins_ELSE( EXEC_ARG_ args );
+ Ins_ELSE( exc );
break;
case 0x1C: /* JMPR */
- DO_JMPR
+ Ins_JMPR( exc, args );
break;
case 0x1D: /* SCVTCI */
- DO_SCVTCI
+ Ins_SCVTCI( exc, args );
break;
case 0x1E: /* SSWCI */
- DO_SSWCI
+ Ins_SSWCI( exc, args );
break;
case 0x1F: /* SSW */
- DO_SSW
+ Ins_SSW( exc, args );
break;
case 0x20: /* DUP */
- DO_DUP
+ Ins_DUP( args );
break;
case 0x21: /* POP */
- /* nothing :-) */
+ Ins_POP();
break;
case 0x22: /* CLEAR */
- DO_CLEAR
+ Ins_CLEAR( exc );
break;
case 0x23: /* SWAP */
- DO_SWAP
+ Ins_SWAP( args );
break;
case 0x24: /* DEPTH */
- DO_DEPTH
+ Ins_DEPTH( exc, args );
break;
case 0x25: /* CINDEX */
- DO_CINDEX
+ Ins_CINDEX( exc, args );
break;
case 0x26: /* MINDEX */
- Ins_MINDEX( EXEC_ARG_ args );
+ Ins_MINDEX( exc, args );
break;
case 0x27: /* ALIGNPTS */
- Ins_ALIGNPTS( EXEC_ARG_ args );
+ Ins_ALIGNPTS( exc, args );
break;
case 0x28: /* ???? */
- Ins_UNKNOWN( EXEC_ARG_ args );
+ Ins_UNKNOWN( exc );
break;
case 0x29: /* UTP */
- Ins_UTP( EXEC_ARG_ args );
+ Ins_UTP( exc, args );
break;
case 0x2A: /* LOOPCALL */
- Ins_LOOPCALL( EXEC_ARG_ args );
+ Ins_LOOPCALL( exc, args );
break;
case 0x2B: /* CALL */
- Ins_CALL( EXEC_ARG_ args );
+ Ins_CALL( exc, args );
break;
case 0x2C: /* FDEF */
- Ins_FDEF( EXEC_ARG_ args );
+ Ins_FDEF( exc, args );
break;
case 0x2D: /* ENDF */
- Ins_ENDF( EXEC_ARG_ args );
+ Ins_ENDF( exc );
break;
case 0x2E: /* MDAP */
case 0x2F: /* MDAP */
- Ins_MDAP( EXEC_ARG_ args );
+ Ins_MDAP( exc, args );
break;
case 0x30: /* IUP */
case 0x31: /* IUP */
- Ins_IUP( EXEC_ARG_ args );
+ Ins_IUP( exc );
break;
case 0x32: /* SHP */
case 0x33: /* SHP */
- Ins_SHP( EXEC_ARG_ args );
+ Ins_SHP( exc );
break;
case 0x34: /* SHC */
case 0x35: /* SHC */
- Ins_SHC( EXEC_ARG_ args );
+ Ins_SHC( exc, args );
break;
case 0x36: /* SHZ */
case 0x37: /* SHZ */
- Ins_SHZ( EXEC_ARG_ args );
+ Ins_SHZ( exc, args );
break;
case 0x38: /* SHPIX */
- Ins_SHPIX( EXEC_ARG_ args );
+ Ins_SHPIX( exc, args );
break;
case 0x39: /* IP */
- Ins_IP( EXEC_ARG_ args );
+ Ins_IP( exc );
break;
case 0x3A: /* MSIRP */
case 0x3B: /* MSIRP */
- Ins_MSIRP( EXEC_ARG_ args );
+ Ins_MSIRP( exc, args );
break;
case 0x3C: /* AlignRP */
- Ins_ALIGNRP( EXEC_ARG_ args );
+ Ins_ALIGNRP( exc );
break;
case 0x3D: /* RTDG */
- DO_RTDG
+ Ins_RTDG( exc );
break;
case 0x3E: /* MIAP */
case 0x3F: /* MIAP */
- Ins_MIAP( EXEC_ARG_ args );
+ Ins_MIAP( exc, args );
break;
case 0x40: /* NPUSHB */
- Ins_NPUSHB( EXEC_ARG_ args );
+ Ins_NPUSHB( exc, args );
break;
case 0x41: /* NPUSHW */
- Ins_NPUSHW( EXEC_ARG_ args );
+ Ins_NPUSHW( exc, args );
break;
case 0x42: /* WS */
- DO_WS
- break;
-
- Set_Invalid_Ref:
- CUR.error = FT_THROW( Invalid_Reference );
+ Ins_WS( exc, args );
break;
case 0x43: /* RS */
- DO_RS
+ Ins_RS( exc, args );
break;
case 0x44: /* WCVTP */
- DO_WCVTP
+ Ins_WCVTP( exc, args );
break;
case 0x45: /* RCVT */
- DO_RCVT
+ Ins_RCVT( exc, args );
break;
case 0x46: /* GC */
case 0x47: /* GC */
- Ins_GC( EXEC_ARG_ args );
+ Ins_GC( exc, args );
break;
case 0x48: /* SCFS */
- Ins_SCFS( EXEC_ARG_ args );
+ Ins_SCFS( exc, args );
break;
case 0x49: /* MD */
case 0x4A: /* MD */
- Ins_MD( EXEC_ARG_ args );
+ Ins_MD( exc, args );
break;
case 0x4B: /* MPPEM */
- DO_MPPEM
+ Ins_MPPEM( exc, args );
break;
case 0x4C: /* MPS */
- DO_MPS
+ Ins_MPS( exc, args );
break;
case 0x4D: /* FLIPON */
- DO_FLIPON
+ Ins_FLIPON( exc );
break;
case 0x4E: /* FLIPOFF */
- DO_FLIPOFF
+ Ins_FLIPOFF( exc );
break;
case 0x4F: /* DEBUG */
- DO_DEBUG
+ Ins_DEBUG( exc );
break;
case 0x50: /* LT */
- DO_LT
+ Ins_LT( args );
break;
case 0x51: /* LTEQ */
- DO_LTEQ
+ Ins_LTEQ( args );
break;
case 0x52: /* GT */
- DO_GT
+ Ins_GT( args );
break;
case 0x53: /* GTEQ */
- DO_GTEQ
+ Ins_GTEQ( args );
break;
case 0x54: /* EQ */
- DO_EQ
+ Ins_EQ( args );
break;
case 0x55: /* NEQ */
- DO_NEQ
+ Ins_NEQ( args );
break;
case 0x56: /* ODD */
- DO_ODD
+ Ins_ODD( exc, args );
break;
case 0x57: /* EVEN */
- DO_EVEN
+ Ins_EVEN( exc, args );
break;
case 0x58: /* IF */
- Ins_IF( EXEC_ARG_ args );
+ Ins_IF( exc, args );
break;
case 0x59: /* EIF */
- /* do nothing */
+ Ins_EIF();
break;
case 0x5A: /* AND */
- DO_AND
+ Ins_AND( args );
break;
case 0x5B: /* OR */
- DO_OR
+ Ins_OR( args );
break;
case 0x5C: /* NOT */
- DO_NOT
+ Ins_NOT( args );
break;
case 0x5D: /* DELTAP1 */
- Ins_DELTAP( EXEC_ARG_ args );
+ Ins_DELTAP( exc, args );
break;
case 0x5E: /* SDB */
- DO_SDB
+ Ins_SDB( exc, args );
break;
case 0x5F: /* SDS */
- DO_SDS
+ Ins_SDS( exc, args );
break;
case 0x60: /* ADD */
- DO_ADD
+ Ins_ADD( args );
break;
case 0x61: /* SUB */
- DO_SUB
+ Ins_SUB( args );
break;
case 0x62: /* DIV */
- DO_DIV
+ Ins_DIV( exc, args );
break;
case 0x63: /* MUL */
- DO_MUL
+ Ins_MUL( args );
break;
case 0x64: /* ABS */
- DO_ABS
+ Ins_ABS( args );
break;
case 0x65: /* NEG */
- DO_NEG
+ Ins_NEG( args );
break;
case 0x66: /* FLOOR */
- DO_FLOOR
+ Ins_FLOOR( args );
break;
case 0x67: /* CEILING */
- DO_CEILING
+ Ins_CEILING( args );
break;
case 0x68: /* ROUND */
case 0x69: /* ROUND */
case 0x6A: /* ROUND */
case 0x6B: /* ROUND */
- DO_ROUND
+ Ins_ROUND( exc, args );
break;
case 0x6C: /* NROUND */
case 0x6D: /* NROUND */
case 0x6E: /* NRRUND */
case 0x6F: /* NROUND */
- DO_NROUND
+ Ins_NROUND( exc, args );
break;
case 0x70: /* WCVTF */
- DO_WCVTF
+ Ins_WCVTF( exc, args );
break;
case 0x71: /* DELTAP2 */
case 0x72: /* DELTAP3 */
- Ins_DELTAP( EXEC_ARG_ args );
+ Ins_DELTAP( exc, args );
break;
case 0x73: /* DELTAC0 */
case 0x74: /* DELTAC1 */
case 0x75: /* DELTAC2 */
- Ins_DELTAC( EXEC_ARG_ args );
+ Ins_DELTAC( exc, args );
break;
case 0x76: /* SROUND */
- DO_SROUND
+ Ins_SROUND( exc, args );
break;
case 0x77: /* S45Round */
- DO_S45ROUND
+ Ins_S45ROUND( exc, args );
break;
case 0x78: /* JROT */
- DO_JROT
+ Ins_JROT( exc, args );
break;
case 0x79: /* JROF */
- DO_JROF
+ Ins_JROF( exc, args );
break;
case 0x7A: /* ROFF */
- DO_ROFF
+ Ins_ROFF( exc );
break;
case 0x7B: /* ???? */
- Ins_UNKNOWN( EXEC_ARG_ args );
+ Ins_UNKNOWN( exc );
break;
case 0x7C: /* RUTG */
- DO_RUTG
+ Ins_RUTG( exc );
break;
case 0x7D: /* RDTG */
- DO_RDTG
+ Ins_RDTG( exc );
break;
case 0x7E: /* SANGW */
- case 0x7F: /* AA */
- /* nothing - obsolete */
+ Ins_SANGW();
+ break;
+
+ case 0x7F: /* AA */
+ Ins_AA();
break;
case 0x80: /* FLIPPT */
- Ins_FLIPPT( EXEC_ARG_ args );
+ Ins_FLIPPT( exc );
break;
case 0x81: /* FLIPRGON */
- Ins_FLIPRGON( EXEC_ARG_ args );
+ Ins_FLIPRGON( exc, args );
break;
case 0x82: /* FLIPRGOFF */
- Ins_FLIPRGOFF( EXEC_ARG_ args );
+ Ins_FLIPRGOFF( exc, args );
break;
case 0x83: /* UNKNOWN */
case 0x84: /* UNKNOWN */
- Ins_UNKNOWN( EXEC_ARG_ args );
+ Ins_UNKNOWN( exc );
break;
case 0x85: /* SCANCTRL */
- Ins_SCANCTRL( EXEC_ARG_ args );
+ Ins_SCANCTRL( exc, args );
break;
- case 0x86: /* SDPVTL */
- case 0x87: /* SDPVTL */
- Ins_SDPVTL( EXEC_ARG_ args );
+ case 0x86: /* SDPvTL */
+ case 0x87: /* SDPvTL */
+ Ins_SDPVTL( exc, args );
break;
case 0x88: /* GETINFO */
- Ins_GETINFO( EXEC_ARG_ args );
+ Ins_GETINFO( exc, args );
break;
case 0x89: /* IDEF */
- Ins_IDEF( EXEC_ARG_ args );
+ Ins_IDEF( exc, args );
break;
case 0x8A: /* ROLL */
- Ins_ROLL( EXEC_ARG_ args );
+ Ins_ROLL( args );
break;
case 0x8B: /* MAX */
- DO_MAX
+ Ins_MAX( args );
break;
case 0x8C: /* MIN */
- DO_MIN
+ Ins_MIN( args );
break;
case 0x8D: /* SCANTYPE */
- Ins_SCANTYPE( EXEC_ARG_ args );
+ Ins_SCANTYPE( exc, args );
break;
case 0x8E: /* INSTCTRL */
- Ins_INSTCTRL( EXEC_ARG_ args );
+ Ins_INSTCTRL( exc, args );
break;
case 0x8F:
- Ins_UNKNOWN( EXEC_ARG_ args );
+ Ins_UNKNOWN( exc );
break;
default:
if ( opcode >= 0xE0 )
- Ins_MIRP( EXEC_ARG_ args );
+ Ins_MIRP( exc, args );
else if ( opcode >= 0xC0 )
- Ins_MDRP( EXEC_ARG_ args );
+ Ins_MDRP( exc, args );
else if ( opcode >= 0xB8 )
- Ins_PUSHW( EXEC_ARG_ args );
+ Ins_PUSHW( exc, args );
else if ( opcode >= 0xB0 )
- Ins_PUSHB( EXEC_ARG_ args );
+ Ins_PUSHB( exc, args );
else
- Ins_UNKNOWN( EXEC_ARG_ args );
+ Ins_UNKNOWN( exc );
}
-
}
-#else
-
- Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
-
-#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
-
- if ( CUR.error )
+ if ( exc->error )
{
- switch ( CUR.error )
+ switch ( exc->error )
{
/* looking for redefined instructions */
case FT_ERR( Invalid_Opcode ):
{
- TT_DefRecord* def = CUR.IDefs;
- TT_DefRecord* limit = def + CUR.numIDefs;
+ TT_DefRecord* def = exc->IDefs;
+ TT_DefRecord* limit = def + exc->numIDefs;
for ( ; def < limit; def++ )
{
- if ( def->active && CUR.opcode == (FT_Byte)def->opc )
+ if ( def->active && exc->opcode == (FT_Byte)def->opc )
{
TT_CallRec* callrec;
- if ( CUR.callTop >= CUR.callSize )
+ if ( exc->callTop >= exc->callSize )
{
- CUR.error = FT_THROW( Invalid_Reference );
+ exc->error = FT_THROW( Invalid_Reference );
goto LErrorLabel_;
}
- callrec = &CUR.callStack[CUR.callTop];
+ callrec = &exc->callStack[exc->callTop];
- callrec->Caller_Range = CUR.curRange;
- callrec->Caller_IP = CUR.IP + 1;
+ callrec->Caller_Range = exc->curRange;
+ callrec->Caller_IP = exc->IP + 1;
callrec->Cur_Count = 1;
- callrec->Cur_Restart = def->start;
- callrec->Cur_End = def->end;
+ callrec->Def = def;
- if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+ if ( Ins_Goto_CodeRange( exc,
+ def->range,
+ def->start ) == FAILURE )
goto LErrorLabel_;
goto LSuiteLabel_;
@@ -8871,7 +8196,7 @@
}
}
- CUR.error = FT_THROW( Invalid_Opcode );
+ exc->error = FT_THROW( Invalid_Opcode );
goto LErrorLabel_;
#if 0
@@ -8889,56 +8214,49 @@
}
}
- CUR.top = CUR.new_top;
+ exc->top = exc->new_top;
- if ( CUR.step_ins )
- CUR.IP += CUR.length;
+ if ( exc->step_ins )
+ exc->IP += exc->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 )
+ if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
return FT_THROW( Execution_Too_Long );
LSuiteLabel_:
- if ( CUR.IP >= CUR.codeSize )
+ if ( exc->IP >= exc->codeSize )
{
- if ( CUR.callTop > 0 )
+ if ( exc->callTop > 0 )
{
- CUR.error = FT_THROW( Code_Overflow );
+ exc->error = FT_THROW( Code_Overflow );
goto LErrorLabel_;
}
else
goto LNo_Error_;
}
- } while ( !CUR.instruction_trap );
+ } while ( !exc->instruction_trap );
LNo_Error_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
- *exc = cur;
-#endif
-
return FT_Err_Ok;
LErrorCodeOverflow_:
- CUR.error = FT_THROW( Code_Overflow );
+ exc->error = FT_THROW( Code_Overflow );
LErrorLabel_:
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
- *exc = cur;
-#endif
-
/* If any errors have occurred, function tables may be broken. */
/* Force a re-execution of `prep' and `fpgm' tables if no */
/* bytecode debugger is run. */
- if ( CUR.error && !CUR.instruction_trap )
+ if ( exc->error &&
+ !exc->instruction_trap &&
+ exc->curRange == tt_coderange_glyph )
{
- FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
- exc->size->cvt_ready = FALSE;
+ FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error ));
+ exc->size->bytecode_ready = -1;
+ exc->size->cvt_ready = -1;
}
- return CUR.error;
+ return exc->error;
}
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 69f5011..32706d0 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
/* */
/* TrueType bytecode interpreter (specification). */
/* */
-/* Copyright 1996-2007, 2010, 2012-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,23 +26,6 @@
FT_BEGIN_HEADER
-#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */
-
-#define EXEC_OP_ TT_ExecContext exc,
-#define EXEC_OP TT_ExecContext exc
-#define EXEC_ARG_ exc,
-#define EXEC_ARG exc
-
-#else /* static implementation */
-
-#define EXEC_OP_ /* void */
-#define EXEC_OP /* void */
-#define EXEC_ARG_ /* void */
-#define EXEC_ARG /* void */
-
-#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
-
-
/*************************************************************************/
/* */
/* Rounding mode constants. */
@@ -67,29 +50,38 @@
/* Rounding function */
typedef FT_F26Dot6
- (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance,
- FT_F26Dot6 compensation );
+ (*TT_Round_Func)( TT_ExecContext exc,
+ FT_F26Dot6 distance,
+ FT_F26Dot6 compensation );
/* Point displacement along the freedom vector routine */
typedef void
- (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone zone,
- FT_UShort point,
- FT_F26Dot6 distance );
+ (*TT_Move_Func)( TT_ExecContext exc,
+ TT_GlyphZone zone,
+ FT_UShort point,
+ FT_F26Dot6 distance );
/* Distance projection along one of the projection vectors */
typedef FT_F26Dot6
- (*TT_Project_Func)( EXEC_OP_ FT_Pos dx,
- FT_Pos dy );
+ (*TT_Project_Func)( TT_ExecContext exc,
+ FT_Pos dx,
+ FT_Pos dy );
+
+ /* getting current ppem. Take care of non-square pixels if necessary */
+ typedef FT_Long
+ (*TT_Cur_Ppem_Func)( TT_ExecContext exc );
/* reading a cvt value. Take care of non-square pixels if necessary */
typedef FT_F26Dot6
- (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx );
+ (*TT_Get_CVT_Func)( TT_ExecContext exc,
+ FT_ULong idx );
/* setting or moving a cvt value. Take care of non-square pixels */
/* if necessary */
typedef void
- (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong idx,
- FT_F26Dot6 value );
+ (*TT_Set_CVT_Func)( TT_ExecContext exc,
+ FT_ULong idx,
+ FT_F26Dot6 value );
/*************************************************************************/
@@ -101,8 +93,8 @@
FT_Int Caller_Range;
FT_Long Caller_IP;
FT_Long Cur_Count;
- FT_Long Cur_Restart;
- FT_Long Cur_End;
+
+ TT_DefRecord *Def; /* either FDEF or IDEF */
} TT_CallRec, *TT_CallStack;
@@ -166,11 +158,11 @@
FT_Long top; /* top of exec. stack */
- FT_UInt stackSize; /* size of exec. stack */
+ FT_Long stackSize; /* size of exec. stack */
FT_Long* stack; /* current exec. stack */
FT_Long args;
- FT_UInt new_top; /* new top after exec. */
+ FT_Long new_top; /* new top after exec. */
TT_GlyphZoneRec zp0, /* zone records */
zp1,
@@ -228,11 +220,6 @@
FT_F26Dot6 phase; /* `SuperRounding' */
FT_F26Dot6 threshold;
-#if 0
- /* this seems to be unused */
- FT_Int cur_ppem; /* ppem along the current proj vector */
-#endif
-
FT_Bool instruction_trap; /* If `True', the interpreter will */
/* exit after each instruction */
@@ -254,6 +241,8 @@
TT_Move_Func func_move; /* current point move function */
TT_Move_Func func_move_orig; /* move original position function */
+ TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */
+
TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */
TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */
TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */
@@ -263,20 +252,22 @@
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
TT_Round_Func func_round_sphn; /* subpixel rounding function */
- FT_Bool grayscale_hinting; /* Using grayscale hinting? */
FT_Bool subpixel_hinting; /* Using subpixel hinting? */
- FT_Bool native_hinting; /* Using native hinting? */
FT_Bool ignore_x_mode; /* Standard rendering mode for */
/* subpixel hinting. On if gray */
- /* or subpixel hinting is on ) */
+ /* or subpixel hinting is on. */
- /* The following 4 aren't fully implemented but here for MS rasterizer */
+ /* The following 6 aren't fully implemented but here for MS rasterizer */
/* compatibility. */
FT_Bool compatible_widths; /* compatible widths? */
FT_Bool symmetrical_smoothing; /* symmetrical_smoothing? */
FT_Bool bgr; /* bgr instead of rgb? */
+ FT_Bool vertical_lcd; /* long side of LCD subpixel */
+ /* rectangles is horizontal */
FT_Bool subpixel_positioned; /* subpixel positioned */
/* (DirectWrite ClearType)? */
+ FT_Bool gray_cleartype; /* ClearType hinting but */
+ /* grayscale rendering */
FT_Int rasterizer_version; /* MS rasterizer version */
@@ -297,18 +288,18 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
TT_Goto_CodeRange( TT_ExecContext exec,
FT_Int range,
FT_Long IP );
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
TT_Set_CodeRange( TT_ExecContext exec,
FT_Int range,
void* base,
FT_Long length );
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
TT_Clear_CodeRange( TT_ExecContext exec,
FT_Int range );
@@ -316,7 +307,7 @@
FT_LOCAL( FT_Error )
Update_Max( FT_Memory memory,
FT_ULong* size,
- FT_Long multiplier,
+ FT_ULong multiplier,
void* _pbuff,
FT_ULong new_max );
#endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -340,13 +331,14 @@
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
+ /* (And right now only the glyph loader uses it.) */
/* */
FT_EXPORT( TT_ExecContext )
TT_New_Context( TT_Driver driver );
#ifdef TT_USE_BYTECODE_INTERPRETER
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
TT_Done_Context( TT_ExecContext exec );
FT_LOCAL( FT_Error )
@@ -354,13 +346,12 @@
TT_Face face,
TT_Size size );
- FT_LOCAL( FT_Error )
+ FT_LOCAL( void )
TT_Save_Context( TT_ExecContext exec,
TT_Size ins );
FT_LOCAL( FT_Error )
- TT_Run_Context( TT_ExecContext exec,
- FT_Bool debug );
+ TT_Run_Context( TT_ExecContext exec );
#endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 7897efa..b0d9f28 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
/* */
/* Objects manager (body). */
/* */
-/* Copyright 1996-2013 */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -150,20 +150,21 @@
tt_check_trickyness_family( FT_String* name )
{
-#define TRICK_NAMES_MAX_CHARACTERS 16
-#define TRICK_NAMES_COUNT 8
+#define TRICK_NAMES_MAX_CHARACTERS 19
+#define TRICK_NAMES_COUNT 9
static const char trick_names[TRICK_NAMES_COUNT]
[TRICK_NAMES_MAX_CHARACTERS + 1] =
{
- "DFKaiSho-SB", /* dfkaisb.ttf */
+ "DFKaiSho-SB", /* dfkaisb.ttf */
"DFKaiShu",
- "DFKai-SB", /* kaiu.ttf */
- "HuaTianKaiTi?", /* htkt2.ttf */
- "HuaTianSongTi?", /* htst3.ttf */
- "MingLiU", /* mingliu.ttf & mingliu.ttc */
- "PMingLiU", /* mingliu.ttc */
- "MingLi43", /* mingli.ttf */
+ "DFKai-SB", /* kaiu.ttf */
+ "HuaTianKaiTi?", /* htkt2.ttf */
+ "HuaTianSongTi?", /* htst3.ttf */
+ "Ming(for ISO10646)", /* hkscsiic.ttf & iicore.ttf */
+ "MingLiU", /* mingliu.ttf & mingliu.ttc */
+ "PMingLiU", /* mingliu.ttc */
+ "MingLi43", /* mingli.ttf */
};
int nn;
@@ -190,7 +191,7 @@
{
FT_Error error;
FT_UInt32 checksum = 0;
- int i;
+ FT_UInt i;
if ( FT_FRAME_ENTER( length ) )
@@ -199,8 +200,8 @@
for ( ; length > 3; length -= 4 )
checksum += (FT_UInt32)FT_GET_ULONG();
- for ( i = 3; length > 0; length --, i-- )
- checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) );
+ for ( i = 3; length > 0; length--, i-- )
+ checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
FT_FRAME_EXIT();
@@ -255,89 +256,89 @@
#define TRICK_SFNT_ID_prep 2
{ /* MingLiU 1995 */
- { 0x05bcf058, 0x000002e4 }, /* cvt */
- { 0x28233bf1, 0x000087c4 }, /* fpgm */
- { 0xa344a1ea, 0x000001e1 } /* prep */
+ { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
+ { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
+ { 0xA344A1EAUL, 0x000001E1UL } /* prep */
},
{ /* MingLiU 1996- */
- { 0x05bcf058, 0x000002e4 }, /* cvt */
- { 0x28233bf1, 0x000087c4 }, /* fpgm */
- { 0xa344a1eb, 0x000001e1 } /* prep */
+ { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
+ { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
+ { 0xA344A1EBUL, 0x000001E1UL } /* prep */
},
{ /* DFKaiShu */
- { 0x11e5ead4, 0x00000350 }, /* cvt */
- { 0x5a30ca3b, 0x00009063 }, /* fpgm */
- { 0x13a42602, 0x0000007e } /* prep */
+ { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
+ { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
+ { 0x13A42602UL, 0x0000007EUL } /* prep */
},
{ /* HuaTianKaiTi */
- { 0xfffbfffc, 0x00000008 }, /* cvt */
- { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
- { 0x70020112, 0x00000008 } /* prep */
+ { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
+ { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
+ { 0x70020112UL, 0x00000008UL } /* prep */
},
{ /* HuaTianSongTi */
- { 0xfffbfffc, 0x00000008 }, /* cvt */
- { 0x0a5a0483, 0x00017c39 }, /* fpgm */
- { 0x70020112, 0x00000008 } /* prep */
+ { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
+ { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
+ { 0x70020112UL, 0x00000008UL } /* prep */
},
{ /* NEC fadpop7.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x40c92555, 0x000000e5 }, /* fpgm */
- { 0xa39b58e3, 0x0000117c } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
+ { 0xA39B58E3UL, 0x0000117CUL } /* prep */
},
{ /* NEC fadrei5.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x33c41652, 0x000000e5 }, /* fpgm */
- { 0x26d6c52a, 0x00000f6a } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
+ { 0x26D6C52AUL, 0x00000F6AUL } /* prep */
},
{ /* NEC fangot7.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x6db1651d, 0x0000019d }, /* fpgm */
- { 0x6c6e4b03, 0x00002492 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
+ { 0x6C6E4B03UL, 0x00002492UL } /* prep */
},
{ /* NEC fangyo5.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x40c92555, 0x000000e5 }, /* fpgm */
- { 0xde51fad0, 0x0000117c } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
+ { 0xDE51FAD0UL, 0x0000117CUL } /* prep */
},
{ /* NEC fankyo5.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x85e47664, 0x000000e5 }, /* fpgm */
- { 0xa6c62831, 0x00001caa } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
+ { 0xA6C62831UL, 0x00001CAAUL } /* prep */
},
{ /* NEC fanrgo5.ttf */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x2d891cfd, 0x0000019d }, /* fpgm */
- { 0xa0604633, 0x00001de8 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
+ { 0xA0604633UL, 0x00001DE8UL } /* prep */
},
{ /* NEC fangot5.ttc */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x40aa774c, 0x000001cb }, /* fpgm */
- { 0x9b5caa96, 0x00001f9a } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
+ { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */
},
{ /* NEC fanmin3.ttc */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x0d3de9cb, 0x00000141 }, /* fpgm */
- { 0xd4127766, 0x00002280 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
+ { 0xD4127766UL, 0x00002280UL } /* prep */
},
{ /* NEC FA-Gothic, 1996 */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x4a692698, 0x000001f0 }, /* fpgm */
- { 0x340d4346, 0x00001fca } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
+ { 0x340D4346UL, 0x00001FCAUL } /* prep */
},
{ /* NEC FA-Minchou, 1996 */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0xcd34c604, 0x00000166 }, /* fpgm */
- { 0x6cf31046, 0x000022b0 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
+ { 0x6CF31046UL, 0x000022B0UL } /* prep */
},
{ /* NEC FA-RoundGothicB, 1996 */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0x5da75315, 0x0000019d }, /* fpgm */
- { 0x40745a5f, 0x000022e0 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
+ { 0x40745A5FUL, 0x000022E0UL } /* prep */
},
{ /* NEC FA-RoundGothicM, 1996 */
- { 0x00000000, 0x00000000 }, /* cvt */
- { 0xf055fc48, 0x000001c2 }, /* fpgm */
- { 0x3900ded3, 0x00001e18 } /* prep */
+ { 0x00000000UL, 0x00000000UL }, /* cvt */
+ { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
+ { 0x3900DED3UL, 0x00001E18UL } /* prep */
}
};
@@ -489,7 +490,10 @@
/* <Input> */
/* stream :: The source font stream. */
/* */
- /* face_index :: The index of the font face in the resource. */
+ /* face_index :: The index of the TrueType font, if we are opening a */
+ /* collection, in bits 0-15. The numbered instance */
+ /* index~+~1 of a GX (sub)font, if applicable, in bits */
+ /* 16-30. */
/* */
/* num_params :: Number of additional generic parameters. Ignored. */
/* */
@@ -532,6 +536,10 @@
/* check that we have a valid TrueType file */
error = sfnt->init_face( stream, face, face_index, num_params, params );
+
+ /* Stream may have changed. */
+ stream = face->root.stream;
+
if ( error )
goto Exit;
@@ -594,7 +602,7 @@
ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
}
-#else
+#else /* !FT_CONFIG_OPTION_INCREMENTAL */
if ( !error )
error = tt_face_load_loca( face, stream );
@@ -618,10 +626,56 @@
ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
}
-#endif
+#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
}
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ {
+ FT_Int instance_index = face_index >> 16;
+
+
+ if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
+ instance_index > 0 )
+ {
+ error = TT_Get_MM_Var( face, NULL );
+ if ( error )
+ goto Exit;
+
+ if ( face->blend->mmvar->namedstyle )
+ {
+ FT_Memory memory = ttface->memory;
+
+ FT_Var_Named_Style* named_style;
+ FT_String* style_name;
+
+
+ /* in `face_index', the instance index starts with value 1 */
+ named_style = face->blend->mmvar->namedstyle + instance_index - 1;
+ error = sfnt->get_name( face,
+ (FT_UShort)named_style->strid,
+ &style_name );
+ if ( error )
+ goto Exit;
+
+ /* set style name; if already set, replace it */
+ if ( face->root.style_name )
+ FT_FREE( face->root.style_name );
+ face->root.style_name = style_name;
+
+ /* finally, select the named instance */
+ error = TT_Set_Var_Design( face,
+ face->blend->mmvar->num_axis,
+ named_style->coords );
+ if ( error )
+ goto Exit;
+ }
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
!defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
@@ -746,16 +800,11 @@
FT_Error error;
- /* debugging instances have their own context */
- if ( size->debug )
- exec = size->context;
- else
- exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+ exec = size->context;
- if ( !exec )
- return FT_THROW( Could_Not_Find_Context );
-
- TT_Load_Context( exec, face, size );
+ error = TT_Load_Context( exec, face, size );
+ if ( error )
+ return error;
exec->callTop = 0;
exec->top = 0;
@@ -788,7 +837,7 @@
TT_Set_CodeRange( exec,
tt_coderange_font,
face->font_program,
- face->font_program_size );
+ (FT_Long)face->font_program_size );
/* disable CVT and glyph programs coderange */
TT_Clear_CodeRange( exec, tt_coderange_cvt );
@@ -796,18 +845,16 @@
if ( face->font_program_size > 0 )
{
- error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+ TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
- if ( !error )
- {
- FT_TRACE4(( "Executing `fpgm' table.\n" ));
-
- error = face->interpreter( exec );
- }
+ FT_TRACE4(( "Executing `fpgm' table.\n" ));
+ error = face->interpreter( exec );
}
else
error = FT_Err_Ok;
+ size->bytecode_ready = error;
+
if ( !error )
TT_Save_Context( exec, size );
@@ -840,16 +887,11 @@
FT_Error error;
- /* debugging instances have their own context */
- if ( size->debug )
- exec = size->context;
- else
- exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+ exec = size->context;
- if ( !exec )
- return FT_THROW( Could_Not_Find_Context );
-
- TT_Load_Context( exec, face, size );
+ error = TT_Load_Context( exec, face, size );
+ if ( error )
+ return error;
exec->callTop = 0;
exec->top = 0;
@@ -861,24 +903,23 @@
TT_Set_CodeRange( exec,
tt_coderange_cvt,
face->cvt_program,
- face->cvt_program_size );
+ (FT_Long)face->cvt_program_size );
TT_Clear_CodeRange( exec, tt_coderange_glyph );
if ( face->cvt_program_size > 0 )
{
- error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+ TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
- if ( !error && !size->debug )
- {
- FT_TRACE4(( "Executing `prep' table.\n" ));
+ FT_TRACE4(( "Executing `prep' table.\n" ));
- error = face->interpreter( exec );
- }
+ error = face->interpreter( exec );
}
else
error = FT_Err_Ok;
+ size->cvt_ready = error;
+
/* UNDOCUMENTED! The MS rasterizer doesn't allow the following */
/* graphics state variables to be modified by the CVT program. */
@@ -907,10 +948,6 @@
return error;
}
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
-
-#ifdef TT_USE_BYTECODE_INTERPRETER
static void
tt_size_done_bytecode( FT_Size ftsize )
@@ -919,12 +956,10 @@
TT_Face face = (TT_Face)ftsize->face;
FT_Memory memory = face->root.memory;
-
- if ( size->debug )
+ if ( size->context )
{
- /* the debug context must be deleted by the debugger itself */
+ TT_Done_Context( size->context );
size->context = NULL;
- size->debug = FALSE;
}
FT_FREE( size->cvt );
@@ -948,8 +983,8 @@
size->max_func = 0;
size->max_ins = 0;
- size->bytecode_ready = 0;
- size->cvt_ready = 0;
+ size->bytecode_ready = -1;
+ size->cvt_ready = -1;
}
@@ -963,14 +998,25 @@
TT_Size size = (TT_Size)ftsize;
TT_Face face = (TT_Face)ftsize->face;
FT_Memory memory = face->root.memory;
- FT_Int i;
FT_UShort n_twilight;
TT_MaxProfile* maxp = &face->max_profile;
- size->bytecode_ready = 1;
- size->cvt_ready = 0;
+ /* clean up bytecode related data */
+ FT_FREE( size->function_defs );
+ FT_FREE( size->instruction_defs );
+ FT_FREE( size->cvt );
+ FT_FREE( size->storage );
+
+ if ( size->context )
+ TT_Done_Context( size->context );
+ tt_glyphzone_done( &size->twilight );
+
+ size->bytecode_ready = -1;
+ size->cvt_ready = -1;
+
+ size->context = TT_New_Context( (TT_Driver)face->root.driver );
size->max_function_defs = maxp->maxFunctionDefs;
size->max_instruction_defs = maxp->maxInstructionDefs;
@@ -992,9 +1038,11 @@
metrics->rotated = FALSE;
metrics->stretched = FALSE;
- /* set default compensation (all 0) */
- for ( i = 0; i < 4; i++ )
- metrics->compensations[i] = 0;
+ /* set default engine compensation */
+ metrics->compensations[0] = 0; /* gray */
+ metrics->compensations[1] = 0; /* black */
+ metrics->compensations[2] = 0; /* white */
+ metrics->compensations[3] = 0; /* reserved */
}
/* allocate function defs, instruction defs, cvt, and storage area */
@@ -1030,7 +1078,15 @@
}
/* Fine, now run the font program! */
+
+ /* In case of an error while executing `fpgm', we intentionally don't */
+ /* clean up immediately – bugs in the `fpgm' are so fundamental that */
+ /* all following hinting calls should fail. Additionally, `fpgm' is */
+ /* to be executed just once; calling it again is completely useless */
+ /* and might even lead to extremely slow behaviour if it is malformed */
+ /* (containing an infinite loop, for example). */
error = tt_size_run_fpgm( size, pedantic );
+ return error;
Exit:
if ( error )
@@ -1047,15 +1103,14 @@
FT_Error error = FT_Err_Ok;
- if ( !size->bytecode_ready )
- {
+ if ( size->bytecode_ready < 0 )
error = tt_size_init_bytecode( (FT_Size)size, pedantic );
- if ( error )
- goto Exit;
- }
+
+ if ( error || size->bytecode_ready )
+ goto Exit;
/* rescale CVT when needed */
- if ( !size->cvt_ready )
+ if ( size->cvt_ready < 0 )
{
FT_UInt i;
TT_Face face = (TT_Face)size->root.face;
@@ -1082,8 +1137,6 @@
size->GS = tt_default_graphics_state;
error = tt_size_run_prep( size, pedantic );
- if ( !error )
- size->cvt_ready = 1;
}
Exit:
@@ -1113,9 +1166,10 @@
TT_Size size = (TT_Size)ttsize;
FT_Error error = FT_Err_Ok;
+
#ifdef TT_USE_BYTECODE_INTERPRETER
- size->bytecode_ready = 0;
- size->cvt_ready = 0;
+ size->bytecode_ready = -1;
+ size->cvt_ready = -1;
#endif
size->ttmetrics.valid = FALSE;
@@ -1143,8 +1197,7 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
- if ( size->bytecode_ready )
- tt_size_done_bytecode( ttsize );
+ tt_size_done_bytecode( ttsize );
#endif
size->ttmetrics.valid = FALSE;
@@ -1224,7 +1277,7 @@
}
#ifdef TT_USE_BYTECODE_INTERPRETER
- size->cvt_ready = 0;
+ size->cvt_ready = -1;
#endif /* TT_USE_BYTECODE_INTERPRETER */
if ( !error )
@@ -1256,10 +1309,6 @@
TT_Driver driver = (TT_Driver)ttdriver;
-
- if ( !TT_New_Context( driver ) )
- return FT_THROW( Could_Not_Find_Context );
-
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
driver->interpreter_version = TT_INTERPRETER_VERSION_38;
#else
@@ -1290,20 +1339,7 @@
FT_LOCAL_DEF( void )
tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
{
-#ifdef TT_USE_BYTECODE_INTERPRETER
- TT_Driver driver = (TT_Driver)ttdriver;
-
-
- /* destroy the execution context */
- if ( driver->context )
- {
- TT_Done_Context( driver->context );
- driver->context = NULL;
- }
-#else
FT_UNUSED( ttdriver );
-#endif
-
}
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index a11dd37..9396089 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
-/* Copyright 1996-2009, 2011-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -42,17 +42,6 @@
/*************************************************************************/
/* */
/* <Type> */
- /* TT_Instance */
- /* */
- /* <Description> */
- /* A handle to a TrueType size object. */
- /* */
- typedef struct TT_SizeRec_* TT_Size;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
/* TT_GlyphSlot */
/* */
/* <Description> */
@@ -95,8 +84,8 @@
FT_F26Dot6 control_value_cutin;
FT_F26Dot6 single_width_cutin;
FT_F26Dot6 single_width_value;
- FT_Short delta_base;
- FT_Short delta_shift;
+ FT_UShort delta_base;
+ FT_UShort delta_shift;
FT_Byte instruct_control;
/* According to Greg Hitchcock from Microsoft, the `scan_control' */
@@ -160,7 +149,7 @@
typedef struct TT_CodeRange_
{
FT_Byte* base;
- FT_ULong size;
+ FT_Long size;
} TT_CodeRange;
@@ -324,17 +313,12 @@
TT_GlyphZoneRec 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. */
-
- FT_Bool debug;
TT_ExecContext context;
- FT_Bool bytecode_ready;
- FT_Bool cvt_ready;
+ /* if negative, `fpgm' (resp. `prep'), wasn't executed yet; */
+ /* otherwise it is the returned error code */
+ FT_Error bytecode_ready;
+ FT_Error cvt_ready;
#endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -349,7 +333,6 @@
{
FT_DriverRec root;
- TT_ExecContext context; /* execution context */
TT_GlyphZoneRec zone; /* glyph loader points zone */
FT_UInt interpreter_version;
diff --git a/src/truetype/ttpic.c b/src/truetype/ttpic.c
index edefae7..242a6b7 100644
--- a/src/truetype/ttpic.c
+++ b/src/truetype/ttpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for truetype module. */
/* */
-/* Copyright 2009, 2010, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/ttpic.h b/src/truetype/ttpic.h
index cfb4ee6..076ae56 100644
--- a/src/truetype/ttpic.h
+++ b/src/truetype/ttpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for truetype module. */
/* */
-/* Copyright 2009, 2012, 2013 by */
+/* Copyright 2009-2015 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,7 +20,8 @@
#define __TTPIC_H__
-FT_BEGIN_HEADER
+#include FT_INTERNAL_PIC_H
+
#ifndef FT_CONFIG_OPTION_PIC
@@ -37,6 +38,8 @@
#include FT_SERVICE_PROPERTIES_H
+FT_BEGIN_HEADER
+
typedef struct TTModulePIC_
{
FT_ServiceDescRec* tt_services;
@@ -68,13 +71,12 @@
FT_Error
tt_driver_class_pic_init( FT_Library library );
+FT_END_HEADER
+
#endif /* FT_CONFIG_OPTION_PIC */
/* */
-
-FT_END_HEADER
-
#endif /* __TTPIC_H__ */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 9723a51..9bf67f9 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2002, 2004-2013 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -118,40 +118,52 @@
/* we only handle the case where `maxp' gives a larger value */
if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
{
- FT_Long new_loca_len =
- ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
+ FT_ULong new_loca_len =
+ ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
- FT_Long pos = FT_Stream_Pos( stream );
- FT_Long dist = 0x7FFFFFFFL;
+ FT_Long pos = (FT_Long)FT_STREAM_POS();
+ FT_Long dist = 0x7FFFFFFFL;
+ FT_Bool found = 0;
/* compute the distance to next table in font file */
for ( ; entry < limit; entry++ )
{
- FT_Long diff = entry->Offset - pos;
+ FT_Long diff = (FT_Long)entry->Offset - pos;
if ( diff > 0 && diff < dist )
- dist = diff;
+ {
+ dist = diff;
+ found = 1;
+ }
}
- if ( entry == limit )
+ if ( !found )
{
/* `loca' is the last table */
- dist = stream->size - pos;
+ dist = (FT_Long)stream->size - pos;
}
- if ( new_loca_len <= dist )
+ if ( new_loca_len <= (FT_ULong)dist )
{
- face->num_locations = face->root.num_glyphs + 1;
+ face->num_locations = (FT_ULong)face->root.num_glyphs + 1;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",
face->num_locations ));
}
+ else
+ {
+ face->root.num_glyphs = face->num_locations
+ ? (FT_Long)face->num_locations - 1 : 0;
+
+ FT_TRACE2(( "adjusting num_glyphs to %d\n",
+ face->root.num_glyphs ));
+ }
}
}
@@ -214,7 +226,8 @@
if ( pos1 > face->glyf_len )
{
FT_TRACE1(( "tt_face_get_location:"
- " too large offset=0x%08lx found for gid=0x%04lx,"
+ " too large offset=0x%08lx found for gid=0x%04lx,\n"
+ " "
" exceeding the end of glyf table (0x%08lx)\n",
pos1, gindex, face->glyf_len ));
*asize = 0;
@@ -224,7 +237,8 @@
if ( pos2 > face->glyf_len )
{
FT_TRACE1(( "tt_face_get_location:"
- " too large offset=0x%08lx found for gid=0x%04lx,"
+ " too large offset=0x%08lx found for gid=0x%04lx,\n"
+ " "
" truncate at the end of glyf table (0x%08lx)\n",
pos2, gindex + 1, face->glyf_len ));
pos2 = face->glyf_len;
@@ -508,9 +522,9 @@
record_size = FT_NEXT_ULONG( p );
/* The maximum number of bytes in an hdmx device record is the */
- /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
- /* the reason why `record_size' is a long (which we read as */
- /* unsigned long for convenience). In practice, two bytes */
+ /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */
+ /* explaining why `record_size' is a long (which we read as */
+ /* unsigned long for convenience). In practice, two bytes are */
/* sufficient to hold the size value. */
/* */
/* There are at least two fonts, HANNOM-A and HANNOM-B version */
@@ -522,8 +536,10 @@
record_size &= 0xFFFFU;
/* The limit for `num_records' is a heuristic value. */
-
- if ( version != 0 || num_records > 255 || record_size > 0x10001L )
+ if ( version != 0 ||
+ num_records > 255 ||
+ record_size > 0x10001L ||
+ record_size < 4 )
{
error = FT_THROW( Invalid_File_Format );
goto Fail;
diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h
index f61ac07..bc92369 100644
--- a/src/truetype/ttpload.h
+++ b/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2005, 2006 by */
+/* Copyright 1996-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
index 28470ad..0d391e9 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
/* */
/* TrueType Subpixel Hinting. */
/* */
-/* Copyright 2010-2013 by */
+/* Copyright 2010-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -63,8 +63,8 @@
/* rules below. A blank entry "" is required at the end of these! */
#define FAMILY_CLASS_RULES_SIZE 7
- static const SPH_Font_Class FAMILY_CLASS_Rules
- [FAMILY_CLASS_RULES_SIZE] =
+ static const SPH_Font_Class FAMILY_CLASS_Rules
+ [FAMILY_CLASS_RULES_SIZE] =
{
{ "MS Legacy Fonts",
{ "Aharoni",
@@ -223,8 +223,8 @@
/* rules below. A blank entry "" is required at the end of these! */
#define STYLE_CLASS_RULES_SIZE 5
- const SPH_Font_Class STYLE_CLASS_Rules
- [STYLE_CLASS_RULES_SIZE] =
+ static const SPH_Font_Class STYLE_CLASS_Rules
+ [STYLE_CLASS_RULES_SIZE] =
{
{ "Regular Class",
{ "Regular",
@@ -279,18 +279,18 @@
/* Force special legacy fixes for fonts. */
#define COMPATIBILITY_MODE_RULES_SIZE 1
- const SPH_TweakRule COMPATIBILITY_MODE_Rules
- [COMPATIBILITY_MODE_RULES_SIZE] =
+ static const SPH_TweakRule COMPATIBILITY_MODE_Rules
+ [COMPATIBILITY_MODE_RULES_SIZE] =
{
- { "-", 0, "", 0 },
+ { "Verdana Clones", 0, "", 0 },
};
/* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */
#define PIXEL_HINTING_RULES_SIZE 2
- const SPH_TweakRule PIXEL_HINTING_Rules
- [PIXEL_HINTING_RULES_SIZE] =
+ static const SPH_TweakRule PIXEL_HINTING_Rules
+ [PIXEL_HINTING_RULES_SIZE] =
{
/* these characters are almost always safe */
{ "Courier New", 12, "Italic", 'z' },
@@ -301,8 +301,8 @@
/* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */
#define DO_SHPIX_RULES_SIZE 1
- const SPH_TweakRule DO_SHPIX_Rules
- [DO_SHPIX_RULES_SIZE] =
+ static const SPH_TweakRule DO_SHPIX_Rules
+ [DO_SHPIX_RULES_SIZE] =
{
{ "-", 0, "", 0 },
};
@@ -312,8 +312,8 @@
/* boundary and don't move that point to a Y pixel boundary. */
#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4
- const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules
- [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
+ static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules
+ [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
{
/* fix vwxyz thinness*/
{ "Consolas", 0, "", 0 },
@@ -328,8 +328,8 @@
#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
- const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
- [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+ static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
+ [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
{
/* Fixes < and > */
{ "Courier New", 0, "Regular", 0 },
@@ -340,8 +340,8 @@
/* boundary and don't move that point to a Y pixel boundary. */
#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2
- const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
- [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
+ static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
+ [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
{
/* Maintain thickness of diagonal in 'N' */
{ "Times New Roman", 0, "Regular/Bold Class", 'N' },
@@ -352,8 +352,8 @@
/* Skip Y moves that move a point off a Y pixel boundary. */
#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1
- const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules
- [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
+ static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules
+ [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
{
{ "-", 0, "", 0 },
};
@@ -361,8 +361,8 @@
#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
- const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
- [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+ static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
+ [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
{
{ "-", 0, "", 0 },
};
@@ -371,8 +371,8 @@
/* Round moves that don't move a point to a Y pixel boundary. */
#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2
- const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules
- [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
+ static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules
+ [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
{
/* Droid font instructions don't snap Y to pixels */
{ "Droid Sans", 0, "Regular/Italic Class", 0 },
@@ -382,8 +382,8 @@
#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1
- const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
- [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+ static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
+ [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
{
{ "-", 0, "", 0 },
};
@@ -392,8 +392,8 @@
/* Allow a Direct_Move along X freedom vector if matched. */
#define ALLOW_X_DMOVE_RULES_SIZE 1
- const SPH_TweakRule ALLOW_X_DMOVE_Rules
- [ALLOW_X_DMOVE_RULES_SIZE] =
+ static const SPH_TweakRule ALLOW_X_DMOVE_Rules
+ [ALLOW_X_DMOVE_RULES_SIZE] =
{
/* Fixes vanishing diagonal in 4 */
{ "Verdana", 0, "Regular", '4' },
@@ -403,8 +403,8 @@
/* Return MS rasterizer version 35 if matched. */
#define RASTERIZER_35_RULES_SIZE 8
- const SPH_TweakRule RASTERIZER_35_Rules
- [RASTERIZER_35_RULES_SIZE] =
+ static const SPH_TweakRule RASTERIZER_35_Rules
+ [RASTERIZER_35_RULES_SIZE] =
{
/* This seems to be the only way to make these look good */
{ "Times New Roman", 0, "Regular", 'i' },
@@ -421,8 +421,8 @@
/* Don't round to the subpixel grid. Round to pixel grid. */
#define NORMAL_ROUND_RULES_SIZE 1
- const SPH_TweakRule NORMAL_ROUND_Rules
- [NORMAL_ROUND_RULES_SIZE] =
+ static const SPH_TweakRule NORMAL_ROUND_Rules
+ [NORMAL_ROUND_RULES_SIZE] =
{
/* Fix serif thickness for certain ppems */
/* Can probably be generalized somehow */
@@ -433,8 +433,8 @@
/* Skip IUP instructions if matched. */
#define SKIP_IUP_RULES_SIZE 1
- const SPH_TweakRule SKIP_IUP_Rules
- [SKIP_IUP_RULES_SIZE] =
+ static const SPH_TweakRule SKIP_IUP_Rules
+ [SKIP_IUP_RULES_SIZE] =
{
{ "Arial", 13, "Regular", 'a' },
};
@@ -443,8 +443,8 @@
/* Skip MIAP Twilight hack if matched. */
#define MIAP_HACK_RULES_SIZE 1
- const SPH_TweakRule MIAP_HACK_Rules
- [MIAP_HACK_RULES_SIZE] =
+ static const SPH_TweakRule MIAP_HACK_Rules
+ [MIAP_HACK_RULES_SIZE] =
{
{ "Geneva", 12, "", 0 },
};
@@ -453,8 +453,8 @@
/* Skip DELTAP instructions if matched. */
#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23
- const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules
- [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
+ static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules
+ [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
{
{ "Georgia", 0, "Regular", 'k' },
/* fix various problems with e in different versions */
@@ -489,8 +489,8 @@
/* Always do DELTAP instructions if matched. */
#define ALWAYS_DO_DELTAP_RULES_SIZE 1
- const SPH_TweakRule ALWAYS_DO_DELTAP_Rules
- [ALWAYS_DO_DELTAP_RULES_SIZE] =
+ static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules
+ [ALWAYS_DO_DELTAP_RULES_SIZE] =
{
{ "-", 0, "", 0 },
};
@@ -744,7 +744,7 @@
#endif /* FORCE_NATURAL_WIDTHS */
- FT_LOCAL_DEF( FT_Bool )
+ static FT_Bool
is_member_of_family_class( const FT_String* detected_font_name,
const FT_String* rule_font_name )
{
@@ -779,7 +779,7 @@
}
- FT_LOCAL_DEF( FT_Bool )
+ static FT_Bool
is_member_of_style_class( const FT_String* detected_font_style,
const FT_String* rule_font_style )
{
@@ -903,9 +903,9 @@
sph_set_tweaks( TT_Loader loader,
FT_UInt glyph_index )
{
- TT_Face face = (TT_Face)loader->face;
+ TT_Face face = loader->face;
FT_String* family = face->root.family_name;
- int ppem = loader->size->metrics.x_ppem;
+ FT_UInt ppem = loader->size->metrics.x_ppem;
FT_String* style = face->root.style_name;
@@ -956,7 +956,7 @@
if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 )
{
loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
- loader->exec->size->cvt_ready = FALSE;
+ loader->exec->size->cvt_ready = -1;
tt_size_ready_bytecode(
loader->exec->size,
@@ -971,7 +971,7 @@
SPH_OPTION_SET_RASTERIZER_VERSION )
{
loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
- loader->exec->size->cvt_ready = FALSE;
+ loader->exec->size->cvt_ready = -1;
tt_size_ready_bytecode(
loader->exec->size,
diff --git a/src/truetype/ttsubpix.h b/src/truetype/ttsubpix.h
index 8a54fc7..9151aa3 100644
--- a/src/truetype/ttsubpix.h
+++ b/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Subpixel Hinting. */
/* */
-/* Copyright 2010-2013 by */
+/* Copyright 2010-2015 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -50,26 +50,26 @@
/* Tweak flags that are set for each glyph by the below rules. */
/* */
/* */
-#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001
-#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002
-#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004
-#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008
-#define SPH_TWEAK_DEEMBOLDEN 0x0000010
-#define SPH_TWEAK_DO_SHPIX 0x0000020
-#define SPH_TWEAK_EMBOLDEN 0x0000040
-#define SPH_TWEAK_MIAP_HACK 0x0000080
-#define SPH_TWEAK_NORMAL_ROUND 0x0000100
-#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200
-#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400
-#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800
-#define SPH_TWEAK_PIXEL_HINTING 0x0001000
-#define SPH_TWEAK_RASTERIZER_35 0x0002000
-#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000
-#define SPH_TWEAK_SKIP_IUP 0x0008000
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000
-#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000
-#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000
-#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000
+#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL
+#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL
+#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL
+#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL
+#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL
+#define SPH_TWEAK_DO_SHPIX 0x0000020UL
+#define SPH_TWEAK_EMBOLDEN 0x0000040UL
+#define SPH_TWEAK_MIAP_HACK 0x0000080UL
+#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL
+#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL
+#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL
+#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL
+#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL
+#define SPH_TWEAK_RASTERIZER_35 0x0002000UL
+#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL
+#define SPH_TWEAK_SKIP_IUP 0x0008000UL
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL
+#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL
+#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL
FT_LOCAL( FT_Bool )