From eba54c28dc97ebcfeb51078025c3c7d996410aa4 Mon Sep 17 00:00:00 2001 From: Ewald Hew Date: Sun, 24 Sep 2017 22:49:56 +0200 Subject: [PATCH] Add objects for new interpreter. Introduce `PS_Decoder' and `PS_Builder' which include all fields from either Type 1 or CFF decoders/builders. * include/freetype/internal/psaux.h (PS_Builder, PS_Decoder): New structs. * src/psaux/psobjs.c, src/psaux/psobjs.h: Add `PS_Builder' functions. * src/psaux/psdecode.c, src/psaux/psdecode.h: New files to hold `PS_Decoder' initialization functions. * src/psaux/psaux.c, src/psaux/Jamfile (_sources), src/psaux/rules.mk (PSAUX_DRV_SRC): Updated. --- ChangeLog | 19 +++ include/freetype/internal/psaux.h | 198 ++++++++++++++++++++++++ src/psaux/Jamfile | 2 + src/psaux/psaux.c | 1 + src/psaux/psdecode.c | 57 +++++++ src/psaux/psdecode.h | 13 ++ src/psaux/psobjs.c | 244 ++++++++++++++++++++++++++++++ src/psaux/psobjs.h | 45 ++++++ src/psaux/rules.mk | 1 + 9 files changed, 580 insertions(+) create mode 100644 src/psaux/psdecode.c create mode 100644 src/psaux/psdecode.h diff --git a/ChangeLog b/ChangeLog index 6a94c5577..e8ba1e12c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2017-09-24 Ewald Hew + + [psaux] Add objects for new interpreter. + + Introduce `PS_Decoder' and `PS_Builder' which include all fields + from either Type 1 or CFF decoders/builders. + + * include/freetype/internal/psaux.h (PS_Builder, PS_Decoder): New + structs. + + * src/psaux/psobjs.c, src/psaux/psobjs.h: Add `PS_Builder' + functions. + + * src/psaux/psdecode.c, src/psaux/psdecode.h: New files to hold + `PS_Decoder' initialization functions. + + * src/psaux/psaux.c, src/psaux/Jamfile (_sources), + src/psaux/rules.mk (PSAUX_DRV_SRC): Updated. + 2017-09-24 Ewald Hew [psaux] Rename files. diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index 258009be5..43ea776fa 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -443,6 +443,204 @@ FT_BEGIN_HEADER } PS_ParserRec; + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct PS_Builder_ PS_Builder; + typedef const struct PS_Builder_FuncsRec_* PS_Builder_Funcs; + + typedef struct PS_Builder_FuncsRec_ + { + void + (*init)( PS_Builder builder, + FT_Face face, + FT_Size size, + FT_GlyphSlot slot, + FT_Bool hinting ); + + void + (*done)( PS_Builder builder ); + + } PS_Builder_FuncsRec; + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: XXX */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* pos_x :: The horizontal translation (if composite glyph). */ + /* */ + /* pos_y :: The vertical translation (if composite glyph). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* bbox :: Unused. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: If this flag is not set, no points are loaded. */ + /* */ + /* no_recurse :: Set but not used. */ + /* */ + /* metrics_only :: A boolean indicating that we only want to compute */ + /* the metrics of a given glyph, not load all of its */ + /* points. */ + /* */ + /* funcs :: An array of function pointers for the builder. */ + /* */ + struct PS_Builder_ + { + FT_Memory memory; + TT_Face face; + CFF_GlyphSlot glyph; + FT_GlyphLoader loader; + FT_Outline* base; + FT_Outline* current; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + FT_Bool no_recurse; + + FT_Bool metrics_only; + + void* hints_funcs; /* hinter-specific */ + void* hints_globals; /* hinter-specific */ + + PS_Builder_FuncsRec funcs; + + }; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS DECODER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#define PS_MAX_OPERANDS 48 +#define PS_MAX_SUBRS_CALLS 16 /* maximum subroutine nesting; */ + /* only 10 are allowed but there exist */ + /* fonts like `HiraKakuProN-W3.ttf' */ + /* (Hiragino Kaku Gothic ProN W3; */ + /* 8.2d6e1; 2014-12-19) that exceed */ + /* this limit */ + + /* execution context charstring zone */ + + typedef struct PS_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } PS_Decoder_Zone; + + + typedef FT_Error + (*PS_Decoder_Get_Glyph_Callback)( TT_Face face, + FT_UInt glyph_index, + FT_Byte** pointer, + FT_ULong* length ); + + typedef void + (*PS_Decoder_Free_Glyph_Callback)( TT_Face face, + FT_Byte** pointer, + FT_ULong length ); + + typedef struct PS_Decoder_ + { + PS_Builder builder; + + FT_Fixed stack[PS_MAX_OPERANDS + 1]; + FT_Fixed* top; + + PS_Decoder_Zone zones[PS_MAX_SUBRS_CALLS + 1]; + PS_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + CFF_Font cff; + CFF_SubFont current_subfont; /* for current glyph_index */ + + FT_Pos glyph_width; + FT_Pos nominal_width; + + FT_Bool read_width; + FT_Bool width_only; + FT_Int num_hints; + + FT_UInt num_locals; + FT_UInt num_globals; + + FT_Int locals_bias; + FT_Int globals_bias; + + FT_Byte** locals; + FT_Byte** globals; + + FT_Byte** glyph_names; /* for pure CFF fonts only */ + FT_UInt num_glyphs; /* number of glyphs in font */ + + FT_Render_Mode hint_mode; + + FT_Bool seac; + + PS_Decoder_Get_Glyph_Callback get_glyph_callback; + PS_Decoder_Free_Glyph_Callback free_glyph_callback; + + /* Type 1 stuff */ + FT_Service_PsCMaps psnames; /* for seac */ + + FT_Int lenIV; /* internal for sub routine calls */ + FT_UInt* locals_len; /* array of subrs length (optional) */ + FT_Hash locals_hash; /* used if `num_subrs' was massaged */ + + FT_Matrix font_matrix; + FT_Vector font_offset; + + PS_Blend blend; /* for multiple master support */ + + FT_Long* buildchar; + FT_UInt len_buildchar; + + } PS_Decoder; + + /*************************************************************************/ /*************************************************************************/ /***** *****/ diff --git a/src/psaux/Jamfile b/src/psaux/Jamfile index 392acabfd..ab861e656 100644 --- a/src/psaux/Jamfile +++ b/src/psaux/Jamfile @@ -22,6 +22,8 @@ SubDir FT2_TOP $(FT2_SRC_DIR) psaux ; psobjs t1cmap t1decode + cffdecode + psdecode psarrst psblues pserror diff --git a/src/psaux/psaux.c b/src/psaux/psaux.c index e30c9b084..8c9e63316 100644 --- a/src/psaux/psaux.c +++ b/src/psaux/psaux.c @@ -26,6 +26,7 @@ #include "t1cmap.c" #include "t1decode.c" #include "cffdecode.c" +#include "psdecode.c" #include "psarrst.c" #include "psblues.c" diff --git a/src/psaux/psdecode.c b/src/psaux/psdecode.c new file mode 100644 index 000000000..700342582 --- /dev/null +++ b/src/psaux/psdecode.c @@ -0,0 +1,57 @@ + + +#include +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_CFF_TABLE_LOAD_H + +#include "psdecode.h" +#include "psobjs.h" + +#include "psauxerr.h" + + + /*************************************************************************/ + /* */ + /* */ + /* ps_decoder_init */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + /* hinting :: Whether hinting is active. */ + /* */ + /* hint_mode :: The hinting mode. */ + /* */ + FT_LOCAL_DEF( void ) + ps_decoder_init( PS_Decoder* decoder, + TT_Face face, + FT_Size size, + CFF_GlyphSlot slot, + FT_Byte** glyph_names, + PS_Blend blend, + FT_Bool hinting, + FT_Render_Mode hint_mode, + PS_Decoder_Get_Glyph_Callback get_callback, + PS_Decoder_Free_Glyph_Callback free_callback ) + { + } + + + /* this function is used to select the subfont */ + /* and the locals subrs array */ + FT_LOCAL_DEF( FT_Error ) + ps_decoder_prepare( PS_Decoder* decoder, + FT_Size size, + FT_UInt glyph_index ) + { + } diff --git a/src/psaux/psdecode.h b/src/psaux/psdecode.h new file mode 100644 index 000000000..2a530656e --- /dev/null +++ b/src/psaux/psdecode.h @@ -0,0 +1,13 @@ +#ifndef PSDECODE_H_ +#define PSDECODE_H_ + + +#include +#include FT_INTERNAL_POSTSCRIPT_AUX_H + +#include "cffdecode.h" +#include "t1decode.h" + + + +#endif diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index 92691db6c..815bca3c2 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -2023,6 +2023,250 @@ } + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* ps_builder_init */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* 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* builder, + TT_Face face, + FT_Size size, + CFF_GlyphSlot glyph, + FT_Bool hinting ) + { + } + + + /*************************************************************************/ + /* */ + /* */ + /* ps_builder_done */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + FT_LOCAL_DEF( void ) + ps_builder_done( PS_Builder* builder ) + { + CFF_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /* 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 ) + { + return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); + } + + + /* 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 ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + +#ifdef CFF_CONFIG_OPTION_OLD_ENGINE + CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); + + + if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) + { + point->x = x >> 16; + point->y = y >> 16; + } + else +#endif +#ifdef T1_CONFIG_OPTION_OLD_ENGINE + if ( builder->face->is_t1 ) + { + point->x = FIXED_TO_INT( x ); + point->y = FIXED_TO_INT( y ); + } + else +#endif + { + /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ + point->x = x >> 10; + point->y = y >> 10; + } + *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); + } + outline->n_points++; + } + + + /* 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 ) + { + FT_Error error; + + + error = ps_builder_check_points( builder, 1 ); + if ( !error ) + ps_builder_add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + FT_LOCAL_DEF( FT_Error ) + ps_builder_add_contour( PS_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + /* this might happen in invalid fonts */ + if ( !outline ) + { + FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" )); + return FT_THROW( Invalid_File_Format ); + } + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + + outline->n_contours++; + } + + return error; + } + + + /* 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 ) + { + FT_Error error = FT_Err_Ok; + + + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + builder->path_begun = 1; + error = ps_builder_add_contour( builder ); + if ( !error ) + error = ps_builder_add_point1( builder, x, y ); + } + + return error; + } + + + /* close the current contour */ + FT_LOCAL_DEF( void ) + ps_builder_close_contour( PS_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Int first; + + + if ( !outline ) + return; + + first = outline->n_contours <= 1 + ? 0 : outline->contours[outline->n_contours - 2] + 1; + + /* in malformed fonts it can happen that a contour was started */ + /* but no points were added */ + if ( outline->n_contours && first == outline->n_points ) + { + outline->n_contours--; + return; + } + + /* We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + 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; + + + /* `delete' last point only if it coincides with the first */ + /* point and it is not a control point (which can happen). */ + if ( p1->x == p2->x && p1->y == p2->y ) + if ( *control == FT_CURVE_TAG_ON ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + { + /* Don't add contours only consisting of one point, i.e., */ + /* check whether the first and the last point is 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 ); + } + } + + /*************************************************************************/ /*************************************************************************/ /***** *****/ diff --git a/src/psaux/psobjs.h b/src/psaux/psobjs.h index c16379462..64e85c580 100644 --- a/src/psaux/psobjs.h +++ b/src/psaux/psobjs.h @@ -233,6 +233,51 @@ FT_BEGIN_HEADER cff_builder_add_contour( CFF_Builder* builder ); + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( void ) + ps_builder_init( PS_Builder* builder, + TT_Face face, + FT_Size size, + CFF_GlyphSlot glyph, + FT_Bool hinting ); + + FT_LOCAL( void ) + ps_builder_done( PS_Builder* builder ); + + FT_LOCAL( FT_Error ) + ps_builder_check_points( PS_Builder* builder, + FT_Int count ); + + FT_LOCAL( void ) + ps_builder_add_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ); + + FT_LOCAL( FT_Error ) + ps_builder_add_point1( PS_Builder* builder, + FT_Pos x, + FT_Pos y ); + + FT_LOCAL( FT_Error ) + ps_builder_add_contour( PS_Builder* builder ); + + FT_LOCAL( FT_Error ) + ps_builder_start_point( PS_Builder* builder, + FT_Pos x, + FT_Pos y ); + + FT_LOCAL( void ) + ps_builder_close_contour( PS_Builder* builder ); + + /*************************************************************************/ /*************************************************************************/ /***** *****/ diff --git a/src/psaux/rules.mk b/src/psaux/rules.mk index 266d446f8..55a835f6a 100644 --- a/src/psaux/rules.mk +++ b/src/psaux/rules.mk @@ -36,6 +36,7 @@ PSAUX_DRV_SRC := $(PSAUX_DIR)/psobjs.c \ $(PSAUX_DIR)/psauxmod.c \ $(PSAUX_DIR)/psarrst.c \ $(PSAUX_DIR)/psblues.c \ + $(PSAUX_DIR)/psdecode.c \ $(PSAUX_DIR)/pserror.c \ $(PSAUX_DIR)/psfont.c \ $(PSAUX_DIR)/psft.c \