diff --git a/ChangeLog b/ChangeLog index 6956d4d41..f1acfd882 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2013-04-13 Werner Lemberg + + [cff] Add a new Type 2 interpreter and hinter. + + This work, written by Dave Arnold and fully + integrated into FreeType by me, is a donation by Adobe in + collaboration with Google. It is vastly superior to the old CFF + engine, and it will replace it soon. Right now, it is still off by + default, and you have to explicitly select it using the new + `hinting-engine' property of the cff driver. + + For convenience, (most of) the new files are committed separately. + + * include/freetype/config/ftheader.h (FT_CFF_DRIVER_H): New macro. + * include/freetype/ftcffdrv.h: New file to access CFF driver + properties. + * include/freetype/fterrdef.h (FT_Err_Glyph_Too_Big): New error + code. + * include/freetype/internal/fttrace.h: Add `cf2blues', `cf2hints', + and `cf2interp'. + + * src/cff/cffgload.h (CFF_SubFont): New member `current_subfont'. + * src/cff/cffobjs.h (CFF_DriverRec): New members `hinting_engine' + and `no_stem_darkening'. + * src/cff/cfftypes.h (CFF_FontRec): New member `cf2_instance'. + + * src/cff/cff.c: Include new files. + * src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle + `hinting-engine' and `no-stem-darkening' properties (only the Adobe + engine listens to them). + * src/cff/cffgload.c: Include `cf2ft.h'. + (cff_decoder_prepare): Initialize `current_subfont'. + (cff_build_add_point): Handle Adobe engine which uses 16.16 + coordinates. + (cff_slot_load): Handle FT_LOAD_NO_SCALE and FT_LOAD_NO_HINTING + separately. + Choose rendering engine based on `hinting_engine' property. + * src/cff/cffload.c (cff_font_done): Call finalizer of the Adobe + engine. + * src/cff/cffobjs.c: Include FT_CFF_DRIVER_H. + (cff_driver_init): Set default property values. + + * src/cff/rules.mk (CFF_DRV_SRC, CFF_DRV_H): Add new files. + + * src/cff/cf2*.*: New files, containing the Adobe engine. + 2013-04-12 Werner Lemberg [cff] Minor code administration issues. diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h index 33d6b4054..93969ef81 100644 --- a/include/freetype/config/ftheader.h +++ b/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ /* */ /* Build macros of the FreeType 2 library. */ /* */ -/* Copyright 1996-2008, 2010, 2012 by */ +/* Copyright 1996-2008, 2010, 2012, 2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -328,6 +328,19 @@ #define FT_AUTOHINTER_H + /************************************************************************* + * + * @macro: + * FT_CFF_DRIVER_H + * + * @description: + * A macro used in #include statements to name the file containing + * structures and macros related to the CFF driver module. + * + */ +#define FT_CFF_DRIVER_H + + /************************************************************************* * * @macro: diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h new file mode 100644 index 000000000..07ae54d3d --- /dev/null +++ b/include/freetype/ftcffdrv.h @@ -0,0 +1,150 @@ +/***************************************************************************/ +/* */ +/* ftcffdrv.h */ +/* */ +/* FreeType API for controlling the CFF driver (specification only). */ +/* */ +/* Copyright 2013 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCFFDRV_H__ +#define __FTCFFDRV_H__ + +#include +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /************************************************************************** + * + * @section: + * cff_driver + * + * @title: + * The CFF driver + * + * @abstract: + * Controlling the CFF driver module. + * + * @description: + * While FreeType's CFF driver doesn't expose API functions by itself, + * it is possible to control its behaviour with @FT_Property_Set and + * @FT_Property_Get. The following lists the available properties + * together with the necessary macros and structures. + * + * The CFF driver's module name is `cff'. + * + */ + + + /************************************************************************** + * + * @property: + * hinting-engine + * + * @description: + * Thanks to Adobe, which contributed a new hinting (and parsing) + * engine, an application can select between `freetype' and `adobe'. + * + * Right now, the default engine is `freetype'. However, this will + * change: After a certain time of intensive testing it is planned to + * make `adobe' the default due to its superior rendering results. + * + * The following example code demonstrates how to select Adobe's hinting + * engine (omitting the error handling). + * + * { + * FT_Library library; + * FT_Face face; + * FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "cff", + * "hinting-engine", &hinting_engine ); + * } + * + * @note: + * This property can be used with @FT_Property_Get also. + * + */ + + + /************************************************************************** + * + * @enum: + * FT_CFF_HINTING_XXX + * + * @description: + * A list of constants used for the @hinting-engine property to select + * the hinting engine for CFF fonts. + * + * @values: + * FT_CFF_HINTING_FREETYPE :: + * Use the old FreeType hinting engine. + * + * FT_CFF_HINTING_ADOBE :: + * Use the hinting engine contributed by Adobe. + * + */ +#define FT_CFF_HINTING_FREETYPE 0 +#define FT_CFF_HINTING_ADOBE 1 + + + /************************************************************************** + * + * @property: + * no-stem-darkening + * + * @description: + * By default, the Adobe CFF engine darkens stems at smaller sizes, + * regardless of hinting, to enhance contrast. Setting this property, + * stem darkening gets switched off. + * + * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set. + * + * { + * FT_Library library; + * FT_Face face; + * FT_Bool no_stem_darkening = TRUE; + * + * + * FT_Init_FreeType( &library ); + * + * FT_Property_Set( library, "cff", + * "no-stem-darkening", &no_stem_darkening ); + * } + * + * @note: + * This property can be used with @FT_Property_Get also. + * + */ + + + /* */ + +FT_END_HEADER + + +#endif /* __FTCFFDRV_H__ */ + + +/* END */ diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h index 984eef372..eccacaba6 100644 --- a/include/freetype/ftchapters.h +++ b/include/freetype/ftchapters.h @@ -78,6 +78,20 @@ /***************************************************************************/ +/***************************************************************************/ +/* */ +/* */ +/* cff_driver */ +/* */ +/* */ +/* The CFF Driver */ +/* */ +/* <Sections> */ +/* cff_driver */ +/* */ +/***************************************************************************/ + + /***************************************************************************/ /* */ /* <Chapter> */ diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h index bb06d79e9..76c7b9e36 100644 --- a/include/freetype/fterrdef.h +++ b/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ /* */ /* FreeType error codes (specification). */ /* */ -/* Copyright 2002, 2004, 2006, 2007, 2010-2012 by */ +/* Copyright 2002, 2004, 2006, 2007, 2010-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -217,6 +217,8 @@ "ignore" ) FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3, \ "no Unicode glyph name found" ) + FT_ERRORDEF_( Glyph_Too_Big, 0xA4, \ + "glyph to big for hinting" ) /* BDF errors */ diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h index 5481854b6..a9d98b60a 100644 --- a/include/freetype/internal/fttrace.h +++ b/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ /* */ /* Tracing handling (specification only). */ /* */ -/* Copyright 2002, 2004-2007, 2009, 2011-2012 by */ +/* Copyright 2002, 2004-2007, 2009, 2011-2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -88,6 +88,10 @@ FT_TRACE_DEF( cffload ) FT_TRACE_DEF( cffobjs ) FT_TRACE_DEF( cffparse ) +FT_TRACE_DEF( cf2blues ) +FT_TRACE_DEF( cf2hints ) +FT_TRACE_DEF( cf2interp ) + /* Type 42 driver component */ FT_TRACE_DEF( t42 ) diff --git a/src/cff/cff.c b/src/cff/cff.c index fccfd442f..c3840b583 100644 --- a/src/cff/cff.c +++ b/src/cff/cff.c @@ -4,7 +4,7 @@ /* */ /* FreeType OpenType driver component (body only). */ /* */ -/* Copyright 1996-2001, 2002 by */ +/* Copyright 1996-2001, 2002, 2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,6 +19,7 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> + #include "cffpic.c" #include "cffdrivr.c" #include "cffparse.c" @@ -27,4 +28,14 @@ #include "cffgload.c" #include "cffcmap.c" +#include "cf2arrst.c" +#include "cf2blues.c" +#include "cf2error.c" +#include "cf2font.c" +#include "cf2ft.c" +#include "cf2hints.c" +#include "cf2intrp.c" +#include "cf2read.c" +#include "cf2stack.c" + /* END */ diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index ce41ee06f..8d216fe87 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -577,20 +577,73 @@ * */ static FT_Error - cff_property_set( FT_Module ft_module, + cff_property_set( FT_Module module, /* CFF_Driver */ const char* property_name, const void* value ) { - return FT_Err_Ok; + FT_Error error = FT_Err_Ok; + CFF_Driver driver = (CFF_Driver)module; + + + if ( !ft_strcmp( property_name, "hinting-engine" ) ) + { + FT_UInt* hinting_engine = (FT_UInt*)value; + + + driver->hinting_engine = *hinting_engine; + + return error; + } + else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) + { + FT_Bool* no_stem_darkening = (FT_Bool*)value; + + + driver->no_stem_darkening = *no_stem_darkening; + + return error; + } + + FT_TRACE0(( "cff_property_set: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); } static FT_Error - cff_property_get( FT_Module ft_module, + cff_property_get( FT_Module module, /* CFF_Driver */ const char* property_name, const void* value ) { - return FT_Err_Ok; + FT_Error error = FT_Err_Ok; + CFF_Driver driver = (CFF_Driver)module; + + FT_UInt hinting_engine = driver->hinting_engine; + FT_Bool no_stem_darkening = driver->no_stem_darkening; + + + if ( !ft_strcmp( property_name, "hinting-engine" ) ) + { + FT_UInt* val = (FT_UInt*)value; + + + *val = hinting_engine; + + return error; + } + else if ( !ft_strcmp( property_name, "no-stem-darkening" ) ) + { + FT_Bool* val = (FT_Bool*)value; + + + *val = no_stem_darkening; + + return error; + } + + FT_TRACE0(( "cff_property_get: missing property `%s'\n", + property_name )); + return FT_THROW( Missing_Property ); } diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 0d4b5d1f7..7d62a9fa1 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -25,6 +25,7 @@ #include "cffobjs.h" #include "cffload.h" #include "cffgload.h" +#include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ #include "cfferrs.h" @@ -455,6 +456,8 @@ decoder->glyph_width = sub->private_dict.default_width; decoder->nominal_width = sub->private_dict.nominal_width; + decoder->current_subfont = sub; /* for Adobe's CFF handler */ + Exit: return error; } @@ -481,12 +484,23 @@ if ( builder->load_points ) { + CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); + FT_Vector* point = outline->points + outline->n_points; FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; - point->x = x >> 16; - point->y = y >> 16; + if ( driver->hinting_engine == FT_CFF_HINTING_ADOBE ) + { + /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ + point->x = x >> 10; + point->y = y >> 10; + } + else + { + point->x = x >> 16; + point->y = y >> 16; + } *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); } @@ -2585,7 +2599,7 @@ FT_Error error; CFF_Decoder decoder; TT_Face face = (TT_Face)glyph->root.face; - FT_Bool hinting, force_scaling; + FT_Bool hinting, scaled, force_scaling; CFF_Font cff = (CFF_Font)face->extra.data; FT_Matrix font_matrix; @@ -2773,12 +2787,18 @@ glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && - ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + /* top-level code ensures that FT_LOAD_NO_HINTING is set */ + /* if FT_LOAD_NO_SCALE is active */ + hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); + glyph->hint = hinting; + glyph->scaled = scaled; glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ { + CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); + FT_Byte* charstring; FT_ULong charstring_len; @@ -2802,9 +2822,19 @@ if ( error ) goto Glyph_Build_Finished; - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); + /* choose which CFF renderer to use */ + if ( driver->hinting_engine == FT_CFF_HINTING_ADOBE ) + error = cf2_decoder_parse_charstrings( &decoder, + charstring, + charstring_len ); + + /* Adobe's engine uses 16.16 numbers everywhere; */ + /* as a consequence, glyphs larger than 2000ppem get rejected */ + if ( FT_ERR_EQ( error, Glyph_Too_Big ) || + driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) + error = cff_decoder_parse_charstrings( &decoder, + charstring, + charstring_len ); cff_free_glyph_data( face, &charstring, charstring_len ); diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h index 8bbe99b9a..11b389e21 100644 --- a/src/cff/cffgload.h +++ b/src/cff/cffgload.h @@ -191,6 +191,8 @@ FT_BEGIN_HEADER FT_Bool seac; + CFF_SubFont current_subfont; /* for current glyph_index */ + } CFF_Decoder; diff --git a/src/cff/cffload.c b/src/cff/cffload.c index da4f36182..6a303ff0c 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1684,6 +1684,12 @@ FT_FREE( font->global_subrs ); FT_FREE( font->strings ); FT_FREE( font->string_pool ); + + if ( font->cf2_instance.finalizer ) + { + font->cf2_instance.finalizer( font->cf2_instance.data ); + FT_FREE( font->cf2_instance.data ); + } } diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index 6a65cc8cf..ebcf18936 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -17,6 +17,7 @@ #include <ft2build.h> + #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_CALC_H #include FT_INTERNAL_STREAM_H @@ -24,12 +25,15 @@ #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_SFNT_H +#include FT_CFF_DRIVER_H + #include "cffobjs.h" #include "cffload.h" #include "cffcmap.h" -#include "cfferrs.h" #include "cffpic.h" +#include "cfferrs.h" + /*************************************************************************/ /* */ @@ -1046,16 +1050,21 @@ FT_LOCAL_DEF( FT_Error ) - cff_driver_init( FT_Module module ) + cff_driver_init( FT_Module module ) /* CFF_Driver */ { - FT_UNUSED( module ); + CFF_Driver driver = (CFF_Driver)module; + + + /* set default property values */ + driver->hinting_engine = FT_CFF_HINTING_FREETYPE; + driver->no_stem_darkening = FALSE; return FT_Err_Ok; } FT_LOCAL_DEF( void ) - cff_driver_done( FT_Module module ) + cff_driver_done( FT_Module module ) /* CFF_Driver */ { FT_UNUSED( module ); } diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h index 4e6f220b4..b375c20c7 100644 --- a/src/cff/cffobjs.h +++ b/src/cff/cffobjs.h @@ -112,12 +112,14 @@ FT_BEGIN_HEADER /***********************************************************************/ /* */ - /* TrueType driver class. */ + /* CFF driver class. */ /* */ typedef struct CFF_DriverRec_ { FT_DriverRec root; - void* extension_component; + + FT_UInt hinting_engine; + FT_Bool no_stem_darkening; } CFF_DriverRec; diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index 7c99036b5..872744666 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -5,7 +5,7 @@ /* Basic OpenType/CFF type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2003, 2006-2008, 2010-2011 by */ +/* Copyright 1996-2003, 2006-2008, 2010-2011, 2013 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -270,6 +270,9 @@ FT_BEGIN_HEADER FT_String* registry; FT_String* ordering; + /* since version 2.4.12 */ + FT_Generic cf2_instance; + } CFF_FontRec, *CFF_Font; diff --git a/src/cff/rules.mk b/src/cff/rules.mk index ca7aa5de8..13115c255 100644 --- a/src/cff/rules.mk +++ b/src/cff/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2000, 2001, 2003, 2011 by +# Copyright 1996-2001, 2003, 2011, 2013 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, @@ -29,14 +29,27 @@ CFF_DRV_SRC := $(CFF_DIR)/cffcmap.c \ $(CFF_DIR)/cffload.c \ $(CFF_DIR)/cffobjs.c \ $(CFF_DIR)/cffparse.c \ - $(CFF_DIR)/cffpic.c + $(CFF_DIR)/cffpic.c \ + $(CFF_DIR)/cf2arrst.c \ + $(CFF_DIR)/cf2blues.c \ + $(CFF_DIR)/cf2error.c \ + $(CFF_DIR)/cf2font.c \ + $(CFF_DIR)/cf2ft.c \ + $(CFF_DIR)/cf2hints.c \ + $(CFF_DIR)/cf2intrp.c \ + $(CFF_DIR)/cf2read.c \ + $(CFF_DIR)/cf2stack.c + # CFF driver headers # CFF_DRV_H := $(CFF_DRV_SRC:%.c=%.h) \ $(CFF_DIR)/cfferrs.h \ $(CFF_DIR)/cfftoken.h \ - $(CFF_DIR)/cfftypes.h + $(CFF_DIR)/cfftypes.h \ + $(CFF_DIR)/cf2fixed.h \ + $(CFF_DIR)/cf2glue.h \ + $(CFF_DIR)/cf2types.h # CFF driver object(s)