/**************************************************************************** * * psobjs.c * * Auxiliary functions for PostScript fonts (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. * */ #include <freetype/internal/psaux.h> #include <freetype/internal/ftdebug.h> #include <freetype/internal/ftcalc.h> #include <freetype/ftdriver.h> #include "psobjs.h" #include "psconv.h" #include "psauxerr.h" #include "psauxmod.h" /************************************************************************** * * 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 … /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** PS_TABLE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * @Function: * ps_table_new * * @Description: * Initializes a PS_Table. * * @InOut: * table :: * The address of the target table. * * @Input: * count :: * The table size = the maximum number of elements. * * memory :: * The memory object to use for all subsequent * reallocations. * * @Return: * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) ps_table_new( PS_Table table, FT_Int count, FT_Memory memory ) { … } static FT_Error ps_table_realloc( PS_Table table, FT_Offset new_size ) { … } /************************************************************************** * * @Function: * ps_table_add * * @Description: * Adds an object to a PS_Table, possibly growing its memory block. * * @InOut: * table :: * The target table. * * @Input: * idx :: * The index of the object in the table. * * object :: * The address of the object to copy in memory. * * length :: * The length in bytes of the source object. * * @Return: * FreeType error code. 0 means success. An error is returned if a * reallocation fails. */ FT_LOCAL_DEF( FT_Error ) ps_table_add( PS_Table table, FT_Int idx, const void* object, FT_UInt length ) { … } /************************************************************************** * * @Function: * ps_table_done * * @Description: * Finalizes a PS_TableRec (i.e., reallocate it to its current * cursor). * * @InOut: * table :: * The target table. */ FT_LOCAL_DEF( void ) ps_table_done( PS_Table table ) { … } FT_LOCAL_DEF( void ) ps_table_release( PS_Table table ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** T1 PARSER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /* first character must be already part of the comment */ static void skip_comment( FT_Byte* *acur, FT_Byte* limit ) { … } static void skip_spaces( FT_Byte* *acur, FT_Byte* limit ) { … } #define IS_OCTAL_DIGIT( c ) … /* first character must be `('; */ /* *acur is positioned at the character after the closing `)' */ static FT_Error skip_literal_string( FT_Byte* *acur, FT_Byte* limit ) { … } /* first character must be `<' */ static FT_Error skip_string( FT_Byte* *acur, FT_Byte* limit ) { … } /* first character must be the opening brace that */ /* starts the procedure */ /* NB: [ and ] need not match: */ /* `/foo {[} def' is a valid PostScript fragment, */ /* even within a Type1 font */ static FT_Error skip_procedure( FT_Byte* *acur, FT_Byte* limit ) { … } /************************************************************************ * * All exported parsing routines handle leading whitespace and stop at * the first character which isn't part of the just handled token. * */ FT_LOCAL_DEF( void ) ps_parser_skip_PS_token( PS_Parser parser ) { … } FT_LOCAL_DEF( void ) ps_parser_skip_spaces( PS_Parser parser ) { … } /* `token' here means either something between balanced delimiters */ /* or the next token; the delimiters are not removed. */ FT_LOCAL_DEF( void ) ps_parser_to_token( PS_Parser parser, T1_Token token ) { … } /* NB: `tokens' can be NULL if we only want to count */ /* the number of array elements */ FT_LOCAL_DEF( void ) ps_parser_to_token_array( PS_Parser parser, T1_Token tokens, FT_UInt max_tokens, FT_Int* pnum_tokens ) { … } /* first character must be a delimiter or a part of a number */ /* NB: `coords' can be NULL if we just want to skip the */ /* array; in this case we ignore `max_coords' */ static FT_Int ps_tocoordarray( FT_Byte* *acur, FT_Byte* limit, FT_Int max_coords, FT_Short* coords ) { … } /* first character must be a delimiter or a part of a number */ /* NB: `values' can be NULL if we just want to skip the */ /* array; in this case we ignore `max_values' */ /* */ /* return number of successfully parsed values */ static FT_Int ps_tofixedarray( FT_Byte* *acur, FT_Byte* limit, FT_Int max_values, FT_Fixed* values, FT_Int power_ten ) { … } #if 0 static FT_String* ps_tostring( FT_Byte** cursor, FT_Byte* limit, FT_Memory memory ) { FT_Byte* cur = *cursor; FT_UInt len = 0; FT_Int count; FT_String* result; FT_Error error; /* XXX: some stupid fonts have a `Notice' or `Copyright' string */ /* that simply doesn't begin with an opening parenthesis, even */ /* though they have a closing one! E.g. "amuncial.pfb" */ /* */ /* We must deal with these ill-fated cases there. Note that */ /* these fonts didn't work with the old Type 1 driver as the */ /* notice/copyright was not recognized as a valid string token */ /* and made the old token parser commit errors. */ while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) ) cur++; if ( cur + 1 >= limit ) return 0; if ( *cur == '(' ) cur++; /* skip the opening parenthesis, if there is one */ *cursor = cur; count = 0; /* then, count its length */ for ( ; cur < limit; cur++ ) { if ( *cur == '(' ) count++; else if ( *cur == ')' ) { count--; if ( count < 0 ) break; } } len = (FT_UInt)( cur - *cursor ); if ( cur >= limit || FT_QALLOC( result, len + 1 ) ) return 0; /* now copy the string */ FT_MEM_COPY( result, *cursor, len ); result[len] = '\0'; *cursor = cur; return result; } #endif /* 0 */ static int ps_tobool( FT_Byte* *acur, FT_Byte* limit ) { … } /* load a simple field (i.e. non-table) into the current list of objects */ FT_LOCAL_DEF( FT_Error ) ps_parser_load_field( PS_Parser parser, const T1_Field field, void** objects, FT_UInt max_objects, FT_ULong* pflags ) { … } #define T1_MAX_TABLE_ELEMENTS … FT_LOCAL_DEF( FT_Error ) ps_parser_load_field_table( PS_Parser parser, const T1_Field field, void** objects, FT_UInt max_objects, FT_ULong* pflags ) { … } FT_LOCAL_DEF( FT_Long ) ps_parser_to_int( PS_Parser parser ) { … } /* first character must be `<' if `delimiters' is non-zero */ FT_LOCAL_DEF( FT_Error ) ps_parser_to_bytes( PS_Parser parser, FT_Byte* bytes, FT_Offset max_bytes, FT_ULong* pnum_bytes, FT_Bool delimiters ) { … } FT_LOCAL_DEF( FT_Fixed ) ps_parser_to_fixed( PS_Parser parser, FT_Int power_ten ) { … } FT_LOCAL_DEF( FT_Int ) ps_parser_to_coord_array( PS_Parser parser, FT_Int max_coords, FT_Short* coords ) { … } FT_LOCAL_DEF( FT_Int ) ps_parser_to_fixed_array( PS_Parser parser, FT_Int max_values, FT_Fixed* values, FT_Int power_ten ) { … } #if 0 FT_LOCAL_DEF( FT_String* ) T1_ToString( PS_Parser parser ) { return ps_tostring( &parser->cursor, parser->limit, parser->memory ); } FT_LOCAL_DEF( FT_Bool ) T1_ToBool( PS_Parser parser ) { return ps_tobool( &parser->cursor, parser->limit ); } #endif /* 0 */ FT_LOCAL_DEF( void ) ps_parser_init( PS_Parser parser, FT_Byte* base, FT_Byte* limit, FT_Memory memory ) { … } FT_LOCAL_DEF( void ) ps_parser_done( PS_Parser parser ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** T1 BUILDER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * @Function: * t1_builder_init * * @Description: * Initializes a given glyph builder. * * @InOut: * builder :: * A pointer to the glyph builder to initialize. * * @Input: * face :: * The current face object. * * size :: * The current size object. * * glyph :: * The current glyph object. * * hinting :: * Whether hinting should be applied. */ FT_LOCAL_DEF( void ) t1_builder_init( T1_Builder builder, FT_Face face, FT_Size size, FT_GlyphSlot glyph, FT_Bool hinting ) { … } /************************************************************************** * * @Function: * t1_builder_done * * @Description: * Finalizes a given glyph builder. Its contents can still be used * after the call, but the function saves important information * within the corresponding glyph slot. * * @Input: * builder :: * A pointer to the glyph builder to finalize. */ FT_LOCAL_DEF( void ) t1_builder_done( T1_Builder builder ) { … } /* check that there is enough space for `count' more points */ FT_LOCAL_DEF( FT_Error ) t1_builder_check_points( T1_Builder builder, FT_Int count ) { … } /* add a new point, do not check space */ FT_LOCAL_DEF( void ) t1_builder_add_point( T1_Builder builder, FT_Pos x, FT_Pos y, FT_Byte flag ) { … } /* check space for a new on-curve point, then add it */ FT_LOCAL_DEF( FT_Error ) t1_builder_add_point1( T1_Builder builder, FT_Pos x, FT_Pos y ) { … } /* check space for a new contour, then add it */ FT_LOCAL_DEF( FT_Error ) t1_builder_add_contour( T1_Builder builder ) { … } /* if a path was begun, add its first on-curve point */ FT_LOCAL_DEF( FT_Error ) t1_builder_start_point( T1_Builder builder, FT_Pos x, FT_Pos y ) { … } /* close the current contour */ FT_LOCAL_DEF( void ) t1_builder_close_contour( T1_Builder builder ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** CFF BUILDER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * @Function: * cff_builder_init * * @Description: * Initializes a given glyph builder. * * @InOut: * builder :: * A pointer to the glyph builder to initialize. * * @Input: * face :: * The current face object. * * size :: * The current size object. * * glyph :: * The current glyph object. * * hinting :: * Whether hinting is active. */ FT_LOCAL_DEF( void ) cff_builder_init( CFF_Builder* builder, TT_Face face, CFF_Size size, CFF_GlyphSlot glyph, FT_Bool hinting ) { … } /************************************************************************** * * @Function: * cff_builder_done * * @Description: * Finalizes a given glyph builder. Its contents can still be used * after the call, but the function saves important information * within the corresponding glyph slot. * * @Input: * builder :: * A pointer to the glyph builder to finalize. */ FT_LOCAL_DEF( void ) cff_builder_done( CFF_Builder* builder ) { … } /* check that there is enough space for `count' more points */ FT_LOCAL_DEF( FT_Error ) cff_check_points( CFF_Builder* builder, FT_Int count ) { … } /* add a new point, do not check space */ FT_LOCAL_DEF( void ) cff_builder_add_point( CFF_Builder* builder, FT_Pos x, FT_Pos y, FT_Byte flag ) { … } /* check space for a new on-curve point, then add it */ FT_LOCAL_DEF( FT_Error ) cff_builder_add_point1( CFF_Builder* builder, FT_Pos x, FT_Pos y ) { … } /* check space for a new contour, then add it */ FT_LOCAL_DEF( FT_Error ) cff_builder_add_contour( CFF_Builder* builder ) { … } /* if a path was begun, add its first on-curve point */ FT_LOCAL_DEF( FT_Error ) cff_builder_start_point( CFF_Builder* builder, FT_Pos x, FT_Pos y ) { … } /* close the current contour */ FT_LOCAL_DEF( void ) cff_builder_close_contour( CFF_Builder* builder ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** PS BUILDER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * @Function: * ps_builder_init * * @Description: * Initializes a given glyph builder. * * @InOut: * builder :: * A pointer to the glyph builder to initialize. * * @Input: * face :: * The current face object. * * size :: * The current size object. * * glyph :: * The current glyph object. * * hinting :: * Whether hinting should be applied. */ FT_LOCAL_DEF( void ) ps_builder_init( PS_Builder* ps_builder, void* builder, FT_Bool is_t1 ) { … } /************************************************************************** * * @Function: * ps_builder_done * * @Description: * Finalizes a given glyph builder. Its contents can still be used * after the call, but the function saves important information * within the corresponding glyph slot. * * @Input: * builder :: * A pointer to the glyph builder to finalize. */ FT_LOCAL_DEF( void ) ps_builder_done( PS_Builder* builder ) { … } /* check that there is enough space for `count' more points */ FT_LOCAL_DEF( FT_Error ) ps_builder_check_points( PS_Builder* builder, FT_Int count ) { … } /* add a new point, do not check space */ FT_LOCAL_DEF( void ) ps_builder_add_point( PS_Builder* builder, FT_Pos x, FT_Pos y, FT_Byte flag ) { … } /* check space for a new on-curve point, then add it */ FT_LOCAL_DEF( FT_Error ) ps_builder_add_point1( PS_Builder* builder, FT_Pos x, FT_Pos y ) { … } /* check space for a new contour, then add it */ FT_LOCAL_DEF( FT_Error ) ps_builder_add_contour( PS_Builder* builder ) { … } /* if a path was begun, add its first on-curve point */ FT_LOCAL_DEF( FT_Error ) ps_builder_start_point( PS_Builder* builder, FT_Pos x, FT_Pos y ) { … } /* close the current contour */ FT_LOCAL_DEF( void ) ps_builder_close_contour( PS_Builder* builder ) { … } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** OTHER *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /************************************************************************** * * @Function: * ps_decoder_init * * @Description: * Creates a wrapper decoder for use in the combined * Type 1 / CFF interpreter. * * @InOut: * ps_decoder :: * A pointer to the decoder to initialize. * * @Input: * decoder :: * A pointer to the original decoder. * * is_t1 :: * Flag indicating Type 1 or CFF */ FT_LOCAL_DEF( void ) ps_decoder_init( PS_Decoder* ps_decoder, void* decoder, FT_Bool is_t1 ) { … } /* Synthesize a SubFont object for Type 1 fonts, for use in the */ /* new interpreter to access Private dict data. */ FT_LOCAL_DEF( void ) t1_make_subfont( FT_Face face, PS_Private priv, CFF_SubFont subfont ) { … } FT_LOCAL_DEF( void ) t1_decrypt( FT_Byte* buffer, FT_Offset length, FT_UShort seed ) { … } FT_LOCAL_DEF( FT_UInt32 ) cff_random( FT_UInt32 r ) { … } /* END */