summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Coucheron <arco68@gmail.com>2011-08-24 05:32:14 +0200
committerArne Coucheron <arco68@gmail.com>2011-08-24 05:32:14 +0200
commit6a26dd05f335a4ebab267657ae31bb7ee7114625 (patch)
treef5a0d98f1d887b8063987f5e9b58a4ed2931833e
parent1db8a080668ca5428a7f000f668ebf8bec20ad08 (diff)
downloadandroid_external_freetype-gb-release-7.2.tar.gz
android_external_freetype-gb-release-7.2.tar.bz2
android_external_freetype-gb-release-7.2.zip
CHANGES BETWEEN 2.4.5 and 2.4.6 I. IMPORTANT BUG FIXES - For TrueType based fonts, the ascender and descender values were incorrect sometimes (off by a pixel if the ppem value was not a multiple of 5). Depending on the use you might now experience a different layout; the change should result in better, more consistent line spacing. - Fix CVE-2011-0226 which causes a vulnerability while handling Type 1 fonts. - BDF fonts containing glyphs with negative values for ENCODING were incorrectly rejected. This bug has been introduced in FreeType version 2.2.0. - David Bevan contributed a major revision of the FreeType stroker code: . The behaviour of FT_STROKER_LINEJOIN_BEVEL has been corrected. . A new line join style, FT_STROKER_LINEJOIN_MITER_FIXED, has been introduced to support PostScript and PDF miter joins. . FT_STROKER_LINEJOIN_MITER_VARIABLE has been introduced as an alias for FT_STROKER_LINEJOIN_MITER. . Various stroking glitches has been fixed. II. MISCELLANEOUS - SFNT bitmap fonts which contain an outline glyph for `.notdef' only no longer set the FT_FACE_FLAG_SCALABLE flag. CHANGES BETWEEN 2.4.4 and 2.4.5 I. IMPORTANT BUG FIXES - A rendering regression for second-order Bézier curves has been fixed, introduced in 2.4.3. II. IMPORTANT CHANGES - If autohinting is not explicitly disabled, FreeType now uses the autohinter if a TrueType based font doesn't contain native hints. - The load flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH has been made redundant and is simply ignored; this means that FreeType now ignores the global advance width value in TrueType fonts. III. MISCELLANEOUS - `FT_Sfnt_Table_Info' can now return the number of SFNT tables of a font. - Support for PCF files compressed with bzip2 has been contributed by Joel Klinghed. To make this work, the OS must provide a bzip2 library. - Bradley Grainger contributed project and solution files in Visual Studio 2010 format. - Again some fixes to better handle broken fonts. - Some improvements to the B/W rasterizer. - Fixes to the cache module to improve robustness. - Just Fill Bugs contributed (experimental) code to compute blue zones for CJK Ideographs, improving the alignment of horizontal stems at the top or bottom edges. - The `ftgrid' demo program can now display autohinter segments, to be toggled on and off with key `s'. CHANGES BETWEEN 2.4.3 and 2.4.4 I. IMPORTANT BUG FIXES - UVS support (TrueType/OpenType cmap format 14) support is fixed. This regression has been introduced in version 2.4.0. II. MISCELLANEOUS - Detect tricky fonts (e.g. MingLiU) by the lengths and checksums of Type42-persistent subtables (`cvt ', `fpgm', and `prep') when a TrueType font without family name is given. The previous fix, introduced in 2.4.3, was too rigorous, causing many subsetted fonts (mainly from PDF files) displayed badly because FreeType forced rendering with the TrueType bytecode engine instead of the autohinter. - Better support for 64bit platforms. - More fixes to improve handling of broken fonts. CHANGES BETWEEN 2.4.2 and 2.4.3 I. IMPORTANT BUG FIXES - Fix rendering of certain cubic, S-shaped arcs. This regression has been introduced in version 2.4.0. II. MISCELLANEOUS - To fix the above mentioned rendering issue, a new spline flattening algorithm has been introduced which speeds up both conic and cubic arcs. - Handling of broken fonts has been further improved. Change-Id: Ie06b74b29738a34d686ab1132e9fa44d5d258d1c
-rw-r--r--Android.mk4
-rw-r--r--ThirdPartyProject.prop4
-rw-r--r--include/freetype/config/ftconfig.h60
-rw-r--r--include/freetype/config/ftheader.h15
-rw-r--r--include/freetype/config/ftoption.h78
-rw-r--r--include/freetype/freetype.h36
-rw-r--r--include/freetype/ftbbox.h10
-rw-r--r--include/freetype/ftbzip2.h102
-rw-r--r--include/freetype/ftcache.h19
-rw-r--r--include/freetype/ftchapters.h1
-rw-r--r--include/freetype/fterrdef.h1
-rw-r--r--include/freetype/ftgasp.h18
-rw-r--r--include/freetype/ftglyph.h9
-rw-r--r--include/freetype/ftimage.h12
-rw-r--r--include/freetype/ftmoderr.h39
-rw-r--r--include/freetype/ftoutln.h7
-rw-r--r--include/freetype/ftrender.h8
-rw-r--r--include/freetype/ftstroke.h49
-rw-r--r--include/freetype/internal/ftstream.h114
-rw-r--r--include/freetype/internal/fttrace.h7
-rw-r--r--include/freetype/internal/pcftypes.h56
-rw-r--r--include/freetype/tttables.h12
-rw-r--r--src/autofit/afangles.c4
-rw-r--r--src/autofit/afcjk.c835
-rw-r--r--src/autofit/afcjk.h104
-rw-r--r--src/autofit/afdummy.c9
-rw-r--r--src/autofit/afdummy.h4
-rw-r--r--src/autofit/afglobal.c14
-rw-r--r--src/autofit/afglobal.h8
-rw-r--r--src/autofit/afhints.c241
-rw-r--r--src/autofit/afhints.h217
-rw-r--r--src/autofit/afindic.c55
-rw-r--r--src/autofit/aflatin.c500
-rw-r--r--src/autofit/aflatin.h25
-rw-r--r--src/autofit/aflatin2.c227
-rw-r--r--src/autofit/afloader.c32
-rw-r--r--src/autofit/afloader.h8
-rw-r--r--src/autofit/afmodule.c17
-rw-r--r--src/autofit/afpic.c46
-rw-r--r--src/autofit/afpic.h27
-rw-r--r--src/autofit/aftypes.h129
-rw-r--r--src/autofit/afwarp.c62
-rw-r--r--src/autofit/autofit.c4
-rw-r--r--src/base/ftbase.h11
-rw-r--r--src/base/ftbitmap.c2
-rw-r--r--src/base/ftdbgmem.c6
-rw-r--r--src/base/ftobjs.c56
-rw-r--r--src/base/ftpatent.c2
-rw-r--r--src/base/ftrfork.c88
-rw-r--r--src/base/ftstream.c72
-rw-r--r--src/base/ftstroke.c814
-rw-r--r--src/base/ftsynth.c4
-rw-r--r--src/base/ftsystem.c21
-rw-r--r--src/cff/cffdrivr.c2
-rw-r--r--src/cff/cffgload.c19
-rw-r--r--src/cff/cffload.c58
-rw-r--r--src/cff/cffobjs.c62
-rw-r--r--src/cff/cffparse.c31
-rw-r--r--src/cff/cfftypes.h5
-rw-r--r--src/psaux/psobjs.c13
-rw-r--r--src/psaux/t1decode.c165
-rw-r--r--src/pshinter/pshalgo.c4
-rw-r--r--src/raster/ftraster.c60
-rw-r--r--src/raster/ftrend1.c8
-rw-r--r--src/sfnt/sfdriver.c19
-rw-r--r--src/sfnt/sfobjs.c80
-rw-r--r--src/sfnt/ttload.c15
-rw-r--r--src/sfnt/ttmtx.c4
-rw-r--r--src/sfnt/ttpost.c60
-rw-r--r--src/sfnt/ttsbit.c2
-rw-r--r--src/smooth/ftgrays.c298
-rw-r--r--src/smooth/ftsmooth.c33
-rw-r--r--src/truetype/ttdriver.c12
-rw-r--r--src/truetype/ttgload.c56
-rw-r--r--src/truetype/ttgload.h4
-rw-r--r--src/truetype/ttgxvar.c12
-rw-r--r--src/truetype/ttinterp.c248
-rw-r--r--src/truetype/ttobjs.c372
-rw-r--r--src/truetype/ttobjs.h11
-rw-r--r--src/truetype/ttpload.c41
80 files changed, 4323 insertions, 1676 deletions
diff --git a/Android.mk b/Android.mk
index 1ca1f7e..3a67228 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.4.6
endif
-ifeq ($(USE_FREETYPE),2.4.2)
+ifeq ($(USE_FREETYPE),2.4.6)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop
index 7bf6d4d..5d1258d 100644
--- a/ThirdPartyProject.prop
+++ b/ThirdPartyProject.prop
@@ -1,7 +1,7 @@
# Copyright 2010 Google Inc. All Rights Reserved.
#Fri Jul 16 10:03:09 PDT 2010
-currentVersion=2.4.2
-version=2.4.2
+currentVersion=2.4.6
+version=2.4.6
isNative=true
feedurl=http\://freetype.sourceforge.net/index2.html
name=freetype
diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h
index cbe30f2..b304896 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-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2010 by */
+/* Copyright 1996-2004, 2006-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -127,7 +127,12 @@ FT_BEGIN_HEADER
#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \
( defined( __MWERKS__ ) && defined( macintosh ) )
/* no Carbon frameworks for 64bit 10.4.x */
+ /* AvailabilityMacros.h is available since Mac OS X 10.2, */
+ /* so guess the system version by maximum errno before inclusion */
+#include <errno.h>
+#ifdef ECANCELED /* defined since 10.2 */
#include "AvailabilityMacros.h"
+#endif
#if defined( __LP64__ ) && \
( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 )
#define DARWIN_NO_CARBON 1
@@ -348,14 +353,14 @@ FT_BEGIN_HEADER
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, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
+ __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) );
return a;
@@ -395,6 +400,43 @@ FT_BEGIN_HEADER
#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 */
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index b63945d..2a7b8c4 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-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
+/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -427,6 +427,19 @@
/*************************************************************************
*
* @macro:
+ * FT_BZIP2_H
+ *
+ * @description:
+ * A macro used in #include statements to name the file containing the
+ * definitions of an API which supports bzip2-compressed files.
+ *
+ */
+#define FT_BZIP2_H <freetype/ftbzip2.h>
+
+
+ /*************************************************************************
+ *
+ * @macro:
* FT_WINFONTS_H
*
* @description:
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index 22056e1..c41f089 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,8 +4,7 @@
/* */
/* User-selectable configuration macros (specification only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -190,6 +189,33 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
+ /* Bzip2-compressed file support. */
+ /* */
+ /* FreeType now handles font files that have been compressed with the */
+ /* `bzip2' program. This is mostly used to parse many of the PCF */
+ /* files that come with XFree86. The implementation uses `libbz2' to */
+ /* partially uncompress the file on the fly (see src/bzip2/ftbzip2.c). */
+ /* Contrary to gzip, bzip2 currently is not included and need to use */
+ /* the system available bzip2 implementation. */
+ /* */
+ /* Define this macro if you want to enable this `feature'. */
+ /* */
+/* #define FT_CONFIG_OPTION_USE_BZIP2 */
+
+
+ /*************************************************************************/
+ /* */
+ /* Define to disable the use of file stream functions and types, FILE, */
+ /* fopen() etc. Enables the use of smaller system libraries on embedded */
+ /* systems that have multiple system libraries, some with or without */
+ /* file stream support, in the cases where file stream support is not */
+ /* necessary such as memory loading of font files. */
+ /* */
+/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
+
+
+ /*************************************************************************/
+ /* */
/* DLL export compilation */
/* */
/* When compiling FreeType as a DLL, some systems/compilers need a */
@@ -365,6 +391,39 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* */
+ /* Autofitter debugging */
+ /* */
+ /* If FT_DEBUG_AUTOFIT is defined, FreeType provides some means to */
+ /* control the autofitter behaviour for debugging purposes with global */
+ /* boolean variables (consequently, you should *never* enable this */
+ /* while compiling in `release' mode): */
+ /* */
+ /* _af_debug_disable_horz_hints */
+ /* _af_debug_disable_vert_hints */
+ /* _af_debug_disable_blue_hints */
+ /* */
+ /* Additionally, the following functions provide dumps of various */
+ /* internal autofit structures to stdout (using `printf'): */
+ /* */
+ /* af_glyph_hints_dump_points */
+ /* af_glyph_hints_dump_segments */
+ /* af_glyph_hints_dump_edges */
+ /* */
+ /* As an argument, they use another global variable: */
+ /* */
+ /* _af_debug_hints */
+ /* */
+ /* Please have a look at the `ftgrid' demo program to see how those */
+ /* variables and macros should be used. */
+ /* */
+ /* Do not #undef these macros here since the build system might define */
+ /* them for certain configurations only. */
+ /* */
+/* #define FT_DEBUG_AUTOFIT */
+
+
+ /*************************************************************************/
+ /* */
/* Memory Debugging */
/* */
/* FreeType now comes with an integrated memory debugger that is */
@@ -575,7 +634,7 @@ FT_BEGIN_HEADER
/* composite flags array which can be used to disambiguate, but old */
/* fonts will not have them. */
/* */
- /* http://partners.adobe.com/asn/developer/opentype/glyf.html */
+ /* http://www.microsoft.com/typography/otspec/glyf.htm */
/* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
/* */
#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
@@ -676,6 +735,19 @@ FT_BEGIN_HEADER
/* */
#define AF_CONFIG_OPTION_INDIC
+ /*************************************************************************/
+ /* */
+ /* Compile autofit module with warp hinting. The idea of the warping */
+ /* code is to slightly scale and shift a glyph within a single dimension */
+ /* so that as much of its segments are aligned (more or less) on the */
+ /* 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. */
+ /* */
+/* #define AF_CONFIG_OPTION_USE_WARPER */
+
/* */
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 7799b70..660b303 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,8 +4,7 @@
/* */
/* FreeType high-level API and common types (specification only). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -227,10 +226,12 @@ FT_BEGIN_HEADER
/* Left side bearing for vertical layout. */
/* */
/* vertBearingY :: */
- /* Top side bearing for vertical layout. */
+ /* Top side bearing for vertical layout. Larger positive values */
+ /* mean further below the vertical glyph origin. */
/* */
/* vertAdvance :: */
- /* Advance height for vertical layout. */
+ /* Advance height for vertical layout. Positive values mean the */
+ /* glyph has a positive advance downward. */
/* */
/* <Note> */
/* If not disabled with @FT_LOAD_NO_HINTING, the values represent */
@@ -1058,12 +1059,12 @@ FT_BEGIN_HEADER
/* */
/* It is not possible to autohint such fonts using */
/* @FT_LOAD_FORCE_AUTOHINT; it will also ignore */
- /* @FT_LOAD_NO_HINTING. You have to set both FT_LOAD_NO_HINTING */
+ /* @FT_LOAD_NO_HINTING. You have to set both @FT_LOAD_NO_HINTING */
/* and @FT_LOAD_NO_AUTOHINT to really disable hinting; however, you */
/* probably never want this except for demonstration purposes. */
/* */
- /* Currently, there are six TrueType fonts in the list of tricky */
- /* fonts; they are hard-coded in file `ttobjs.c'. */
+ /* Currently, there are about a dozen TrueType fonts in the list of */
+ /* tricky fonts; they are hard-coded in file `ttobjs.c'. */
/* */
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
@@ -2106,8 +2107,8 @@ FT_BEGIN_HEADER
/* used to determine both scaling values. */
/* */
/* FT_SIZE_REQUEST_TYPE_REAL_DIM :: */
- /* The real dimension. The sum of the the `Ascender' and (minus */
- /* of) the `Descender' fields of @FT_FaceRec are used to determine */
+ /* The real dimension. The sum of the the `ascender' and (minus */
+ /* of) the `descender' fields of @FT_FaceRec are used to determine */
/* both scaling values. */
/* */
/* FT_SIZE_REQUEST_TYPE_BBOX :: */
@@ -2445,13 +2446,7 @@ FT_BEGIN_HEADER
* in fonts. By default, FreeType tries to handle broken fonts also.
*
* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
- * Indicates that the font driver should ignore the global advance
- * width defined in the font. By default, that value is used as the
- * advance width for all glyphs when the face has
- * @FT_FACE_FLAG_FIXED_WIDTH set.
- *
- * This flag exists for historical reasons (to support buggy CJK
- * fonts).
+ * Ignored. Deprecated.
*
* FT_LOAD_NO_RECURSE ::
* This flag is only used internally. It merely indicates that the
@@ -2921,6 +2916,10 @@ FT_BEGIN_HEADER
/* The glyph name is truncated to fit within the buffer if it is too */
/* long. The returned string is always zero-terminated. */
/* */
+ /* Be aware that FreeType reorders glyph indices internally so that */
+ /* 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'. */
@@ -3331,6 +3330,9 @@ FT_BEGIN_HEADER
/* in the @PS_FontInfoRec structure which is only guaranteed to */
/* return the correct results for Type~1 fonts. */
/* */
+ /* <Since> */
+ /* 2.3.8 */
+ /* */
FT_EXPORT( FT_UShort )
FT_Get_FSType_Flags( FT_Face face );
@@ -3808,7 +3810,7 @@ FT_BEGIN_HEADER
*/
#define FREETYPE_MAJOR 2
#define FREETYPE_MINOR 4
-#define FREETYPE_PATCH 2
+#define FREETYPE_PATCH 6
/*************************************************************************/
diff --git a/include/freetype/ftbbox.h b/include/freetype/ftbbox.h
index 01fe3fb..9766919 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 by */
+/* Copyright 1996-2001, 2003, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -73,6 +73,14 @@ FT_BEGIN_HEADER
/* <Return> */
/* FreeType error code. 0~means success. */
/* */
+ /* <Note> */
+ /* If the font is tricky and the glyph has been loaded with */
+ /* @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 */
+ /* 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/ftbzip2.h b/include/freetype/ftbzip2.h
new file mode 100644
index 0000000..1bf81b1
--- /dev/null
+++ b/include/freetype/ftbzip2.h
@@ -0,0 +1,102 @@
+/***************************************************************************/
+/* */
+/* ftbzip2.h */
+/* */
+/* Bzip2-compressed stream support. */
+/* */
+/* Copyright 2010 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 a9e1237..6af5306 100644
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -56,9 +56,12 @@ FT_BEGIN_HEADER
* interpret them in any way.
*
* Second, the cache calls, only when needed, a client-provided function
- * to convert a @FTC_FaceID into a new @FT_Face object. The latter is
+ * to convert an @FTC_FaceID into a new @FT_Face object. The latter is
* then completely managed by the cache, including its termination
- * through @FT_Done_Face.
+ * through @FT_Done_Face. To monitor termination of face objects, the
+ * finalizer callback in the `generic' field of the @FT_Face object can
+ * be used, which might also be used to store the @FTC_FaceID of the
+ * face.
*
* Clients are free to map face IDs to anything else. The most simple
* usage is to associate them to a (pathname,face_index) pair that is
@@ -211,12 +214,17 @@ FT_BEGIN_HEADER
/* */
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* these macros are incompatible with LLP64, should not be used */
+
#define FT_POINTER_TO_ULONG( p ) ( (FT_ULong)(FT_Pointer)(p) )
#define FTC_FACE_ID_HASH( i ) \
((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \
( FT_POINTER_TO_ULONG( i ) << 7 ) ) )
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
/*************************************************************************/
/*************************************************************************/
@@ -697,11 +705,17 @@ FT_BEGIN_HEADER
(d1)->width == (d2)->width && \
(d1)->flags == (d2)->flags )
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+
+ /* this macro is incompatible with LLP64, should not be used */
+
#define FTC_IMAGE_TYPE_HASH( d ) \
(FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id ) ^ \
( (d)->width << 8 ) ^ (d)->height ^ \
( (d)->flags << 4 ) )
+#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
+
/*************************************************************************/
/* */
@@ -1093,6 +1107,7 @@ FT_BEGIN_HEADER
(f1)->pix_width == (f2)->pix_width && \
(f1)->pix_height == (f2)->pix_height )
+ /* this macro is incompatible with LLP64, should not be used */
#define FTC_FONT_HASH( f ) \
(FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \
((f)->pix_width << 8) ^ \
diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h
index 7775a6b..6cdf54e 100644
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -98,6 +98,7 @@
/* module_management */
/* gzip */
/* lzw */
+/* bzip2 */
/* lcd_filtering */
/* */
/***************************************************************************/
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index bf52220..d4e7287 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -214,7 +214,6 @@
FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \
"no Unicode glyph name found" )
-
/* BDF errors */
FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \
diff --git a/include/freetype/ftgasp.h b/include/freetype/ftgasp.h
index 91a769e..5e978e5 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 by */
+/* Copyright 2007, 2008, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -62,19 +62,27 @@
* It is up to the client to decide what to do.
*
* FT_GASP_DO_GRIDFIT ::
- * Grid-fitting and hinting should be performed at the specified ppem.
- * This *really* means TrueType bytecode interpretation.
+ * Grid-fitting and hinting should be performed at the specified ppem.
+ * This *really* means TrueType bytecode interpretation. If this bit
+ * is not set, no hinting gets applied.
*
* FT_GASP_DO_GRAY ::
- * Anti-aliased rendering should be performed at the specified ppem.
+ * Anti-aliased rendering should be performed at the specified ppem.
+ * If not set, do monochrome rendering.
*
* FT_GASP_SYMMETRIC_SMOOTHING ::
- * Smoothing along multiple axes must be used with ClearType.
+ * If set, smoothing along multiple axes must be used with ClearType.
*
* FT_GASP_SYMMETRIC_GRIDFIT ::
* Grid-fitting must be used with ClearType's symmetric smoothing.
*
* @note:
+ * The bit-flags `FT_GASP_DO_GRIDFIT' and `FT_GASP_DO_GRAY' are to be
+ * used for standard font rasterization only. Independently of that,
+ * `FT_GASP_SYMMETRIC_SMOOTHING' and `FT_GASP_SYMMETRIC_GRIDFIT' are to
+ * be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT' and
+ * `FT_GASP_DO_GRAY' are consequently ignored).
+ *
* `ClearType' is Microsoft's implementation of LCD rendering, partly
* protected by patents.
*
diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index 0b8f0c0..3de69f7 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009 by */
+/* Copyright 1996-2003, 2006, 2008, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -384,6 +384,13 @@ FT_BEGIN_HEADER
/* units in 26.6 pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS */
/* is another name for this constant. */
/* */
+ /* If the font is tricky and the glyph has been loaded with */
+ /* @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 */
+ /* which can be eventually converted back to font units. */
+ /* */
/* Note that the maximum coordinates are exclusive, which means that */
/* one can compute the width and height of the glyph image (be it in */
/* integer or 26.6 pixels) as: */
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 0272e92..04b5e04 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -268,9 +268,21 @@ FT_BEGIN_HEADER
/* flow. In all cases, the pitch is an offset to add */
/* to a bitmap pointer in order to go down one row. */
/* */
+ /* Note that `padding' means the alignment of a */
+ /* bitmap to a byte border, and FreeType functions */
+ /* normally align to the smallest possible integer */
+ /* value. */
+ /* */
/* For the B/W rasterizer, `pitch' is always an even */
/* number. */
/* */
+ /* To change the pitch of a bitmap (say, to make it a */
+ /* multiple of 4), use @FT_Bitmap_Convert. */
+ /* Alternatively, you might use callback functions to */
+ /* directly render to the application's surface; see */
+ /* the file `example2.cpp' in the tutorial for a */
+ /* demonstration. */
+ /* */
/* buffer :: A typeless pointer to the bitmap buffer. This */
/* value should be aligned on 32-bit boundaries in */
/* most cases. */
diff --git a/include/freetype/ftmoderr.h b/include/freetype/ftmoderr.h
index b0115dd..1bf3b38 100644
--- a/include/freetype/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
/* */
/* FreeType module error offsets (specification). */
/* */
-/* Copyright 2001, 2002, 2003, 2004, 2005 by */
+/* Copyright 2001, 2002, 2003, 2004, 2005, 2010 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -105,24 +105,25 @@
FT_MODERRDEF( Base, 0x000, "base module" )
FT_MODERRDEF( Autofit, 0x100, "autofitter module" )
FT_MODERRDEF( BDF, 0x200, "BDF module" )
- FT_MODERRDEF( Cache, 0x300, "cache module" )
- FT_MODERRDEF( CFF, 0x400, "CFF module" )
- FT_MODERRDEF( CID, 0x500, "CID module" )
- FT_MODERRDEF( Gzip, 0x600, "Gzip module" )
- FT_MODERRDEF( LZW, 0x700, "LZW module" )
- FT_MODERRDEF( OTvalid, 0x800, "OpenType validation module" )
- FT_MODERRDEF( PCF, 0x900, "PCF module" )
- FT_MODERRDEF( PFR, 0xA00, "PFR module" )
- FT_MODERRDEF( PSaux, 0xB00, "PS auxiliary module" )
- FT_MODERRDEF( PShinter, 0xC00, "PS hinter module" )
- FT_MODERRDEF( PSnames, 0xD00, "PS names module" )
- FT_MODERRDEF( Raster, 0xE00, "raster module" )
- FT_MODERRDEF( SFNT, 0xF00, "SFNT module" )
- FT_MODERRDEF( Smooth, 0x1000, "smooth raster module" )
- FT_MODERRDEF( TrueType, 0x1100, "TrueType module" )
- FT_MODERRDEF( Type1, 0x1200, "Type 1 module" )
- FT_MODERRDEF( Type42, 0x1300, "Type 42 module" )
- FT_MODERRDEF( Winfonts, 0x1400, "Windows FON/FNT module" )
+ FT_MODERRDEF( Bzip2, 0x300, "Bzip2 module" )
+ FT_MODERRDEF( Cache, 0x400, "cache module" )
+ FT_MODERRDEF( CFF, 0x500, "CFF module" )
+ FT_MODERRDEF( CID, 0x600, "CID module" )
+ FT_MODERRDEF( Gzip, 0x700, "Gzip module" )
+ FT_MODERRDEF( LZW, 0x800, "LZW module" )
+ FT_MODERRDEF( OTvalid, 0x900, "OpenType validation module" )
+ FT_MODERRDEF( PCF, 0xA00, "PCF module" )
+ FT_MODERRDEF( PFR, 0xB00, "PFR module" )
+ FT_MODERRDEF( PSaux, 0xC00, "PS auxiliary module" )
+ FT_MODERRDEF( PShinter, 0xD00, "PS hinter module" )
+ FT_MODERRDEF( PSnames, 0xE00, "PS names module" )
+ FT_MODERRDEF( Raster, 0xF00, "raster module" )
+ FT_MODERRDEF( SFNT, 0x1000, "SFNT module" )
+ FT_MODERRDEF( Smooth, 0x1100, "smooth raster module" )
+ FT_MODERRDEF( TrueType, 0x1200, "TrueType module" )
+ FT_MODERRDEF( Type1, 0x1300, "Type 1 module" )
+ FT_MODERRDEF( Type42, 0x1400, "Type 42 module" )
+ FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
#ifdef FT_MODERR_END_LIST
diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h
index 2829a05..1cf3c3f 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-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2003, 2005-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -227,6 +227,9 @@ FT_BEGIN_HEADER
/* <Output> */
/* acbox :: The outline's control box. */
/* */
+ /* <Note> */
+ /* See @FT_Glyph_Get_CBox for a discussion of tricky fonts. */
+ /* */
FT_EXPORT( void )
FT_Outline_Get_CBox( const FT_Outline* outline,
FT_BBox *acbox );
@@ -332,7 +335,7 @@ FT_BEGIN_HEADER
/* handled incorrectly. */
/* */
/* If you need `better' metrics values you should call */
- /* @FT_Outline_Get_CBox ot @FT_Outline_Get_BBox. */
+ /* @FT_Outline_Get_CBox or @FT_Outline_Get_BBox. */
/* */
/* Example call: */
/* */
diff --git a/include/freetype/ftrender.h b/include/freetype/ftrender.h
index e06a814..dd0229b 100644
--- a/include/freetype/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -212,6 +212,14 @@ FT_BEGIN_HEADER
/* */
/* 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. */
+ /* */
FT_EXPORT( FT_Error )
FT_Set_Renderer( FT_Library library,
FT_Renderer renderer,
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index 3afb87d..dbda6d2 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (specification). */
/* */
-/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009 by */
+/* Copyright 2002-2006, 2008, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -75,20 +75,44 @@ FT_BEGIN_HEADER
* to join two lines smoothly.
*
* FT_STROKER_LINEJOIN_BEVEL ::
- * Used to render beveled line joins; i.e., the two joining lines
- * are extended until they intersect.
- *
+ * Used to render beveled line joins. The outer corner of
+ * the joined lines is filled by enclosing the triangular
+ * region of the corner with a straight line between the
+ * outer corners of each stroke.
+ *
+ * FT_STROKER_LINEJOIN_MITER_FIXED ::
+ * Used to render mitered line joins, with fixed bevels if the
+ * miter limit is exceeded. The outer edges of the strokes
+ * for the two segments are extended until they meet at an
+ * angle. If the segments meet at too sharp an angle (such
+ * that the miter would extend from the intersection of the
+ * segments a distance greater than the product of the miter
+ * limit value and the border radius), then a bevel join (see
+ * above) is used instead. This prevents long spikes being
+ * created. FT_STROKER_LINEJOIN_MITER_FIXED generates a miter
+ * line join as used in PostScript and PDF.
+ *
+ * FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* FT_STROKER_LINEJOIN_MITER ::
- * Same as beveled rendering, except that an additional line
- * break is added if the angle between the two joining lines
- * is too closed (this is useful to avoid unpleasant spikes
- * in beveled rendering).
+ * Used to render mitered line joins, with variable bevels if
+ * the miter limit is exceeded. The intersection of the
+ * strokes is clipped at a line perpendicular to the bisector
+ * of the angle between the strokes, at the distance from the
+ * intersection of the segments equal to the product of the
+ * miter limit value and the border radius. This prevents
+ * long spikes being created.
+ * FT_STROKER_LINEJOIN_MITER_VARIABLE generates a mitered line
+ * join as used in XPS. FT_STROKER_LINEJOIN_MITER is an alias
+ * for FT_STROKER_LINEJOIN_MITER_VARIABLE, retained for
+ * backwards compatibility.
*/
typedef enum FT_Stroker_LineJoin_
{
- FT_STROKER_LINEJOIN_ROUND = 0,
- FT_STROKER_LINEJOIN_BEVEL,
- FT_STROKER_LINEJOIN_MITER
+ FT_STROKER_LINEJOIN_ROUND = 0,
+ FT_STROKER_LINEJOIN_BEVEL = 1,
+ FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
+ FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE,
+ FT_STROKER_LINEJOIN_MITER_FIXED = 3
} FT_Stroker_LineJoin;
@@ -245,7 +269,8 @@ FT_BEGIN_HEADER
* The line join style.
*
* miter_limit ::
- * The miter limit for the FT_STROKER_LINEJOIN_MITER style,
+ * The miter limit for the FT_STROKER_LINEJOIN_MITER_FIXED and
+ * FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
* expressed as 16.16 fixed point value.
*
* @note:
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index a91eb72..8b18500 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
/* */
/* Stream handling (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006 by */
+/* Copyright 1996-2002, 2004-2006, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -292,18 +292,18 @@ FT_BEGIN_HEADER
#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char )
#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )
-#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_Short )
-#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_UShort )
-#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_Long )
-#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_ULong )
-#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetLong, FT_Long )
-#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
-#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong )
-
-#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_Short )
-#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_UShort )
-#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_Long )
-#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_ULong )
+#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_Short )
+#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort )
+#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long )
+#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong )
+#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetULong, FT_Long )
+#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
+#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
+
+#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short )
+#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort )
+#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long )
+#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong )
#endif
#define FT_READ_MACRO( func, type, var ) \
@@ -312,17 +312,17 @@ FT_BEGIN_HEADER
#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )
#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )
-#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_Short, var )
-#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_UShort, var )
-#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_Long, var )
-#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_ULong, var )
-#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_Long, var )
-#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_ULong, var )
+#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var )
+#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var )
+#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_Long, var )
+#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var )
+#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var )
+#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var )
-#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_Short, var )
-#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_UShort, var )
-#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_Long, var )
-#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_ULong, var )
+#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_Short, var )
+#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadUShortLE, FT_UShort, var )
+#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_Long, var )
+#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadULongLE, FT_ULong, var )
#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
@@ -431,25 +431,25 @@ FT_BEGIN_HEADER
FT_BASE( FT_Char )
FT_Stream_GetChar( FT_Stream stream );
- /* read a 16-bit big-endian integer from an entered frame */
- FT_BASE( FT_Short )
- FT_Stream_GetShort( FT_Stream stream );
+ /* read a 16-bit big-endian unsigned integer from an entered frame */
+ FT_BASE( FT_UShort )
+ FT_Stream_GetUShort( FT_Stream stream );
- /* read a 24-bit big-endian integer from an entered frame */
- FT_BASE( FT_Long )
- FT_Stream_GetOffset( FT_Stream stream );
+ /* read a 24-bit big-endian unsigned integer from an entered frame */
+ FT_BASE( FT_ULong )
+ FT_Stream_GetUOffset( FT_Stream stream );
- /* read a 32-bit big-endian integer from an entered frame */
- FT_BASE( FT_Long )
- FT_Stream_GetLong( FT_Stream stream );
+ /* read a 32-bit big-endian unsigned integer from an entered frame */
+ FT_BASE( FT_ULong )
+ FT_Stream_GetULong( FT_Stream stream );
- /* read a 16-bit little-endian integer from an entered frame */
- FT_BASE( FT_Short )
- FT_Stream_GetShortLE( FT_Stream stream );
+ /* read a 16-bit little-endian unsigned integer from an entered frame */
+ FT_BASE( FT_UShort )
+ FT_Stream_GetUShortLE( FT_Stream stream );
- /* read a 32-bit little-endian integer from an entered frame */
- FT_BASE( FT_Long )
- FT_Stream_GetLongLE( FT_Stream stream );
+ /* read a 32-bit little-endian unsigned integer from an entered frame */
+ FT_BASE( FT_ULong )
+ FT_Stream_GetULongLE( FT_Stream stream );
/* read a byte from a stream */
@@ -457,30 +457,30 @@ FT_BEGIN_HEADER
FT_Stream_ReadChar( FT_Stream stream,
FT_Error* error );
- /* read a 16-bit big-endian integer from a stream */
- FT_BASE( FT_Short )
- FT_Stream_ReadShort( FT_Stream stream,
- FT_Error* error );
-
- /* read a 24-bit big-endian integer from a stream */
- FT_BASE( FT_Long )
- FT_Stream_ReadOffset( FT_Stream stream,
+ /* read a 16-bit big-endian unsigned integer from a stream */
+ FT_BASE( FT_UShort )
+ FT_Stream_ReadUShort( FT_Stream stream,
FT_Error* error );
+ /* read a 24-bit big-endian unsigned integer from a stream */
+ FT_BASE( FT_ULong )
+ FT_Stream_ReadUOffset( FT_Stream stream,
+ FT_Error* error );
+
/* read a 32-bit big-endian integer from a stream */
- FT_BASE( FT_Long )
- FT_Stream_ReadLong( FT_Stream stream,
- FT_Error* error );
+ FT_BASE( FT_ULong )
+ FT_Stream_ReadULong( FT_Stream stream,
+ FT_Error* error );
- /* read a 16-bit little-endian integer from a stream */
- FT_BASE( FT_Short )
- FT_Stream_ReadShortLE( FT_Stream stream,
- FT_Error* error );
+ /* read a 16-bit little-endian unsigned integer from a stream */
+ FT_BASE( FT_UShort )
+ FT_Stream_ReadUShortLE( FT_Stream stream,
+ FT_Error* error );
- /* read a 32-bit little-endian integer from a stream */
- FT_BASE( FT_Long )
- FT_Stream_ReadLongLE( FT_Stream stream,
- FT_Error* error );
+ /* read a 32-bit little-endian unsigned integer from a stream */
+ FT_BASE( FT_ULong )
+ FT_Stream_ReadULongLE( FT_Stream stream,
+ FT_Error* error );
/* Read a structure from a stream. The structure must be described */
/* by an array of FT_Frame_Field records. */
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index e9b383a..fbefdbd 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
/* */
/* Tracing handling (specification only). */
/* */
-/* Copyright 2002, 2004, 2005, 2006, 2007 by */
+/* Copyright 2002, 2004-2007, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -135,5 +135,10 @@ FT_TRACE_DEF( gxvtrak )
FT_TRACE_DEF( gxvprop )
FT_TRACE_DEF( gxvlcar )
+ /* autofit components */
+FT_TRACE_DEF( afcjk )
+FT_TRACE_DEF( aflatin )
+FT_TRACE_DEF( aflatin2 )
+FT_TRACE_DEF( afwarp )
/* 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/tttables.h b/include/freetype/tttables.h
index 4610e50..02236c2 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-2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 by */
+/* Copyright 1996-2005, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -687,12 +687,16 @@ FT_BEGIN_HEADER
* The index of an SFNT table. The function returns
* FT_Err_Table_Missing for an invalid value.
*
- * @output:
+ * @inout:
* tag ::
- * The name tag of the SFNT table.
+ * The name tag of the SFNT table. If the value is NULL, `table_index'
+ * is ignored, and `length' returns the number of SFNT tables in the
+ * font.
*
+ * @output:
* length ::
- * The length of the SFNT table.
+ * The length of the SFNT table (or the number of SFNT tables, depending
+ * on `tag').
*
* @return:
* FreeType error code. 0~means success.
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index e2360d1..790af17 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, 2004, 2005, 2006 by */
+/* Copyright 2003-2006, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -77,7 +77,7 @@
return 1 - 2 * ( delta < 0 );
}
-#endif
+#endif /* 0 */
/*
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index f3b1067..0acef9c 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK script (body). */
/* */
-/* Copyright 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2006-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,22 +22,38 @@
*
*/
+#include <ft2build.h>
+#include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
+
#include "aftypes.h"
#include "aflatin.h"
#ifdef AF_CONFIG_OPTION_CJK
+#undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
#include "afcjk.h"
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/*************************************************************************/
+ /* */
+ /* 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_afcjk
+
+
+ /*************************************************************************/
/*************************************************************************/
/***** *****/
/***** C J K G L O B A L M E T R I C S *****/
@@ -45,24 +61,504 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Basically the Latin version with AF_CJKMetrics */
+ /* to replace AF_LatinMetrics. */
+
+ FT_LOCAL_DEF( void )
+ af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode )
+ {
+ /* scan the array of segments in each direction */
+ AF_GlyphHintsRec hints[1];
+
+
+ af_glyph_hints_init( hints, face->memory );
+
+ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+ {
+ FT_Error error;
+ FT_UInt glyph_index;
+ int dim;
+ AF_CJKMetricsRec dummy[1];
+ AF_Scaler scaler = &dummy->root.scaler;
+
+
+ glyph_index = FT_Get_Char_Index( face, charcode );
+ if ( glyph_index == 0 )
+ goto Exit;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || face->glyph->outline.n_points <= 0 )
+ goto Exit;
+
+ FT_ZERO( dummy );
+
+ dummy->units_per_em = metrics->units_per_em;
+
+ scaler->x_scale = 0x10000L;
+ scaler->y_scale = 0x10000L;
+ scaler->x_delta = 0;
+ scaler->y_delta = 0;
+
+ scaler->face = face;
+ scaler->render_mode = FT_RENDER_MODE_NORMAL;
+ scaler->flags = 0;
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+
+ error = af_glyph_hints_reload( hints, &face->glyph->outline );
+ if ( error )
+ goto Exit;
+
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_CJKAxis axis = &metrics->axis[dim];
+ AF_AxisHints axhints = &hints->axis[dim];
+ AF_Segment seg, limit, link;
+ FT_UInt num_widths = 0;
+
+
+ error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim );
+ if ( error )
+ goto Exit;
+
+ af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+
+ seg = axhints->segments;
+ limit = seg + axhints->num_segments;
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < AF_CJK_MAX_WIDTHS )
+ axis->widths[num_widths++].org = dist;
+ }
+ }
+
+ af_sort_widths( num_widths, axis->widths );
+ axis->width_count = num_widths;
+ }
+
+ Exit:
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_CJKAxis axis = &metrics->axis[dim];
+ FT_Pos stdw;
+
+
+ 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;
+ axis->standard_width = stdw;
+ axis->extra_light = 0;
+ }
+ }
+
+ 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. */
+
+ 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] )
+ {
+ FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
+ FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
+
+ FT_Int num_fills;
+ FT_Int num_flats;
+
+ FT_Int bb;
+ AF_CJKBlue blue;
+ FT_Error error;
+ AF_CJKAxis axis;
+ FT_GlyphSlot glyph = face->glyph;
+
+#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
+
+
+ /* 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;
+
+
+ num_fills = 0;
+ num_flats = 0;
+
+ for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
+ {
+ 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_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
+ cjk_blue_type_name[fill_type] ));
+
+
+ for ( ; p < limit && *p; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Pos best_pos; /* same as points.y */
+ FT_Int best_point;
+ FT_Vector* points;
+
+
+ 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 )
+ {
+ 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;
+
+
+ for ( nn = 0;
+ nn < glyph->outline.n_contours;
+ first = last + 1, nn++ )
+ {
+ 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 )
+ {
+ 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:
+ ;
+ }
+ }
+ FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
+ }
+
+ if ( fill )
+ fills[num_fills++] = best_pos;
+ else
+ flats[num_flats++] = best_pos;
+ }
+ }
+
+ if ( num_flats == 0 && num_fills == 0 )
+ {
+ /*
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+ 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 );
+ af_sort_pos( num_fills, fills );
+
+ 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;
+
+ axis->blue_count++;
+ if ( num_flats == 0 )
+ {
+ *blue_ref = fills[num_fills / 2];
+ *blue_shoot = fills[num_fills / 2];
+ }
+ else if ( num_fills == 0 )
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = fills[num_fills / 2];
+ *blue_shoot = flats[num_flats / 2];
+ }
+
+ /* make sure blue_ref >= blue_shoot for top/right or */
+ /* vice versa for bottom/left */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ 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;
+ }
+
+ 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;
+
+ FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n",
+ cjk_blue_name[bb], *blue_ref, *blue_shoot ));
+ }
+
+ 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;
+
+
+ /* check whether all ASCII digits have the same advance width; */
+ /* digit `0' is 0x30 in all supported charmaps */
+ for ( i = 0x30; i <= 0x39; i++ )
+ {
+ FT_UInt glyph_index;
+
+
+ glyph_index = FT_Get_Char_Index( face, i );
+ if ( glyph_index == 0 )
+ continue;
+
+ if ( FT_Get_Advance( face, glyph_index,
+ FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_IGNORE_TRANSFORM,
+ &advance ) )
+ continue;
+
+ if ( started )
+ {
+ if ( advance != old_advance )
+ {
+ same_width = 0;
+ break;
+ }
+ }
+ else
+ {
+ old_advance = advance;
+ started = 1;
+ }
+ }
+
+ metrics->root.digits_have_same_width = same_width;
+ }
+
+
FT_LOCAL_DEF( FT_Error )
- af_cjk_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ af_cjk_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face )
{
FT_CharMap oldmap = face->charmap;
metrics->units_per_em = face->units_per_EM;
- /* TODO are there blues? */
-
if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
face->charmap = NULL;
else
{
- /* latin's version would suffice */
- af_latin_metrics_init_widths( metrics, face, 0x7530 );
- af_latin_metrics_check_digits( metrics, face );
+ af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+ af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
+ af_cjk_metrics_check_digits( metrics, face );
}
FT_Set_Charmap( face, oldmap );
@@ -72,31 +568,100 @@
static void
- af_cjk_metrics_scale_dim( AF_LatinMetrics metrics,
- AF_Scaler scaler,
- AF_Dimension dim )
+ af_cjk_metrics_scale_dim( AF_CJKMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
{
- AF_LatinAxis axis;
+ FT_Fixed scale;
+ FT_Pos delta;
+ AF_CJKAxis axis;
+ FT_UInt nn;
axis = &metrics->axis[dim];
if ( dim == AF_DIMENSION_HORZ )
{
- axis->scale = scaler->x_scale;
- axis->delta = scaler->x_delta;
+ scale = scaler->x_scale;
+ delta = scaler->x_delta;
}
else
{
- axis->scale = scaler->y_scale;
- axis->delta = scaler->y_delta;
+ scale = scaler->y_scale;
+ delta = scaler->y_delta;
+ }
+
+ if ( axis->org_scale == scale && axis->org_delta == delta )
+ return;
+
+ axis->org_scale = scale;
+ axis->org_delta = delta;
+
+ axis->scale = scale;
+ axis->delta = delta;
+
+ /* scale the blue zones */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_CJKBlue blue = &axis->blues[nn];
+ FT_Pos dist;
+
+
+ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
+ blue->ref.fit = blue->ref.cur;
+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+ blue->shoot.fit = blue->shoot.cur;
+ blue->flags &= ~AF_CJK_BLUE_ACTIVE;
+
+ /* a blue zone is only active if it is less than 3/4 pixels tall */
+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
+ if ( dist <= 48 && dist >= -48 )
+ {
+ FT_Pos delta1, delta2;
+
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+
+ /* shoot is under shoot for cjk */
+ delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org;
+ delta2 = delta1;
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ delta2 = FT_MulFix( delta2, scale );
+
+ FT_TRACE5(( "delta: %d", delta1 ));
+ if ( delta2 < 32 )
+ delta2 = 0;
+#if 0
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+#endif
+ else
+ delta2 = FT_PIX_ROUND( delta2 );
+ FT_TRACE5(( "/%d\n", delta2 ));
+
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ 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 ));
+
+ blue->flags |= AF_CJK_BLUE_ACTIVE;
+ }
}
}
FT_LOCAL_DEF( void )
- af_cjk_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ af_cjk_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler )
{
metrics->root.scaler = *scaler;
@@ -329,7 +894,7 @@
AF_AxisHints axis = &hints->axis[dim];
FT_Error error = AF_Err_Ok;
FT_Memory memory = hints->memory;
- AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+ AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
@@ -601,9 +1166,96 @@
}
+ FT_LOCAL_DEF( void )
+ af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
+ AF_CJKMetrics metrics,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edge = axis->edges;
+ AF_Edge edge_limit = edge + axis->num_edges;
+ AF_CJKAxis cjk = &metrics->axis[dim];
+ FT_Fixed scale = cjk->scale;
+ FT_Pos best_dist0; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
+
+ if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */
+ best_dist0 = 64 / 2;
+
+ /* compute which blue zones are active, i.e. have their scaled */
+ /* size < 3/4 pixels */
+
+ /* If the distant between an edge and a blue zone is shorter than */
+ /* best_dist0, set the blue zone for the edge. Then search for */
+ /* the blue zone with the smallest best_dist to the edge. */
+
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_UInt bb;
+ AF_Width best_blue = NULL;
+ FT_Pos best_dist = best_dist0;
+
+
+ for ( bb = 0; bb < cjk->blue_count; bb++ )
+ {
+ AF_CJKBlue blue = cjk->blues + bb;
+ FT_Bool is_top_right_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too small) */
+ if ( !( blue->flags & AF_CJK_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_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 );
+
+ /* 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_right_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+ AF_Width compare;
+
+
+ /* Compare the edge to the closest blue zone type */
+ if ( FT_ABS( edge->fpos - blue->ref.org ) >
+ FT_ABS( edge->fpos - blue->shoot.org ) )
+ compare = &blue->shoot;
+ else
+ compare = &blue->ref;
+
+ dist = edge->fpos - compare->org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = compare;
+ }
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ af_cjk_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
@@ -623,7 +1275,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#ifdef AF_USE_WARPER
+#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
@@ -728,11 +1380,11 @@
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
- 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 );
+ 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 );
FT_UNUSED( base_flags );
FT_UNUSED( stem_flags );
@@ -1025,7 +1677,61 @@
AF_Edge anchor = 0;
FT_Pos delta = 0;
FT_Int skipped = 0;
+ FT_Bool has_last_stem = FALSE;
+ FT_Pos last_stem_pos = 0;
+
+ /* 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 ) )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Width blue;
+ AF_Edge edge1, edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ 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 ));
+
+ edge1->pos = blue->fit;
+ edge1->flags |= AF_EDGE_DONE;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ af_cjk_align_linked_edge( hints, dim, edge1, edge2 );
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ if ( !anchor )
+ anchor = edge;
+ }
+ }
/* now we align all stem edges. */
for ( edge = edges; edge < edge_limit; edge++ )
@@ -1044,12 +1750,43 @@
continue;
}
+ /* Some CJK characters have so many stems that
+ * the hinter is likely to merge two adjacent ones.
+ * To solve this problem, if either edge of a stem
+ * is too close to the previous one, we avoid
+ * aligning the two edges, but rather interpolate
+ * their locations at the end of this function in
+ * order to preserve the space between the stems.
+ */
+ if ( has_last_stem &&
+ ( edge->pos < last_stem_pos + 64 ||
+ edge2->pos < last_stem_pos + 64 ) )
+ {
+ skipped++;
+ continue;
+ }
+
/* now align the stem */
+ /* 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 ));
+
+ af_cjk_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
if ( edge2 < edge )
{
af_cjk_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
+ /* We rarely reaches here it seems;
+ * usually the two edges belonging
+ * to one stem are marked as DONE together
+ */
+ has_last_stem = TRUE;
+ last_stem_pos = edge->pos;
continue;
}
@@ -1142,6 +1879,8 @@
anchor = edge;
edge->flags |= AF_EDGE_DONE;
edge2->flags |= AF_EDGE_DONE;
+ has_last_stem = TRUE;
+ last_stem_pos = edge2->pos;
}
/* make sure that lowercase m's maintain their symmetry */
@@ -1361,9 +2100,9 @@
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics )
+ af_cjk_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics )
{
FT_Error error;
int dim;
@@ -1381,6 +2120,8 @@
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
goto Exit;
+
+ af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_HORZ );
}
if ( AF_HINTS_DO_VERTICAL( hints ) )
@@ -1388,6 +2129,8 @@
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT );
if ( error )
goto Exit;
+
+ af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_VERT );
}
/* grid-fit the outline */
@@ -1397,7 +2140,7 @@
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
{
@@ -1406,11 +2149,13 @@
FT_Pos delta;
- af_warper_compute( &warper, hints, dim, &scale, &delta );
- af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
continue;
}
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
af_cjk_hint_edges( hints, (AF_Dimension)dim );
af_cjk_align_edge_points( hints, (AF_Dimension)dim );
@@ -1441,18 +2186,19 @@
/*************************************************************************/
+ /* this corresponds to Unicode 6.0 */
+
static const AF_Script_UniRangeRec af_cjk_uniranges[] =
{
-#if 0
- AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */
-#endif
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 */
@@ -1461,10 +2207,19 @@
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 )
};
@@ -1474,7 +2229,7 @@
AF_SCRIPT_CJK,
af_cjk_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) af_cjk_metrics_init,
(AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
@@ -1496,7 +2251,7 @@
AF_SCRIPT_CJK,
af_cjk_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index 0b20d4a..8416c0d 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK script (specification). */
/* */
-/* Copyright 2006, 2007 by */
+/* Copyright 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,6 +20,7 @@
#define __AFCJK_H__
#include "afhints.h"
+#include "aflatin.h"
FT_BEGIN_HEADER
@@ -29,23 +30,106 @@ FT_BEGIN_HEADER
AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)
+ /* CJK (global) metrics management */
+
+ /*
+ * 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_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
+ };
+
+
+ typedef struct AF_CJKBlueRec_
+ {
+ AF_WidthRec ref;
+ AF_WidthRec shoot; /* undershoot */
+ FT_UInt flags;
+
+ } AF_CJKBlueRec, *AF_CJKBlue;
+
+
+ typedef struct AF_CJKAxisRec_
+ {
+ 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;
+
+ /* used for horizontal metrics too for CJK */
+ FT_Bool control_overshoot;
+ FT_UInt blue_count;
+ AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
+
+ FT_Fixed org_scale;
+ FT_Pos org_delta;
+
+ } AF_CJKAxisRec, *AF_CJKAxis;
+
+
+ typedef struct AF_CJKMetricsRec_
+ {
+ AF_ScriptMetricsRec root;
+ FT_UInt units_per_em;
+ AF_CJKAxisRec axis[AF_DIMENSION_MAX];
+
+ } AF_CJKMetricsRec, *AF_CJKMetrics;
+
FT_LOCAL( FT_Error )
- af_cjk_metrics_init( AF_LatinMetrics metrics,
- FT_Face face );
+ af_cjk_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face );
FT_LOCAL( void )
- af_cjk_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler );
+ af_cjk_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler );
FT_LOCAL( FT_Error )
- af_cjk_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics );
+ af_cjk_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics );
FT_LOCAL( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics );
+ af_cjk_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics );
+
+ /* Shared. called from afindic.c */
+ FT_LOCAL( void )
+ af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
+ FT_Face face );
+
+ FT_LOCAL( void )
+ af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode );
+
/* */
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 42b2fcb..c712651 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, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,6 +19,7 @@
#include "afdummy.h"
#include "afhints.h"
+#include "aferrors.h"
static FT_Error
@@ -27,7 +28,7 @@
{
af_glyph_hints_rescale( hints,
metrics );
- return 0;
+ return AF_Err_Ok;
}
@@ -38,11 +39,11 @@
FT_UNUSED( hints );
FT_UNUSED( outline );
- return 0;
+ return AF_Err_Ok;
}
- AF_DEFINE_SCRIPT_CLASS(af_dummy_script_class,
+ AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
AF_SCRIPT_NONE,
NULL,
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index b69ef43..95d8f8c 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, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,7 +29,7 @@ FT_BEGIN_HEADER
* be performed. This is the default for non-latin glyphs!
*/
- AF_DECLARE_SCRIPT_CLASS(af_dummy_script_class)
+ AF_DECLARE_SCRIPT_CLASS( af_dummy_script_class )
/* */
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 178c884..3c5f02e 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, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,8 +31,8 @@
#ifndef FT_CONFIG_OPTION_PIC
-/* when updating this table, don't forget to update
- AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
+ /* when updating this table, don't forget to update */
+ /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
/* populate this list when you add new scripts */
static AF_ScriptClass const af_script_classes[] =
@@ -47,7 +47,7 @@
NULL /* do not remove */
};
-#endif /* FT_CONFIG_OPTION_PIC */
+#endif /* !FT_CONFIG_OPTION_PIC */
/* index of default script in `af_script_classes' */
#define AF_SCRIPT_LIST_DEFAULT 2
@@ -85,7 +85,7 @@
FT_UInt ss, i;
- /* the value 255 means `uncovered glyph' */
+ /* the value AF_SCRIPT_LIST_NONE means `uncovered glyph' */
FT_MEM_SET( globals->glyph_scripts,
AF_SCRIPT_LIST_NONE,
globals->glyph_count );
@@ -126,9 +126,7 @@
if ( gindex != 0 &&
gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
- {
gscripts[gindex] = (FT_Byte)ss;
- }
for (;;)
{
@@ -139,9 +137,7 @@
if ( gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
- {
gscripts[gindex] = (FT_Byte)ss;
- }
}
}
}
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index 2a68e19..cc6860b 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, 2004, 2005, 2007, 2009 by */
+/* Copyright 2003-2005, 2007, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,8 +17,8 @@
/***************************************************************************/
-#ifndef __AF_GLOBAL_H__
-#define __AF_GLOBAL_H__
+#ifndef __AFGLOBAL_H__
+#define __AFGLOBAL_H__
#include "aftypes.h"
@@ -65,7 +65,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __AF_GLOBALS_H__ */
+#endif /* __AFGLOBAL_H__ */
/* END */
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index c349709..f51066f 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 2003-2007, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,8 @@
#include FT_INTERNAL_CALC_H
+ /* Get new segment for given axis. */
+
FT_LOCAL_DEF( FT_Error )
af_axis_hints_new_segment( AF_AxisHints axis,
FT_Memory memory,
@@ -61,6 +63,8 @@
}
+ /* Get new edge for given axis, direction, and position. */
+
FT_LOCAL( FT_Error )
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
@@ -125,7 +129,7 @@
}
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
@@ -160,6 +164,9 @@
#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
{
@@ -169,20 +176,20 @@
printf( "Table of points:\n" );
- printf( " [ index | xorg | yorg | xscale | yscale "
- "| xfit | yfit | flags ]\n" );
+ printf( " [ index | xorg | yorg | xscale | yscale"
+ " | xfit | yfit | flags ]\n" );
for ( point = points; point < limit; point++ )
{
- printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "
- "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
+ printf( " [ %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->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 ) ? '<' : ' ',
@@ -192,6 +199,9 @@
}
printf( "\n" );
}
+#ifdef __cplusplus
+ }
+#endif
static const char*
@@ -222,7 +232,11 @@
}
- /* A function to dump the array of linked segments. */
+ /* Dump the array of linked segments. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
{
@@ -240,11 +254,11 @@
printf ( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
- " height | extra | flags ]\n" );
+ " height | extra | flags ]\n" );
for ( seg = segments; seg < limit; seg++ )
{
- printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
+ printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
seg - segments,
dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
: (int)seg->first->oy / 64.0,
@@ -253,13 +267,84 @@
AF_INDEX_NUM( seg->serif, segments ),
seg->height,
seg->height - ( seg->max_coord - seg->min_coord ),
- af_edge_flags_to_string( seg->flags ) );
+ af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) );
}
printf( "\n" );
}
}
+#ifdef __cplusplus
+ }
+#endif
+
+
+ /* Fetch number of segments. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ FT_Error
+ af_glyph_hints_get_num_segments( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int* num_segments )
+ {
+ AF_Dimension dim;
+ AF_AxisHints axis;
+
+
+ dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+ axis = &hints->axis[dim];
+ *num_segments = axis->num_segments;
+
+ return AF_Err_Ok;
+ }
+#ifdef __cplusplus
+ }
+#endif
+
+
+ /* Fetch offset of segments into user supplied offset array. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ FT_Error
+ af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int idx,
+ FT_Pos* offset )
+ {
+ AF_Dimension dim;
+ AF_AxisHints axis;
+ AF_Segment seg;
+
+
+ if ( !offset )
+ return AF_Err_Invalid_Argument;
+
+ dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+ axis = &hints->axis[dim];
+
+ if ( idx < 0 || idx >= axis->num_segments )
+ return AF_Err_Invalid_Argument;
+
+ seg = &axis->segments[idx];
+ *offset = (dim == AF_DIMENSION_HORZ) ? seg->first->ox
+ : seg->first->oy;
+
+ return AF_Err_Ok;
+ }
+#ifdef __cplusplus
+ }
+#endif
+
+ /* Dump the array of linked edges. */
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
@@ -276,17 +361,17 @@
/*
* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
- * since they have constant a X coordinate.
+ * since they have a constant X coordinate.
*/
printf ( "Table of %s edges:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
- " serif | blue | opos | pos | flags ]\n" );
+ " serif | blue | opos | pos | flags ]\n" );
for ( edge = edges; edge < limit; edge++ )
{
printf ( " [ %5d | %5.2g | %5s | %4d |"
- " %5d | %c | %5.2f | %5.2f | %s ]\n",
+ " %5d | %c | %5.2f | %5.2f | %11s ]\n",
edge - edges,
(int)edge->opos / 64.0,
af_dir_str( (AF_Direction)edge->dir ),
@@ -295,16 +380,23 @@
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0,
- af_edge_flags_to_string( edge->flags ) );
+ af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) );
}
printf( "\n" );
}
}
+#ifdef __cplusplus
+ }
+#endif
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
/* these empty stubs are only used to link the `ftgrid' test program */
- /* when debugging is disabled */
+ /* if debugging is disabled */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
@@ -320,16 +412,49 @@
}
+ 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 );
}
-#endif /* !AF_DEBUG */
+#ifdef __cplusplus
+ }
+#endif
+#endif /* !FT_DEBUG_AUTOFIT */
+
+
+ /* Compute the direction value of a given vector. */
- /* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
@@ -369,6 +494,8 @@
}
}
+ /* return no direction if arm lengths differ too much */
+ /* (value 14 is heuristic) */
ss *= 14;
if ( FT_ABS( ll ) <= FT_ABS( ss ) )
dir = AF_DIR_NONE;
@@ -397,7 +524,7 @@
/*
* note that we don't need to free the segment and edge
- * buffers, since they are really within the hints->points array
+ * buffers since they are really within the hints->points array
*/
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
@@ -408,8 +535,8 @@
axis->max_segments = 0;
FT_FREE( axis->segments );
- axis->num_edges = 0;
- axis->max_edges = 0;
+ axis->num_edges = 0;
+ axis->max_edges = 0;
FT_FREE( axis->edges );
}
@@ -426,6 +553,8 @@
}
+ /* Reset metrics. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
@@ -435,6 +564,9 @@
}
+ /* Recompute all AF_Point in AF_GlyphHints from the definitions */
+ /* in a source outline. */
+
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline )
@@ -457,12 +589,12 @@
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
- /* first of all, reallocate the contours array when necessary */
+ /* 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 )
{
- new_max = ( new_max + 3 ) & ~3;
+ new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
@@ -479,7 +611,7 @@
old_max = hints->max_points;
if ( new_max > old_max )
{
- new_max = ( new_max + 2 + 7 ) & ~7;
+ new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
goto Exit;
@@ -545,7 +677,7 @@
point->flags = AF_FLAG_CUBIC;
break;
default:
- point->flags = 0;
+ point->flags = AF_FLAG_NONE;
}
point->prev = prev;
@@ -563,7 +695,7 @@
}
}
- /* set-up the contours array */
+ /* set up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
@@ -611,6 +743,8 @@
in_dir = af_direction_compute( out_x, out_y );
point->out_dir = (FT_Char)in_dir;
+ /* check for weak points */
+
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
Is_Weak_Point:
@@ -639,6 +773,8 @@
}
+ /* Store the hinted outline in an FT_Outline structure. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
@@ -671,6 +807,9 @@
****************************************************************/
+ /* Align all points of an edge to the same coordinate value, */
+ /* either horizontally or vertically. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
@@ -704,7 +843,6 @@
break;
point = point->next;
-
}
}
}
@@ -744,8 +882,8 @@
****************************************************************/
- /* hint the strong points -- this is equivalent to the TrueType `IP' */
- /* hinting instruction */
+ /* Hint the strong points -- this is equivalent to the TrueType `IP' */
+ /* hinting instruction. */
FT_LOCAL_DEF( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
@@ -827,11 +965,12 @@
max = edge_limit - edges;
#if 1
- /* for small edge counts, a linear search is better */
+ /* for a small number of edges, a linear search is better */
if ( max <= 8 )
{
FT_PtrDist nn;
+
for ( nn = 0; nn < max; nn++ )
if ( edges[nn].fpos >= u )
break;
@@ -863,6 +1002,7 @@
}
}
+ /* point is not on an edge */
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
@@ -898,6 +1038,10 @@
****************************************************************/
+ /* Shift the original coordinates of all points between `p1' and */
+ /* `p2' to get hinted coordinates, using the same difference as */
+ /* given by `ref'. */
+
static void
af_iup_shift( AF_Point p1,
AF_Point p2,
@@ -906,6 +1050,7 @@
AF_Point p;
FT_Pos delta = ref->u - ref->v;
+
if ( delta == 0 )
return;
@@ -917,6 +1062,13 @@
}
+ /* Interpolate the original coordinates of all points between `p1' and */
+ /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the */
+ /* reference points. The `u' and `v' members are the current and */
+ /* original coordinate values, respectively. */
+ /* */
+ /* Details can be found in the TrueType bytecode specification. */
+
static void
af_iup_interp( AF_Point p1,
AF_Point p2,
@@ -985,6 +1137,9 @@
}
+ /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
+ /* hinting instruction. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1050,17 +1205,18 @@
for (;;)
{
- FT_ASSERT( point <= end_point &&
+ FT_ASSERT( point <= end_point &&
( point->flags & touch_flag ) != 0 );
- /* skip any touched neighbhours */
- while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
+ /* skip any touched neighbours */
+ while ( point < end_point &&
+ ( point[1].flags & touch_flag ) != 0 )
point++;
last_touched = point;
/* find the next touched point, if any */
- point ++;
+ point++;
for (;;)
{
if ( point > end_point )
@@ -1080,9 +1236,8 @@
EndContour:
/* special case: only one point was touched */
if ( last_touched == first_touched )
- {
af_iup_shift( first_point, end_point, first_touched );
- }
+
else /* interpolate the last part */
{
if ( last_touched < end_point )
@@ -1112,7 +1267,9 @@
}
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /* Apply (small) warp scale and warp delta for given dimension. */
FT_LOCAL_DEF( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
@@ -1137,6 +1294,6 @@
}
}
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
/* END */
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 10e673b..1c52e0d 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (specification). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/* Copyright 2003-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,10 +25,10 @@
FT_BEGIN_HEADER
- /*
- * The definition of outline glyph hints. These are shared by all
- * script analysis routines (until now).
- */
+ /*
+ * The definition of outline glyph hints. These are shared by all
+ * script analysis routines (until now).
+ */
typedef enum AF_Dimension_
{
@@ -55,6 +55,151 @@ FT_BEGIN_HEADER
} AF_Direction;
+ /*
+ * The following explanations are mostly taken from the article
+ *
+ * Real-Time Grid Fitting of Typographic Outlines
+ *
+ * by David Turner and Werner Lemberg
+ *
+ * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ *
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ * 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.
+ *
+ *
+ * A H
+ * | |
+ * | |
+ * | |
+ * | |
+ * C | | F
+ * +------<-----+ +-----<------+
+ * | B G |
+ * | |
+ * | |
+ * +--------------->------------------+
+ * D E
+ *
+ *
+ * Stems
+ *
+ * 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
+ * vocabulary from the TrueType specification, stem segments form a
+ * `black distance'.
+ *
+ * In the above ASCII drawing, the horizontal segments are BC, DE, and
+ * FG; the vertical segments are AB, CD, EF, and GH.
+ *
+ * Each segment has at most one `best' candidate to form a black
+ * distance, or no candidate at all. Notice that two distinct segments
+ * can have the same candidate, which frequently means a serif.
+ *
+ * A stem is recognized by the following condition:
+ *
+ * best segment_1 = segment_2 && best segment_2 = segment_1
+ *
+ * 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.
+ *
+ *
+ * Serifs
+ *
+ * On the opposite, a serif has
+ *
+ * best segment_1 = segment_2 && best segment_2 != segment_1
+ *
+ * where segment_1 corresponds to the serif segment (CD and EF in the
+ * above ASCII drawing).
+ *
+ * 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
+ *
+ * A point is called `touched' if it has been processed somehow by the
+ * auto-hinter. It basically means that it shouldn't be moved again
+ * (or moved only under certain constraints to preserve the already
+ * applied processing).
+ *
+ *
+ * Flat and round segments
+ *
+ * Segments are `round' or `flat', depending on the series of points
+ * that define them. A segment is round if the next and previous point
+ * of an extremum (which can be either a single point or sequence of
+ * points) are both conic or cubic control points. Otherwise, a
+ * segment with an extremum is flat.
+ *
+ *
+ * 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
+ *
+ * - 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)
+ *
+ * `af_glyph_hints_align_strong_points' is the function which takes
+ * care of such situations; it is equivalent to the TrueType `IP'
+ * hinting instruction.
+ *
+ *
+ * Weak Points
+ *
+ * Other points in the outline must be interpolated using the
+ * coordinates of their previous and next unfitted contour neighbours.
+ * These are called `weak points' and are touched by the function
+ * `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
+ * hinting instruction. Typical candidates are control points and
+ * points on the contour without a major direction.
+ *
+ * The major effect is to reduce possible distortion caused by
+ * alignment of edges and strong points, thus weak points are processed
+ * after strong points.
+ */
+
+
/* point hint flags */
typedef enum AF_Flags_
{
@@ -137,9 +282,8 @@ FT_BEGIN_HEADER
FT_Pos score; /* used during stem matching */
FT_Pos len; /* used during stem matching */
- AF_Point first; /* first point in edge segment */
- AF_Point last; /* last point in edge segment */
- AF_Point* contour; /* ptr to first point of segment's contour */
+ AF_Point first; /* first point in edge segment */
+ AF_Point last; /* last point in edge segment */
} AF_SegmentRec;
@@ -155,32 +299,31 @@ FT_BEGIN_HEADER
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
- AF_Edge link;
- AF_Edge serif;
- FT_Short num_linked;
-
- FT_Int score;
+ AF_Edge link; /* link edge */
+ AF_Edge serif; /* primary edge for serifs */
+ FT_Short num_linked; /* number of linked edges */
+ FT_Int score; /* used during stem matching */
- AF_Segment first;
- AF_Segment last;
+ AF_Segment first; /* first segment in edge */
+ AF_Segment last; /* last segment in edge */
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
- FT_Int num_segments;
- FT_Int max_segments;
- AF_Segment segments;
+ FT_Int num_segments; /* number of used segments */
+ FT_Int max_segments; /* number of allocated segments */
+ AF_Segment segments; /* segments array */
#ifdef AF_SORT_SEGMENTS
FT_Int mid_segments;
#endif
- FT_Int num_edges;
- FT_Int max_edges;
- AF_Edge edges;
+ FT_Int num_edges; /* number of used edges */
+ FT_Int max_edges; /* number of allocated edges */
+ AF_Edge edges; /* edges array */
- AF_Direction major_dir;
+ AF_Direction major_dir; /* either vertical or horizontal */
} AF_AxisHintsRec, *AF_AxisHints;
@@ -195,15 +338,13 @@ FT_BEGIN_HEADER
FT_Fixed y_scale;
FT_Pos y_delta;
- FT_Pos edge_distance_threshold;
+ 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;
- FT_Int num_points;
- AF_Point points;
-
- FT_Int max_contours;
- FT_Int num_contours;
- AF_Point* contours;
+ 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];
@@ -214,7 +355,7 @@ FT_BEGIN_HEADER
FT_Pos xmin_delta; /* used for warping */
FT_Pos xmax_delta;
-
+
} AF_GlyphHintsRec;
@@ -222,7 +363,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#define AF_HINTS_DO_HORIZONTAL( h ) \
( !_af_debug_disable_horz_hints && \
@@ -237,7 +378,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
#define AF_HINTS_DO_HORIZONTAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
@@ -250,7 +391,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_BLUES( h ) 1
-#endif /* !AF_DEBUG */
+#endif /* !FT_DEBUG_AUTOFIT */
FT_LOCAL( AF_Direction )
@@ -274,12 +415,6 @@ FT_BEGIN_HEADER
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
-
-
- /*
- * recompute all AF_Point in a AF_GlyphHints from the definitions
- * in a source outline
- */
FT_LOCAL( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics );
@@ -304,7 +439,7 @@ FT_BEGIN_HEADER
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_LOCAL( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
AF_Dimension dim,
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 1d9e9ea..c232cff 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for Indic scripts (body). */
/* */
-/* Copyright 2007 by */
+/* Copyright 2007, 2011 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, */
@@ -27,23 +27,42 @@
#include "afcjk.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
static FT_Error
- af_indic_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ af_indic_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face )
{
- /* use CJK routines */
- return af_cjk_metrics_init( metrics, face );
+ /* skip blue zone init in CJK routines */
+ FT_CharMap oldmap = face->charmap;
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
+ face->charmap = NULL;
+ else
+ {
+ af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+#if 0
+ /* either need indic specific blue_chars[] or just skip blue zones */
+ af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
+#endif
+ af_cjk_metrics_check_digits( metrics, face );
+ }
+
+ FT_Set_Charmap( face, oldmap );
+
+ return AF_Err_Ok;
}
static void
- af_indic_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ af_indic_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler )
{
/* use CJK routines */
af_cjk_metrics_scale( metrics, scaler );
@@ -51,8 +70,8 @@
static FT_Error
- af_indic_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ af_indic_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_init( hints, metrics );
@@ -60,9 +79,9 @@
static FT_Error
- af_indic_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics)
+ af_indic_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_apply( hints, outline, metrics );
@@ -84,6 +103,12 @@
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)
};
@@ -92,7 +117,7 @@
AF_SCRIPT_INDIC,
af_indic_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) af_indic_metrics_init,
(AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
@@ -114,7 +139,7 @@
AF_SCRIPT_INDIC,
af_indic_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 8c6c430..54fcf7f 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for latin script (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,17 +18,28 @@
#include <ft2build.h>
#include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
#include "aflatin.h"
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/*************************************************************************/
+ /* */
+ /* 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_aflatin
+
+
+ /*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
@@ -36,6 +47,10 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Find segments and links, compute all stem widths, and initialize */
+ /* standard width and height for the glyph with given charcode. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_init_widths( AF_LatinMetrics metrics,
FT_Face face,
@@ -69,8 +84,12 @@
FT_ZERO( dummy );
dummy->units_per_em = metrics->units_per_em;
- scaler->x_scale = scaler->y_scale = 0x10000L;
- scaler->x_delta = scaler->y_delta = 0;
+
+ scaler->x_scale = 0x10000L;
+ scaler->y_scale = 0x10000L;
+ scaler->x_delta = 0;
+ scaler->y_delta = 0;
+
scaler->face = face;
scaler->render_mode = FT_RENDER_MODE_NORMAL;
scaler->flags = 0;
@@ -115,7 +134,7 @@
dist = -dist;
if ( num_widths < AF_LATIN_MAX_WIDTHS )
- axis->widths[ num_widths++ ].org = dist;
+ axis->widths[num_widths++].org = dist;
}
}
@@ -161,6 +180,9 @@
};
+ /* Find all blue zones. Flat segments give the reference points, */
+ /* round segments the overshoot positions. */
+
static void
af_latin_metrics_init_blues( AF_LatinMetrics metrics,
FT_Face face )
@@ -177,11 +199,11 @@
/* we compute the blues simply by loading each character from the */
- /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */
+ /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
/* bottom-most points (depending on `AF_IS_TOP_BLUE') */
- AF_LOG(( "blue zones computation\n" ));
- AF_LOG(( "------------------------------------------------\n" ));
+ FT_TRACE5(( "blue zones computation\n" ));
+ FT_TRACE5(( "------------------------------------------------\n" ));
for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
{
@@ -191,7 +213,7 @@
FT_Pos* blue_shoot;
- AF_LOG(( "blue %3d: ", bb ));
+ FT_TRACE5(( "blue %3d: ", bb ));
num_flats = 0;
num_rounds = 0;
@@ -199,13 +221,13 @@
for ( ; p < limit && *p; p++ )
{
FT_UInt glyph_index;
- FT_Pos best_y; /* same as points.y */
+ FT_Pos best_y; /* same as points.y */
FT_Int best_point, best_first, best_last;
FT_Vector* points;
FT_Bool round = 0;
- AF_LOG(( "'%c'", *p ));
+ FT_TRACE5(( "'%c'", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -229,7 +251,9 @@
FT_Int last = -1;
- for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+ for ( nn = 0;
+ nn < glyph->outline.n_contours;
+ first = last + 1, nn++ )
{
FT_Int old_best_point = best_point;
FT_Int pp;
@@ -241,7 +265,7 @@
/* In some fonts, they correspond to mark attachment points */
/* which are way outside of the glyph's real outline. */
if ( last <= first )
- continue;
+ continue;
if ( AF_LATIN_IS_TOP_BLUE( bb ) )
{
@@ -268,7 +292,7 @@
best_last = last;
}
}
- AF_LOG(( "%5d", best_y ));
+ FT_TRACE5(( "%5d", best_y ));
}
/* now check whether the point belongs to a straight or round */
@@ -311,12 +335,12 @@
} while ( next != best_point );
- /* now, set the `round' flag depending on the segment's kind */
+ /* now set the `round' flag depending on the segment's kind */
round = FT_BOOL(
FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
- AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
}
if ( round )
@@ -325,7 +349,7 @@
flats[num_flats++] = best_y;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -333,7 +357,7 @@
* we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then
*/
- AF_LOG(( "empty\n" ));
+ FT_TRACE5(( "empty\n" ));
continue;
}
@@ -343,9 +367,9 @@
af_sort_pos( num_rounds, rounds );
af_sort_pos( num_flats, flats );
- 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++;
@@ -376,7 +400,8 @@
if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
- *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ *blue_ref =
+ *blue_shoot = ( shoot + ref ) / 2;
}
blue->flags = 0;
@@ -391,13 +416,17 @@
if ( bb == AF_LATIN_BLUE_SMALL_TOP )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
- AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
}
+ FT_TRACE5(( "\n" ));
+
return;
}
+ /* Check whether all ASCII digits have the same advance width. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face )
@@ -407,8 +436,7 @@
FT_Fixed advance, old_advance = 0;
- /* check whether all ASCII digits have the same advance width; */
- /* digit `0' is 0x30 in all supported charmaps */
+ /* digit `0' is 0x30 in all supported charmaps */
for ( i = 0x30; i <= 0x39; i++ )
{
FT_UInt glyph_index;
@@ -444,6 +472,8 @@
}
+ /* Initialize global metrics. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face )
@@ -458,6 +488,7 @@
FT_ENCODING_APPLE_ROMAN,
FT_ENCODING_ADOBE_STANDARD,
FT_ENCODING_ADOBE_LATIN_1,
+
FT_ENCODING_NONE /* end of list */
};
@@ -485,6 +516,9 @@
}
+ /* Adjust scaling value, then scale and shift widths */
+ /* and blue zones (if applicable) for given dimension. */
+
static void
af_latin_metrics_scale_dim( AF_LatinMetrics metrics,
AF_Scaler scaler,
@@ -550,9 +584,7 @@
else
#endif
if ( dim == AF_DIMENSION_VERT )
- {
scale = FT_MulDiv( scale, fitted, scaled );
- }
}
}
}
@@ -571,7 +603,7 @@
metrics->root.scaler.y_delta = delta;
}
- /* scale the standard widths */
+ /* scale the widths */
for ( nn = 0; nn < axis->width_count; nn++ )
{
AF_Width width = axis->widths + nn;
@@ -582,7 +614,7 @@
}
/* an extra-light axis corresponds to a standard width that is */
- /* smaller than 0.75 pixels */
+ /* smaller than 5/8 pixels */
axis->extra_light =
(FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
@@ -605,9 +637,17 @@
dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
if ( dist <= 48 && dist >= -48 )
{
- FT_Pos delta1, delta2;
+#if 0
+ FT_Pos delta1;
+#endif
+ FT_Pos delta2;
+
+ /* use discrete values for blue zone widths */
+#if 0
+
+ /* generic, original code */
delta1 = blue->shoot.org - blue->ref.org;
delta2 = delta1;
if ( delta1 < 0 )
@@ -628,6 +668,28 @@
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
blue->shoot.fit = blue->ref.fit + delta2;
+#else
+
+ /* simplified version due to abs(dist) <= 48 */
+ delta2 = dist;
+ if ( dist < 0 )
+ delta2 = -delta2;
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta < 48 )
+ delta2 = 32;
+ else
+ delta2 = 64;
+
+ if ( dist < 0 )
+ delta2 = -delta2;
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+ blue->shoot.fit = blue->ref.fit - delta2;
+
+#endif
+
blue->flags |= AF_LATIN_BLUE_ACTIVE;
}
}
@@ -635,6 +697,8 @@
}
+ /* Scale global values in both directions. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler )
@@ -655,18 +719,21 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Walk over all contours and compute its segments. */
+
FT_LOCAL_DEF( FT_Error )
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 = AF_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_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = AF_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_ZERO( &seg0 );
@@ -762,7 +829,7 @@
/* a segment is round if either its first or last point */
/* is a control point */
if ( ( segment->first->flags | point->flags ) &
- AF_FLAG_CONTROL )
+ AF_FLAG_CONTROL )
segment->flags |= AF_EDGE_ROUND;
/* compute segment size */
@@ -808,7 +875,6 @@
min_pos = max_pos = point->u;
segment->first = point;
segment->last = point;
- segment->contour = contour;
on_edge = 1;
}
@@ -874,6 +940,8 @@
}
+ /* Link segments to form stems and serifs. */
+
FT_LOCAL_DEF( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
AF_Dimension dim )
@@ -899,51 +967,56 @@
if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
continue;
+ /* search for stems having opposite directions, */
+ /* with seg1 to the `left' of seg2 */
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
- if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
- {
- FT_Pos pos1 = seg1->pos;
- FT_Pos pos2 = seg2->pos;
- FT_Pos dist = pos2 - pos1;
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
- if ( dist < 0 )
- dist = -dist;
+ 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, score;
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
- if ( min < seg2->min_coord )
- min = seg2->min_coord;
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
- if ( max > seg2->max_coord )
- max = seg2->max_coord;
+ /* compute maximum coordinate difference of the two segments */
+ 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;
- len = max - min;
- if ( len >= len_threshold )
+ /* and we search for the smallest score */
+ /* of the sum of the two values */
+ if ( score < seg1->score )
{
- score = dist + len_score / len;
-
- if ( score < seg1->score )
- {
- seg1->score = score;
- seg1->link = seg2;
- }
+ seg1->score = score;
+ seg1->link = seg2;
+ }
- if ( score < seg2->score )
- {
- seg2->score = score;
- seg2->link = seg1;
- }
+ if ( score < seg2->score )
+ {
+ seg2->score = score;
+ seg2->link = seg1;
}
}
}
+ }
}
- /* now, compute the `serif' segments */
+ /* now compute the `serif' segments, cf. explanations in `afhints.h' */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
seg2 = seg1->link;
@@ -960,6 +1033,8 @@
}
+ /* Link segments to edges, using feature analysis for selection. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -973,7 +1048,9 @@
AF_Segment segment_limit = segments + axis->num_segments;
AF_Segment seg;
+#if 0
AF_Direction up_dir;
+#endif
FT_Fixed scale;
FT_Pos edge_distance_threshold;
FT_Pos segment_length_threshold;
@@ -984,11 +1061,13 @@
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
: hints->y_scale;
+#if 0
up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
: AF_DIR_RIGHT;
+#endif
/*
- * We ignore all segments that are less than 1 pixels in length,
+ * We ignore all segments that are less than 1 pixel in length
* to avoid many problems with serif fonts. We compute the
* corresponding threshold in font units.
*/
@@ -999,20 +1078,21 @@
/*********************************************************************/
/* */
- /* We will begin by generating a sorted table of edges for the */
- /* current direction. To do so, we simply scan each segment and try */
- /* to find an edge in our table that corresponds to its position. */
+ /* We begin by generating a sorted table of edges for the current */
+ /* direction. To do so, we simply scan each segment and try to find */
+ /* an edge in our table that corresponds to its position. */
/* */
/* If no edge is found, we create and insert a new edge in the */
/* sorted table. Otherwise, we simply add the segment to the edge's */
- /* list which will be processed in the second step to compute the */
+ /* list which gets processed in the second step to compute the */
/* edge's properties. */
/* */
- /* Note that the edges table is sorted along the segment/edge */
+ /* Note that the table of edges is sorted along the segment/edge */
/* position. */
/* */
/*********************************************************************/
+ /* assure that edge distance threshold is at most 0.25px */
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
scale );
if ( edge_distance_threshold > 64 / 4 )
@@ -1023,7 +1103,7 @@
for ( seg = segments; seg < segment_limit; seg++ )
{
- AF_Edge found = 0;
+ AF_Edge found = NULL;
FT_Int ee;
@@ -1072,9 +1152,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
@@ -1091,9 +1172,9 @@
/*********************************************************************/
/* */
/* Good, we will now compute each edge's properties according to */
- /* segments found on its position. Basically, these are: */
+ /* the segments found on its position. Basically, these are */
/* */
- /* - edge's main direction */
+ /* - 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 */
@@ -1126,13 +1207,15 @@
} while ( seg != edge->first );
}
- /* now, compute each edge properties */
+ /* now compute each edge properties */
for ( edge = edges; edge < edge_limit; edge++ )
{
FT_Int is_round = 0; /* does it contain round segments? */
FT_Int is_straight = 0; /* does it contain straight segments? */
+#if 0
FT_Pos ups = 0; /* number of upwards segments */
FT_Pos downs = 0; /* number of downwards segments */
+#endif
seg = edge->first;
@@ -1148,11 +1231,13 @@
else
is_straight++;
+#if 0
/* check for segment direction */
if ( seg->dir == up_dir )
- ups += seg->max_coord-seg->min_coord;
+ ups += seg->max_coord - seg->min_coord;
else
- downs += seg->max_coord-seg->min_coord;
+ downs += seg->max_coord - seg->min_coord;
+#endif
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
@@ -1228,7 +1313,7 @@
edge->dir = 0; /* both up and down! */
#endif
- /* gets rid of serifs if link is set */
+ /* get rid of serifs if link is set */
/* XXX: This gets rid of many unpleasant artefacts! */
/* Example: the `c' in cour.pfa at size 13 */
@@ -1242,6 +1327,8 @@
}
+ /* Detect segments and edges for given dimension. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1256,18 +1343,21 @@
error = af_latin_hints_compute_edges( hints, dim );
}
+
return error;
}
+ /* Compute all edges which lie within blue zones. */
+
FT_LOCAL_DEF( void )
af_latin_hints_compute_blue_edges( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
- AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
+ AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
AF_Edge edge = axis->edges;
AF_Edge edge_limit = edge + axis->num_edges;
- AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];
+ AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT];
FT_Fixed scale = latin->scale;
@@ -1283,8 +1373,10 @@
/* compute the initial threshold as a fraction of the EM size */
+ /* (the value 40 is heuristic) */
best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
+ /* assure a minimum distance of 0.5px */
if ( best_dist > 64 / 2 )
best_dist = 64 / 2;
@@ -1294,7 +1386,7 @@
FT_Bool is_top_blue, is_major_dir;
- /* skip inactive blue zones (i.e., those that are too small) */
+ /* skip inactive blue zones (i.e., those that are too large) */
if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
continue;
@@ -1322,12 +1414,13 @@
if ( dist < best_dist )
{
best_dist = dist;
- best_blue = & blue->ref;
+ best_blue = &blue->ref;
}
- /* now, compare it to the overshoot position if the edge is */
- /* rounded, and if the edge is over the reference position of a */
- /* top zone, or under the reference position of a bottom zone */
+ /* 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 )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
@@ -1335,7 +1428,6 @@
if ( is_top_blue ^ is_under_ref )
{
- blue = latin->blues + bb;
dist = edge->fpos - blue->shoot.org;
if ( dist < 0 )
dist = -dist;
@@ -1344,7 +1436,7 @@
if ( dist < best_dist )
{
best_dist = dist;
- best_blue = & blue->shoot;
+ best_blue = &blue->shoot;
}
}
}
@@ -1357,6 +1449,8 @@
}
+ /* Initalize hinting engine. */
+
static FT_Error
af_latin_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics )
@@ -1370,7 +1464,7 @@
/*
* correct x_scale and y_scale if needed, since they may have
- * been modified `af_latin_metrics_scale_dim' above
+ * been modified by `af_latin_metrics_scale_dim' above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -1380,7 +1474,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#if 0 /* #ifdef AF_USE_WARPER */
+#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;
@@ -1417,14 +1511,14 @@
* In `light' hinting mode we disable horizontal hinting completely.
* We also do it if the face is italic.
*/
- if ( mode == FT_RENDER_MODE_LIGHT ||
- (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
- return 0;
+ return AF_Err_Ok;
}
@@ -1436,8 +1530,8 @@
/*************************************************************************/
/*************************************************************************/
- /* 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_latin_snap_width( AF_Width widths,
@@ -1484,7 +1578,9 @@
}
- /* compute the snapped width of a given stem */
+ /* Compute the snapped width of a given stem, ignoring very thin ones. */
+ /* There is a lot of voodoo in this function; changing the hard-coded */
+ /* parameters influence the whole hinting process. */
static FT_Pos
af_latin_compute_stem_width( AF_GlyphHints hints,
@@ -1501,7 +1597,7 @@
if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
- axis->extra_light )
+ axis->extra_light )
return width;
if ( dist < 0 )
@@ -1516,11 +1612,12 @@
/* smooth hinting process: very lightly quantize the stem width */
/* leave the widths of serifs alone */
-
- if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+ if ( ( stem_flags & AF_EDGE_SERIF ) &&
+ vertical &&
+ ( dist < 3 * 64 ) )
goto Done_Width;
- else if ( ( base_flags & AF_EDGE_ROUND ) )
+ else if ( base_flags & AF_EDGE_ROUND )
{
if ( dist < 80 )
dist = 64;
@@ -1534,21 +1631,18 @@
/* compare to standard width */
- if ( axis->width_count > 0 )
- {
- delta = dist - axis->widths[0].cur;
+ delta = dist - axis->widths[0].cur;
- if ( delta < 0 )
- delta = -delta;
+ if ( delta < 0 )
+ delta = -delta;
- if ( delta < 40 )
- {
- dist = axis->widths[0].cur;
- if ( dist < 48 )
- dist = 48;
+ if ( delta < 40 )
+ {
+ dist = axis->widths[0].cur;
+ if ( dist < 48 )
+ dist = 48;
- goto Done_Width;
- }
+ goto Done_Width;
}
if ( dist < 3 * 64 )
@@ -1575,6 +1669,7 @@
else
{
/* strong hinting process: snap the stem width to integer pixels */
+
FT_Pos org_dist = dist;
@@ -1649,7 +1744,7 @@
}
- /* align one stem edge relative to the previous stem edge */
+ /* Align one stem edge relative to the previous stem edge. */
static void
af_latin_align_linked_edge( AF_GlyphHints hints,
@@ -1667,13 +1762,16 @@
stem_edge->pos = base_edge->pos + fitted_width;
- AF_LOG(( "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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ 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->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_latin_align_serif_edge( AF_GlyphHints hints,
AF_Edge base,
@@ -1681,7 +1779,7 @@
{
FT_UNUSED( hints );
- serif->pos = base->pos + (serif->opos - base->opos);
+ serif->pos = base->pos + ( serif->opos - base->opos );
}
@@ -1696,6 +1794,8 @@
/*************************************************************************/
+ /* The main grid-fitting routine. */
+
FT_LOCAL_DEF( void )
af_latin_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1705,10 +1805,13 @@
AF_Edge edge_limit = edges + axis->num_edges;
FT_PtrDist n_edges;
AF_Edge edge;
- AF_Edge anchor = 0;
+ AF_Edge anchor = NULL;
FT_Int has_serifs = 0;
+ FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
+ : "vertical"));
+
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
@@ -1717,7 +1820,7 @@
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Width blue;
- AF_Edge edge1, edge2;
+ AF_Edge edge1, edge2; /* these edges form the stem to check */
if ( edge->flags & AF_EDGE_DONE )
@@ -1728,9 +1831,9 @@
edge2 = edge->link;
if ( blue )
- {
edge1 = edge;
- }
+
+ /* flip edges if the other stem is aligned to a blue zone */
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;
@@ -1741,10 +1844,10 @@
if ( !edge1 )
continue;
- AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
- "was (%.2f)\n",
- edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
- edge1->pos / 64.0 ));
+ FT_TRACE5(( " BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
+ " was (%.2f)\n",
+ edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
@@ -1760,8 +1863,8 @@
}
}
- /* now we will align all stem edges, trying to maintain the */
- /* relative order of stems in the glyph */
+ /* now we align all other stem edges, trying to maintain the */
+ /* relative order of stems in the glyph */
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Edge edge2;
@@ -1783,7 +1886,7 @@
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
- AF_LOG(( "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;
@@ -1792,6 +1895,8 @@
if ( !anchor )
{
+ /* if we reach this if clause, no stem has been aligned yet */
+
FT_Pos org_len, org_center, cur_len;
FT_Pos cur_pos1, error1, error2, u_off, d_off;
@@ -1801,10 +1906,19 @@
hints, dim, org_len,
(AF_Edge_Flags)edge->flags,
(AF_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 */
+ /* the stem edges to suitable positions */
if ( cur_len <= 64 )
- u_off = d_off = 32;
+ {
+ /* width <= 1px */
+ u_off = 32;
+ d_off = 32;
+ }
else
{
+ /* 1px < width < 1.5px */
u_off = 38;
d_off = 26;
}
@@ -1812,7 +1926,6 @@
if ( cur_len < 96 )
{
org_center = edge->opos + ( org_len >> 1 );
-
cur_pos1 = FT_PIX_ROUND( org_center );
error1 = org_center - ( cur_pos1 - u_off );
@@ -1834,11 +1947,11 @@
else
edge->pos = FT_PIX_ROUND( edge->opos );
- AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
- "snapped to (%.2f) (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+ " snapped to (%.2f) (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
anchor = edge;
edge->flags |= AF_EDGE_DONE;
@@ -1856,12 +1969,18 @@
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 );
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
if ( edge2->flags & AF_EDGE_DONE )
+ {
+ FT_TRACE5(( " ADJUST: edge %d (pos=%.2f) moved to %.2f\n",
+ edge - edges, edge->pos / 64.0,
+ ( edge2->pos - cur_len ) / 64.0 ));
+
edge->pos = edge2->pos - cur_len;
+ }
else if ( cur_len < 96 )
{
@@ -1871,7 +1990,10 @@
cur_pos1 = FT_PIX_ROUND( org_center );
if (cur_len <= 64 )
- u_off = d_off = 32;
+ {
+ u_off = 32;
+ d_off = 32;
+ }
else
{
u_off = 38;
@@ -1894,11 +2016,11 @@
edge->pos = cur_pos1 - cur_len / 2;
edge2->pos = cur_pos1 + cur_len / 2;
- AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
}
else
{
@@ -1911,24 +2033,24 @@
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
- cur_pos1 = FT_PIX_ROUND( org_pos );
- delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
+ cur_pos1 = FT_PIX_ROUND( org_pos );
+ delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
if ( delta1 < 0 )
delta1 = -delta1;
- cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
- delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
+ cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
+ delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
if ( delta2 < 0 )
delta2 = -delta2;
edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
edge2->pos = edge->pos + cur_len;
- AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
}
edge->flags |= AF_EDGE_DONE;
@@ -1936,8 +2058,8 @@
if ( edge > edges && edge->pos < edge[-1].pos )
{
- AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
- edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ FT_TRACE5(( " BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
edge->pos = edge[-1].pos;
}
}
@@ -2031,18 +2153,19 @@
if ( delta < 64 + 16 )
{
af_latin_align_serif_edge( hints, edge->serif, edge );
- AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
- "aligned to (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->serif - edges, edge->serif->opos / 64.0,
- edge->pos / 64.0 ));
+ FT_TRACE5(( " SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+ " aligned to (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
}
else if ( !anchor )
{
- AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
+ FT_TRACE5(( " SERIF_ANCHOR: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
else
{
@@ -2067,18 +2190,21 @@
FT_MulDiv( edge->opos - before->opos,
after->pos - before->pos,
after->opos - before->opos );
- AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "
- "from %d (opos=%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->pos / 64.0, before - edges,
- before->opos / 64.0 ));
+
+ FT_TRACE5(( " SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+ " from %d (opos=%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge->pos / 64.0,
+ before - edges, before->opos / 64.0 ));
}
else
{
edge->pos = anchor->pos +
( ( edge->opos - anchor->opos + 16 ) & ~31 );
- AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+
+ FT_TRACE5(( " SERIF_LINK2: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge - edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
}
@@ -2093,9 +2219,13 @@
edge->pos = edge[1].pos;
}
}
+
+ FT_TRACE5(( "\n" ));
}
+ /* Apply the complete hinting algorithm to a latin glyph. */
+
static FT_Error
af_latin_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
@@ -2110,9 +2240,9 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
+ AF_HINTS_DO_HORIZONTAL( hints ) )
#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
#endif
@@ -2134,17 +2264,19 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
-#ifdef AF_USE_WARPER
- if ( ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
{
AF_WarperRec warper;
FT_Fixed scale;
FT_Pos delta;
- af_warper_compute( &warper, hints, dim, &scale, &delta );
- af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
continue;
}
#endif
@@ -2209,7 +2341,7 @@
};
- AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
+ AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
AF_SCRIPT_LATIN,
af_latin_uniranges,
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index 660b10c..c5c2d13 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for latin script (specification). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */
+/* Copyright 2003-2007, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -30,8 +30,8 @@ FT_BEGIN_HEADER
AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)
-/* constants are given with units_per_em == 2048 in mind */
-#define AF_LATIN_CONSTANT( metrics, c ) \
+ /* constants are given with units_per_em == 2048 in mind */
+#define AF_LATIN_CONSTANT( metrics, c ) \
( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
@@ -76,10 +76,10 @@ FT_BEGIN_HEADER
enum
{
- AF_LATIN_BLUE_ACTIVE = 1 << 0,
- AF_LATIN_BLUE_TOP = 1 << 1,
- AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
- /* optimization */
+ 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
};
@@ -98,14 +98,13 @@ FT_BEGIN_HEADER
FT_Fixed scale;
FT_Pos delta;
- FT_UInt width_count;
- AF_WidthRec widths[AF_LATIN_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_LATIN_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? */
/* ignored for horizontal metrics */
- FT_Bool control_overshoot;
FT_UInt blue_count;
AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index 6546475..23558b8 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* aflatin.c */
+/* aflatin2.c */
/* */
/* Auto-fitter hinting routines for latin script (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,13 +23,24 @@
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
+
+ /*************************************************************************/
+ /* */
+ /* 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_aflatin2
+
+
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_segments( AF_GlyphHints hints,
- AF_Dimension dim );
+ AF_Dimension dim );
FT_LOCAL_DEF( void )
af_latin2_hints_link_segments( AF_GlyphHints hints,
@@ -45,8 +56,8 @@
FT_LOCAL_DEF( void )
af_latin2_metrics_init_widths( AF_LatinMetrics metrics,
- FT_Face face,
- FT_ULong charcode )
+ FT_Face face,
+ FT_ULong charcode )
{
/* scan the array of segments in each direction */
AF_GlyphHintsRec hints[1];
@@ -156,7 +167,8 @@
#define AF_LATIN_MAX_TEST_CHARACTERS 12
- static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES][AF_LATIN_MAX_TEST_CHARACTERS+1] =
+ static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
+ [AF_LATIN_MAX_TEST_CHARACTERS+1] =
{
"THEZOCQS",
"HEZLOCUS",
@@ -169,7 +181,7 @@
static void
af_latin2_metrics_init_blues( AF_LatinMetrics metrics,
- FT_Face face )
+ FT_Face face )
{
FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
@@ -182,12 +194,12 @@
FT_GlyphSlot glyph = face->glyph;
- /* we compute the blues simply by loading each character from the */
+ /* we compute the blues simply by loading each character from the */
/* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
- /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
- AF_LOG(( "blue zones computation\n" ));
- AF_LOG(( "------------------------------------------------\n" ));
+ FT_TRACE5(( "blue zones computation\n" ));
+ FT_TRACE5(( "------------------------------------------------\n" ));
for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
{
@@ -197,7 +209,7 @@
FT_Pos* blue_shoot;
- AF_LOG(( "blue %3d: ", bb ));
+ FT_TRACE5(( "blue %3d: ", bb ));
num_flats = 0;
num_rounds = 0;
@@ -210,7 +222,7 @@
FT_Bool round;
- AF_LOG(( "'%c'", *p ));
+ FT_TRACE5(( "'%c'", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -273,7 +285,7 @@
best_last = last;
}
}
- AF_LOG(( "%5d", best_y ));
+ FT_TRACE5(( "%5d", best_y ));
}
/* now check whether the point belongs to a straight or round */
@@ -321,7 +333,7 @@
FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
- AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
}
if ( round )
@@ -330,7 +342,7 @@
flats[num_flats++] = best_y;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -338,7 +350,7 @@
* we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then
*/
- AF_LOG(( "empty\n" ));
+ FT_TRACE5(( "empty\n" ));
continue;
}
@@ -396,7 +408,7 @@
if ( bb == AF_LATIN_BLUE_SMALL_TOP )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
- AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
}
return;
@@ -451,7 +463,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ FT_Face face )
{
FT_Error error = AF_Err_Ok;
FT_CharMap oldmap = face->charmap;
@@ -492,8 +504,8 @@
static void
af_latin2_metrics_scale_dim( AF_LatinMetrics metrics,
- AF_Scaler scaler,
- AF_Dimension dim )
+ AF_Scaler scaler,
+ AF_Dimension dim )
{
FT_Fixed scale;
FT_Pos delta;
@@ -548,7 +560,10 @@
if ( scaled != fitted )
{
scale = FT_MulDiv( scale, fitted, scaled );
- AF_LOG(( "== scaled x-top = %.2g fitted = %.2g, scaling = %.4g\n", scaled/64.0, fitted/64.0, (fitted*1.0)/scaled ));
+ FT_TRACE5(( "== scaled x-top = %.2g"
+ " fitted = %.2g, scaling = %.4g\n",
+ scaled / 64.0, fitted / 64.0,
+ ( fitted * 1.0 ) / scaled ));
}
#endif
}
@@ -579,7 +594,7 @@
}
/* an extra-light axis corresponds to a standard width that is */
- /* smaller than 0.75 pixels */
+ /* smaller than 5/8 pixels */
axis->extra_light =
(FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
@@ -624,9 +639,11 @@
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
blue->shoot.fit = blue->ref.fit + delta2;
- AF_LOG(( ">> activating blue zone %d: ref.cur=%.2g ref.fit=%.2g shoot.cur=%.2g shoot.fit=%.2g\n",
- nn, blue->ref.cur/64.0, blue->ref.fit/64.0,
- blue->shoot.cur/64.0, blue->shoot.fit/64.0 ));
+ FT_TRACE5(( ">> activating blue zone %d:"
+ " ref.cur=%.2g ref.fit=%.2g"
+ " shoot.cur=%.2g shoot.fit=%.2g\n",
+ nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+ blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
blue->flags |= AF_LATIN_BLUE_ACTIVE;
}
@@ -637,7 +654,7 @@
FT_LOCAL_DEF( void )
af_latin2_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ AF_Scaler scaler )
{
metrics->root.scaler.render_mode = scaler->render_mode;
metrics->root.scaler.face = scaler->face;
@@ -659,7 +676,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_segments( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
FT_Memory memory = hints->memory;
@@ -779,7 +796,6 @@
segment->dir = first->out_dir;
segment->first = first;
segment->last = point;
- segment->contour = contour;
segment->pos = (FT_Short)(( min_u + max_u ) >> 1);
segment->min_coord = (FT_Short) min_v;
segment->max_coord = (FT_Short) max_v;
@@ -917,7 +933,7 @@
FT_LOCAL_DEF( void )
af_latin2_hints_link_segments( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
@@ -1017,7 +1033,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_edges( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
FT_Error error = AF_Err_Ok;
@@ -1137,7 +1153,8 @@
/* insert a new edge in the list and */
/* sort according to the position */
- error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
+ memory, &edge );
if ( error )
goto Exit;
@@ -1205,8 +1222,10 @@
{
FT_Int is_round = 0; /* does it contain round segments? */
FT_Int is_straight = 0; /* does it contain straight segments? */
+#if 0
FT_Pos ups = 0; /* number of upwards segments */
FT_Pos downs = 0; /* number of downwards segments */
+#endif
seg = edge->first;
@@ -1222,11 +1241,13 @@
else
is_straight++;
+#if 0
/* check for segment direction */
if ( seg->dir == up_dir )
ups += seg->max_coord-seg->min_coord;
else
downs += seg->max_coord-seg->min_coord;
+#endif
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
@@ -1318,7 +1339,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_detect_features( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
FT_Error error;
@@ -1336,7 +1357,7 @@
FT_LOCAL_DEF( void )
af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ AF_LatinMetrics metrics )
{
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
AF_Edge edge = axis->edges;
@@ -1442,7 +1463,7 @@
static FT_Error
af_latin2_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ AF_LatinMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
@@ -1463,7 +1484,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#if 0 /* #ifdef AF_USE_WARPER */
+#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;
@@ -1524,8 +1545,8 @@
static FT_Pos
af_latin2_snap_width( AF_Width widths,
- FT_Int count,
- FT_Pos width )
+ FT_Int count,
+ FT_Pos width )
{
int n;
FT_Pos best = 64 + 32 + 2;
@@ -1571,10 +1592,10 @@
static FT_Pos
af_latin2_compute_stem_width( AF_GlyphHints hints,
- AF_Dimension dim,
- FT_Pos width,
- AF_Edge_Flags base_flags,
- AF_Edge_Flags stem_flags )
+ AF_Dimension dim,
+ FT_Pos width,
+ AF_Edge_Flags base_flags,
+ AF_Edge_Flags stem_flags )
{
AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
AF_LatinAxis axis = & metrics->axis[dim];
@@ -1739,9 +1760,9 @@
static void
af_latin2_align_linked_edge( AF_GlyphHints hints,
- AF_Dimension dim,
- AF_Edge base_edge,
- AF_Edge stem_edge )
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
@@ -1753,17 +1774,17 @@
stem_edge->pos = base_edge->pos + fitted_width;
- AF_LOG(( "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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ 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->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
}
static void
af_latin2_align_serif_edge( AF_GlyphHints hints,
- AF_Edge base,
- AF_Edge serif )
+ AF_Edge base,
+ AF_Edge serif )
{
FT_UNUSED( hints );
@@ -1784,7 +1805,7 @@
FT_LOCAL_DEF( void )
af_latin2_hint_edges( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
@@ -1796,7 +1817,8 @@
- AF_LOG(( "==== hinting %s edges =====\n", dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+ FT_TRACE5(( "==== hinting %s edges =====\n",
+ dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
@@ -1830,10 +1852,10 @@
if ( !edge1 )
continue;
- AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
- "was (%.2f)\n",
- edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
- edge1->pos / 64.0 ));
+ FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
@@ -1878,7 +1900,7 @@
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
- AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+ FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
af_latin2_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
@@ -1929,11 +1951,11 @@
else
edge->pos = FT_PIX_ROUND( edge->opos );
- AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
- "snapped to (%.2f) (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+ " snapped to (%.2f) (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
anchor = edge;
edge->flags |= AF_EDGE_DONE;
@@ -1945,7 +1967,7 @@
anchor_drift = ( (anchor->pos - anchor->opos) +
(edge2->pos - edge2->opos)) >> 1;
- AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
+ FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
}
else
{
@@ -1965,12 +1987,13 @@
org_left = org_pos + ((org_len - cur_len) >> 1);
org_right = org_pos + ((org_len + cur_len) >> 1);
- AF_LOG(( "ALIGN: left=%.2f right=%.2f ", org_left/64.0, org_right/64.0 ));
+ FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
+ org_left / 64.0, org_right / 64.0 ));
cur_center = org_center;
if ( edge2->flags & AF_EDGE_DONE )
{
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
edge->pos = edge2->pos - cur_len;
}
else
@@ -1985,14 +2008,14 @@
/* note: don't even try to fit tiny stems */
if ( cur_len < 32 )
{
- AF_LOG(( "tiny stem\n" ));
+ FT_TRACE5(( "tiny stem\n" ));
goto AlignStem;
}
/* if the span is within a single pixel, don't touch it */
if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
{
- AF_LOG(( "single pixel stem\n" ));
+ FT_TRACE5(( "single pixel stem\n" ));
goto AlignStem;
}
@@ -2015,14 +2038,14 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispA=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta ));
org = frac_right;
fit = (org <= 32) ? 16 : 48;
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispB=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta ));
}
}
@@ -2032,7 +2055,7 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta ));
/* snapping the right edge to the grid */
org = org_right;
@@ -2040,7 +2063,7 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta ));
/* now find the best displacement */
{
@@ -2059,27 +2082,28 @@
cur_center = org_center + best_disp;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
}
AlignStem:
edge->pos = cur_center - (cur_len >> 1);
edge2->pos = edge->pos + cur_len;
- AF_LOG(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f), org_len = %.2f cur_len=%.2f\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0,
- org_len / 64.0, cur_len / 64.0 ));
+ FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f),"
+ " org_len=%.2f cur_len=%.2f\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0,
+ org_len / 64.0, cur_len / 64.0 ));
edge->flags |= AF_EDGE_DONE;
edge2->flags |= AF_EDGE_DONE;
if ( edge > edges && edge->pos < edge[-1].pos )
{
- AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
- edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
edge->pos = edge[-1].pos;
}
}
@@ -2179,16 +2203,17 @@
if ( delta < 64 + 16 )
{
af_latin2_align_serif_edge( hints, edge->serif, edge );
- AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
- "aligned to (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->serif - edges, edge->serif->opos / 64.0,
- edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+ " aligned to (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
}
else if ( !anchor )
{
- AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
}
@@ -2215,15 +2240,19 @@
FT_MulDiv( edge->opos - before->opos,
after->pos - before->pos,
after->opos - before->opos );
- AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));
+ FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+ " from %d (opos=%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0,
+ before - edges, before->opos / 64.0 ));
}
else
{
- edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);
+ edge->pos = anchor->pos +
+ ( ( edge->opos - anchor->opos + 16 ) & ~31 );
- AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
}
@@ -2243,8 +2272,8 @@
static FT_Error
af_latin2_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics )
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
@@ -2255,7 +2284,7 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
AF_HINTS_DO_HORIZONTAL( hints ) )
#else
@@ -2279,7 +2308,7 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
{
@@ -2321,7 +2350,7 @@
static const AF_Script_UniRangeRec af_latin2_uniranges[] =
{
- AF_UNIRANGE_REC( 32UL, 127UL ), /* XXX: TODO: Add new Unicode ranges here! */
+ AF_UNIRANGE_REC( 32UL, 127UL ), /* TODO: Add new Unicode ranges here! */
AF_UNIRANGE_REC( 160UL, 255UL ),
AF_UNIRANGE_REC( 0UL, 0UL )
};
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 6dd9f2a..966a0df 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 2003-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,8 @@
#include "aferrors.h"
+ /* Initialize glyph loader. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory )
@@ -29,13 +31,15 @@
FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory );
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
_af_debug_hints = &loader->hints;
#endif
return FT_GlyphLoader_New( memory, &loader->gloader );
}
+ /* Reset glyph loader and compute globals if necessary. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face )
@@ -64,6 +68,8 @@
}
+ /* Finalize glyph loader. */
+
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
@@ -72,7 +78,7 @@
loader->face = NULL;
loader->globals = NULL;
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
_af_debug_hints = NULL;
#endif
FT_GlyphLoader_Done( loader->gloader );
@@ -80,6 +86,10 @@
}
+ /* Load a single glyph component. This routine calls itself */
+ /* recursively, if necessary, and does the main work of */
+ /* `af_loader_load_glyph.' */
+
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
@@ -169,8 +179,8 @@
&gloader->current.outline,
metrics );
- /* we now need to hint the metrics according to the change in */
- /* width/positioning that occurred during the hinting process */
+ /* we now need to adjust the metrics according to the change in */
+ /* width/positioning that occurred during the hinting process */
if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
{
FT_Pos old_rsb, old_lsb, new_lsb;
@@ -265,7 +275,7 @@
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
- /* now, read each subglyph independently */
+ /* now read each subglyph independently */
for ( nn = 0; nn < num_subglyphs; nn++ )
{
FT_Vector pp1, pp2;
@@ -305,7 +315,7 @@
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
- /* now perform the transform required for this subglyph */
+ /* now perform the transformation required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE |
@@ -444,7 +454,7 @@
#endif
slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
- metrics->scaler.y_scale );
+ metrics->scaler.y_scale );
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
@@ -459,15 +469,13 @@
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
-#ifdef DEBUG_HINTER
- af_debug_hinter = hinter;
-#endif
-
Exit:
return error;
}
+ /* Load a glyph. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index fa67c10..3f91e1a 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (specification). */
/* */
-/* Copyright 2003, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 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 __AF_LOADER_H__
-#define __AF_LOADER_H__
+#ifndef __AFLOADER_H__
+#define __AFLOADER_H__
#include "afhints.h"
#include "afglobal.h"
@@ -67,7 +67,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __AF_LOADER_H__ */
+#endif /* __AFLOADER_H__ */
/* END */
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index ec2d707..20b6218 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006 by */
+/* Copyright 2003-2006, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,8 +20,7 @@
#include "afloader.h"
#include "afpic.h"
-#ifdef AF_DEBUG
- int _af_debug;
+#ifdef FT_DEBUG_AUTOFIT
int _af_debug_disable_horz_hints;
int _af_debug_disable_vert_hints;
int _af_debug_disable_blue_hints;
@@ -67,14 +66,15 @@
}
- FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,
+ FT_DEFINE_AUTOHINTER_SERVICE(
+ af_autofitter_service,
NULL,
NULL,
NULL,
- (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
- )
+ (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph )
- FT_DEFINE_MODULE(autofit_module_class,
+ FT_DEFINE_MODULE(
+ autofit_module_class,
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
@@ -87,8 +87,7 @@
(FT_Module_Constructor)af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
- (FT_Module_Requester) NULL
- )
+ (FT_Module_Requester) NULL )
/* END */
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 5b9aba6..3aefbc5 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, 2010 by */
+/* Copyright 2009, 2010, 2011 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,7 +24,8 @@
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from afmodule.c */
- void FT_Init_Class_af_autofitter_service( FT_Library, FT_AutoHinter_ServiceRec*);
+ void FT_Init_Class_af_autofitter_service( FT_Library,
+ FT_AutoHinter_ServiceRec* );
/* forward declaration of PIC init functions from script classes */
#include "aflatin.h"
@@ -34,10 +35,12 @@
#include "afindic.h"
void
- autofit_module_class_pic_free( FT_Library library )
+ autofit_module_class_pic_free( FT_Library library )
{
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
+ FT_PIC_Container* pic_container = &library->pic_container;
+ FT_Memory memory = library->memory;
+
+
if ( pic_container->autofit )
{
FT_FREE( pic_container->autofit );
@@ -62,28 +65,37 @@
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->autofit = container;
- /* initialize pointer table - this is how the module usually expects this data */
+ /* initialize pointer table - */
+ /* this is how the module usually expects this data */
for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
{
- container->af_script_classes[ss] = &container->af_script_classes_rec[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_CLASSES_COUNT - 1] = NULL;
/* add call to initialization function when you add new scripts */
ss = 0;
- FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]);
+ 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++]);
+ 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++]);
+ 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++] );
+
+ FT_Init_Class_af_autofitter_service(
+ library, &container->af_autofitter_service );
- FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service);
+/* Exit: */
-/*Exit:*/
- if(error)
- autofit_module_class_pic_free(library);
+ if ( error )
+ autofit_module_class_pic_free( library );
return error;
}
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 80e62d3..c1632e7 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 by */
+/* Copyright 2009, 2011 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -33,24 +33,29 @@ FT_BEGIN_HEADER
#include "aftypes.h"
-/* increase these when you add new scripts, and update autofit_module_class_pic_init */
+ /* increase these when you add new scripts, */
+ /* and update autofit_module_class_pic_init */
#ifdef FT_OPTION_AUTOFIT2
- #define AF_SCRIPT_CLASSES_COUNT 6
+#define AF_SCRIPT_CLASSES_COUNT 6
#else
- #define AF_SCRIPT_CLASSES_COUNT 5
+#define AF_SCRIPT_CLASSES_COUNT 5
#endif
-#define AF_SCRIPT_CLASSES_REC_COUNT (AF_SCRIPT_CLASSES_COUNT-1)
+#define AF_SCRIPT_CLASSES_REC_COUNT ( AF_SCRIPT_CLASSES_COUNT - 1 )
typedef struct AFModulePIC_
{
- AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
- AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
- FT_AutoHinter_ServiceRec af_autofitter_service;
+ AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
+ AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
+ FT_AutoHinter_ServiceRec af_autofitter_service;
+
} AFModulePIC;
-#define GET_PIC(lib) ((AFModulePIC*)((lib)->pic_container.autofit))
-#define AF_SCRIPT_CLASSES_GET (GET_PIC(FT_FACE_LIBRARY(globals->face))->af_script_classes)
-#define AF_AF_AUTOFITTER_SERVICE_GET (GET_PIC(library)->af_autofitter_service)
+#define GET_PIC( lib ) \
+ ( (AFModulePIC*)((lib)->pic_container.autofit) )
+#define AF_SCRIPT_CLASSES_GET \
+ ( GET_PIC( FT_FACE_LIBRARY(globals->face) )->af_script_classes )
+#define AF_AF_AUTOFITTER_SERVICE_GET \
+ ( GET_PIC( library )->af_autofitter_service )
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 5574f0c..44997d1 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter types (specification only). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 2003-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -53,26 +53,16 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
-#define xxAF_USE_WARPER /* only define to use warp hinting */
-#define xxAF_DEBUG
-
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
-#define AF_LOG( x ) do { if ( _af_debug ) printf x; } while ( 0 )
-
-extern int _af_debug;
extern int _af_debug_disable_horz_hints;
extern int _af_debug_disable_vert_hints;
extern int _af_debug_disable_blue_hints;
extern void* _af_debug_hints;
-#else /* !AF_DEBUG */
-
-#define AF_LOG( x ) do { } while ( 0 ) /* nothing */
-
-#endif /* !AF_DEBUG */
+#endif /* FT_DEBUG_AUTOFIT */
/*************************************************************************/
@@ -159,36 +149,11 @@ extern void* _af_debug_hints;
FT_END_STMNT
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** O U T L I N E S *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
/* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
- /* This structure is used to model an input glyph outline to
- * the auto-hinter. The latter will set the `hints' field
- * depending on the glyph's script.
- */
- typedef struct AF_OutlineRec_
- {
- FT_Face face;
- FT_Outline outline;
- FT_UInt outline_resolution;
-
- FT_Int advance;
- FT_UInt metrics_resolution;
-
- AF_GlyphHints hints;
-
- } AF_OutlineRec;
-
/*************************************************************************/
/*************************************************************************/
@@ -241,7 +206,7 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * The list of know scripts. Each different script corresponds to the
+ * The list of known scripts. Each different script corresponds to the
* following information:
*
* - A set of Unicode ranges to test whether the face supports the
@@ -342,55 +307,57 @@ extern void* _af_debug_hints;
} AF_ScriptClassRec;
-/* Declare and define vtables for classes */
+
+ /* Declare and define vtables for classes */
#ifndef FT_CONFIG_OPTION_PIC
-#define AF_DECLARE_SCRIPT_CLASS(script_class) \
- FT_CALLBACK_TABLE const AF_ScriptClassRec \
+#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
+ FT_CALLBACK_TABLE const AF_ScriptClassRec \
script_class;
-#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \
- m_init, m_scale, m_done, h_init, h_apply) \
- FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \
- script_class = \
- { \
- script_, \
- ranges, \
- \
- m_size, \
- \
- m_init, \
- m_scale, \
- m_done, \
- \
- h_init, \
- h_apply \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size, \
+ m_init, m_scale, m_done, h_init, h_apply ) \
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \
+ script_class = \
+ { \
+ script_, \
+ ranges, \
+ \
+ m_size, \
+ \
+ m_init, \
+ m_scale, \
+ m_done, \
+ \
+ h_init, \
+ h_apply \
};
-#else
-
-#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, 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->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; \
+#else /* FT_CONFIG_OPTION_PIC */
+
+#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, 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->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; \
}
-#endif
+
+#endif /* FT_CONFIG_OPTION_PIC */
/* */
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
index f5bb9b1..d0d4850 100644
--- a/src/autofit/afwarp.c
+++ b/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (body). */
/* */
-/* Copyright 2006, 2007 by */
+/* Copyright 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,10 +16,30 @@
/***************************************************************************/
+ /*
+ * The idea of the warping code is to slightly scale and shift a glyph
+ * within a single dimension so that as much of its segments are aligned
+ * (more or less) on the grid. To find out the optimal scaling and
+ * shifting value, various parameter combinations are tried and scored.
+ */
+
#include "afwarp.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /*************************************************************************/
+ /* */
+ /* 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_afwarp
+
+ /* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */
+ /* values around a half pixel (which means exactly between two grid */
+ /* lines) gets the worst weight. */
#if 1
static const AF_WarpScore
af_warper_weights[64] =
@@ -43,6 +63,11 @@
#endif
+ /* Score segments for a given `scale' and `delta' in the range */
+ /* `xx1' to `xx2', and store the best result in `warper'. If */
+ /* the new best score is equal to the old one, prefer the */
+ /* value with a smaller distortion (around `base_distort'). */
+
static void
af_warper_compute_line_best( AF_Warper warper,
FT_Fixed scale,
@@ -82,12 +107,12 @@
if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
{
- AF_LOG(( "invalid indices:\n"
- " min=%d max=%d, xx1=%ld xx2=%ld,\n"
- " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
- idx_min, idx_max, xx1, xx2,
- warper->x1min, warper->x1max,
- warper->x2min, warper->x2max ));
+ FT_TRACE5(( "invalid indices:\n"
+ " min=%d max=%d, xx1=%ld xx2=%ld,\n"
+ " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
+ idx_min, idx_max, xx1, xx2,
+ warper->x1min, warper->x1max,
+ warper->x2min, warper->x2max ));
return;
}
}
@@ -100,6 +125,7 @@
FT_Int idx;
+ /* score the length of the segments for the given range */
for ( idx = idx_min; idx <= idx_max; idx++, y++ )
scores[idx] += af_warper_weights[y & 63] * len;
}
@@ -115,9 +141,9 @@
AF_WarpScore distort = base_distort + ( idx - idx0 );
- if ( score > warper->best_score ||
+ if ( score > warper->best_score ||
( score == warper->best_score &&
- distort < warper->best_distort ) )
+ distort < warper->best_distort ) )
{
warper->best_score = score;
warper->best_distort = distort;
@@ -129,6 +155,9 @@
}
+ /* Compute optimal scaling and delta values for a given glyph and */
+ /* dimension. */
+
FT_LOCAL_DEF( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
@@ -215,6 +244,7 @@
warper->t1 = AF_WARPER_FLOOR( warper->x1 );
warper->t2 = AF_WARPER_CEIL( warper->x2 );
+ /* examine a half pixel wide range around the maximum coordinates */
warper->x1min = warper->x1 & ~31;
warper->x1max = warper->x1min + 32;
warper->x2min = warper->x2 & ~31;
@@ -234,10 +264,12 @@
warper->x2min = warper->x2;
}
+ /* examine (at most) a pixel wide range around the natural width */
warper->wmin = warper->x2min - warper->x1max;
warper->wmax = warper->x2max - warper->x1min;
#if 1
+ /* some heuristics to reduce the number of widths to be examined */
{
int margin = 16;
@@ -273,6 +305,8 @@
FT_Pos xx1, xx2;
+ /* compute min and max positions for given width, */
+ /* assuring that they stay within the coordinate ranges */
xx1 = warper->x1;
xx2 = warper->x2;
if ( w >= warper->w0 )
@@ -304,6 +338,7 @@
else
base_distort += xx2 - warper->x2;
+ /* give base distortion a greater weight while scoring */
base_distort *= 10;
new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
@@ -329,10 +364,11 @@
}
}
-#else /* !AF_USE_WARPER */
+#else /* !AF_CONFIG_OPTION_USE_WARPER */
-char af_warper_dummy = 0; /* make compiler happy */
+ /* ANSI C doesn't like empty source files */
+ typedef int _af_warp_dummy;
-#endif /* !AF_USE_WARPER */
+#endif /* !AF_CONFIG_OPTION_USE_WARPER */
/* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index 83b613e..3883a0a 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* Copyright 2003-2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -34,7 +34,7 @@
#include "afloader.c"
#include "afmodule.c"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.c"
#endif
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index 1dc49f3..6375613 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -49,6 +49,17 @@ FT_BEGIN_HEADER
FT_Face *aface );
+#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
+ /* Mac OS X/Darwin kernel often changes recommended method to access */
+ /* the resource fork and older methods makes the kernel issue the */
+ /* warning of deprecated method. To calm it down, the methods based */
+ /* on Darwin VFS should be grouped and skip the rest methods after */
+ /* the case the resource is opened but found to lack a font in it. */
+ FT_LOCAL( FT_Bool )
+ raccess_rule_by_darwin_vfs( FT_UInt rule_index );
+#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
+
+
FT_END_HEADER
#endif /* __FTBASE_H__ */
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 46fcce6..22ec337 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -105,7 +105,7 @@
int new_pitch;
FT_UInt bpp;
FT_Int i, width, height;
- unsigned char* buffer;
+ unsigned char* buffer = NULL;
width = bitmap->width;
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 160269d..12fed04 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -47,7 +47,7 @@
typedef struct FT_MemTableRec_* FT_MemTable;
-#define FT_MEM_VAL( addr ) ((FT_ULong)(FT_Pointer)( addr ))
+#define FT_MEM_VAL( addr ) ((FT_PtrDist)(FT_Pointer)( addr ))
/*
* This structure holds statistics for a single allocation/release
@@ -275,7 +275,7 @@
for ( i = 0; i < table->size; i++ )
{
FT_MemNode node, next, *pnode;
- FT_ULong hash;
+ FT_PtrDist hash;
node = table->buckets[i];
@@ -430,7 +430,7 @@
ft_mem_table_get_nodep( FT_MemTable table,
FT_Byte* address )
{
- FT_ULong hash;
+ FT_PtrDist hash;
FT_MemNode *pnode, node;
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 7f38df0..5069afb 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,8 +4,7 @@
/* */
/* The FreeType private base classes (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -131,7 +130,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stream stream;
+ FT_Stream stream = NULL;
*astream = 0;
@@ -156,6 +155,9 @@
(const FT_Byte*)args->memory_base,
args->memory_size );
}
+
+#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
+
else if ( args->flags & FT_OPEN_PATHNAME )
{
/* create a normal system stream */
@@ -171,6 +173,9 @@
FT_FREE( stream );
stream = args->stream;
}
+
+#endif
+
else
error = FT_Err_Invalid_Argument;
@@ -375,7 +380,7 @@
FT_Driver driver;
FT_Driver_Class clazz;
FT_Memory memory;
- FT_GlyphSlot slot;
+ FT_GlyphSlot slot = NULL;
if ( !face || !face->driver )
@@ -561,6 +566,7 @@
FT_Library library;
FT_Bool autohint = FALSE;
FT_Module hinter;
+ TT_Face ttface = (TT_Face)face;
if ( !face || !face->size || !face->glyph )
@@ -601,7 +607,8 @@
* - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
* have a native font hinter.
*
- * - Otherwise, auto-hint for LIGHT hinting mode.
+ * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
+ * any hinting bytecode in the TrueType/OpenType font.
*
* - Exception: The font is `tricky' and requires the native hinter to
* load properly.
@@ -626,8 +633,13 @@
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
- if ( mode == FT_RENDER_MODE_LIGHT ||
- face->internal->ignore_unpatented_hinter )
+ /* 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 ||
+ face->internal->ignore_unpatented_hinter ||
+ ( FT_IS_SFNT( face ) &&
+ ttface->num_locations &&
+ ttface->max_profile.maxSizeOfInstructions == 0 ) )
autohint = TRUE;
}
}
@@ -1062,6 +1074,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 )
{
@@ -1071,6 +1084,7 @@
}
#endif
return cur[0];
+ }
}
return NULL;
@@ -1281,7 +1295,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stream stream;
+ FT_Stream stream = NULL;
if ( !library )
@@ -1456,7 +1470,7 @@
FT_ULong offset, length;
FT_Long pos;
FT_Bool is_sfnt_cid;
- FT_Byte* sfnt_ps;
+ FT_Byte* sfnt_ps = NULL;
FT_UNUSED( num_params );
FT_UNUSED( params );
@@ -1523,7 +1537,7 @@
{
FT_Error error = FT_Err_Cannot_Open_Resource;
FT_Memory memory = library->memory;
- FT_Byte* pfb_data;
+ FT_Byte* pfb_data = NULL;
int i, type, flags;
FT_Long len;
FT_Long pfb_len, pfb_pos, pfb_lenpos;
@@ -1665,7 +1679,7 @@
FT_Face *aface )
{
FT_Memory memory = library->memory;
- FT_Byte* sfnt_data;
+ FT_Byte* sfnt_data = NULL;
FT_Error error;
FT_Long flag_offset;
FT_Long rlen;
@@ -1849,6 +1863,7 @@
char * file_names[FT_RACCESS_N_RULES];
FT_Long offsets[FT_RACCESS_N_RULES];
FT_Error errors[FT_RACCESS_N_RULES];
+ FT_Bool is_darwin_vfs, vfs_rfork_has_no_font = FALSE; /* not tested */
FT_Open_Args args2;
FT_Stream stream2 = 0;
@@ -1859,6 +1874,15 @@
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
+ is_darwin_vfs = raccess_rule_by_darwin_vfs( i );
+ if ( is_darwin_vfs && vfs_rfork_has_no_font )
+ {
+ FT_TRACE3(( "Skip rule %d: darwin vfs resource fork"
+ " is already checked and"
+ " no font is found\n", i ));
+ continue;
+ }
+
if ( errors[i] )
{
FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i ));
@@ -1872,6 +1896,9 @@
i, args2.pathname, offsets[i] ));
error = FT_Stream_New( library, &args2, &stream2 );
+ if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )
+ vfs_rfork_has_no_font = TRUE;
+
if ( error )
{
FT_TRACE3(( "failed\n" ));
@@ -1886,6 +1913,8 @@
if ( !error )
break;
+ else if ( is_darwin_vfs )
+ vfs_rfork_has_no_font = TRUE;
}
for (i = 0; i < FT_RACCESS_N_RULES; i++)
@@ -3131,7 +3160,7 @@
FT_Error error = FT_Err_Ok;
FT_Face face;
FT_Memory memory;
- FT_CMap cmap;
+ FT_CMap cmap = NULL;
if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
@@ -3870,6 +3899,7 @@
error = set_mode( renderer, parameters->tag, parameters->data );
if ( error )
break;
+ parameters++;
}
}
@@ -4133,7 +4163,7 @@
FT_Renderer renderer = FT_RENDERER( module );
- if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
+ if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
renderer->raster )
renderer->clazz->raster_class->raster_done( renderer->raster );
}
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
index 501cab5..82b42f0 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -269,7 +269,7 @@
#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
- !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER )
+ !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER )
if ( face && FT_IS_SFNT( face ) )
{
result = !face->internal->ignore_unpatented_hinter;
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index f64d28b..4e7d510 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -159,8 +159,8 @@
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
- FT_Long *offsets_internal;
- FT_RFork_Ref *ref;
+ FT_Long *offsets_internal = NULL;
+ FT_RFork_Ref *ref = NULL;
error = FT_Stream_Seek( stream, map_offset );
@@ -349,6 +349,42 @@
const char *insertion );
+ typedef enum FT_RFork_Rule_ {
+ FT_RFork_Rule_invalid = -2,
+ FT_RFork_Rule_uknown, /* -1 */
+ FT_RFork_Rule_apple_double,
+ FT_RFork_Rule_apple_single,
+ FT_RFork_Rule_darwin_ufs_export,
+ FT_RFork_Rule_darwin_newvfs,
+ FT_RFork_Rule_darwin_hfsplus,
+ FT_RFork_Rule_vfat,
+ FT_RFork_Rule_linux_cap,
+ FT_RFork_Rule_linux_double,
+ FT_RFork_Rule_linux_netatalk
+ } FT_RFork_Rule;
+
+ /* For fast translation between rule index and rule type,
+ * the macros FT_RFORK_xxx should be kept consistent with
+ * the raccess_guess_funcs table
+ */
+ typedef struct raccess_guess_rec_ {
+ raccess_guess_func func;
+ FT_RFork_Rule type;
+ } raccess_guess_rec;
+
+ static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] =
+ {
+ { raccess_guess_apple_double, FT_RFork_Rule_apple_double, },
+ { raccess_guess_apple_single, FT_RFork_Rule_apple_single, },
+ { raccess_guess_darwin_ufs_export, FT_RFork_Rule_darwin_ufs_export, },
+ { raccess_guess_darwin_newvfs, FT_RFork_Rule_darwin_newvfs, },
+ { raccess_guess_darwin_hfsplus, FT_RFork_Rule_darwin_hfsplus, },
+ { raccess_guess_vfat, FT_RFork_Rule_vfat, },
+ { raccess_guess_linux_cap, FT_RFork_Rule_linux_cap, },
+ { raccess_guess_linux_double, FT_RFork_Rule_linux_double, },
+ { raccess_guess_linux_netatalk, FT_RFork_Rule_linux_netatalk, },
+ };
+
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
@@ -360,19 +396,6 @@
FT_Long i;
- raccess_guess_func funcs[FT_RACCESS_N_RULES] =
- {
- raccess_guess_apple_double,
- raccess_guess_apple_single,
- raccess_guess_darwin_ufs_export,
- raccess_guess_darwin_newvfs,
- raccess_guess_darwin_hfsplus,
- raccess_guess_vfat,
- raccess_guess_linux_cap,
- raccess_guess_linux_double,
- raccess_guess_linux_netatalk,
- };
-
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
@@ -384,14 +407,41 @@
if ( errors[i] )
continue ;
- errors[i] = (funcs[i])( library, stream, base_name,
- &(new_names[i]), &(offsets[i]) );
+ errors[i] = (raccess_guess_table[i].func)( library,
+ stream, base_name,
+ &(new_names[i]),
+ &(offsets[i]) );
}
return;
}
+ static FT_RFork_Rule
+ raccess_get_rule_type_from_rule_index( FT_UInt rule_index )
+ {
+ if ( rule_index >= FT_RACCESS_N_RULES )
+ return FT_RFork_Rule_invalid;
+
+ return raccess_guess_table[rule_index].type;
+ }
+
+
+ FT_LOCAL_DEF( FT_Bool )
+ raccess_rule_by_darwin_vfs( FT_UInt rule_index )
+ {
+ switch( raccess_get_rule_type_from_rule_index( rule_index ) )
+ {
+ case FT_RFork_Rule_darwin_newvfs:
+ case FT_RFork_Rule_darwin_hfsplus:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+
+
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
@@ -477,7 +527,7 @@
Only meaningful on systems with hfs+ drivers (or Macs).
*/
FT_Error error;
- char* newpath;
+ char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
@@ -513,7 +563,7 @@
Only meaningful on systems with Mac OS X (> 10.1).
*/
FT_Error error;
- char* newpath;
+ char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index 210aaa4..fc2868e 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
/* */
/* I/O stream support (body). */
/* */
-/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 by */
+/* Copyright 2000-2002, 2004-2006, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -354,8 +354,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_GetShort( FT_Stream stream )
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_GetUShort( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
@@ -366,15 +366,15 @@
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
- result = FT_NEXT_SHORT( p );
+ result = FT_NEXT_USHORT( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_GetShortLE( FT_Stream stream )
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_GetUShortLE( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
@@ -385,15 +385,15 @@
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
- result = FT_NEXT_SHORT_LE( p );
+ result = FT_NEXT_USHORT_LE( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetOffset( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetUOffset( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -404,14 +404,14 @@
result = 0;
p = stream->cursor;
if ( p + 2 < stream->limit )
- result = FT_NEXT_OFF3( p );
+ result = FT_NEXT_UOFF3( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetLong( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetULong( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -422,14 +422,14 @@
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
- result = FT_NEXT_LONG( p );
+ result = FT_NEXT_ULONG( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetLongLE( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetULongLE( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -440,7 +440,7 @@
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
- result = FT_NEXT_LONG_LE( p );
+ result = FT_NEXT_ULONG_LE( p );
stream->cursor = p;
return result;
}
@@ -483,8 +483,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_ReadShort( FT_Stream stream,
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_ReadUShort( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
@@ -511,7 +511,7 @@
}
if ( p )
- result = FT_NEXT_SHORT( p );
+ result = FT_NEXT_USHORT( p );
}
else
goto Fail;
@@ -522,7 +522,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadShort:"
+ FT_ERROR(( "FT_Stream_ReadUShort:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -530,8 +530,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_ReadShortLE( FT_Stream stream,
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_ReadUShortLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
@@ -558,7 +558,7 @@
}
if ( p )
- result = FT_NEXT_SHORT_LE( p );
+ result = FT_NEXT_USHORT_LE( p );
}
else
goto Fail;
@@ -569,7 +569,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadShortLE:"
+ FT_ERROR(( "FT_Stream_ReadUShortLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -577,8 +577,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadOffset( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadUOffset( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[3];
@@ -605,7 +605,7 @@
}
if ( p )
- result = FT_NEXT_OFF3( p );
+ result = FT_NEXT_UOFF3( p );
}
else
goto Fail;
@@ -616,7 +616,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadOffset:"
+ FT_ERROR(( "FT_Stream_ReadUOffset:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -624,8 +624,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadLong( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadULong( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
@@ -652,7 +652,7 @@
}
if ( p )
- result = FT_NEXT_LONG( p );
+ result = FT_NEXT_ULONG( p );
}
else
goto Fail;
@@ -663,7 +663,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadLong:"
+ FT_ERROR(( "FT_Stream_ReadULong:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -671,8 +671,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadLongLE( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadULongLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
@@ -699,7 +699,7 @@
}
if ( p )
- result = FT_NEXT_LONG_LE( p );
+ result = FT_NEXT_ULONG_LE( p );
}
else
goto Fail;
@@ -710,7 +710,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadLongLE:"
+ FT_ERROR(( "FT_Stream_ReadULongLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index 75bcbde..3f24f9e 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (body). */
/* */
-/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by */
+/* Copyright 2002-2006, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -34,7 +34,7 @@
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
- : FT_STROKER_BORDER_LEFT ;
+ : FT_STROKER_BORDER_LEFT;
}
@@ -47,20 +47,21 @@
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
- : FT_STROKER_BORDER_RIGHT ;
+ : FT_STROKER_BORDER_RIGHT;
}
- /***************************************************************************/
- /***************************************************************************/
- /***** *****/
- /***** BEZIER COMPUTATIONS *****/
- /***** *****/
- /***************************************************************************/
- /***************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BEZIER COMPUTATIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )
-#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 6 )
+#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 )
+
#define FT_EPSILON 2
#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
@@ -69,7 +70,7 @@
static FT_Pos
ft_pos_abs( FT_Pos x )
{
- return x >= 0 ? x : -x ;
+ return x >= 0 ? x : -x;
}
@@ -114,18 +115,28 @@
if ( close1 )
{
if ( close2 )
- *angle_in = *angle_out = 0;
+ {
+ /* basically a point; */
+ /* do nothing to retain original direction */
+ }
else
- *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );
- }
- else if ( close2 )
- {
- *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );
+ {
+ *angle_in =
+ *angle_out = FT_Atan2( d2.x, d2.y );
+ }
}
- else
+ else /* !close1 */
{
- *angle_in = FT_Atan2( d1.x, d1.y );
- *angle_out = FT_Atan2( d2.x, d2.y );
+ if ( close2 )
+ {
+ *angle_in =
+ *angle_out = FT_Atan2( d1.x, d1.y );
+ }
+ else
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_out = FT_Atan2( d2.x, d2.y );
+ }
}
theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
@@ -162,6 +173,17 @@
}
+ /* Return the average of `angle1' and `angle2'. */
+ /* This gives correct result even if `angle1' and `angle2' */
+ /* have opposite signs. */
+ static FT_Angle
+ ft_angle_mean( FT_Angle angle1,
+ FT_Angle angle2 )
+ {
+ return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2;
+ }
+
+
static FT_Bool
ft_cubic_is_small_enough( FT_Vector* base,
FT_Angle *angle_in,
@@ -184,34 +206,70 @@
close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
- if ( close1 || close3 )
+ if ( close1 )
{
if ( close2 )
{
- /* basically a point */
- *angle_in = *angle_out = *angle_mid = 0;
- }
- else if ( close1 )
- {
- *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y );
- *angle_out = FT_Atan2( d3.x, d3.y );
+ if ( close3 )
+ {
+ /* basically a point; */
+ /* do nothing to retain original direction */
+ }
+ else /* !close3 */
+ {
+ *angle_in =
+ *angle_mid =
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
}
- else /* close2 */
+ else /* !close2 */
{
- *angle_in = FT_Atan2( d1.x, d1.y );
- *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );
+ if ( close3 )
+ {
+ *angle_in =
+ *angle_mid =
+ *angle_out = FT_Atan2( d2.x, d2.y );
+ }
+ else /* !close3 */
+ {
+ *angle_in =
+ *angle_mid = FT_Atan2( d2.x, d2.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
}
}
- else if ( close2 )
- {
- *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y );
- *angle_out = FT_Atan2( d3.x, d3.y );
- }
- else
+ else /* !close1 */
{
- *angle_in = FT_Atan2( d1.x, d1.y );
- *angle_mid = FT_Atan2( d2.x, d2.y );
- *angle_out = FT_Atan2( d3.x, d3.y );
+ if ( close2 )
+ {
+ if ( close3 )
+ {
+ *angle_in =
+ *angle_mid =
+ *angle_out = FT_Atan2( d1.x, d1.y );
+ }
+ else /* !close3 */
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ *angle_mid = ft_angle_mean( *angle_in, *angle_out );
+ }
+ }
+ else /* !close2 */
+ {
+ if ( close3 )
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_mid =
+ *angle_out = FT_Atan2( d2.x, d2.y );
+ }
+ else /* !close3 */
+ {
+ *angle_in = FT_Atan2( d1.x, d1.y );
+ *angle_mid = FT_Atan2( d2.x, d2.y );
+ *angle_out = FT_Atan2( d3.x, d3.y );
+ }
+ }
}
theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) );
@@ -222,13 +280,13 @@
}
- /***************************************************************************/
- /***************************************************************************/
- /***** *****/
- /***** STROKE BORDERS *****/
- /***** *****/
- /***************************************************************************/
- /***************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STROKE BORDERS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
typedef enum FT_StrokeTags_
{
@@ -239,7 +297,7 @@
} FT_StrokeTags;
-#define FT_STROKE_TAG_BEGIN_END (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END)
+#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
typedef struct FT_StrokeBorderRec_
{
@@ -247,7 +305,7 @@
FT_UInt max_points;
FT_Vector* points;
FT_Byte* tags;
- FT_Bool movable;
+ FT_Bool movable; /* TRUE for ends of lineto borders */
FT_Int start; /* index of current sub-path start point */
FT_Memory memory;
FT_Bool valid;
@@ -368,6 +426,12 @@
}
else
{
+ /* don't add zero-length lineto */
+ if ( border->num_points > 0 &&
+ FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
+ FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
+ return error;
+
/* add one point */
error = ft_stroke_border_grow( border, 1 );
if ( !error )
@@ -403,6 +467,7 @@
FT_Vector* vec = border->points + border->num_points;
FT_Byte* tag = border->tags + border->num_points;
+
vec[0] = *control;
vec[1] = *to;
@@ -411,7 +476,9 @@
border->num_points += 2;
}
+
border->movable = FALSE;
+
return error;
}
@@ -444,7 +511,9 @@
border->num_points += 3;
}
+
border->movable = FALSE;
+
return error;
}
@@ -530,7 +599,7 @@
if ( border->start >= 0 )
ft_stroke_border_close( border, FALSE );
- border->start = border->num_points;
+ border->start = border->num_points;
border->movable = FALSE;
return ft_stroke_border_lineto( border, to, FALSE );
@@ -673,38 +742,41 @@
}
}
- outline->n_points = (short)( outline->n_points + border->num_points );
+ outline->n_points = (short)( outline->n_points + border->num_points );
FT_ASSERT( FT_Outline_Check( outline ) == 0 );
}
- /***************************************************************************/
- /***************************************************************************/
- /***** *****/
- /***** STROKER *****/
- /***** *****/
- /***************************************************************************/
- /***************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** STROKER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
typedef struct FT_StrokerRec_
{
- FT_Angle angle_in;
- FT_Angle angle_out;
- FT_Vector center;
- FT_Bool first_point;
- FT_Bool subpath_open;
- FT_Angle subpath_angle;
- FT_Vector subpath_start;
+ FT_Angle angle_in; /* direction into curr join */
+ FT_Angle angle_out; /* direction out of join */
+ FT_Vector center; /* current position */
+ FT_Fixed line_length; /* length of last lineto */
+ FT_Bool first_point; /* is this the start? */
+ FT_Bool subpath_open; /* is the subpath open? */
+ FT_Angle subpath_angle; /* subpath start direction */
+ FT_Vector subpath_start; /* subpath start position */
+ FT_Fixed subpath_line_length; /* subpath start lineto len */
+ FT_Bool handle_wide_strokes; /* use wide strokes logic? */
FT_Stroker_LineCap line_cap;
FT_Stroker_LineJoin line_join;
+ FT_Stroker_LineJoin line_join_saved;
FT_Fixed miter_limit;
FT_Fixed radius;
- FT_Bool valid;
FT_StrokeBorderRec borders[2];
FT_Library library;
@@ -719,7 +791,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stroker stroker;
+ FT_Stroker stroker = NULL;
if ( !library )
@@ -734,7 +806,9 @@
ft_stroke_border_init( &stroker->borders[0], memory );
ft_stroke_border_init( &stroker->borders[1], memory );
}
+
*astroker = stroker;
+
return error;
}
@@ -753,6 +827,14 @@
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;
+
+ /* save line join style: */
+ /* line join style can be temporarily changed when stroking curves */
+ stroker->line_join_saved = line_join;
+
FT_Stroker_Rewind( stroker );
}
@@ -789,7 +871,7 @@
}
- /* creates a circular arc at a corner or cap */
+ /* create a circular arc at a corner or cap */
static FT_Error
ft_stroker_arcto( FT_Stroker stroker,
FT_Int side )
@@ -816,7 +898,7 @@
}
- /* adds a cap at the end of an opened path */
+ /* add a cap at the end of an opened path */
static FT_Error
ft_stroker_cap( FT_Stroker stroker,
FT_Angle angle,
@@ -830,6 +912,7 @@
/* add a round cap */
stroker->angle_in = angle;
stroker->angle_out = angle + FT_ANGLE_PI;
+
error = ft_stroker_arcto( stroker, side );
}
else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
@@ -882,7 +965,7 @@
delta.x += stroker->center.x;
delta.y += stroker->center.y;
- error = ft_stroke_border_lineto( border, &delta, FALSE );
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
}
Exit:
@@ -893,40 +976,52 @@
/* process an inside corner, i.e. compute intersection */
static FT_Error
ft_stroker_inside( FT_Stroker stroker,
- FT_Int side)
+ FT_Int side,
+ FT_Fixed line_length )
{
FT_StrokeBorder border = stroker->borders + side;
FT_Angle phi, theta, rotate;
- FT_Fixed length, thcos, sigma;
+ FT_Fixed length, thcos;
FT_Vector delta;
FT_Error error = FT_Err_Ok;
+ FT_Bool intersect; /* use intersection of lines? */
rotate = FT_SIDE_TO_ROTATE( side );
- /* compute median angle */
- theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
- if ( theta == FT_ANGLE_PI )
- theta = rotate;
+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
+
+ /* 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 )
+ intersect = FALSE;
else
- theta = theta / 2;
+ {
+ /* compute minimum required length of lines */
+ FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius,
+ FT_Tan( theta ) ) );
- phi = stroker->angle_in + theta;
- thcos = FT_Cos( theta );
- sigma = FT_MulFix( stroker->miter_limit, thcos );
+ intersect = FT_BOOL( stroker->line_length >= min_length &&
+ line_length >= min_length );
+ }
- /* TODO: find better criterion to switch off the optimization */
- if ( sigma < 0x10000L )
+ if ( !intersect )
{
FT_Vector_From_Polar( &delta, stroker->radius,
stroker->angle_out + rotate );
delta.x += stroker->center.x;
delta.y += stroker->center.y;
+
border->movable = FALSE;
}
else
{
+ /* compute median angle */
+ phi = stroker->angle_in + theta;
+
+ thcos = FT_Cos( theta );
+
length = FT_DivFix( stroker->radius, thcos );
FT_Vector_From_Polar( &delta, length, phi + rotate );
@@ -943,7 +1038,8 @@
/* process an outside corner, i.e. compute bevel/miter/round */
static FT_Error
ft_stroker_outside( FT_Stroker stroker,
- FT_Int side )
+ FT_Int side,
+ FT_Fixed line_length )
{
FT_StrokeBorder border = stroker->borders + side;
FT_Error error;
@@ -954,79 +1050,119 @@
error = ft_stroker_arcto( stroker, side );
else
{
- /* this is a mitered or beveled corner */
- FT_Fixed sigma, radius = stroker->radius;
- FT_Angle theta, phi;
- FT_Fixed thcos;
- FT_Bool miter;
+ /* this is a mitered (pointed) or beveled (truncated) corner */
+ FT_Fixed sigma = 0, radius = stroker->radius;
+ FT_Angle theta = 0, phi = 0;
+ FT_Fixed thcos = 0;
+ FT_Bool bevel, fixed_bevel;
rotate = FT_SIDE_TO_ROTATE( side );
- miter = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER );
- theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
- if ( theta == FT_ANGLE_PI )
+ bevel =
+ FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
+
+ fixed_bevel =
+ FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
+
+ if ( !bevel )
{
- theta = rotate;
- phi = stroker->angle_in;
+ theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
+
+ if ( theta == FT_ANGLE_PI )
+ {
+ theta = rotate;
+ phi = stroker->angle_in;
+ }
+ else
+ {
+ theta /= 2;
+ phi = stroker->angle_in + theta + rotate;
+ }
+
+ thcos = FT_Cos( theta );
+ sigma = FT_MulFix( stroker->miter_limit, thcos );
+
+ /* is miter limit exceeded? */
+ if ( sigma < 0x10000L )
+ {
+ /* don't create variable bevels for very small deviations; */
+ /* FT_Sin(x) = 0 for x <= 57 */
+ if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
+ bevel = TRUE;
+ }
}
- else
+
+ if ( bevel ) /* this is a bevel (broken angle) */
{
- theta = theta / 2;
- phi = stroker->angle_in + theta + rotate;
- }
+ if ( fixed_bevel )
+ {
+ /* the outer corners are simply joined together */
+ FT_Vector delta;
- thcos = FT_Cos( theta );
- sigma = FT_MulFix( stroker->miter_limit, thcos );
- /* FT_Sin(x) = 0 for x <= 57 */
- if ( sigma >= 0x10000L || ft_pos_abs( theta ) <= 57 )
- miter = FALSE;
+ /* add bevel */
+ FT_Vector_From_Polar( &delta,
+ radius,
+ stroker->angle_out + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
- if ( miter ) /* this is a miter (broken angle) */
- {
- FT_Vector middle, delta;
- FT_Fixed length;
+ border->movable = FALSE;
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ }
+ else /* variable bevel */
+ {
+ /* the miter is truncated */
+ FT_Vector middle, delta;
+ FT_Fixed length;
- /* compute middle point */
- FT_Vector_From_Polar( &middle,
- FT_MulFix( radius, stroker->miter_limit ),
- phi );
- middle.x += stroker->center.x;
- middle.y += stroker->center.y;
+ /* compute middle point */
+ FT_Vector_From_Polar( &middle,
+ FT_MulFix( radius, stroker->miter_limit ),
+ phi );
+ middle.x += stroker->center.x;
+ middle.y += stroker->center.y;
- /* compute first angle point */
- length = FT_MulFix( radius,
- FT_DivFix( 0x10000L - sigma,
- ft_pos_abs( FT_Sin( theta ) ) ) );
+ /* compute first angle point */
+ length = FT_MulFix( radius,
+ FT_DivFix( 0x10000L - sigma,
+ ft_pos_abs( FT_Sin( theta ) ) ) );
- FT_Vector_From_Polar( &delta, length, phi + rotate );
- delta.x += middle.x;
- delta.y += middle.y;
+ FT_Vector_From_Polar( &delta, length, phi + rotate );
+ delta.x += middle.x;
+ delta.y += middle.y;
- error = ft_stroke_border_lineto( border, &delta, FALSE );
- if ( error )
- goto Exit;
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ if ( error )
+ goto Exit;
- /* compute second angle point */
- FT_Vector_From_Polar( &delta, length, phi - rotate );
- delta.x += middle.x;
- delta.y += middle.y;
+ /* compute second angle point */
+ FT_Vector_From_Polar( &delta, length, phi - rotate );
+ delta.x += middle.x;
+ delta.y += middle.y;
- error = ft_stroke_border_lineto( border, &delta, FALSE );
- if ( error )
- goto Exit;
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ if ( error )
+ goto Exit;
- /* finally, add a movable end point */
- FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate );
- delta.x += stroker->center.x;
- delta.y += stroker->center.y;
+ /* finally, add an end point; only needed if not lineto */
+ /* (line_length is zero for curves) */
+ if ( line_length == 0 )
+ {
+ FT_Vector_From_Polar( &delta,
+ radius,
+ stroker->angle_out + rotate );
- error = ft_stroke_border_lineto( border, &delta, TRUE );
- }
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
- else /* this is a bevel (intersection) */
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ }
+ }
+ }
+ else /* this is a miter (intersection) */
{
FT_Fixed length;
FT_Vector delta;
@@ -1042,13 +1178,18 @@
if ( error )
goto Exit;
- /* now add end point */
- FT_Vector_From_Polar( &delta, stroker->radius,
- stroker->angle_out + rotate );
- delta.x += stroker->center.x;
- delta.y += stroker->center.y;
+ /* now add an end point; only needed if not lineto */
+ /* (line_length is zero for curves) */
+ if ( line_length == 0 )
+ {
+ FT_Vector_From_Polar( &delta,
+ stroker->radius,
+ stroker->angle_out + rotate );
+ delta.x += stroker->center.x;
+ delta.y += stroker->center.y;
- error = ft_stroke_border_lineto( border, &delta, TRUE );
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ }
}
}
@@ -1058,7 +1199,8 @@
static FT_Error
- ft_stroker_process_corner( FT_Stroker stroker )
+ ft_stroker_process_corner( FT_Stroker stroker,
+ FT_Fixed line_length )
{
FT_Error error = FT_Err_Ok;
FT_Angle turn;
@@ -1079,12 +1221,12 @@
inside_side = 1;
/* process the inside side */
- error = ft_stroker_inside( stroker, inside_side );
+ error = ft_stroker_inside( stroker, inside_side, line_length );
if ( error )
goto Exit;
/* process the outside side */
- error = ft_stroker_outside( stroker, 1 - inside_side );
+ error = ft_stroker_outside( stroker, 1 - inside_side, line_length );
Exit:
return error;
@@ -1095,7 +1237,8 @@
/* start of the subpath */
static FT_Error
ft_stroker_subpath_start( FT_Stroker stroker,
- FT_Angle start_angle )
+ FT_Angle start_angle,
+ FT_Fixed line_length )
{
FT_Vector delta;
FT_Vector point;
@@ -1120,9 +1263,11 @@
border++;
error = ft_stroke_border_moveto( border, &point );
- /* save angle for last cap */
- stroker->subpath_angle = start_angle;
- stroker->first_point = FALSE;
+ /* save angle, position, and line length for last join */
+ /* (line_length is zero for curves) */
+ stroker->subpath_angle = start_angle;
+ stroker->first_point = FALSE;
+ stroker->subpath_line_length = line_length;
Exit:
return error;
@@ -1140,10 +1285,19 @@
FT_Vector delta;
FT_Angle angle;
FT_Int side;
+ FT_Fixed line_length;
+
delta.x = to->x - stroker->center.x;
delta.y = to->y - stroker->center.y;
+ /* a zero-length lineto is a no-op; avoid creating a spurious corner */
+ if ( delta.x == 0 && delta.y == 0 )
+ goto Exit;
+
+ /* compute length of line */
+ line_length = FT_Vector_Length( &delta );
+
angle = FT_Atan2( delta.x, delta.y );
FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
@@ -1153,7 +1307,7 @@
/* This is the first segment of a subpath. We need to */
/* add a point to each border at their respective starting */
/* point locations. */
- error = ft_stroker_subpath_start( stroker, angle );
+ error = ft_stroker_subpath_start( stroker, angle, line_length );
if ( error )
goto Exit;
}
@@ -1161,13 +1315,12 @@
{
/* process the current corner */
stroker->angle_out = angle;
- error = ft_stroker_process_corner( stroker );
+ error = ft_stroker_process_corner( stroker, line_length );
if ( error )
goto Exit;
}
/* now add a line segment to both the `inside' and `outside' paths */
-
for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
{
FT_Vector point;
@@ -1176,6 +1329,7 @@
point.x = to->x + delta.x;
point.y = to->y + delta.y;
+ /* the ends of lineto borders are movable */
error = ft_stroke_border_lineto( border, &point, TRUE );
if ( error )
goto Exit;
@@ -1184,8 +1338,9 @@
delta.y = -delta.y;
}
- stroker->angle_in = angle;
- stroker->center = *to;
+ stroker->angle_in = angle;
+ stroker->center = *to;
+ stroker->line_length = line_length;
Exit:
return error;
@@ -1203,10 +1358,20 @@
FT_Vector bez_stack[34];
FT_Vector* arc;
FT_Vector* limit = bez_stack + 30;
- FT_Angle start_angle;
FT_Bool first_arc = TRUE;
+ /* 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 ) &&
+ FT_IS_SMALL( stroker->center.y - control->y ) &&
+ FT_IS_SMALL( control->x - to->x ) &&
+ FT_IS_SMALL( control->y - to->y ) )
+ {
+ stroker->center = *to;
+ goto Exit;
+ }
+
arc = bez_stack;
arc[0] = *to;
arc[1] = *control;
@@ -1217,11 +1382,15 @@
FT_Angle angle_in, angle_out;
- angle_in = angle_out = 0; /* remove compiler warnings */
+ /* initialize with current direction */
+ angle_in = angle_out = stroker->angle_in;
if ( arc < limit &&
!ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
{
+ if ( stroker->first_point )
+ stroker->angle_in = angle_in;
+
ft_conic_split( arc );
arc += 2;
continue;
@@ -1231,32 +1400,54 @@
{
first_arc = FALSE;
- start_angle = angle_in;
-
/* process corner if necessary */
if ( stroker->first_point )
- error = ft_stroker_subpath_start( stroker, start_angle );
+ error = ft_stroker_subpath_start( stroker, angle_in, 0 );
else
{
- stroker->angle_out = start_angle;
- error = ft_stroker_process_corner( stroker );
+ stroker->angle_out = angle_in;
+ error = ft_stroker_process_corner( stroker, 0 );
}
}
+ else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
+ FT_SMALL_CONIC_THRESHOLD / 4 )
+ {
+ /* if the deviation from one arc to the next is too great, */
+ /* add a round corner */
+ stroker->center = arc[2];
+ stroker->angle_out = angle_in;
+ stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
+
+ error = ft_stroker_process_corner( stroker, 0 );
+
+ /* reinstate line join style */
+ stroker->line_join = stroker->line_join_saved;
+ }
+
+ if ( error )
+ goto Exit;
/* the arc's angle is small enough; we can add it directly to each */
/* border */
{
- FT_Vector ctrl, end;
- FT_Angle theta, phi, rotate;
- FT_Fixed length;
- FT_Int side;
+ FT_Vector ctrl, end;
+ FT_Angle theta, phi, rotate, alpha0 = 0;
+ FT_Fixed length;
+ FT_StrokeBorder border;
+ FT_Int side;
theta = FT_Angle_Diff( angle_in, angle_out ) / 2;
phi = angle_in + theta;
length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
- for ( side = 0; side <= 1; side++ )
+ /* compute direction of original arc */
+ if ( stroker->handle_wide_strokes )
+ alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y );
+
+ for ( border = stroker->borders, side = 0;
+ side <= 1;
+ side++, border++ )
{
rotate = FT_SIDE_TO_ROTATE( side );
@@ -1270,8 +1461,70 @@
end.x += arc[0].x;
end.y += arc[0].y;
- error = ft_stroke_border_conicto( stroker->borders + side,
- &ctrl, &end );
+ if ( stroker->handle_wide_strokes )
+ {
+ FT_Vector start;
+ FT_Angle alpha1;
+
+
+ /* determine whether the border radius is greater than the */
+ /* radius of curvature of the original arc */
+ start = border->points[border->num_points - 1];
+
+ alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
+
+ /* is the direction of the border arc opposite to */
+ /* that of the original arc? */
+ if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
+ FT_ANGLE_PI / 2 )
+ {
+ FT_Angle beta, gamma;
+ FT_Vector bvec, delta;
+ FT_Fixed blen, sinA, sinB, alen;
+
+
+ /* use the sine rule to find the intersection point */
+ beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y );
+ gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
+
+ bvec.x = end.x - start.x;
+ bvec.y = end.y - start.y;
+
+ blen = FT_Vector_Length( &bvec );
+
+ sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
+ sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
+
+ alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+
+ FT_Vector_From_Polar( &delta, alen, beta );
+ delta.x += start.x;
+ delta.y += start.y;
+
+ /* circumnavigate the negative sector backwards */
+ border->movable = FALSE;
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ if ( error )
+ goto Exit;
+ error = ft_stroke_border_lineto( border, &end, FALSE );
+ if ( error )
+ goto Exit;
+ error = ft_stroke_border_conicto( border, &ctrl, &start );
+ if ( error )
+ goto Exit;
+ /* and then move to the endpoint */
+ error = ft_stroke_border_lineto( border, &end, FALSE );
+ if ( error )
+ goto Exit;
+
+ continue;
+ }
+
+ /* else fall through */
+ }
+
+ /* simply add an arc */
+ error = ft_stroke_border_conicto( border, &ctrl, &end );
if ( error )
goto Exit;
}
@@ -1279,8 +1532,7 @@
arc -= 2;
- if ( arc < bez_stack )
- stroker->angle_in = angle_out;
+ stroker->angle_in = angle_out;
}
stroker->center = *to;
@@ -1302,10 +1554,22 @@
FT_Vector bez_stack[37];
FT_Vector* arc;
FT_Vector* limit = bez_stack + 32;
- FT_Angle start_angle;
FT_Bool first_arc = TRUE;
+ /* 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 ) &&
+ FT_IS_SMALL( stroker->center.y - control1->y ) &&
+ FT_IS_SMALL( control1->x - control2->x ) &&
+ FT_IS_SMALL( control1->y - control2->y ) &&
+ FT_IS_SMALL( control2->x - to->x ) &&
+ FT_IS_SMALL( control2->y - to->y ) )
+ {
+ stroker->center = *to;
+ goto Exit;
+ }
+
arc = bez_stack;
arc[0] = *to;
arc[1] = *control2;
@@ -1317,13 +1581,16 @@
FT_Angle angle_in, angle_mid, angle_out;
- /* remove compiler warnings */
- angle_in = angle_out = angle_mid = 0;
+ /* initialize with current direction */
+ angle_in = angle_out = angle_mid = stroker->angle_in;
if ( arc < limit &&
!ft_cubic_is_small_enough( arc, &angle_in,
&angle_mid, &angle_out ) )
{
+ if ( stroker->first_point )
+ stroker->angle_in = angle_in;
+
ft_cubic_split( arc );
arc += 3;
continue;
@@ -1334,36 +1601,56 @@
first_arc = FALSE;
/* process corner if necessary */
- start_angle = angle_in;
-
if ( stroker->first_point )
- error = ft_stroker_subpath_start( stroker, start_angle );
+ error = ft_stroker_subpath_start( stroker, angle_in, 0 );
else
{
- stroker->angle_out = start_angle;
- error = ft_stroker_process_corner( stroker );
+ stroker->angle_out = angle_in;
+ error = ft_stroker_process_corner( stroker, 0 );
}
- if ( error )
- goto Exit;
+ }
+ else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
+ FT_SMALL_CUBIC_THRESHOLD / 4 )
+ {
+ /* if the deviation from one arc to the next is too great, */
+ /* add a round corner */
+ stroker->center = arc[3];
+ stroker->angle_out = angle_in;
+ stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
+
+ error = ft_stroker_process_corner( stroker, 0 );
+
+ /* reinstate line join style */
+ stroker->line_join = stroker->line_join_saved;
}
+ if ( error )
+ goto Exit;
+
/* the arc's angle is small enough; we can add it directly to each */
/* border */
{
- FT_Vector ctrl1, ctrl2, end;
- FT_Angle theta1, phi1, theta2, phi2, rotate;
- FT_Fixed length1, length2;
- FT_Int side;
+ FT_Vector ctrl1, ctrl2, end;
+ FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
+ FT_Fixed length1, length2;
+ FT_StrokeBorder border;
+ FT_Int side;
- theta1 = ft_pos_abs( angle_mid - angle_in ) / 2;
- theta2 = ft_pos_abs( angle_out - angle_mid ) / 2;
- phi1 = (angle_mid + angle_in ) / 2;
- phi2 = (angle_mid + angle_out ) / 2;
+ theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2;
+ theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2;
+ phi1 = ft_angle_mean( angle_in, angle_mid );
+ phi2 = ft_angle_mean( angle_mid, angle_out );
length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
- for ( side = 0; side <= 1; side++ )
+ /* compute direction of original arc */
+ if ( stroker->handle_wide_strokes )
+ alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y );
+
+ for ( border = stroker->borders, side = 0;
+ side <= 1;
+ side++, border++ )
{
rotate = FT_SIDE_TO_ROTATE( side );
@@ -1381,16 +1668,81 @@
end.x += arc[0].x;
end.y += arc[0].y;
- error = ft_stroke_border_cubicto( stroker->borders + side,
- &ctrl1, &ctrl2, &end );
+ if ( stroker->handle_wide_strokes )
+ {
+ FT_Vector start;
+ FT_Angle alpha1;
+
+
+ /* determine whether the border radius is greater than the */
+ /* radius of curvature of the original arc */
+ start = border->points[border->num_points - 1];
+
+ alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
+
+ /* is the direction of the border arc opposite to */
+ /* that of the original arc? */
+ if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
+ FT_ANGLE_PI / 2 )
+ {
+ FT_Angle beta, gamma;
+ FT_Vector bvec, delta;
+ FT_Fixed blen, sinA, sinB, alen;
+
+
+ /* use the sine rule to find the intersection point */
+ beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y );
+ gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
+
+ bvec.x = end.x - start.x;
+ bvec.y = end.y - start.y;
+
+ blen = FT_Vector_Length( &bvec );
+
+ sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
+ sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
+
+ alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+
+ FT_Vector_From_Polar( &delta, alen, beta );
+ delta.x += start.x;
+ delta.y += start.y;
+
+ /* circumnavigate the negative sector backwards */
+ border->movable = FALSE;
+ error = ft_stroke_border_lineto( border, &delta, FALSE );
+ if ( error )
+ goto Exit;
+ error = ft_stroke_border_lineto( border, &end, FALSE );
+ if ( error )
+ goto Exit;
+ error = ft_stroke_border_cubicto( border,
+ &ctrl2,
+ &ctrl1,
+ &start );
+ if ( error )
+ goto Exit;
+ /* and then move to the endpoint */
+ error = ft_stroke_border_lineto( border, &end, FALSE );
+ if ( error )
+ goto Exit;
+
+ continue;
+ }
+
+ /* else fall through */
+ }
+
+ /* simply add an arc */
+ error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end );
if ( error )
goto Exit;
}
}
arc -= 3;
- if ( arc < bez_stack )
- stroker->angle_in = angle_out;
+
+ stroker->angle_in = angle_out;
}
stroker->center = *to;
@@ -1415,9 +1767,21 @@
stroker->center = *to;
stroker->subpath_open = open;
+ /* Determine if we need to check whether the border radius is greater */
+ /* than the radius of curvature of a curve, to handle this case */
+ /* specially. This is only required if bevel joins or butt caps may */
+ /* be created, because round & miter joins and round & square caps */
+ /* cover the negative sector created with wide strokes. */
+ stroker->handle_wide_strokes =
+ FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND ||
+ ( stroker->subpath_open &&
+ stroker->line_cap == FT_STROKER_LINECAP_BUTT ) );
+
/* record the subpath start point for each border */
stroker->subpath_start = *to;
+ stroker->angle_in = 0;
+
return FT_Err_Ok;
}
@@ -1447,6 +1811,7 @@
FT_Vector* src_point = left->points + left->num_points - 1;
FT_Byte* src_tag = left->tags + left->num_points - 1;
+
while ( src_point >= left->points + left->start )
{
*dst_point = *src_point;
@@ -1456,14 +1821,14 @@
dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
else
{
- FT_Byte ttag = (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
+ FT_Byte ttag =
+ (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
/* switch begin/end tags if necessary */
if ( ttag == FT_STROKE_TAG_BEGIN ||
ttag == FT_STROKE_TAG_END )
dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
-
}
src_point--;
@@ -1498,6 +1863,7 @@
{
FT_StrokeBorder right = stroker->borders;
+
/* All right, this is an opened path, we need to add a cap between */
/* right & left, add the reverse of left, then add a final cap */
/* between left & right. */
@@ -1526,13 +1892,14 @@
FT_Angle turn;
FT_Int inside_side;
+
/* close the path if needed */
if ( stroker->center.x != stroker->subpath_start.x ||
stroker->center.y != stroker->subpath_start.y )
{
- error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
- if ( error )
- goto Exit;
+ error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
+ if ( error )
+ goto Exit;
}
/* process the corner */
@@ -1550,19 +1917,23 @@
if ( turn < 0 )
inside_side = 1;
- error = ft_stroker_inside( stroker, inside_side );
+ error = ft_stroker_inside( stroker,
+ inside_side,
+ stroker->subpath_line_length );
if ( error )
goto Exit;
/* process the outside side */
- error = ft_stroker_outside( stroker, 1 - inside_side );
+ error = ft_stroker_outside( stroker,
+ 1 - inside_side,
+ stroker->subpath_line_length );
if ( error )
goto Exit;
}
/* then end our two subpaths */
- ft_stroke_border_close( stroker->borders + 0, TRUE );
- ft_stroke_border_close( stroker->borders + 1, FALSE );
+ ft_stroke_border_close( stroker->borders + 0, FALSE );
+ ft_stroke_border_close( stroker->borders + 1, TRUE );
}
Exit:
@@ -1684,9 +2055,9 @@
FT_Error error;
- FT_Int n; /* index of contour in outline */
- FT_UInt first; /* index of first point in contour */
- FT_Int tag; /* current point's state */
+ FT_Int n; /* index of contour in outline */
+ FT_UInt first; /* index of first point in contour */
+ FT_Int tag; /* current point's state */
if ( !outline || !stroker )
@@ -1867,9 +2238,10 @@
return FT_Err_Invalid_Outline;
}
-/* declare an extern to access ft_outline_glyph_class global allocated
- in ftglyph.c, and use the FT_OUTLINE_GLYPH_CLASS_GET macro to access
- it when FT_CONFIG_OPTION_PIC is defined */
+
+ /* 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
@@ -1883,10 +2255,12 @@
FT_Stroker stroker,
FT_Bool destroy )
{
- FT_Error error = FT_Err_Invalid_Argument;
- FT_Glyph glyph = NULL;
- FT_Library library = stroker->library;
- FT_UNUSED(library);
+ FT_Error error = FT_Err_Invalid_Argument;
+ FT_Glyph glyph = NULL;
+ FT_Library library = stroker->library;
+
+ FT_UNUSED( library );
+
if ( pglyph == NULL )
goto Exit;
@@ -1907,7 +2281,7 @@
}
{
- FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;
+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
FT_Outline* outline = &oglyph->outline;
FT_UInt num_points, num_contours;
@@ -1957,10 +2331,12 @@
FT_Bool inside,
FT_Bool destroy )
{
- FT_Error error = FT_Err_Invalid_Argument;
- FT_Glyph glyph = NULL;
- FT_Library library = stroker->library;
- FT_UNUSED(library);
+ FT_Error error = FT_Err_Invalid_Argument;
+ FT_Glyph glyph = NULL;
+ FT_Library library = stroker->library;
+
+ FT_UNUSED( library );
+
if ( pglyph == NULL )
goto Exit;
@@ -1981,7 +2357,7 @@
}
{
- FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph;
+ FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
FT_StrokerBorder border;
FT_Outline* outline = &oglyph->outline;
FT_UInt num_points, num_contours;
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index ba3c633..d4ec0da 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -90,7 +90,7 @@
if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
- slot->format != FT_GLYPH_FORMAT_BITMAP )
+ slot->format != FT_GLYPH_FORMAT_BITMAP )
return;
/* some reasonable strength */
@@ -108,7 +108,7 @@
xstr = xstr * 2;
ystr = xstr;
}
- else if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+ else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
{
/* round to full pixels */
xstr &= ~63;
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index ba86005..7e203be 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-2001, 2002, 2006, 2008, 2009, 2010 by */
+/* Copyright 1996-2002, 2006, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -137,6 +137,7 @@
/* */
/*************************************************************************/
+#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
/*************************************************************************/
/* */
@@ -229,6 +230,13 @@
if ( !stream )
return FT_Err_Invalid_Stream_Handle;
+ stream->descriptor.pointer = NULL;
+ stream->pathname.pointer = (char*)filepathname;
+ stream->base = 0;
+ stream->pos = 0;
+ stream->read = NULL;
+ stream->close = NULL;
+
file = ft_fopen( filepathname, "rb" );
if ( !file )
{
@@ -240,12 +248,16 @@
ft_fseek( file, 0, SEEK_END );
stream->size = ft_ftell( file );
+ if ( !stream->size )
+ {
+ FT_ERROR(( "FT_Stream_Open:" ));
+ FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
+ ft_fclose( file );
+ return FT_Err_Cannot_Open_Stream;
+ }
ft_fseek( file, 0, SEEK_SET );
stream->descriptor.pointer = file;
- stream->pathname.pointer = (char*)filepathname;
- stream->pos = 0;
-
stream->read = ft_ansi_stream_io;
stream->close = ft_ansi_stream_close;
@@ -256,6 +268,7 @@
return FT_Err_Ok;
}
+#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
#ifdef FT_DEBUG_MEMORY
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 39f04ee..4fd3436 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -328,7 +328,7 @@
if ( cff && cff->font_info == NULL )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
- PS_FontInfoRec *font_info;
+ PS_FontInfoRec *font_info = NULL;
FT_Memory memory = face->root.memory;
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index e99ee70..cb06bdf 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,8 +4,7 @@
/* */
/* OpenType Glyph Loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -1159,8 +1158,8 @@
op = cff_op_flex1;
break;
default:
- /* decrement ip for syntax error message */
- ip--;
+ FT_TRACE4(( " unknown op (12, %d)\n", v ));
+ break;
}
}
break;
@@ -1213,11 +1212,12 @@
op = cff_op_hvcurveto;
break;
default:
+ FT_TRACE4(( " unknown op (%d)\n", v ));
break;
}
if ( op == cff_op_unknown )
- goto Syntax_Error;
+ continue;
/* check arguments */
req_args = cff_argument_counts[op];
@@ -1438,9 +1438,14 @@
FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
: " vlineto\n" ));
- if ( num_args < 1 )
+ if ( num_args < 0 )
goto Stack_Underflow;
+ /* there exist subsetted fonts (found in PDFs) */
+ /* which call `hlineto' without arguments */
+ if ( num_args == 0 )
+ break;
+
if ( cff_builder_start_point ( builder, x, y ) ||
check_points( builder, num_args ) )
goto Fail;
@@ -2701,7 +2706,7 @@
glyph_index );
if ( fd_index >= cff->num_subfonts )
- fd_index = cff->num_subfonts - 1;
+ 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;
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 42e7730..98d8e1c 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -387,7 +387,7 @@
{
FT_Error error = CFF_Err_Ok;
FT_Memory memory = idx->stream->memory;
- FT_Byte** t;
+ FT_Byte** t = NULL;
FT_Byte* new_bytes = NULL;
@@ -519,6 +519,18 @@
}
}
+ /* XXX: should check off2 does not exceed the end of this entry; */
+ /* at present, only truncate off2 at the end of this stream */
+ if ( off2 > stream->size + 1 ||
+ idx->data_offset > stream->size - off2 + 1 )
+ {
+ FT_ERROR(( "cff_index_access_element:"
+ " offset to next entry (%d)"
+ " exceeds the end of stream (%d)\n",
+ off2, stream->size - idx->data_offset + 1 ));
+ off2 = stream->size - idx->data_offset + 1;
+ }
+
/* access element */
if ( off1 && off2 > off1 )
{
@@ -779,11 +791,12 @@
goto Exit;
for ( i = 0; i < num_glyphs; i++ )
+ {
if ( charset->sids[i] > max_cid )
max_cid = charset->sids[i];
- max_cid++;
+ }
- if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
+ if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
goto Exit;
/* When multiple GIDs map to the same CID, we choose the lowest */
@@ -807,7 +820,7 @@
FT_UInt result = 0;
- if ( cid < charset->max_cid )
+ if ( cid <= charset->max_cid )
result = charset->cids[cid];
return result;
@@ -881,20 +894,7 @@
goto Exit;
for ( j = 1; j < num_glyphs; j++ )
- {
- FT_UShort sid = FT_GET_USHORT();
-
-
- /* this constant is given in the CFF specification */
- if ( sid < 65000L )
- charset->sids[j] = sid;
- else
- {
- FT_TRACE0(( "cff_charset_load:"
- " invalid SID value %d set to zero\n", sid ));
- charset->sids[j] = 0;
- }
- }
+ charset->sids[j] = FT_GET_USHORT();
FT_FRAME_EXIT();
}
@@ -927,20 +927,12 @@
goto Exit;
}
- /* check whether the range contains at least one valid glyph; */
- /* the constant is given in the CFF specification */
- if ( glyph_sid >= 65000L )
- {
- FT_ERROR(( "cff_charset_load: invalid SID range\n" ));
- error = CFF_Err_Invalid_File_Format;
- goto Exit;
- }
-
/* try to rescue some of the SIDs if `nleft' is too large */
- if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft )
+ if ( glyph_sid > 0xFFFFL - nleft )
{
- FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" ));
- nleft = ( FT_UInt )( 65000L - 1L - glyph_sid );
+ FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
+ " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
+ nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
}
/* Fill in the range of sids -- `nleft + 1' glyphs. */
@@ -1277,9 +1269,7 @@
if ( gid != 0 )
{
encoding->codes[j] = (FT_UShort)gid;
-
- if ( encoding->count < j + 1 )
- encoding->count = j + 1;
+ encoding->count = j + 1;
}
else
{
@@ -1524,7 +1514,7 @@
if ( dict->cid_registry != 0xFFFFU )
{
CFF_IndexRec fd_index;
- CFF_SubFont sub;
+ CFF_SubFont sub = NULL;
FT_UInt idx;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index f8b07c3..cd38676 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,8 +4,7 @@
/* */
/* OpenType objects manager (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -162,7 +161,7 @@
{
CFF_Face face = (CFF_Face)cffsize->face;
CFF_Font font = (CFF_Font)face->extra.data;
- CFF_Internal internal;
+ CFF_Internal internal = NULL;
PS_PrivateRec priv;
FT_Memory memory = cffsize->face->memory;
@@ -421,6 +420,7 @@
{
for ( idx = 7; idx < length; idx++ )
name[idx - 7] = name[idx];
+ length -= 7;
}
}
else
@@ -429,6 +429,51 @@
}
+ /* Remove the style part from the family name (if present). */
+
+ static void
+ remove_style( FT_String* family_name,
+ const FT_String* style_name )
+ {
+ FT_Int32 family_name_length, style_name_length;
+
+
+ family_name_length = strlen( family_name );
+ style_name_length = strlen( style_name );
+
+ if ( family_name_length > style_name_length )
+ {
+ FT_Int idx;
+
+
+ for ( idx = 1; idx <= style_name_length; ++idx )
+ {
+ if ( family_name[family_name_length - idx] !=
+ style_name[style_name_length - idx] )
+ break;
+ }
+
+ if ( idx > style_name_length )
+ {
+ /* family_name ends with style_name; remove it */
+ idx = family_name_length - style_name_length - 1;
+
+ /* also remove special characters */
+ /* between real family name and style */
+ while ( idx > 0 &&
+ ( family_name[idx] == '-' ||
+ family_name[idx] == ' ' ||
+ family_name[idx] == '_' ||
+ family_name[idx] == '+' ) )
+ --idx;
+
+ if ( idx > 0 )
+ family_name[idx + 1] = '\0';
+ }
+ }
+ }
+
+
FT_LOCAL_DEF( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face cffface, /* CFF_Face */
@@ -436,14 +481,14 @@
FT_Int num_params,
FT_Parameter* params )
{
- CFF_Face face = (CFF_Face)cffface;
+ CFF_Face face = (CFF_Face)cffface;
FT_Error error;
SFNT_Service sfnt;
FT_Service_PsCMaps psnames;
PSHinter_Service pshinter;
FT_Bool pure_cff = 1;
FT_Bool sfnt_format = 0;
- FT_Library library = cffface->driver->root.library;
+ FT_Library library = cffface->driver->root.library;
sfnt = (SFNT_Service)FT_Get_Module_Interface(
@@ -523,7 +568,7 @@
/* now load and parse the CFF table in the file */
{
- CFF_Font cff;
+ CFF_Font cff = NULL;
CFF_FontRecDict dict;
FT_Memory memory = cffface->memory;
FT_Int32 flags;
@@ -677,7 +722,7 @@
/* compute number of glyphs */
if ( dict->cid_registry != 0xFFFFU )
- cffface->num_glyphs = cff->charset.max_cid;
+ cffface->num_glyphs = cff->charset.max_cid + 1;
else
cffface->num_glyphs = cff->charstrings_index.count;
@@ -758,6 +803,9 @@
/* case, the remaining string in `fullp' will be used as */
/* the style name. */
style_name = cff_strcpy( memory, fullp );
+
+ /* remove the style part from the family name (if present) */
+ remove_style( cffface->family_name, style_name );
}
break;
}
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 0d11a72..4f71e85 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (body) */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2004, 2007-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -35,8 +35,6 @@
#define FT_COMPONENT trace_cffparse
-
-
FT_LOCAL_DEF( void )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
@@ -475,6 +473,12 @@
if ( scaling < 0 || scaling > 9 )
{
/* Return default matrix in case of unlikely values. */
+
+ FT_TRACE1(( "cff_parse_font_matrix:"
+ " strange scaling value for xx element (%d),\n"
+ " "
+ " using default matrix\n", scaling ));
+
matrix->xx = 0x10000L;
matrix->yx = 0;
matrix->yx = 0;
@@ -493,6 +497,12 @@
offset->y = cff_parse_fixed_scaled( data, scaling );
*upm = power_tens[scaling];
+
+ FT_TRACE4(( " font matrix: [%f %f %f %f]\n",
+ (double)matrix->xx / *upm / 65536,
+ (double)matrix->xy / *upm / 65536,
+ (double)matrix->yx / *upm / 65536,
+ (double)matrix->yy / *upm / 65536 ));
}
Exit:
@@ -518,6 +528,12 @@
bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
error = CFF_Err_Ok;
+
+ FT_TRACE4(( " bbox: [%d %d %d %d]\n",
+ bbox->xMin / 65536,
+ bbox->yMin / 65536,
+ bbox->xMax / 65536,
+ bbox->yMax / 65536 ));
}
return error;
@@ -557,8 +573,8 @@
if ( parser->top >= parser->stack + 3 )
{
- dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
- dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
+ dict->cid_registry = (FT_UInt)cff_parse_num( data++ );
+ dict->cid_ordering = (FT_UInt)cff_parse_num( data++ );
if ( **data == 30 )
FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
dict->cid_supplement = cff_parse_num( data );
@@ -566,6 +582,11 @@
FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
dict->cid_supplement ));
error = CFF_Err_Ok;
+
+ FT_TRACE4(( " ROS: registry sid %d, ordering sid %d, supplement %d\n",
+ dict->cid_registry,
+ dict->cid_ordering,
+ dict->cid_supplement ));
}
return error;
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index d405357..665ab6f 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-2001, 2002, 2003, 2006, 2007, 2008, 2010 by */
+/* Copyright 1996-2003, 2006-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -212,8 +212,7 @@ FT_BEGIN_HEADER
} CFF_SubFontRec, *CFF_SubFont;
- /* maximum number of sub-fonts in a CID-keyed file */
-#define CFF_MAX_CID_FONTS 32
+#define CFF_MAX_CID_FONTS 256
typedef struct CFF_FontRec_
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index 45c7419..a28b5fc 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,8 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -186,13 +185,13 @@
/* grow the base block if needed */
if ( table->cursor + length > table->capacity )
{
- FT_Error error;
- FT_Offset new_size = table->capacity;
- FT_Long in_offset;
+ FT_Error error;
+ FT_Offset new_size = table->capacity;
+ FT_PtrDist in_offset;
- in_offset = (FT_Long)((FT_Byte*)object - table->block);
- if ( (FT_ULong)in_offset >= table->capacity )
+ in_offset = (FT_Byte*)object - table->block;
+ if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
in_offset = -1;
while ( new_size < table->cursor + length )
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index babf3ba..90874f0 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,8 +4,7 @@
/* */
/* PostScript Type 1 decoding routines (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */
-/* 2010 by */
+/* Copyright 2000-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -28,6 +27,8 @@
#include "psauxerr.h"
+/* ensure proper sign extension */
+#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) )
/*************************************************************************/
/* */
@@ -373,15 +374,6 @@
#endif
- /* we don't want to touch the source code -- use macro trick */
-#define start_point t1_builder_start_point
-#define check_points t1_builder_check_points
-#define add_point t1_builder_add_point
-#define add_point1 t1_builder_add_point1
-#define add_contour t1_builder_add_contour
-#define close_contour t1_builder_close_contour
-
-
/* compute random seed from stack address of parameter */
seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^
(FT_PtrDist)(char*)&decoder ^
@@ -405,7 +397,7 @@
FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
( decoder->buildchar == NULL ) );
- if ( decoder->len_buildchar > 0 )
+ if ( decoder->buildchar && decoder->len_buildchar > 0 )
ft_memset( &decoder->buildchar[0],
0,
sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
@@ -671,7 +663,7 @@
if ( large_int )
FT_TRACE4(( " %ld", value ));
else
- FT_TRACE4(( " %ld", (FT_Int32)( value >> 16 ) ));
+ FT_TRACE4(( " %ld", Fix2Int( value ) ));
#endif
*top++ = value;
@@ -693,8 +685,8 @@
top -= 2;
- subr_no = (FT_Int)( top[1] >> 16 );
- arg_cnt = (FT_Int)( top[0] >> 16 );
+ subr_no = Fix2Int( top[1] );
+ arg_cnt = Fix2Int( top[0] );
/***********************************************************/
/* */
@@ -733,14 +725,34 @@
switch ( subr_no )
{
+ case 0: /* end flex feature */
+ if ( arg_cnt != 3 )
+ goto Unexpected_OtherSubr;
+
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings:"
+ " unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
+
+ /* the two `results' are popped by the following setcurrentpoint */
+ top[0] = x;
+ top[1] = y;
+ known_othersubr_result_cnt = 2;
+ break;
+
case 1: /* start flex feature */
if ( arg_cnt != 0 )
goto Unexpected_OtherSubr;
decoder->flex_state = 1;
decoder->num_flex_vectors = 0;
- if ( start_point( builder, x, y ) ||
- check_points( builder, 6 ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok ||
+ ( error = t1_builder_check_points( builder, 6 ) )
+ != PSaux_Err_Ok )
goto Fail;
break;
@@ -757,31 +769,13 @@
/* point without adding any point to the outline */
idx = decoder->num_flex_vectors++;
if ( idx > 0 && idx < 7 )
- add_point( builder,
- x,
- y,
- (FT_Byte)( idx == 3 || idx == 6 ) );
+ t1_builder_add_point( builder,
+ x,
+ y,
+ (FT_Byte)( idx == 3 || idx == 6 ) );
}
break;
- case 0: /* end flex feature */
- if ( arg_cnt != 3 )
- goto Unexpected_OtherSubr;
-
- if ( decoder->flex_state == 0 ||
- decoder->num_flex_vectors != 7 )
- {
- FT_ERROR(( "t1_decoder_parse_charstrings:"
- " unexpected flex end\n" ));
- goto Syntax_Error;
- }
-
- /* the two `results' are popped by the following setcurrentpoint */
- top[0] = x;
- top[1] = y;
- known_othersubr_result_cnt = 2;
- break;
-
case 3: /* change hints */
if ( arg_cnt != 1 )
goto Unexpected_OtherSubr;
@@ -825,17 +819,18 @@
goto Syntax_Error;
}
- /* we want to compute: */
+ /* We want to compute */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
/* */
- /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
/* */
- /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
- /* however, given that w0 + w1 + ... + wk == 1, we can */
- /* rewrite it easily as: */
+ /* However, given that w0 + w1 + ... + wk == 1, we can */
+ /* rewrite it easily as */
/* */
- /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
/* */
- /* where k == num_designs-1 */
+ /* where k == num_designs-1. */
/* */
/* I guess that's why it's written in this `compact' */
/* form. */
@@ -869,7 +864,7 @@
if ( arg_cnt != 1 || blend == NULL )
goto Unexpected_OtherSubr;
- idx = (FT_Int)( top[0] >> 16 );
+ idx = Fix2Int( top[0] );
if ( idx < 0 ||
idx + blend->num_designs > decoder->len_buildchar )
@@ -937,7 +932,7 @@
if ( arg_cnt != 2 || blend == NULL )
goto Unexpected_OtherSubr;
- idx = (FT_Int)( top[1] >> 16 );
+ idx = Fix2Int( top[1] );
if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
goto Unexpected_OtherSubr;
@@ -958,7 +953,7 @@
if ( arg_cnt != 1 || blend == NULL )
goto Unexpected_OtherSubr;
- idx = (FT_Int)( top[0] >> 16 );
+ idx = Fix2Int( top[0] );
if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
goto Unexpected_OtherSubr;
@@ -1016,11 +1011,15 @@
break;
default:
- FT_ERROR(( "t1_decoder_parse_charstrings:"
- " unknown othersubr [%d %d], wish me luck\n",
- arg_cnt, subr_no ));
- unknown_othersubr_result_cnt = arg_cnt;
- break;
+ if ( arg_cnt >= 0 && subr_no >= 0 )
+ {
+ FT_ERROR(( "t1_decoder_parse_charstrings:"
+ " unknown othersubr [%d %d], wish me luck\n",
+ arg_cnt, subr_no ));
+ unknown_othersubr_result_cnt = arg_cnt;
+ break;
+ }
+ /* fall through */
Unexpected_OtherSubr:
FT_ERROR(( "t1_decoder_parse_charstrings:"
@@ -1077,7 +1076,7 @@
case op_endchar:
FT_TRACE4(( " endchar\n" ));
- close_contour( builder );
+ t1_builder_close_contour( builder );
/* close hints recording session */
if ( hinter )
@@ -1146,8 +1145,8 @@
top[0],
top[1],
top[2],
- (FT_Int)( top[3] >> 16 ),
- (FT_Int)( top[4] >> 16 ) );
+ Fix2Int( top[3] ),
+ Fix2Int( top[4] ) );
case op_sbw:
FT_TRACE4(( " sbw" ));
@@ -1176,7 +1175,7 @@
/* if there is no path, `closepath' is a no-op */
if ( builder->parse_state == T1_Parse_Have_Path ||
builder->parse_state == T1_Parse_Have_Moveto )
- close_contour( builder );
+ t1_builder_close_contour( builder );
builder->parse_state = T1_Parse_Have_Width;
break;
@@ -1184,7 +1183,8 @@
case op_hlineto:
FT_TRACE4(( " hlineto" ));
- if ( start_point( builder, x, y ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok )
goto Fail;
x += top[0];
@@ -1205,30 +1205,34 @@
case op_hvcurveto:
FT_TRACE4(( " hvcurveto" ));
- if ( start_point( builder, x, y ) ||
- check_points( builder, 3 ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok ||
+ ( error = t1_builder_check_points( builder, 3 ) )
+ != PSaux_Err_Ok )
goto Fail;
x += top[0];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
x += top[1];
y += top[2];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
y += top[3];
- add_point( builder, x, y, 1 );
+ t1_builder_add_point( builder, x, y, 1 );
break;
case op_rlineto:
FT_TRACE4(( " rlineto" ));
- if ( start_point( builder, x, y ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok )
goto Fail;
x += top[0];
y += top[1];
Add_Line:
- if ( add_point1( builder, x, y ) )
+ if ( ( error = t1_builder_add_point1( builder, x, y ) )
+ != PSaux_Err_Ok )
goto Fail;
break;
@@ -1248,43 +1252,48 @@
case op_rrcurveto:
FT_TRACE4(( " rrcurveto" ));
- if ( start_point( builder, x, y ) ||
- check_points( builder, 3 ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok ||
+ ( error = t1_builder_check_points( builder, 3 ) )
+ != PSaux_Err_Ok )
goto Fail;
x += top[0];
y += top[1];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
x += top[2];
y += top[3];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
x += top[4];
y += top[5];
- add_point( builder, x, y, 1 );
+ t1_builder_add_point( builder, x, y, 1 );
break;
case op_vhcurveto:
FT_TRACE4(( " vhcurveto" ));
- if ( start_point( builder, x, y ) ||
- check_points( builder, 3 ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok ||
+ ( error = t1_builder_check_points( builder, 3 ) )
+ != PSaux_Err_Ok )
goto Fail;
y += top[0];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
x += top[1];
y += top[2];
- add_point( builder, x, y, 0 );
+ t1_builder_add_point( builder, x, y, 0 );
x += top[3];
- add_point( builder, x, y, 1 );
+ t1_builder_add_point( builder, x, y, 1 );
break;
case op_vlineto:
FT_TRACE4(( " vlineto" ));
- if ( start_point( builder, x, y ) )
+ if ( ( error = t1_builder_start_point( builder, x, y ) )
+ != PSaux_Err_Ok )
goto Fail;
y += top[0];
@@ -1321,7 +1330,7 @@
FT_TRACE4(( " callsubr" ));
- idx = (FT_Int)( top[0] >> 16 );
+ idx = Fix2Int( top[0] );
if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
{
FT_ERROR(( "t1_decoder_parse_charstrings:"
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index 4b08785..d798978 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -1862,12 +1862,10 @@
point->cur_u = hint->cur_pos + hint->cur_len +
FT_MulFix( delta - hint->org_len, scale );
- else if ( hint->org_len > 0 )
+ else /* hint->org_len > 0 */
point->cur_u = hint->cur_pos +
FT_MulDiv( delta, hint->cur_len,
hint->org_len );
- else
- point->cur_u = hint->cur_pos;
}
psh_point_set_fitted( point );
}
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index ce6fdfe..55e2d0d 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -302,7 +302,6 @@
typedef short Short;
typedef unsigned short UShort, *PUShort;
typedef long Long, *PLong;
- typedef unsigned long ULong;
typedef unsigned char Byte, *PByte;
typedef char Bool;
@@ -448,7 +447,6 @@
Int precision_bits; /* precision related variables */
Int precision;
Int precision_half;
- Long precision_mask;
Int precision_shift;
Int precision_step;
Int precision_jitter;
@@ -653,11 +651,33 @@
static void
Set_High_Precision( RAS_ARGS Int High )
{
+ /*
+ * `precision_step' is used in `Bezier_Up' to decide when to split a
+ * given y-monotonous Bezier arc that crosses a scanline before
+ * approximating it as a straight segment. The default value of 32 (for
+ * low accuracy) corresponds to
+ *
+ * 32 / 64 == 0.5 pixels ,
+ *
+ * while for the high accuracy case we have
+ *
+ * 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
+ * decomposition (after all, we are working with approximations only);
+ * it avoids switching on additional pixels which would cause artifacts
+ * otherwise.
+ *
+ * The value of `precision_jitter' has been determined heuristically.
+ *
+ */
+
if ( High )
{
ras.precision_bits = 12;
ras.precision_step = 256;
- ras.precision_jitter = 50;
+ ras.precision_jitter = 30;
}
else
{
@@ -671,7 +691,6 @@
ras.precision = 1 << ras.precision_bits;
ras.precision_half = ras.precision / 2;
ras.precision_shift = ras.precision_bits - Pixel_Bits;
- ras.precision_mask = -ras.precision;
}
@@ -725,13 +744,13 @@
if ( overshoot )
ras.cProfile->flags |= Overshoot_Bottom;
- FT_TRACE6(( "New ascending profile = %lx\n", (long)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 = %lx\n", (long)ras.cProfile ));
+ FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
break;
default:
@@ -784,8 +803,8 @@
if ( h > 0 )
{
- FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
- (long)ras.cProfile, ras.cProfile->start, h ));
+ FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
+ ras.cProfile, ras.cProfile->start, h ));
ras.cProfile->height = h;
if ( overshoot )
@@ -1094,7 +1113,7 @@
return SUCCESS;
else
{
- x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+ x1 += SMulDiv( Dx, ras.precision - f1, Dy );
e1 += 1;
}
}
@@ -1122,13 +1141,13 @@
if ( Dx > 0 )
{
- Ix = SMulDiv( ras.precision, Dx, Dy);
+ Ix = SMulDiv( ras.precision, Dx, Dy);
Rx = ( ras.precision * Dx ) % Dy;
Dx = 1;
}
else
{
- Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
+ Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
Rx = ( ras.precision * -Dx ) % Dy;
Dx = -1;
}
@@ -2406,6 +2425,14 @@
return; /* no drop-out control */
}
+ /* undocumented but confirmed: If the drop-out would result in a */
+ /* pixel outside of the bounding box, use the pixel inside of the */
+ /* bounding box instead */
+ if ( pxl < 0 )
+ pxl = e1;
+ else if ( TRUNC( pxl ) >= ras.bWidth )
+ pxl = e2;
+
/* check that the other pixel isn't set */
e1 = pxl == e1 ? e2 : e1;
@@ -2582,6 +2609,14 @@
return; /* no drop-out control */
}
+ /* undocumented but confirmed: If the drop-out would result in a */
+ /* pixel outside of the bounding box, use the pixel inside of the */
+ /* bounding box instead */
+ if ( pxl < 0 )
+ pxl = e1;
+ else if ( TRUNC( pxl ) >= ras.target.rows )
+ pxl = e2;
+
/* check that the other pixel isn't set */
e1 = pxl == e1 ? e2 : e1;
@@ -3385,6 +3420,7 @@
FT_Raster *araster )
{
static TRaster the_raster;
+ FT_UNUSED( memory );
*araster = (FT_Raster)&the_raster;
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 1ed8af6..d8a89f2 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -161,10 +161,18 @@
/* compute the control box, and grid fit it */
FT_Outline_Get_CBox( outline, &cbox );
+ /* 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 );
+#else
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 );
+#endif
width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index b74679b..247aa67 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 1996-2007, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -117,15 +117,20 @@
FT_ULong *offset,
FT_ULong *length )
{
- if ( !tag || !offset || !length )
+ if ( !offset || !length )
return SFNT_Err_Invalid_Argument;
- if ( idx >= face->num_tables )
- return SFNT_Err_Table_Missing;
+ if ( !tag )
+ *length = face->num_tables;
+ else
+ {
+ if ( idx >= face->num_tables )
+ return SFNT_Err_Table_Missing;
- *tag = face->dir_tables[idx].Tag;
- *offset = face->dir_tables[idx].Offset;
- *length = face->dir_tables[idx].Length;
+ *tag = face->dir_tables[idx].Tag;
+ *offset = face->dir_tables[idx].Offset;
+ *length = face->dir_tables[idx].Length;
+ }
return SFNT_Err_Ok;
}
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 6e35e2d..44471f6 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (base). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/* Copyright 1996-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -356,7 +356,7 @@
FT_FRAME_START( 8 ),
FT_FRAME_LONG( version ),
- FT_FRAME_LONG( count ),
+ FT_FRAME_LONG( count ), /* this is ULong in the specs */
FT_FRAME_END
};
@@ -390,6 +390,17 @@
if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
return error;
+ if ( face->ttc_header.count == 0 )
+ return SFNT_Err_Invalid_Table;
+
+ /* a rough size estimate: let's conservatively assume that there */
+ /* is just a single table info in each subfont header (12 + 16*1 = */
+ /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
+ /* size of the TTC header plus `28*count' bytes for all subfont */
+ /* headers */
+ if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
+ return SFNT_Err_Array_Too_Large;
+
/* now read the offsets of each font in the file */
if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
return error;
@@ -536,7 +547,7 @@
FT_UNUSED( face_index );
/* Check parameters */
-
+
{
FT_Int i;
@@ -571,12 +582,12 @@
/* do we have outlines in there? */
#ifdef FT_CONFIG_OPTION_INCREMENTAL
- has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
- tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
- tt_face_lookup_table( face, TTAG_CFF ) != 0 );
+ has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
+ tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );
#else
- has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
- tt_face_lookup_table( face, TTAG_CFF ) != 0 );
+ has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
+ tt_face_lookup_table( face, TTAG_CFF ) != 0 );
#endif
is_apple_sbit = 0;
@@ -651,8 +662,9 @@
if ( face->format_tag == TTAG_true )
{
FT_TRACE2(( "This is an SFNT Mac font.\n" ));
+
has_outline = 0;
- error = SFNT_Err_Ok;
+ error = SFNT_Err_Ok;
}
else
{
@@ -691,9 +703,7 @@
LOAD_( os2 );
if ( error )
{
- if ( error != SFNT_Err_Table_Missing )
- goto Exit;
-
+ /* we treat the table as missing if there are any errors */
face->os2.version = 0xFFFFU;
}
}
@@ -989,40 +999,36 @@
/* table cannot be used to compute the text height reliably! */
/* */
- /* The ascender/descender/height are computed from the OS/2 table */
- /* when found. Otherwise, they're taken from the horizontal */
- /* header. */
- /* */
+ /* The ascender and descender are taken from the `hhea' table. */
+ /* If zero, they are taken from the `OS/2' table. */
root->ascender = face->horizontal.Ascender;
root->descender = face->horizontal.Descender;
- root->height = (FT_Short)( root->ascender - root->descender +
- face->horizontal.Line_Gap );
-
-#if 0
- /* if the line_gap is 0, we add an extra 15% to the text height -- */
- /* this computation is based on various versions of Times New Roman */
- if ( face->horizontal.Line_Gap == 0 )
- root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
-#endif /* 0 */
+ root->height = (FT_Short)( root->ascender - root->descender +
+ face->horizontal.Line_Gap );
-#if 0
- /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
- /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
- if ( face->os2.version != 0xFFFFU && root->ascender )
+ if ( !( root->ascender || root->descender ) )
{
- FT_Int height;
-
+ if ( face->os2.version != 0xFFFFU )
+ {
+ if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
+ {
+ root->ascender = face->os2.sTypoAscender;
+ root->descender = face->os2.sTypoDescender;
- root->ascender = face->os2.sTypoAscender;
- root->descender = -face->os2.sTypoDescender;
+ root->height = (FT_Short)( root->ascender - root->descender +
+ face->os2.sTypoLineGap );
+ }
+ else
+ {
+ root->ascender = (FT_Short)face->os2.usWinAscent;
+ root->descender = -(FT_Short)face->os2.usWinDescent;
- height = root->ascender + root->descender + face->os2.sTypoLineGap;
- if ( height > root->height )
- root->height = height;
+ root->height = (FT_UShort)( root->ascender - root->descender );
+ }
+ }
}
-#endif /* 0 */
root->max_advance_width = face->horizontal.advance_Width_Max;
root->max_advance_height = (FT_Short)( face->vertical_info
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 1c174af..5fb9aea 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -384,6 +384,10 @@
entry = face->dir_tables;
+ FT_TRACE2(( "\n"
+ " tag offset length checksum\n"
+ " ----------------------------------\n" ));
+
for ( nn = 0; nn < sfnt.num_tables; nn++ )
{
entry->Tag = FT_GET_TAG4();
@@ -396,13 +400,14 @@
continue;
else
{
- FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
+ 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->Length,
+ entry->CheckSum ));
entry++;
}
}
@@ -680,9 +685,9 @@
/* broken fonts like `Keystrokes MT' :-( */
/* */
/* We allocate 64 function entries by default when */
- /* the maxFunctionDefs field is null. */
+ /* the maxFunctionDefs value is smaller. */
- if ( maxProfile->maxFunctionDefs == 0 )
+ if ( maxProfile->maxFunctionDefs < 64 )
maxProfile->maxFunctionDefs = 64;
/* we add 4 phantom points later */
@@ -1208,7 +1213,7 @@
FT_Memory memory = stream->memory;
FT_UInt j,num_ranges;
- TT_GaspRange gaspranges;
+ TT_GaspRange gaspranges = NULL;
/* the gasp table is optional */
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 53e6ac7..73ac8b2 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, 2007, 2008, 2009 by */
+/* Copyright 2006-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -163,7 +163,7 @@
{
FT_TRACE0(( "tt_face_load_hmtx:"
" %cmtx has more metrics than glyphs.\n",
- vertical ? "v" : "h" ));
+ vertical ? 'v' : 'h' ));
/* Adobe simply ignores this problem. So we shall do the same. */
#if 0
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index aa0bf1e..6f4bb1d 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-2001, 2002, 2003, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,6 +26,7 @@
#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include "ttpost.h"
@@ -153,7 +154,8 @@
static FT_Error
load_format_20( TT_Face face,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_Long post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -230,13 +232,46 @@
FT_UInt len;
- if ( FT_READ_BYTE ( len ) ||
- FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
- FT_STREAM_READ ( name_strings[n], len ) )
+ if ( FT_STREAM_POS() >= post_limit )
+ break;
+ else
+ {
+ FT_TRACE6(( "load_format_20: %d byte left in post table\n",
+ post_limit - FT_STREAM_POS() ));
+
+ if ( FT_READ_BYTE( len ) )
+ goto Fail1;
+ }
+
+ if ( (FT_Int)len > post_limit ||
+ FT_STREAM_POS() > post_limit - (FT_Int)len )
+ {
+ 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() );
+ }
+
+ if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
+ FT_STREAM_READ( name_strings[n], len ) )
goto Fail1;
name_strings[n][len] = '\0';
}
+
+ if ( n < num_names )
+ {
+ FT_ERROR(( "load_format_20:"
+ " all entries in post table are already parsed,"
+ " using NULL names for gid %d - %d\n",
+ n, num_names - 1 ));
+ for ( ; n < num_names; n++ )
+ if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
+ goto Fail1;
+ else
+ name_strings[n][0] = '\0';
+ }
}
/* all right, set table fields and exit successfully */
@@ -271,7 +306,8 @@
static FT_Error
load_format_25( TT_Face face,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_Long post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -279,6 +315,8 @@
FT_Int num_glyphs;
FT_Char* offset_table = 0;
+ FT_UNUSED( post_limit );
+
/* UNDOCUMENTED! This value appears only in the Apple TT specs. */
if ( FT_READ_USHORT( num_glyphs ) )
@@ -338,16 +376,20 @@
FT_Stream stream;
FT_Error error;
FT_Fixed format;
+ FT_ULong post_len;
+ FT_Long post_limit;
/* get a stream for the face's resource */
stream = face->root.stream;
/* seek to the beginning of the PS names table */
- error = face->goto_table( face, TTAG_post, stream, 0 );
+ error = face->goto_table( face, TTAG_post, stream, &post_len );
if ( error )
goto Exit;
+ post_limit = FT_STREAM_POS() + post_len;
+
format = face->postscript.FormatType;
/* go to beginning of subtable */
@@ -356,9 +398,9 @@
/* now read postscript table */
if ( format == 0x00020000L )
- error = load_format_20( face, stream );
+ error = load_format_20( face, stream, post_limit );
else if ( format == 0x00028000L )
- error = load_format_25( face, stream );
+ error = load_format_25( face, stream, post_limit );
else
error = SFNT_Err_Invalid_File_Format;
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index faa8f88..283ba7e 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -1343,7 +1343,7 @@
/* All right, we have a compound format. First of all, read */
/* the array of elements. */
{
- TT_SBit_Component components;
+ TT_SBit_Component components = NULL;
TT_SBit_Component comp;
FT_UShort num_components, count;
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 0b94143..40de269 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2000-2003, 2005-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -187,7 +187,7 @@ typedef ptrdiff_t FT_PtrDist;
shift_, \
delta_ \
};
-
+
#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \
raster_new_, raster_reset_, \
raster_set_mode_, raster_render_, \
@@ -354,8 +354,6 @@ typedef ptrdiff_t FT_PtrDist;
int band_size;
int band_shoot;
- int conic_level;
- int cubic_level;
ft_jmp_buf jump_buffer;
@@ -879,55 +877,31 @@ typedef ptrdiff_t FT_PtrDist;
FT_Vector* arc;
- dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
- if ( dy < 0 )
- dy = -dy;
+ arc = ras.bez_stack;
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control->x );
+ arc[1].y = UPSCALE( control->y );
+ arc[2].x = ras.x;
+ arc[2].y = ras.y;
+
+ dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+ dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
if ( dx < dy )
dx = dy;
- level = 1;
- dx = dx / ras.conic_level;
- while ( dx > 0 )
+ level = 0;
+ while ( dx > ONE_PIXEL / 6 )
{
dx >>= 2;
level++;
}
- /* a shortcut to speed things up */
- if ( level <= 1 )
- {
- /* we compute the mid-point directly in order to avoid */
- /* calling gray_split_conic() */
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
- mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
- }
-
- arc = ras.bez_stack;
levels = ras.lev_stack;
- top = 0;
levels[0] = level;
+ top = 0;
- arc[0].x = UPSCALE( to->x );
- arc[0].y = UPSCALE( to->y );
- arc[1].x = UPSCALE( control->x );
- arc[1].y = UPSCALE( control->y );
- arc[2].x = ras.x;
- arc[2].y = ras.y;
-
- while ( top >= 0 )
+ do
{
level = levels[top];
if ( level > 1 )
@@ -957,24 +931,11 @@ typedef ptrdiff_t FT_PtrDist;
}
Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
-
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+ top--;
+ arc -= 2;
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
- mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- top--;
- arc -= 2;
- }
- }
-
- return;
+ } while ( top >= 0 );
}
@@ -1011,55 +972,8 @@ typedef ptrdiff_t FT_PtrDist;
const FT_Vector* control2,
const FT_Vector* to )
{
- int top, level;
- int* levels;
FT_Vector* arc;
- int mid_x = ( DOWNSCALE( ras.x ) + to->x +
- 3 * (control1->x + control2->x ) ) / 8;
- int mid_y = ( DOWNSCALE( ras.y ) + to->y +
- 3 * (control1->y + control2->y ) ) / 8;
- TPos dx = DOWNSCALE( ras.x ) + to->x - ( mid_x << 1 );
- TPos dy = DOWNSCALE( ras.y ) + to->y - ( mid_y << 1 );
-
-
- if ( dx < 0 )
- dx = -dx;
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
-
- level = 1;
- dx /= ras.cubic_level;
- while ( dx > 0 )
- {
- dx >>= 2;
- level++;
- }
-
- if ( level <= 1 )
- {
- TPos to_x, to_y;
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
-
- /* Recalculation of midpoint is needed only if */
- /* UPSCALE and DOWNSCALE have any effect. */
-
-#if ( PIXEL_BITS != 6 )
- mid_x = ( ras.x + to_x +
- 3 * UPSCALE( control1->x + control2->x ) ) / 8;
- mid_y = ( ras.y + to_y +
- 3 * UPSCALE( control1->y + control2->y ) ) / 8;
-#endif
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
- }
arc = ras.bez_stack;
arc[0].x = UPSCALE( to->x );
@@ -1071,58 +985,127 @@ typedef ptrdiff_t FT_PtrDist;
arc[3].x = ras.x;
arc[3].y = ras.y;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
-
- while ( top >= 0 )
+ for (;;)
{
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
+ /* Check that the arc crosses the current band. */
+ TPos min, max, y;
- min = max = arc[0].y;
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[3].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
- goto Draw;
- gray_split_cubic( arc );
- arc += 3;
- top ++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
- }
+ min = max = arc[0].y;
- Draw:
- {
- TPos to_x, to_y;
+ y = arc[1].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
+ y = arc[2].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
- mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+ y = arc[3].y;
+ if ( y < min )
+ min = y;
+ if ( y > max )
+ max = y;
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
- top --;
- arc -= 3;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+ goto Draw;
+
+ /* Decide whether to split or draw. See `Rapid Termination */
+ /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
+ /* F. Hain, at */
+ /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
+
+ {
+ TPos dx, dy, dx_, dy_;
+ TPos dx1, dy1, dx2, dy2;
+ TPos L, s, s_limit;
+
+
+ /* 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;
+
+ /* 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;
+
+ /* Avoid possible arithmetic overflow below by splitting. */
+ if ( L > 32767 )
+ goto Split;
+
+ /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+ s_limit = L * (TPos)( ONE_PIXEL / 6 );
+
+ /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+ dx1 = arc[1].x - arc[0].x;
+ dy1 = arc[1].y - arc[0].y;
+ s = FT_ABS( dy * dx1 - dx * dy1 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+ dx2 = arc[2].x - arc[0].x;
+ dy2 = arc[2].y - arc[0].y;
+ s = FT_ABS( dy * dx2 - dx * dy2 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* If P1 or P2 is outside P0-P3, split the curve. */
+ if ( dy * dy1 + dx * dx1 < 0 ||
+ dy * dy2 + dx * dx2 < 0 ||
+ dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||
+ dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )
+ goto Split;
+
+ /* No reason to split. */
+ goto Draw;
}
- }
- return;
- }
+ Split:
+ gray_split_cubic( arc );
+ arc += 3;
+ continue;
+ Draw:
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+
+ if ( arc == ras.bez_stack )
+ return;
+
+ arc -= 3;
+ }
+ }
static int
@@ -1760,25 +1743,6 @@ typedef ptrdiff_t FT_PtrDist;
ras.count_ex = ras.max_ex - ras.min_ex;
ras.count_ey = ras.max_ey - ras.min_ey;
- /* simple heuristic used to speed up the bezier decomposition -- see */
- /* the code in gray_render_conic() and gray_render_cubic() for more */
- /* details */
- ras.conic_level = 32;
- ras.cubic_level = 16;
-
- {
- int level = 0;
-
-
- if ( ras.count_ex > 24 || ras.count_ey > 24 )
- level++;
- if ( ras.count_ex > 120 || ras.count_ey > 120 )
- level++;
-
- ras.conic_level <<= level;
- ras.cubic_level <<= level;
- }
-
/* set up vertical bands */
num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
if ( num_bands == 0 )
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 7d16b94..1350a56 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */
+/* Copyright 2000-2006, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -105,7 +105,10 @@
FT_Error error;
FT_Outline* outline = NULL;
FT_BBox cbox;
- FT_UInt width, height, height_org, width_org, pitch;
+ FT_UInt width, height, pitch;
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+ FT_UInt height_org, width_org;
+#endif
FT_Bitmap* bitmap;
FT_Memory memory;
FT_Int hmul = mode == FT_RENDER_MODE_LCD;
@@ -140,13 +143,33 @@
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
- width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
- height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+ 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 ));
+ return Smooth_Err_Raster_Overflow;
+ }
+ else
+ width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
+
+ 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 ));
+ return Smooth_Err_Raster_Overflow;
+ }
+ else
+ height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
+
bitmap = &slot->bitmap;
memory = render->root.memory;
+#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 )
@@ -202,7 +225,7 @@
/* but we care realistic cases only. Always pitch <= width. */
if ( width > 0x7FFFU || height > 0x7FFFU )
{
- FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n",
+ FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
width, height ));
return Smooth_Err_Raster_Overflow;
}
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index d723b57..e70a611 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,8 +4,7 @@
/* */
/* TrueType font driver implementation (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -135,8 +134,6 @@
{
FT_UInt nn;
TT_Face face = (TT_Face) ttface;
- FT_Bool check = FT_BOOL(
- !( flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) );
/* XXX: TODO: check for sbits */
@@ -149,7 +146,7 @@
FT_UShort ah;
- TT_Get_VMetrics( face, start + nn, check, &tsb, &ah );
+ TT_Get_VMetrics( face, start + nn, &tsb, &ah );
advances[nn] = ah;
}
}
@@ -161,7 +158,7 @@
FT_UShort aw;
- TT_Get_HMetrics( face, start + nn, check, &lsb, &aw );
+ TT_Get_HMetrics( face, start + nn, &lsb, &aw );
advances[nn] = aw;
}
}
@@ -249,7 +246,10 @@
FT_Request_Metrics( size->face, req );
if ( FT_IS_SCALABLE( size->face ) )
+ {
error = tt_size_reset( ttsize );
+ ttsize->root.metrics = ttsize->metrics;
+ }
return error;
}
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 1b496c0..f35521e 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,8 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -47,7 +46,7 @@
/*************************************************************************/
/* */
- /* Composite font flags. */
+ /* Composite glyph flags. */
/* */
#define ARGS_ARE_WORDS 0x0001
#define ARGS_ARE_XY_VALUES 0x0002
@@ -66,22 +65,16 @@
/*************************************************************************/
/* */
- /* Returns the horizontal metrics in font units for a given glyph. If */
- /* `check' is true, take care of monospaced fonts by returning the */
- /* advance width maximum. */
+ /* Return the horizontal metrics in font units for a given glyph. */
/* */
FT_LOCAL_DEF( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw )
{
( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
- if ( check && face->postscript.isFixedPitch )
- *aw = face->horizontal.advance_Width_Max;
-
FT_TRACE5(( " advance width (font units): %d\n", *aw ));
FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
}
@@ -89,7 +82,7 @@
/*************************************************************************/
/* */
- /* Returns the vertical metrics in font units for a given glyph. */
+ /* 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 */
@@ -97,18 +90,12 @@
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* */
- /* The monospace `check' is probably not meaningful here, but we leave */
- /* it in for a consistent interface. */
- /* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah )
{
- FT_UNUSED( check );
-
if ( face->vertical_info )
( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
@@ -151,13 +138,9 @@
TT_Get_HMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing,
&advance_width );
TT_Get_VMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&top_bearing,
&advance_height );
@@ -1656,23 +1639,7 @@
/* get the device-independent horizontal advance; it is scaled later */
/* by the base layer. */
- {
- FT_Pos advance = loader->linear;
-
-
- /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
- /* correctly support DynaLab fonts, which have an incorrect */
- /* `advance_Width_Max' field! It is used, to my knowledge, */
- /* exclusively in the X-TrueType font server. */
- /* */
- if ( face->postscript.isFixedPitch &&
- ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- advance = face->horizontal.advance_Width_Max;
-
- /* we need to return the advance in font units in linearHoriAdvance, */
- /* it will be scaled later by the base layer. */
- glyph->linearHoriAdvance = advance;
- }
+ glyph->linearHoriAdvance = loader->linear;
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
@@ -1869,6 +1836,7 @@
{
TT_Face face;
FT_Stream stream;
+ FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
face = (TT_Face)glyph->face;
@@ -1887,7 +1855,9 @@
if ( !size->cvt_ready )
{
- FT_Error error = tt_size_ready_bytecode( size );
+ FT_Error error = tt_size_ready_bytecode( size, pedantic );
+
+
if ( error )
return error;
}
@@ -1910,11 +1880,14 @@
FT_UInt i;
+ FT_TRACE4(( "tt_loader_init: grayscale change,"
+ " re-executing `prep' table\n" ));
+
exec->grayscale = grayscale;
for ( i = 0; i < size->cvt_size; i++ )
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size );
+ tt_size_run_prep( size, pedantic );
}
/* see whether the cvt program has disabled hinting */
@@ -2044,9 +2017,6 @@
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
loader.vadvance;
- if ( face->postscript.isFixedPitch &&
- ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
}
return TT_Err_Ok;
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 958d67d..05f7588 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 by */
+/* Copyright 1996-2006, 2008, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -37,14 +37,12 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw );
FT_LOCAL( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah );
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 653d9d5..37bbe6d 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -123,14 +123,14 @@
ft_var_readpackedpoints( FT_Stream stream,
FT_UInt *point_cnt )
{
- FT_UShort *points;
+ FT_UShort *points = NULL;
FT_Int n;
FT_Int runcnt;
FT_Int i;
FT_Int j;
FT_Int first;
FT_Memory memory = stream->memory;
- FT_Error error = TT_Err_Ok;
+ FT_Error error = TT_Err_Ok;
FT_UNUSED( error );
@@ -154,7 +154,7 @@
runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
first = points[i++] = FT_GET_USHORT();
- if ( runcnt < 1 )
+ if ( runcnt < 1 || i + runcnt >= n )
goto Exit;
/* first point not included in runcount */
@@ -165,7 +165,7 @@
{
first = points[i++] = FT_GET_BYTE();
- if ( runcnt < 1 )
+ if ( runcnt < 1 || i + runcnt >= n )
goto Exit;
for ( j = 0; j < runcnt; ++j )
@@ -622,7 +622,7 @@
FT_Error error = TT_Err_Ok;
FT_ULong fvar_start;
FT_Int i, j;
- FT_MM_Var* mmvar;
+ FT_MM_Var* mmvar = NULL;
FT_Fixed* next_coords;
FT_String* next_name;
FT_Var_Axis* a;
@@ -1325,7 +1325,7 @@
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
- FT_Vector* delta_xy;
+ FT_Vector* delta_xy = NULL;
FT_Error error;
FT_ULong glyph_start;
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index d22e94f..d568926 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,8 +4,7 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 */
+/* Copyright 1996-2011 */
/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -478,8 +477,7 @@
return TT_Err_Ok;
Fail_Memory:
- FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
- (FT_Long)exec ));
+ FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
TT_Done_Context( exec );
return error;
@@ -596,6 +594,12 @@
exec->storage = size->storage;
exec->twilight = size->twilight;
+
+ /* In case of multi-threading it can happen that the old size object */
+ /* no longer exists, thus we must clear all glyph zone references. */
+ ft_memset( &exec->zp0, 0, sizeof ( exec->zp0 ) );
+ exec->zp1 = exec->zp0;
+ exec->zp2 = exec->zp0;
}
/* XXX: We reserve a little more elements on the stack to deal safely */
@@ -981,8 +985,8 @@
/* INS_$83 */ PACK( 0, 0 ),
/* INS_$84 */ PACK( 0, 0 ),
/* ScanCTRL */ PACK( 1, 0 ),
- /* SDVPTL[0] */ PACK( 2, 0 ),
- /* SDVPTL[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 ),
@@ -3162,44 +3166,54 @@
args[0] = CUR.top;
-#define DO_CINDEX \
- { \
- FT_Long L; \
- \
- \
- L = args[0]; \
- \
- if ( L <= 0 || L > CUR.args ) \
- CUR.error = TT_Err_Invalid_Reference; \
- else \
- args[0] = CUR.stack[CUR.args - L]; \
- }
-
-
-#define DO_JROT \
- if ( args[1] != 0 ) \
- { \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
- CUR.step_ins = FALSE; \
- }
-
-
-#define DO_JMPR \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
+#define DO_CINDEX \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ \
+ if ( L <= 0 || L > CUR.args ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ CUR.error = TT_Err_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 = TT_Err_Bad_Argument; \
+ CUR.IP += args[0]; \
+ if ( CUR.IP < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_JMPR \
+ if ( args[0] == 0 && CUR.args == 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.IP += args[0]; \
+ if ( CUR.IP < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
CUR.step_ins = FALSE;
-#define DO_JROF \
- if ( args[1] == 0 ) \
- { \
- CUR.IP += args[0]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
- CUR.step_ins = FALSE; \
+#define DO_JROF \
+ if ( args[1] == 0 ) \
+ { \
+ if ( args[0] == 0 && CUR.args == 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.IP += args[0]; \
+ if ( CUR.IP < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.step_ins = FALSE; \
}
@@ -4381,17 +4395,19 @@
if ( L <= 0 || L > CUR.args )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
}
+ else
+ {
+ K = CUR.stack[CUR.args - L];
- K = CUR.stack[CUR.args - L];
-
- FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
- &CUR.stack[CUR.args - L + 1],
- ( L - 1 ) );
+ FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
+ &CUR.stack[CUR.args - L + 1],
+ ( L - 1 ) );
- CUR.stack[CUR.args - 1] = K;
+ CUR.stack[CUR.args - 1] = K;
+ }
}
@@ -5034,12 +5050,8 @@
if ( BOUNDSL( L, CUR.zp2.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- else
- R = 0;
+ R = 0;
}
else
{
@@ -5119,10 +5131,7 @@
BOUNDS( K, CUR.zp1.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
D = 0;
}
else
@@ -5460,8 +5469,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -5484,6 +5494,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5671,8 +5682,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
@@ -5698,6 +5710,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5795,7 +5808,16 @@
if ( CUR.GS.gep2 == 0 && CUR.zp2.n_points > 0 )
last_point = (FT_UShort)( CUR.zp2.n_points - 1 );
else if ( CUR.GS.gep2 == 1 && CUR.zp2.n_contours > 0 )
+ {
last_point = (FT_UShort)( CUR.zp2.contours[CUR.zp2.n_contours - 1] );
+
+ if ( BOUNDS( last_point, CUR.zp2.n_points ) )
+ {
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ return;
+ }
+ }
else
last_point = 0;
@@ -5823,8 +5845,9 @@
if ( CUR.top < CUR.GS.loop + 1 )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
@@ -5868,6 +5891,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5982,7 +6006,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: UNDOCUMENTED! */
@@ -6028,6 +6052,7 @@
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+ Fail:
CUR.GS.rp0 = point;
CUR.GS.rp1 = point;
}
@@ -6053,7 +6078,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: Is there some undocumented feature while in the */
@@ -6138,6 +6163,7 @@
CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
CUR.GS.rp2 = point;
@@ -6175,7 +6201,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( !cvtEntry )
@@ -6230,8 +6256,22 @@
/* refer to the same zone. */
if ( CUR.GS.gep0 == CUR.GS.gep1 )
- if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+ {
+ /* XXX: According to Greg Hitchcock, the following wording is */
+ /* the right one: */
+ /* */
+ /* When the absolute difference between the value in */
+ /* the table [CVT] and the measurement directly from */
+ /* the outline is _greater_ than the cut_in value, the */
+ /* outline measurement is used. */
+ /* */
+ /* This is from `instgly.doc'. The description in */
+ /* `ttinst2.doc', version 1.66, is thus incorrect since */
+ /* it implies `>=' instead of `>'. */
+
+ if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
cvt_dist = org_dist;
+ }
distance = CUR_Func_round(
cvt_dist,
@@ -6260,6 +6300,7 @@
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
if ( ( CUR.opcode & 16 ) != 0 )
@@ -6290,7 +6331,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -6318,6 +6359,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6459,8 +6501,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
/*
@@ -6474,7 +6517,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( twilight )
@@ -6539,6 +6582,8 @@
CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
}
+
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6773,12 +6818,11 @@
{
if ( ( CUR.pts.tags[point] & mask ) != 0 )
{
- if ( point > 0 )
- _iup_worker_interpolate( &V,
- cur_touched + 1,
- point - 1,
- cur_touched,
- point );
+ _iup_worker_interpolate( &V,
+ cur_touched + 1,
+ point - 1,
+ cur_touched,
+ point );
cur_touched = point;
}
@@ -6832,8 +6876,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6849,8 +6894,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -6899,6 +6946,7 @@
CUR.error = TT_Err_Invalid_Reference;
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -6926,8 +6974,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6942,8 +6991,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -6991,6 +7042,7 @@
}
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -7452,8 +7504,19 @@
/* One can also interpret it as the index of the last argument. */
if ( CUR.args < 0 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- goto LErrorLabel_;
+ FT_UShort i;
+
+
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_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;
}
CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
@@ -7490,7 +7553,7 @@
case 0x04: /* SFvTCA y */
case 0x05: /* SFvTCA x */
{
- FT_Short AA, BB;
+ FT_Short AA, BB;
AA = (FT_Short)( ( opcode & 1 ) << 14 );
@@ -8128,6 +8191,15 @@
*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 )
+ {
+ FT_TRACE1(( " The interpreter returned error 0x%x\n", CUR.error ));
+ exc->size->cvt_ready = FALSE;
+ }
+
return CUR.error;
}
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 11d662d..d77c3c4 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
/* */
/* Objects manager (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -146,28 +146,28 @@
/* This list shall be expanded as we find more of them. */
static FT_Bool
- tt_check_trickyness( FT_String* name )
+ tt_check_trickyness_family( FT_String* name )
{
+
#define TRICK_NAMES_MAX_CHARACTERS 16
-#define TRICK_NAMES_COUNT 7
- static const char trick_names[TRICK_NAMES_COUNT][TRICK_NAMES_MAX_CHARACTERS+1] =
+#define TRICK_NAMES_COUNT 8
+
+ static const char trick_names[TRICK_NAMES_COUNT]
+ [TRICK_NAMES_MAX_CHARACTERS + 1] =
{
"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 */
};
+
int nn;
- if ( !name )
- return FALSE;
-
- /* Note that we only check the face name at the moment; it might */
- /* be worth to do more checks for a few special cases. */
for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
if ( ft_strstr( name, trick_names[nn] ) )
return TRUE;
@@ -176,6 +176,287 @@
}
+ /* XXX: This function should be in the `sfnt' module. */
+
+ /* Some PDF generators clear the checksums in the TrueType header table. */
+ /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */
+ /* Printer clears the entries for subsetted subtables. We thus have to */
+ /* recalculate the checksums where necessary. */
+
+ static FT_UInt32
+ tt_synth_sfnt_checksum( FT_Stream stream,
+ FT_ULong length )
+ {
+ FT_Error error;
+ FT_UInt32 checksum = 0;
+ int i;
+
+
+ if ( FT_FRAME_ENTER( length ) )
+ return 0;
+
+ 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 ) );
+
+ FT_FRAME_EXIT();
+
+ return checksum;
+ }
+
+
+ /* XXX: This function should be in the `sfnt' module. */
+
+ static FT_ULong
+ tt_get_sfnt_checksum( TT_Face face,
+ FT_UShort i )
+ {
+#if 0 /* if we believe the written value, use following part. */
+ if ( face->dir_tables[i].CheckSum )
+ return face->dir_tables[i].CheckSum;
+#endif
+
+ if ( !face->goto_table )
+ return 0;
+
+ if ( face->goto_table( face,
+ face->dir_tables[i].Tag,
+ face->root.stream,
+ NULL ) )
+ return 0;
+
+ return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
+ face->dir_tables[i].Length );
+ }
+
+
+ typedef struct tt_sfnt_id_rec_
+ {
+ FT_ULong CheckSum;
+ FT_ULong Length;
+
+ } tt_sfnt_id_rec;
+
+
+ static FT_Bool
+ tt_check_trickyness_sfnt_ids( TT_Face face )
+ {
+#define TRICK_SFNT_IDS_PER_FACE 3
+#define TRICK_SFNT_IDS_NUM_FACES 13
+
+ static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
+ [TRICK_SFNT_IDS_PER_FACE] = {
+
+#define TRICK_SFNT_ID_cvt 0
+#define TRICK_SFNT_ID_fpgm 1
+#define TRICK_SFNT_ID_prep 2
+
+ { /* MingLiU 1995 */
+ { 0x05bcf058, 0x000002e4 }, /* cvt */
+ { 0x28233bf1, 0x000087c4 }, /* fpgm */
+ { 0xa344a1ea, 0x000001e1 } /* prep */
+ },
+ { /* MingLiU 1996- */
+ { 0x05bcf058, 0x000002e4 }, /* cvt */
+ { 0x28233bf1, 0x000087c4 }, /* fpgm */
+ { 0xa344a1eb, 0x000001e1 } /* prep */
+ },
+ { /* DFKaiShu */
+ { 0x11e5ead4, 0x00000350 }, /* cvt */
+ { 0x5a30ca3b, 0x00009063 }, /* fpgm */
+ { 0x13a42602, 0x0000007e } /* prep */
+ },
+ { /* HuaTianKaiTi */
+ { 0xfffbfffc, 0x00000008 }, /* cvt */
+ { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */
+ { 0x70020112, 0x00000008 } /* prep */
+ },
+ { /* HuaTianSongTi */
+ { 0xfffbfffc, 0x00000008 }, /* cvt */
+ { 0x0a5a0483, 0x00017c39 }, /* fpgm */
+ { 0x70020112, 0x00000008 } /* prep */
+ },
+ { /* NEC fadpop7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xa39b58e3, 0x0000117c } /* prep */
+ },
+ { /* NEC fadrei5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x33c41652, 0x000000e5 }, /* fpgm */
+ { 0x26d6c52a, 0x00000f6a } /* prep */
+ },
+ { /* NEC fangot7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x6db1651d, 0x0000019d }, /* fpgm */
+ { 0x6c6e4b03, 0x00002492 } /* prep */
+ },
+ { /* NEC fangyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xde51fad0, 0x0000117c } /* prep */
+ },
+ { /* NEC fankyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x85e47664, 0x000000e5 }, /* fpgm */
+ { 0xa6c62831, 0x00001caa } /* prep */
+ },
+ { /* NEC fanrgo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x2d891cfd, 0x0000019d }, /* fpgm */
+ { 0xa0604633, 0x00001de8 } /* prep */
+ },
+ { /* NEC fangot5.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40aa774c, 0x000001cb }, /* fpgm */
+ { 0x9b5caa96, 0x00001f9a } /* prep */
+ },
+ { /* NEC fanmin3.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x0d3de9cb, 0x00000141 }, /* fpgm */
+ { 0xd4127766, 0x00002280 } /* prep */
+ }
+ };
+
+ FT_ULong checksum;
+ int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+ FT_Bool has_cvt, has_fpgm, has_prep;
+ FT_UShort i;
+ int j, k;
+
+
+ FT_MEM_SET( num_matched_ids, 0,
+ sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+ has_cvt = FALSE;
+ has_fpgm = FALSE;
+ has_prep = FALSE;
+
+ for ( i = 0; i < face->num_tables; i++ )
+ {
+ checksum = 0;
+
+ switch( face->dir_tables[i].Tag )
+ {
+ case TTAG_cvt:
+ k = TRICK_SFNT_ID_cvt;
+ has_cvt = TRUE;
+ break;
+
+ case TTAG_fpgm:
+ k = TRICK_SFNT_ID_fpgm;
+ has_fpgm = TRUE;
+ break;
+
+ case TTAG_prep:
+ k = TRICK_SFNT_ID_prep;
+ has_prep = TRUE;
+ break;
+
+ default:
+ continue;
+ }
+
+ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+ if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
+ {
+ if ( !checksum )
+ checksum = tt_get_sfnt_checksum( face, i );
+
+ if ( sfnt_id[j][k].CheckSum == checksum )
+ num_matched_ids[j]++;
+
+ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+ return TRUE;
+ }
+ }
+
+ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+ {
+ if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
+ num_matched_ids[j] ++;
+ if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
+ num_matched_ids[j] ++;
+ if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
+ num_matched_ids[j] ++;
+ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ static FT_Bool
+ tt_check_trickyness( FT_Face face )
+ {
+ if ( !face )
+ return FALSE;
+
+ /* For first, check the face name for quick check. */
+ if ( face->family_name &&
+ tt_check_trickyness_family( face->family_name ) )
+ return TRUE;
+
+ /* Type42 fonts may lack `name' tables, we thus try to identify */
+ /* tricky fonts by checking the checksums of Type42-persistent */
+ /* sfnt tables (`cvt', `fpgm', and `prep'). */
+ if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
+ return TRUE;
+
+ return FALSE;
+ }
+
+
+ /* Check whether `.notdef' is the only glyph in the `loca' table. */
+ static FT_Bool
+ tt_check_single_notdef( FT_Face ttface )
+ {
+ FT_Bool result = FALSE;
+
+ TT_Face face = (TT_Face)ttface;
+ FT_UInt asize;
+ FT_ULong i;
+ FT_ULong glyph_index = 0;
+ FT_UInt count = 0;
+
+
+ for( i = 0; i < face->num_locations; i++ )
+ {
+ tt_face_get_location( face, i, &asize );
+ if ( asize > 0 )
+ {
+ count += 1;
+ if ( count > 1 )
+ break;
+ glyph_index = i;
+ }
+ }
+
+ /* Only have a single outline. */
+ if ( count == 1 )
+ {
+ if ( glyph_index == 0 )
+ result = TRUE;
+ else
+ {
+ /* FIXME: Need to test glyphname == .notdef ? */
+ FT_Error error;
+ char buf[8];
+
+
+ error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
+ if ( !error &&
+ buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
+ result = TRUE;
+ }
+ }
+
+ return result;
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -250,7 +531,7 @@
if ( error )
goto Exit;
- if ( tt_check_trickyness( ttface->family_name ) )
+ if ( tt_check_trickyness( ttface ) )
ttface->face_flags |= FT_FACE_FLAG_TRICKY;
error = tt_face_load_hdmx( face, stream );
@@ -271,6 +552,20 @@
if ( !error )
error = tt_face_load_prep( face, stream );
+ /* Check the scalable flag based on `loca'. */
+ if ( !ttface->internal->incremental_interface &&
+ ttface->num_fixed_sizes &&
+ face->glyph_locations &&
+ tt_check_single_notdef( ttface ) )
+ {
+ FT_TRACE5(( "tt_face_init:"
+ " Only the `.notdef' glyph has an outline.\n"
+ " "
+ " Resetting scalable flag to FALSE.\n" ));
+
+ ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+ }
+
#else
if ( !error )
@@ -282,6 +577,19 @@
if ( !error )
error = tt_face_load_prep( face, stream );
+ /* Check the scalable flag based on `loca'. */
+ if ( ttface->num_fixed_sizes &&
+ face->glyph_locations &&
+ tt_check_single_notdef( ttface ) )
+ {
+ FT_TRACE5(( "tt_face_init:"
+ " Only the `.notdef' glyph has an outline.\n"
+ " "
+ " Resetting scalable flag to FALSE.\n" ));
+
+ ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
+ }
+
#endif
}
@@ -394,13 +702,16 @@
/* Run the font program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_fpgm( TT_Size size )
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -418,15 +729,17 @@
TT_Load_Context( exec, face, size );
- exec->callTop = 0;
- exec->top = 0;
+ exec->callTop = 0;
+ exec->top = 0;
exec->period = 64;
exec->phase = 0;
exec->threshold = 0;
exec->instruction_trap = FALSE;
- exec->F_dot_P = 0x10000L;
+ exec->F_dot_P = 0x10000L;
+
+ exec->pedantic_hinting = pedantic;
{
FT_Size_Metrics* metrics = &exec->metrics;
@@ -458,7 +771,11 @@
error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
if ( !error )
+ {
+ FT_TRACE4(( "Executing `fpgm' table.\n" ));
+
error = face->interpreter( exec );
+ }
}
else
error = TT_Err_Ok;
@@ -479,13 +796,16 @@
/* Run the control value program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_prep( TT_Size size )
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -508,6 +828,8 @@
exec->instruction_trap = FALSE;
+ exec->pedantic_hinting = pedantic;
+
TT_Set_CodeRange( exec,
tt_coderange_cvt,
face->cvt_program,
@@ -520,7 +842,11 @@
error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
if ( !error && !size->debug )
+ {
+ FT_TRACE4(( "Executing `prep' table.\n" ));
+
error = face->interpreter( exec );
+ }
}
else
error = TT_Err_Ok;
@@ -582,7 +908,8 @@
/* Initialize bytecode-related fields in the size object. */
/* We do this only if bytecode interpretation is really needed. */
static FT_Error
- tt_size_init_bytecode( FT_Size ftsize )
+ tt_size_init_bytecode( FT_Size ftsize,
+ FT_Bool pedantic )
{
FT_Error error;
TT_Size size = (TT_Size)ftsize;
@@ -655,7 +982,7 @@
}
/* Fine, now run the font program! */
- error = tt_size_run_fpgm( size );
+ error = tt_size_run_fpgm( size, pedantic );
Exit:
if ( error )
@@ -666,14 +993,15 @@
FT_LOCAL_DEF( FT_Error )
- tt_size_ready_bytecode( TT_Size size )
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic )
{
FT_Error error = TT_Err_Ok;
if ( !size->bytecode_ready )
{
- error = tt_size_init_bytecode( (FT_Size)size );
+ error = tt_size_init_bytecode( (FT_Size)size, pedantic );
if ( error )
goto Exit;
}
@@ -705,7 +1033,7 @@
size->GS = tt_default_graphics_state;
- error = tt_size_run_prep( size );
+ error = tt_size_run_prep( size, pedantic );
if ( !error )
size->cvt_ready = 1;
}
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 30c8669..087b3c2 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -390,13 +390,16 @@ FT_BEGIN_HEADER
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_LOCAL( FT_Error )
- tt_size_run_fpgm( TT_Size size );
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_run_prep( TT_Size size );
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_ready_bytecode( TT_Size size );
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic );
#endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index a311b03..818b29d 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2002, 2004-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -110,15 +110,16 @@
face->num_locations = table_len >> shift;
}
- if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
{
FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
- face->num_locations, face->root.num_glyphs ));
+ face->num_locations - 1, face->root.num_glyphs ));
/* we only handle the case where `maxp' gives a larger value */
- if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
{
- FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+ FT_Long new_loca_len =
+ ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
@@ -137,9 +138,15 @@
dist = diff;
}
+ if ( entry == limit )
+ {
+ /* `loca' is the last table */
+ dist = stream->size - pos;
+ }
+
if ( new_loca_len <= dist )
{
- face->num_locations = face->root.num_glyphs;
+ face->num_locations = face->root.num_glyphs + 1;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",
@@ -203,6 +210,26 @@
}
}
+ /* Check broken location data */
+ if ( pos1 >= face->glyf_len )
+ {
+ FT_TRACE1(( "tt_face_get_location:"
+ " too large offset=0x%08lx found for gid=0x%04lx,"
+ " exceeding the end of glyf table (0x%08lx)\n",
+ pos1, gindex, face->glyf_len ));
+ *asize = 0;
+ return 0;
+ }
+
+ if ( pos2 >= face->glyf_len )
+ {
+ FT_TRACE1(( "tt_face_get_location:"
+ " too large offset=0x%08lx found for gid=0x%04lx,"
+ " truncate at the end of glyf table (0x%08lx)\n",
+ pos2, gindex + 1, face->glyf_len ));
+ pos2 = face->glyf_len;
+ }
+
/* The `loca' table must be ordered; it refers to the length of */
/* an entry as the difference between the current and the next */
/* position. However, there do exist (malformed) fonts which */
@@ -287,7 +314,7 @@
FT_Short* limit = cur + face->cvt_size;
- for ( ; cur < limit; cur++ )
+ for ( ; cur < limit; cur++ )
*cur = FT_GET_SHORT();
}