/**************************************************************************** * * t1load.c * * Type 1 font loader (body). * * Copyright (C) 1996-2023 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, * modified, and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify, or distribute * this file you indicate that you have read the license and * understand and accept it fully. * */ /************************************************************************** * * This is the new and improved Type 1 data loader for FreeType 2. The * old loader has several problems: it is slow, complex, difficult to * maintain, and contains incredible hacks to make it accept some * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of * the Type 1 fonts on my machine still aren't loaded correctly by it. * * This version is much simpler, much faster and also easier to read and * maintain by a great order of magnitude. The idea behind it is to * _not_ try to read the Type 1 token stream with a state machine (i.e. * a Postscript-like interpreter) but rather to perform simple pattern * matching. * * Indeed, nearly all data definitions follow a simple pattern like * * ... /Field <data> ... * * where <data> can be a number, a boolean, a string, or an array of * numbers. There are a few exceptions, namely the encoding, font name, * charstrings, and subrs; they are handled with a special pattern * matching routine. * * All other common cases are handled very simply. The matching rules * are defined in the file `t1tokens.h' through the use of several * macros calls PARSE_XXX. This file is included twice here; the first * time to generate parsing callback functions, the second time to * generate a table of keywords (with pointers to the associated * callback functions). * * The function `parse_dict' simply scans *linearly* a given dictionary * (either the top-level or private one) and calls the appropriate * callback when it encounters an immediate keyword. * * This is by far the fastest way one can find to parse and read all * data. * * This led to tremendous code size reduction. Note that later, the * glyph loader will also be _greatly_ simplified, and the automatic * hinter will replace the clumsy `t1hinter'. * */ #include <ft2build.h> #include <freetype/internal/ftdebug.h> #include FT_CONFIG_CONFIG_H #include <freetype/ftmm.h> #include <freetype/internal/t1types.h> #include <freetype/internal/ftcalc.h> #include <freetype/internal/fthash.h> #include "t1load.h" #include "t1errors.h" #ifdef FT_CONFIG_OPTION_INCREMENTAL #define IS_INCREMENTAL … #else #define IS_INCREMENTAL … #endif /************************************************************************** * * The macro FT_COMPONENT is used in trace mode. It is an implicit * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log * messages during execution. */ #undef FT_COMPONENT #define FT_COMPONENT … #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** MULTIPLE MASTERS SUPPORT *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ static FT_Error t1_allocate_blend( T1_Face face, FT_UInt num_designs, FT_UInt num_axis ) { … } FT_LOCAL_DEF( FT_Error ) T1_Get_Multi_Master( FT_Face face, /* T1_Face */ FT_Multi_Master* master ) { … } /************************************************************************** * * Given a normalized (blend) coordinate, figure out the design * coordinate appropriate for that value. */ static FT_Fixed mm_axis_unmap( PS_DesignMap axismap, FT_Fixed ncv ) { … } /************************************************************************** * * Given a vector of weights, one for each design, figure out the * normalized axis coordinates which gave rise to those weights. */ static void mm_weights_unmap( FT_Fixed* weights, FT_Fixed* axiscoords, FT_UInt axis_count ) { … } /************************************************************************** * * Just a wrapper around T1_Get_Multi_Master to support the different * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) T1_Get_MM_Var( FT_Face face, /* T1_Face */ FT_MM_Var* *master ) { … } static FT_Error t1_set_mm_blend( T1_Face face, FT_UInt num_coords, FT_Fixed* coords ) { … } FT_LOCAL_DEF( FT_Error ) T1_Set_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { … } FT_LOCAL_DEF( FT_Error ) T1_Get_MM_Blend( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { … } FT_LOCAL_DEF( FT_Error ) T1_Set_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt len, FT_Fixed* weightvector ) { … } FT_LOCAL_DEF( FT_Error ) T1_Get_MM_WeightVector( FT_Face face, /* T1_Face */ FT_UInt* len, FT_Fixed* weightvector ) { … } FT_LOCAL_DEF( FT_Error ) T1_Set_MM_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Long* coords ) { … } /* MM fonts don't have named instances, so only the design is reset */ FT_LOCAL_DEF( FT_Error ) T1_Reset_MM_Blend( FT_Face face, FT_UInt instance_index ) { … } /************************************************************************** * * Just a wrapper around T1_Set_MM_Design to support the different * arguments needed by the GX var distortable fonts. */ FT_LOCAL_DEF( FT_Error ) T1_Set_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { … } FT_LOCAL_DEF( FT_Error ) T1_Get_Var_Design( FT_Face face, /* T1_Face */ FT_UInt num_coords, FT_Fixed* coords ) { … } FT_LOCAL_DEF( void ) T1_Done_Blend( FT_Face face ) /* T1_Face */ { … } static void parse_blend_axis_types( FT_Face face, /* T1_Face */ void* loader_ ) { … } static void parse_blend_design_positions( FT_Face face, /* T1_Face */ void* loader_ ) { … } static void parse_blend_design_map( FT_Face face, /* T1_Face */ void* loader_ ) { … } static void parse_weight_vector( FT_Face face, /* T1_Face */ void* loader_ ) { … } /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ /* we're only interested in the number of array elements */ static void parse_buildchar( FT_Face face, /* T1_Face */ void* loader_ ) { … } #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** TYPE 1 SYMBOL PARSING *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ static FT_Error t1_load_keyword( T1_Face face, T1_Loader loader, const T1_Field field ) { … } static void parse_private( FT_Face face, void* loader_ ) { … } /* return 1 in case of success */ static int read_binary_data( T1_Parser parser, FT_ULong* size, FT_Byte** base, FT_Bool incremental ) { … } /* We now define the routines to handle the `/Encoding', `/Subrs', */ /* and `/CharStrings' dictionaries. */ static void t1_parse_font_matrix( FT_Face face, /* T1_Face */ void* loader_ ) { … } static void parse_encoding( FT_Face face, /* T1_Face */ void* loader_ ) { … } static void parse_subrs( FT_Face face, /* T1_Face */ void* loader_ ) { … } #define TABLE_EXTEND … static void parse_charstrings( FT_Face face, /* T1_Face */ void* loader_ ) { … } /************************************************************************** * * Define the token field static variables. This is a set of * T1_FieldRec variables. * */ static const T1_FieldRec t1_keywords[] = …; static FT_Error parse_dict( T1_Face face, T1_Loader loader, FT_Byte* base, FT_ULong size ) { … } static void t1_init_loader( T1_Loader loader, T1_Face face ) { … } static void t1_done_loader( T1_Loader loader ) { … } FT_LOCAL_DEF( FT_Error ) T1_Open_Face( T1_Face face ) { … } /* END */