From 27a4f9c4ac45ff65f941964f7351b64b1e6a9f35 Mon Sep 17 00:00:00 2001 From: scuri Date: Tue, 20 Oct 2009 17:20:18 +0000 Subject: *** empty log message *** --- src/freetype2/cff/cff.c | 1 + src/freetype2/cff/cffcmap.c | 25 +- src/freetype2/cff/cffcmap.h | 6 +- src/freetype2/cff/cffdrivr.c | 329 +++++++++++++++----- src/freetype2/cff/cffdrivr.h | 3 +- src/freetype2/cff/cffgload.c | 706 ++++++++++++++++++++++++++++--------------- src/freetype2/cff/cffgload.h | 17 +- src/freetype2/cff/cffload.c | 98 ++++-- src/freetype2/cff/cffload.h | 8 +- src/freetype2/cff/cffobjs.c | 431 ++++++++++++++++++-------- src/freetype2/cff/cffobjs.h | 22 +- src/freetype2/cff/cffparse.c | 459 +++++++++++++++++++++------- src/freetype2/cff/cffparse.h | 35 ++- src/freetype2/cff/cffpic.c | 99 ++++++ src/freetype2/cff/cffpic.h | 80 +++++ src/freetype2/cff/cfftypes.h | 10 +- 16 files changed, 1702 insertions(+), 627 deletions(-) create mode 100644 src/freetype2/cff/cffpic.c create mode 100644 src/freetype2/cff/cffpic.h (limited to 'src/freetype2/cff') diff --git a/src/freetype2/cff/cff.c b/src/freetype2/cff/cff.c index e6d8954..fccfd44 100644 --- a/src/freetype2/cff/cff.c +++ b/src/freetype2/cff/cff.c @@ -19,6 +19,7 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include +#include "cffpic.c" #include "cffdrivr.c" #include "cffparse.c" #include "cffload.c" diff --git a/src/freetype2/cff/cffcmap.c b/src/freetype2/cff/cffcmap.c index fffc5fc..46d603e 100644 --- a/src/freetype2/cff/cffcmap.c +++ b/src/freetype2/cff/cffcmap.c @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 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, */ @@ -65,7 +65,7 @@ } - FT_CALLBACK_DEF( FT_UInt ) + FT_CALLBACK_DEF( FT_UInt32 ) cff_cmap_encoding_char_next( CFF_CMapStd cmap, FT_UInt32 *pchar_code ) { @@ -99,16 +99,16 @@ } - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - cff_cmap_encoding_class_rec = - { + FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec, sizeof ( CFF_CMapStdRec ), (FT_CMap_InitFunc) cff_cmap_encoding_init, (FT_CMap_DoneFunc) cff_cmap_encoding_done, (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index, - (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next - }; + (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next, + + NULL, NULL, NULL, NULL, NULL + ) /*************************************************************************/ @@ -192,7 +192,7 @@ } - FT_CALLBACK_DEF( FT_UInt ) + FT_CALLBACK_DEF( FT_UInt32 ) cff_cmap_unicode_char_next( PS_Unicodes unicodes, FT_UInt32 *pchar_code ) { @@ -205,16 +205,15 @@ } - FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec - cff_cmap_unicode_class_rec = - { + FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec, sizeof ( PS_UnicodesRec ), (FT_CMap_InitFunc) cff_cmap_unicode_init, (FT_CMap_DoneFunc) cff_cmap_unicode_done, (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index, - (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next - }; + (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next, + NULL, NULL, NULL, NULL, NULL + ) /* END */ diff --git a/src/freetype2/cff/cffcmap.h b/src/freetype2/cff/cffcmap.h index 3809b85..3f7f67b 100644 --- a/src/freetype2/cff/cffcmap.h +++ b/src/freetype2/cff/cffcmap.h @@ -43,8 +43,7 @@ FT_BEGIN_HEADER } CFF_CMapStdRec; - FT_CALLBACK_TABLE const FT_CMap_ClassRec - cff_cmap_encoding_class_rec; + FT_DECLARE_CMAP_CLASS(cff_cmap_encoding_class_rec) /*************************************************************************/ @@ -57,8 +56,7 @@ FT_BEGIN_HEADER /* unicode (synthetic) cmaps */ - FT_CALLBACK_TABLE const FT_CMap_ClassRec - cff_cmap_unicode_class_rec; + FT_DECLARE_CMAP_CLASS(cff_cmap_unicode_class_rec) FT_END_HEADER diff --git a/src/freetype2/cff/cffdrivr.c b/src/freetype2/cff/cffdrivr.c index 952e88e..217adf2 100644 --- a/src/freetype2/cff/cffdrivr.c +++ b/src/freetype2/cff/cffdrivr.c @@ -4,7 +4,7 @@ /* */ /* OpenType font driver implementation (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -21,21 +21,25 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H -#include FT_TRUETYPE_IDS_H +#include FT_SERVICE_CID_H #include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_SERVICE_POSTSCRIPT_INFO_H +#include FT_SERVICE_POSTSCRIPT_NAME_H #include FT_SERVICE_TT_CMAP_H #include "cffdrivr.h" #include "cffgload.h" #include "cffload.h" #include "cffcmap.h" +#include "cffparse.h" #include "cfferrs.h" +#include "cffpic.h" #include FT_SERVICE_XFREE86_NAME_H #include FT_SERVICE_GLYPH_DICT_H + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ @@ -151,7 +155,7 @@ FT_UInt glyph_index, FT_Int32 load_flags ) { - FT_Error error; + FT_Error error; CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; CFF_Size size = (CFF_Size)cffsize; @@ -163,10 +167,10 @@ if ( !size ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + /* reset the size object if necessary */ if ( load_flags & FT_LOAD_NO_SCALE ) size = NULL; - /* reset the size object if necessary */ if ( size ) { /* these two objects must have the same parent */ @@ -184,10 +188,39 @@ } - /* - * GLYPH DICT SERVICE - * - */ + FT_CALLBACK_DEF( FT_Error ) + cff_get_advances( FT_Face face, + FT_UInt start, + FT_UInt count, + FT_Int32 flags, + FT_Fixed* advances ) + { + FT_UInt nn; + FT_Error error = CFF_Err_Ok; + FT_GlyphSlot slot = face->glyph; + + + flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; + + for ( nn = 0; nn < count; nn++ ) + { + error = Load_Glyph( slot, face->size, start + nn, flags ); + if ( error ) + break; + + advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) + ? slot->linearVertAdvance + : slot->linearHoriAdvance; + } + + return error; + } + + + /* + * GLYPH DICT SERVICE + * + */ static FT_Error cff_get_glyph_name( CFF_Face face, @@ -206,10 +239,10 @@ FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); if ( !psnames ) { - FT_ERROR(( "cff_get_glyph_name:" )); - FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" )); - FT_ERROR(( " " )); - FT_ERROR(( " without the `PSNames' module\n" )); + FT_ERROR(( "cff_get_glyph_name:" + " cannot get glyph name from CFF & CEF fonts\n" + " " + " without the `PSNames' module\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } @@ -226,8 +259,8 @@ FT_FREE( gname ); error = CFF_Err_Ok; - Exit: - return error; + Exit: + return error; } @@ -277,17 +310,16 @@ } - static const FT_Service_GlyphDictRec cff_service_glyph_dict = - { + FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict, (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, - (FT_GlyphDict_NameIndexFunc)cff_get_name_index, - }; + (FT_GlyphDict_NameIndexFunc)cff_get_name_index + ) - /* - * POSTSCRIPT INFO SERVICE - * - */ + /* + * POSTSCRIPT INFO SERVICE + * + */ static FT_Int cff_ps_has_glyph_names( FT_Face face ) @@ -306,9 +338,10 @@ if ( cff && cff->font_info == NULL ) { - CFF_FontRecDict dict = &cff->top_font.font_dict; - PS_FontInfoRec *font_info; - FT_Memory memory = face->root.memory; + CFF_FontRecDict dict = &cff->top_font.font_dict; + PS_FontInfoRec *font_info; + FT_Memory memory = face->root.memory; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) @@ -316,19 +349,19 @@ font_info->version = cff_index_get_sid_string( &cff->string_index, dict->version, - cff->psnames ); + psnames ); font_info->notice = cff_index_get_sid_string( &cff->string_index, dict->notice, - cff->psnames ); + psnames ); font_info->full_name = cff_index_get_sid_string( &cff->string_index, dict->full_name, - cff->psnames ); + psnames ); font_info->family_name = cff_index_get_sid_string( &cff->string_index, dict->family_name, - cff->psnames ); + psnames ); font_info->weight = cff_index_get_sid_string( &cff->string_index, dict->weight, - cff->psnames ); + psnames ); font_info->italic_angle = dict->italic_angle; font_info->is_fixed_pitch = dict->is_fixed_pitch; font_info->underline_position = (FT_Short)dict->underline_position; @@ -337,19 +370,40 @@ cff->font_info = font_info; } - *afont_info = *cff->font_info; + if ( cff ) + *afont_info = *cff->font_info; Fail: return error; } - static const FT_Service_PsInfoRec cff_service_ps_info = - { + FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info, (PS_GetFontInfoFunc) cff_ps_get_font_info, + (PS_GetFontExtraFunc) NULL, (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, (PS_GetFontPrivateFunc)NULL /* unsupported with CFF fonts */ - }; + ) + + + /* + * POSTSCRIPT NAME SERVICE + * + */ + + static const char* + cff_get_ps_name( CFF_Face face ) + { + CFF_Font cff = (CFF_Font)face->extra.data; + + + return (const char*)cff->font_name; + } + + + FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name, + (FT_PsName_GetFunc)cff_get_ps_name + ) /* @@ -368,15 +422,16 @@ { FT_CMap cmap = FT_CMAP( charmap ); FT_Error error = CFF_Err_Ok; + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Library library = FT_FACE_LIBRARY( face ); cmap_info->language = 0; + cmap_info->format = 0; - if ( cmap->clazz != &cff_cmap_encoding_class_rec && - cmap->clazz != &cff_cmap_unicode_class_rec ) + if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET && + cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET ) { - FT_Face face = FT_CMAP_FACE( cmap ); - FT_Library library = FT_FACE_LIBRARY( face ); FT_Module sfnt = FT_Get_Module( library, "sfnt" ); FT_Service_TTCMaps service = (FT_Service_TTCMaps)ft_module_get_service( sfnt, @@ -391,10 +446,143 @@ } - static const FT_Service_TTCMapsRec cff_service_get_cmap_info = - { + FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info, (TT_CMap_Info_GetFunc)cff_get_cmap_info - }; + ) + + + /* + * CID INFO SERVICE + * + */ + static FT_Error + cff_get_ros( CFF_Face face, + const char* *registry, + const char* *ordering, + FT_Int *supplement ) + { + FT_Error error = CFF_Err_Ok; + CFF_Font cff = (CFF_Font)face->extra.data; + + + if ( cff ) + { + CFF_FontRecDict dict = &cff->top_font.font_dict; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + + + if ( dict->cid_registry == 0xFFFFU ) + { + error = CFF_Err_Invalid_Argument; + goto Fail; + } + + if ( registry ) + { + if ( cff->registry == NULL ) + cff->registry = cff_index_get_sid_string( &cff->string_index, + dict->cid_registry, + psnames ); + *registry = cff->registry; + } + + if ( ordering ) + { + if ( cff->ordering == NULL ) + cff->ordering = cff_index_get_sid_string( &cff->string_index, + dict->cid_ordering, + psnames ); + *ordering = cff->ordering; + } + + /* + * XXX: According to Adobe TechNote #5176, the supplement in CFF + * can be a real number. We truncate it to fit public API + * since freetype-2.3.6. + */ + if ( supplement ) + { + if ( dict->cid_supplement < FT_INT_MIN || + dict->cid_supplement > FT_INT_MAX ) + FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n", + dict->cid_supplement )); + *supplement = (FT_Int)dict->cid_supplement; + } + } + + Fail: + return error; + } + + + static FT_Error + cff_get_is_cid( CFF_Face face, + FT_Bool *is_cid ) + { + FT_Error error = CFF_Err_Ok; + CFF_Font cff = (CFF_Font)face->extra.data; + + + *is_cid = 0; + + if ( cff ) + { + CFF_FontRecDict dict = &cff->top_font.font_dict; + + + if ( dict->cid_registry != 0xFFFFU ) + *is_cid = 1; + } + + return error; + } + + + static FT_Error + cff_get_cid_from_glyph_index( CFF_Face face, + FT_UInt glyph_index, + FT_UInt *cid ) + { + FT_Error error = CFF_Err_Ok; + CFF_Font cff; + + + cff = (CFF_Font)face->extra.data; + + if ( cff ) + { + FT_UInt c; + CFF_FontRecDict dict = &cff->top_font.font_dict; + + + if ( dict->cid_registry == 0xFFFFU ) + { + error = CFF_Err_Invalid_Argument; + goto Fail; + } + + if ( glyph_index > cff->num_glyphs ) + { + error = CFF_Err_Invalid_Argument; + goto Fail; + } + + c = cff->charset.sids[glyph_index]; + + if ( cid ) + *cid = c; + } + + Fail: + return error; + } + + + FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info, + (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros, + (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid, + (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index + ) /*************************************************************************/ @@ -408,18 +596,24 @@ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ - - static const FT_ServiceDescRec cff_services[] = - { - { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF }, - { FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info }, #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES - { FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict }, + FT_DEFINE_SERVICEDESCREC6(cff_services, + FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF, + FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET, + FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET, + FT_SERVICE_ID_GLYPH_DICT, &FT_CFF_SERVICE_GLYPH_DICT_GET, + FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET, + FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET + ) +#else + FT_DEFINE_SERVICEDESCREC5(cff_services, + FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF, + FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET, + FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET, + FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET, + FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET + ) #endif - { FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info }, - { NULL, NULL } - }; - FT_CALLBACK_DEF( FT_Module_Interface ) cff_get_interface( FT_Module driver, /* CFF_Driver */ @@ -427,9 +621,11 @@ { FT_Module sfnt; FT_Module_Interface result; + FT_Library library = driver->library; + FT_UNUSED(library); - result = ft_service_list_lookup( cff_services, module_interface ); + result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface ); if ( result != NULL ) return result; @@ -442,11 +638,13 @@ /* The FT_DriverInterface structure is defined in ftdriver.h. */ - FT_CALLBACK_TABLE_DEF - const FT_Driver_ClassRec cff_driver_class = - { - /* begin with the FT_Module_Class fields */ - { +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#define CFF_SIZE_SELECT cff_size_select +#else +#define CFF_SIZE_SELECT 0 +#endif + + FT_DEFINE_DRIVER(cff_driver_class, FT_MODULE_FONT_DRIVER | FT_MODULE_DRIVER_SCALABLE | FT_MODULE_DRIVER_HAS_HINTER, @@ -461,7 +659,6 @@ cff_driver_init, cff_driver_done, cff_get_interface, - }, /* now the specific driver fields */ sizeof( TT_FaceRec ), @@ -475,25 +672,19 @@ cff_slot_init, cff_slot_done, -#ifdef FT_CONFIG_OPTION_OLD_INTERNALS - ft_stub_set_char_sizes, - ft_stub_set_pixel_sizes, -#endif + ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ + ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ Load_Glyph, cff_get_kerning, 0, /* FT_Face_AttachFunc */ - 0, /* FT_Face_GetAdvancesFunc */ + cff_get_advances, /* FT_Face_GetAdvancesFunc */ cff_size_request, -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS - cff_size_select -#else - 0 /* FT_Size_SelectFunc */ -#endif - }; + CFF_SIZE_SELECT + ) /* END */ diff --git a/src/freetype2/cff/cffdrivr.h b/src/freetype2/cff/cffdrivr.h index 553848c..50e8138 100644 --- a/src/freetype2/cff/cffdrivr.h +++ b/src/freetype2/cff/cffdrivr.h @@ -27,8 +27,7 @@ FT_BEGIN_HEADER - FT_CALLBACK_TABLE - const FT_Driver_ClassRec cff_driver_class; + FT_DECLARE_DRIVER( cff_driver_class ) FT_END_HEADER diff --git a/src/freetype2/cff/cffgload.c b/src/freetype2/cff/cffgload.c index 0e2a179..40fa20b 100644 --- a/src/freetype2/cff/cffgload.c +++ b/src/freetype2/cff/cffgload.c @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,11 +18,9 @@ #include #include FT_INTERNAL_DEBUG_H -#include FT_INTERNAL_CALC_H #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_OUTLINE_H -#include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_POSTSCRIPT_HINTS_H #include "cffobjs.h" @@ -110,6 +108,12 @@ cff_op_callgsubr, cff_op_return, + /* Type 1 opcodes: invalid but seen in real life */ + cff_op_hsbw, + cff_op_closepath, + cff_op_callothersubr, + cff_op_pop, + /* do not remove */ cff_op_max @@ -120,6 +124,11 @@ #define CFF_COUNT_EXACT 0x40 #define CFF_COUNT_CLEAR_STACK 0x20 + /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ + /* used for checking the width and requested numbers of arguments */ + /* only; they are set to zero afterwards */ + + /* the other two flags are informative only and unused currently */ static const FT_Byte cff_argument_counts[] = { @@ -187,6 +196,11 @@ 1, /* callsubr */ 1, + 0, + + 2, /* hsbw */ + 0, + 0, 0 }; @@ -222,6 +236,8 @@ /* */ /* glyph :: The current glyph object. */ /* */ + /* hinting :: Whether hinting is active. */ + /* */ static void cff_builder_init( CFF_Builder* builder, TT_Face face, @@ -251,17 +267,14 @@ if ( hinting && size ) { - builder->hints_globals = size->root.internal; + CFF_Internal internal = (CFF_Internal)size->root.internal; + + + builder->hints_globals = (void *)internal->topfont; builder->hints_funcs = glyph->root.internal->glyph_hints; } } - if ( size ) - { - builder->scale_x = size->root.metrics.x_scale; - builder->scale_y = size->root.metrics.y_scale; - } - builder->pos_x = 0; builder->pos_y = 0; @@ -339,11 +352,15 @@ /* decoder :: A pointer to the glyph builder to initialize. */ /* */ /* */ - /* face :: The current face object. */ + /* face :: The current face object. */ /* */ - /* size :: The current size object. */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ /* */ - /* slot :: The current glyph object. */ + /* hinting :: Whether hinting is active. */ + /* */ + /* hint_mode :: The hinting mode. */ /* */ FT_LOCAL_DEF( void ) cff_decoder_init( CFF_Decoder* decoder, @@ -371,18 +388,21 @@ } - /* this function is used to select the locals subrs array */ + /* this function is used to select the subfont */ + /* and the locals subrs array */ FT_LOCAL_DEF( FT_Error ) cff_decoder_prepare( CFF_Decoder* decoder, + CFF_Size size, FT_UInt glyph_index ) { - CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data; - CFF_SubFont sub = &cff->top_font; - FT_Error error = CFF_Err_Ok; + CFF_Builder *builder = &decoder->builder; + CFF_Font cff = (CFF_Font)builder->face->extra.data; + CFF_SubFont sub = &cff->top_font; + FT_Error error = CFF_Err_Ok; /* manage CID fonts */ - if ( cff->num_subfonts >= 1 ) + if ( cff->num_subfonts ) { FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); @@ -393,9 +413,24 @@ error = CFF_Err_Invalid_File_Format; goto Exit; } - + + FT_TRACE4(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); + sub = cff->subfonts[fd_index]; + + if ( builder->hints_funcs && size ) + { + CFF_Internal internal = (CFF_Internal)size->root.internal; + + + /* for CFFs without subfonts, this value has already been set */ + builder->hints_globals = (void *)internal->subfonts[fd_index]; + } } +#ifdef FT_DEBUG_LEVEL_TRACE + else + FT_TRACE4(( "glyph index %d:\n", glyph_index )); +#endif decoder->num_locals = sub->num_local_subrs; decoder->locals = sub->local_subrs; @@ -437,8 +472,6 @@ point->x = x >> 16; point->y = y >> 16; *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); - - builder->last = *point; } outline->n_points++; @@ -517,27 +550,24 @@ cff_builder_close_contour( CFF_Builder* builder ) { FT_Outline* outline = builder->current; + FT_Int first; if ( !outline ) return; - /* XXXX: We must not include the last point in the path if it */ - /* is located on the first point. */ + first = outline->n_contours <= 1 + ? 0 : outline->contours[outline->n_contours - 2] + 1; + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ if ( outline->n_points > 1 ) { - FT_Int first = 0; FT_Vector* p1 = outline->points + first; FT_Vector* p2 = outline->points + outline->n_points - 1; FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; - if ( outline->n_contours > 1 ) - { - first = outline->contours[outline->n_contours - 2] + 1; - p1 = outline->points + first; - } - /* `delete' last point only if it coincides with the first */ /* point and if it is not a control point (which can happen). */ if ( p1->x == p2->x && p1->y == p2->y ) @@ -546,8 +576,18 @@ } if ( outline->n_contours > 0 ) - outline->contours[outline->n_contours - 1] = - (short)( outline->n_points - 1 ); + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether begin point and last point are the same. */ + if ( first == outline->n_points - 1 ) + { + outline->n_contours--; + outline->n_points--; + } + else + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + } } @@ -667,6 +707,12 @@ FT_ULong charstring_len; + if ( decoder->seac ) + { + FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); + return CFF_Err_Syntax_Error; + } + #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts don't necessarily have valid charsets. */ /* They use the character code, not the glyph index, in this case. */ @@ -687,8 +733,8 @@ if ( bchar_index < 0 || achar_index < 0 ) { - FT_ERROR(( "cff_operator_seac:" )); - FT_ERROR(( " invalid seac character code arguments\n" )); + FT_ERROR(( "cff_operator_seac:" + " invalid seac character code arguments\n" )); return CFF_Err_Syntax_Error; } @@ -737,8 +783,11 @@ &charstring, &charstring_len ); if ( !error ) { + /* the seac operator must not be nested */ + decoder->seac = TRUE; error = cff_decoder_parse_charstrings( decoder, charstring, charstring_len ); + decoder->seac = FALSE; if ( error ) goto Exit; @@ -763,8 +812,11 @@ &charstring, &charstring_len ); if ( !error ) { + /* the seac operator must not be nested */ + decoder->seac = TRUE; error = cff_decoder_parse_charstrings( decoder, charstring, charstring_len ); + decoder->seac = FALSE; if ( error ) goto Exit; @@ -826,9 +878,10 @@ decoder->read_width = 1; /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)(char*)&seed ^ - (FT_Fixed)(char*)&decoder ^ - (FT_Fixed)(char*)&charstring_base; + seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ + (FT_PtrDist)(char*)&decoder ^ + (FT_PtrDist)(char*)&charstring_base ) & + FT_ULONG_MAX ) ; seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; if ( seed == 0 ) seed = 0x7384; @@ -883,18 +936,18 @@ ip += 2; } else if ( v < 247 ) - val = (FT_Long)v - 139; + val = (FT_Int32)v - 139; else if ( v < 251 ) { if ( ip >= limit ) goto Syntax_Error; - val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108; + val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; } else if ( v < 255 ) { if ( ip >= limit ) goto Syntax_Error; - val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108; + val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; } else { @@ -923,6 +976,11 @@ } else { + /* The specification says that normally arguments are to be taken */ + /* from the bottom of the stack. However, this seems not to be */ + /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ + /* arguments similar to a PS interpreter. */ + FT_Fixed* args = decoder->top; FT_Int num_args = (FT_Int)( args - decoder->stack ); FT_Int req_args; @@ -954,6 +1012,9 @@ case 8: op = cff_op_rrcurveto; break; + case 9: + op = cff_op_closepath; + break; case 10: op = cff_op_callsubr; break; @@ -1004,6 +1065,12 @@ case 15: op = cff_op_eq; break; + case 16: + op = cff_op_callothersubr; + break; + case 17: + op = cff_op_pop; + break; case 18: op = cff_op_drop; break; @@ -1055,6 +1122,9 @@ } } break; + case 13: + op = cff_op_hsbw; + break; case 14: op = cff_op_endchar; break; @@ -1103,6 +1173,7 @@ default: ; } + if ( op == cff_op_unknown ) goto Syntax_Error; @@ -1110,8 +1181,6 @@ req_args = cff_argument_counts[op]; if ( req_args & CFF_COUNT_CHECK_WIDTH ) { - args = stack; - if ( num_args > 0 && decoder->read_width ) { /* If `nominal_width' is non-zero, the number is really a */ @@ -1145,7 +1214,7 @@ case cff_op_endchar: /* If there is a width specified for endchar, we either have */ /* 1 argument or 5 arguments. We like to argue. */ - set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) ); + set_width_ok = ( num_args == 5 ) || ( num_args == 1 ); break; default: @@ -1158,9 +1227,14 @@ decoder->glyph_width = decoder->nominal_width + ( stack[0] >> 16 ); + if ( decoder->width_only ) + { + /* we only want the advance width; stop here */ + break; + } + /* Consumed an argument. */ num_args--; - args++; } } @@ -1168,12 +1242,20 @@ req_args = 0; } - req_args &= 15; + req_args &= 0x000F; if ( num_args < req_args ) goto Stack_Underflow; args -= req_args; num_args -= req_args; + /* At this point, `args' points to the first argument of the */ + /* operand in case `req_args' isn't zero. Otherwise, we have */ + /* to adjust `args' manually. */ + + /* Note that we only pop arguments from the stack which we */ + /* really need and can digest so that we can continue in case */ + /* of superfluous stack elements. */ + switch ( op ) { case cff_op_hstem: @@ -1181,15 +1263,16 @@ case cff_op_hstemhm: case cff_op_vstemhm: /* the number of arguments is always even here */ - FT_TRACE4(( op == cff_op_hstem ? " hstem" : - ( op == cff_op_vstem ? " vstem" : - ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) )); + FT_TRACE4(( + op == cff_op_hstem ? " hstem\n" : + ( op == cff_op_vstem ? " vstem\n" : + ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); if ( hinter ) hinter->stems( hinter->hints, ( op == cff_op_hstem || op == cff_op_hstemhm ), num_args / 2, - args ); + args - ( num_args & ~1 ) ); decoder->num_hints += num_args / 2; args = stack; @@ -1209,7 +1292,7 @@ hinter->stems( hinter->hints, 0, num_args / 2, - args ); + args - ( num_args & ~1 ) ); decoder->num_hints += num_args / 2; } @@ -1232,12 +1315,14 @@ FT_UInt maskbyte; - FT_TRACE4(( " " )); + FT_TRACE4(( " (maskbytes: " )); for ( maskbyte = 0; maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); maskbyte++, ip++ ) FT_TRACE4(( "0x%02X", *ip )); + + FT_TRACE4(( ")\n" )); } #else ip += ( decoder->num_hints + 7 ) >> 3; @@ -1248,44 +1333,44 @@ break; case cff_op_rmoveto: - FT_TRACE4(( " rmoveto" )); + FT_TRACE4(( " rmoveto\n" )); cff_builder_close_contour( builder ); builder->path_begun = 0; - x += args[0]; - y += args[1]; + x += args[-2]; + y += args[-1]; args = stack; break; case cff_op_vmoveto: - FT_TRACE4(( " vmoveto" )); + FT_TRACE4(( " vmoveto\n" )); cff_builder_close_contour( builder ); builder->path_begun = 0; - y += args[0]; + y += args[-1]; args = stack; break; case cff_op_hmoveto: - FT_TRACE4(( " hmoveto" )); + FT_TRACE4(( " hmoveto\n" )); cff_builder_close_contour( builder ); builder->path_begun = 0; - x += args[0]; + x += args[-1]; args = stack; break; case cff_op_rlineto: - FT_TRACE4(( " rlineto" )); + FT_TRACE4(( " rlineto\n" )); if ( cff_builder_start_point ( builder, x, y ) || check_points( builder, num_args / 2 ) ) goto Fail; - if ( num_args < 2 || num_args & 1 ) + if ( num_args < 2 ) goto Stack_Underflow; - args = stack; + args -= num_args & ~1; while ( args < decoder->top ) { x += args[0]; @@ -1302,8 +1387,11 @@ FT_Int phase = ( op == cff_op_hlineto ); - FT_TRACE4(( op == cff_op_hlineto ? " hlineto" - : " vlineto" )); + FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" + : " vlineto\n" )); + + if ( num_args < 1 ) + goto Stack_Underflow; if ( cff_builder_start_point ( builder, x, y ) || check_points( builder, num_args ) ) @@ -1328,125 +1416,164 @@ break; case cff_op_rrcurveto: - FT_TRACE4(( " rrcurveto" )); + { + FT_Int nargs; - /* check number of arguments; must be a multiple of 6 */ - if ( num_args % 6 != 0 ) - goto Stack_Underflow; - if ( cff_builder_start_point ( builder, x, y ) || - check_points( builder, num_args / 2 ) ) - goto Fail; + FT_TRACE4(( " rrcurveto\n" )); - args = stack; - while ( args < decoder->top ) - { - x += args[0]; - y += args[1]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[2]; - y += args[3]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[4]; - y += args[5]; - cff_builder_add_point( builder, x, y, 1 ); - args += 6; + if ( num_args < 6 ) + goto Stack_Underflow; + + nargs = num_args - num_args % 6; + + if ( cff_builder_start_point ( builder, x, y ) || + check_points( builder, nargs / 2 ) ) + goto Fail; + + args -= nargs; + while ( args < decoder->top ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + cff_builder_add_point( builder, x, y, 1 ); + args += 6; + } + args = stack; } - args = stack; break; case cff_op_vvcurveto: - FT_TRACE4(( " vvcurveto" )); + { + FT_Int nargs; - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - args = stack; - if ( num_args & 1 ) - { - x += args[0]; - args++; - num_args--; - } + FT_TRACE4(( " vvcurveto\n" )); - if ( num_args % 4 != 0 ) - goto Stack_Underflow; + if ( num_args < 4 ) + goto Stack_Underflow; - if ( check_points( builder, 3 * ( num_args / 4 ) ) ) - goto Fail; + /* if num_args isn't of the form 4n or 4n+1, */ + /* we reduce it to 4n+1 */ - while ( args < decoder->top ) - { - y += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - y += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; + nargs = num_args - num_args % 4; + if ( num_args - nargs > 0 ) + nargs += 1; + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args -= nargs; + + if ( nargs & 1 ) + { + x += args[0]; + args++; + nargs--; + } + + if ( check_points( builder, 3 * ( nargs / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + y += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + y += args[3]; + cff_builder_add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; } - args = stack; break; case cff_op_hhcurveto: - FT_TRACE4(( " hhcurveto" )); + { + FT_Int nargs; - if ( cff_builder_start_point( builder, x, y ) ) - goto Fail; - args = stack; - if ( num_args & 1 ) - { - y += args[0]; - args++; - num_args--; - } + FT_TRACE4(( " hhcurveto\n" )); - if ( num_args % 4 != 0 ) - goto Stack_Underflow; + if ( num_args < 4 ) + goto Stack_Underflow; - if ( check_points( builder, 3 * ( num_args / 4 ) ) ) - goto Fail; + /* if num_args isn't of the form 4n or 4n+1, */ + /* we reduce it to 4n+1 */ - while ( args < decoder->top ) - { - x += args[0]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[1]; - y += args[2]; - cff_builder_add_point( builder, x, y, 0 ); - x += args[3]; - cff_builder_add_point( builder, x, y, 1 ); - args += 4; + nargs = num_args - num_args % 4; + if ( num_args - nargs > 0 ) + nargs += 1; + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args -= nargs; + if ( nargs & 1 ) + { + y += args[0]; + args++; + nargs--; + } + + if ( check_points( builder, 3 * ( nargs / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + x += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[3]; + cff_builder_add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; } - args = stack; break; case cff_op_vhcurveto: case cff_op_hvcurveto: { FT_Int phase; + FT_Int nargs; - FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto" - : " hvcurveto" )); + FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" + : " hvcurveto\n" )); if ( cff_builder_start_point( builder, x, y ) ) goto Fail; - args = stack; - if ( num_args < 4 || ( num_args % 4 ) > 1 ) + if ( num_args < 4 ) goto Stack_Underflow; - if ( check_points( builder, ( num_args / 4 ) * 3 ) ) + /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ + /* we reduce it to the largest one which fits */ + + nargs = num_args - num_args % 4; + if ( num_args - nargs > 0 ) + nargs += 1; + + args -= nargs; + if ( check_points( builder, ( nargs / 4 ) * 3 ) ) goto Stack_Underflow; phase = ( op == cff_op_hvcurveto ); - while ( num_args >= 4 ) + while ( nargs >= 4 ) { - num_args -= 4; + nargs -= 4; if ( phase ) { x += args[0]; @@ -1455,7 +1582,7 @@ y += args[2]; cff_builder_add_point( builder, x, y, 0 ); y += args[3]; - if ( num_args == 1 ) + if ( nargs == 1 ) x += args[4]; cff_builder_add_point( builder, x, y, 1 ); } @@ -1467,7 +1594,7 @@ y += args[2]; cff_builder_add_point( builder, x, y, 0 ); x += args[3]; - if ( num_args == 1 ) + if ( nargs == 1 ) y += args[4]; cff_builder_add_point( builder, x, y, 1 ); } @@ -1480,19 +1607,23 @@ case cff_op_rlinecurve: { - FT_Int num_lines = ( num_args - 6 ) / 2; + FT_Int num_lines; + FT_Int nargs; - FT_TRACE4(( " rlinecurve" )); + FT_TRACE4(( " rlinecurve\n" )); - if ( num_args < 8 || ( num_args - 6 ) & 1 ) + if ( num_args < 8 ) goto Stack_Underflow; + nargs = num_args & ~1; + num_lines = ( nargs - 6 ) / 2; + if ( cff_builder_start_point( builder, x, y ) || check_points( builder, num_lines + 3 ) ) goto Fail; - args = stack; + args -= nargs; /* first, add the line segments */ while ( num_lines > 0 ) @@ -1520,19 +1651,24 @@ case cff_op_rcurveline: { - FT_Int num_curves = ( num_args - 2 ) / 6; + FT_Int num_curves; + FT_Int nargs; - FT_TRACE4(( " rcurveline" )); + FT_TRACE4(( " rcurveline\n" )); - if ( num_args < 8 || ( num_args - 2 ) % 6 ) + if ( num_args < 8 ) goto Stack_Underflow; + nargs = num_args - 2; + nargs = nargs - nargs % 6 + 2; + num_curves = ( nargs - 2 ) / 6; + if ( cff_builder_start_point ( builder, x, y ) || - check_points( builder, num_curves*3 + 2 ) ) + check_points( builder, num_curves * 3 + 2 ) ) goto Fail; - args = stack; + args -= nargs; /* first, add the curves */ while ( num_curves > 0 ) @@ -1563,18 +1699,16 @@ FT_Pos start_y; - FT_TRACE4(( " hflex1" )); - - args = stack; + FT_TRACE4(( " hflex1\n" )); - /* adding five more points; 4 control points, 1 on-curve point */ - /* make sure we have enough space for the start point if it */ + /* adding five more points: 4 control points, 1 on-curve point */ + /* -- make sure we have enough space for the start point if it */ /* needs to be added */ if ( cff_builder_start_point( builder, x, y ) || check_points( builder, 6 ) ) goto Fail; - /* Record the starting point's y position for later use */ + /* record the starting point's y position for later use */ start_y = y; /* first control point */ @@ -1616,9 +1750,7 @@ FT_Pos start_y; - FT_TRACE4(( " hflex" )); - - args = stack; + FT_TRACE4(( " hflex\n" )); /* adding six more points; 4 control points, 2 on-curve points */ if ( cff_builder_start_point( builder, x, y ) || @@ -1663,14 +1795,15 @@ case cff_op_flex1: { - FT_Pos start_x, start_y; /* record start x, y values for */ - /* alter use */ - FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ - /* algorithm below */ - FT_Int horizontal, count; + FT_Pos start_x, start_y; /* record start x, y values for */ + /* alter use */ + FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ + /* algorithm below */ + FT_Int horizontal, count; + FT_Fixed* temp; - FT_TRACE4(( " flex1" )); + FT_TRACE4(( " flex1\n" )); /* adding six more points; 4 control points, 2 on-curve points */ if ( cff_builder_start_point( builder, x, y ) || @@ -1684,21 +1817,20 @@ /* XXX: figure out whether this is supposed to be a horizontal */ /* or vertical flex; the Type 2 specification is vague... */ - args = stack; + temp = args; /* grab up to the last argument */ for ( count = 5; count > 0; count-- ) { - dx += args[0]; - dy += args[1]; - args += 2; + dx += temp[0]; + dy += temp[1]; + temp += 2; } - /* rewind */ - args = stack; - - if ( dx < 0 ) dx = -dx; - if ( dy < 0 ) dy = -dy; + if ( dx < 0 ) + dx = -dx; + if ( dy < 0 ) + dy = -dy; /* strange test, but here it is... */ horizontal = ( dx > dy ); @@ -1707,7 +1839,8 @@ { x += args[0]; y += args[1]; - cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) ); + cff_builder_add_point( builder, x, y, + (FT_Bool)( count == 3 ) ); args += 2; } @@ -1734,13 +1867,12 @@ FT_UInt count; - FT_TRACE4(( " flex" )); + FT_TRACE4(( " flex\n" )); if ( cff_builder_start_point( builder, x, y ) || check_points( builder, 6 ) ) goto Fail; - args = stack; for ( count = 6; count > 0; count-- ) { x += args[0]; @@ -1755,21 +1887,20 @@ break; case cff_op_endchar: - FT_TRACE4(( " endchar" )); + FT_TRACE4(( " endchar\n" )); /* We are going to emulate the seac operator. */ - if ( num_args == 4 ) + if ( num_args >= 4 ) { /* Save glyph width so that the subglyphs don't overwrite it. */ FT_Pos glyph_width = decoder->glyph_width; error = cff_operator_seac( decoder, - args[0], - args[1], - (FT_Int)( args[2] >> 16 ), - (FT_Int)( args[3] >> 16 ) ); - args += 4; + args[-4], + args[-3], + (FT_Int)( args[-2] >> 16 ), + (FT_Int)( args[-1] >> 16 ) ); decoder->glyph_width = glyph_width; } @@ -1799,11 +1930,11 @@ } /* return now! */ - FT_TRACE4(( "\n\n" )); + FT_TRACE4(( "\n" )); return error; case cff_op_abs: - FT_TRACE4(( " abs" )); + FT_TRACE4(( " abs\n" )); if ( args[0] < 0 ) args[0] = -args[0]; @@ -1811,28 +1942,28 @@ break; case cff_op_add: - FT_TRACE4(( " add" )); + FT_TRACE4(( " add\n" )); args[0] += args[1]; args++; break; case cff_op_sub: - FT_TRACE4(( " sub" )); + FT_TRACE4(( " sub\n" )); args[0] -= args[1]; args++; break; case cff_op_div: - FT_TRACE4(( " div" )); + FT_TRACE4(( " div\n" )); args[0] = FT_DivFix( args[0], args[1] ); args++; break; case cff_op_neg: - FT_TRACE4(( " neg" )); + FT_TRACE4(( " neg\n" )); args[0] = -args[0]; args++; @@ -1843,7 +1974,7 @@ FT_Fixed Rand; - FT_TRACE4(( " rand" )); + FT_TRACE4(( " rand\n" )); Rand = seed; if ( Rand >= 0x8000L ) @@ -1858,14 +1989,14 @@ break; case cff_op_mul: - FT_TRACE4(( " mul" )); + FT_TRACE4(( " mul\n" )); args[0] = FT_MulFix( args[0], args[1] ); args++; break; case cff_op_sqrt: - FT_TRACE4(( " sqrt" )); + FT_TRACE4(( " sqrt\n" )); if ( args[0] > 0 ) { @@ -1890,7 +2021,7 @@ case cff_op_drop: /* nothing */ - FT_TRACE4(( " drop" )); + FT_TRACE4(( " drop\n" )); break; @@ -1899,7 +2030,7 @@ FT_Fixed tmp; - FT_TRACE4(( " exch" )); + FT_TRACE4(( " exch\n" )); tmp = args[0]; args[0] = args[1]; @@ -1913,7 +2044,7 @@ FT_Int idx = (FT_Int)( args[0] >> 16 ); - FT_TRACE4(( " index" )); + FT_TRACE4(( " index\n" )); if ( idx < 0 ) idx = 0; @@ -1930,7 +2061,7 @@ FT_Int idx = (FT_Int)( args[1] >> 16 ); - FT_TRACE4(( " roll" )); + FT_TRACE4(( " roll\n" )); if ( count <= 0 ) count = 1; @@ -1972,7 +2103,7 @@ break; case cff_op_dup: - FT_TRACE4(( " dup" )); + FT_TRACE4(( " dup\n" )); args[1] = args[0]; args++; @@ -1984,7 +2115,7 @@ FT_Int idx = (FT_Int)( args[1] >> 16 ); - FT_TRACE4(( " put" )); + FT_TRACE4(( " put\n" )); if ( idx >= 0 && idx < decoder->len_buildchar ) decoder->buildchar[idx] = val; @@ -1997,7 +2128,7 @@ FT_Fixed val = 0; - FT_TRACE4(( " get" )); + FT_TRACE4(( " get\n" )); if ( idx >= 0 && idx < decoder->len_buildchar ) val = decoder->buildchar[idx]; @@ -2008,18 +2139,63 @@ break; case cff_op_store: - FT_TRACE4(( " store ")); + FT_TRACE4(( " store\n")); goto Unimplemented; case cff_op_load: - FT_TRACE4(( " load" )); + FT_TRACE4(( " load\n" )); goto Unimplemented; case cff_op_dotsection: /* this operator is deprecated and ignored by the parser */ - FT_TRACE4(( " dotsection" )); + FT_TRACE4(( " dotsection\n" )); + break; + + case cff_op_closepath: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " closepath (invalid op)\n" )); + + args = stack; + break; + + case cff_op_hsbw: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " hsbw (invalid op)\n" )); + + decoder->glyph_width = decoder->nominal_width + + (args[1] >> 16); + x = args[0]; + y = 0; + args = stack; + break; + + case cff_op_callothersubr: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " callothersubr (invalid op)\n" )); + + /* don't modify stack; handle the subr as `unknown' so that */ + /* following `pop' operands use the arguments on stack */ + break; + + case cff_op_pop: + /* this is an invalid Type 2 operator; however, there */ + /* exist fonts which are incorrectly converted from probably */ + /* Type 1 to CFF, and some parsers seem to accept it */ + + FT_TRACE4(( " pop (invalid op)\n" )); + + args++; break; case cff_op_and: @@ -2027,7 +2203,7 @@ FT_Fixed cond = args[0] && args[1]; - FT_TRACE4(( " and" )); + FT_TRACE4(( " and\n" )); args[0] = cond ? 0x10000L : 0; args++; @@ -2039,7 +2215,7 @@ FT_Fixed cond = args[0] || args[1]; - FT_TRACE4(( " or" )); + FT_TRACE4(( " or\n" )); args[0] = cond ? 0x10000L : 0; args++; @@ -2051,7 +2227,7 @@ FT_Fixed cond = !args[0]; - FT_TRACE4(( " eq" )); + FT_TRACE4(( " eq\n" )); args[0] = cond ? 0x10000L : 0; args++; @@ -2063,7 +2239,7 @@ FT_Fixed cond = ( args[2] <= args[3] ); - FT_TRACE4(( " ifelse" )); + FT_TRACE4(( " ifelse\n" )); if ( !cond ) args[0] = args[1]; @@ -2077,12 +2253,12 @@ decoder->locals_bias ); - FT_TRACE4(( " callsubr(%d)", idx )); + FT_TRACE4(( " callsubr(%d)\n", idx )); if ( idx >= decoder->num_locals ) { - FT_ERROR(( "cff_decoder_parse_charstrings:" )); - FT_ERROR(( " invalid local subr index\n" )); + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invalid local subr index\n" )); goto Syntax_Error; } @@ -2103,7 +2279,7 @@ if ( !zone->base || zone->limit == zone->base ) { FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs!\n" )); + " invoking empty subrs\n" )); goto Syntax_Error; } @@ -2119,12 +2295,12 @@ decoder->globals_bias ); - FT_TRACE4(( " callgsubr(%d)", idx )); + FT_TRACE4(( " callgsubr(%d)\n", idx )); if ( idx >= decoder->num_globals ) { - FT_ERROR(( "cff_decoder_parse_charstrings:" )); - FT_ERROR(( " invalid global subr index\n" )); + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invalid global subr index\n" )); goto Syntax_Error; } @@ -2145,7 +2321,7 @@ if ( !zone->base || zone->limit == zone->base ) { FT_ERROR(( "cff_decoder_parse_charstrings:" - " invoking empty subrs!\n" )); + " invoking empty subrs\n" )); goto Syntax_Error; } @@ -2156,7 +2332,7 @@ break; case cff_op_return: - FT_TRACE4(( " return" )); + FT_TRACE4(( " return\n" )); if ( decoder->zone <= decoder->zones ) { @@ -2194,15 +2370,15 @@ return error; Syntax_Error: - FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" )); + FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); return CFF_Err_Invalid_File_Format; Stack_Underflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" )); + FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); return CFF_Err_Too_Few_Arguments; Stack_Overflow: - FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" )); + FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); return CFF_Err_Stack_Overflow; } @@ -2260,7 +2436,7 @@ &charstring, &charstring_len ); if ( !error ) { - error = cff_decoder_prepare( &decoder, glyph_index ); + error = cff_decoder_prepare( &decoder, size, glyph_index ); if ( !error ) error = cff_decoder_parse_charstrings( &decoder, charstring, @@ -2290,23 +2466,30 @@ { FT_Error error; CFF_Decoder decoder; - TT_Face face = (TT_Face)glyph->root.face; - FT_Bool hinting; - CFF_Font cff = (CFF_Font)face->extra.data; + TT_Face face = (TT_Face)glyph->root.face; + FT_Bool hinting, force_scaling; + CFF_Font cff = (CFF_Font)face->extra.data; FT_Matrix font_matrix; FT_Vector font_offset; + force_scaling = FALSE; + /* in a CID-keyed font, consider `glyph_index' as a CID and map */ /* it immediately to the real glyph_index -- if it isn't a */ /* subsetted font, glyph_indices and CIDs are identical, though */ if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && - cff->charset.cids ) + cff->charset.cids ) { - glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index ); - if ( glyph_index == 0 ) - return CFF_Err_Invalid_Argument; + /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ + if ( glyph_index != 0 ) + { + glyph_index = cff_charset_cid_to_gindex( &cff->charset, + glyph_index ); + if ( glyph_index == 0 ) + return CFF_Err_Invalid_Argument; + } } else if ( glyph_index >= cff->num_glyphs ) return CFF_Err_Invalid_Argument; @@ -2389,6 +2572,36 @@ if ( load_flags & FT_LOAD_SBITS_ONLY ) return CFF_Err_Invalid_Argument; + /* if we have a CID subfont, use its matrix (which has already */ + /* been multiplied with the root matrix) */ + + /* this scaling is only relevant if the PS hinter isn't active */ + if ( cff->num_subfonts ) + { + FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, + glyph_index ); + + FT_ULong top_upm = cff->top_font.font_dict.units_per_em; + FT_ULong sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; + + + font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; + font_offset = cff->subfonts[fd_index]->font_dict.font_offset; + + if ( top_upm != sub_upm ) + { + glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); + glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); + + force_scaling = TRUE; + } + } + else + { + font_matrix = cff->top_font.font_dict.font_matrix; + font_offset = cff->top_font.font_dict.font_offset; + } + glyph->root.outline.n_points = 0; glyph->root.outline.n_contours = 0; @@ -2405,15 +2618,18 @@ cff_decoder_init( &decoder, face, size, glyph, hinting, FT_LOAD_TARGET_MODE( load_flags ) ); + if ( load_flags & FT_LOAD_ADVANCE_ONLY ) + decoder.width_only = TRUE; + decoder.builder.no_recurse = - (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); + (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); /* now load the unscaled outline */ error = cff_get_glyph_data( face, glyph_index, &charstring, &charstring_len ); if ( !error ) { - error = cff_decoder_prepare( &decoder, glyph_index ); + error = cff_decoder_prepare( &decoder, size, glyph_index ); if ( !error ) { error = cff_decoder_parse_charstrings( &decoder, @@ -2481,21 +2697,6 @@ 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. */ @@ -2526,9 +2727,14 @@ glyph->root.linearHoriAdvance = decoder.glyph_width; glyph->root.internal->glyph_transformed = 0; +#ifdef FT_CONFIG_OPTION_OLD_INTERNALS has_vertical_info = FT_BOOL( face->vertical_info && face->vertical.number_Of_VMetrics > 0 && - face->vertical.long_metrics != 0 ); + face->vertical.long_metrics ); +#else + has_vertical_info = FT_BOOL( face->vertical_info && + face->vertical.number_Of_VMetrics > 0 ); +#endif /* get the vertical metrics from the vtmx table if we have one */ if ( has_vertical_info ) @@ -2565,7 +2771,6 @@ glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; - /* apply the font matrix */ if ( !( font_matrix.xx == 0x10000L && font_matrix.yy == 0x10000L && font_matrix.xy == 0 && @@ -2587,7 +2792,7 @@ FT_Vector_Transform( &advance, &font_matrix ); metrics->vertAdvance = advance.y + font_offset.y; - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; @@ -2620,7 +2825,8 @@ metrics->horiBearingY = cbox.yMax; if ( has_vertical_info ) - metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingX = metrics->horiBearingX - + metrics->horiAdvance / 2; else ft_synthesize_vertical_metrics( metrics, metrics->vertAdvance ); diff --git a/src/freetype2/cff/cffgload.h b/src/freetype2/cff/cffgload.h index f67864a..956817a 100644 --- a/src/freetype2/cff/cffgload.h +++ b/src/freetype2/cff/cffgload.h @@ -4,7 +4,7 @@ /* */ /* OpenType Glyph Loader (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -53,12 +53,6 @@ FT_BEGIN_HEADER /* */ /* current :: The current glyph outline. */ /* */ - /* last :: The last point position. */ - /* */ - /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ - /* */ - /* scale_y :: The vertical scale (FUnits to sub-pixels). */ - /* */ /* pos_x :: The horizontal translation (if composite glyph). */ /* */ /* pos_y :: The vertical translation (if composite glyph). */ @@ -92,11 +86,6 @@ FT_BEGIN_HEADER FT_Outline* base; FT_Outline* current; - FT_Vector last; - - FT_Fixed scale_x; - FT_Fixed scale_y; - FT_Pos pos_x; FT_Pos pos_y; @@ -146,6 +135,7 @@ FT_BEGIN_HEADER FT_Pos nominal_width; FT_Bool read_width; + FT_Bool width_only; FT_Int num_hints; FT_Fixed* buildchar; FT_Int len_buildchar; @@ -164,6 +154,8 @@ FT_BEGIN_HEADER FT_Render_Mode hint_mode; + FT_Bool seac; + } CFF_Decoder; @@ -177,6 +169,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) cff_decoder_prepare( CFF_Decoder* decoder, + CFF_Size size, FT_UInt glyph_index ); #if 0 /* unused until we support pure CFF fonts */ diff --git a/src/freetype2/cff/cffload.c b/src/freetype2/cff/cffload.c index dd2f113..64d1395 100644 --- a/src/freetype2/cff/cffload.c +++ b/src/freetype2/cff/cffload.c @@ -4,7 +4,7 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -31,6 +31,7 @@ #if 1 + static const FT_UShort cff_isoadobe_charset[229] = { 0, 1, 2, 3, 4, 5, 6, 7, @@ -175,13 +176,15 @@ 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378 }; -#endif + +#endif /* 1 */ FT_LOCAL_DEF( FT_UShort ) cff_get_standard_encoding( FT_UInt charcode ) { - return (FT_UShort)(charcode < 256 ? cff_standard_encoding[charcode] : 0); + return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode] + : 0 ); } @@ -316,7 +319,7 @@ static FT_Error cff_index_load_offsets( CFF_Index idx ) { - FT_Error error = 0; + FT_Error error = CFF_Err_Ok; FT_Stream stream = idx->stream; FT_Memory memory = stream->memory; @@ -399,6 +402,7 @@ old_offset = 1; for ( n = 0; n <= idx->count; n++ ) { + /* at this point, `idx->offsets' can't be NULL */ offset = idx->offsets[n]; if ( !offset ) offset = old_offset; @@ -732,6 +736,7 @@ { FT_Error error = FT_Err_Ok; FT_UInt i; + FT_Long j; FT_UShort max_cid = 0; @@ -746,8 +751,11 @@ if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) goto Exit; - for ( i = 0; i < num_glyphs; i++ ) - charset->cids[charset->sids[i]] = (FT_UShort)i; + /* When multiple GIDs map to the same CID, we choose the lowest */ + /* GID. This is not described in any spec, but it matches the */ + /* behaviour of recent Acroread versions. */ + for ( j = num_glyphs - 1; j >= 0 ; j-- ) + charset->cids[charset->sids[j]] = (FT_UShort)j; charset->max_cid = max_cid; charset->num_glyphs = num_glyphs; @@ -838,7 +846,20 @@ goto Exit; for ( j = 1; j < num_glyphs; j++ ) - charset->sids[j] = FT_GET_USHORT(); + { + FT_UShort sid = FT_GET_USHORT(); + + + /* this constant is given in the CFF specification */ + if ( sid < 65000L ) + charset->sids[j] = sid; + else + { + FT_TRACE0(( "cff_charset_load:" + " invalid SID value %d set to zero\n", sid )); + charset->sids[j] = 0; + } + } FT_FRAME_EXIT(); } @@ -871,6 +892,20 @@ goto Exit; } + /* check whether the range contains at least one valid glyph; */ + /* the constant is given in the CFF specification */ + if ( glyph_sid >= 65000L ) { + FT_ERROR(( "cff_charset_load: invalid SID range\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* try to rescue some of the SIDs if `nleft' is too large */ + if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) { + FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" )); + nleft = ( FT_UInt )( 65000L - 1L - glyph_sid ); + } + /* Fill in the range of sids -- `nleft + 1' glyphs. */ for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) charset->sids[j] = glyph_sid; @@ -879,7 +914,7 @@ break; default: - FT_ERROR(( "cff_charset_load: invalid table format!\n" )); + FT_ERROR(( "cff_charset_load: invalid table format\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -902,7 +937,7 @@ if ( num_glyphs > 229 ) { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe ISO-Latin)!\n" )); + "predefined charset (Adobe ISO-Latin)\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -920,7 +955,7 @@ if ( num_glyphs > 166 ) { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert)!\n" )); + "predefined charset (Adobe Expert)\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -938,7 +973,7 @@ if ( num_glyphs > 87 ) { FT_ERROR(( "cff_charset_load: implicit charset larger than\n" - "predefined charset (Adobe Expert Subset)!\n" )); + "predefined charset (Adobe Expert Subset)\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -1123,7 +1158,7 @@ break; default: - FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); + FT_ERROR(( "cff_encoding_load: invalid table format\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -1218,7 +1253,7 @@ break; default: - FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); + FT_ERROR(( "cff_encoding_load: invalid table format\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } @@ -1236,7 +1271,8 @@ CFF_Index idx, FT_UInt font_index, FT_Stream stream, - FT_ULong base_offset ) + FT_ULong base_offset, + FT_Library library ) { FT_Error error; CFF_ParserRec parser; @@ -1246,7 +1282,7 @@ CFF_Private priv = &font->private_dict; - cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict ); + cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library ); /* set defaults */ FT_MEM_ZERO( top, sizeof ( *top ) ); @@ -1272,8 +1308,9 @@ top->cid_ordering = 0xFFFFU; top->cid_font_name = 0xFFFFU; - error = cff_index_access_element( idx, font_index, &dict, &dict_len ) || - cff_parser_run( &parser, dict, dict + dict_len ); + error = cff_index_access_element( idx, font_index, &dict, &dict_len ); + if ( !error ) + error = cff_parser_run( &parser, dict, dict + dict_len ); cff_index_forget_element( idx, &dict ); @@ -1296,7 +1333,7 @@ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); - cff_parser_init( &parser, CFF_CODE_PRIVATE, priv ); + cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library ); if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || FT_FRAME_ENTER( font->font_dict.private_size ) ) @@ -1349,9 +1386,11 @@ FT_LOCAL_DEF( FT_Error ) - cff_font_load( FT_Stream stream, + cff_font_load( FT_Library library, + FT_Stream stream, FT_Int face_index, - CFF_Font font ) + CFF_Font font, + FT_Bool pure_cff ) { static const FT_Frame_Field cff_header_fields[] = { @@ -1388,7 +1427,7 @@ font->header_size < 4 || font->absolute_offsize > 4 ) { - FT_TRACE2(( "[not a CFF font header!]\n" )); + FT_TRACE2(( "[not a CFF font header]\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } @@ -1426,7 +1465,8 @@ &font->font_dict_index, face_index, stream, - base_offset ); + base_offset, + library ); if ( error ) goto Exit; @@ -1456,7 +1496,7 @@ if ( fd_index.count > CFF_MAX_CID_FONTS ) { - FT_ERROR(( "cff_font_load: FD array too large in CID font\n" )); + FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" )); goto Fail_CID; } @@ -1474,7 +1514,7 @@ { sub = font->subfonts[idx]; error = cff_subfont_load( sub, &fd_index, idx, - stream, base_offset ); + stream, base_offset, library ); if ( error ) goto Fail_CID; } @@ -1497,7 +1537,7 @@ /* read the charstrings index now */ if ( dict->charstrings_offset == 0 ) { - FT_ERROR(( "cff_font_load: no charstrings offset!\n" )); + FT_ERROR(( "cff_font_load: no charstrings offset\n" )); error = CFF_Err_Unknown_File_Format; goto Exit; } @@ -1515,7 +1555,7 @@ /* read the Charset and Encoding tables if available */ if ( font->num_glyphs > 0 ) { - FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU ); + FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff ); error = cff_charset_load( &font->charset, font->num_glyphs, stream, @@ -1535,9 +1575,6 @@ if ( error ) goto Exit; } - else - /* CID-keyed fonts only need CIDs */ - FT_FREE( font->charset.sids ); } /* get the font name (/CIDFontName for CID-keyed fonts, */ @@ -1590,6 +1627,9 @@ FT_FREE( font->font_info ); } + FT_FREE( font->registry ); + FT_FREE( font->ordering ); + FT_FREE( font->global_subrs ); FT_FREE( font->font_name ); } diff --git a/src/freetype2/cff/cffload.h b/src/freetype2/cff/cffload.h index 068cbb5..2b313ac 100644 --- a/src/freetype2/cff/cffload.h +++ b/src/freetype2/cff/cffload.h @@ -4,7 +4,7 @@ /* */ /* OpenType & CFF data/program tables loader (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -58,9 +58,11 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) - cff_font_load( FT_Stream stream, + cff_font_load( FT_Library library, + FT_Stream stream, FT_Int face_index, - CFF_Font font ); + CFF_Font font, + FT_Bool pure_cff ); FT_LOCAL( void ) cff_font_done( CFF_Font font ); diff --git a/src/freetype2/cff/cffobjs.c b/src/freetype2/cff/cffobjs.c index c02cf33..e0966e0 100644 --- a/src/freetype2/cff/cffobjs.c +++ b/src/freetype2/cff/cffobjs.c @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,7 @@ #include "cffload.h" #include "cffcmap.h" #include "cfferrs.h" +#include "cffpic.h" /*************************************************************************/ @@ -56,7 +57,7 @@ cff_size_get_globals_funcs( CFF_Size size ) { CFF_Face face = (CFF_Face)size->root.face; - CFF_Font font = (CFF_FontRec *)face->extra.data; + CFF_Font font = (CFF_Font)face->extra.data; PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; FT_Module module; @@ -72,23 +73,84 @@ FT_LOCAL_DEF( void ) cff_size_done( FT_Size cffsize ) /* CFF_Size */ { - CFF_Size size = (CFF_Size)cffsize; + CFF_Size size = (CFF_Size)cffsize; + CFF_Face face = (CFF_Face)size->root.face; + CFF_Font font = (CFF_Font)face->extra.data; + CFF_Internal internal = (CFF_Internal)cffsize->internal; - if ( cffsize->internal ) + if ( internal ) { PSH_Globals_Funcs funcs; funcs = cff_size_get_globals_funcs( size ); if ( funcs ) - funcs->destroy( (PSH_Globals)cffsize->internal ); + { + FT_UInt i; + + + funcs->destroy( internal->topfont ); + + for ( i = font->num_subfonts; i > 0; i-- ) + funcs->destroy( internal->subfonts[i - 1] ); + } - cffsize->internal = 0; + /* `internal' is freed by destroy_size (in ftobjs.c) */ } } + /* CFF and Type 1 private dictionaries have slightly different */ + /* structures; we need to synthesize a Type 1 dictionary on the fly */ + + static void + cff_make_private_dict( CFF_SubFont subfont, + PS_Private priv ) + { + CFF_Private cpriv = &subfont->private_dict; + FT_UInt n, count; + + + FT_MEM_ZERO( priv, sizeof ( *priv ) ); + + count = priv->num_blue_values = cpriv->num_blue_values; + for ( n = 0; n < count; n++ ) + priv->blue_values[n] = (FT_Short)cpriv->blue_values[n]; + + count = priv->num_other_blues = cpriv->num_other_blues; + for ( n = 0; n < count; n++ ) + priv->other_blues[n] = (FT_Short)cpriv->other_blues[n]; + + count = priv->num_family_blues = cpriv->num_family_blues; + for ( n = 0; n < count; n++ ) + priv->family_blues[n] = (FT_Short)cpriv->family_blues[n]; + + count = priv->num_family_other_blues = cpriv->num_family_other_blues; + for ( n = 0; n < count; n++ ) + priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; + + priv->blue_scale = cpriv->blue_scale; + priv->blue_shift = (FT_Int)cpriv->blue_shift; + priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz; + + priv->standard_width[0] = (FT_UShort)cpriv->standard_width; + priv->standard_height[0] = (FT_UShort)cpriv->standard_height; + + count = priv->num_snap_widths = cpriv->num_snap_widths; + for ( n = 0; n < count; n++ ) + priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; + + count = priv->num_snap_heights = cpriv->num_snap_heights; + for ( n = 0; n < count; n++ ) + priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; + + priv->force_bold = cpriv->force_bold; + priv->language_group = cpriv->language_group; + priv->lenIV = cpriv->lenIV; + } + + FT_LOCAL_DEF( FT_Error ) cff_size_init( FT_Size cffsize ) /* CFF_Size */ { @@ -99,68 +161,43 @@ if ( funcs ) { - PSH_Globals globals; - CFF_Face face = (CFF_Face)cffsize->face; - CFF_Font font = (CFF_FontRec *)face->extra.data; - CFF_SubFont subfont = &font->top_font; + CFF_Face face = (CFF_Face)cffsize->face; + CFF_Font font = (CFF_Font)face->extra.data; + CFF_Internal internal; - CFF_Private cpriv = &subfont->private_dict; PS_PrivateRec priv; + FT_Memory memory = cffsize->face->memory; + FT_UInt i; - /* IMPORTANT: The CFF and Type1 private dictionaries have */ - /* slightly different structures; we need to */ - /* synthetize a type1 dictionary on the fly here. */ - - { - FT_UInt n, count; - - - FT_MEM_ZERO( &priv, sizeof ( priv ) ); - - count = priv.num_blue_values = cpriv->num_blue_values; - for ( n = 0; n < count; n++ ) - priv.blue_values[n] = (FT_Short)cpriv->blue_values[n]; - - count = priv.num_other_blues = cpriv->num_other_blues; - for ( n = 0; n < count; n++ ) - priv.other_blues[n] = (FT_Short)cpriv->other_blues[n]; - count = priv.num_family_blues = cpriv->num_family_blues; - for ( n = 0; n < count; n++ ) - priv.family_blues[n] = (FT_Short)cpriv->family_blues[n]; - - count = priv.num_family_other_blues = cpriv->num_family_other_blues; - for ( n = 0; n < count; n++ ) - priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; - - priv.blue_scale = cpriv->blue_scale; - priv.blue_shift = (FT_Int)cpriv->blue_shift; - priv.blue_fuzz = (FT_Int)cpriv->blue_fuzz; + if ( FT_NEW( internal ) ) + goto Exit; - priv.standard_width[0] = (FT_UShort)cpriv->standard_width; - priv.standard_height[0] = (FT_UShort)cpriv->standard_height; + cff_make_private_dict( &font->top_font, &priv ); + error = funcs->create( cffsize->face->memory, &priv, + &internal->topfont ); + if ( error ) + goto Exit; - count = priv.num_snap_widths = cpriv->num_snap_widths; - for ( n = 0; n < count; n++ ) - priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; + for ( i = font->num_subfonts; i > 0; i-- ) + { + CFF_SubFont sub = font->subfonts[i - 1]; - count = priv.num_snap_heights = cpriv->num_snap_heights; - for ( n = 0; n < count; n++ ) - priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; - priv.force_bold = cpriv->force_bold; - priv.language_group = cpriv->language_group; - priv.lenIV = cpriv->lenIV; + cff_make_private_dict( sub, &priv ); + error = funcs->create( cffsize->face->memory, &priv, + &internal->subfonts[i - 1] ); + if ( error ) + goto Exit; } - error = funcs->create( cffsize->face->memory, &priv, &globals ); - if ( !error ) - cffsize->internal = (FT_Size_Internal)(void*)globals; + cffsize->internal = (FT_Size_Internal)(void*)internal; } size->strike_index = 0xFFFFFFFFUL; + Exit: return error; } @@ -182,11 +219,42 @@ funcs = cff_size_get_globals_funcs( cffsize ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->internal, - size->metrics.x_scale, - size->metrics.y_scale, + { + CFF_Face face = (CFF_Face)size->face; + CFF_Font font = (CFF_Font)face->extra.data; + CFF_Internal internal = (CFF_Internal)size->internal; + + FT_ULong top_upm = font->top_font.font_dict.units_per_em; + FT_UInt i; + + + funcs->set_scale( internal->topfont, + size->metrics.x_scale, size->metrics.y_scale, 0, 0 ); + for ( i = font->num_subfonts; i > 0; i-- ) + { + CFF_SubFont sub = font->subfonts[i - 1]; + FT_ULong sub_upm = sub->font_dict.units_per_em; + FT_Pos x_scale, y_scale; + + + if ( top_upm != sub_upm ) + { + x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); + y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); + } + else + { + x_scale = size->metrics.x_scale; + y_scale = size->metrics.y_scale; + } + + funcs->set_scale( internal->subfonts[i - 1], + x_scale, y_scale, 0, 0 ); + } + } + return CFF_Err_Ok; } @@ -223,11 +291,42 @@ funcs = cff_size_get_globals_funcs( cffsize ); if ( funcs ) - funcs->set_scale( (PSH_Globals)size->internal, - size->metrics.x_scale, - size->metrics.y_scale, + { + CFF_Face cffface = (CFF_Face)size->face; + CFF_Font font = (CFF_Font)cffface->extra.data; + CFF_Internal internal = (CFF_Internal)size->internal; + + FT_ULong top_upm = font->top_font.font_dict.units_per_em; + FT_UInt i; + + + funcs->set_scale( internal->topfont, + size->metrics.x_scale, size->metrics.y_scale, 0, 0 ); + for ( i = font->num_subfonts; i > 0; i-- ) + { + CFF_SubFont sub = font->subfonts[i - 1]; + FT_ULong sub_upm = sub->font_dict.units_per_em; + FT_Pos x_scale, y_scale; + + + if ( top_upm != sub_upm ) + { + x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); + y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); + } + else + { + x_scale = size->metrics.x_scale; + y_scale = size->metrics.y_scale; + } + + funcs->set_scale( internal->subfonts[i - 1], + x_scale, y_scale, 0, 0 ); + } + } + return CFF_Err_Ok; } @@ -249,7 +348,7 @@ cff_slot_init( FT_GlyphSlot slot ) { CFF_Face face = (CFF_Face)slot->face; - CFF_Font font = (CFF_FontRec *)face->extra.data; + CFF_Font font = (CFF_Font)face->extra.data; PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; @@ -270,7 +369,7 @@ } } - return 0; + return CFF_Err_Ok; } @@ -288,7 +387,9 @@ FT_String* result; - result = ft_mem_strdup( memory, source, &error ); + (void)FT_STRDUP( result, source ); + + FT_UNUSED( error ); return result; } @@ -308,6 +409,7 @@ PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; + FT_Library library = cffface->driver->root.library; #if 0 @@ -319,14 +421,14 @@ goto Bad_Format; #else sfnt = (SFNT_Service)FT_Get_Module_Interface( - cffface->driver->root.library, "sfnt" ); + library, "sfnt" ); if ( !sfnt ) goto Bad_Format; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( - cffface->driver->root.library, "pshinter" ); + library, "pshinter" ); #endif /* create input stream from resource */ @@ -337,7 +439,7 @@ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { - if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ + if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ { FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); goto Bad_Format; @@ -365,8 +467,7 @@ pure_cff = 0; /* load font directory */ - error = sfnt->load_face( stream, face, - face_index, num_params, params ); + error = sfnt->load_face( stream, face, 0, num_params, params ); if ( error ) goto Exit; } @@ -408,13 +509,15 @@ goto Exit; face->extra.data = cff; - error = cff_font_load( stream, face_index, cff ); + error = cff_font_load( library, stream, face_index, cff, pure_cff ); if ( error ) goto Exit; cff->pshinter = pshinter; cff->psnames = (void*)psnames; + cffface->face_index = face_index; + /* Complement the root flags with some interesting information. */ /* Note that this is only necessary for pure CFF and CEF fonts; */ /* SFNT based fonts use the `name' table instead. */ @@ -427,13 +530,118 @@ /* which aren't CID-keyed */ if ( dict->cid_registry == 0xFFFFU && !psnames ) { - FT_ERROR(( "cff_face_init:" )); - FT_ERROR(( " cannot open CFF & CEF fonts\n" )); - FT_ERROR(( " " )); - FT_ERROR(( " without the `PSNames' module\n" )); + FT_ERROR(( "cff_face_init:" + " cannot open CFF & CEF fonts\n" + " " + " without the `PSNames' module\n" )); goto Bad_Format; } + if ( !dict->units_per_em ) + dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; + + /* Normalize the font matrix so that `matrix->xx' is 1; the */ + /* scaling is done with `units_per_em' then (at this point, */ + /* it already contains the scaling factor, but without */ + /* normalization of the matrix). */ + /* */ + /* Note that the offsets must be expressed in integer font */ + /* units. */ + + { + FT_Matrix* matrix = &dict->font_matrix; + FT_Vector* offset = &dict->font_offset; + FT_ULong* upm = &dict->units_per_em; + FT_Fixed temp = FT_ABS( matrix->yy ); + + + if ( temp != 0x10000L ) + { + *upm = FT_DivFix( *upm, temp ); + + matrix->xx = FT_DivFix( matrix->xx, temp ); + matrix->yx = FT_DivFix( matrix->yx, temp ); + matrix->xy = FT_DivFix( matrix->xy, temp ); + matrix->yy = FT_DivFix( matrix->yy, temp ); + offset->x = FT_DivFix( offset->x, temp ); + offset->y = FT_DivFix( offset->y, temp ); + } + + offset->x >>= 16; + offset->y >>= 16; + } + + for ( i = cff->num_subfonts; i > 0; i-- ) + { + CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; + CFF_FontRecDict top = &cff->top_font.font_dict; + + FT_Matrix* matrix; + FT_Vector* offset; + FT_ULong* upm; + FT_Fixed temp; + + + if ( sub->units_per_em ) + { + FT_Long scaling; + + + if ( top->units_per_em > 1 && sub->units_per_em > 1 ) + scaling = FT_MIN( top->units_per_em, sub->units_per_em ); + else + scaling = 1; + + FT_Matrix_Multiply_Scaled( &top->font_matrix, + &sub->font_matrix, + scaling ); + FT_Vector_Transform_Scaled( &sub->font_offset, + &top->font_matrix, + scaling ); + + sub->units_per_em = FT_MulDiv( sub->units_per_em, + top->units_per_em, + scaling ); + } + else + { + sub->font_matrix = top->font_matrix; + sub->font_offset = top->font_offset; + + sub->units_per_em = top->units_per_em; + } + + matrix = &sub->font_matrix; + offset = &sub->font_offset; + upm = &sub->units_per_em; + temp = FT_ABS( matrix->yy ); + + if ( temp != 0x10000L ) + { + *upm = FT_DivFix( *upm, temp ); + + /* if *upm is larger than 100*1000 we divide by 1000 -- */ + /* this can happen if e.g. there is no top-font FontMatrix */ + /* and the subfont FontMatrix already contains the complete */ + /* scaling for the subfont (see section 5.11 of the PLRM) */ + + /* 100 is a heuristic value */ + + if ( *upm > 100L * 1000L ) + *upm = ( *upm + 500 ) / 1000; + + matrix->xx = FT_DivFix( matrix->xx, temp ); + matrix->yx = FT_DivFix( matrix->yx, temp ); + matrix->xy = FT_DivFix( matrix->xy, temp ); + matrix->yy = FT_DivFix( matrix->yy, temp ); + offset->x = FT_DivFix( offset->x, temp ); + offset->y = FT_DivFix( offset->y, temp ); + } + + offset->x >>= 16; + offset->y >>= 16; + } + if ( pure_cff ) { char* style_name = NULL; @@ -444,7 +652,7 @@ /* compute number of glyphs */ if ( dict->cid_registry != 0xFFFFU ) - cffface->num_glyphs = dict->cid_count; + cffface->num_glyphs = cff->charset.max_cid; else cffface->num_glyphs = cff->charstrings_index.count; @@ -454,10 +662,7 @@ cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16; cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16; - if ( !dict->units_per_em ) - dict->units_per_em = 1000; - - cffface->units_per_EM = dict->units_per_em; + cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); cffface->ascender = (FT_Short)( cffface->bbox.yMax ); cffface->descender = (FT_Short)( cffface->bbox.yMin ); @@ -561,22 +766,22 @@ /* */ /* Compute face flags. */ /* */ - flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ - FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ - FT_FACE_FLAG_HINTER; /* has native hinter */ + flags = (FT_UInt32)( FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ + FT_FACE_FLAG_HINTER ); /* has native hinter */ if ( sfnt_format ) - flags |= FT_FACE_FLAG_SFNT; + flags |= (FT_UInt32)FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) - flags |= FT_FACE_FLAG_FIXED_WIDTH; + flags |= (FT_UInt32)FT_FACE_FLAG_FIXED_WIDTH; /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ #if 0 /* kerning available? */ if ( face->kern_pairs ) - flags |= FT_FACE_FLAG_KERNING; + flags |= (FT_UInt32)FT_FACE_FLAG_KERNING; #endif cffface->face_flags = flags; @@ -611,51 +816,25 @@ cffface->style_flags = flags; } - else - { - if ( !dict->units_per_em ) - dict->units_per_em = face->root.units_per_EM; - } - - /* handle font matrix settings in subfonts (if any) */ - for ( i = cff->num_subfonts; i > 0; i-- ) - { - CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; - CFF_FontRecDict top = &cff->top_font.font_dict; - if ( sub->units_per_em ) - { - FT_Matrix scale; - - - scale.xx = scale.yy = (FT_Fixed)FT_DivFix( top->units_per_em, - sub->units_per_em ); - scale.xy = scale.yx = 0; - - FT_Matrix_Multiply( &scale, &sub->font_matrix ); - FT_Vector_Transform( &sub->font_offset, &scale ); - } - else - { - sub->font_matrix = top->font_matrix; - sub->font_offset = top->font_offset; - } - } - #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ - /* has unset this flag because of the 3.0 `post' table */ + /* has unset this flag because of the 3.0 `post' table. */ if ( dict->cid_registry == 0xFFFFU ) cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif + if ( dict->cid_registry != 0xFFFFU && pure_cff ) + cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; + + /*******************************************************************/ /* */ /* Compute char maps. */ /* */ - /* Try to synthetize a Unicode charmap if there is none available */ + /* Try to synthesize a Unicode charmap if there is none available */ /* already. If an OpenType font contains a Unicode "cmap", we */ /* will use it, whatever be in the CFF part of the file. */ { @@ -683,7 +862,7 @@ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; - /* we didn't find a Unicode charmap -- synthetize one */ + /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; cmaprec.platform_id = 3; cmaprec.encoding_id = 1; @@ -691,7 +870,7 @@ nn = (FT_UInt)cffface->num_charmaps; - FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); + FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL ); /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) @@ -710,19 +889,19 @@ { cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; - clazz = &cff_cmap_encoding_class_rec; + clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } else if ( encoding->offset == 1 ) { cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; - clazz = &cff_cmap_encoding_class_rec; + clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } else { cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; - clazz = &cff_cmap_encoding_class_rec; + clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } FT_CMap_New( clazz, NULL, &cmaprec, NULL ); @@ -742,10 +921,16 @@ FT_LOCAL_DEF( void ) cff_face_done( FT_Face cffface ) /* CFF_Face */ { - CFF_Face face = (CFF_Face)cffface; - FT_Memory memory = cffface->memory; - SFNT_Service sfnt = (SFNT_Service)face->sfnt; + CFF_Face face = (CFF_Face)cffface; + FT_Memory memory; + SFNT_Service sfnt; + + + if ( !face ) + return; + memory = cffface->memory; + sfnt = (SFNT_Service)face->sfnt; if ( sfnt ) sfnt->done_face( face ); diff --git a/src/freetype2/cff/cffobjs.h b/src/freetype2/cff/cffobjs.h index f18b5d9..3c81cee 100644 --- a/src/freetype2/cff/cffobjs.h +++ b/src/freetype2/cff/cffobjs.h @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -25,6 +25,7 @@ #include "cfftypes.h" #include FT_INTERNAL_TRUETYPE_TYPES_H #include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H FT_BEGIN_HEADER @@ -53,8 +54,8 @@ FT_BEGIN_HEADER /* */ typedef struct CFF_SizeRec_ { - FT_SizeRec root; - FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ + FT_SizeRec root; + FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */ } CFF_SizeRec, *CFF_Size; @@ -80,6 +81,21 @@ FT_BEGIN_HEADER } CFF_GlyphSlotRec, *CFF_GlyphSlot; + /*************************************************************************/ + /* */ + /* */ + /* CFF_Internal */ + /* */ + /* */ + /* The interface to the `internal' field of `FT_Size'. */ + /* */ + typedef struct CFF_InternalRec_ + { + PSH_Globals topfont; + PSH_Globals subfonts[CFF_MAX_CID_FONTS]; + + } CFF_InternalRec, *CFF_Internal; + /*************************************************************************/ /* */ diff --git a/src/freetype2/cff/cffparse.c b/src/freetype2/cff/cffparse.c index 41af6a3..947ec9d 100644 --- a/src/freetype2/cff/cffparse.c +++ b/src/freetype2/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -19,8 +19,10 @@ #include #include "cffparse.h" #include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_DEBUG_H #include "cfferrs.h" +#include "cffpic.h" /*************************************************************************/ @@ -33,47 +35,20 @@ #define FT_COMPONENT trace_cffparse - enum - { - cff_kind_none = 0, - cff_kind_num, - cff_kind_fixed, - cff_kind_fixed_thousand, - cff_kind_string, - cff_kind_bool, - cff_kind_delta, - cff_kind_callback, - - cff_kind_max /* do not remove */ - }; - - - /* now generate handlers for the most simple fields */ - typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser ); - - typedef struct CFF_Field_Handler_ - { - int kind; - int code; - FT_UInt offset; - FT_Byte size; - CFF_Field_Reader reader; - FT_UInt array_max; - FT_UInt count_offset; - - } CFF_Field_Handler; FT_LOCAL_DEF( void ) cff_parser_init( CFF_Parser parser, FT_UInt code, - void* object ) + void* object, + FT_Library library) { FT_MEM_ZERO( parser, sizeof ( *parser ) ); parser->top = parser->stack; parser->object_code = code; parser->object = object; + parser->library = library; } @@ -136,24 +111,53 @@ } + static const FT_Long power_tens[] = + { + 1L, + 10L, + 100L, + 1000L, + 10000L, + 100000L, + 1000000L, + 10000000L, + 100000000L, + 1000000000L + }; + + /* read a real */ static FT_Fixed cff_parse_real( FT_Byte* start, FT_Byte* limit, - FT_Int power_ten ) + FT_Long power_ten, + FT_Long* scaling ) { - FT_Byte* p = start; - FT_Long num, divider, result, exponent; - FT_Int sign = 0, exponent_sign = 0; + FT_Byte* p = start; FT_UInt nib; FT_UInt phase; + FT_Long result, number, rest, exponent; + FT_Int sign = 0, exponent_sign = 0; + FT_Long exponent_add, integer_length, fraction_length; + + + if ( scaling ) + *scaling = 0; + + result = 0; + + number = 0; + rest = 0; + exponent = 0; - result = 0; - num = 0; - divider = 1; + exponent_add = 0; + integer_length = 0; + fraction_length = 0; - /* first of all, read the integer part */ + FT_UNUSED( rest ); + + /* First of all, read the integer part. */ phase = 4; for (;;) @@ -166,7 +170,7 @@ /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Bad; + goto Exit; } /* Get the nibble. */ @@ -178,10 +182,20 @@ else if ( nib > 9 ) break; else - result = result * 10 + nib; + { + /* Increase exponent if we can't add the digit. */ + if ( number >= 0xCCCCCCCL ) + exponent_add++; + /* Skip leading zeros. */ + else if ( nib || number ) + { + integer_length++; + number = number * 10 + nib; + } + } } - /* read decimal part, if any */ + /* Read fraction part, if any. */ if ( nib == 0xa ) for (;;) { @@ -193,7 +207,7 @@ /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Bad; + goto Exit; } /* Get the nibble. */ @@ -202,14 +216,18 @@ if ( nib >= 10 ) break; - if ( divider < 10000000L ) + /* Skip leading zeros if possible. */ + if ( !nib && !number ) + exponent_add--; + /* Only add digit if we don't overflow. */ + else if ( number < 0xCCCCCCCL && fraction_length < 9 ) { - num = num * 10 + nib; - divider *= 10; + fraction_length++; + number = number * 10 + nib; } } - /* read exponent, if any */ + /* Read exponent, if any. */ if ( nib == 12 ) { exponent_sign = 1; @@ -218,19 +236,17 @@ if ( nib == 11 ) { - exponent = 0; - for (;;) { - /* If we entered this iteration with phase == 4, we need */ - /* to read a new byte. */ + /* If we entered this iteration with phase == 4, */ + /* we need to read a new byte. */ if ( phase ) { p++; /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Bad; + goto Exit; } /* Get the nibble. */ @@ -240,47 +256,111 @@ break; exponent = exponent * 10 + nib; + + /* Arbitrarily limit exponent. */ + if ( exponent > 1000 ) + goto Exit; } if ( exponent_sign ) exponent = -exponent; - - power_ten += (FT_Int)exponent; } - /* raise to power of ten if needed */ - while ( power_ten > 0 ) + /* We don't check `power_ten' and `exponent_add'. */ + exponent += power_ten + exponent_add; + + if ( scaling ) { - result = result * 10; - num = num * 10; + /* Only use `fraction_length'. */ + fraction_length += integer_length; + exponent += integer_length; - power_ten--; - } + if ( fraction_length <= 5 ) + { + if ( number > 0x7FFFL ) + { + result = FT_DivFix( number, 10 ); + *scaling = exponent - fraction_length + 1; + } + else + { + if ( exponent > 0 ) + { + FT_Long new_fraction_length, shift; - while ( power_ten < 0 ) - { - result = result / 10; - divider = divider * 10; - power_ten++; + /* Make `scaling' as small as possible. */ + new_fraction_length = FT_MIN( exponent, 5 ); + exponent -= new_fraction_length; + shift = new_fraction_length - fraction_length; + + number *= power_tens[shift]; + if ( number > 0x7FFFL ) + { + number /= 10; + exponent += 1; + } + } + else + exponent -= fraction_length; + + result = number << 16; + *scaling = exponent; + } + } + else + { + if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL ) + { + result = FT_DivFix( number, power_tens[fraction_length - 4] ); + *scaling = exponent - 4; + } + else + { + result = FT_DivFix( number, power_tens[fraction_length - 5] ); + *scaling = exponent - 5; + } + } } + else + { + integer_length += exponent; + fraction_length -= exponent; + + /* Check for overflow and underflow. */ + if ( FT_ABS( integer_length ) > 5 ) + goto Exit; + + /* Remove non-significant digits. */ + if ( integer_length < 0 ) { + number /= power_tens[-integer_length]; + fraction_length += integer_length; + } + + /* Convert into 16.16 format. */ + if ( fraction_length > 0 ) + { + if ( ( number / power_tens[fraction_length] ) > 0x7FFFL ) + goto Exit; + + result = FT_DivFix( number, power_tens[fraction_length] ); + } + else + { + number *= power_tens[-fraction_length]; - /* Move the integer part into the high 16 bits. */ - result <<= 16; + if ( number > 0x7FFFL ) + goto Exit; - /* Place the decimal part into the low 16 bits. */ - if ( num ) - result |= FT_DivFix( num, divider ); + result = number << 16; + } + } if ( sign ) result = -result; Exit: return result; - - Bad: - result = 0; - goto Exit; } @@ -288,8 +368,8 @@ static FT_Long cff_parse_num( FT_Byte** d ) { - return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 ) - : cff_parse_integer( d[0], d[1] ) ); + return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 ) + : cff_parse_integer( d[0], d[1] ); } @@ -297,64 +377,120 @@ static FT_Fixed cff_parse_fixed( FT_Byte** d ) { - return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 ) - : cff_parse_integer( d[0], d[1] ) << 16 ); + return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL ) + : cff_parse_integer( d[0], d[1] ) << 16; } + /* read a floating point number, either integer or real, */ - /* but return 1000 times the number read in. */ + /* but return `10^scaling' times the number read in */ + static FT_Fixed + cff_parse_fixed_scaled( FT_Byte** d, + FT_Long scaling ) + { + return **d == 30 ? cff_parse_real( d[0], d[1], scaling, NULL ) + : ( cff_parse_integer( d[0], d[1] ) * + power_tens[scaling] ) << 16; + } + + + /* read a floating point number, either integer or real, */ + /* and return it as precise as possible -- `scaling' returns */ + /* the scaling factor (as a power of 10) */ static FT_Fixed - cff_parse_fixed_thousand( FT_Byte** d ) + cff_parse_fixed_dynamic( FT_Byte** d, + FT_Long* scaling ) { - return **d == - 30 ? cff_parse_real ( d[0], d[1], 3 ) - : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 ); + FT_ASSERT( scaling ); + + if ( **d == 30 ) + return cff_parse_real( d[0], d[1], 0, scaling ); + else + { + FT_Long number; + FT_Int integer_length; + + + number = cff_parse_integer( d[0], d[1] ); + + if ( number > 0x7FFFL ) + { + for ( integer_length = 5; integer_length < 10; integer_length++ ) + if ( number < power_tens[integer_length] ) + break; + + if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL ) + { + *scaling = integer_length - 4; + return FT_DivFix( number, power_tens[integer_length - 4] ); + } + else + { + *scaling = integer_length - 5; + return FT_DivFix( number, power_tens[integer_length - 5] ); + } + } + else + { + *scaling = 0; + return number << 16; + } + } } + static FT_Error cff_parse_font_matrix( CFF_Parser parser ) { CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; FT_Matrix* matrix = &dict->font_matrix; FT_Vector* offset = &dict->font_offset; - FT_UShort* upm = &dict->units_per_em; + FT_ULong* upm = &dict->units_per_em; FT_Byte** data = parser->stack; - FT_Error error; - FT_Fixed temp; + FT_Error error = CFF_Err_Stack_Underflow; - error = CFF_Err_Stack_Underflow; - if ( parser->top >= parser->stack + 6 ) { - matrix->xx = cff_parse_fixed_thousand( data++ ); - matrix->yx = cff_parse_fixed_thousand( data++ ); - matrix->xy = cff_parse_fixed_thousand( data++ ); - matrix->yy = cff_parse_fixed_thousand( data++ ); - offset->x = cff_parse_fixed_thousand( data++ ); - offset->y = cff_parse_fixed_thousand( data ); + FT_Long scaling; - temp = FT_ABS( matrix->yy ); - *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) ); + error = CFF_Err_Ok; + + /* We expect a well-formed font matrix, this is, the matrix elements */ + /* `xx' and `yy' are of approximately the same magnitude. To avoid */ + /* loss of precision, we use the magnitude of element `xx' to scale */ + /* all other elements. The scaling factor is then contained in the */ + /* `units_per_em' value. */ - if ( temp != 0x10000L ) + matrix->xx = cff_parse_fixed_dynamic( data++, &scaling ); + + scaling = -scaling; + + if ( scaling < 0 || scaling > 9 ) { - matrix->xx = FT_DivFix( matrix->xx, temp ); - matrix->yx = FT_DivFix( matrix->yx, temp ); - matrix->xy = FT_DivFix( matrix->xy, temp ); - matrix->yy = FT_DivFix( matrix->yy, temp ); - offset->x = FT_DivFix( offset->x, temp ); - offset->y = FT_DivFix( offset->y, temp ); + /* Return default matrix in case of unlikely values. */ + matrix->xx = 0x10000L; + matrix->yx = 0; + matrix->yx = 0; + matrix->yy = 0x10000L; + offset->x = 0; + offset->y = 0; + *upm = 1; + + goto Exit; } - /* note that the offsets must be expressed in integer font units */ - offset->x >>= 16; - offset->y >>= 16; + matrix->yx = cff_parse_fixed_scaled( data++, scaling ); + matrix->xy = cff_parse_fixed_scaled( data++, scaling ); + matrix->yy = cff_parse_fixed_scaled( data++, scaling ); + offset->x = cff_parse_fixed_scaled( data++, scaling ); + offset->y = cff_parse_fixed_scaled( data, scaling ); - error = CFF_Err_Ok; + *upm = power_tens[scaling]; } + Exit: return error; } @@ -418,7 +554,12 @@ { dict->cid_registry = (FT_UInt)cff_parse_num ( data++ ); dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ ); - dict->cid_supplement = (FT_ULong)cff_parse_num( data ); + if ( **data == 30 ) + FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" )); + dict->cid_supplement = cff_parse_num( data ); + if ( dict->cid_supplement < 0 ) + FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n", + dict->cid_supplement )); error = CFF_Err_Ok; } @@ -439,6 +580,11 @@ #define CFF_FIELD_DELTA( code, name, max ) \ CFF_FIELD( code, name, cff_kind_delta ) +#define CFFCODE_TOPDICT 0x1000 +#define CFFCODE_PRIVATE 0x2000 + +#ifndef FT_CONFIG_OPTION_PIC + #define CFF_FIELD_CALLBACK( code, name ) \ { \ cff_kind_callback, \ @@ -470,9 +616,6 @@ FT_FIELD_OFFSET( num_ ## name ) \ }, -#define CFFCODE_TOPDICT 0x1000 -#define CFFCODE_PRIVATE 0x2000 - static const CFF_Field_Handler cff_field_handlers[] = { @@ -482,13 +625,99 @@ }; +#else /* FT_CONFIG_OPTION_PIC */ + + void FT_Destroy_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler* clazz) + { + FT_Memory memory = library->memory; + if ( clazz ) + FT_FREE( clazz ); + } + + FT_Error FT_Create_Class_cff_field_handlers(FT_Library library, CFF_Field_Handler** output_class) + { + CFF_Field_Handler* clazz; + FT_Error error; + FT_Memory memory = library->memory; + int i=0; + +#undef CFF_FIELD +#undef CFF_FIELD_DELTA +#undef CFF_FIELD_CALLBACK +#define CFF_FIELD_CALLBACK( code, name ) i++; +#define CFF_FIELD( code, name, kind ) i++; +#define CFF_FIELD_DELTA( code, name, max ) i++; + +#include "cfftoken.h" + i++;/*{ 0, 0, 0, 0, 0, 0, 0 }*/ + + if ( FT_ALLOC( clazz, sizeof(CFF_Field_Handler)*i ) ) + return error; + + i=0; +#undef CFF_FIELD +#undef CFF_FIELD_DELTA +#undef CFF_FIELD_CALLBACK + +#define CFF_FIELD_CALLBACK( code_, name_ ) \ + clazz[i].kind = cff_kind_callback; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = 0; \ + clazz[i].size = 0; \ + clazz[i].reader = cff_parse_ ## name_; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + i++; + +#undef CFF_FIELD +#define CFF_FIELD( code_, name_, kind_ ) \ + clazz[i].kind = kind_; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ + clazz[i].size = FT_FIELD_SIZE( name_ ); \ + clazz[i].reader = 0; \ + clazz[i].array_max = 0; \ + clazz[i].count_offset = 0; \ + i++; \ + +#undef CFF_FIELD_DELTA +#define CFF_FIELD_DELTA( code_, name_, max_ ) \ + clazz[i].kind = cff_kind_delta; \ + clazz[i].code = code_ | CFFCODE; \ + clazz[i].offset = FT_FIELD_OFFSET( name_ ); \ + clazz[i].size = FT_FIELD_SIZE_DELTA( name_ ); \ + clazz[i].reader = 0; \ + clazz[i].array_max = max_; \ + clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \ + i++; + +#include "cfftoken.h" + + clazz[i].kind = 0; + clazz[i].code = 0; + clazz[i].offset = 0; + clazz[i].size = 0; + clazz[i].reader = 0; + clazz[i].array_max = 0; + clazz[i].count_offset = 0; + + *output_class = clazz; + return FT_Err_Ok; + } + + +#endif /* FT_CONFIG_OPTION_PIC */ + + FT_LOCAL_DEF( FT_Error ) cff_parser_run( CFF_Parser parser, FT_Byte* start, FT_Byte* limit ) { - FT_Byte* p = start; - FT_Error error = CFF_Err_Ok; + FT_Byte* p = start; + FT_Error error = CFF_Err_Ok; + FT_Library library = parser->library; + FT_UNUSED(library); parser->top = parser->stack; @@ -558,7 +787,7 @@ } code = code | parser->object_code; - for ( field = cff_field_handlers; field->kind; field++ ) + for ( field = FT_CFF_FIELD_HANDLERS_GET; field->kind; field++ ) { if ( field->code == (FT_Int)code ) { @@ -585,7 +814,7 @@ goto Store_Number; case cff_kind_fixed_thousand: - val = cff_parse_fixed_thousand( parser->stack ); + val = cff_parse_fixed_scaled( parser->stack, 3 ); Store_Number: switch ( field->size ) diff --git a/src/freetype2/cff/cffparse.h b/src/freetype2/cff/cffparse.h index 8f3fa58..7e2c00a 100644 --- a/src/freetype2/cff/cffparse.h +++ b/src/freetype2/cff/cffparse.h @@ -36,6 +36,7 @@ FT_BEGIN_HEADER typedef struct CFF_ParserRec_ { + FT_Library library; FT_Byte* start; FT_Byte* limit; FT_Byte* cursor; @@ -52,7 +53,8 @@ FT_BEGIN_HEADER FT_LOCAL( void ) cff_parser_init( CFF_Parser parser, FT_UInt code, - void* object ); + void* object, + FT_Library library); FT_LOCAL( FT_Error ) cff_parser_run( CFF_Parser parser, @@ -60,6 +62,37 @@ FT_BEGIN_HEADER FT_Byte* limit ); + enum + { + cff_kind_none = 0, + cff_kind_num, + cff_kind_fixed, + cff_kind_fixed_thousand, + cff_kind_string, + cff_kind_bool, + cff_kind_delta, + cff_kind_callback, + + cff_kind_max /* do not remove */ + }; + + + /* now generate handlers for the most simple fields */ + typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser ); + + typedef struct CFF_Field_Handler_ + { + int kind; + int code; + FT_UInt offset; + FT_Byte size; + CFF_Field_Reader reader; + FT_UInt array_max; + FT_UInt count_offset; + + } CFF_Field_Handler; + + FT_END_HEADER diff --git a/src/freetype2/cff/cffpic.c b/src/freetype2/cff/cffpic.c new file mode 100644 index 0000000..568956d --- /dev/null +++ b/src/freetype2/cff/cffpic.c @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* cffpic.c */ +/* */ +/* The FreeType position independent code services for cff module. */ +/* */ +/* Copyright 2009 by */ +/* Oran Agra and Mickey Gabel. */ +/* */ +/* 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_INTERNAL_OBJECTS_H +#include "cffpic.h" + +#ifdef FT_CONFIG_OPTION_PIC + + /* forward declaration of PIC init functions from cffdrivr.c */ + FT_Error FT_Create_Class_cff_services( FT_Library, FT_ServiceDescRec**); + void FT_Destroy_Class_cff_services( FT_Library, FT_ServiceDescRec*); + void FT_Init_Class_cff_service_ps_info( FT_Library, FT_Service_PsInfoRec*); + void FT_Init_Class_cff_service_glyph_dict( FT_Library, FT_Service_GlyphDictRec*); + void FT_Init_Class_cff_service_ps_name( FT_Library, FT_Service_PsFontNameRec*); + void FT_Init_Class_cff_service_get_cmap_info( FT_Library, FT_Service_TTCMapsRec*); + void FT_Init_Class_cff_service_cid_info( FT_Library, FT_Service_CIDRec*); + + /* forward declaration of PIC init functions from cffparse.c */ + FT_Error FT_Create_Class_cff_field_handlers( FT_Library, CFF_Field_Handler**); + void FT_Destroy_Class_cff_field_handlers( FT_Library, CFF_Field_Handler*); + + /* forward declaration of PIC init functions from cffcmap.c */ + void FT_Init_Class_cff_cmap_encoding_class_rec( FT_Library, FT_CMap_ClassRec*); + void FT_Init_Class_cff_cmap_unicode_class_rec( FT_Library, FT_CMap_ClassRec*); + + void + cff_driver_class_pic_free( FT_Library library ) + { + FT_PIC_Container* pic_container = &library->pic_container; + FT_Memory memory = library->memory; + if ( pic_container->cff ) + { + CffModulePIC* container = (CffModulePIC*)pic_container->cff; + if(container->cff_services) + FT_Destroy_Class_cff_services(library, container->cff_services); + container->cff_services = NULL; + if(container->cff_field_handlers) + FT_Destroy_Class_cff_field_handlers(library, container->cff_field_handlers); + container->cff_field_handlers = NULL; + FT_FREE( container ); + pic_container->cff = NULL; + } + } + + FT_Error + cff_driver_class_pic_init( FT_Library library ) + { + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = FT_Err_Ok; + CffModulePIC* container; + FT_Memory memory = library->memory; + + /* allocate pointer, clear and set global container pointer */ + if ( FT_ALLOC ( container, sizeof ( *container ) ) ) + return error; + FT_MEM_SET( container, 0, sizeof(*container) ); + pic_container->cff = container; + + /* initialize pointer table - this is how the module usually expects this data */ + error = FT_Create_Class_cff_services(library, &container->cff_services); + if(error) + goto Exit; + error = FT_Create_Class_cff_field_handlers(library, &container->cff_field_handlers); + if(error) + goto Exit; + FT_Init_Class_cff_service_ps_info(library, &container->cff_service_ps_info); + FT_Init_Class_cff_service_glyph_dict(library, &container->cff_service_glyph_dict); + FT_Init_Class_cff_service_ps_name(library, &container->cff_service_ps_name); + FT_Init_Class_cff_service_get_cmap_info(library, &container->cff_service_get_cmap_info); + FT_Init_Class_cff_service_cid_info(library, &container->cff_service_cid_info); + FT_Init_Class_cff_cmap_encoding_class_rec(library, &container->cff_cmap_encoding_class_rec); + FT_Init_Class_cff_cmap_unicode_class_rec(library, &container->cff_cmap_unicode_class_rec); +Exit: + if(error) + cff_driver_class_pic_free(library); + return error; + } + +#endif /* FT_CONFIG_OPTION_PIC */ + + +/* END */ diff --git a/src/freetype2/cff/cffpic.h b/src/freetype2/cff/cffpic.h new file mode 100644 index 0000000..e29d068 --- /dev/null +++ b/src/freetype2/cff/cffpic.h @@ -0,0 +1,80 @@ +/***************************************************************************/ +/* */ +/* cffpic.h */ +/* */ +/* The FreeType position independent code services for cff module. */ +/* */ +/* Copyright 2009 by */ +/* Oran Agra and Mickey Gabel. */ +/* */ +/* 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 __CFFPIC_H__ +#define __CFFPIC_H__ + + +FT_BEGIN_HEADER + +#include FT_INTERNAL_PIC_H + +#ifndef FT_CONFIG_OPTION_PIC +#define FT_CFF_SERVICE_PS_INFO_GET cff_service_ps_info +#define FT_CFF_SERVICE_GLYPH_DICT_GET cff_service_glyph_dict +#define FT_CFF_SERVICE_PS_NAME_GET cff_service_ps_name +#define FT_CFF_SERVICE_GET_CMAP_INFO_GET cff_service_get_cmap_info +#define FT_CFF_SERVICE_CID_INFO_GET cff_service_cid_info +#define FT_CFF_SERVICES_GET cff_services +#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec +#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec +#define FT_CFF_FIELD_HANDLERS_GET cff_field_handlers + +#else /* FT_CONFIG_OPTION_PIC */ + +#include FT_SERVICE_GLYPH_DICT_H +#include "cffparse.h" +#include FT_SERVICE_POSTSCRIPT_INFO_H +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_TT_CMAP_H +#include FT_SERVICE_CID_H + + typedef struct CffModulePIC_ + { + FT_ServiceDescRec* cff_services; + CFF_Field_Handler* cff_field_handlers; + FT_Service_PsInfoRec cff_service_ps_info; + FT_Service_GlyphDictRec cff_service_glyph_dict; + FT_Service_PsFontNameRec cff_service_ps_name; + FT_Service_TTCMapsRec cff_service_get_cmap_info; + FT_Service_CIDRec cff_service_cid_info; + FT_CMap_ClassRec cff_cmap_encoding_class_rec; + FT_CMap_ClassRec cff_cmap_unicode_class_rec; + } CffModulePIC; + +#define GET_PIC(lib) ((CffModulePIC*)((lib)->pic_container.cff)) +#define FT_CFF_SERVICE_PS_INFO_GET (GET_PIC(library)->cff_service_ps_info) +#define FT_CFF_SERVICE_GLYPH_DICT_GET (GET_PIC(library)->cff_service_glyph_dict) +#define FT_CFF_SERVICE_PS_NAME_GET (GET_PIC(library)->cff_service_ps_name) +#define FT_CFF_SERVICE_GET_CMAP_INFO_GET (GET_PIC(library)->cff_service_get_cmap_info) +#define FT_CFF_SERVICE_CID_INFO_GET (GET_PIC(library)->cff_service_cid_info) +#define FT_CFF_SERVICES_GET (GET_PIC(library)->cff_services) +#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET (GET_PIC(library)->cff_cmap_encoding_class_rec) +#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET (GET_PIC(library)->cff_cmap_unicode_class_rec) +#define FT_CFF_FIELD_HANDLERS_GET (GET_PIC(library)->cff_field_handlers) + +#endif /* FT_CONFIG_OPTION_PIC */ + + /* */ + +FT_END_HEADER + +#endif /* __CFFPIC_H__ */ + + +/* END */ diff --git a/src/freetype2/cff/cfftypes.h b/src/freetype2/cff/cfftypes.h index 306e5aa..df92e9a 100644 --- a/src/freetype2/cff/cfftypes.h +++ b/src/freetype2/cff/cfftypes.h @@ -5,7 +5,7 @@ /* Basic OpenType/CFF type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -114,7 +114,7 @@ FT_BEGIN_HEADER FT_Int paint_type; FT_Int charstring_type; FT_Matrix font_matrix; - FT_UShort units_per_em; + FT_ULong units_per_em; /* temporarily used as scaling value also */ FT_Vector font_offset; FT_ULong unique_id; FT_BBox font_bbox; @@ -130,7 +130,7 @@ FT_BEGIN_HEADER /* these should only be used for the top-level font dictionary */ FT_UInt cid_registry; FT_UInt cid_ordering; - FT_ULong cid_supplement; + FT_Long cid_supplement; FT_Long cid_font_version; FT_Long cid_font_revision; @@ -259,6 +259,10 @@ FT_BEGIN_HEADER /* since version 2.3.0 */ PS_FontInfoRec* font_info; /* font info dictionary */ + /* since version 2.3.6 */ + FT_String* registry; + FT_String* ordering; + } CFF_FontRec, *CFF_Font; -- cgit v1.2.3