From 6a2b62ec796948e0e2986ce0b099a97add86348f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 9 Aug 2007 21:33:28 +0000 Subject: [PATCH] updated freetype to 2.3.5 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21879 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../libs/freetype2/freetype/config/ftoption.h | 56 +- .../libs/freetype2/freetype/config/ftstdlib.h | 9 - headers/libs/freetype2/freetype/freetype.h | 76 +- headers/libs/freetype2/freetype/ftcache.h | 120 +- headers/libs/freetype2/freetype/fterrdef.h | 6 +- headers/libs/freetype2/freetype/ftmodapi.h | 2 +- headers/libs/freetype2/freetype/ftstroke.h | 12 +- headers/libs/freetype2/freetype/fttypes.h | 7 +- .../libs/freetype2/freetype/internal/ftobjs.h | 19 + .../libs/freetype2/freetype/internal/ftserv.h | 3 +- .../freetype/internal/services/svttcmap.h | 1 + .../freetype/internal/services/svttglyf.h | 48 + headers/libs/freetype2/freetype/tttables.h | 22 +- src/libs/freetype2/autofit/Jamfile | 2 +- src/libs/freetype2/autofit/afcjk.c | 10 +- src/libs/freetype2/autofit/afglobal.c | 28 +- src/libs/freetype2/autofit/afglobal.h | 3 +- src/libs/freetype2/autofit/afhints.c | 510 ++-- src/libs/freetype2/autofit/afhints.h | 8 +- src/libs/freetype2/autofit/afindic.c | 134 + src/libs/freetype2/autofit/afindic.h | 41 + src/libs/freetype2/autofit/aflatin.c | 166 +- src/libs/freetype2/autofit/aflatin2.c | 2286 +++++++++++++++++ src/libs/freetype2/autofit/aflatin2.h | 40 + src/libs/freetype2/autofit/afloader.c | 16 +- src/libs/freetype2/autofit/aftypes.h | 5 + src/libs/freetype2/autofit/autofit.c | 8 +- src/libs/freetype2/autofit/rules.mk | 5 +- src/libs/freetype2/base/Jamfile | 2 +- src/libs/freetype2/base/ftcalc.c | 1 - src/libs/freetype2/base/ftglyph.c | 6 +- src/libs/freetype2/base/ftmac.c | 48 +- src/libs/freetype2/base/ftobjs.c | 67 +- src/libs/freetype2/base/ftoutln.c | 4 +- src/libs/freetype2/base/ftpatent.c | 281 ++ src/libs/freetype2/bdf/bdflib.c | 21 + src/libs/freetype2/cache/ftcbasic.c | 113 +- src/libs/freetype2/cache/ftccache.c | 12 +- src/libs/freetype2/cache/ftccache.h | 5 +- src/libs/freetype2/cache/ftccmap.c | 3 +- src/libs/freetype2/cache/ftcglyph.h | 15 +- src/libs/freetype2/cff/cffgload.c | 126 +- src/libs/freetype2/cff/cffgload.h | 4 +- src/libs/freetype2/cid/cidgload.c | 19 +- src/libs/freetype2/cid/cidparse.c | 9 +- src/libs/freetype2/gzip/adler32.c | 4 +- src/libs/freetype2/gzip/zconf.h | 60 +- src/libs/freetype2/gzip/zutil.h | 2 +- src/libs/freetype2/lzw/ftzopen.c | 174 +- src/libs/freetype2/lzw/ftzopen.h | 14 +- src/libs/freetype2/pfr/pfrcmap.c | 13 +- src/libs/freetype2/pfr/pfrgload.c | 65 +- src/libs/freetype2/pfr/pfrtypes.h | 4 +- src/libs/freetype2/psaux/afmparse.c | 9 +- src/libs/freetype2/psaux/psobjs.c | 66 +- src/libs/freetype2/psaux/t1decode.c | 7 +- src/libs/freetype2/pshinter/pshmod.c | 7 +- src/libs/freetype2/pshinter/pshrec.c | 14 +- src/libs/freetype2/psnames/psmodule.c | 8 +- src/libs/freetype2/sfnt/sfobjs.c | 15 + src/libs/freetype2/sfnt/ttcmap.c | 10 +- src/libs/freetype2/sfnt/ttkern.c | 4 +- src/libs/freetype2/sfnt/ttmtx.c | 37 +- src/libs/freetype2/sfnt/ttsbit0.c | 49 +- src/libs/freetype2/smooth/ftgrays.c | 16 +- src/libs/freetype2/truetype/ttdriver.c | 8 + src/libs/freetype2/truetype/ttgload.c | 139 +- src/libs/freetype2/truetype/ttinterp.c | 32 +- src/libs/freetype2/truetype/ttobjs.c | 13 +- src/libs/freetype2/truetype/ttobjs.h | 6 +- src/libs/freetype2/type1/t1load.c | 36 +- src/libs/freetype2/type1/t1objs.c | 10 +- src/libs/freetype2/type42/t42objs.c | 4 +- src/libs/freetype2/type42/t42parse.c | 36 +- src/libs/freetype2/winfonts/winfnt.c | 324 ++- src/libs/freetype2/winfonts/winfnt.h | 64 +- 76 files changed, 4718 insertions(+), 911 deletions(-) create mode 100644 headers/libs/freetype2/freetype/internal/services/svttglyf.h create mode 100644 src/libs/freetype2/autofit/afindic.c create mode 100644 src/libs/freetype2/autofit/afindic.h create mode 100644 src/libs/freetype2/autofit/aflatin2.c create mode 100644 src/libs/freetype2/autofit/aflatin2.h create mode 100644 src/libs/freetype2/base/ftpatent.c diff --git a/headers/libs/freetype2/freetype/config/ftoption.h b/headers/libs/freetype2/freetype/config/ftoption.h index 7097512699..5f823e89f1 100644 --- a/headers/libs/freetype2/freetype/config/ftoption.h +++ b/headers/libs/freetype2/freetype/config/ftoption.h @@ -302,7 +302,9 @@ FT_BEGIN_HEADER /* The size in bytes of the render pool used by the scan-line converter */ /* to do all of its work. */ /* */ - /* This must be greater than 4KByte. */ + /* This must be greater than 4KByte if you use FreeType to rasterize */ + /* glyphs; otherwise, you may set it to zero to avoid unnecessary */ + /* allocation of the render pool. */ /* */ #define FT_RENDER_POOL_SIZE 16384L @@ -461,12 +463,47 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ - /* Define TT_CONFIG_OPTION_UNPATENTED_HINTING (in addition to */ - /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER) to compile the unpatented */ - /* work-around hinting system. Note that for the moment, the algorithm */ - /* is only used when selected at runtime through the parameter tag */ - /* FT_PARAM_TAG_UNPATENTED_HINTING; or when the debug hook */ - /* FT_DEBUG_HOOK_UNPATENTED_HINTING is globally activated. */ + /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version */ + /* of the TrueType bytecode interpreter is used that doesn't implement */ + /* any of the patented opcodes and algorithms. Note that the */ + /* the TT_CONFIG_OPTION_UNPATENTED_HINTING macro is *ignored* if you */ + /* define TT_CONFIG_OPTION_BYTECODE_INTERPRETER; with other words, */ + /* either define TT_CONFIG_OPTION_BYTECODE_INTERPRETER or */ + /* TT_CONFIG_OPTION_UNPATENTED_HINTING but not both at the same time. */ + /* */ + /* This macro is only useful for a small number of font files (mostly */ + /* for Asian scripts) that require bytecode interpretation to properly */ + /* load glyphs. For all other fonts, this produces unpleasant results, */ + /* thus the unpatented interpreter is never used to load glyphs from */ + /* TrueType fonts unless one of the following two options is used. */ + /* */ + /* - The unpatented interpreter is explicitly activated by the user */ + /* through the FT_PARAM_TAG_UNPATENTED_HINTING parameter tag */ + /* when opening the FT_Face. */ + /* */ + /* - FreeType detects that the FT_Face corresponds to one of the */ + /* `trick' fonts (e.g., `Mingliu') it knows about. The font engine */ + /* contains a hard-coded list of font names and other matching */ + /* parameters (see function `tt_face_init' in file */ + /* `src/truetype/ttobjs.c'). */ + /* */ + /* Here a sample code snippet for using FT_PARAM_TAG_UNPATENTED_HINTING. */ + /* */ + /* { */ + /* FT_Parameter parameter; */ + /* FT_Open_Args open_args; */ + /* */ + /* */ + /* parameter.tag = FT_PARAM_TAG_UNPATENTED_HINTING; */ + /* */ + /* open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; */ + /* open_args.pathname = my_font_pathname; */ + /* open_args.num_params = 1; */ + /* open_args.params = ¶meter; */ + /* */ + /* error = FT_Open_Face( library, &open_args, index, &face ); */ + /* ... */ + /* } */ /* */ #define TT_CONFIG_OPTION_UNPATENTED_HINTING @@ -591,6 +628,11 @@ FT_BEGIN_HEADER /* */ #define AF_CONFIG_OPTION_CJK + /*************************************************************************/ + /* */ + /* Compile autofit module with Indic script support. */ + /* */ +#define AF_CONFIG_OPTION_INDIC /* */ diff --git a/headers/libs/freetype2/freetype/config/ftstdlib.h b/headers/libs/freetype2/freetype/config/ftstdlib.h index 82702d3cd9..f923f3e4cf 100644 --- a/headers/libs/freetype2/freetype/config/ftstdlib.h +++ b/headers/libs/freetype2/freetype/config/ftstdlib.h @@ -78,15 +78,6 @@ /**********************************************************************/ -#include - -#define ft_isalnum isalnum -#define ft_isdigit isdigit -#define ft_islower islower -#define ft_isupper isupper -#define ft_isxdigit isxdigit - - #include #define ft_memchr memchr diff --git a/headers/libs/freetype2/freetype/freetype.h b/headers/libs/freetype2/freetype/freetype.h index 46ef83386b..dbca087e5f 100644 --- a/headers/libs/freetype2/freetype/freetype.h +++ b/headers/libs/freetype2/freetype/freetype.h @@ -648,8 +648,8 @@ FT_BEGIN_HEADER { FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ), - FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), - FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), + FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), + FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), @@ -2111,9 +2111,16 @@ FT_BEGIN_HEADER /* FreeType error code. 0 means success. */ /* */ /* */ - /* If either the horizontal or vertical resolution is zero, it is set */ - /* to a default value of 72dpi. */ + /* If either the character width or height is zero, it is set equal */ + /* to the other value. */ /* */ + /* If either the horizontal or vertical resolution is zero, it is set */ + /* equal to the other value. */ + /* */ + /* A character width or height smaller than 1pt is set to 1pt; if */ + /* both resolution values are zero, they are set to 72dpi. */ + /* */ + FT_EXPORT( FT_Error ) FT_Set_Char_Size( FT_Face face, FT_F26Dot6 char_width, @@ -2731,8 +2738,7 @@ FT_BEGIN_HEADER /* */ /* */ /* Retrieve the ASCII name of a given glyph in a face. This only */ - /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns */ - /* TRUE. */ + /* works for those faces where @FT_HAS_GLYPH_NAMES(face) returns 1. */ /* */ /* */ /* face :: A handle to a source face object. */ @@ -3323,7 +3329,7 @@ FT_BEGIN_HEADER */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 3 -#define FREETYPE_PATCH 4 +#define FREETYPE_PATCH 5 /*************************************************************************/ @@ -3361,6 +3367,62 @@ FT_BEGIN_HEADER FT_Int *aminor, FT_Int *apatch ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Face_CheckTrueTypePatents */ + /* */ + /* */ + /* Parse all bytecode instructions of a TrueType font file to check */ + /* whether any of the patented opcodes are used. This is only useful */ + /* if you want to be able to use the unpatented hinter with */ + /* fonts that do *not* use these opcodes. */ + /* */ + /* Note that this function parses *all* glyph instructions in the */ + /* font file, which may be slow. */ + /* */ + /* */ + /* face :: A face handle. */ + /* */ + /* */ + /* 1 if this is a TrueType font that uses one of the patented */ + /* opcodes, 0 otherwise. */ + /* */ + /* */ + /* 2.3.5 */ + /* */ + FT_EXPORT( FT_Bool ) + FT_Face_CheckTrueTypePatents( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Face_SetUnpatentedHinting */ + /* */ + /* */ + /* Enable or disable the unpatented hinter for a given face. */ + /* Only enable it if you have determined that the face doesn't */ + /* use any patented opcodes (see @FT_Face_CheckTrueTypePatents). */ + /* */ + /* */ + /* face :: A face handle. */ + /* */ + /* value :: New boolean setting. */ + /* */ + /* */ + /* The old setting value. This will always be false if this is not */ + /* a SFNT font, or if the unpatented hinter is not compiled in this */ + /* instance of the library. */ + /* */ + /* */ + /* 2.3.5 */ + /* */ + FT_EXPORT( FT_Bool ) + FT_Face_SetUnpatentedHinting( FT_Face face, + FT_Bool value ); + /* */ diff --git a/headers/libs/freetype2/freetype/ftcache.h b/headers/libs/freetype2/freetype/ftcache.h index 38b956c0ac..721aa16f32 100644 --- a/headers/libs/freetype2/freetype/ftcache.h +++ b/headers/libs/freetype2/freetype/ftcache.h @@ -4,7 +4,7 @@ /* */ /* FreeType Cache subsystem (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -411,14 +411,14 @@ FT_BEGIN_HEADER /* */ /* height :: The character height. */ /* */ - /* pixel :: A Boolean. If TRUE, the `width' and `height' fields */ - /* are interpreted as integer pixel character sizes. */ + /* pixel :: A Boolean. If 1, the `width' and `height' fields are */ + /* interpreted as integer pixel character sizes. */ /* Otherwise, they are expressed as 1/64th of points. */ /* */ - /* x_res :: Only used when `pixel' is FALSE to indicate the */ + /* x_res :: Only used when `pixel' is value 0 to indicate the */ /* horizontal resolution in dpi. */ /* */ - /* y_res :: Only used when `pixel' is FALSE to indicate the */ + /* y_res :: Only used when `pixel' is value 0 to indicate the */ /* vertical resolution in dpi. */ /* */ /* */ @@ -776,6 +776,60 @@ FT_BEGIN_HEADER FTC_Node *anode ); + /*************************************************************************/ + /* */ + /* */ + /* FTC_ImageCache_LookupScaler */ + /* */ + /* */ + /* A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec */ + /* to specify the face ID and its size. */ + /* */ + /* */ + /* cache :: A handle to the source glyph image cache. */ + /* */ + /* scaler :: A pointer to a scaler descriptor. */ + /* */ + /* load_flags :: The corresponding load flags. */ + /* */ + /* gindex :: The glyph index to retrieve. */ + /* */ + /* */ + /* aglyph :: The corresponding @FT_Glyph object. 0 in case of */ + /* failure. */ + /* */ + /* anode :: Used to return the address of of the corresponding */ + /* cache node after incrementing its reference count */ + /* (see note below). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The returned glyph is owned and managed by the glyph image cache. */ + /* Never try to transform or discard it manually! You can however */ + /* create a copy with @FT_Glyph_Copy and modify the new one. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the glyph image, after increasing its reference */ + /* count. This ensures that the node (as well as the @FT_Glyph) will */ + /* always be kept in the cache until you call @FTC_Node_Unref to */ + /* `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the @FT_Glyph could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_LookupScaler( FTC_ImageCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ); + + /*************************************************************************/ /* */ /* */ @@ -930,6 +984,62 @@ FT_BEGIN_HEADER FTC_Node *anode ); + /*************************************************************************/ + /* */ + /* */ + /* FTC_SBitCache_LookupScaler */ + /* */ + /* */ + /* A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec */ + /* to specify the face ID and its size. */ + /* */ + /* */ + /* cache :: A handle to the source sbit cache. */ + /* */ + /* scaler :: A pointer to the scaler descriptor. */ + /* */ + /* load_flags :: The corresponding load flags. */ + /* */ + /* gindex :: The glyph index. */ + /* */ + /* */ + /* sbit :: A handle to a small bitmap descriptor. */ + /* */ + /* anode :: Used to return the address of of the corresponding */ + /* cache node after incrementing its reference count */ + /* (see note below). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The small bitmap descriptor and its bit buffer are owned by the */ + /* cache and should never be freed by the application. They might */ + /* as well disappear from memory on the next cache lookup, so don't */ + /* treat them as persistent data. */ + /* */ + /* The descriptor's `buffer' field is set to 0 to indicate a missing */ + /* glyph bitmap. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the bitmap, after increasing its reference count. */ + /* This ensures that the node (as well as the image) will always be */ + /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the bitmap could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_LookupScaler( FTC_SBitCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FTC_SBit *sbit, + FTC_Node *anode ); + + /* */ #ifdef FT_CONFIG_OPTION_OLD_INTERNALS diff --git a/headers/libs/freetype2/freetype/fterrdef.h b/headers/libs/freetype2/freetype/fterrdef.h index ab8c3f7d92..d7ad256bdb 100644 --- a/headers/libs/freetype2/freetype/fterrdef.h +++ b/headers/libs/freetype2/freetype/fterrdef.h @@ -4,7 +4,7 @@ /* */ /* FreeType error codes (specification). */ /* */ -/* Copyright 2002, 2004, 2006 by */ +/* Copyright 2002, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -230,6 +230,10 @@ "`BBX' field missing" ) FT_ERRORDEF_( Bbx_Too_Big, 0xB7, \ "`BBX' too big" ) + FT_ERRORDEF_( Corrupted_Font_Header, 0xB8, \ + "Font header corrupted or missing fields" ) + FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xB9, \ + "Font glyphs corrupted or missing fields" ) /* END */ diff --git a/headers/libs/freetype2/freetype/ftmodapi.h b/headers/libs/freetype2/freetype/ftmodapi.h index 4628bdf833..9cc32aff4e 100644 --- a/headers/libs/freetype2/freetype/ftmodapi.h +++ b/headers/libs/freetype2/freetype/ftmodapi.h @@ -316,7 +316,7 @@ FT_BEGIN_HEADER /************************************************************************** * * @section: - * ttengine + * truetype_engine * * @title: * The TrueType Engine diff --git a/headers/libs/freetype2/freetype/ftstroke.h b/headers/libs/freetype2/freetype/ftstroke.h index 6e75921a7c..738b43c1ac 100644 --- a/headers/libs/freetype2/freetype/ftstroke.h +++ b/headers/libs/freetype2/freetype/ftstroke.h @@ -297,8 +297,8 @@ FT_BEGIN_HEADER * The source outline. * * opened :: - * A boolean. If TRUE, the outline is treated as an open path - * instead of a closed one. + * A boolean. If 1, the outline is treated as an open path instead + * of a closed one. * * @return: * FreeType error code. 0 means success. @@ -334,7 +334,7 @@ FT_BEGIN_HEADER * A pointer to the start vector. * * open :: - * A boolean. If TRUE, the sub-path is treated as an open one. + * A boolean. If 1, the sub-path is treated as an open one. * * @return: * FreeType error code. 0 means success. @@ -649,7 +649,7 @@ FT_BEGIN_HEADER * A stroker handle. * * destroy :: - * A Boolean. If TRUE, the source glyph object is destroyed + * A Boolean. If 1, the source glyph object is destroyed * on success. * * @return: @@ -682,11 +682,11 @@ FT_BEGIN_HEADER * A stroker handle. * * inside :: - * A Boolean. If TRUE, return the inside border, otherwise + * A Boolean. If 1, return the inside border, otherwise * the outside border. * * destroy :: - * A Boolean. If TRUE, the source glyph object is destroyed + * A Boolean. If 1, the source glyph object is destroyed * on success. * * @return: diff --git a/headers/libs/freetype2/freetype/fttypes.h b/headers/libs/freetype2/freetype/fttypes.h index 44ad625c15..2340bacd31 100644 --- a/headers/libs/freetype2/freetype/fttypes.h +++ b/headers/libs/freetype2/freetype/fttypes.h @@ -4,7 +4,7 @@ /* */ /* FreeType simple types definitions (specification only). */ /* */ -/* Copyright 1996-2001, 2002, 2004, 2006 by */ +/* Copyright 1996-2001, 2002, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -94,7 +94,8 @@ FT_BEGIN_HEADER /* FT_Bool */ /* */ /* */ - /* A typedef of unsigned char, used for simple booleans. */ + /* A typedef of unsigned char, used for simple booleans. As usual, */ + /* values 1 and 0 represent true and false, respectively. */ /* */ typedef unsigned char FT_Bool; @@ -384,7 +385,7 @@ FT_BEGIN_HEADER /*************************************************************************/ /* */ /* */ - /* FT_Data */ + /* FT_Data */ /* */ /* */ /* Read-only binary data represented as a pointer and a length. */ diff --git a/headers/libs/freetype2/freetype/internal/ftobjs.h b/headers/libs/freetype2/freetype/internal/ftobjs.h index 2f497582c2..15b68d63f1 100644 --- a/headers/libs/freetype2/freetype/internal/ftobjs.h +++ b/headers/libs/freetype2/freetype/internal/ftobjs.h @@ -89,6 +89,25 @@ FT_BEGIN_HEADER ft_highpow2( FT_UInt32 value ); + /* + * character classification functions -- since these are used to parse + * font files, we must not use those in which are + * locale-dependent + */ +#define ft_isdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U ) + +#define ft_isxdigit( x ) ( ( (unsigned)(x) - '0' ) < 10U || \ + ( (unsigned)(x) - 'a' ) < 6U || \ + ( (unsigned)(x) - 'A' ) < 6U ) + + /* the next two macros assume ASCII representation */ +#define ft_isupper( x ) ( ( (unsigned)(x) - 'A' ) < 26U ) +#define ft_islower( x ) ( ( (unsigned)(x) - 'a' ) < 26U ) + +#define ft_isalpha( x ) ( ft_isupper( x ) || ft_islower( x ) ) +#define ft_isalnum( x ) ( ft_isdigit( x ) || ft_isalpha( x ) ) + + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ diff --git a/headers/libs/freetype2/freetype/internal/ftserv.h b/headers/libs/freetype2/freetype/internal/ftserv.h index 2666a8746e..45d2fa9183 100644 --- a/headers/libs/freetype2/freetype/internal/ftserv.h +++ b/headers/libs/freetype2/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ /* */ /* The FreeType services (specification only). */ /* */ -/* Copyright 2003, 2004, 2005, 2006 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -315,6 +315,7 @@ FT_BEGIN_HEADER #define FT_SERVICE_TT_CMAP_H #define FT_SERVICE_WINFNT_H #define FT_SERVICE_XFREE86_NAME_H +#define FT_SERVICE_TRUETYPE_GLYF_H /* */ diff --git a/headers/libs/freetype2/freetype/internal/services/svttcmap.h b/headers/libs/freetype2/freetype/internal/services/svttcmap.h index 1ef96b4fca..1e02d15506 100644 --- a/headers/libs/freetype2/freetype/internal/services/svttcmap.h +++ b/headers/libs/freetype2/freetype/internal/services/svttcmap.h @@ -52,6 +52,7 @@ FT_BEGIN_HEADER typedef struct TT_CMapInfo_ { FT_ULong language; + FT_Long format; } TT_CMapInfo; diff --git a/headers/libs/freetype2/freetype/internal/services/svttglyf.h b/headers/libs/freetype2/freetype/internal/services/svttglyf.h new file mode 100644 index 0000000000..e57d484b7e --- /dev/null +++ b/headers/libs/freetype2/freetype/internal/services/svttglyf.h @@ -0,0 +1,48 @@ +/***************************************************************************/ +/* */ +/* svttglyf.h */ +/* */ +/* The FreeType TrueType glyph service. */ +/* */ +/* Copyright 2007 by David Turner. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* 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 __SVTTGLYF_H__ +#define __SVTTGLYF_H__ + +#include FT_INTERNAL_SERVICE_H +#include FT_TRUETYPE_TABLES_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_TT_GLYF "tt-glyf" + + + typedef FT_ULong + (*TT_Glyf_GetLocationFunc)( FT_Face face, + FT_UInt gindex, + FT_ULong *psize ); + + FT_DEFINE_SERVICE( TTGlyf ) + { + TT_Glyf_GetLocationFunc get_location; + }; + + /* */ + + +FT_END_HEADER + +#endif /* __SVTTGLYF_H__ */ + + +/* END */ diff --git a/headers/libs/freetype2/freetype/tttables.h b/headers/libs/freetype2/freetype/tttables.h index d6e690f880..43eca2e258 100644 --- a/headers/libs/freetype2/freetype/tttables.h +++ b/headers/libs/freetype2/freetype/tttables.h @@ -595,7 +595,7 @@ FT_BEGIN_HEADER /* */ /* This function is only useful to access SFNT tables that are loaded */ /* by the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for */ - /* a list. */ + /* a list. */ /* */ FT_EXPORT( void* ) FT_Get_Sfnt_Table( FT_Face face, @@ -725,6 +725,26 @@ FT_BEGIN_HEADER FT_EXPORT( FT_ULong ) FT_Get_CMap_Language_ID( FT_CharMap charmap ); + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_CMap_Format */ + /* */ + /* */ + /* Return TrueType/sfnt specific cmap format. */ + /* */ + /* */ + /* charmap :: */ + /* The target charmap. */ + /* */ + /* */ + /* The format of `charmap'. If `charmap' doesn't belong to a */ + /* TrueType/sfnt face, return -1. */ + /* */ + FT_EXPORT( FT_Long ) + FT_Get_CMap_Format( FT_CharMap charmap ); + /* */ diff --git a/src/libs/freetype2/autofit/Jamfile b/src/libs/freetype2/autofit/Jamfile index 331dd12625..2abea47d16 100644 --- a/src/libs/freetype2/autofit/Jamfile +++ b/src/libs/freetype2/autofit/Jamfile @@ -21,7 +21,7 @@ UseFreeTypeHeaders ; if $(FT2_MULTI) { - _sources = afangles afglobal afhints aflatin afloader afmodule afdummy afwarp ; + _sources = afangles afglobal afhints aflatin afcjk afindic afloader afmodule afdummy afwarp ; } else { diff --git a/src/libs/freetype2/autofit/afcjk.c b/src/libs/freetype2/autofit/afcjk.c index 2d01111661..c7ca266da8 100644 --- a/src/libs/freetype2/autofit/afcjk.c +++ b/src/libs/freetype2/autofit/afcjk.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK script (body). */ /* */ -/* Copyright 2006 by */ +/* Copyright 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -332,7 +332,6 @@ AF_Segment segment_limit = segments + axis->num_segments; AF_Segment seg; - AF_Direction up_dir; FT_Fixed scale; FT_Pos edge_distance_threshold; @@ -342,9 +341,6 @@ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale : hints->y_scale; - up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP - : AF_DIR_RIGHT; - /*********************************************************************/ /* */ /* We begin by generating a sorted table of edges for the current */ @@ -431,7 +427,7 @@ /* insert a new edge in the list and */ /* sort according to the position */ - error = af_axis_hints_new_edge( axis, seg->pos, memory, &edge ); + error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge ); if ( error ) goto Exit; @@ -1365,7 +1361,7 @@ FT_UNUSED( metrics ); - error = af_glyph_hints_reload( hints, outline ); + error = af_glyph_hints_reload( hints, outline, 0 ); if ( error ) goto Exit; diff --git a/src/libs/freetype2/autofit/afglobal.c b/src/libs/freetype2/autofit/afglobal.c index ccb3b190d8..ad3baa1639 100644 --- a/src/libs/freetype2/autofit/afglobal.c +++ b/src/libs/freetype2/autofit/afglobal.c @@ -20,21 +20,29 @@ #include "afdummy.h" #include "aflatin.h" #include "afcjk.h" +#include "afindic.h" + #include "aferrors.h" +#ifdef FT_OPTION_AUTOFIT2 +#include "aflatin2.h" +#endif /* populate this list when you add new scripts */ static AF_ScriptClass const af_script_classes[] = { &af_dummy_script_class, +#ifdef FT_OPTION_AUTOFIT2 + &af_latin2_script_class, +#endif &af_latin_script_class, &af_cjk_script_class, - + &af_indic_script_class, NULL /* do not remove */ }; /* index of default script in `af_script_classes' */ -#define AF_SCRIPT_LIST_DEFAULT 1 +#define AF_SCRIPT_LIST_DEFAULT 2 /* indicates an uncovered glyph */ #define AF_SCRIPT_LIST_NONE 255 @@ -217,12 +225,16 @@ FT_LOCAL_DEF( FT_Error ) af_face_globals_get_metrics( AF_FaceGlobals globals, FT_UInt gindex, + FT_UInt options, AF_ScriptMetrics *ametrics ) { AF_ScriptMetrics metrics = NULL; FT_UInt gidx; AF_ScriptClass clazz; - FT_Error error = AF_Err_Ok; + FT_UInt script = options & 15; + const FT_UInt script_max = sizeof ( af_script_classes ) / + sizeof ( af_script_classes[0] ); + FT_Error error = AF_Err_Ok; if ( gindex >= globals->glyph_count ) @@ -231,8 +243,14 @@ goto Exit; } - gidx = globals->glyph_scripts[gindex]; - clazz = af_script_classes[gidx]; + gidx = script; + if ( gidx == 0 || gidx + 1 >= script_max ) + gidx = globals->glyph_scripts[gindex]; + + clazz = af_script_classes[gidx]; + if ( script == 0 ) + script = clazz->script; + metrics = globals->metrics[clazz->script]; if ( metrics == NULL ) { diff --git a/src/libs/freetype2/autofit/afglobal.h b/src/libs/freetype2/autofit/afglobal.h index 95a92512d5..cf52c08756 100644 --- a/src/libs/freetype2/autofit/afglobal.h +++ b/src/libs/freetype2/autofit/afglobal.h @@ -5,7 +5,7 @@ /* Auto-fitter routines to compute global hinting values */ /* (specification). */ /* */ -/* Copyright 2003, 2004, 2005 by */ +/* Copyright 2003, 2004, 2005, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -50,6 +50,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) af_face_globals_get_metrics( AF_FaceGlobals globals, FT_UInt gindex, + FT_UInt options, AF_ScriptMetrics *ametrics ); FT_LOCAL( void ) diff --git a/src/libs/freetype2/autofit/afhints.c b/src/libs/freetype2/autofit/afhints.c index b1360a1a8d..482870686d 100644 --- a/src/libs/freetype2/autofit/afhints.c +++ b/src/libs/freetype2/autofit/afhints.c @@ -54,9 +54,6 @@ } segment = axis->segments + axis->num_segments++; -#if 0 - FT_ZERO( segment ); -#endif Exit: *asegment = segment; @@ -67,6 +64,7 @@ FT_LOCAL( FT_Error ) af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, + AF_Direction dir, FT_Memory memory, AF_Edge *aedge ) { @@ -101,8 +99,16 @@ edges = axis->edges; edge = edges + axis->num_edges; - while ( edge > edges && edge[-1].fpos > fpos ) + while ( edge > edges ) { + if ( edge[-1].fpos < fpos ) + break; + + /* we want the edge with same position and minor direction */ + /* to appear before those in the major one in the list */ + if ( edge[-1].fpos == fpos && dir == axis->major_dir ) + break; + edge[0] = edge[-1]; edge--; } @@ -111,6 +117,7 @@ FT_ZERO( edge ); edge->fpos = (FT_Short)fpos; + edge->dir = (FT_Char)dir; Exit: *aedge = edge; @@ -187,6 +194,34 @@ } + static const char* + af_edge_flags_to_string( AF_Edge_Flags flags ) + { + static char temp[32]; + int pos = 0; + + + if ( flags & AF_EDGE_ROUND ) + { + memcpy( temp + pos, "round", 5 ); + pos += 5; + } + if ( flags & AF_EDGE_SERIF ) + { + if ( pos > 0 ) + temp[pos++] = ' '; + memcpy( temp + pos, "serif", 5 ); + pos += 5; + } + if ( pos == 0 ) + return "normal"; + + temp[pos] = 0; + + return temp; + } + + /* A function to dump the array of linked segments. */ void af_glyph_hints_dump_segments( AF_GlyphHints hints ) @@ -204,19 +239,21 @@ printf ( "Table of %s segments:\n", dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); - printf ( " [ index | pos | dir | link | serif |" - " height | extra ]\n" ); + printf ( " [ index | pos | dir | link | serif |" + " height | extra | flags ]\n" ); for ( seg = segments; seg < limit; seg++ ) { - printf ( " [ %5d | %4d | %5s | %4d | %5d | %5d | %5d ]\n", + printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n", seg - segments, - (int)seg->pos, + dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0 + : (int)seg->first->oy / 64.0, af_dir_str( (AF_Direction)seg->dir ), AF_INDEX_NUM( seg->link, segments ), AF_INDEX_NUM( seg->serif, segments ), seg->height, - seg->height - ( seg->max_coord - seg->min_coord ) ); + seg->height - ( seg->max_coord - seg->min_coord ), + af_edge_flags_to_string( seg->flags ) ); } printf( "\n" ); } @@ -243,21 +280,22 @@ */ printf ( "Table of %s edges:\n", dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); - printf ( " [ index | pos | dir | link |" - " serif | blue | opos | pos ]\n" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos | flags ]\n" ); for ( edge = edges; edge < limit; edge++ ) { - printf ( " [ %5d | %4d | %5s | %4d |" - " %5d | %c | %5.2f | %5.2f ]\n", + printf ( " [ %5d | %5.2g | %5s | %4d |" + " %5d | %c | %5.2f | %5.2f | %s ]\n", edge - edges, - (int)edge->fpos, + (int)edge->opos / 64.0, af_dir_str( (AF_Direction)edge->dir ), AF_INDEX_NUM( edge->link, edges ), AF_INDEX_NUM( edge->serif, edges ), edge->blue_edge ? 'y' : 'n', edge->opos / 64.0, - edge->pos / 64.0 ); + edge->pos / 64.0, + af_edge_flags_to_string( edge->flags ) ); } printf( "\n" ); } @@ -296,9 +334,6 @@ af_direction_compute( FT_Pos dx, FT_Pos dy ) { - -#if 1 - FT_Pos ll, ss; /* long and short arm lengths */ AF_Direction dir; /* candidate direction */ @@ -334,45 +369,16 @@ } } - ss *= 12; - if ( FT_ABS(ll) <= FT_ABS(ss) ) + ss *= 14; + if ( FT_ABS( ll ) <= FT_ABS( ss ) ) dir = AF_DIR_NONE; return dir; - -#else /* 0 */ - - AF_Direction dir; - FT_Pos ax = FT_ABS( dx ); - FT_Pos ay = FT_ABS( dy ); - - - dir = AF_DIR_NONE; - - /* atan(1/12) == 4.7 degrees */ - - /* test for vertical direction */ - if ( ax * 12 < ay ) - { - dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN; - } - /* test for horizontal direction */ - else if ( ay * 12 < ax ) - { - dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT; - } - - return dir; - -#endif /* 0 */ - } /* compute all inflex points in a given glyph */ -#if 1 - static void af_glyph_hints_compute_inflections( AF_GlyphHints hints ) { @@ -484,117 +490,6 @@ } } -#else /* old code */ - - static void - af_glyph_hints_compute_inflections( AF_GlyphHints hints ) - { - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - - - /* do each contour separately */ - for ( ; contour < contour_limit; contour++ ) - { - AF_Point point = contour[0]; - AF_Point first = point; - AF_Point start = point; - AF_Point end = point; - AF_Point before; - AF_Point after; - AF_Angle angle_in, angle_seg, angle_out; - AF_Angle diff_in, diff_out; - FT_Int finished = 0; - - - /* compute first segment in contour */ - first = point; - - start = end = first; - do - { - end = end->next; - if ( end == first ) - goto Skip; - - } while ( end->fx == first->fx && end->fy == first->fy ); - - angle_seg = af_angle_atan( end->fx - start->fx, - end->fy - start->fy ); - - /* extend the segment start whenever possible */ - before = start; - do - { - do - { - start = before; - before = before->prev; - if ( before == first ) - goto Skip; - - } while ( before->fx == start->fx && before->fy == start->fy ); - - angle_in = af_angle_atan( start->fx - before->fx, - start->fy - before->fy ); - - } while ( angle_in == angle_seg ); - - first = start; - - AF_ANGLE_DIFF( diff_in, angle_in, angle_seg ); - - /* now, process all segments in the contour */ - do - { - /* first, extend current segment's end whenever possible */ - after = end; - do - { - do - { - end = after; - after = after->next; - if ( after == first ) - finished = 1; - - } while ( end->fx == after->fx && end->fy == after->fy ); - - angle_out = af_angle_atan( after->fx - end->fx, - after->fy - end->fy ); - - } while ( angle_out == angle_seg ); - - AF_ANGLE_DIFF( diff_out, angle_seg, angle_out ); - - if ( ( diff_in ^ diff_out ) < 0 ) - { - /* diff_in and diff_out have different signs, we have */ - /* inflection points here... */ - do - { - start->flags |= AF_FLAG_INFLECTION; - start = start->next; - - } while ( start != end ); - - start->flags |= AF_FLAG_INFLECTION; - } - - start = end; - end = after; - angle_seg = angle_out; - diff_in = diff_out; - - } while ( !finished ); - - Skip: - ; - } - } - -#endif /* old code */ - FT_LOCAL_DEF( void ) af_glyph_hints_init( AF_GlyphHints hints, @@ -656,7 +551,8 @@ FT_LOCAL_DEF( FT_Error ) af_glyph_hints_reload( AF_GlyphHints hints, - FT_Outline* outline ) + FT_Outline* outline, + FT_Bool get_inflections ) { FT_Error error = AF_Err_Ok; AF_Point points; @@ -739,10 +635,14 @@ AF_Point point_limit = points + hints->num_points; - /* compute coordinates & Bezier flags */ + /* compute coordinates & Bezier flags, next and prev */ { - FT_Vector* vec = outline->points; - char* tag = outline->tags; + FT_Vector* vec = outline->points; + char* tag = outline->tags; + AF_Point first = points; + AF_Point end = points + outline->contours[0]; + AF_Point prev = end; + FT_Int contour_index = 0; for ( point = points; point < point_limit; point++, vec++, tag++ ) @@ -763,39 +663,17 @@ default: point->flags = 0; } - } - } - /* compute `next' and `prev' */ - { - FT_Int contour_index; - AF_Point prev; - AF_Point first; - AF_Point end; - - - contour_index = 0; - - first = points; - end = points + outline->contours[0]; - prev = end; - - for ( point = points; point < point_limit; point++ ) - { point->prev = prev; - if ( point < end ) + prev->next = point; + prev = point; + + if ( point == end ) { - point->next = point + 1; - prev = point; - } - else - { - point->next = first; - contour_index++; - if ( point + 1 < point_limit ) + if ( ++contour_index < outline->n_contours ) { - end = points + outline->contours[contour_index]; first = point + 1; + end = points + outline->contours[contour_index]; prev = end; } } @@ -819,24 +697,36 @@ /* compute directions of in & out vectors */ { + AF_Point first = points; + AF_Point prev = NULL; + FT_Pos in_x = 0; + FT_Pos in_y = 0; + AF_Direction in_dir = AF_DIR_NONE; + + for ( point = points; point < point_limit; point++ ) { - AF_Point prev; AF_Point next; - FT_Pos in_x, in_y, out_x, out_y; + FT_Pos out_x, out_y; - prev = point->prev; - in_x = point->fx - prev->fx; - in_y = point->fy - prev->fy; + if ( point == first ) + { + prev = first->prev; + in_x = first->fx - prev->fx; + in_y = first->fy - prev->fy; + in_dir = af_direction_compute( in_x, in_y ); + first = prev + 1; + } - point->in_dir = (FT_Char)af_direction_compute( in_x, in_y ); + point->in_dir = (FT_Char)in_dir; - next = point->next; - out_x = next->fx - point->fx; - out_y = next->fy - point->fy; + next = point->next; + out_x = next->fx - point->fx; + out_y = next->fy - point->fy; - point->out_dir = (FT_Char)af_direction_compute( out_x, out_y ); + in_dir = af_direction_compute( out_x, out_y ); + point->out_dir = (FT_Char)in_dir; if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) ) { @@ -845,42 +735,26 @@ } else if ( point->out_dir == point->in_dir ) { - -#if 1 - if ( point->out_dir != AF_DIR_NONE ) goto Is_Weak_Point; if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) ) goto Is_Weak_Point; - -#else /* old code */ - - AF_Angle angle_in, angle_out, delta; - - - if ( point->out_dir != AF_DIR_NONE ) - goto Is_Weak_Point; - - angle_in = af_angle_atan( in_x, in_y ); - angle_out = af_angle_atan( out_x, out_y ); - - AF_ANGLE_DIFF( delta, angle_in, angle_out ); - - if ( delta < 2 && delta > -2 ) - goto Is_Weak_Point; - -#endif /* old code */ - } else if ( point->in_dir == -point->out_dir ) goto Is_Weak_Point; + + in_x = out_x; + in_y = out_y; + prev = point; } } } - /* compute inflection points */ - af_glyph_hints_compute_inflections( hints ); + /* compute inflection points -- */ + /* disabled due to no longer perceived benefits */ + if ( 0 && get_inflections ) + af_glyph_hints_compute_inflections( hints ); Exit: return error; @@ -923,46 +797,64 @@ af_glyph_hints_align_edge_points( AF_GlyphHints hints, AF_Dimension dim ) { - AF_AxisHints axis = & hints->axis[dim]; - AF_Edge edges = axis->edges; - AF_Edge edge_limit = edges + axis->num_edges; - AF_Edge edge; + AF_AxisHints axis = & hints->axis[dim]; + AF_Segment segments = axis->segments; + AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment seg; - for ( edge = edges; edge < edge_limit; edge++ ) + if ( dim == AF_DIMENSION_HORZ ) { - /* move the points of each segment */ - /* in each edge to the edge's position */ - AF_Segment seg = edge->first; - - - do + for ( seg = segments; seg < segment_limit; seg++ ) { - AF_Point point = seg->first; + AF_Edge edge = seg->edge; + AF_Point point, first, last; + if ( edge == NULL ) + continue; + + first = seg->first; + last = seg->last; + point = first; for (;;) { - if ( dim == AF_DIMENSION_HORZ ) - { - point->x = edge->pos; - point->flags |= AF_FLAG_TOUCH_X; - } - else - { - point->y = edge->pos; - point->flags |= AF_FLAG_TOUCH_Y; - } + point->x = edge->pos; + point->flags |= AF_FLAG_TOUCH_X; - if ( point == seg->last ) + if ( point == last ) + break; + + point = point->next; + + } + } + } + else + { + for ( seg = segments; seg < segment_limit; seg++ ) + { + AF_Edge edge = seg->edge; + AF_Point point, first, last; + + + if ( edge == NULL ) + continue; + + first = seg->first; + last = seg->last; + point = first; + for (;;) + { + point->y = edge->pos; + point->flags |= AF_FLAG_TOUCH_Y; + + if ( point == last ) break; point = point->next; } - - seg = seg->edge_next; - - } while ( seg != edge->first ); + } } } @@ -1056,6 +948,25 @@ min = 0; max = edge_limit - edges; +#if 1 + /* for small edge counts, a linear search is better */ + if ( max <= 8 ) + { + FT_UInt nn; + + for ( nn = 0; nn < max; nn++ ) + if ( edges[nn].fpos >= u ) + break; + + if ( edges[nn].fpos == u ) + { + u = edges[nn].pos; + goto Store_Point; + } + min = nn; + } + else +#endif while ( min < max ) { mid = ( max + min ) >> 1; @@ -1117,6 +1028,8 @@ AF_Point p; FT_Pos delta = ref->u - ref->v; + if ( delta == 0 ) + return; for ( p = p1; p < ref; p++ ) p->u = p->v + delta; @@ -1235,53 +1148,76 @@ for ( ; contour < contour_limit; contour++ ) { + AF_Point first_touched, last_touched; + + point = *contour; end_point = point->prev; first_point = point; - while ( point <= end_point && !( point->flags & touch_flag ) ) - point++; - - if ( point <= end_point ) + /* find first touched point */ + for (;;) { - AF_Point first_touched = point; - AF_Point cur_touched = point; + if ( point > end_point ) /* no touched point in contour */ + goto NextContour; + if ( point->flags & touch_flag ) + break; point++; - while ( point <= end_point ) + } + + first_touched = point; + last_touched = point; + + for (;;) + { + FT_ASSERT( point <= end_point && + ( point->flags & touch_flag ) != 0 ); + + /* skip any touched neighbhours */ + while ( point < end_point && ( point[1].flags & touch_flag ) != 0 ) + point++; + + last_touched = point; + + /* find the next touched point, if any */ + point ++; + for (;;) { - if ( point->flags & touch_flag ) - { - /* we found two successive touched points; we interpolate */ - /* all contour points between them */ - af_iup_interp( cur_touched + 1, point - 1, - cur_touched, point ); - cur_touched = point; - } + if ( point > end_point ) + goto EndContour; + + if ( ( point->flags & touch_flag ) != 0 ) + break; + point++; } - if ( cur_touched == first_touched ) - { - /* this is a special case: only one point was touched in the */ - /* contour; we thus simply shift the whole contour */ - af_iup_shift( first_point, end_point, cur_touched ); - } - else - { - /* now interpolate after the last touched point to the end */ - /* of the contour */ - af_iup_interp( cur_touched + 1, end_point, - cur_touched, first_touched ); - - /* if the first contour point isn't touched, interpolate */ - /* from the contour start to the first touched point */ - if ( first_touched > points ) - af_iup_interp( first_point, first_touched - 1, - cur_touched, first_touched ); - } + /* interpolate between last_touched and point */ + af_iup_interp( last_touched + 1, point - 1, + last_touched, point ); } + + 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 ) + af_iup_interp( last_touched + 1, end_point, + last_touched, first_touched ); + + if ( first_touched > points ) + af_iup_interp( first_point, first_touched - 1, + last_touched, first_touched ); + } + + NextContour: + ; } /* now save the interpolated values back to x/y */ diff --git a/src/libs/freetype2/autofit/afhints.h b/src/libs/freetype2/autofit/afhints.h index a983855b39..1308d5c4b7 100644 --- a/src/libs/freetype2/autofit/afhints.h +++ b/src/libs/freetype2/autofit/afhints.h @@ -21,6 +21,7 @@ #include "aftypes.h" +#define xxAF_SORT_SEGMENTS FT_BEGIN_HEADER @@ -171,6 +172,9 @@ FT_BEGIN_HEADER FT_Int num_segments; FT_Int max_segments; AF_Segment segments; +#ifdef AF_SORT_SEGMENTS + FT_Int mid_segments; +#endif FT_Int num_edges; FT_Int max_edges; @@ -262,6 +266,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error) af_axis_hints_new_edge( AF_AxisHints axis, FT_Int fpos, + AF_Direction dir, FT_Memory memory, AF_Edge *edge ); @@ -281,7 +286,8 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) af_glyph_hints_reload( AF_GlyphHints hints, - FT_Outline* outline ); + FT_Outline* outline, + FT_Bool get_inflections ); FT_LOCAL( void ) af_glyph_hints_save( AF_GlyphHints hints, diff --git a/src/libs/freetype2/autofit/afindic.c b/src/libs/freetype2/autofit/afindic.c new file mode 100644 index 0000000000..c6e7522e15 --- /dev/null +++ b/src/libs/freetype2/autofit/afindic.c @@ -0,0 +1,134 @@ +/***************************************************************************/ +/* */ +/* afindic.c */ +/* */ +/* Auto-fitter hinting routines for Indic scripts (body). */ +/* */ +/* Copyright 2007 by */ +/* Rahul Bhalerao , . */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "aftypes.h" +#include "aflatin.h" + + +#ifdef AF_CONFIG_OPTION_INDIC + +#include "afindic.h" +#include "aferrors.h" +#include "afcjk.h" + + +#ifdef AF_USE_WARPER +#include "afwarp.h" +#endif + + + static FT_Error + af_indic_metrics_init( AF_LatinMetrics metrics, + FT_Face face ) + { + /* use CJK routines */ + return af_cjk_metrics_init( metrics, face ); + } + + + static void + af_indic_metrics_scale( AF_LatinMetrics metrics, + AF_Scaler scaler ) + { + /* use CJK routines */ + af_cjk_metrics_scale( metrics, scaler ); + } + + + static FT_Error + af_indic_hints_init( AF_GlyphHints hints, + AF_LatinMetrics metrics ) + { + /* use CJK routines */ + return af_cjk_hints_init( hints, metrics ); + } + + + static FT_Error + af_indic_hints_apply( AF_GlyphHints hints, + FT_Outline* outline, + AF_LatinMetrics metrics) + { + /* use CJK routines */ + return af_cjk_hints_apply( hints, outline, metrics ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** I N D I C S C R I P T C L A S S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static const AF_Script_UniRangeRec af_indic_uniranges[] = + { +#if 0 + { 0x0100, 0xFFFF }, /* why this? */ +#endif + { 0x0900, 0x0DFF}, /* Indic Range */ + { 0, 0 } + }; + + + FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec + af_indic_script_class = + { + AF_SCRIPT_INDIC, + af_indic_uniranges, + + sizeof( AF_LatinMetricsRec ), + + (AF_Script_InitMetricsFunc) af_indic_metrics_init, + (AF_Script_ScaleMetricsFunc)af_indic_metrics_scale, + (AF_Script_DoneMetricsFunc) NULL, + + (AF_Script_InitHintsFunc) af_indic_hints_init, + (AF_Script_ApplyHintsFunc) af_indic_hints_apply + }; + +#else /* !AF_CONFIG_OPTION_INDIC */ + + static const AF_Script_UniRangeRec af_indic_uniranges[] = + { + { 0, 0 } + }; + + + FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec + af_indic_script_class = + { + AF_SCRIPT_INDIC, + af_indic_uniranges, + + sizeof( AF_LatinMetricsRec ), + + (AF_Script_InitMetricsFunc) NULL, + (AF_Script_ScaleMetricsFunc)NULL, + (AF_Script_DoneMetricsFunc) NULL, + + (AF_Script_InitHintsFunc) NULL, + (AF_Script_ApplyHintsFunc) NULL + }; + +#endif /* !AF_CONFIG_OPTION_INDIC */ + + +/* END */ diff --git a/src/libs/freetype2/autofit/afindic.h b/src/libs/freetype2/autofit/afindic.h new file mode 100644 index 0000000000..b242b26144 --- /dev/null +++ b/src/libs/freetype2/autofit/afindic.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* afindic.h */ +/* */ +/* Auto-fitter hinting routines for Indic scripts (specification). */ +/* */ +/* Copyright 2007 by */ +/* Rahul Bhalerao , . */ +/* */ +/* 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 __AFINDIC_H__ +#define __AFINDIC_H__ + +#include "afhints.h" + + +FT_BEGIN_HEADER + + + /* the Indic-specific script class */ + + FT_CALLBACK_TABLE const AF_ScriptClassRec + af_indic_script_class; + + +/* */ + +FT_END_HEADER + +#endif /* __AFINDIC_H__ */ + + +/* END */ diff --git a/src/libs/freetype2/autofit/aflatin.c b/src/libs/freetype2/autofit/aflatin.c index 4cec6cb4b3..2ae9ec5a19 100644 --- a/src/libs/freetype2/autofit/aflatin.c +++ b/src/libs/freetype2/autofit/aflatin.c @@ -74,7 +74,7 @@ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); - error = af_glyph_hints_reload( hints, &face->glyph->outline ); + error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 ); if ( error ) goto Exit; @@ -269,6 +269,7 @@ /* now check whether the point belongs to a straight or round */ /* segment; we first need to find in which contour the extremum */ /* lies, then inspect its previous and next points */ + if ( best_point >= 0 ) { FT_Int prev, next; FT_Pos dist; @@ -488,12 +489,15 @@ if ( scaled != fitted ) { +#if 0 if ( dim == AF_DIMENSION_HORZ ) { if ( fitted < scaled ) scale -= scale / 50; /* scale *= 0.98 */ } else +#endif + if ( dim == AF_DIMENSION_VERT ) { scale = FT_MulDiv( scale, fitted, scaled ); } @@ -527,7 +531,8 @@ /* an extra-light axis corresponds to a standard width that is */ /* smaller than 0.75 pixels */ - axis->extra_light = FT_MulFix( axis->standard_width, scale ) < 32 + 8; + axis->extra_light = + (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 ); if ( dim == AF_DIMENSION_VERT ) { @@ -611,13 +616,6 @@ AF_Point* contour_limit = contour + hints->num_contours; AF_Direction major_dir, segment_dir; -#ifdef AF_HINT_METRICS - AF_Point min_point = 0; - AF_Point max_point = 0; - FT_Pos min_coord = 32000; - FT_Pos max_coord = -32000; -#endif - FT_ZERO( &seg0 ); seg0.score = 32000; @@ -665,19 +663,6 @@ FT_Bool passed; -#ifdef AF_HINT_METRICS - if ( point->u < min_coord ) - { - min_coord = point->u; - min_point = point; - } - if ( point->u > max_coord ) - { - max_coord = point->u; - max_point = point; - } -#endif - if ( point == last ) /* skip singletons -- just in case */ continue; @@ -773,14 +758,6 @@ segment->last = point; segment->contour = contour; on_edge = 1; - -#ifdef AF_HINT_METRICS - if ( point == max_point ) - max_point = 0; - - if ( point == min_point ) - min_point = 0; -#endif } point = point->next; @@ -840,77 +817,6 @@ } } -#ifdef AF_HINT_METRICS - /* we need to ensure that there are edges on the left-most and */ - /* right-most points of the glyph in order to hint the metrics; */ - /* we do this by inserting fake segments when needed */ - - if ( dim == AF_DIMENSION_HORZ ) - { - AF_Point point = hints->points; - AF_Point point_limit = point + hints->num_points; - - FT_Pos min_pos = 32000; - FT_Pos max_pos = -32000; - - - min_point = 0; - max_point = 0; - - /* compute minimum and maximum points */ - for ( ; point < point_limit; point++ ) - { - FT_Pos x = point->fx; - - - if ( x < min_pos ) - { - min_pos = x; - min_point = point; - } - if ( x > max_pos ) - { - max_pos = x; - max_point = point; - } - } - - /* insert minimum segment */ - if ( min_point ) - { - /* clear all segment fields */ - error = af_axis_hints_new_segment( axis, memory, &segment ); - if ( error ) - goto Exit; - - segment[0] = seg0; - segment->dir = segment_dir; - segment->first = min_point; - segment->last = min_point; - segment->pos = min_pos; - - segment = NULL; - } - - /* insert maximum segment */ - if ( max_point ) - { - /* clear all segment fields */ - error = af_axis_hints_new_segment( axis, memory, &segment ); - if ( error ) - goto Exit; - - segment[0] = seg0; - segment->dir = segment_dir; - segment->first = max_point; - segment->last = max_point; - segment->pos = max_pos; - - segment = NULL; - } - } -#endif /* AF_HINT_METRICS */ - Exit: return error; } @@ -938,11 +844,11 @@ { /* the fake segments are introduced to hint the metrics -- */ /* we must never link them to anything */ - if ( seg1->first == seg1->last ) + if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) continue; - for ( seg2 = seg1 + 1; seg2 < segment_limit; seg2++ ) - if ( seg1->dir + seg2->dir == 0 ) + 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; @@ -1089,7 +995,7 @@ if ( dist < 0 ) dist = -dist; - if ( dist < edge_distance_threshold ) + if ( dist < edge_distance_threshold && edge->dir == seg->dir ) { found = edge; break; @@ -1103,7 +1009,7 @@ /* insert a new edge in the list and */ /* sort according to the position */ - error = af_axis_hints_new_edge( axis, seg->pos, memory, &edge ); + error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge ); if ( error ) goto Exit; @@ -1113,6 +1019,7 @@ edge->first = seg; edge->last = seg; edge->fpos = seg->pos; + edge->dir = seg->dir; edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); seg->edge_next = seg; } @@ -1253,6 +1160,7 @@ if ( is_round > 0 && is_round >= is_straight ) edge->flags |= AF_EDGE_ROUND; +#if 0 /* set the edge's main direction */ edge->dir = AF_DIR_NONE; @@ -1264,6 +1172,7 @@ else if ( ups == downs ) edge->dir = 0; /* both up and down! */ +#endif /* gets rid of serifs if link is set */ /* XXX: This gets rid of many unpleasant artefacts! */ @@ -2096,16 +2005,24 @@ if ( before >= edges && before < edge && after < edge_limit && after > edge ) + { edge->pos = before->pos + 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 )); + } else + { edge->pos = anchor->pos + - FT_PIX_ROUND( edge->opos - anchor->opos ); - - AF_LOG(( "SERIF_LINK: edge %d (opos=%.2f) snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); + ( ( 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 )); + } } edge->flags |= AF_EDGE_DONE; @@ -2131,7 +2048,7 @@ int dim; - error = af_glyph_hints_reload( hints, outline ); + error = af_glyph_hints_reload( hints, outline, 1 ); if ( error ) goto Exit; @@ -2200,11 +2117,32 @@ /*************************************************************************/ + /* XXX: this should probably fine tuned to differentiate better between */ + /* scripts... */ + static const AF_Script_UniRangeRec af_latin_uniranges[] = { - { 32, 127 }, /* XXX: TODO: Add new Unicode ranges here! */ - { 160, 255 }, - { 0, 0 } + { 0x0020, 0x007F }, /* Basic Latin (no control characters) */ + { 0x00A0, 0x00FF }, /* Latin-1 Supplement (no control characters) */ + { 0x0100, 0x017F }, /* Latin Extended-A */ + { 0x0180, 0x024F }, /* Latin Extended-B */ + { 0x0250, 0x02AF }, /* IPA Extensions */ + { 0x02B0, 0x02FF }, /* Spacing Modifier Letters */ + { 0x0300, 0x036F }, /* Combining Diacritical Marks */ + { 0x0370, 0x03FF }, /* Greek and Coptic */ + { 0x0400, 0x04FF }, /* Cyrillic */ + { 0x0500, 0x052F }, /* Cyrillic Supplement */ + { 0x1D00, 0x1D7F }, /* Phonetic Extensions */ + { 0x1D80, 0x1DBF }, /* Phonetic Extensions Supplement */ + { 0x1DC0, 0x1DFF }, /* Combining Diacritical Marks Supplement */ + { 0x1E00, 0x1EFF }, /* Latin Extended Additional */ + { 0x1F00, 0x1FFF }, /* Greek Extended */ + { 0x2000, 0x206F }, /* General Punctuation */ + { 0x2070, 0x209F }, /* Superscripts and Subscripts */ + { 0x20A0, 0x20CF }, /* Currency Symbols */ + { 0x2150, 0x218F }, /* Number Forms */ + { 0x2460, 0x24FF }, /* Enclosed Alphanumerics */ + { 0 , 0 } }; diff --git a/src/libs/freetype2/autofit/aflatin2.c b/src/libs/freetype2/autofit/aflatin2.c new file mode 100644 index 0000000000..0b4177414c --- /dev/null +++ b/src/libs/freetype2/autofit/aflatin2.c @@ -0,0 +1,2286 @@ +/***************************************************************************/ +/* */ +/* aflatin.c */ +/* */ +/* Auto-fitter hinting routines for latin script (body). */ +/* */ +/* Copyright 2003, 2004, 2005, 2006, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "aflatin.h" +#include "aflatin2.h" +#include "aferrors.h" + + +#ifdef AF_USE_WARPER +#include "afwarp.h" +#endif + + FT_LOCAL_DEF( FT_Error ) + af_latin2_hints_compute_segments( AF_GlyphHints hints, + AF_Dimension dim ); + + FT_LOCAL_DEF( void ) + af_latin2_hints_link_segments( AF_GlyphHints hints, + AF_Dimension dim ); + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** L A T I N G L O B A L M E T R I C S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + af_latin2_metrics_init_widths( AF_LatinMetrics 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_LatinMetricsRec 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 = scaler->y_scale = 0x10000L; + scaler->x_delta = 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, 0 ); + if ( error ) + goto Exit; + + for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) + { + AF_LatinAxis axis = &metrics->axis[dim]; + AF_AxisHints axhints = &hints->axis[dim]; + AF_Segment seg, limit, link; + FT_UInt num_widths = 0; + + + error = af_latin2_hints_compute_segments( hints, + (AF_Dimension)dim ); + if ( error ) + goto Exit; + + af_latin2_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_LATIN_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_LatinAxis 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_LATIN_MAX_TEST_CHARACTERS 12 + + + static const char* const af_latin2_blue_chars[AF_LATIN_MAX_BLUES] = + { + "THEZOCQS", + "HEZLOCUS", + "fijkdbh", + "xzroesc", + "xzroesc", + "pqgjy" + }; + + + static void + af_latin2_metrics_init_blues( AF_LatinMetrics metrics, + FT_Face face ) + { + FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS]; + FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS]; + FT_Int num_flats; + FT_Int num_rounds; + FT_Int bb; + AF_LatinBlue blue; + FT_Error error; + AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; + FT_GlyphSlot glyph = face->glyph; + + + /* 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') */ + + AF_LOG(( "blue zones computation\n" )); + AF_LOG(( "------------------------------------------------\n" )); + + for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) + { + const char* p = af_latin2_blue_chars[bb]; + const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS; + FT_Pos* blue_ref; + FT_Pos* blue_shoot; + + + AF_LOG(( "blue %3d: ", bb )); + + num_flats = 0; + num_rounds = 0; + + for ( ; p < limit && *p; p++ ) + { + FT_UInt glyph_index; + FT_Int best_point, best_y, best_first, best_last; + FT_Vector* points; + FT_Bool round; + + + AF_LOG(( "'%c'", *p )); + + /* load the character in the face -- skip unknown or empty ones */ + glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); + if ( glyph_index == 0 ) + continue; + + error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); + if ( error || glyph->outline.n_points <= 0 ) + continue; + + /* now compute min or max point indices and coordinates */ + points = glyph->outline.points; + best_point = -1; + best_y = 0; /* make compiler happy */ + best_first = 0; /* ditto */ + best_last = 0; /* ditto */ + + { + 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 old_best_point = best_point; + 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; + + if ( AF_LATIN_IS_TOP_BLUE( bb ) ) + { + for ( pp = first; pp <= last; pp++ ) + if ( best_point < 0 || points[pp].y > best_y ) + { + best_point = pp; + best_y = points[pp].y; + } + } + else + { + for ( pp = first; pp <= last; pp++ ) + if ( best_point < 0 || points[pp].y < best_y ) + { + best_point = pp; + best_y = points[pp].y; + } + } + + if ( best_point != old_best_point ) + { + best_first = first; + best_last = last; + } + } + AF_LOG(( "%5d", best_y )); + } + + /* now check whether the point belongs to a straight or round */ + /* segment; we first need to find in which contour the extremum */ + /* lies, then inspect its previous and next points */ + { + FT_Int start, end, prev, next; + FT_Pos dist; + + + /* now look for the previous and next points that are not on the */ + /* same Y coordinate. Threshold the `closeness'... */ + start = end = best_point; + + do + { + prev = start-1; + if ( prev < best_first ) + prev = best_last; + + dist = points[prev].y - best_y; + if ( dist < -5 || dist > 5 ) + break; + + start = prev; + + } while ( start != best_point ); + + do + { + next = end+1; + if ( next > best_last ) + next = best_first; + + dist = points[next].y - best_y; + if ( dist < -5 || dist > 5 ) + break; + + end = next; + + } while ( end != best_point ); + + /* now, set the `round' flag depending on the segment's kind */ + round = FT_BOOL( + 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' )); + } + + if ( round ) + rounds[num_rounds++] = best_y; + else + flats[num_flats++] = best_y; + } + + AF_LOG(( "\n" )); + + if ( num_flats == 0 && num_rounds == 0 ) + { + /* + * we couldn't find a single glyph to compute this blue zone, + * we will simply ignore it then + */ + AF_LOG(( "empty!\n" )); + continue; + } + + /* we have computed the contents of the `rounds' and `flats' tables, */ + /* now determine the reference and overshoot position of the blue -- */ + /* we simply take the median value after a simple sort */ + af_sort_pos( num_rounds, rounds ); + af_sort_pos( num_flats, flats ); + + 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 = + *blue_shoot = rounds[num_rounds / 2]; + } + else if ( num_rounds == 0 ) + { + *blue_ref = + *blue_shoot = flats[num_flats / 2]; + } + else + { + *blue_ref = flats[num_flats / 2]; + *blue_shoot = rounds[num_rounds / 2]; + } + + /* there are sometimes problems: if the overshoot position of top */ + /* zones is under its reference position, or the opposite for bottom */ + /* zones. We must thus check everything there and correct the errors */ + if ( *blue_shoot != *blue_ref ) + { + FT_Pos ref = *blue_ref; + FT_Pos shoot = *blue_shoot; + FT_Bool over_ref = FT_BOOL( shoot > ref ); + + + if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) + *blue_shoot = *blue_ref = ( shoot + ref ) / 2; + } + + blue->flags = 0; + if ( AF_LATIN_IS_TOP_BLUE( bb ) ) + blue->flags |= AF_LATIN_BLUE_TOP; + + /* + * The following flags is used later to adjust the y and x scales + * in order to optimize the pixel grid alignment of the top of small + * letters. + */ + if ( bb == AF_LATIN_BLUE_SMALL_TOP ) + blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; + + AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); + } + + return; + } + + + FT_LOCAL_DEF( FT_Error ) + af_latin2_metrics_init( AF_LatinMetrics metrics, + FT_Face face ) + { + FT_Error error = AF_Err_Ok; + FT_CharMap oldmap = face->charmap; + FT_UInt ee; + + static const FT_Encoding latin_encodings[] = + { + FT_ENCODING_UNICODE, + FT_ENCODING_APPLE_ROMAN, + FT_ENCODING_ADOBE_STANDARD, + FT_ENCODING_ADOBE_LATIN_1, + FT_ENCODING_NONE /* end of list */ + }; + + + metrics->units_per_em = face->units_per_EM; + + /* do we have a latin charmap in there? */ + for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ ) + { + error = FT_Select_Charmap( face, latin_encodings[ee] ); + if ( !error ) + break; + } + + if ( !error ) + { + /* For now, compute the standard width and height from the `o'. */ + af_latin2_metrics_init_widths( metrics, face, 'o' ); + af_latin2_metrics_init_blues( metrics, face ); + } + + FT_Set_Charmap( face, oldmap ); + return AF_Err_Ok; + } + + + static void + af_latin2_metrics_scale_dim( AF_LatinMetrics metrics, + AF_Scaler scaler, + AF_Dimension dim ) + { + FT_Fixed scale; + FT_Pos delta; + AF_LatinAxis axis; + FT_UInt nn; + + + if ( dim == AF_DIMENSION_HORZ ) + { + scale = scaler->x_scale; + delta = scaler->x_delta; + } + else + { + scale = scaler->y_scale; + delta = scaler->y_delta; + } + + axis = &metrics->axis[dim]; + + if ( axis->org_scale == scale && axis->org_delta == delta ) + return; + + axis->org_scale = scale; + axis->org_delta = delta; + + /* + * correct Y scale to optimize the alignment of the top of small + * letters to the pixel grid + */ + if ( dim == AF_DIMENSION_VERT ) + { + AF_LatinAxis vaxis = &metrics->axis[AF_DIMENSION_VERT]; + AF_LatinBlue blue = NULL; + + + for ( nn = 0; nn < vaxis->blue_count; nn++ ) + { + if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT ) + { + blue = &vaxis->blues[nn]; + break; + } + } + + if ( blue ) + { + FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); + FT_Pos fitted = ( scaled + 40 ) & ~63; + +#if 1 + 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 )); + } +#endif + } + } + + axis->scale = scale; + axis->delta = delta; + + if ( dim == AF_DIMENSION_HORZ ) + { + metrics->root.scaler.x_scale = scale; + metrics->root.scaler.x_delta = delta; + } + else + { + metrics->root.scaler.y_scale = scale; + metrics->root.scaler.y_delta = delta; + } + + /* scale the standard widths */ + for ( nn = 0; nn < axis->width_count; nn++ ) + { + AF_Width width = axis->widths + nn; + + + width->cur = FT_MulFix( width->org, scale ); + width->fit = width->cur; + } + + /* an extra-light axis corresponds to a standard width that is */ + /* smaller than 0.75 pixels */ + axis->extra_light = + (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 ); + + if ( dim == AF_DIMENSION_VERT ) + { + /* scale the blue zones */ + for ( nn = 0; nn < axis->blue_count; nn++ ) + { + AF_LatinBlue 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_LATIN_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; + + delta1 = blue->shoot.org - blue->ref.org; + delta2 = delta1; + if ( delta1 < 0 ) + delta2 = -delta2; + + delta2 = FT_MulFix( delta2, scale ); + + if ( delta2 < 32 ) + delta2 = 0; + else if ( delta2 < 64 ) + delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); + else + delta2 = FT_PIX_ROUND( delta2 ); + + if ( delta1 < 0 ) + delta2 = -delta2; + + 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 )); + + blue->flags |= AF_LATIN_BLUE_ACTIVE; + } + } + } + } + + + FT_LOCAL_DEF( void ) + af_latin2_metrics_scale( AF_LatinMetrics metrics, + AF_Scaler scaler ) + { + metrics->root.scaler.render_mode = scaler->render_mode; + metrics->root.scaler.face = scaler->face; + + af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); + af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** L A T I N G L Y P H A N A L Y S I S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#define SORT_SEGMENTS + + FT_LOCAL_DEF( FT_Error ) + af_latin2_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; + + + FT_ZERO( &seg0 ); + seg0.score = 32000; + seg0.flags = AF_EDGE_NORMAL; + + major_dir = (AF_Direction)FT_ABS( axis->major_dir ); + segment_dir = major_dir; + + axis->num_segments = 0; + + /* set up (u,v) in each point */ + if ( dim == AF_DIMENSION_HORZ ) + { + AF_Point point = hints->points; + AF_Point limit = point + hints->num_points; + + + for ( ; point < limit; point++ ) + { + point->u = point->fx; + point->v = point->fy; + } + } + else + { + AF_Point point = hints->points; + AF_Point limit = point + hints->num_points; + + + for ( ; point < limit; point++ ) + { + point->u = point->fy; + point->v = point->fx; + } + } + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + AF_Point point = contour[0]; + AF_Point start = point; + AF_Point last = point->prev; + + + if ( point == last ) /* skip singletons -- just in case */ + continue; + + /* already on an edge ?, backtrack to find its start */ + if ( FT_ABS( point->in_dir ) == major_dir ) + { + point = point->prev; + + while ( point->in_dir == start->in_dir ) + point = point->prev; + } + else /* otherwise, find first segment start, if any */ + { + while ( FT_ABS( point->out_dir ) != major_dir ) + { + point = point->next; + + if ( point == start ) + goto NextContour; + } + } + + start = point; + + for (;;) + { + AF_Point first; + FT_Pos min_u, min_v, max_u, max_v; + + /* we're at the start of a new segment */ + FT_ASSERT( FT_ABS( point->out_dir ) == major_dir && + point->in_dir != point->out_dir ); + first = point; + + min_u = max_u = point->u; + min_v = max_v = point->v; + + point = point->next; + + while ( point->out_dir == first->out_dir ) + { + point = point->next; + + if ( point->u < min_u ) + min_u = point->u; + + if ( point->u > max_u ) + max_u = point->u; + } + + if ( point->v < min_v ) + min_v = point->v; + + if ( point->v > max_v ) + max_v = point->v; + + /* record new segment */ + error = af_axis_hints_new_segment( axis, memory, &segment ); + if ( error ) + goto Exit; + + segment[0] = seg0; + 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; + segment->height = (FT_Short)(max_v - min_v); + + /* a segment is round if it doesn't have successive */ + /* on-curve points. */ + { + AF_Point pt = first; + AF_Point last = point; + AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); + AF_Flags f1; + + + segment->flags &= ~AF_EDGE_ROUND; + + for ( ; pt != last; f0 = f1 ) + { + pt = pt->next; + f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); + + if ( !f0 && !f1 ) + break; + + if ( pt == last ) + segment->flags |= AF_EDGE_ROUND; + } + } + + /* this can happen in the case of a degenerate contour + * e.g. a 2-point vertical contour + */ + if ( point == start ) + break; + + /* jump to the start of the next segment, if any */ + while ( FT_ABS(point->out_dir) != major_dir ) + { + point = point->next; + + if ( point == start ) + goto NextContour; + } + } + + NextContour: + ; + } /* contours */ + + /* now slightly increase the height of segments when this makes */ + /* sense -- this is used to better detect and ignore serifs */ + { + AF_Segment segments = axis->segments; + AF_Segment segments_end = segments + axis->num_segments; + + + for ( segment = segments; segment < segments_end; segment++ ) + { + AF_Point first = segment->first; + AF_Point last = segment->last; + AF_Point p; + FT_Pos first_v = first->v; + FT_Pos last_v = last->v; + + + if ( first == last ) + continue; + + if ( first_v < last_v ) + { + p = first->prev; + if ( p->v < first_v ) + segment->height = (FT_Short)( segment->height + + ( ( first_v - p->v ) >> 1 ) ); + + p = last->next; + if ( p->v > last_v ) + segment->height = (FT_Short)( segment->height + + ( ( p->v - last_v ) >> 1 ) ); + } + else + { + p = first->prev; + if ( p->v > first_v ) + segment->height = (FT_Short)( segment->height + + ( ( p->v - first_v ) >> 1 ) ); + + p = last->next; + if ( p->v < last_v ) + segment->height = (FT_Short)( segment->height + + ( ( last_v - p->v ) >> 1 ) ); + } + } + } + +#ifdef AF_SORT_SEGMENTS + /* place all segments with a negative direction to the start + * of the array, used to speed up segment linking later... + */ + { + AF_Segment segments = axis->segments; + FT_UInt count = axis->num_segments; + FT_UInt ii, jj; + + for (ii = 0; ii < count; ii++) + { + if ( segments[ii].dir > 0 ) + { + for (jj = ii+1; jj < count; jj++) + { + if ( segments[jj].dir < 0 ) + { + AF_SegmentRec tmp; + + tmp = segments[ii]; + segments[ii] = segments[jj]; + segments[jj] = tmp; + + break; + } + } + + if ( jj == count ) + break; + } + } + axis->mid_segments = ii; + } +#endif + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + af_latin2_hints_link_segments( AF_GlyphHints hints, + AF_Dimension dim ) + { + AF_AxisHints axis = &hints->axis[dim]; + AF_Segment segments = axis->segments; + AF_Segment segment_limit = segments + axis->num_segments; +#ifdef AF_SORT_SEGMENTS + AF_Segment segment_mid = segments + axis->mid_segments; +#endif + FT_Pos len_threshold, len_score; + AF_Segment seg1, seg2; + + + len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); + if ( len_threshold == 0 ) + len_threshold = 1; + + len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 ); + +#ifdef AF_SORT_SEGMENTS + for ( seg1 = segments; seg1 < segment_mid; seg1++ ) + { + if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) + continue; + + for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ ) +#else + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { + /* the fake segments are introduced to hint the metrics -- */ + /* we must never link them to anything */ + if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) + continue; + + for ( seg2 = segments; seg2 < segment_limit; seg2++ ) + if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos ) +#endif + { + FT_Pos pos1 = seg1->pos; + FT_Pos pos2 = seg2->pos; + FT_Pos dist = pos2 - pos1; + + + if ( dist < 0 ) + continue; + + { + 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 ( max > seg2->max_coord ) + max = seg2->max_coord; + + len = max - min; + if ( len >= len_threshold ) + { + score = dist + len_score / len; + if ( score < seg1->score ) + { + seg1->score = score; + seg1->link = seg2; + } + + if ( score < seg2->score ) + { + seg2->score = score; + seg2->link = seg1; + } + } + } + } + } + + /* now, compute the `serif' segments */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { + seg2 = seg1->link; + + if ( seg2 ) + { + if ( seg2->link != seg1 ) + { + seg1->link = 0; + seg1->serif = seg2->link; + } + } + } + } + + + FT_LOCAL_DEF( FT_Error ) + af_latin2_hints_compute_edges( AF_GlyphHints hints, + AF_Dimension dim ) + { + 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_Segment segments = axis->segments; + AF_Segment segment_limit = segments + axis->num_segments; + AF_Segment seg; + + AF_Direction up_dir; + FT_Fixed scale; + FT_Pos edge_distance_threshold; + FT_Pos segment_length_threshold; + + + axis->num_edges = 0; + + scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale + : hints->y_scale; + + up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP + : AF_DIR_RIGHT; + + /* + * We want to ignore very small (mostly serif) segments, we do that + * by ignoring those that whose length is less than a given fraction + * of the standard width. If there is no standard width, we ignore + * those that are less than a given size in pixels + * + * also, unlink serif segments that are linked to segments farther + * than 50% of the standard width + */ + if ( dim == AF_DIMENSION_HORZ ) + { + if ( laxis->width_count > 0 ) + segment_length_threshold = (laxis->standard_width * 10 ) >> 4; + else + segment_length_threshold = FT_DivFix( 64, hints->y_scale ); + } + else + segment_length_threshold = 0; + + /*********************************************************************/ + /* */ + /* 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. */ + /* */ + /* 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 */ + /* edge's properties. */ + /* */ + /* Note that the edges table is sorted along the segment/edge */ + /* position. */ + /* */ + /*********************************************************************/ + + edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, + scale ); + if ( edge_distance_threshold > 64 / 4 ) + edge_distance_threshold = 64 / 4; + + edge_distance_threshold = FT_DivFix( edge_distance_threshold, + scale ); + + for ( seg = segments; seg < segment_limit; seg++ ) + { + AF_Edge found = 0; + FT_Int ee; + + + if ( seg->height < segment_length_threshold ) + continue; + + /* A special case for serif edges: If they are smaller than */ + /* 1.5 pixels we ignore them. */ + if ( seg->serif ) + { + FT_Pos dist = seg->serif->pos - seg->pos; + + if (dist < 0) + dist = -dist; + + if (dist >= laxis->standard_width >> 1) + { + /* unlink this serif, it is too distant from its reference stem */ + seg->serif = NULL; + } + else if ( 2*seg->height < 3 * segment_length_threshold ) + continue; + } + + /* look for an edge corresponding to the segment */ + for ( ee = 0; ee < axis->num_edges; ee++ ) + { + AF_Edge edge = axis->edges + ee; + FT_Pos dist; + + + dist = seg->pos - edge->fpos; + if ( dist < 0 ) + dist = -dist; + + if ( dist < edge_distance_threshold && edge->dir == seg->dir ) + { + found = edge; + break; + } + } + + if ( !found ) + { + AF_Edge edge; + + + /* 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 ); + if ( error ) + goto Exit; + + /* add the segment to the new edge's list */ + FT_ZERO( edge ); + + edge->first = seg; + edge->last = seg; + edge->fpos = seg->pos; + edge->dir = seg->dir; + edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); + seg->edge_next = seg; + } + else + { + /* if an edge was found, simply add the segment to the edge's */ + /* list */ + seg->edge_next = found->first; + found->last->edge_next = seg; + found->last = seg; + } + } + + + /*********************************************************************/ + /* */ + /* Good, we will now compute each edge's properties according to */ + /* segments found on its position. Basically, these are: */ + /* */ + /* - edge's main direction */ + /* - stem edge, serif edge or both (which defaults to stem then) */ + /* - rounded edge, straight or both (which defaults to straight) */ + /* - link for edge */ + /* */ + /*********************************************************************/ + + /* first of all, set the `edge' field in each segment -- this is */ + /* required in order to compute edge links */ + + /* + * Note that removing this loop and setting the `edge' field of each + * segment directly in the code above slows down execution speed for + * some reasons on platforms like the Sun. + */ + { + AF_Edge edges = axis->edges; + AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge; + + + for ( edge = edges; edge < edge_limit; edge++ ) + { + seg = edge->first; + if ( seg ) + do + { + seg->edge = edge; + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + + /* 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? */ + FT_Pos ups = 0; /* number of upwards segments */ + FT_Pos downs = 0; /* number of downwards segments */ + + + seg = edge->first; + + do + { + FT_Bool is_serif; + + + /* check for roundness of segment */ + if ( seg->flags & AF_EDGE_ROUND ) + is_round++; + else + is_straight++; + + /* check for segment direction */ + if ( seg->dir == up_dir ) + ups += seg->max_coord-seg->min_coord; + else + downs += seg->max_coord-seg->min_coord; + + /* check for links -- if seg->serif is set, then seg->link must */ + /* be ignored */ + is_serif = (FT_Bool)( seg->serif && + seg->serif->edge && + seg->serif->edge != edge ); + + if ( ( seg->link && seg->link->edge != NULL ) || is_serif ) + { + AF_Edge edge2; + AF_Segment seg2; + + + edge2 = edge->link; + seg2 = seg->link; + + if ( is_serif ) + { + seg2 = seg->serif; + edge2 = edge->serif; + } + + if ( edge2 ) + { + FT_Pos edge_delta; + FT_Pos seg_delta; + + + edge_delta = edge->fpos - edge2->fpos; + if ( edge_delta < 0 ) + edge_delta = -edge_delta; + + seg_delta = seg->pos - seg2->pos; + if ( seg_delta < 0 ) + seg_delta = -seg_delta; + + if ( seg_delta < edge_delta ) + edge2 = seg2->edge; + } + else + edge2 = seg2->edge; + + if ( is_serif ) + { + edge->serif = edge2; + edge2->flags |= AF_EDGE_SERIF; + } + else + edge->link = edge2; + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + + /* set the round/straight flags */ + edge->flags = AF_EDGE_NORMAL; + + if ( is_round > 0 && is_round >= is_straight ) + edge->flags |= AF_EDGE_ROUND; + +#if 0 + /* set the edge's main direction */ + edge->dir = AF_DIR_NONE; + + if ( ups > downs ) + edge->dir = (FT_Char)up_dir; + + else if ( ups < downs ) + edge->dir = (FT_Char)-up_dir; + + else if ( ups == downs ) + edge->dir = 0; /* both up and down! */ +#endif + + /* gets rid of serifs if link is set */ + /* XXX: This gets rid of many unpleasant artefacts! */ + /* Example: the `c' in cour.pfa at size 13 */ + + if ( edge->serif && edge->link ) + edge->serif = 0; + } + } + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + af_latin2_hints_detect_features( AF_GlyphHints hints, + AF_Dimension dim ) + { + FT_Error error; + + + error = af_latin2_hints_compute_segments( hints, dim ); + if ( !error ) + { + af_latin2_hints_link_segments( hints, dim ); + + error = af_latin2_hints_compute_edges( hints, dim ); + } + return error; + } + + + FT_LOCAL_DEF( void ) + af_latin2_hints_compute_blue_edges( AF_GlyphHints hints, + AF_LatinMetrics metrics ) + { + 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 ]; + FT_Fixed scale = latin->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 ) + best_dist0 = 64 / 2; + + /* compute which blue zones are active, i.e. have their scaled */ + /* size < 3/4 pixels */ + + /* for each horizontal edge search the blue zone which is closest */ + for ( ; edge < edge_limit; edge++ ) + { + FT_Int bb; + AF_Width best_blue = NULL; + FT_Pos best_dist = best_dist0; + + for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) + { + AF_LatinBlue blue = latin->blues + bb; + FT_Bool is_top_blue, is_major_dir; + + + /* skip inactive blue zones (i.e., those that are too small) */ + if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) + continue; + + /* if it is a top zone, check for right edges -- if it is a bottom */ + /* zone, check for left edges */ + /* */ + /* of course, that's for TrueType */ + is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 ); + is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); + + /* if it is a top zone, the edge must be against the major */ + /* direction; if it is a bottom zone, it must be in the major */ + /* direction */ + if ( is_top_blue ^ is_major_dir ) + { + FT_Pos dist; + AF_Width compare; + + + /* if it's a rounded edge, compare it to the overshoot position */ + /* if it's a flat edge, compare it to the reference position */ + if ( edge->flags & AF_EDGE_ROUND ) + 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 0 + /* 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 */ + if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) + { + FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); + + + if ( is_top_blue ^ is_under_ref ) + { + blue = latin->blues + bb; + dist = edge->fpos - blue->shoot.org; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, scale ); + if ( dist < best_dist ) + { + best_dist = dist; + best_blue = & blue->shoot; + } + } + } +#endif + } + } + + if ( best_blue ) + edge->blue_edge = best_blue; + } + } + + + static FT_Error + af_latin2_hints_init( AF_GlyphHints hints, + AF_LatinMetrics metrics ) + { + FT_Render_Mode mode; + FT_UInt32 scaler_flags, other_flags; + FT_Face face = metrics->root.scaler.face; + + + af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); + + /* + * correct x_scale and y_scale if needed, since they may have + * been modified `af_latin2_metrics_scale_dim' above + */ + hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale; + hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta; + hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale; + hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta; + + /* compute flags depending on render mode, etc. */ + mode = metrics->root.scaler.render_mode; + +#if 0 /* #ifdef AF_USE_WARPER */ + if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) + { + metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; + } +#endif + + scaler_flags = hints->scaler_flags; + other_flags = 0; + + /* + * We snap the width of vertical stems for the monochrome and + * horizontal LCD rendering targets only. + */ + if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD ) + other_flags |= AF_LATIN_HINTS_HORZ_SNAP; + + /* + * We snap the width of horizontal stems for the monochrome and + * vertical LCD rendering targets only. + */ + if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V ) + other_flags |= AF_LATIN_HINTS_VERT_SNAP; + + /* + * We adjust stems to full pixels only if we don't use the `light' mode. + */ + if ( mode != FT_RENDER_MODE_LIGHT ) + other_flags |= AF_LATIN_HINTS_STEM_ADJUST; + + if ( mode == FT_RENDER_MODE_MONO ) + other_flags |= AF_LATIN_HINTS_MONO; + + /* + * 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 ) + scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; + + hints->scaler_flags = scaler_flags; + hints->other_flags = other_flags; + + return 0; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** L A T I N G L Y P H G R I D - F I T T I N G *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* snap a given width in scaled coordinates to one of the */ + /* current standard widths */ + + static FT_Pos + af_latin2_snap_width( AF_Width widths, + FT_Int count, + FT_Pos width ) + { + int n; + FT_Pos best = 64 + 32 + 2; + FT_Pos reference = width; + FT_Pos scaled; + + + for ( n = 0; n < count; n++ ) + { + FT_Pos w; + FT_Pos dist; + + + w = widths[n].cur; + dist = width - w; + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) + { + best = dist; + reference = w; + } + } + + scaled = FT_PIX_ROUND( reference ); + + if ( width >= reference ) + { + if ( width < scaled + 48 ) + width = reference; + } + else + { + if ( width > scaled - 48 ) + width = reference; + } + + return width; + } + + + /* compute the snapped width of a given stem */ + + 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_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 ); + + + FT_UNUSED(base_flags); + + if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || + axis->extra_light ) + return width; + + if ( dist < 0 ) + { + dist = -width; + sign = 1; + } + + if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) + { + /* 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 ) ) + goto Done_Width; + +#if 0 + else if ( ( base_flags & AF_EDGE_ROUND ) ) + { + if ( dist < 80 ) + dist = 64; + } + else if ( dist < 56 ) + dist = 56; +#endif + if ( axis->width_count > 0 ) + { + FT_Pos delta; + + + /* compare to standard width */ + if ( axis->width_count > 0 ) + { + delta = dist - axis->widths[0].cur; + + if ( delta < 0 ) + delta = -delta; + + if ( delta < 40 ) + { + dist = axis->widths[0].cur; + if ( dist < 48 ) + dist = 48; + + goto Done_Width; + } + } + + if ( dist < 3 * 64 ) + { + delta = dist & 63; + dist &= -64; + + if ( delta < 10 ) + dist += delta; + + else if ( delta < 32 ) + dist += 10; + + else if ( delta < 54 ) + dist += 54; + + else + dist += delta; + } + else + dist = ( dist + 32 ) & ~63; + } + } + else + { + /* strong hinting process: snap the stem width to integer pixels */ + FT_Pos org_dist = dist; + + + dist = af_latin2_snap_width( axis->widths, axis->width_count, dist ); + + if ( vertical ) + { + /* in the case of vertical hinting, always round */ + /* the stem heights to integer pixels */ + + if ( dist >= 64 ) + dist = ( dist + 16 ) & ~63; + else + dist = 64; + } + else + { + if ( AF_LATIN_HINTS_DO_MONO( hints ) ) + { + /* monochrome horizontal hinting: snap widths to integer pixels */ + /* with a different threshold */ + + if ( dist < 64 ) + dist = 64; + else + dist = ( dist + 32 ) & ~63; + } + else + { + /* for horizontal anti-aliased hinting, we adopt a more subtle */ + /* approach: we strengthen small stems, round stems whose size */ + /* is between 1 and 2 pixels to an integer, otherwise nothing */ + + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + + else if ( dist < 128 ) + { + /* We only round to an integer width if the corresponding */ + /* distortion is less than 1/4 pixel. Otherwise this */ + /* makes everything worse since the diagonals, which are */ + /* not hinted, appear a lot bolder or thinner than the */ + /* vertical stems. */ + + FT_Int delta; + + + dist = ( dist + 22 ) & ~63; + delta = dist - org_dist; + if ( delta < 0 ) + delta = -delta; + + if (delta >= 16) + { + dist = org_dist; + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + } + } + else + /* round otherwise to prevent color fringes in LCD mode */ + dist = ( dist + 32 ) & ~63; + } + } + } + + Done_Width: + if ( sign ) + dist = -dist; + + return dist; + } + + + /* align one stem edge relative to the previous stem edge */ + + static void + af_latin2_align_linked_edge( AF_GlyphHints hints, + AF_Dimension dim, + AF_Edge base_edge, + AF_Edge stem_edge ) + { + FT_Pos dist = stem_edge->opos - base_edge->opos; + + FT_Pos fitted_width = af_latin2_compute_stem_width( + hints, dim, dist, + (AF_Edge_Flags)base_edge->flags, + (AF_Edge_Flags)stem_edge->flags ); + + + 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 )); + } + + + static void + af_latin2_align_serif_edge( AF_GlyphHints hints, + AF_Edge base, + AF_Edge serif ) + { + FT_UNUSED( hints ); + + serif->pos = base->pos + (serif->opos - base->opos); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** E D G E H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( void ) + af_latin2_hint_edges( AF_GlyphHints hints, + AF_Dimension dim ) + { + AF_AxisHints axis = &hints->axis[dim]; + AF_Edge edges = axis->edges; + AF_Edge edge_limit = edges + axis->num_edges; + FT_Int n_edges; + AF_Edge edge; + AF_Edge anchor = 0; + FT_Int has_serifs = 0; + FT_Pos anchor_drift = 0; + + + + AF_LOG(( "==== 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 */ + + if ( dim == AF_DIMENSION_VERT && 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; + + 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 )); + + edge1->pos = blue->fit; + edge1->flags |= AF_EDGE_DONE; + + if ( edge2 && !edge2->blue_edge ) + { + af_latin2_align_linked_edge( hints, dim, edge1, edge2 ); + edge2->flags |= AF_EDGE_DONE; + } + + if ( !anchor ) + { + anchor = edge; + + anchor_drift = (anchor->pos - anchor->opos); + if (edge2) + anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1; + } + } + } + + /* now we will align all stem edges, trying to maintain the */ + /* relative order of stems in the glyph */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + AF_Edge edge2; + + + if ( edge->flags & AF_EDGE_DONE ) + continue; + + /* skip all non-stem edges */ + edge2 = edge->link; + if ( !edge2 ) + { + has_serifs++; + continue; + } + + /* now align the stem */ + + /* 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 )); + + af_latin2_align_linked_edge( hints, dim, edge2, edge ); + edge->flags |= AF_EDGE_DONE; + continue; + } + + if ( !anchor ) + { + FT_Pos org_len, org_center, cur_len; + FT_Pos cur_pos1, error1, error2, u_off, d_off; + + + org_len = edge2->opos - edge->opos; + cur_len = af_latin2_compute_stem_width( + hints, dim, org_len, + (AF_Edge_Flags)edge->flags, + (AF_Edge_Flags)edge2->flags ); + if ( cur_len <= 64 ) + u_off = d_off = 32; + else + { + u_off = 38; + d_off = 26; + } + + 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 ); + if ( error1 < 0 ) + error1 = -error1; + + error2 = org_center - ( cur_pos1 + d_off ); + if ( error2 < 0 ) + error2 = -error2; + + if ( error1 < error2 ) + cur_pos1 -= u_off; + else + cur_pos1 += d_off; + + edge->pos = cur_pos1 - cur_len / 2; + edge2->pos = edge->pos + cur_len; + } + 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 )); + anchor = edge; + + edge->flags |= AF_EDGE_DONE; + + af_latin2_align_linked_edge( hints, dim, edge, edge2 ); + + edge2->flags |= AF_EDGE_DONE; + + anchor_drift = ( (anchor->pos - anchor->opos) + + (edge2->pos - edge2->opos)) >> 1; + + AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 )); + } + else + { + FT_Pos org_pos, org_len, org_center, cur_center, cur_len; + FT_Pos org_left, org_right; + + + org_pos = edge->opos + anchor_drift; + org_len = edge2->opos - edge->opos; + org_center = org_pos + ( org_len >> 1 ); + + cur_len = af_latin2_compute_stem_width( + hints, dim, org_len, + (AF_Edge_Flags)edge->flags, + (AF_Edge_Flags)edge2->flags ); + + 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 )); + cur_center = org_center; + + if ( edge2->flags & AF_EDGE_DONE ) + { + AF_LOG(( "\n" )); + edge->pos = edge2->pos - cur_len; + } + else + { + /* we want to compare several displacement, and choose + * the one that increases fitness while minimizing + * distortion as well + */ + FT_Pos displacements[6], scores[6], org, fit, delta; + FT_UInt count = 0; + + /* note: don't even try to fit tiny stems */ + if ( cur_len < 32 ) + { + AF_LOG(( "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" )); + goto AlignStem; + } + + if (cur_len <= 96) + { + /* we want to avoid the absolute worst case which is + * when the left and right edges of the span each represent + * about 50% of the gray. we'd better want to change this + * to 25/75%, since this is much more pleasant to the eye with + * very acceptable distortion + */ + FT_Pos frac_left = (org_left) & 63; + FT_Pos frac_right = (org_right) & 63; + + if ( frac_left >= 22 && frac_left <= 42 && + frac_right >= 22 && frac_right <= 42 ) + { + org = frac_left; + fit = (org <= 32) ? 16 : 48; + delta = FT_ABS(fit - org); + displacements[count] = fit - org; + scores[count++] = delta; + AF_LOG(( "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 )); + } + } + + /* snapping the left edge to the grid */ + org = org_left; + fit = FT_PIX_ROUND(org); + delta = FT_ABS(fit - org); + displacements[count] = fit - org; + scores[count++] = delta; + AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta )); + + /* snapping the right edge to the grid */ + org = org_right; + fit = FT_PIX_ROUND(org); + delta = FT_ABS(fit - org); + displacements[count] = fit - org; + scores[count++] = delta; + AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta )); + + /* now find the best displacement */ + { + FT_Pos best_score = scores[0]; + FT_Pos best_disp = displacements[0]; + FT_UInt nn; + + for (nn = 1; nn < count; nn++) + { + if (scores[nn] < best_score) + { + best_score = scores[nn]; + best_disp = displacements[nn]; + } + } + + cur_center = org_center + best_disp; + } + AF_LOG(( "\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 )); + + 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 )); + edge->pos = edge[-1].pos; + } + } + } + + /* make sure that lowercase m's maintain their symmetry */ + + /* In general, lowercase m's have six vertical edges if they are sans */ + /* serif, or twelve if they are with serifs. This implementation is */ + /* based on that assumption, and seems to work very well with most */ + /* faces. However, if for a certain face this assumption is not */ + /* true, the m is just rendered like before. In addition, any stem */ + /* correction will only be applied to symmetrical glyphs (even if the */ + /* glyph is not an m), so the potential for unwanted distortion is */ + /* relatively low. */ + + /* We don't handle horizontal edges since we can't easily assure that */ + /* the third (lowest) stem aligns with the base line; it might end up */ + /* one pixel higher or lower. */ +#if 0 + n_edges = edge_limit - edges; + if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) + { + AF_Edge edge1, edge2, edge3; + FT_Pos dist1, dist2, span, delta; + + + if ( n_edges == 6 ) + { + edge1 = edges; + edge2 = edges + 2; + edge3 = edges + 4; + } + else + { + edge1 = edges + 1; + edge2 = edges + 5; + edge3 = edges + 9; + } + + dist1 = edge2->opos - edge1->opos; + dist2 = edge3->opos - edge2->opos; + + span = dist1 - dist2; + if ( span < 0 ) + span = -span; + + if ( span < 8 ) + { + delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); + edge3->pos -= delta; + if ( edge3->link ) + edge3->link->pos -= delta; + + /* move the serifs along with the stem */ + if ( n_edges == 12 ) + { + ( edges + 8 )->pos -= delta; + ( edges + 11 )->pos -= delta; + } + + edge3->flags |= AF_EDGE_DONE; + if ( edge3->link ) + edge3->link->flags |= AF_EDGE_DONE; + } + } +#endif + if ( has_serifs || !anchor ) + { + /* + * now hint the remaining edges (serifs and single) in order + * to complete our processing + */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Pos delta; + + + if ( edge->flags & AF_EDGE_DONE ) + continue; + + delta = 1000; + + if ( edge->serif ) + { + delta = edge->serif->opos - edge->opos; + if ( delta < 0 ) + delta = -delta; + } + + 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 )); + } + 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; + } + else + { + AF_Edge before, after; + + + for ( before = edge - 1; before >= edges; before-- ) + if ( before->flags & AF_EDGE_DONE ) + break; + + for ( after = edge + 1; after < edge_limit; after++ ) + if ( after->flags & AF_EDGE_DONE ) + break; + + if ( before >= edges && before < edge && + after < edge_limit && after > edge ) + { + edge->pos = before->pos + + 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 )); + } + 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 )); + } + } + + edge->flags |= AF_EDGE_DONE; + + if ( edge > edges && edge->pos < edge[-1].pos ) + edge->pos = edge[-1].pos; + + if ( edge + 1 < edge_limit && + edge[1].flags & AF_EDGE_DONE && + edge->pos > edge[1].pos ) + edge->pos = edge[1].pos; + } + } + } + + + static FT_Error + af_latin2_hints_apply( AF_GlyphHints hints, + FT_Outline* outline, + AF_LatinMetrics metrics ) + { + FT_Error error; + int dim; + + + error = af_glyph_hints_reload( hints, outline, 1 ); + if ( error ) + goto Exit; + + /* analyze glyph outline */ +#ifdef AF_USE_WARPER + if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT || + AF_HINTS_DO_HORIZONTAL( hints ) ) +#else + if ( AF_HINTS_DO_HORIZONTAL( hints ) ) +#endif + { + error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ ); + if ( error ) + goto Exit; + } + + if ( AF_HINTS_DO_VERTICAL( hints ) ) + { + error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT ); + if ( error ) + goto Exit; + + af_latin2_hints_compute_blue_edges( hints, metrics ); + } + + /* 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 ) ) + { + 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 ); + continue; + } +#endif + + if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || + ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) + { + af_latin2_hint_edges( hints, (AF_Dimension)dim ); + af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim ); + af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); + af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); + } + } + af_glyph_hints_save( hints, outline ); + + Exit: + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** L A T I N S C R I P T C L A S S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static const AF_Script_UniRangeRec af_latin2_uniranges[] = + { + { 32, 127 }, /* XXX: TODO: Add new Unicode ranges here! */ + { 160, 255 }, + { 0, 0 } + }; + + + FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec + af_latin2_script_class = + { + AF_SCRIPT_LATIN2, + af_latin2_uniranges, + + sizeof( AF_LatinMetricsRec ), + + (AF_Script_InitMetricsFunc) af_latin2_metrics_init, + (AF_Script_ScaleMetricsFunc)af_latin2_metrics_scale, + (AF_Script_DoneMetricsFunc) NULL, + + (AF_Script_InitHintsFunc) af_latin2_hints_init, + (AF_Script_ApplyHintsFunc) af_latin2_hints_apply + }; + + +/* END */ diff --git a/src/libs/freetype2/autofit/aflatin2.h b/src/libs/freetype2/autofit/aflatin2.h new file mode 100644 index 0000000000..34eda05822 --- /dev/null +++ b/src/libs/freetype2/autofit/aflatin2.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* aflatin2.h */ +/* */ +/* Auto-fitter hinting routines for latin script (specification). */ +/* */ +/* Copyright 2003, 2004, 2005, 2006, 2007 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __AFLATIN2_H__ +#define __AFLATIN2_H__ + +#include "afhints.h" + + +FT_BEGIN_HEADER + + + /* the latin-specific script class */ + + FT_CALLBACK_TABLE const AF_ScriptClassRec + af_latin2_script_class; + +/* */ + +FT_END_HEADER + +#endif /* __AFLATIN_H__ */ + + +/* END */ diff --git a/src/libs/freetype2/autofit/afloader.c b/src/libs/freetype2/autofit/afloader.c index 1633e9e7fc..4e4373a492 100644 --- a/src/libs/freetype2/autofit/afloader.c +++ b/src/libs/freetype2/autofit/afloader.c @@ -173,7 +173,7 @@ /* width/positioning that occurred during the hinting process */ if ( scaler->render_mode != FT_RENDER_MODE_LIGHT ) { - FT_Pos old_advance, old_rsb, old_lsb, new_lsb; + FT_Pos old_rsb, old_lsb, new_lsb; FT_Pos pp1x_uh, pp2x_uh; AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ]; AF_Edge edge1 = axis->edges; /* leftmost edge */ @@ -183,7 +183,6 @@ if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) { - old_advance = loader->pp2.x - loader->pp1.x; old_rsb = loader->pp2.x - edge2->opos; old_lsb = edge1->opos; new_lsb = edge1->pos; @@ -391,12 +390,12 @@ FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix ); FT_Vector_Transform( &vvector, &loader->trans_matrix ); } - +#if 1 /* we must translate our final outline by -pp1.x and compute */ /* the new metrics */ if ( loader->pp1.x ) FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 ); - +#endif FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); @@ -493,10 +492,17 @@ if ( !error ) { AF_ScriptMetrics metrics; + FT_UInt options = 0; +#ifdef FT_OPTION_AUTOFIT2 + /* XXX: undocumented hook to activate the latin2 hinter */ + if ( load_flags & ( 1UL << 20 ) ) + options = 2; +#endif + error = af_face_globals_get_metrics( loader->globals, gindex, - &metrics ); + options, &metrics ); if ( !error ) { loader->metrics = metrics; diff --git a/src/libs/freetype2/autofit/aftypes.h b/src/libs/freetype2/autofit/aftypes.h index 617274d021..bd3fa88230 100644 --- a/src/libs/freetype2/autofit/aftypes.h +++ b/src/libs/freetype2/autofit/aftypes.h @@ -265,6 +265,11 @@ extern void* _af_debug_hints; AF_SCRIPT_NONE = 0, AF_SCRIPT_LATIN = 1, AF_SCRIPT_CJK = 2, + AF_SCRIPT_INDIC = 3, +#ifdef FT_OPTION_AUTOFIT2 + AF_SCRIPT_LATIN2, +#endif + /* add new scripts here. Don't forget to update the list in */ /* `afglobal.c'. */ diff --git a/src/libs/freetype2/autofit/autofit.c b/src/libs/freetype2/autofit/autofit.c index b4b304068e..2fe66a990e 100644 --- a/src/libs/freetype2/autofit/autofit.c +++ b/src/libs/freetype2/autofit/autofit.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter module (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,9 +21,15 @@ #include "afangles.c" #include "afglobal.c" #include "afhints.c" + #include "afdummy.c" #include "aflatin.c" +#ifdef FT_OPTION_AUTOFIT2 +#include "aflatin2.c" +#endif #include "afcjk.c" +#include "afindic.c" + #include "afloader.c" #include "afmodule.c" diff --git a/src/libs/freetype2/autofit/rules.mk b/src/libs/freetype2/autofit/rules.mk index 8d6f668f52..017489d9e0 100644 --- a/src/libs/freetype2/autofit/rules.mk +++ b/src/libs/freetype2/autofit/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 2003, 2004, 2005, 2006 by +# Copyright 2003, 2004, 2005, 2006, 2007 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -26,11 +26,12 @@ AUTOF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(AUTOF_DIR)) # AUTOF driver sources (i.e., C files) # AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \ + $(AUTOF_DIR)/afcjk.c \ $(AUTOF_DIR)/afdummy.c \ $(AUTOF_DIR)/afglobal.c \ $(AUTOF_DIR)/afhints.c \ + $(AUTOF_DIR)/afindic.c \ $(AUTOF_DIR)/aflatin.c \ - $(AUTOF_DIR)/afcjk.c \ $(AUTOF_DIR)/afloader.c \ $(AUTOF_DIR)/afmodule.c \ $(AUTOF_DIR)/afwarp.c diff --git a/src/libs/freetype2/base/Jamfile b/src/libs/freetype2/base/Jamfile index d1571d4d17..dd268f9b42 100644 --- a/src/libs/freetype2/base/Jamfile +++ b/src/libs/freetype2/base/Jamfile @@ -38,7 +38,7 @@ UseFreeTypeHeaders ; local _sources = system init glyph mm bdf bbox debug xf86 type1 pfr stroke winfnt otval bitmap synth - gxval lcdfil gasp + gxval lcdfil gasp patent ; FT2_Library $(FT2_LIB) : ft$(_sources).c ; diff --git a/src/libs/freetype2/base/ftcalc.c b/src/libs/freetype2/base/ftcalc.c index b7fb78199d..63aed95b75 100644 --- a/src/libs/freetype2/base/ftcalc.c +++ b/src/libs/freetype2/base/ftcalc.c @@ -743,7 +743,6 @@ } else /* general case */ { - #ifdef FT_LONG64 FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x; diff --git a/src/libs/freetype2/base/ftglyph.c b/src/libs/freetype2/base/ftglyph.c index af0eadf728..969c5dbb05 100644 --- a/src/libs/freetype2/base/ftglyph.c +++ b/src/libs/freetype2/base/ftglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType convenience functions to handle glyphs (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -376,6 +376,8 @@ const FT_Glyph_Class* clazz; + *target = 0; + /* check arguments */ if ( !target || !source || !source->clazz ) { @@ -383,8 +385,6 @@ goto Exit; } - *target = 0; - clazz = source->clazz; error = ft_new_glyph( source->library, clazz, © ); if ( error ) diff --git a/src/libs/freetype2/base/ftmac.c b/src/libs/freetype2/base/ftmac.c index d696586071..fd6201adb5 100644 --- a/src/libs/freetype2/base/ftmac.c +++ b/src/libs/freetype2/base/ftmac.c @@ -105,6 +105,10 @@ FSSpec* pathSpec, FT_Long* face_index ) { + FT_UNUSED( fontName ); + FT_UNUSED( pathSpec ); + FT_UNUSED( face_index ); + return FT_Err_Unimplemented_Feature; } @@ -118,6 +122,12 @@ FT_ATSFontGetFileReference( ATSFontRef ats_font_id, FSRef* ats_font_ref ) { +#if __LP64__ + FT_UNUSED( ats_font_id ); + FT_UNUSED( ats_font_ref ); + + return fnfErr; +#else OSStatus err; FSSpec spec; @@ -127,6 +137,7 @@ err = FSpMakeFSRef( &spec, ats_font_ref ); return err; +#endif } @@ -204,11 +215,12 @@ FT_Long* face_index ) { #if __LP64__ + FT_UNUSED( fontName ); + FT_UNUSED( pathSpec ); + FT_UNUSED( face_index ); return FT_Err_Unimplemented_Feature; - #else - FSRef ref; FT_Error err; @@ -222,7 +234,6 @@ return FT_Err_Unknown_File_Format; return FT_Err_Ok; - #endif } @@ -447,10 +458,10 @@ static FT_Error - lookup_lwfn_by_fond( const UInt8* path_fond, - const StringPtr base_lwfn, - UInt8* path_lwfn, - int path_size ) + lookup_lwfn_by_fond( const UInt8* path_fond, + ConstStr255Param base_lwfn, + UInt8* path_lwfn, + size_t path_size ) { FSRef ref, par_ref; int dirname_len; @@ -472,12 +483,8 @@ if ( ft_strlen( (char *)path_lwfn ) + 1 + base_lwfn[0] > path_size ) return FT_Err_Invalid_Argument; - /* now we have absolute dirname in lookup_path */ - if ( path_lwfn[0] == '/' ) - ft_strcat( (char *)path_lwfn, "/" ); - else - ft_strcat( (char *)path_lwfn, ":" ); - + /* now we have absolute dirname in path_lwfn */ + ft_strcat( (char *)path_lwfn, "/" ); dirname_len = ft_strlen( (char *)path_lwfn ); ft_strcat( (char *)path_lwfn, (char *)base_lwfn + 1 ); path_lwfn[dirname_len + base_lwfn[0]] = '\0'; @@ -507,7 +514,6 @@ have_sfnt = have_lwfn = 0; - HLock( fond ); parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 ); if ( lwfn_file_name[0] ) @@ -523,7 +529,6 @@ else num_faces = count_faces_scalable( *fond ); - HUnlock( fond ); return num_faces; } @@ -810,9 +815,7 @@ return error; } - HLock( sfnt ); ft_memcpy( sfnt_data, *sfnt, sfnt_size ); - HUnlock( sfnt ); ReleaseResource( sfnt ); is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' && @@ -894,9 +897,7 @@ if ( ResError() != noErr || fond_type != 'FOND' ) return FT_Err_Invalid_File_Format; - HLock( fond ); parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index ); - HUnlock( fond ); if ( lwfn_file_name[0] ) { @@ -1073,6 +1074,14 @@ FT_Long face_index, FT_Face* aface ) { +#if __LP64__ + FT_UNUSED( library ); + FT_UNUSED( spec ); + FT_UNUSED( face_index ); + FT_UNUSED( aface ); + + return FT_Err_Unimplemented_Feature; +#else FSRef ref; @@ -1080,6 +1089,7 @@ return FT_Err_Invalid_Argument; else return FT_New_Face_From_FSRef( library, &ref, face_index, aface ); +#endif } diff --git a/src/libs/freetype2/base/ftobjs.c b/src/libs/freetype2/base/ftobjs.c index f9eceb7fb8..fa08094004 100644 --- a/src/libs/freetype2/base/ftobjs.c +++ b/src/libs/freetype2/base/ftobjs.c @@ -92,14 +92,14 @@ /* since the cast below also disables the compiler's */ /* type check, we introduce a dummy variable, which */ /* will be optimized away */ - volatile jmp_buf* jump_buffer = &valid->jump_buffer; + volatile ft_jmp_buf* jump_buffer = &valid->jump_buffer; valid->error = error; /* throw away volatileness; use `jump_buffer' or the */ /* compiler may warn about an unused local variable */ - ft_longjmp( *(jmp_buf*) jump_buffer, 1 ); + ft_longjmp( *(ft_jmp_buf*) jump_buffer, 1 ); } @@ -787,6 +787,9 @@ FT_Int n; + if ( !face ) + return; + for ( n = 0; n < face->num_charmaps; n++ ) { FT_CMap cmap = FT_CMAP( face->charmaps[n] ); @@ -1198,7 +1201,7 @@ { FT_Open_Args args; FT_Error error; - FT_Stream stream; + FT_Stream stream = NULL; FT_Memory memory = library->memory; @@ -2223,16 +2226,14 @@ FT_Request_Metrics( FT_Face face, FT_Size_Request req ) { - FT_Driver_Class clazz; FT_Size_Metrics* metrics; - clazz = face->driver->clazz; metrics = &face->size->metrics; if ( FT_IS_SCALABLE( face ) ) { - FT_Long w, h, scaled_w = 0, scaled_h = 0; + FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0; switch ( req->type ) @@ -2245,16 +2246,16 @@ w = h = face->ascender - face->descender; break; - case FT_SIZE_REQUEST_TYPE_CELL: - w = face->max_advance_width; - h = face->ascender - face->descender; - break; - case FT_SIZE_REQUEST_TYPE_BBOX: w = face->bbox.xMax - face->bbox.xMin; h = face->bbox.yMax - face->bbox.yMin; break; + case FT_SIZE_REQUEST_TYPE_CELL: + w = face->max_advance_width; + h = face->ascender - face->descender; + break; + case FT_SIZE_REQUEST_TYPE_SCALES: metrics->x_scale = (FT_Fixed)req->width; metrics->y_scale = (FT_Fixed)req->height; @@ -2263,11 +2264,8 @@ else if ( !metrics->y_scale ) metrics->y_scale = metrics->x_scale; goto Calculate_Ppem; - break; - default: - /* this never happens */ - return; + case FT_SIZE_REQUEST_TYPE_MAX: break; } @@ -2435,11 +2433,14 @@ if ( char_height < 1 * 64 ) char_height = 1 * 64; + if ( !horz_resolution ) + horz_resolution = vert_resolution = 72; + req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; req.width = char_width; req.height = char_height; - req.horiResolution = ( horz_resolution ) ? horz_resolution : 72; - req.vertResolution = ( vert_resolution ) ? vert_resolution : 72; + req.horiResolution = horz_resolution; + req.vertResolution = vert_resolution; return FT_Request_Size( face, &req ); } @@ -2551,7 +2552,6 @@ { FT_Service_Kerning service; FT_Error error = FT_Err_Ok; - FT_Driver driver; if ( !face ) @@ -2560,8 +2560,6 @@ if ( !akerning ) return FT_Err_Invalid_Argument; - driver = face->driver; - FT_FACE_FIND_SERVICE( face, service, KERNING ); if ( !service ) return FT_Err_Unimplemented_Feature; @@ -3030,6 +3028,30 @@ } + /* documentation is in tttables.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_Get_CMap_Format( FT_CharMap charmap ) + { + FT_Service_TTCMaps service; + FT_Face face; + TT_CMapInfo cmap_info; + + + if ( !charmap || !charmap->face ) + return -1; + + face = charmap->face; + FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); + if ( service == NULL ) + return -1; + if ( service->get_cmap_info( charmap, &cmap_info )) + return -1; + + return cmap_info.format; + } + + /* documentation is in ftsizes.h */ FT_EXPORT_DEF( FT_Error ) @@ -3703,8 +3725,9 @@ /* allocate the render pool */ library->raster_pool_size = FT_RENDER_POOL_SIZE; - if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) - goto Fail; + if ( FT_RENDER_POOL_SIZE > 0 ) + if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) + goto Fail; /* That's ok now */ *alibrary = library; diff --git a/src/libs/freetype2/base/ftoutln.c b/src/libs/freetype2/base/ftoutln.c index 2a35659e1a..6926f3a09a 100644 --- a/src/libs/freetype2/base/ftoutln.c +++ b/src/libs/freetype2/base/ftoutln.c @@ -83,7 +83,9 @@ FT_Int last; /* index of last point in contour */ - last = outline->contours[n]; + last = outline->contours[n]; + if ( last < 0 ) + goto Invalid_Outline; limit = outline->points + last; v_start = outline->points[first]; diff --git a/src/libs/freetype2/base/ftpatent.c b/src/libs/freetype2/base/ftpatent.c new file mode 100644 index 0000000000..d63f191c3e --- /dev/null +++ b/src/libs/freetype2/base/ftpatent.c @@ -0,0 +1,281 @@ +/***************************************************************************/ +/* */ +/* ftpatent.c */ +/* */ +/* FreeType API for checking patented TrueType bytecode instructions */ +/* (body). */ +/* */ +/* Copyright 2007 by David Turner. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#include +#include FT_FREETYPE_H +#include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H +#include FT_SERVICE_SFNT_H +#include FT_SERVICE_TRUETYPE_GLYF_H + + + static FT_Bool + _tt_check_patents_in_range( FT_Stream stream, + FT_ULong size ) + { + FT_Bool result = FALSE; + FT_Error error; + FT_Bytes p, end; + + + if ( FT_FRAME_ENTER( size ) ) + return 0; + + p = stream->cursor; + end = p + size; + + while ( p < end ) + { + switch (p[0]) + { + case 0x06: /* SPvTL // */ + case 0x07: /* SPvTL + */ + case 0x08: /* SFvTL // */ + case 0x09: /* SFvTL + */ + case 0x0A: /* SPvFS */ + case 0x0B: /* SFvFS */ + result = TRUE; + goto Exit; + + case 0x40: + if ( p + 1 >= end ) + goto Exit; + + p += p[1] + 2; + break; + + case 0x41: + if ( p + 1 >= end ) + goto Exit; + + p += p[1] * 2 + 2; + break; + + case 0x71: /* DELTAP2 */ + case 0x72: /* DELTAP3 */ + case 0x73: /* DELTAC0 */ + case 0x74: /* DELTAC1 */ + case 0x75: /* DELTAC2 */ + result = TRUE; + goto Exit; + + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + p += ( p[0] - 0xB0 ) + 2; + break; + + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + p += ( p[0] - 0xB8 ) * 2 + 3; + break; + + default: + p += 1; + break; + } + } + + Exit: + FT_FRAME_EXIT(); + return result; + } + + + static FT_Bool + _tt_check_patents_in_table( FT_Face face, + FT_ULong tag ) + { + FT_Stream stream = face->stream; + FT_Error error; + FT_Service_SFNT_Table service; + FT_Bool result = FALSE; + + + FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); + + if ( service ) + { + FT_ULong offset, size; + + + error = service->table_info( face, tag, &offset, &size ); + if ( error || + FT_STREAM_SEEK( offset ) ) + goto Exit; + + result = _tt_check_patents_in_range( stream, size ); + } + + Exit: + return result; + } + + + static FT_Bool + _tt_face_check_patents( FT_Face face ) + { + FT_Stream stream = face->stream; + FT_UInt gindex; + FT_Error error; + FT_Bool result; + + FT_Service_TTGlyf service; + + + result = _tt_check_patents_in_table( face, TTAG_fpgm ); + if ( result ) + goto Exit; + + result = _tt_check_patents_in_table( face, TTAG_prep ); + if ( result ) + goto Exit; + + FT_FACE_FIND_SERVICE( face, service, TT_GLYF ); + if ( service == NULL ) + goto Exit; + + for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ ) + { + FT_ULong offset, num_ins, size; + FT_Int num_contours; + + + offset = service->get_location( face, gindex, &size ); + if ( size == 0 ) + continue; + + if ( FT_STREAM_SEEK( offset ) || + FT_READ_SHORT( num_contours ) ) + continue; + + if ( num_contours >= 0 ) /* simple glyph */ + { + if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) ) + continue; + } + else /* compound glyph */ + { + FT_Bool has_instr = 0; + + + if ( FT_STREAM_SKIP( 8 ) ) + continue; + + /* now read each component */ + for (;;) + { + FT_UInt flags, toskip; + + + if( FT_READ_USHORT( flags ) ) + break; + + toskip = 2 + 1 + 1; + + if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */ + toskip += 2; + + if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */ + toskip += 2; + else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */ + toskip += 4; + else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */ + toskip += 8; + + if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */ + has_instr = 1; + + if ( FT_STREAM_SKIP( toskip ) ) + goto NextGlyph; + + if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */ + break; + } + + if ( !has_instr ) + goto NextGlyph; + } + + if ( FT_READ_USHORT( num_ins ) ) + continue; + + result = _tt_check_patents_in_range( stream, num_ins ); + if ( result ) + goto Exit; + + NextGlyph: + ; + } + + Exit: + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Face_CheckTrueTypePatents( FT_Face face ) + { + FT_Bool result = FALSE; + + + if ( face && FT_IS_SFNT( face ) ) + result = _tt_face_check_patents( face ); + + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Bool ) + FT_Face_SetUnpatentedHinting( FT_Face face, + FT_Bool value ) + { + FT_Bool result = 0; + + +#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ + !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER ) + if ( face && FT_IS_SFNT( face ) ) + { + result = !face->internal->ignore_unpatented_hinter; + face->internal->ignore_unpatented_hinter = !value; + } +#else + FT_UNUSED( face ); + FT_UNUSED( value ); +#endif + + return result; + } + +/* END */ diff --git a/src/libs/freetype2/bdf/bdflib.c b/src/libs/freetype2/bdf/bdflib.c index 93061bb830..512cd62c3e 100644 --- a/src/libs/freetype2/bdf/bdflib.c +++ b/src/libs/freetype2/bdf/bdflib.c @@ -1537,6 +1537,12 @@ s = _bdf_list_join( &p->list, ' ', &slen ); + if ( !s ) + { + error = BDF_Err_Invalid_File_Format; + goto Exit; + } + if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) ) goto Exit; @@ -2117,6 +2123,13 @@ _bdf_list_shift( &p->list, 1 ); s = _bdf_list_join( &p->list, ' ', &slen ); + + if ( !s ) + { + error = BDF_Err_Invalid_File_Format; + goto Exit; + } + if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) ) goto Exit; FT_MEM_COPY( p->font->name, s, slen + 1 ); @@ -2301,11 +2314,19 @@ { /* The ENDFONT field was never reached or did not exist. */ if ( !( p->flags & _BDF_GLYPHS ) ) + { /* Error happened while parsing header. */ FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno )); + error = BDF_Err_Corrupted_Font_Header; + goto Exit; + } else + { /* Error happened when parsing glyphs. */ FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno )); + error = BDF_Err_Corrupted_Font_Glyphs; + goto Exit; + } } } diff --git a/src/libs/freetype2/cache/ftcbasic.c b/src/libs/freetype2/cache/ftcbasic.c index e9e8135ae9..a568b975bb 100644 --- a/src/libs/freetype2/cache/ftcbasic.c +++ b/src/libs/freetype2/cache/ftcbasic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType basic cache interface (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -383,6 +383,62 @@ } + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_ImageCache_LookupScaler( FTC_ImageCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ) + { + FTC_BasicQueryRec query; + FTC_INode node = 0; /* make compiler happy */ + FT_Error error; + FT_UInt32 hash; + + + /* some argument checks are delayed to FTC_Cache_Lookup */ + if ( !aglyph || !scaler ) + { + error = FTC_Err_Invalid_Argument; + goto Exit; + } + + *aglyph = NULL; + if ( anode ) + *anode = NULL; + + query.attrs.scaler = scaler[0]; + query.attrs.load_flags = load_flags; + + hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; + + FTC_GCACHE_LOOKUP_CMP( cache, + ftc_basic_family_compare, + FTC_GNode_Compare, + hash, gindex, + &query, + node, + error ); + if ( !error ) + { + *aglyph = FTC_INODE( node )->glyph; + + if ( anode ) + { + *anode = FTC_NODE( node ); + FTC_NODE( node )->ref_count++; + } + } + + Exit: + return error; + } + + + #ifdef FT_CONFIG_OPTION_OLD_INTERNALS /* yet another backwards-legacy structure */ @@ -652,6 +708,61 @@ } + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_SBitCache_LookupScaler( FTC_SBitCache cache, + FTC_Scaler scaler, + FT_ULong load_flags, + FT_UInt gindex, + FTC_SBit *ansbit, + FTC_Node *anode ) + { + FT_Error error; + FTC_BasicQueryRec query; + FTC_SNode node = 0; /* make compiler happy */ + FT_UInt32 hash; + + + if ( anode ) + *anode = NULL; + + /* other argument checks delayed to FTC_Cache_Lookup */ + if ( !ansbit || !scaler ) + return FTC_Err_Invalid_Argument; + + *ansbit = NULL; + + query.attrs.scaler = scaler[0]; + query.attrs.load_flags = load_flags; + + /* beware, the hash must be the same for all glyph ranges! */ + hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + + gindex / FTC_SBIT_ITEMS_PER_NODE; + + FTC_GCACHE_LOOKUP_CMP( cache, + ftc_basic_family_compare, + FTC_SNode_Compare, + hash, gindex, + &query, + node, + error ); + if ( error ) + goto Exit; + + *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex ); + + if ( anode ) + { + *anode = FTC_NODE( node ); + FTC_NODE( node )->ref_count++; + } + + Exit: + return error; + } + + #ifdef FT_CONFIG_OPTION_OLD_INTERNALS FT_EXPORT( FT_Error ) diff --git a/src/libs/freetype2/cache/ftccache.c b/src/libs/freetype2/cache/ftccache.c index 797d35f6dc..f3e699c385 100644 --- a/src/libs/freetype2/cache/ftccache.c +++ b/src/libs/freetype2/cache/ftccache.c @@ -4,7 +4,7 @@ /* */ /* The FreeType internal cache interface (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -46,7 +46,10 @@ ftc_node_mru_link( FTC_Node node, FTC_Manager manager ) { - FTC_MruNode_Prepend( (FTC_MruNode*)&manager->nodes_list, + void *nl = &manager->nodes_list; + + + FTC_MruNode_Prepend( (FTC_MruNode*)nl, (FTC_MruNode)node ); manager->num_nodes++; } @@ -57,7 +60,10 @@ ftc_node_mru_unlink( FTC_Node node, FTC_Manager manager ) { - FTC_MruNode_Remove( (FTC_MruNode*)&manager->nodes_list, + void *nl = &manager->nodes_list; + + + FTC_MruNode_Remove( (FTC_MruNode*)nl, (FTC_MruNode)node ); manager->num_nodes--; } diff --git a/src/libs/freetype2/cache/ftccache.h b/src/libs/freetype2/cache/ftccache.h index 6c9b9b9e84..8c0a7c94fe 100644 --- a/src/libs/freetype2/cache/ftccache.h +++ b/src/libs/freetype2/cache/ftccache.h @@ -4,7 +4,7 @@ /* */ /* FreeType internal cache interface (specification). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -233,10 +233,11 @@ FT_BEGIN_HEADER \ { \ FTC_Manager _manager = _cache->manager; \ + void* _nl = &_manager->nodes_list; \ \ \ if ( _node != _manager->nodes_list ) \ - FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \ + FTC_MruNode_Up( (FTC_MruNode*)_nl, \ (FTC_MruNode)_node ); \ } \ goto _Ok; \ diff --git a/src/libs/freetype2/cache/ftccmap.c b/src/libs/freetype2/cache/ftccmap.c index 1568e5e855..aa59307f48 100644 --- a/src/libs/freetype2/cache/ftccmap.c +++ b/src/libs/freetype2/cache/ftccmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType CharMap cache (body) */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -341,7 +341,6 @@ return FT_Get_Char_Index( face, char_code ); } - break; default: return 0; diff --git a/src/libs/freetype2/cache/ftcglyph.h b/src/libs/freetype2/cache/ftcglyph.h index 1a5d12deb3..87a4199bfd 100644 --- a/src/libs/freetype2/cache/ftcglyph.h +++ b/src/libs/freetype2/cache/ftcglyph.h @@ -4,7 +4,7 @@ /* */ /* FreeType abstract glyph cache (specification). */ /* */ -/* Copyright 2000-2001, 2003, 2004, 2006 by */ +/* Copyright 2000-2001, 2003, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -300,11 +300,14 @@ FT_BEGIN_HEADER #else /* !FTC_INLINE */ -#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ - gindex, query, node, error ) \ - FT_BEGIN_STMNT \ - error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \ - FTC_GQUERY( query ), (FTC_Node*)&(node) ); \ +#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ + gindex, query, node, error ) \ + FT_BEGIN_STMNT \ + void* _n = &(node); \ + \ + \ + error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \ + FTC_GQUERY( query ), (FTC_Node*)_n ); \ FT_END_STMNT #endif /* !FTC_INLINE */ diff --git a/src/libs/freetype2/cff/cffgload.c b/src/libs/freetype2/cff/cffgload.c index 4c20a684f5..0e2a179c7c 100644 --- a/src/libs/freetype2/cff/cffgload.c +++ b/src/libs/freetype2/cff/cffgload.c @@ -372,12 +372,13 @@ /* this function is used to select the locals subrs array */ - FT_LOCAL_DEF( void ) + FT_LOCAL_DEF( FT_Error ) cff_decoder_prepare( CFF_Decoder* decoder, FT_UInt glyph_index ) { - CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data; - CFF_SubFont sub = &cff->top_font; + CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data; + CFF_SubFont sub = &cff->top_font; + FT_Error error = CFF_Err_Ok; /* manage CID fonts */ @@ -386,6 +387,13 @@ FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); + if ( fd_index >= cff->num_subfonts ) + { + FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + sub = cff->subfonts[fd_index]; } @@ -395,6 +403,9 @@ decoder->glyph_width = sub->private_dict.default_width; decoder->nominal_width = sub->private_dict.nominal_width; + + Exit: + return error; } @@ -2071,7 +2082,7 @@ if ( idx >= decoder->num_locals ) { FT_ERROR(( "cff_decoder_parse_charstrings:" )); - FT_ERROR(( " invalid local subr index\n" )); + FT_ERROR(( " invalid local subr index\n" )); goto Syntax_Error; } @@ -2249,9 +2260,11 @@ &charstring, &charstring_len ); if ( !error ) { - cff_decoder_prepare( &decoder, glyph_index ); - error = cff_decoder_parse_charstrings( &decoder, - charstring, charstring_len ); + error = cff_decoder_prepare( &decoder, glyph_index ); + if ( !error ) + error = cff_decoder_parse_charstrings( &decoder, + charstring, + charstring_len ); cff_free_glyph_data( face, &charstring, &charstring_len ); } @@ -2400,36 +2413,40 @@ &charstring, &charstring_len ); if ( !error ) { - cff_decoder_prepare( &decoder, glyph_index ); - error = cff_decoder_parse_charstrings( &decoder, - charstring, charstring_len ); + error = cff_decoder_prepare( &decoder, glyph_index ); + if ( !error ) + { + error = cff_decoder_parse_charstrings( &decoder, + charstring, + charstring_len ); - cff_free_glyph_data( face, &charstring, charstring_len ); + cff_free_glyph_data( face, &charstring, charstring_len ); #ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Control data and length may not be available for incremental */ - /* fonts. */ - if ( face->root.internal->incremental_interface ) - { - glyph->root.control_data = 0; - glyph->root.control_len = 0; - } - else + /* Control data and length may not be available for incremental */ + /* fonts. */ + if ( face->root.internal->incremental_interface ) + { + glyph->root.control_data = 0; + glyph->root.control_len = 0; + } + else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - /* We set control_data and control_len if charstrings is loaded. */ - /* See how charstring loads at cff_index_access_element() in */ - /* cffload.c. */ - { - CFF_Index csindex = &cff->charstrings_index; - - - if ( csindex->offsets ) + /* We set control_data and control_len if charstrings is loaded. */ + /* See how charstring loads at cff_index_access_element() in */ + /* cffload.c. */ { - glyph->root.control_data = csindex->bytes + - csindex->offsets[glyph_index] - 1; - glyph->root.control_len = charstring_len; + CFF_Index csindex = &cff->charstrings_index; + + + if ( csindex->offsets ) + { + glyph->root.control_data = csindex->bytes + + csindex->offsets[glyph_index] - 1; + glyph->root.control_len = charstring_len; + } } } } @@ -2462,25 +2479,27 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - if ( cff->num_subfonts >= 1 ) - { - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); - - - font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; - font_offset = cff->subfonts[fd_index]->font_dict.font_offset; - } - else - { - font_matrix = cff->top_font.font_dict.font_matrix; - font_offset = cff->top_font.font_dict.font_offset; - } - - /* Now, set the metrics -- this is rather simple, as */ - /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax. */ if ( !error ) { + if ( cff->num_subfonts >= 1 ) + { + FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, + glyph_index ); + + + font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; + font_offset = cff->subfonts[fd_index]->font_dict.font_offset; + } + else + { + font_matrix = cff->top_font.font_dict.font_matrix; + font_offset = cff->top_font.font_dict.font_offset; + } + + /* Now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax. */ + /* For composite glyphs, return only left side bearing and */ /* advance width. */ if ( load_flags & FT_LOAD_NO_RECURSE ) @@ -2547,11 +2566,16 @@ glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; /* apply the font matrix */ - FT_Outline_Transform( &glyph->root.outline, &font_matrix ); + if ( !( font_matrix.xx == 0x10000L && + font_matrix.yy == 0x10000L && + font_matrix.xy == 0 && + font_matrix.yx == 0 ) ) + FT_Outline_Transform( &glyph->root.outline, &font_matrix ); - FT_Outline_Translate( &glyph->root.outline, - font_offset.x, - font_offset.y ); + if ( !( font_offset.x == 0 && + font_offset.y == 0 ) ) + FT_Outline_Translate( &glyph->root.outline, + font_offset.x, font_offset.y ); advance.x = metrics->horiAdvance; advance.y = 0; diff --git a/src/libs/freetype2/cff/cffgload.h b/src/libs/freetype2/cff/cffgload.h index 01c6bcb964..f67864a692 100644 --- a/src/libs/freetype2/cff/cffgload.h +++ b/src/libs/freetype2/cff/cffgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -175,7 +175,7 @@ FT_BEGIN_HEADER FT_Bool hinting, FT_Render_Mode hint_mode ); - FT_LOCAL( void ) + FT_LOCAL( FT_Error ) cff_decoder_prepare( CFF_Decoder* decoder, FT_UInt glyph_index ); diff --git a/src/libs/freetype2/cid/cidgload.c b/src/libs/freetype2/cid/cidgload.c index aec34855cc..8bec6e187b 100644 --- a/src/libs/freetype2/cid/cidgload.c +++ b/src/libs/freetype2/cid/cidgload.c @@ -4,7 +4,7 @@ /* */ /* CID-keyed Type1 Glyph Loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -44,12 +44,12 @@ CID_FaceInfo cid = &face->cid; FT_Byte* p; FT_UInt fd_select; - FT_Stream stream = face->cid_stream; - FT_Error error = 0; - FT_Byte* charstring = 0; - FT_Memory memory = face->root.memory; + FT_Stream stream = face->cid_stream; + FT_Error error = CID_Err_Ok; + FT_Byte* charstring = 0; + FT_Memory memory = face->root.memory; FT_ULong glyph_length = 0; - PSAux_Service psaux = (PSAux_Service)face->psaux; + PSAux_Service psaux = (PSAux_Service)face->psaux; #ifdef FT_CONFIG_OPTION_INCREMENTAL @@ -111,6 +111,11 @@ glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; FT_FRAME_EXIT(); + if ( fd_select >= (FT_UInt)cid->num_dicts ) + { + error = CID_Err_Invalid_Offset; + goto Exit; + } if ( glyph_length == 0 ) goto Exit; if ( FT_ALLOC( charstring, glyph_length ) ) @@ -150,7 +155,7 @@ error = decoder->funcs.parse_charstrings( decoder, charstring + cs_offset, - (FT_Int)glyph_length - cs_offset ); + (FT_Int)glyph_length - cs_offset ); } FT_FREE( charstring ); diff --git a/src/libs/freetype2/cid/cidparse.c b/src/libs/freetype2/cid/cidparse.c index c2381fac1b..bb87afc589 100644 --- a/src/libs/freetype2/cid/cidparse.c +++ b/src/libs/freetype2/cid/cidparse.c @@ -98,7 +98,11 @@ stream_len = stream->size - FT_STREAM_POS(); if ( stream_len == 0 ) + { + FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); + error = CID_Err_Unknown_File_Format; goto Exit; + } read_len = FT_MIN( read_len, stream_len ); if ( FT_STREAM_READ( p, read_len ) ) @@ -165,7 +169,10 @@ while ( cur < limit ) { if ( parser->root.error ) - break; + { + error = parser->root.error; + goto Exit; + } if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) { diff --git a/src/libs/freetype2/gzip/adler32.c b/src/libs/freetype2/gzip/adler32.c index 706da263d2..c53f9dd125 100644 --- a/src/libs/freetype2/gzip/adler32.c +++ b/src/libs/freetype2/gzip/adler32.c @@ -34,12 +34,12 @@ ZEXPORT(uLong) adler32( /* adler, buf, len) */ len -= k; while (k >= 16) { DO16(buf); - buf += 16; + buf += 16; k -= 16; } if (k != 0) do { s1 += *buf++; - s2 += s1; + s2 += s1; } while (--k); s1 %= BASE; s2 %= BASE; diff --git a/src/libs/freetype2/gzip/zconf.h b/src/libs/freetype2/gzip/zconf.h index d6989c9f85..24ec0af242 100644 --- a/src/libs/freetype2/gzip/zconf.h +++ b/src/libs/freetype2/gzip/zconf.h @@ -13,39 +13,39 @@ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. */ #ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define inflateInit2_ z_inflateInit2_ +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ # define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateReset z_inflateReset -# define compress z_compress -# define compress2 z_compress2 -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp #endif #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) diff --git a/src/libs/freetype2/gzip/zutil.h b/src/libs/freetype2/gzip/zutil.h index 5f2d543130..c9688cd9c0 100644 --- a/src/libs/freetype2/gzip/zutil.h +++ b/src/libs/freetype2/gzip/zutil.h @@ -203,7 +203,7 @@ typedef unsigned long ulg; typedef uLong (*check_func) OF((uLong check, const Bytef *buf, - uInt len)); + uInt len)); local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); local void zcfree OF((voidpf opaque, voidpf ptr)); diff --git a/src/libs/freetype2/lzw/ftzopen.c b/src/libs/freetype2/lzw/ftzopen.c index a9d25c5fa6..fc7831510d 100644 --- a/src/libs/freetype2/lzw/ftzopen.c +++ b/src/libs/freetype2/lzw/ftzopen.c @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005, 2006 by David Turner. */ +/* Copyright 2005, 2006, 2007 by David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -23,55 +23,84 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_DEBUG_H - /* refill input buffer, return 0 on success, or -1 if eof */ + static int ft_lzwstate_refill( FT_LzwState state ) { - int result = -1; + FT_ULong count; - if ( !state->in_eof ) - { - FT_ULong count = FT_Stream_TryRead( state->source, - state->in_buff, - sizeof ( state->in_buff ) ); + if ( state->in_eof ) + return -1; - state->in_cursor = state->in_buff; - state->in_limit = state->in_buff + count; - state->in_eof = FT_BOOL( count < sizeof ( state->in_buff ) ); + count = FT_Stream_TryRead( state->source, + state->buf_tab, + state->num_bits ); /* WHY? */ - if ( count > 0 ) - result = 0; - } - return result; + state->buf_size = (FT_UInt)count; + state->buf_total += count; + state->in_eof = FT_BOOL( count < state->num_bits ); + state->buf_offset = 0; + state->buf_size = ( state->buf_size << 3 ) - ( state->num_bits - 1 ); + + if ( count == 0 ) /* end of file */ + return -1; + + return 0; } - /* return new code of 'num_bits', or -1 if eof */ static FT_Int32 - ft_lzwstate_get_code( FT_LzwState state, - FT_UInt num_bits ) + ft_lzwstate_get_code( FT_LzwState state ) { - FT_Int32 result = -1; - FT_UInt32 pad = state->pad; - FT_UInt pad_bits = state->pad_bits; + FT_UInt num_bits = state->num_bits; + FT_Int offset = state->buf_offset; + FT_Byte* p; + FT_Int result; - while ( num_bits > pad_bits ) + if ( state->buf_clear || + offset >= state->buf_size || + state->free_ent >= state->free_bits ) { - if ( state->in_cursor >= state->in_limit && - ft_lzwstate_refill( state ) < 0 ) - goto Exit; + if ( state->free_ent >= state->free_bits ) + { + state->num_bits = ++num_bits; + state->free_bits = state->num_bits < state->max_bits + ? (FT_UInt)( ( 1UL << num_bits ) - 256 ) + : state->max_free + 1; + } - pad |= (FT_UInt32)(*state->in_cursor++) << pad_bits; - pad_bits += 8; + if ( state->buf_clear ) + { + state->num_bits = num_bits = LZW_INIT_BITS; + state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 ); + state->buf_clear = 0; + } + + if ( ft_lzwstate_refill( state ) < 0 ) + return -1; + + offset = 0; } - result = (FT_Int32)( pad & LZW_MASK( num_bits ) ); - state->pad_bits = pad_bits - num_bits; - state->pad = pad >> num_bits; + state->buf_offset = offset + num_bits; + + p = &state->buf_tab[offset >> 3]; + offset &= 7; + result = *p++ >> offset; + offset = 8 - offset; + num_bits -= offset; + + if ( num_bits >= 8 ) + { + result |= *p++ << offset; + offset += 8; + num_bits -= 8; + } + if ( num_bits > 0 ) + result |= ( *p & LZW_MASK( num_bits ) ) << offset; - Exit: return result; } @@ -146,15 +175,14 @@ FT_LOCAL_DEF( void ) ft_lzwstate_reset( FT_LzwState state ) { - state->in_cursor = state->in_buff; - state->in_limit = state->in_buff; - state->in_eof = 0; - state->pad_bits = 0; - state->pad = 0; - - state->stack_top = 0; - state->num_bits = LZW_INIT_BITS; - state->phase = FT_LZW_PHASE_START; + state->in_eof = 0; + state->buf_offset = 0; + state->buf_size = 0; + state->buf_clear = 0; + state->buf_total = 0; + state->stack_top = 0; + state->num_bits = LZW_INIT_BITS; + state->phase = FT_LZW_PHASE_START; } @@ -196,13 +224,13 @@ } -#define FTLZW_STACK_PUSH( c ) \ - FT_BEGIN_STMNT \ - if ( state->stack_top >= state->stack_size && \ - ft_lzwstate_stack_grow( state ) < 0 ) \ - goto Eof; \ - \ - state->stack[ state->stack_top++ ] = (FT_Byte)(c); \ +#define FTLZW_STACK_PUSH( c ) \ + FT_BEGIN_STMNT \ + if ( state->stack_top >= state->stack_size && \ + ft_lzwstate_stack_grow( state ) < 0 ) \ + goto Eof; \ + \ + state->stack[state->stack_top++] = (FT_Byte)(c); \ FT_END_STMNT @@ -213,8 +241,6 @@ { FT_ULong result = 0; - FT_UInt num_bits = state->num_bits; - FT_UInt free_ent = state->free_ent; FT_UInt old_char = state->old_char; FT_UInt old_code = state->old_code; FT_UInt in_code = state->in_code; @@ -243,15 +269,16 @@ if ( state->max_bits > LZW_MAX_BITS ) goto Eof; - num_bits = LZW_INIT_BITS; - free_ent = ( state->block_mode ? LZW_FIRST : LZW_CLEAR ) - 256; + state->num_bits = LZW_INIT_BITS; + state->free_ent = ( state->block_mode ? LZW_FIRST + : LZW_CLEAR ) - 256; in_code = 0; - state->free_bits = num_bits < state->max_bits - ? (FT_UInt)( ( 1UL << num_bits ) - 256 ) + state->free_bits = state->num_bits < state->max_bits + ? (FT_UInt)( ( 1UL << state->num_bits ) - 256 ) : state->max_free + 1; - c = ft_lzwstate_get_code( state, num_bits ); + c = ft_lzwstate_get_code( state ); if ( c < 0 ) goto Eof; @@ -274,7 +301,7 @@ NextCode: - c = ft_lzwstate_get_code( state, num_bits ); + c = ft_lzwstate_get_code( state ); if ( c < 0 ) goto Eof; @@ -282,14 +309,10 @@ if ( code == LZW_CLEAR && state->block_mode ) { - free_ent = ( LZW_FIRST - 1 ) - 256; /* why not LZW_FIRST-256 ? */ - num_bits = LZW_INIT_BITS; - - state->free_bits = num_bits < state->max_bits - ? (FT_UInt)( ( 1UL << num_bits ) - 256 ) - : state->max_free + 1; - - c = ft_lzwstate_get_code( state, num_bits ); + /* why not LZW_FIRST-256 ? */ + state->free_ent = ( LZW_FIRST - 1 ) - 256; + state->buf_clear = 1; + c = ft_lzwstate_get_code( state ); if ( c < 0 ) goto Eof; @@ -301,7 +324,7 @@ if ( code >= 256U ) { /* special case for KwKwKwK */ - if ( code - 256U >= free_ent ) + if ( code - 256U >= state->free_ent ) { FTLZW_STACK_PUSH( old_char ); code = old_code; @@ -335,25 +358,18 @@ } /* now create new entry */ - if ( free_ent < state->max_free ) + if ( state->free_ent < state->max_free ) { - if ( free_ent >= state->prefix_size && - ft_lzwstate_prefix_grow( state ) < 0 ) + if ( state->free_ent >= state->prefix_size && + ft_lzwstate_prefix_grow( state ) < 0 ) goto Eof; - FT_ASSERT( free_ent < state->prefix_size ); + FT_ASSERT( state->free_ent < state->prefix_size ); - state->prefix[free_ent] = (FT_UShort)old_code; - state->suffix[free_ent] = (FT_Byte) old_char; + state->prefix[state->free_ent] = (FT_UShort)old_code; + state->suffix[state->free_ent] = (FT_Byte) old_char; - if ( ++free_ent == state->free_bits ) - { - num_bits++; - - state->free_bits = num_bits < state->max_bits - ? (FT_UInt)( ( 1UL << num_bits ) - 256 ) - : state->max_free + 1; - } + state->free_ent += 1; } old_code = in_code; @@ -367,8 +383,6 @@ } Exit: - state->num_bits = num_bits; - state->free_ent = free_ent; state->old_code = old_code; state->old_char = old_char; state->in_code = in_code; diff --git a/src/libs/freetype2/lzw/ftzopen.h b/src/libs/freetype2/lzw/ftzopen.h index 8b1831b567..97881149c2 100644 --- a/src/libs/freetype2/lzw/ftzopen.h +++ b/src/libs/freetype2/lzw/ftzopen.h @@ -8,7 +8,7 @@ /* be used to parse compressed PCF fonts, as found with many X11 server */ /* distributions. */ /* */ -/* Copyright 2005, 2006 by David Turner. */ +/* Copyright 2005, 2006, 2007 by David Turner. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -112,13 +112,13 @@ typedef struct _FT_LzwStateRec { FT_LzwPhase phase; - FT_Int in_eof; - FT_Byte* in_cursor; /* current buffer pos */ - FT_Byte* in_limit; /* current buffer limit */ - FT_UInt32 pad; /* a pad value where incoming bits were read */ - FT_Int pad_bits; /* number of meaningful bits in pad value */ + FT_Byte buf_tab[16]; + FT_Int buf_offset; + FT_Int buf_size; + FT_Bool buf_clear; + FT_Int buf_total; FT_UInt max_bits; /* max code bits, from file header */ FT_Int block_mode; /* block mode flag, from file header */ @@ -138,8 +138,6 @@ FT_Byte* stack; /* character stack */ FT_UInt stack_top; FT_UInt stack_size; - - FT_Byte in_buff[FT_LZW_IN_BUFF_SIZE]; /* small read-buffer */ FT_Byte stack_0[FT_LZW_DEFAULT_STACK_SIZE]; /* minimize heap alloc */ FT_Stream source; /* source stream */ diff --git a/src/libs/freetype2/pfr/pfrcmap.c b/src/libs/freetype2/pfr/pfrcmap.c index 05fe68fbe9..c8faee0436 100644 --- a/src/libs/freetype2/pfr/pfrcmap.c +++ b/src/libs/freetype2/pfr/pfrcmap.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR cmap handling (body). */ /* */ -/* Copyright 2002 by */ +/* Copyright 2002, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,7 +24,8 @@ FT_CALLBACK_DEF( FT_Error ) pfr_cmap_init( PFR_CMap cmap ) { - PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); + FT_Error error = PFR_Err_Ok; + PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); cmap->num_chars = face->phy_font.num_chars; @@ -39,11 +40,15 @@ for ( n = 1; n < cmap->num_chars; n++ ) { if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) - FT_ASSERT( 0 ); + { + error = PFR_Err_Invalid_Table; + goto Exit; + } } } - return 0; + Exit: + return error; } diff --git a/src/libs/freetype2/pfr/pfrgload.c b/src/libs/freetype2/pfr/pfrgload.c index 7cee187607..3bb173302d 100644 --- a/src/libs/freetype2/pfr/pfrgload.c +++ b/src/libs/freetype2/pfr/pfrgload.c @@ -4,7 +4,7 @@ /* */ /* FreeType PFR glyph loader (body). */ /* */ -/* Copyright 2002, 2003, 2005 by */ +/* Copyright 2002, 2003, 2005, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -59,8 +59,10 @@ glyph->y_control = NULL; glyph->max_xy_control = 0; +#if 0 glyph->num_x_control = 0; glyph->num_y_control = 0; +#endif FT_FREE( glyph->subs ); @@ -131,7 +133,12 @@ /* check that we have begun a new path */ - FT_ASSERT( glyph->path_begun != 0 ); + if ( !glyph->path_begun ) + { + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" )); + goto Exit; + } error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 ); if ( !error ) @@ -145,6 +152,7 @@ outline->n_points++; } + Exit: return error; } @@ -161,7 +169,12 @@ /* check that we have begun a new path */ - FT_ASSERT( glyph->path_begun != 0 ); + if ( !glyph->path_begun ) + { + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" )); + goto Exit; + } error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 ); if ( !error ) @@ -180,6 +193,7 @@ outline->n_points = (FT_Short)( outline->n_points + 3 ); } + Exit: return error; } @@ -244,7 +258,8 @@ flags = PFR_NEXT_BYTE( p ); /* test for composite glyphs */ - FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) == 0 ); + if ( flags & PFR_GLYPH_IS_COMPOUND ) + goto Failure; x_count = 0; y_count = 0; @@ -339,14 +354,15 @@ for (;;) { - FT_Int format, args_format = 0, args_count, n; + FT_UInt format, format_low, args_format = 0, args_count, n; /***************************************************************/ /* read instruction */ /* */ PFR_CHECK( 1 ); - format = PFR_NEXT_BYTE( p ); + format = PFR_NEXT_BYTE( p ); + format_low = format & 15; switch ( format >> 4 ) { @@ -366,30 +382,34 @@ case 5: /* move to outside contour */ FT_TRACE6(( "- move to outside" )); Line1: - args_format = format & 15; + args_format = format_low; args_count = 1; break; case 2: /* horizontal line to */ - FT_TRACE6(( "- horizontal line to cx.%d", format & 15 )); + FT_TRACE6(( "- horizontal line to cx.%d", format_low )); + if ( format_low > x_count ) + goto Failure; + pos[0].x = glyph->x_control[format_low]; pos[0].y = pos[3].y; - pos[0].x = glyph->x_control[format & 15]; pos[3] = pos[0]; args_count = 0; break; case 3: /* vertical line to */ - FT_TRACE6(( "- vertical line to cy.%d", format & 15 )); + FT_TRACE6(( "- vertical line to cy.%d", format_low )); + if ( format_low > y_count ) + goto Failure; pos[0].x = pos[3].x; - pos[0].y = glyph->y_control[format & 15]; - pos[3] = pos[0]; + pos[0].y = glyph->y_control[format_low]; + pos[3] = pos[0]; args_count = 0; break; case 6: /* horizontal to vertical curve */ FT_TRACE6(( "- hv curve " )); - args_format = 0xB8E; - args_count = 3; + args_format = 0xB8E; + args_count = 3; break; case 7: /* vertical to horizontal curve */ @@ -401,7 +421,7 @@ default: /* general curve to */ FT_TRACE6(( "- general curve" )); args_count = 4; - args_format = format & 15; + args_format = format_low; } /***********************************************************/ @@ -410,7 +430,8 @@ cur = pos; for ( n = 0; n < args_count; n++ ) { - FT_Int idx, delta; + FT_UInt idx; + FT_Int delta; /* read the X argument */ @@ -419,6 +440,8 @@ case 0: /* 8-bit index */ PFR_CHECK( 1 ); idx = PFR_NEXT_BYTE( p ); + if ( idx > x_count ) + goto Failure; cur->x = glyph->x_control[idx]; FT_TRACE7(( " cx#%d", idx )); break; @@ -447,6 +470,8 @@ case 0: /* 8-bit index */ PFR_CHECK( 1 ); idx = PFR_NEXT_BYTE( p ); + if ( idx > y_count ) + goto Failure; cur->y = glyph->y_control[idx]; FT_TRACE7(( " cy#%d", idx )); break; @@ -519,6 +544,7 @@ Exit: return error; + Failure: Too_Short: error = PFR_Err_Invalid_Table; FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" )); @@ -544,7 +570,8 @@ flags = PFR_NEXT_BYTE( p ); /* test for composite glyphs */ - FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) != 0 ); + if ( !( flags & PFR_GLYPH_IS_COMPOUND ) ) + goto Failure; count = flags & 0x3F; @@ -670,6 +697,7 @@ Exit: return error; + Failure: Too_Short: error = PFR_Err_Invalid_Table; FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" )); @@ -677,9 +705,6 @@ } - - - static FT_Error pfr_glyph_load_rec( PFR_Glyph glyph, FT_Stream stream, diff --git a/src/libs/freetype2/pfr/pfrtypes.h b/src/libs/freetype2/pfr/pfrtypes.h index df12ecf197..c0ae04253a 100644 --- a/src/libs/freetype2/pfr/pfrtypes.h +++ b/src/libs/freetype2/pfr/pfrtypes.h @@ -4,7 +4,7 @@ /* */ /* FreeType PFR data structures (specification only). */ /* */ -/* Copyright 2002, 2003, 2005 by */ +/* Copyright 2002, 2003, 2005, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -335,8 +335,10 @@ FT_BEGIN_HEADER { FT_Byte format; +#if 0 FT_UInt num_x_control; FT_UInt num_y_control; +#endif FT_UInt max_xy_control; FT_Pos* x_control; FT_Pos* y_control; diff --git a/src/libs/freetype2/psaux/afmparse.c b/src/libs/freetype2/psaux/afmparse.c index 012ff8c75d..0528fe6ff4 100644 --- a/src/libs/freetype2/psaux/afmparse.c +++ b/src/libs/freetype2/psaux/afmparse.c @@ -4,7 +4,7 @@ /* */ /* AFM parser (body). */ /* */ -/* Copyright 2006 by */ +/* Copyright 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -642,14 +642,12 @@ case AFM_TOKEN_ENDFONTMETRICS: fi->NumTrackKern = n + 1; return PSaux_Err_Ok; - break; case AFM_TOKEN_UNKNOWN: break; default: goto Fail; - break; } } @@ -761,7 +759,6 @@ default: goto Fail; - break; } } @@ -804,7 +801,6 @@ default: goto Fail; - break; } } @@ -921,7 +917,7 @@ case AFM_TOKEN_STARTCHARMETRICS: { - FT_Int n; + FT_Int n = 0; if ( afm_parser_read_int( parser, &n ) ) @@ -942,7 +938,6 @@ case AFM_TOKEN_ENDFONTMETRICS: return PSaux_Err_Ok; - break; default: break; diff --git a/src/libs/freetype2/psaux/psobjs.c b/src/libs/freetype2/psaux/psobjs.c index ee7d2cc3bc..957085668b 100644 --- a/src/libs/freetype2/psaux/psobjs.c +++ b/src/libs/freetype2/psaux/psobjs.c @@ -592,7 +592,6 @@ error = PSaux_Err_Invalid_File_Format; } - FT_ASSERT( parser->error == PSaux_Err_Ok ); parser->error = error; parser->cursor = cur; } @@ -785,8 +784,7 @@ if ( c == '[' ) ender = ']'; - - if ( c == '{' ) + else if ( c == '{' ) ender = '}'; if ( ender ) @@ -795,7 +793,8 @@ /* now, read the coordinates */ while ( cur < limit ) { - FT_Short dummy; + FT_Short dummy; + FT_Byte* old_cur; /* skip whitespace in front of data */ @@ -803,20 +802,29 @@ if ( cur >= limit ) goto Exit; - if ( coords != NULL && count >= max_coords ) - break; - if ( *cur == ender ) { cur++; break; } + old_cur = cur; + + if ( coords != NULL && count >= max_coords ) + break; + /* call PS_Conv_ToFixed() even if coords == NULL */ /* to properly parse number at `cur' */ *( coords != NULL ? &coords[count] : &dummy ) = (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 ); - count++; + + if ( old_cur == cur ) + { + count = -1; + goto Exit; + } + else + count++; if ( !ender ) break; @@ -830,7 +838,7 @@ /* first character must be a delimiter or a part of a number */ /* NB: `values' can be NULL if we just want to skip the */ - /* array in this case we ignore `max_values' */ + /* array; in this case we ignore `max_values' */ static FT_Int ps_tofixedarray( FT_Byte* *acur, @@ -854,8 +862,7 @@ if ( c == '[' ) ender = ']'; - - if ( c == '{' ) + else if ( c == '{' ) ender = '}'; if ( ender ) @@ -864,7 +871,8 @@ /* now, read the values */ while ( cur < limit ) { - FT_Fixed dummy; + FT_Fixed dummy; + FT_Byte* old_cur; /* skip whitespace in front of data */ @@ -872,20 +880,29 @@ if ( cur >= limit ) goto Exit; - if ( values != NULL && count >= max_values ) - break; - if ( *cur == ender ) { cur++; break; } + old_cur = cur; + + if ( values != NULL && count >= max_values ) + break; + /* call PS_Conv_ToFixed() even if coords == NULL */ /* to properly parse number at `cur' */ *( values != NULL ? &values[count] : &dummy ) = PS_Conv_ToFixed( &cur, limit, power_ten ); - count++; + + if ( old_cur == cur ) + { + count = -1; + goto Exit; + } + else + count++; if ( !ender ) break; @@ -1161,9 +1178,18 @@ { FT_Fixed temp[4]; FT_BBox* bbox = (FT_BBox*)q; + FT_Int result; - (void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 ); + result = ps_tofixedarray( &cur, limit, 4, temp, 0 ); + + if ( result < 0 ) + { + FT_ERROR(( "ps_parser_load_field: " + "expected four integers in bounding box\n" )); + error = PSaux_Err_Invalid_File_Format; + goto Exit; + } bbox->xMin = FT_RoundFix( temp[0] ); bbox->yMin = FT_RoundFix( temp[1] ); @@ -1227,8 +1253,8 @@ error = PSaux_Err_Ignore; goto Exit; } - if ( num_elements > T1_MAX_TABLE_ELEMENTS ) - num_elements = T1_MAX_TABLE_ELEMENTS; + if ( (FT_UInt)num_elements > field->array_max ) + num_elements = field->array_max; old_cursor = parser->cursor; old_limit = parser->limit; @@ -1311,7 +1337,7 @@ { if ( cur < parser->limit && *cur != '>' ) { - FT_ERROR(( "ps_tobytes: Missing closing delimiter `>'\n" )); + FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" )); error = PSaux_Err_Invalid_File_Format; goto Exit; } diff --git a/src/libs/freetype2/psaux/t1decode.c b/src/libs/freetype2/psaux/t1decode.c index 4373d6fa1e..f790643f96 100644 --- a/src/libs/freetype2/psaux/t1decode.c +++ b/src/libs/freetype2/psaux/t1decode.c @@ -4,7 +4,7 @@ /* */ /* PostScript Type 1 decoding routines (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -951,8 +951,9 @@ default: if ( top - decoder->stack != num_args ) - FT_TRACE0(( "\nMore operands on the stack than expected " - "(have %d, expected %d)\n", + FT_TRACE0(( "t1_decoder_parse_charstrings: " + "too much operands on the stack " + "(seen %d, expected %d)\n", top - decoder->stack, num_args )); break; } diff --git a/src/libs/freetype2/pshinter/pshmod.c b/src/libs/freetype2/pshinter/pshmod.c index 5b18684c75..4eb3d91272 100644 --- a/src/libs/freetype2/pshinter/pshmod.c +++ b/src/libs/freetype2/pshinter/pshmod.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hinter module implementation (body). */ /* */ -/* Copyright 2001, 2002 by */ +/* Copyright 2001, 2002, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -51,6 +51,7 @@ ps_hinter_init( PS_Hinter_Module module ) { FT_Memory memory = module->root.memory; + void* ph = &module->ps_hints; ps_hints_init( &module->ps_hints, memory ); @@ -58,10 +59,10 @@ psh_globals_funcs_init( &module->globals_funcs ); t1_hints_funcs_init( &module->t1_funcs ); - module->t1_funcs.hints = (T1_Hints)&module->ps_hints; + module->t1_funcs.hints = (T1_Hints)ph; t2_hints_funcs_init( &module->t2_funcs ); - module->t2_funcs.hints = (T2_Hints)&module->ps_hints; + module->t2_funcs.hints = (T2_Hints)ph; return 0; } diff --git a/src/libs/freetype2/pshinter/pshrec.c b/src/libs/freetype2/pshinter/pshrec.c index b6ada7581e..2a885ef276 100644 --- a/src/libs/freetype2/pshinter/pshrec.c +++ b/src/libs/freetype2/pshinter/pshrec.c @@ -308,11 +308,11 @@ /* set a new mask to a given bit range */ static FT_Error - ps_mask_table_set_bits( PS_Mask_Table table, - FT_Byte* source, - FT_UInt bit_pos, - FT_UInt bit_count, - FT_Memory memory ) + ps_mask_table_set_bits( PS_Mask_Table table, + const FT_Byte* source, + FT_UInt bit_pos, + FT_UInt bit_count, + FT_Memory memory ) { FT_Error error = 0; PS_Mask mask; @@ -330,7 +330,7 @@ /* now, copy bits */ { - FT_Byte* read = source + ( bit_pos >> 3 ); + FT_Byte* read = (FT_Byte*)source + ( bit_pos >> 3 ); FT_Int rmask = 0x80 >> ( bit_pos & 7 ); FT_Byte* write = mask->bytes; FT_Int wmask = 0x80; @@ -628,7 +628,7 @@ goto Exit; /* set bits in new mask */ - error = ps_mask_table_set_bits( &dim->masks, (FT_Byte*)source, + error = ps_mask_table_set_bits( &dim->masks, source, source_pos, source_bits, memory ); Exit: diff --git a/src/libs/freetype2/psnames/psmodule.c b/src/libs/freetype2/psnames/psmodule.c index 76fb174143..8d8c476a14 100644 --- a/src/libs/freetype2/psnames/psmodule.c +++ b/src/libs/freetype2/psnames/psmodule.c @@ -32,7 +32,7 @@ #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST -#define VARIANT_BIT ( 1L << 31 ) +#define VARIANT_BIT 0x80000000UL #define BASE_GLYPH( code ) ( (code) & ~VARIANT_BIT ) @@ -92,7 +92,7 @@ if ( *p == '\0' ) return value; if ( *p == '.' ) - return value ^ VARIANT_BIT; + return value | VARIANT_BIT; } } @@ -132,7 +132,7 @@ if ( *p == '\0' ) return value; if ( *p == '.' ) - return value ^ VARIANT_BIT; + return value | VARIANT_BIT; } } @@ -156,7 +156,7 @@ if ( !dot ) return ft_get_adobe_glyph_index( glyph_name, p ); else - return ft_get_adobe_glyph_index( glyph_name, dot ) ^ VARIANT_BIT; + return ft_get_adobe_glyph_index( glyph_name, dot ) | VARIANT_BIT; } } diff --git a/src/libs/freetype2/sfnt/sfobjs.c b/src/libs/freetype2/sfnt/sfobjs.c index ffdc33bd15..cc901100d1 100644 --- a/src/libs/freetype2/sfnt/sfobjs.c +++ b/src/libs/freetype2/sfnt/sfobjs.c @@ -619,7 +619,22 @@ error = SFNT_Err_Ok; } else + { error = SFNT_Err_Horiz_Header_Missing; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics, tolerate a missing `hhea' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + } +#endif + + } } if ( error ) diff --git a/src/libs/freetype2/sfnt/ttcmap.c b/src/libs/freetype2/sfnt/ttcmap.c index 8a35e14c42..854d567d1a 100644 --- a/src/libs/freetype2/sfnt/ttcmap.c +++ b/src/libs/freetype2/sfnt/ttcmap.c @@ -155,6 +155,7 @@ FT_Byte* p = cmap->data + 4; + cmap_info->format = 0; cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); return SFNT_Err_Ok; @@ -527,6 +528,7 @@ FT_Byte* p = cmap->data + 4; + cmap_info->format = 2; cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); return SFNT_Err_Ok; @@ -1303,6 +1305,7 @@ FT_Byte* p = cmap->data + 4; + cmap_info->format = 4; cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); return SFNT_Err_Ok; @@ -1462,6 +1465,7 @@ FT_Byte* p = cmap->data + 4; + cmap_info->format = 6; cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); return SFNT_Err_Ok; @@ -1715,6 +1719,7 @@ FT_Byte* p = cmap->data + 8; + cmap_info->format = 8; cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); return SFNT_Err_Ok; @@ -1863,6 +1868,7 @@ FT_Byte* p = cmap->data + 8; + cmap_info->format = 10; cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); return SFNT_Err_Ok; @@ -2179,6 +2185,7 @@ FT_Byte* p = cmap->data + 8; + cmap_info->format = 12; cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); return SFNT_Err_Ok; @@ -2299,7 +2306,8 @@ valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; - if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 ) + if ( ft_setjmp( + *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 ) { /* validate this cmap sub-table */ error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); diff --git a/src/libs/freetype2/sfnt/ttkern.c b/src/libs/freetype2/sfnt/ttkern.c index 08f9dba3d0..28e52c333e 100644 --- a/src/libs/freetype2/sfnt/ttkern.c +++ b/src/libs/freetype2/sfnt/ttkern.c @@ -84,7 +84,7 @@ for ( nn = 0; nn < num_tables; nn++ ) { - FT_UInt num_pairs, version, length, coverage; + FT_UInt num_pairs, length, coverage; FT_Byte* p_next; FT_UInt32 mask = 1UL << nn; @@ -94,7 +94,7 @@ p_next = p; - version = FT_NEXT_USHORT( p ); + p += 2; /* skip version */ length = FT_NEXT_USHORT( p ); coverage = FT_NEXT_USHORT( p ); diff --git a/src/libs/freetype2/sfnt/ttmtx.c b/src/libs/freetype2/sfnt/ttmtx.c index 63837b4f2d..286bd0c311 100644 --- a/src/libs/freetype2/sfnt/ttmtx.c +++ b/src/libs/freetype2/sfnt/ttmtx.c @@ -110,40 +110,48 @@ FT_ULong table_len; FT_Long num_shorts, num_longs, num_shorts_checked; - TT_LongMetrics * longs; + TT_LongMetrics* longs; TT_ShortMetrics** shorts; FT_Byte* p; if ( vertical ) { + void* lm = &face->vertical.long_metrics; + void** sm = &face->vertical.short_metrics; + + error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->vertical.number_Of_VMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) - num_longs = (FT_Long)(table_len / 4); + num_longs = (FT_Long)( table_len / 4 ); face->vertical.number_Of_VMetrics = 0; - longs = (TT_LongMetrics *)&face->vertical.long_metrics; - shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; + longs = (TT_LongMetrics*)lm; + shorts = (TT_ShortMetrics**)sm; } else { + void* lm = &face->horizontal.long_metrics; + void** sm = &face->horizontal.short_metrics; + + error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->horizontal.number_Of_HMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) - num_longs = (FT_Long)(table_len / 4); + num_longs = (FT_Long)( table_len / 4 ); face->horizontal.number_Of_HMetrics = 0; - longs = (TT_LongMetrics *)&face->horizontal.long_metrics; - shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; + longs = (TT_LongMetrics*)lm; + shorts = (TT_ShortMetrics**)sm; } /* never trust derived values */ @@ -279,11 +287,14 @@ if ( vertical ) { + void *v = &face->vertical; + + error = face->goto_table( face, TTAG_vhea, stream, 0 ); if ( error ) goto Fail; - header = (TT_HoriHeader*)&face->vertical; + header = (TT_HoriHeader*)v; } else { @@ -348,7 +359,10 @@ if ( vertical ) { - header = (TT_HoriHeader*)&face->vertical; + void* v = &face->vertical; + + + header = (TT_HoriHeader*)v; table_pos = face->vert_metrics_offset; table_size = face->vert_metrics_size; } @@ -415,8 +429,9 @@ FT_Short* abearing, FT_UShort* aadvance ) { - TT_HoriHeader* header = vertical ? (TT_HoriHeader*)&face->vertical - : &face->horizontal; + void* v = &face->vertical; + void* h = &face->horizontal; + TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v : h; TT_LongMetrics longs_m; FT_UShort k = header->number_Of_HMetrics; diff --git a/src/libs/freetype2/sfnt/ttsbit0.c b/src/libs/freetype2/sfnt/ttsbit0.c index edbfa103d3..f8adc64a73 100644 --- a/src/libs/freetype2/sfnt/ttsbit0.c +++ b/src/libs/freetype2/sfnt/ttsbit0.c @@ -235,7 +235,7 @@ TT_SBit_MetricsRec* metrics ) { FT_Error error; - FT_Stream stream = face->root.stream; + FT_Stream stream = face->root.stream; FT_ULong ebdt_size; @@ -261,14 +261,27 @@ /* now find the strike corresponding to the index */ { - FT_Byte* p = decoder->eblc_base + 8 + 48 * strike_index; + FT_Byte* p; + if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size ) + { + error = SFNT_Err_Invalid_File_Format; + goto Exit; + } + + p = decoder->eblc_base + 8 + 48 * strike_index; + decoder->strike_index_array = FT_NEXT_ULONG( p ); p += 4; decoder->strike_index_count = FT_NEXT_ULONG( p ); p += 34; decoder->bit_depth = *p; + + if ( decoder->strike_index_array > face->sbit_table_size || + decoder->strike_index_array + 8 * decoder->strike_index_count > + face->sbit_table_size ) + error = SFNT_Err_Invalid_File_Format; } Exit: @@ -642,9 +655,9 @@ for ( nn = 0; nn < num_components; nn++ ) { - FT_UInt gindex = FT_NEXT_USHORT( p ); - FT_Byte dx = FT_NEXT_BYTE( p ); - FT_Byte dy = FT_NEXT_BYTE( p ); + FT_UInt gindex = FT_NEXT_USHORT( p ); + FT_Byte dx = FT_NEXT_BYTE( p ); + FT_Byte dy = FT_NEXT_BYTE( p ); /* NB: a recursive call */ @@ -775,9 +788,6 @@ FT_ULong image_start = 0, image_end = 0, image_offset; - if ( p + 8 * num_ranges > p_limit ) - goto NoBitmap; - for ( ; num_ranges > 0; num_ranges-- ) { start = FT_NEXT_USHORT( p ); @@ -792,6 +802,12 @@ FoundRange: image_offset = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( decoder->eblc_base + decoder->strike_index_array + image_offset < + decoder->eblc_base ) + goto Failure; + p = decoder->eblc_base + decoder->strike_index_array + image_offset; if ( p + 8 > p_limit ) goto NoBitmap; @@ -831,7 +847,7 @@ goto NoBitmap; image_start = image_size * ( glyph_index - start ); - image_end = image_start + image_size; + image_end = image_start + image_size; } break; @@ -858,6 +874,11 @@ goto NoBitmap; num_glyphs = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( p + ( num_glyphs + 1 ) * 4 < p ) + goto Failure; + if ( p + ( num_glyphs + 1 ) * 4 > p_limit ) goto NoBitmap; @@ -895,6 +916,11 @@ goto NoBitmap; num_glyphs = FT_NEXT_ULONG( p ); + + /* overflow check */ + if ( p + 2 * num_glyphs < p ) + goto Failure; + if ( p + 2 * num_glyphs > p_limit ) goto NoBitmap; @@ -910,7 +936,7 @@ if ( mm >= num_glyphs ) goto NoBitmap; - image_start = image_size*mm; + image_start = image_size * mm; image_end = image_start + image_size; } break; @@ -932,6 +958,9 @@ x_pos, y_pos ); + Failure: + return SFNT_Err_Invalid_Table; + NoBitmap: return SFNT_Err_Invalid_Argument; } diff --git a/src/libs/freetype2/smooth/ftgrays.c b/src/libs/freetype2/smooth/ftgrays.c index 15e7ab8cdc..5a4a544e5a 100644 --- a/src/libs/freetype2/smooth/ftgrays.c +++ b/src/libs/freetype2/smooth/ftgrays.c @@ -197,7 +197,7 @@ #define ONE_PIXEL ( 1L << PIXEL_BITS ) #define PIXEL_MASK ( -1L << PIXEL_BITS ) -#define TRUNC( x ) ( (TCoord)((x) >> PIXEL_BITS) ) +#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) ) #define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS ) #define FLOOR( x ) ( (x) & -ONE_PIXEL ) #define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) @@ -398,6 +398,9 @@ int x = ras.ex; + if ( x > ras.max_ex ) + x = ras.max_ex; + pcell = &ras.ycells[ras.ey]; for (;;) { @@ -462,6 +465,10 @@ /* All cells that are on the left of the clipping region go to the */ /* min_ex - 1 horizontal position. */ ey -= ras.min_ey; + + if ( ex > ras.max_ex ) + ex = ras.max_ex; + ex -= ras.min_ex; if ( ex < 0 ) ex = -1; @@ -492,6 +499,9 @@ gray_start_cell( RAS_ARG_ TCoord ex, TCoord ey ) { + if ( ex > ras.max_ex ) + ex = (TCoord)( ras.max_ex ); + if ( ex < ras.min_ex ) ex = (TCoord)( ras.min_ex - 1 ); @@ -1196,6 +1206,10 @@ y += (TCoord)ras.min_ey; x += (TCoord)ras.min_ex; + /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */ + if ( x >= 32768 ) + x = 32767; + if ( coverage ) { /* see whether we can add this span to the current list */ diff --git a/src/libs/freetype2/truetype/ttdriver.c b/src/libs/freetype2/truetype/ttdriver.c index e1b3d7e8f4..c2cf45298a 100644 --- a/src/libs/freetype2/truetype/ttdriver.c +++ b/src/libs/freetype2/truetype/ttdriver.c @@ -29,9 +29,11 @@ #endif #include FT_SERVICE_TRUETYPE_ENGINE_H +#include FT_SERVICE_TRUETYPE_GLYF_H #include "ttdriver.h" #include "ttgload.h" +#include "ttpload.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #include "ttgxvar.h" @@ -313,6 +315,11 @@ #endif /* TT_USE_BYTECODE_INTERPRETER */ }; + static const FT_Service_TTGlyfRec tt_service_truetype_glyf = + { + (TT_Glyf_GetLocationFunc)tt_face_get_location + }; + static const FT_ServiceDescRec tt_services[] = { { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE }, @@ -320,6 +327,7 @@ { FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters }, #endif { FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine }, + { FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf }, { NULL, NULL } }; diff --git a/src/libs/freetype2/truetype/ttgload.c b/src/libs/freetype2/truetype/ttgload.c index 4d7f61eae5..ae476a4171 100644 --- a/src/libs/freetype2/truetype/ttgload.c +++ b/src/libs/freetype2/truetype/ttgload.c @@ -244,13 +244,14 @@ FT_Outline* outline; TT_Face face = (TT_Face)load->face; FT_UShort n_ins; - FT_Int n, n_points; + FT_Int n_points; FT_Byte *flag, *flag_limit; FT_Byte c, count; FT_Vector *vec, *vec_limit; FT_Pos x; - FT_Short *cont, *cont_limit; + FT_Short *cont, *cont_limit, prev_cont; + FT_Int xy_size = 0; /* check that we can add the contours to the glyph */ @@ -263,15 +264,29 @@ cont_limit = cont + n_contours; /* check space for contours array + instructions count */ - if ( n_contours >= 0xFFF || p + (n_contours + 1) * 2 > limit ) + if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) goto Invalid_Outline; - for ( ; cont < cont_limit; cont++ ) + cont[0] = prev_cont = FT_NEXT_USHORT( p ); + for ( cont++; cont < cont_limit; cont++ ) + { cont[0] = FT_NEXT_USHORT( p ); + if ( cont[0] <= prev_cont ) + { + /* unordered contours: this is invalid */ + error = FT_Err_Invalid_Table; + goto Fail; + } + prev_cont = cont[0]; + } n_points = 0; if ( n_contours > 0 ) + { n_points = cont[-1] + 1; + if ( n_points < 0 ) + goto Invalid_Outline; + } /* note that we will add four phantom points later */ error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); @@ -298,7 +313,8 @@ if ( n_ins > face->max_profile.maxSizeOfInstructions ) { - FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" )); + FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions (%d)\n", + n_ins )); error = TT_Err_Too_Many_Hints; goto Fail; } @@ -357,21 +373,25 @@ flag = (FT_Byte*)outline->tags; x = 0; + if ( p + xy_size > limit ) + goto Invalid_Outline; + for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos y = 0; + FT_Byte f = *flag; - if ( *flag & 2 ) + if ( f & 2 ) { if ( p + 1 > limit ) goto Invalid_Outline; y = (FT_Pos)FT_NEXT_BYTE( p ); - if ( ( *flag & 16 ) == 0 ) + if ( ( f & 16 ) == 0 ) y = -y; } - else if ( ( *flag & 16 ) == 0 ) + else if ( ( f & 16 ) == 0 ) { if ( p + 2 > limit ) goto Invalid_Outline; @@ -381,6 +401,7 @@ x += y; vec->x = x; + *flag = f & ~( 2 | 16 ); } /* reading the Y coordinates */ @@ -393,18 +414,19 @@ for ( ; vec < vec_limit; vec++, flag++ ) { FT_Pos y = 0; + FT_Byte f = *flag; - if ( *flag & 4 ) + if ( f & 4 ) { - if ( p +1 > limit ) + if ( p + 1 > limit ) goto Invalid_Outline; y = (FT_Pos)FT_NEXT_BYTE( p ); - if ( ( *flag & 32 ) == 0 ) + if ( ( f & 32 ) == 0 ) y = -y; } - else if ( ( *flag & 32 ) == 0 ) + else if ( ( f & 32 ) == 0 ) { if ( p + 2 > limit ) goto Invalid_Outline; @@ -414,12 +436,9 @@ x += y; vec->y = x; + *flag = f & FT_CURVE_TAG_ON; } - /* clear the touch tags */ - for ( n = 0; n < n_points; n++ ) - outline->tags[n] &= FT_CURVE_TAG_ON; - outline->n_points = (FT_UShort)n_points; outline->n_contours = (FT_Short) n_contours; @@ -572,13 +591,14 @@ FT_UInt start_point, FT_UInt start_contour ) { - zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); - zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); - zone->org = load->extra_points + start_point; - zone->cur = load->outline.points + start_point; - zone->orus = load->extra_points2 + start_point; - zone->tags = (FT_Byte*)load->outline.tags + start_point; - zone->contours = (FT_UShort*)load->outline.contours + start_contour; + zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); + zone->n_contours = (FT_Short) ( load->outline.n_contours - + start_contour ); + zone->org = load->extra_points + start_point; + zone->cur = load->outline.points + start_point; + zone->orus = load->extra_points2 + start_point; + zone->tags = (FT_Byte*)load->outline.tags + start_point; + zone->contours = (FT_UShort*)load->outline.contours + start_contour; zone->first_point = (FT_UShort)start_point; } @@ -984,7 +1004,8 @@ /* check it */ if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions ) { - FT_TRACE0(( "Too many instructions (%d)\n", n_ins )); + FT_TRACE0(( "TT_Process_Composite_Glyph: Too many instructions (%d)\n", + n_ins )); return TT_Err_Too_Many_Hints; } @@ -1284,9 +1305,9 @@ /* otherwise, load a composite! */ else if ( loader->n_contours == -1 ) { - FT_UInt start_point; - FT_UInt start_contour; - FT_ULong ins_pos; /* position of composite instructions, if any */ + FT_UInt start_point; + FT_UInt start_contour; + FT_ULong ins_pos; /* position of composite instructions, if any */ start_point = gloader->base.outline.n_points; @@ -1316,11 +1337,11 @@ /* this provides additional offsets */ /* for each component's translation */ - if ( (error = TT_Vary_Get_Glyph_Deltas( - face, - glyph_index, - &deltas, - gloader->current.num_subglyphs + 4 )) != 0 ) + if ( ( error = TT_Vary_Get_Glyph_Deltas( + face, + glyph_index, + &deltas, + gloader->current.num_subglyphs + 4 )) != 0 ) goto Exit; subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; @@ -1356,7 +1377,6 @@ /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ /* `as is' in the glyph slot (the client application will be */ /* responsible for interpreting these data)... */ - /* */ if ( loader->load_flags & FT_LOAD_NO_RECURSE ) { FT_GlyphLoader_Add( gloader ); @@ -1370,15 +1390,20 @@ /*********************************************************************/ { - FT_UInt n, num_base_points; - FT_SubGlyph subglyph = 0; + FT_UInt n, num_base_points; + FT_SubGlyph subglyph = 0; - FT_UInt num_points = start_point; - FT_UInt num_subglyphs = gloader->current.num_subglyphs; - FT_UInt num_base_subgs = gloader->base.num_subglyphs; + FT_UInt num_points = start_point; + FT_UInt num_subglyphs = gloader->current.num_subglyphs; + FT_UInt num_base_subgs = gloader->base.num_subglyphs; - FT_Stream old_stream = loader->stream; + FT_Stream old_stream = loader->stream; + TT_GraphicsState saved_GS; + + + if ( loader->exec ) + saved_GS = loader->exec->GS; FT_GlyphLoader_Add( gloader ); @@ -1388,6 +1413,10 @@ FT_Vector pp[4]; + /* reinitialize graphics state */ + if ( loader->exec ) + loader->exec->GS = saved_GS; + /* Each time we call load_truetype_glyph in this loop, the */ /* value of `gloader.base.subglyphs' can change due to table */ /* reallocations. We thus need to recompute the subglyph */ @@ -1422,12 +1451,12 @@ if ( num_points == num_base_points ) continue; - /* gloader->base.outline consists of three part: */ - /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ - /* */ - /* (1): exist from the beginning */ - /* (2): components that have been loaded so far */ - /* (3): the newly loaded component */ + /* gloader->base.outline consists of three parts: */ + /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ + /* */ + /* (1): exists from the beginning */ + /* (2): components that have been loaded so far */ + /* (3): the newly loaded component */ TT_Process_Composite_Component( loader, subglyph, start_point, num_base_points ); } @@ -1451,7 +1480,7 @@ } else { - /* invalid composite count ( negative but not -1 ) */ + /* invalid composite count (negative but not -1) */ error = TT_Err_Invalid_Outline; goto Exit; } @@ -1479,8 +1508,8 @@ static FT_Error - compute_glyph_metrics( TT_Loader loader, - FT_UInt glyph_index ) + compute_glyph_metrics( TT_Loader loader, + FT_UInt glyph_index ) { FT_BBox bbox; TT_Face face = (TT_Face)loader->face; @@ -1498,8 +1527,8 @@ else bbox = loader->bbox; - /* get the device-independent horizontal advance. It is scaled later */ - /* by the base layer. */ + /* get the device-independent horizontal advance; it is scaled later */ + /* by the base layer. */ { FT_Pos advance = loader->linear; @@ -1759,11 +1788,11 @@ tt_size_run_prep( size ); } - /* see if the cvt program has disabled hinting */ + /* see whether the cvt program has disabled hinting */ if ( exec->GS.instruct_control & 1 ) load_flags |= FT_LOAD_NO_HINTING; - /* load default graphics state - if needed */ + /* load default graphics state -- if needed */ if ( exec->GS.instruct_control & 2 ) exec->GS = tt_default_graphics_state; @@ -1774,7 +1803,7 @@ #endif /* TT_USE_BYTECODE_INTERPRETER */ - /* seek to the beginning of the glyph table. For Type 42 fonts */ + /* seek to the beginning of the glyph table -- for Type 42 fonts */ /* the table might be accessed from a Postscript stream or something */ /* else... */ @@ -1852,13 +1881,11 @@ FT_Int32 load_flags ) { TT_Face face; - FT_Stream stream; FT_Error error; TT_LoaderRec loader; face = (TT_Face)glyph->face; - stream = face->root.stream; error = TT_Err_Ok; #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS @@ -1892,7 +1919,7 @@ glyph->num_subglyphs = 0; glyph->outline.flags = 0; - /* Main loading loop */ + /* main loading loop */ error = load_truetype_glyph( &loader, glyph_index, 0 ); if ( !error ) { diff --git a/src/libs/freetype2/truetype/ttinterp.c b/src/libs/freetype2/truetype/ttinterp.c index 7a45cc5d7b..85c8529ac7 100644 --- a/src/libs/freetype2/truetype/ttinterp.c +++ b/src/libs/freetype2/truetype/ttinterp.c @@ -621,6 +621,10 @@ exec->pts.n_points = 0; exec->pts.n_contours = 0; + exec->zp1 = exec->pts; + exec->zp2 = exec->pts; + exec->zp0 = exec->pts; + exec->instruction_trap = FALSE; return TT_Err_Ok; @@ -1127,17 +1131,8 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - static - const FT_Vector Null_Vector = {0,0}; - - #undef PACK - -#undef NULL_Vector -#define NULL_Vector (FT_Vector*)&Null_Vector - - #if 1 static FT_Int32 @@ -6157,6 +6152,13 @@ */ twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0; + if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + if ( twilight ) orus_base = &CUR.zp0.org[CUR.GS.rp1]; else @@ -6213,7 +6215,7 @@ ? TT_MULDIV( org_dist, cur_range, old_range ) : cur_dist; - CUR_Func_move( &CUR.zp2, point, new_dist - cur_dist ); + CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist ); } CUR.GS.loop = 1; CUR.new_top = CUR.args; @@ -6260,6 +6262,7 @@ FT_Vector* orgs; /* original and current coordinate */ FT_Vector* curs; /* arrays */ FT_Vector* orus; + FT_UInt max_points; } IUP_WorkerRec, *IUP_Worker; @@ -6300,6 +6303,10 @@ if ( p1 > p2 ) return; + if ( BOUNDS( ref1, worker->max_points ) || + BOUNDS( ref2, worker->max_points ) ) + return; + orus1 = worker->orus[ref1].x; orus2 = worker->orus[ref2].x; @@ -6399,6 +6406,10 @@ FT_UNUSED_ARG; + /* ignore empty outlines */ + if ( CUR.pts.n_contours == 0 ) + return; + if ( CUR.opcode & 1 ) { mask = FT_CURVE_TAG_TOUCH_X; @@ -6413,6 +6424,7 @@ V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 ); V.orus = (FT_Vector*)( (FT_Pos*)CUR.pts.orus + 1 ); } + V.max_points = CUR.pts.n_points; contour = 0; point = 0; diff --git a/src/libs/freetype2/truetype/ttobjs.c b/src/libs/freetype2/truetype/ttobjs.c index a1a1cbb7da..0294a1b7e6 100644 --- a/src/libs/freetype2/truetype/ttobjs.c +++ b/src/libs/freetype2/truetype/ttobjs.c @@ -693,21 +693,14 @@ size->GS = tt_default_graphics_state; error = tt_size_run_prep( size ); + if ( !error ) + size->cvt_ready = 1; } Exit: return error; } -#else /* !TT_USE_BYTECODE_INTERPRETER */ - - FT_LOCAL_DEF( FT_Error ) - tt_size_ready_bytecode( TT_Size size ) - { - FT_UNUSED( size ); - return 0; - } - -#endif /* !TT_USE_BYTECODE_INTERPRETER */ +#endif /* TT_USE_BYTECODE_INTERPRETER */ /*************************************************************************/ diff --git a/src/libs/freetype2/truetype/ttobjs.h b/src/libs/freetype2/truetype/ttobjs.h index 652ead33e9..6971013af9 100644 --- a/src/libs/freetype2/truetype/ttobjs.h +++ b/src/libs/freetype2/truetype/ttobjs.h @@ -423,14 +423,14 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) tt_size_run_prep( TT_Size size ); + FT_LOCAL( FT_Error ) + tt_size_ready_bytecode( TT_Size size ); + #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) tt_size_reset( TT_Size size ); - FT_LOCAL( FT_Error ) - tt_size_ready_bytecode( TT_Size size ); - /*************************************************************************/ /* */ diff --git a/src/libs/freetype2/type1/t1load.c b/src/libs/freetype2/type1/t1load.c index ed56bb46d6..55177eed43 100644 --- a/src/libs/freetype2/type1/t1load.c +++ b/src/libs/freetype2/type1/t1load.c @@ -1066,12 +1066,26 @@ FT_Face root = (FT_Face)&face->root; FT_Fixed temp[6]; FT_Fixed temp_scale; + FT_Int result; - (void)T1_ToFixedArray( parser, 6, temp, 3 ); + result = T1_ToFixedArray( parser, 6, temp, 3 ); + + if ( result < 0 ) + { + parser->root.error = T1_Err_Invalid_File_Format; + return; + } temp_scale = FT_ABS( temp[3] ); + if ( temp_scale == 0 ) + { + FT_ERROR(( "parse_font_matrix: invalid font matrix\n" )); + parser->root.error = T1_Err_Invalid_File_Format; + return; + } + /* Set Units per EM based on FontMatrix values. We set the value to */ /* 1000 / temp_scale, because temp_scale was already multiplied by */ /* 1000 (in t1_tofixed, from psobjs.c). */ @@ -1253,7 +1267,11 @@ } } else + { T1_Skip_PS_Token( parser ); + if ( parser->root.error ) + return; + } T1_Skip_Spaces( parser ); } @@ -1379,6 +1397,12 @@ FT_Byte* temp; + if ( size <= face->type1.private_dict.lenIV ) + { + error = T1_Err_Invalid_File_Format; + goto Fail; + } + /* t1_decrypt() shouldn't write to base -- make temporary copy */ if ( FT_ALLOC( temp, size ) ) goto Fail; @@ -1548,12 +1572,18 @@ notdef_found = 1; } - if ( face->type1.private_dict.lenIV >= 0 && - n < num_glyphs + TABLE_EXTEND ) + if ( face->type1.private_dict.lenIV >= 0 && + n < num_glyphs + TABLE_EXTEND ) { FT_Byte* temp; + if ( size <= face->type1.private_dict.lenIV ) + { + error = T1_Err_Invalid_File_Format; + goto Fail; + } + /* t1_decrypt() shouldn't write to base -- make temporary copy */ if ( FT_ALLOC( temp, size ) ) goto Fail; diff --git a/src/libs/freetype2/type1/t1objs.c b/src/libs/freetype2/type1/t1objs.c index 095e7f16c8..3d08336c60 100644 --- a/src/libs/freetype2/type1/t1objs.c +++ b/src/libs/freetype2/type1/t1objs.c @@ -4,7 +4,7 @@ /* */ /* Type 1 objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -191,13 +191,11 @@ FT_LOCAL_DEF( void ) T1_Face_Done( T1_Face face ) { - FT_Memory memory; - T1_Font type1 = &face->type1; - - if ( face ) { - memory = face->root.memory; + FT_Memory memory = face->root.memory; + T1_Font type1 = &face->type1; + #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT /* release multiple masters information */ diff --git a/src/libs/freetype2/type42/t42objs.c b/src/libs/freetype2/type42/t42objs.c index ecd0473647..db04fde367 100644 --- a/src/libs/freetype2/type42/t42objs.c +++ b/src/libs/freetype2/type42/t42objs.c @@ -4,7 +4,7 @@ /* */ /* Type 42 objects manager (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006 by Roberto Alameda. */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -55,6 +55,8 @@ error = t42_parse_dict( face, &loader, parser->base_dict, parser->base_len ); + if ( error ) + goto Exit; if ( type1->font_type != 42 ) { diff --git a/src/libs/freetype2/type42/t42parse.c b/src/libs/freetype2/type42/t42parse.c index 9233985581..7148379644 100644 --- a/src/libs/freetype2/type42/t42parse.c +++ b/src/libs/freetype2/type42/t42parse.c @@ -4,7 +4,7 @@ /* */ /* Type 42 font parser (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006 by Roberto Alameda. */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by Roberto Alameda. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -393,7 +393,7 @@ break; } - /* check whether we've found an entry */ + /* check whether we have found an entry */ if ( ft_isdigit( *cur ) || only_immediates ) { FT_Int charcode; @@ -433,7 +433,11 @@ } } else + { T1_Skip_PS_Token( parser ); + if ( parser->root.error ) + return; + } T1_Skip_Spaces( parser ); } @@ -490,7 +494,7 @@ FT_Long n, string_size, old_string_size, real_size; FT_Byte* string_buf = NULL; - FT_Bool alloc = 0; + FT_Bool allocated = 0; T42_Load_Status status; @@ -545,7 +549,7 @@ if ( FT_REALLOC( string_buf, old_string_size, string_size ) ) goto Fail; - alloc = 1; + allocated = 1; parser->root.cursor = cur; (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 ); @@ -555,6 +559,14 @@ else if ( ft_isdigit( *cur ) ) { + if ( allocated ) + { + FT_ERROR(( "t42_parse_sfnts: " + "can't handle mixed binary and hex strings!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + string_size = T1_ToInt( parser ); T1_Skip_PS_Token( parser ); /* `RD' */ @@ -572,10 +584,24 @@ } } + if ( !string_buf ) + { + FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + /* A string can have a trailing zero byte for padding. Ignore it. */ if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) ) string_size--; + if ( !string_size ) + { + FT_ERROR(( "t42_parse_sfnts: invalid string!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + for ( n = 0; n < string_size; n++ ) { switch ( status ) @@ -654,7 +680,7 @@ parser->root.error = error; Exit: - if ( alloc ) + if ( allocated ) FT_FREE( string_buf ); } diff --git a/src/libs/freetype2/winfonts/winfnt.c b/src/libs/freetype2/winfonts/winfnt.c index d3d602426e..4aa974410f 100644 --- a/src/libs/freetype2/winfonts/winfnt.c +++ b/src/libs/freetype2/winfonts/winfnt.c @@ -4,8 +4,10 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2006 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* Copyright 2003 Huw D M Davies for Codeweavers */ +/* Copyright 2007 Dmitry Timoshkov for Codeweavers */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -62,6 +64,80 @@ FT_FRAME_END }; + static const FT_Frame_Field winpe32_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE32_HeaderRec + + FT_FRAME_START( 248 ), + FT_FRAME_ULONG_LE ( magic ), /* PE00 */ + FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */ + FT_FRAME_USHORT_LE ( number_of_sections ), + FT_FRAME_SKIP_BYTES( 12 ), + FT_FRAME_USHORT_LE ( size_of_optional_header ), + FT_FRAME_SKIP_BYTES( 2 ), + FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */ + FT_FRAME_SKIP_BYTES( 110 ), + FT_FRAME_ULONG_LE ( rsrc_virtual_address ), + FT_FRAME_ULONG_LE ( rsrc_size ), + FT_FRAME_SKIP_BYTES( 104 ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe32_section_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE32_SectionRec + + FT_FRAME_START( 40 ), + FT_FRAME_BYTES ( name, 8 ), + FT_FRAME_SKIP_BYTES( 4 ), + FT_FRAME_ULONG_LE ( virtual_address ), + FT_FRAME_ULONG_LE ( size_of_raw_data ), + FT_FRAME_ULONG_LE ( pointer_to_raw_data ), + FT_FRAME_SKIP_BYTES( 16 ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_dir_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDirRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE ( characteristics ), + FT_FRAME_ULONG_LE ( time_date_stamp ), + FT_FRAME_USHORT_LE( major_version ), + FT_FRAME_USHORT_LE( minor_version ), + FT_FRAME_USHORT_LE( number_of_named_entries ), + FT_FRAME_USHORT_LE( number_of_id_entries ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_dir_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDirEntryRec + + FT_FRAME_START( 8 ), + FT_FRAME_ULONG_LE( name ), + FT_FRAME_ULONG_LE( offset ), + FT_FRAME_END + }; + + static const FT_Frame_Field winpe_rsrc_data_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinPE_RsrcDataEntryRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE( offset_to_data ), + FT_FRAME_ULONG_LE( size ), + FT_FRAME_ULONG_LE( code_page ), + FT_FRAME_ULONG_LE( reserved ), + FT_FRAME_END + }; + static const FT_Frame_Field winfnt_header_fields[] = { #undef FT_STRUCTURE @@ -214,6 +290,8 @@ WinNE_HeaderRec ne_header; + FT_TRACE2(( "MZ signature found\n" )); + if ( FT_STREAM_SEEK( mz_header.lfanew ) || FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) ) goto Exit; @@ -229,6 +307,8 @@ FT_ULong font_offset = 0; + FT_TRACE2(( "NE signature found\n" )); + if ( FT_STREAM_SEEK( res_offset ) || FT_FRAME_ENTER( ne_header.rname_tab_offset - ne_header.resource_tab_offset ) ) @@ -263,7 +343,16 @@ if ( !font_count || !font_offset ) { FT_TRACE2(( "this file doesn't contain any FNT resources!\n" )); - error = FNT_Err_Unknown_File_Format; + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + /* loading `winfnt_header_fields' needs at least 118 bytes; */ + /* use this as a rough measure to check the expected font size */ + if ( font_count * 118UL > stream->size ) + { + FT_TRACE2(( "invalid number of faces\n" )); + error = FNT_Err_Invalid_File_Format; goto Exit; } @@ -282,9 +371,8 @@ FT_FRAME_ENTER( 12 ) ) goto Fail; - face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; - face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; - face->font->size_shift = size_shift; + face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; + face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; stream->cursor += 8; @@ -292,6 +380,193 @@ error = fnt_font_load( face->font, stream ); } + else if ( ne_header.magic == WINFNT_PE_MAGIC ) + { + WinPE32_HeaderRec pe32_header; + WinPE32_SectionRec pe32_section; + WinPE_RsrcDirRec root_dir, name_dir, lang_dir; + WinPE_RsrcDirEntryRec dir_entry1, dir_entry2, dir_entry3; + WinPE_RsrcDataEntryRec data_entry; + + FT_Long root_dir_offset, name_dir_offset, lang_dir_offset; + FT_UShort i, j, k; + + + FT_TRACE2(( "PE signature found\n" )); + + if ( FT_STREAM_SEEK( mz_header.lfanew ) || + FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) ) + goto Exit; + + FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, " + "size_of_optional_header %02x\n" + "magic32 %02x, rsrc_virtual_address %04lx, " + "rsrc_size %04lx\n", + pe32_header.magic, pe32_header.machine, + pe32_header.number_of_sections, + pe32_header.size_of_optional_header, + pe32_header.magic32, pe32_header.rsrc_virtual_address, + pe32_header.rsrc_size )); + + if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ || + pe32_header.machine != 0x014c /* i386 */ || + pe32_header.size_of_optional_header != 0xe0 /* FIXME */ || + pe32_header.magic32 != 0x10b ) + { + FT_TRACE2(( "this file has an invalid PE header\n" )); + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + face->root.num_faces = 0; + + for ( i = 0; i < pe32_header.number_of_sections; i++ ) + { + if ( FT_STREAM_READ_FIELDS( winpe32_section_fields, + &pe32_section ) ) + goto Exit; + + FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n", + pe32_section.name, pe32_section.virtual_address, + pe32_section.size_of_raw_data, + pe32_section.pointer_to_raw_data )); + + if ( pe32_header.rsrc_virtual_address == + pe32_section.virtual_address ) + goto Found_rsrc_section; + } + + FT_TRACE2(( "this file doesn't contain any resources\n" )); + error = FNT_Err_Invalid_File_Format; + goto Exit; + + Found_rsrc_section: + FT_TRACE2(( "found resources section %.8s\n", pe32_section.name )); + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) ) + goto Exit; + + root_dir_offset = pe32_section.pointer_to_raw_data; + + for ( i = 0; i < root_dir.number_of_named_entries + + root_dir.number_of_id_entries; i++ ) + { + if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, + &dir_entry1 ) ) + goto Exit; + + if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + dir_entry1.offset &= ~0x80000000UL; + + name_dir_offset = pe32_section.pointer_to_raw_data + + dir_entry1.offset; + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data + + dir_entry1.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) ) + goto Exit; + + for ( j = 0; j < name_dir.number_of_named_entries + + name_dir.number_of_id_entries; j++ ) + { + if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, + &dir_entry2 ) ) + goto Exit; + + if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + dir_entry2.offset &= ~0x80000000UL; + + lang_dir_offset = pe32_section.pointer_to_raw_data + + dir_entry2.offset; + + if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data + + dir_entry2.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) ) + goto Exit; + + for ( k = 0; k < lang_dir.number_of_named_entries + + lang_dir.number_of_id_entries; k++ ) + { + if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields, + &dir_entry3 ) ) + goto Exit; + + if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ ) + { + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + if ( dir_entry1.name == 8 /* RT_FONT */ ) + { + if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) || + FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields, + &data_entry ) ) + goto Exit; + + FT_TRACE2(( "found font #%lu, offset %04lx, " + "size %04lx, cp %lu\n", + dir_entry2.name, + pe32_section.pointer_to_raw_data + + data_entry.offset_to_data - + pe32_section.virtual_address, + data_entry.size, data_entry.code_page )); + + if ( face_index == face->root.num_faces ) + { + if ( FT_NEW( face->font ) ) + goto Exit; + + face->font->offset = pe32_section.pointer_to_raw_data + + data_entry.offset_to_data - + pe32_section.virtual_address; + face->font->fnt_size = data_entry.size; + + error = fnt_font_load( face->font, stream ); + if ( error ) + { + FT_TRACE2(( "font #%lu load error %d\n", + dir_entry2.name, error )); + goto Fail; + } + else + FT_TRACE2(( "font #%lu successfully loaded\n", + dir_entry2.name )); + } + + face->root.num_faces++; + } + } + } + } + } + + if ( !face->root.num_faces ) + { + FT_TRACE2(( "this file doesn't contain any RT_FONT resources\n" )); + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + if ( face_index >= face->root.num_faces ) + { + error = FNT_Err_Bad_Argument; + goto Exit; + } } Fail: @@ -386,13 +661,16 @@ static void FNT_Face_Done( FNT_Face face ) { - FT_Memory memory = FT_FACE_MEMORY( face ); + if ( face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); - fnt_font_done( face ); + fnt_font_done( face ); - FT_FREE( face->root.available_sizes ); - face->root.num_fixed_sizes = 0; + FT_FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + } } @@ -412,12 +690,18 @@ /* try to load font from a DLL */ error = fnt_face_get_dll_font( face, face_index ); - if ( error ) + if ( error == FNT_Err_Unknown_File_Format ) { /* this didn't work; try to load a single FNT font */ FNT_Font font; + if ( face_index > 0 ) + { + error = FNT_Err_Bad_Argument; + goto Exit; + } + if ( FT_NEW( face->font ) ) goto Exit; @@ -428,10 +712,11 @@ font->fnt_size = stream->size; error = fnt_font_load( font, stream ); - if ( error ) - goto Fail; } + if ( error ) + goto Fail; + /* we now need to fill the root FT_Face fields */ /* with relevant information */ { @@ -533,11 +818,17 @@ root->num_glyphs = font->header.last_char - font->header.first_char + 1 + 1; + if ( font->header.face_name_offset >= font->header.file_size ) + { + FT_TRACE2(( "invalid family name offset!\n" )); + error = FNT_Err_Invalid_File_Format; + goto Fail; + } + family_size = font->header.file_size - font->header.face_name_offset; /* Some broken fonts don't delimit the face name with a final */ /* NULL byte -- the frame is erroneously one byte too small. */ /* We thus allocate one more byte, setting it explicitly to */ /* zero. */ - family_size = font->header.file_size - font->header.face_name_offset; if ( FT_ALLOC( font->family_name, family_size + 1 ) ) goto Fail; @@ -696,6 +987,13 @@ bitmap->rows = font->header.pixel_height; bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + if ( offset + pitch * bitmap->rows >= font->header.file_size ) + { + FT_TRACE2(( "invalid bitmap width\n" )); + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + /* note: since glyphs are stored in columns and not in rows we */ /* can't use ft_glyphslot_set_bitmap */ if ( FT_ALLOC_MULT( bitmap->buffer, pitch, bitmap->rows ) ) diff --git a/src/libs/freetype2/winfonts/winfnt.h b/src/libs/freetype2/winfonts/winfnt.h index 32ab6daf0a..ca75c9501a 100644 --- a/src/libs/freetype2/winfonts/winfnt.h +++ b/src/libs/freetype2/winfonts/winfnt.h @@ -4,8 +4,9 @@ /* */ /* FreeType font driver for Windows FNT/FON files */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* Copyright 2007 Dmitry Timoshkov for Codeweavers */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -46,6 +47,65 @@ FT_BEGIN_HEADER } WinNE_HeaderRec; + typedef struct WinPE32_HeaderRec_ + { + FT_ULong magic; + FT_UShort machine; + FT_UShort number_of_sections; + /* skipped content */ + FT_UShort size_of_optional_header; + /* skipped content */ + FT_UShort magic32; + /* skipped content */ + FT_ULong rsrc_virtual_address; + FT_ULong rsrc_size; + /* skipped content */ + + } WinPE32_HeaderRec; + + + typedef struct WinPE32_SectionRec_ + { + FT_Byte name[8]; + /* skipped content */ + FT_ULong virtual_address; + FT_ULong size_of_raw_data; + FT_ULong pointer_to_raw_data; + /* skipped content */ + + } WinPE32_SectionRec; + + + typedef struct WinPE_RsrcDirRec_ + { + FT_ULong characteristics; + FT_ULong time_date_stamp; + FT_UShort major_version; + FT_UShort minor_version; + FT_UShort number_of_named_entries; + FT_UShort number_of_id_entries; + + } WinPE_RsrcDirRec; + + + typedef struct WinPE_RsrcDirEntryRec_ + { + FT_ULong name; + FT_ULong offset; + + } WinPE_RsrcDirEntryRec; + + + typedef struct WinPE_RsrcDataEntryRec_ + { + FT_ULong offset_to_data; + FT_ULong size; + FT_ULong code_page; + FT_ULong reserved; + + } WinPE_RsrcDataEntryRec; + + typedef struct WinNameInfoRec_ { FT_UShort offset; @@ -68,12 +128,12 @@ FT_BEGIN_HEADER #define WINFNT_MZ_MAGIC 0x5A4D #define WINFNT_NE_MAGIC 0x454E +#define WINFNT_PE_MAGIC 0x4550 typedef struct FNT_FontRec_ { FT_ULong offset; - FT_Int size_shift; FT_WinFNT_HeaderRec header;