diff options
Diffstat (limited to 'src/3rdparty/freetype/src/cff/cffobjs.c')
-rw-r--r-- | src/3rdparty/freetype/src/cff/cffobjs.c | 342 |
1 files changed, 221 insertions, 121 deletions
diff --git a/src/3rdparty/freetype/src/cff/cffobjs.c b/src/3rdparty/freetype/src/cff/cffobjs.c index bd56c4ba11..da3d0190fe 100644 --- a/src/3rdparty/freetype/src/cff/cffobjs.c +++ b/src/3rdparty/freetype/src/cff/cffobjs.c @@ -4,7 +4,7 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2014 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,6 +17,7 @@ #include <ft2build.h> + #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_CALC_H #include FT_INTERNAL_STREAM_H @@ -24,14 +25,15 @@ #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_SFNT_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include FT_CFF_DRIVER_H + #include "cffobjs.h" #include "cffload.h" #include "cffcmap.h" -#include "cfferrs.h" #include "cffpic.h" +#include "cfferrs.h" + /*************************************************************************/ /* */ @@ -58,7 +60,7 @@ { CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + PSHinter_Service pshinter = font->pshinter; FT_Module module; @@ -155,7 +157,7 @@ cff_size_init( FT_Size cffsize ) /* CFF_Size */ { CFF_Size size = (CFF_Size)cffsize; - FT_Error error = CFF_Err_Ok; + FT_Error error = FT_Err_Ok; PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); @@ -163,7 +165,7 @@ { CFF_Face face = (CFF_Face)cffsize->face; CFF_Font font = (CFF_Font)face->extra.data; - CFF_Internal internal; + CFF_Internal internal = NULL; PS_PrivateRec priv; FT_Memory memory = cffsize->face->memory; @@ -255,7 +257,7 @@ } } - return CFF_Err_Ok; + return FT_Err_Ok; } #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ @@ -327,7 +329,7 @@ } } - return CFF_Err_Ok; + return FT_Err_Ok; } @@ -349,7 +351,7 @@ { CFF_Face face = (CFF_Face)slot->face; CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + PSHinter_Service pshinter = font->pshinter; if ( pshinter ) @@ -369,7 +371,7 @@ } } - return CFF_Err_Ok; + return FT_Err_Ok; } @@ -395,6 +397,87 @@ } + /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */ + /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */ + /* have been seen in the wild. */ + + static void + remove_subset_prefix( FT_String* name ) + { + FT_Int32 idx = 0; + FT_Int32 length = (FT_Int32)strlen( name ) + 1; + FT_Bool continue_search = 1; + + + while ( continue_search ) + { + if ( length >= 7 && name[6] == '+' ) + { + for ( idx = 0; idx < 6; idx++ ) + { + /* ASCII uppercase letters */ + if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) + continue_search = 0; + } + + if ( continue_search ) + { + for ( idx = 7; idx < length; idx++ ) + name[idx - 7] = name[idx]; + length -= 7; + } + } + else + continue_search = 0; + } + } + + + /* Remove the style part from the family name (if present). */ + + static void + remove_style( FT_String* family_name, + const FT_String* style_name ) + { + FT_Int32 family_name_length, style_name_length; + + + family_name_length = (FT_Int32)strlen( family_name ); + style_name_length = (FT_Int32)strlen( style_name ); + + if ( family_name_length > style_name_length ) + { + FT_Int idx; + + + for ( idx = 1; idx <= style_name_length; ++idx ) + { + if ( family_name[family_name_length - idx] != + style_name[style_name_length - idx] ) + break; + } + + if ( idx > style_name_length ) + { + /* family_name ends with style_name; remove it */ + idx = family_name_length - style_name_length - 1; + + /* also remove special characters */ + /* between real family name and style */ + while ( idx > 0 && + ( family_name[idx] == '-' || + family_name[idx] == ' ' || + family_name[idx] == '_' || + family_name[idx] == '+' ) ) + --idx; + + if ( idx > 0 ) + family_name[idx + 1] = '\0'; + } + } + } + + FT_LOCAL_DEF( FT_Error ) cff_face_init( FT_Stream stream, FT_Face cffface, /* CFF_Face */ @@ -402,34 +485,31 @@ FT_Int num_params, FT_Parameter* params ) { - CFF_Face face = (CFF_Face)cffface; + CFF_Face face = (CFF_Face)cffface; FT_Error error; SFNT_Service sfnt; FT_Service_PsCMaps psnames; PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; - FT_Library library = cffface->driver->root.library; + FT_Library library = cffface->driver->root.library; -#if 0 - FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT ); - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES ); - FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER ); - - if ( !sfnt ) - goto Bad_Format; -#else sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) - goto Bad_Format; + { + FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); + error = FT_THROW( Missing_Module ); + goto Exit; + } FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, "pshinter" ); -#endif + + FT_TRACE2(( "CFF driver\n" )); /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) @@ -441,21 +521,14 @@ { if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ { - FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); - goto Bad_Format; + FT_TRACE2(( " not an OpenType/CFF font\n" )); + error = FT_THROW( Unknown_File_Format ); + goto Exit; } /* if we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) - return CFF_Err_Ok; - - /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ - if ( face_index > 0 ) - { - FT_ERROR(( "cff_face_init: invalid face index\n" )); - error = CFF_Err_Invalid_Argument; - goto Exit; - } + return FT_Err_Ok; sfnt_format = 1; @@ -467,7 +540,8 @@ pure_cff = 0; /* load font directory */ - error = sfnt->load_face( stream, face, 0, num_params, params ); + error = sfnt->load_face( stream, face, face_index, + num_params, params ); if ( error ) goto Exit; } @@ -477,10 +551,6 @@ error = sfnt->load_cmap( face, stream ); if ( error ) goto Exit; - - /* XXX: we don't load the GPOS table, as OpenType Layout */ - /* support will be added later to a layout library on top of */ - /* FreeType 2 */ } /* now load the CFF part of the file */ @@ -493,12 +563,12 @@ /* rewind to start of file; we are going to load a pure-CFF font */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; - error = CFF_Err_Ok; + error = FT_Err_Ok; } /* now load and parse the CFF table in the file */ { - CFF_Font cff; + CFF_Font cff = NULL; CFF_FontRecDict dict; FT_Memory memory = cffface->memory; FT_Int32 flags; @@ -514,7 +584,7 @@ goto Exit; cff->pshinter = pshinter; - cff->psnames = (void*)psnames; + cff->psnames = psnames; cffface->face_index = face_index; @@ -534,10 +604,29 @@ " cannot open CFF & CEF fonts\n" " " " without the `PSNames' module\n" )); - goto Bad_Format; + error = FT_THROW( Missing_Module ); + goto Exit; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_UInt idx; + FT_String* s; + + + FT_TRACE4(( "SIDs\n" )); + + /* dump string index, including default strings for convenience */ + for ( idx = 0; idx < cff->num_strings + 390; idx++ ) + { + s = cff_index_get_sid_string( cff, idx ); + if ( s ) + FT_TRACE4((" %5d %s\n", idx, s )); + } } +#endif /* FT_DEBUG_LEVEL_TRACE */ - if ( !dict->units_per_em ) + if ( !dict->has_font_matrix ) dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; /* Normalize the font matrix so that `matrix->xx' is 1; the */ @@ -582,26 +671,32 @@ FT_Fixed temp; - if ( sub->units_per_em ) + if ( sub->has_font_matrix ) { 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 ); + /* if we have a top-level matrix, */ + /* concatenate the subfont matrix */ + + if ( top->has_font_matrix ) + { + if ( top->units_per_em > 1 && sub->units_per_em > 1 ) + scaling = FT_MIN( top->units_per_em, sub->units_per_em ); + 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 { @@ -620,16 +715,6 @@ { *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 ); @@ -652,7 +737,7 @@ /* compute number of glyphs */ if ( dict->cid_registry != 0xFFFFU ) - cffface->num_glyphs = cff->charset.max_cid; + cffface->num_glyphs = cff->charset.max_cid + 1; else cffface->num_glyphs = cff->charstrings_index.count; @@ -678,24 +763,22 @@ (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ - cffface->family_name = cff_index_get_name( &cff->name_index, - face_index ); - + cffface->family_name = cff_index_get_name( cff, face_index ); if ( cffface->family_name ) { - char* full = cff_index_get_sid_string( &cff->string_index, - dict->full_name, - psnames ); + char* full = cff_index_get_sid_string( cff, + dict->full_name ); char* fullp = full; char* family = cffface->family_name; - char* family_name = 0; + char* family_name = NULL; + + remove_subset_prefix( cffface->family_name ); if ( dict->family_name ) { - family_name = cff_index_get_sid_string( &cff->string_index, - dict->family_name, - psnames); + family_name = cff_index_get_sid_string( cff, + dict->family_name ); if ( family_name ) family = family_name; } @@ -735,26 +818,24 @@ /* case, the remaining string in `fullp' will be used as */ /* the style name. */ style_name = cff_strcpy( memory, fullp ); + + /* remove the style part from the family name (if present) */ + remove_style( cffface->family_name, style_name ); } break; } - - if ( family_name ) - FT_FREE( family_name ); - FT_FREE( full ); } } else { char *cid_font_name = - cff_index_get_sid_string( &cff->string_index, - dict->cid_font_name, - psnames ); + cff_index_get_sid_string( cff, + dict->cid_font_name ); /* do we have a `/FontName' for a CID-keyed font? */ if ( cid_font_name ) - cffface->family_name = cid_font_name; + cffface->family_name = cff_strcpy( memory, cid_font_name ); } if ( style_name ) @@ -767,25 +848,25 @@ /* */ /* Compute face flags. */ /* */ - flags = (FT_UInt32)( FT_FACE_FLAG_SCALABLE | /* scalable outlines */ - FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ - FT_FACE_FLAG_HINTER ); /* has native hinter */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ + FT_FACE_FLAG_HINTER; /* has native hinter */ if ( sfnt_format ) - flags |= (FT_UInt32)FT_FACE_FLAG_SFNT; + flags |= FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) - flags |= (FT_UInt32)FT_FACE_FLAG_FIXED_WIDTH; + flags |= 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_UInt32)FT_FACE_FLAG_KERNING; + flags |= FT_FACE_FLAG_KERNING; #endif - cffface->face_flags = flags; + cffface->face_flags |= flags; /*******************************************************************/ /* */ @@ -797,16 +878,14 @@ flags |= FT_STYLE_FLAG_ITALIC; { - char *weight = cff_index_get_sid_string( &cff->string_index, - dict->weight, - psnames ); + char *weight = cff_index_get_sid_string( cff, + dict->weight ); if ( weight ) if ( !ft_strcmp( weight, "Bold" ) || !ft_strcmp( weight, "Black" ) ) flags |= FT_STYLE_FLAG_BOLD; - FT_FREE( weight ); } /* double check */ @@ -849,13 +928,14 @@ { cmap = cffface->charmaps[nn]; - /* Windows Unicode (3,1)? */ - if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) + /* Windows Unicode? */ + if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && + cmap->encoding_id == TT_MS_ID_UNICODE_CS ) goto Skip_Unicode; - /* Deprecated Unicode platform id? */ - if ( cmap->platform_id == 0 ) - goto Skip_Unicode; /* Standard Unicode (deprecated) */ + /* Apple Unicode platform id? */ + if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) + goto Skip_Unicode; /* Apple Unicode */ } /* since CID-keyed fonts don't contain glyph names, we can't */ @@ -865,13 +945,18 @@ /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; - cmaprec.platform_id = 3; - cmaprec.encoding_id = 1; + cmaprec.platform_id = TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt)cffface->num_charmaps; - FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL ); + error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, + &cmaprec, NULL ); + if ( error && + FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) + goto Exit; + error = FT_Err_Ok; /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) @@ -884,38 +969,34 @@ cmaprec.face = cffface; - cmaprec.platform_id = 7; /* Adobe platform id */ + cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ if ( encoding->offset == 0 ) { cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; - clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + clazz = &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 = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; } else { cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; - clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; + clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; } - FT_CMap_New( clazz, NULL, &cmaprec, NULL ); + error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } } Exit: return error; - - Bad_Format: - error = CFF_Err_Unknown_File_Format; - goto Exit; } @@ -950,16 +1031,35 @@ FT_LOCAL_DEF( FT_Error ) - cff_driver_init( FT_Module module ) + cff_driver_init( FT_Module module ) /* CFF_Driver */ { - FT_UNUSED( module ); + CFF_Driver driver = (CFF_Driver)module; + + + /* set default property values, cf. `ftcffdrv.h' */ +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + driver->hinting_engine = FT_CFF_HINTING_FREETYPE; +#else + driver->hinting_engine = FT_CFF_HINTING_ADOBE; +#endif + + driver->no_stem_darkening = FALSE; + + driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; + driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; + driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; + driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; + driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; + driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; + driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; + driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; - return CFF_Err_Ok; + return FT_Err_Ok; } FT_LOCAL_DEF( void ) - cff_driver_done( FT_Module module ) + cff_driver_done( FT_Module module ) /* CFF_Driver */ { FT_UNUSED( module ); } |