From 65c39c2bb5ad453e564e299d3c0fba52c3af6d1e Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 17 Jul 2001 07:24:38 +0000 Subject: [PATCH] Postscript hinter advances --- include/freetype/internal/ftobjs.h | 3 + include/freetype/internal/psaux.h | 4 +- include/freetype/internal/psglobal.h | 2 + include/freetype/internal/pshints.h | 259 ++++++++++- include/freetype/internal/t1types.h | 5 +- src/Jamfile | 1 + src/pcf/pcfread.c | 2 +- src/psaux/psobjs.c | 8 +- src/psaux/t1decode.c | 35 +- src/pshinter/Jamfile | 23 + src/pshinter/pshfit.c | 441 +++++++++++++++++++ src/pshinter/pshfit.h | 90 ++++ src/pshinter/pshglob.c | 605 +++++++++++++++++--------- src/pshinter/pshglob.h | 137 +++--- src/pshinter/pshinter.c | 27 ++ src/pshinter/pshmod.c | 114 +++++ src/pshinter/pshmod.h | 37 ++ src/pshinter/{psrecord.c => pshrec.c} | 188 ++++---- src/pshinter/pshrec.h | 152 +++++++ src/pshinter/psrecord.h | 113 ----- src/type1/t1driver.c | 8 +- src/type1/t1objs.c | 99 ++++- src/type1/t1objs.h | 23 +- 23 files changed, 1898 insertions(+), 478 deletions(-) create mode 100644 src/pshinter/Jamfile create mode 100644 src/pshinter/pshfit.c create mode 100644 src/pshinter/pshfit.h create mode 100644 src/pshinter/pshinter.c create mode 100644 src/pshinter/pshmod.c create mode 100644 src/pshinter/pshmod.h rename src/pshinter/{psrecord.c => pshrec.c} (86%) create mode 100644 src/pshinter/pshrec.h delete mode 100644 src/pshinter/psrecord.h diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index f295330d8..d41d9c14d 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -166,12 +166,15 @@ FT_BEGIN_HEADER /* glyph_delta :: The 2d translation vector corresponding to */ /* the glyph transformation, if necessary. */ /* */ + /* glyph_hints :: format-specific glyph hints management */ + /* */ typedef struct FT_Slot_InternalRec_ { FT_GlyphLoader* loader; FT_Bool glyph_transformed; FT_Matrix glyph_matrix; FT_Vector glyph_delta; + void* glyph_hints; } FT_GlyphSlot_InternalRec; diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index 298c5e109..85970e589 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -506,7 +506,9 @@ FT_BEGIN_HEADER FT_Error error; /* only used for memory errors */ FT_Bool metrics_only; - T1_Builder_Funcs funcs; + T1_Hints_Funcs hints_funcs; + + T1_Builder_Funcs funcs; }; diff --git a/include/freetype/internal/psglobal.h b/include/freetype/internal/psglobal.h index 0749812bb..9c961f598 100644 --- a/include/freetype/internal/psglobal.h +++ b/include/freetype/internal/psglobal.h @@ -9,6 +9,7 @@ /**********************************************************************/ /**********************************************************************/ +#if 0 /**************************************************************** * * @constant: PS_GLOBALS_MAX_BLUE_ZONES @@ -134,6 +135,7 @@ } PS_GlobalsRec; +#endif /* */ #endif /* __PS_GLOBALS_H__ */ diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h index cc74f4d96..f1a12fafd 100644 --- a/include/freetype/internal/pshints.h +++ b/include/freetype/internal/pshints.h @@ -20,8 +20,178 @@ #ifndef __PSHINTS_H__ #define __PSHINTS_H__ +#include +#include FT_TYPES_H +#include FT_INTERNAL_POSTSCRIPT_GLOBALS_H + FT_BEGIN_HEADER + /**********************************************************************/ + /**********************************************************************/ + /***** *****/ + /***** EXTERNAL REPRESENTATION OF GLOBALS *****/ + /***** *****/ + /**********************************************************************/ + /**********************************************************************/ + + /**************************************************************** + * + * @constant: PS_GLOBALS_MAX_BLUE_ZONES + * + * @description: + * the maximum number of blue zones in a font global hints + * structure. See @PS_Globals_BluesRec + */ +#define PS_GLOBALS_MAX_BLUE_ZONES 16 + + /**************************************************************** + * + * @constant: PS_GLOBALS_MAX_STD_WIDTHS + * + * @description: + * the maximum number of standard and snap widths in either the + * horizontal or vertical direction. See @PS_Globals_WidthsRec + */ +#define PS_GLOBALS_MAX_STD_WIDTHS 16 + + /**************************************************************** + * + * @type: PS_Globals + * + * @description: + * a handle to a @PS_GlobalsRec structure used to + * describe the global hints of a given font + */ + typedef struct PS_GlobalsRec_* PS_Globals; + + /**************************************************************** + * + * @struct: PS_Globals_BluesRec + * + * @description: + * a structure used to model the global blue zones of a given + * font + * + * @fields: + * count :: number of blue zones + * zones :: an array of (count*2) coordinates describing the zones + * + * count_family :: number of family blue zones + * zones_family :: an array of (count_family*2) coordinates describing + * the family blue zones + * + * scale :: the blue scale to be used (fixed float) + * shift :: the blue shift to be used + * fuzz :: the blue fuzz to be used + * + * @note: + * each blue zone is modeled by a (reference,overshoot) coordinate pair + * in the table. zones can be placed in any order.. + */ + typedef struct PS_Globals_BluesRec + { + FT_UInt count; + FT_Int16 zones[ 2*PS_GLOBALS_MAX_BLUE_ZONES ]; + + FT_UInt count_family; + FT_Int16 zones_family[ 2*PS_GLOBALS_MAX_BLUE_ZONES ]; + + FT_Fixed scale; + FT_Int16 shift; + FT_Int16 fuzz; + + } PS_Globals_BluesRec, *PS_Globals_Blues; + + + /**************************************************************** + * + * @type: PS_Global_Widths; + * + * @description: + * a handle to a @PS_Globals_WidthsRec structure used to model + * the global standard and snap widths in a given direction + */ + typedef struct PS_Globals_WidthsRec_* PS_Globals_Widths; + + + /**************************************************************** + * + * @struct: PS_Globals_WidthsRec + * + * @description: + * a structure used to model the global standard and snap widths + * in a given font + * + * @fields: + * count :: number of widths + * widths :: an array of 'count' widths in font units. + * + * @note: + * 'widths[0]' must be the standard width or height, while + * remaining elements of the array are snap widths or heights + */ + typedef struct PS_Globals_WidthsRec_ + { + FT_UInt count; + FT_Int16 widths[ PS_GLOBALS_MAX_STD_WIDTHS ]; + + } PS_Globals_WidthsRec; + + + /**************************************************************** + * + * @struct: PS_Globals_GlobalsRec + * + * @description: + * a structure used to model the global hints for a given font + * + * @fields: + * horizontal :: horizontal widths + * vertical :: vertical heights + * blues :: blue zones + */ + typedef struct PS_GlobalsRec_ + { + PS_Globals_WidthsRec horizontal; + PS_Globals_WidthsRec vertical; + PS_Globals_BluesRec blues; + + } PS_GlobalsRec; + + + /**********************************************************************/ + /**********************************************************************/ + /***** *****/ + /***** INTERNAL REPRESENTATION OF GLOBALS *****/ + /***** *****/ + /**********************************************************************/ + /**********************************************************************/ + + typedef struct PSH_GlobalsRec_* PSH_Globals; + + typedef FT_Error (*PSH_Globals_NewFunc)( FT_Memory memory, + PSH_Globals* aglobals ); + + typedef FT_Error (*PSH_Globals_ResetFunc)( PSH_Globals globals, + PS_Globals ps_globals ); + + typedef FT_Error (*PSH_Globals_SetScaleFunc)( PSH_Globals globals, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Fixed x_delta, + FT_Fixed y_delta ); + + typedef void (*PSH_Globals_DestroyFunc)( PSH_Globals globals ); + + typedef struct + { + PSH_Globals_NewFunc create; + PSH_Globals_ResetFunc reset; + PSH_Globals_SetScaleFunc set_scale; + PSH_Globals_DestroyFunc destroy; + + } PSH_Globals_FuncsRec, *PSH_Globals_Funcs; + /**********************************************************************/ /**********************************************************************/ /***** *****/ @@ -106,7 +276,7 @@ FT_BEGIN_HEADER * use horizontal coordinates (x) for vertical stems (dim=1) * * "coords[0]" is the absolute stem position (lowest coordinate) - * "corods[1]" is the length. + * "coords[1]" is the length. * * the length can be negative, in which case it must be either * -20 or -21 in order and will be interpreted as a "ghost" stem, @@ -145,7 +315,7 @@ FT_BEGIN_HEADER /************************************************************************ * - * @functype: T1_Hints_ResetStemsFunc + * @functype: T1_Hints_ResetFunc * * @description: * a method of the @T1_Hints class used to reset the stems hints @@ -156,8 +326,8 @@ FT_BEGIN_HEADER * end_point :: index of last point in the input glyph in which * the previously defined hints apply */ - typedef void (*T1_Hints_ResetStemsFunc)( T1_Hints hints, - FT_UInt end_point ); + typedef void (*T1_Hints_ResetFunc)( T1_Hints hints, + FT_UInt end_point ); /************************************************************************ * @@ -178,8 +348,38 @@ FT_BEGIN_HEADER * the error code will be set to indicate that an error occured * during the recording session */ - typedef FT_Error (*T1_Hint_RecordCloseFunc)( T1_Hints hints, - FT_UInt end_point ); + typedef FT_Error (*T1_Hints_CloseFunc)( T1_Hints hints, + FT_UInt end_point ); + + + /************************************************************************ + * + * @functype: T1_Hints_ApplyFunc + * + * @description: + * a method of the @T1_Hints class used to apply hints to the + * corresponding glyph outline. Must be called once all hints + * have been recorded. + * + * @input: + * hints :: handle to Type 1 hints recorder + * outline :: pointer to target outline descriptor + * globals :: the hinter globals for this font + * + * @return: + * error code. 0 means success + * + * @note: + * on input, all points within the outline are in font coordinates. + * on output, they're in 1/64th of pixels. + * + * the scaling transform is taken from the "globals" object, which + * must correspond to the same font than the glyph + */ + typedef FT_Error (*T1_Hints_ApplyFunc)( T1_Hints hints, + FT_Outline* outline, + PSH_Globals globals ); + /************************************************************************ * @@ -189,19 +389,23 @@ FT_BEGIN_HEADER * the structure used to provide the API to @T1_Hints objects * * @fields: + * hints :: handle to T1 Hints recorder * open :: open recording session * close :: close recording session * stem :: set simple stem * stem3 :: set counter-controlled stems * reset :: reset stem hints + * apply :: apply the hints to the corresponding glyph outline */ typedef struct T1_Hints_FuncsRec_ { + T1_Hints hints; T1_Hints_OpenFunc open; T1_Hints_CloseFunc close; T1_Hints_SetStemFunc stem; T1_Hints_SetStem3Func stem3; T1_Hints_ResetFunc reset; + T1_Hints_ApplyFunc apply; } T1_Hints_FuncsRec; @@ -387,6 +591,35 @@ FT_BEGIN_HEADER typedef FT_Error (*T2_Hints_CloseFunc) ( T2_Hints hints, FT_UInt end_point ); + + /************************************************************************ + * + * @functype: T2_Hints_ApplyFunc + * + * @description: + * a method of the @T2_Hints class used to apply hints to the + * corresponding glyph outline. Must be called after the "close" method + * + * @input: + * hints :: handle to Type 2 hints recorder + * outline :: pointer to target outline descriptor + * globals :: the hinter globals for this font + * + * @return: + * error code. 0 means success + * + * @note: + * on input, all points within the outline are in font coordinates. + * on output, they're in 1/64th of pixels. + * + * the scaling transform is taken from the "globals" object, which + * must correspond to the same font than the glyph + */ + typedef FT_Error (*T2_Hints_ApplyFunc)( T2_Hints hints, + FT_Outline* outline, + PSH_Globals globals ); + + /************************************************************************ * * @struct: T2_Hints_FuncsRec @@ -395,24 +628,36 @@ FT_BEGIN_HEADER * the structure used to provide the API to @T2_Hints objects * * @fields: + * hints :: handle to T2 hints recorder object * open :: open recording session * close :: close recording session * stems :: set dimension's stems table * hintmask :: set hint masks * counter :: set counter masks + * apply :: apply the hints on the corresponding glyph outline */ typedef struct T2_Hints_FuncsRec_ { + T2_Hints hints; T2_Hints_OpenFunc open; T2_Hints_CloseFunc close; T2_Hints_StemsFunc stems; T2_Hints_MaskFunc hintmask; T2_Hints_CounterFunc counter; + T2_Hints_ApplyFunc apply; } T2_Hints_FuncsRec; - /* */ + /* */ + + typedef struct PSHinter_Interface_ + { + PSH_Globals_Funcs (*get_globals_funcs)( FT_Module module ); + T1_Hints_Funcs (*get_t1_funcs) ( FT_Module module ); + T2_Hints_Funcs (*get_t2_funcs) ( FT_Module module ); + + } PSHinter_Interface, *PSHinter_InterfacePtr; FT_END_HEADER diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h index 01841f018..ffa9b2a1e 100644 --- a/include/freetype/internal/t1types.h +++ b/include/freetype/internal/t1types.h @@ -24,7 +24,7 @@ #include #include FT_TYPE1_TABLES_H #include FT_INTERNAL_POSTSCRIPT_NAMES_H - +#include FT_INTERNAL_POSTSCRIPT_HINTS_H FT_BEGIN_HEADER @@ -172,6 +172,9 @@ FT_BEGIN_HEADER /* support for Multiple Masters fonts */ T1_Blend* blend; + + /* since FT 2.1 - interface to Postscript hinter */ + void* pshinter; } T1_FaceRec; diff --git a/src/Jamfile b/src/Jamfile index 47248b441..c37cbcbcd 100644 --- a/src/Jamfile +++ b/src/Jamfile @@ -14,6 +14,7 @@ SubDirHdrs [ FT2_SubDir src ] ; # HDRMACRO [ FT2_SubDir include internal internal.h ] ; +SubInclude FT2_TOP src pshinter ; SubInclude FT2_TOP src autohint ; SubInclude FT2_TOP src base ; SubInclude FT2_TOP src cache ; diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c index 06ecfab22..5f8269d2f 100644 --- a/src/pcf/pcfread.c +++ b/src/pcf/pcfread.c @@ -717,7 +717,7 @@ THE SOFTWARE. else encodingOffset = GET_ShortLE(); - if ( encodingOffset != (signed short)0xFFFF ) + if ( encodingOffset != 0xFFFF ) { tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) + firstRow ) * 256 ) + diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index 28306eece..6362618c2 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -1077,10 +1077,12 @@ FT_GlyphLoader* loader = glyph->internal->loader; - builder->loader = loader; - builder->base = &loader->base.outline; - builder->current = &loader->current.outline; + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; FT_GlyphLoader_Rewind( loader ); + + builder->hints_func = (T1_Hints_Funcs) glyph->internal->glyph_hints; } if ( size ) diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index 77bae29c8..1c0b01476 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -18,6 +18,7 @@ #include #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H #include FT_OUTLINE_H #include "t1decode.h" @@ -325,6 +326,7 @@ T1_Builder* builder = &decoder->builder; FT_Pos x, y; + T1_Hints_Funcs hinter; /* we don't want to touch the source code -- use macro trick */ #define start_point T1_Builder_Start_Point @@ -341,6 +343,8 @@ builder->path_begun = 0; + hinter = builder->hints_funcs; + zone->base = charstring_base; limit = zone->limit = charstring_base + charstring_len; ip = zone->cursor = zone->base; @@ -350,6 +354,10 @@ x = builder->pos_x; y = builder->pos_y; + /* begin hints recording session, if any */ + if ( hinter ) + hinter->open( hinter->hints ); + /* now, execute loop */ while ( ip < limit ) { @@ -613,6 +621,10 @@ goto Syntax_Error; } ip += 2; + + if ( hinter ) + hinter->reset( hinter->hints, builder->current->n_points ); + break; case 12: @@ -707,7 +719,11 @@ FT_TRACE4(( " endchar" )); close_contour( builder ); - + + /* close hints recording session */ + if ( hinter ) + hinter->close( hinter->hints, builder->current->n_points ); + /* add current outline to the glyph slot */ FT_GlyphLoader_Add( builder->loader ); @@ -973,22 +989,38 @@ case op_hstem: FT_TRACE4(( " hstem" )); + + /* record horizontal hint */ + if ( hinter ) + hinter->stem( hinter->hints, 0, top ); break; case op_hstem3: FT_TRACE4(( " hstem3" )); + /* record horizontal counter-controlled hints */ + if ( hinter ) + hinter->stem3( hinter->hints, 0, top ); + break; case op_vstem: FT_TRACE4(( " vstem" )); + /* record vertical hint */ + if ( hinter ) + hinter->stem( hinter->hints, 1, top ); + break; case op_vstem3: FT_TRACE4(( " vstem3" )); + /* record vertical counter-controlled hints */ + if ( hinter ) + hinter->stem3( hinter->hints, 1, top ); + break; case op_setcurrentpoint: @@ -1011,6 +1043,7 @@ } /* while ip < limit */ FT_TRACE4(( "..end..\n\n" )); + return error; Syntax_Error: diff --git a/src/pshinter/Jamfile b/src/pshinter/Jamfile new file mode 100644 index 000000000..1dec8d77c --- /dev/null +++ b/src/pshinter/Jamfile @@ -0,0 +1,23 @@ +# FreeType 2 src/pshinter Jamfile (c) 2001 David Turner +# + +SubDir FT2_TOP src pshinter ; + +SubDirHdrs [ FT2_SubDir src pshinter ] ; + +{ + local _sources ; + + if $(FT2_MULTI) + { + _sources = pshrec pshglob pshfit pshmod ; + } + else + { + _sources = pshinter ; + } + + Library $(FT2_LIB) : $(_sources).c ; +} + +# end of src/psaux Jamfile diff --git a/src/pshinter/pshfit.c b/src/pshinter/pshfit.c new file mode 100644 index 000000000..4a4a31b1e --- /dev/null +++ b/src/pshinter/pshfit.c @@ -0,0 +1,441 @@ +#include +#include FT_INTERNAL_OBJECTS_H +#include "pshfit.h" + + /* return true iff two hints overlap */ + static FT_Int + psh_hint_overlap( PSH_Hint hint1, + PSH_Hint hint2 ) + { + return ( hint1->org_pos + hint1->org_len >= hint2->org_pos && + hint2->org_pos + hint2->org_len >= hint1->org_pos ); + } + + + /* destroy hints table */ + static void + psh_hint_table_done( PSH_Hint_Table table, + FT_Memory memory ) + { + FREE( table->zones ); + table->num_zones = 0; + table->zone = 0; + + FREE( table->sort ); + FREE( table->hints ); + table->num_hints = 0; + table->max_hints = 0; + table->sort_global = 0; + } + + + /* deactivate all hints in a table */ + static void + psh_hint_table_deactivate( PSH_Hint_Table table ) + { + FT_UInt count = table->max_hints; + PSH_Hint hint = table->hints; + + for ( ; count > 0; count--, hint++ ) + { + psh_hint_deactivate(hint); + hint->order = -1; + } + } + + + /* internal function used to record a new hint */ + static void + psh_hint_table_record( PSH_Hint_Table table, + FT_UInt index ) + { + PSH_Hint hint = table->hints + index; + + if ( index >= table->max_hints ) + { + FT_ERROR(( "%s.activate: invalid hint index %d\n", index )); + return; + } + + /* ignore active hints */ + if ( psh_hint_is_active(hint) ) + return; + + psh_hint_activate(hint); + + /* now scan the current active hint set in order to determine */ + /* if we're overlapping with another segment.. */ + { + PSH_Hint* sorted = table->sort; + FT_UInt count = table->num_hints; + PSH_Hint hint2; + + hint->parent = 0; + for ( ; count > 0; count--, sorted++ ) + { + hint2 = sorted[0]; + + if ( psh_hint_overlap( hint, hint2 ) ) + { + hint->parent = hint2; + break; + } + } + } + + if ( table->num_hints < table->max_hints ) + table->sort_global[ table->num_hints++ ] = hint; + else + { + FT_ERROR(( "%s.activate: too many sorted hints !! BUG !!\n", + "ps.fitter" )); + } + } + + + static void + psh_hint_table_record_mask( PSH_Hint_Table table, + PS_Mask hint_mask ) + { + FT_Int mask = 0, val = 0; + FT_Byte* cursor = hint_mask->bytes; + FT_UInt index, limit; + + limit = hint_mask->num_bits; + + if ( limit != table->max_hints ) + { + FT_ERROR(( "%s.activate_mask: invalid bit count (%d instead of %d)\n", + "ps.fitter", hint_mask->num_bits, table->max_hints )); + } + + for ( index = 0; index < limit; index++ ) + { + if ( mask == 0 ) + { + val = *cursor++; + mask = 0x80; + } + + if ( val & mask ) + psh_hint_table_record( table, index ); + + mask >>= 1; + } + } + + + /* create hints table */ + static FT_Error + psh_hint_table_init( PSH_Hint_Table table, + PS_Hint_Table hints, + PS_Mask_Table hint_masks, + PS_Mask_Table counter_masks, + FT_Memory memory ) + { + FT_UInt count = hints->num_hints; + FT_Error error; + + FT_UNUSED(counter_masks); + + /* allocate our tables */ + if ( ALLOC_ARRAY( table->sort, 2*count, PSH_Hint ) || + ALLOC_ARRAY( table->hints, count, PSH_HintRec ) || + ALLOC_ARRAY( table->zones, 2*count+1, PSH_ZoneRec ) ) + goto Exit; + + table->max_hints = count; + table->sort_global = table->sort + count; + table->num_hints = 0; + table->num_zones = 0; + table->zone = 0; + + /* now, initialise the "hints" array */ + { + PSH_Hint write = table->hints; + PS_Hint read = hints->hints; + + for ( ; count > 0; count--, write++, read++ ) + { + write->org_pos = read->pos; + write->org_len = read->len; + write->flags = read->flags; + } + } + + /* we now need to determine the initial "parent" stems, first */ + /* activate the hints that are given by the initial hint masks */ + if ( hint_masks ) + { + FT_UInt count = hint_masks->num_masks; + PS_Mask mask = hint_masks->masks; + + for ( ; count > 0; count--, mask++ ) + psh_hint_table_record_mask( table, mask ); + } + + /* now, do a linear parse in case some hints were left alone */ + if ( table->num_hints != table->max_hints ) + { + FT_UInt index, count; + + FT_ERROR(( "%s.init: missing/incorrect hint masks !!\n" )); + count = table->max_hints; + for ( index = 0; index < count; index++ ) + psh_hint_table_record( table, index ); + } + + Exit: + return error; + } + + + + static void + psh_hint_table_activate_mask( PSH_Hint_Table table, + PS_Mask hint_mask ) + { + FT_Int mask = 0, val = 0; + FT_Byte* cursor = hint_mask->bytes; + FT_UInt index, limit, count; + + limit = hint_mask->num_bits; + count = 0; + + psh_hint_table_deactivate( table ); + + for ( index = 0; index < limit; index++ ) + { + if ( mask == 0 ) + { + val = *cursor++; + mask = 0x80; + } + + if ( val & mask ) + { + PSH_Hint hint = &table->hints[index]; + + if ( !psh_hint_is_active(hint) ) + { + PSH_Hint* sort = table->sort; + FT_UInt count2; + PSH_Hint hint2; + + for ( count2 = count; count2 > 0; count2--, sort++ ) + { + hint2 = sort[0]; + if ( psh_hint_overlap( hint, hint2 ) ) + { + FT_ERROR(( "%s.activate_mask: found overlapping hints\n", + "psf.hint" )); + break; + } + } + + if ( count2 == 0 ) + { + psh_hint_activate( hint ); + if ( count < table->max_hints ) + table->sort[count++] = hint; + else + { + FT_ERROR(( "%s.activate_mask: too many active hints\n", + "psf.hint" )); + } + } + } + } + + mask >>= 1; + } + table->num_hints = count; + + /* now, sort the hints, they're guaranteed to not overlap */ + /* so we can compare their "org_pos" field directly.. */ + { + FT_Int i1, i2; + PSH_Hint hint1, hint2; + PSH_Hint* sort = table->sort; + + /* a simple bubble sort will do, since in 99% of cases, the hints */ + /* will be already sorted.. and the sort will be linear */ + for ( i1 = 1; i1 < (FT_Int)count; i1++ ) + { + hint1 = sort[i1]; + for ( i2 = i1-1; i2 >= 0; i2-- ) + { + hint2 = sort[i2]; + if ( hint2->org_pos < hint1->org_pos ) + break; + + sort[i1] = hint2; + sort[i2] = hint1; + } + } + } + } + + +#define PSH_ZONE_MIN -3200000 +#define PSH_ZONE_MAX +3200000 + + /* setup interpolation zones once the hints have been grid-fitted */ + static void + psh_hint_table_setup_zones( PSH_Hint_Table table, + FT_Fixed scale, + FT_Fixed delta ) + { + FT_UInt count; + PSH_Zone zone; + PSH_Hint *sort, hint, hint2; + + zone = table->zones; + + /* special case, no hints defined */ + if ( table->num_hints == 0 ) + { + zone->scale = scale; + zone->delta = delta; + zone->min = PSH_ZONE_MIN; + zone->max = PSH_ZONE_MAX; + table->num_zones = 1; + return; + } + + /* the first zone is before the first hint */ + /* x' = (x-x0)*s + x0' = x*s + ( x0' - x0*s ) */ + sort = table->sort; + hint = sort[0]; + + zone->scale = scale; + zone->delta = hint->cur_pos - FT_MulFix( hint->org_pos, scale ); + zone->min = PSH_ZONE_MIN; + zone->max = hint->org_pos; + zone++; + + for ( count = table->num_hints; count > 1; count-- ) + { + FT_Fixed scale2; + + if ( hint->org_len > 0 ) + { + /* setup a zone for inner-stem interpolation */ + /* (x' - x0') = (x - x0)*(x1'-x0')/(x1-x0) */ + /* x' = x*s2 + x0' - x0*s2 */ + + scale2 = FT_DivFix( hint->cur_len, hint->org_len ); + zone->scale = scale2; + zone->min = hint->org_pos; + zone->max = hint->org_pos + hint->org_len; + zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale2 ); + zone++; + } + + sort++; + hint2 = sort[0]; + + /* setup zone for inter-stem interpolation */ + /* (x'-x1') = (x-x1)*(x2'-x1')/(x2-x1) */ + /* x' = x*s3 + x1' - x1*s3 */ + scale2 = FT_DivFix( hint2->cur_pos - (hint->cur_pos + hint->cur_len), + hint2->org_pos - (hint2->org_pos + hint2->org_len) ); + zone->scale = scale2; + zone->min = hint->org_pos + hint->org_len; + zone->max = hint2->org_pos; + zone->delta = hint->cur_pos + hint->cur_len - FT_MulFix( zone->min, scale2 ); + zone++; + + hint = hint2; + } + + /* the last zone */ + zone->scale = scale; + zone->min = hint->org_pos + hint->org_len; + zone->max = PSH_ZONE_MAX; + zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale ); + zone++; + + table->num_zones = zone - table->zones; + table->zone = table->zones; + } + + + /* tune a single coordinate with the current interpolation zones */ + static FT_Pos + psh_hint_table_tune_coord( PSH_Hint_Table table, + FT_Int coord ) + { + PSH_Zone zone; + + zone = table->zone; + + if ( coord < zone->min ) + { + do + { + if ( zone == table->zones ) + break; + + zone--; + } + while ( coord < zone->min ); + table->zone = zone; + } + else if ( coord > zone->max ) + { + do + { + if ( zone == table->zones + table->num_zones - 1 ) + break; + + zone++; + } + while ( coord > zone->max ); + table->zone = zone; + } + + return zone->delta + FT_MulFix( coord, zone->scale ); + } + + + /* tune a given outline with current interpolation zones */ + static void + psh_hint_table_tune_outline( PSH_Hint_Table table, + FT_Outline* outline, + FT_Fixed scale, + FT_Fixed delta, + FT_Bool vertical ) + + { + FT_UInt count, first, last; + PS_Mask_Table hint_masks; + PS_Mask mask; + + first = 0; + mask = hint_masks->masks; + count = hint_masks->num_masks; + for ( ; count > 0; count--, mask++ ) + { + FT_Vector* vec; + FT_Int count2; + + psh_hint_table_activate_mask( table, mask ); + psh_hint_table_setup_zones( table, scale, delta ); + last = mask->end_point; + + vec = outline->points + first; + count2 = last - first + 1; + for ( ; count2 > 0; count2--, vec++ ) + { + FT_Pos x, *px; + + px = vertical ? &vec->y : &vec->y; + x = *px; + + *px = psh_hint_table_tune_coord( table, (FT_Int)x ); + } + + first = (FT_UInt)(last+1); + } + } diff --git a/src/pshinter/pshfit.h b/src/pshinter/pshfit.h new file mode 100644 index 000000000..bc83d33ad --- /dev/null +++ b/src/pshinter/pshfit.h @@ -0,0 +1,90 @@ +/***************************************************************************/ +/* */ +/* pshfit.h */ +/* */ +/* Postscript (Type 1/CFF) outline grid-fitter */ +/* */ +/* Copyright 2001 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. */ +/* */ +/* */ +/* process the hints provided by the Postscript hints recorder. This */ +/* means sorting and scaling the hints, calling the "optimiser" to */ +/* process them, then grid-fitting the glyph outline based on the */ +/* optimised hints information. */ +/* */ +/* (the real hinting "intelligence" is in "pshoptim.h", not here) */ +/* */ +/***************************************************************************/ + +#ifndef __PS_HINTER_FITTER_H__ +#define __PS_HINTER_FITTER_H__ + +#include "pshrec.h" + +FT_BEGIN_HEADER + + typedef struct PSH_HintRec_* PSH_Hint; + + typedef enum + { + PSH_HINT_FLAG_GHOST = PS_HINT_FLAG_GHOST, + PSH_HINT_FLAG_BOTTOM = PS_HINT_FLAG_BOTTOM, + PSH_HINT_FLAG_ACTIVE = 4 + + } PSH_Hint_Flags; + +#define psh_hint_is_active(x) (((x)->flags & PSH_HINT_FLAG_ACTIVE) != 0) +#define psh_hint_activate(x) (x)->flags |= PSH_HINT_FLAG_ACTIVE +#define psh_hint_deactivate(x) (x)->flags &= ~PSH_HINT_FLAG_ACTIVE + + typedef struct PSH_HintRec_ + { + FT_Int org_pos; + FT_Int org_len; + FT_Pos cur_pos; + FT_Pos cur_len; + + FT_UInt flags; + + PSH_Hint parent; + FT_Int order; + + } PSH_HintRec; + + + typedef struct PSH_ZoneRec_ + { + FT_Fixed scale; + FT_Fixed delta; + FT_Pos min; + FT_Pos max; + + } PSH_ZoneRec, *PSH_Zone; + + + typedef struct PSH_Hint_TableRec_ + { + FT_UInt max_hints; + FT_UInt num_hints; + PSH_Hint hints; + PSH_Hint* sort; + PSH_Hint* sort_global; + FT_UInt num_zones; + PSH_Zone zones; + PSH_Zone zone; + PS_Mask_Table hint_masks; + PS_Mask_Table counter_masks; + + } PSH_Hint_TableRec, *PSH_Hint_Table; + + +FT_END_HEADER + +#endif /* __PS_HINTER_FITTER_H__ */ diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c index c8b1ec429..480116db4 100644 --- a/src/pshinter/pshglob.c +++ b/src/pshinter/pshglob.c @@ -1,27 +1,24 @@ +#include #include "pshglob.h" /* "simple" ps hinter globals management, inspired from the new auto-hinter */ - FT_LOCAL void - psh_globals_init( PSH_Globals globals, - FT_Memory memory ) - { - memset( globals, 0, sizeof(*globals) ); - globals->memory = memory; - globals->x_scale = 0x10000L; - globals->y_scale = 0x10000L; - } - + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** STANDARD WIDTHS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /* reset the widths/heights table */ - static FT_Error + static void psh_globals_reset_widths( PSH_Globals globals, FT_UInt direction, PS_Globals_Widths widths ) { - PSH_Dimension dim = &globals->dim[direction]; - FT_Memory memory = globals->memory; - FT_Error error = 0; + PSH_Dimension dim = &globals->dimension[direction]; /* simple copy of the original widths values - no sorting */ { @@ -37,8 +34,6 @@ read++; } } - - return error; } @@ -47,10 +42,11 @@ psh_globals_scale_widths( PSH_Globals globals, FT_UInt direction ) { - PSH_Widths std = &globals->std[direction]; - FT_UInt count = std->count; - PSH_Width width = std->widths; - FT_Fixed scale = globals->scale[direction]; + PSH_Dimension dim = &globals->dimension[direction]; + PSH_Widths std = &dim->std; + FT_UInt count = std->count; + PSH_Width width = std->widths; + FT_Fixed scale = dim->scale_mult; for ( ; count > 0; count--, width++ ) { @@ -59,219 +55,416 @@ } } + - /* reset the blues table */ - static FT_Error - psh_globals_reset_blues( PSH_Globals globals, - PS_Globals_Blues blues ) + FT_LOCAL_DEF FT_Pos + psh_dimension_snap_width( PSH_Dimension dimension, + FT_Int org_width ) { - FT_Error error = 0; - FT_Memory memory = globals->memory; + FT_UInt n; + FT_Pos width = FT_MulFix( org_width, dimension->scale_mult ); + FT_Pos best = 64 + 32 + 2; + FT_Pos reference = width; - if ( !FT_REALLOC_ARRAY( globals->blues.zones, globals->blues.count, - blues->count, PSH_Blue_ZoneRec ) ) + for ( n = 0; n < dimension->std.count; n++ ) { - FT_UInt count = 0; - - globals->blyes.count = blues->count; + FT_Pos w; + FT_Pos dist; - /* first of all, build a sorted table of blue zones */ + w = dimension->std.widths[n].cur; + dist = width - w; + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) { - FT_Int16* read = blue->zones; - FT_UInt n, i, j; - FT_Pos reference, overshoot, delta; - - for ( n = 0; n < blues->count; n++, read++ ) - { - PSH_Blue_Zone zone; - - /* read new blue zone entry, find top and bottom coordinates */ - reference = read[0]; - overshoot = read[1]; - delta = overshoot - reference; - - /* now, insert in the blue zone table, sorted by reference position */ - zone = globals->blues.zones; - for ( i = 0; i < count; i++, zone++ ) - { - if ( reference > zone->org_ref ) - break; - - if ( reference == zone->org_ref ) - { - /* on the same reference coordinate, place bottom zones */ - /* before top zones.. */ - if ( delta < 0 || zone->org_delta >= 0 ) - break; - } - - for ( j = count - i; j > 0; j-- ) - zone[j+1] = zone[j]; - - zone->org_ref = reference; - zone->org_delta = delta; - - count++; - } + best = dist; + reference = w; } - - /* now, get rid of blue zones located on the same reference position */ - /* (only keep the largest zone).. */ - { - PSH_Blue_Zone zone, limit; - - zone = globals->blues.zones; - limit = zone + count; - for ( ; zone+1 < limit; zone++ ) - { - if ( zone[0].org_ref == zone[1].org_ref ) - { - FT_Int delta0 = zone[0].org_delta; - FT_Int delta1 = zone[1].org_delta; - - /* these two zones are located on the same reference coordinate */ - /* we need to merge them when they're in the same direction.. */ - if ( ( delta0 < 0 ) ^ ( delta1 < 0 ) ) == 0 ) - { - /* ok, take the biggest one */ - if ( delta0 < 0 ) - { - if ( delta1 < delta0 ) - delta0 = delta1; - } - else - { - if ( delta1 > delta0 ) - delta0 = delta1; - } - - zone[0].org_delta = delta0; - - { - PSH_Blue_Zone cur = zone+1; - FT_UInt count2 = limit - cur; - - for ( ; count2 > 0; count2--, cur++ ) - { - cur[0].org_ref = cur[1].org_ref; - cur[0].org_delta = cur[1].org_delta; - } - } - count--; - limit--; - } - } - } - } - - globals->blues.count = count; - globals->blues.org_shift = blues->shift; - globals->blues.org_fuzz = blues->fuzz; } + if ( width >= reference ) + { + width -= 0x21; + if ( width < reference ) + width = reference; + } + else + { + width += 0x21; + if ( width > reference ) + width = reference; + } + + return width; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BLUE ZONES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + psh_blues_reset_zones( PSH_Blues target, + PS_Globals_Blues source, + FT_Int family ) + { + PSH_Blue_Table top_table, bot_table; + FT_Int16* read; + FT_Int read_count, count, count_top, count_bot; + + if ( family ) + { + top_table = &target->family_top; + bot_table = &target->family_bottom; + read = source->zones_family; + read_count = (FT_Int)source->count_family; + } + else + { + top_table = &target->normal_top; + bot_table = &target->normal_bottom; + read = source->zones; + read_count = (FT_Int)source->count; + } + + /* read the input blue zones, and build two sorted tables */ + /* (one for the top zones, the other for the bottom zones */ + count_top = 0; + count_bot = 0; + for ( ; read_count > 0; read_count-- ) + { + FT_Int reference, delta; + PSH_Blue_Zone zones, zone; + + /* read blue zone entry, and select target top/bottom zone */ + reference = read[0]; + delta = read[1] - reference; + + if ( delta >= 0 ) + { + zones = top_table->zones; + count = count_top; + } + else + { + zones = bot_table->zones; + count = count_bot; + } + + /* insert into sorted table */ + zone = zones; + for ( ; count > 0; count--, zone++ ) + { + if ( reference < zone->org_ref ) + break; + + if ( reference == zone->org_ref ) + { + FT_Int delta0 = zone->org_delta; + + /* we have two zones on the same reference position */ + /* only keep the largest one.. */ + if ( delta < 0 ) + { + if ( delta < delta0 ) + zone->org_delta = delta; + } + else + { + if ( delta > delta0 ) + zone->org_delta = delta; + } + goto Skip; + } + } + + for ( ; count > 0; count-- ) + zone[count] = zone[count-1]; + + zone->org_ref = reference; + zone->org_delta = delta; + + if ( delta >= 0 ) + count_top ++; + else + count_bot ++; + + Skip: + read += 2; + } + + top_table->count = count_top; + bot_table->count = count_bot; + + /* sanitize top table */ + { + PSH_Blue_Zone zone = top_table->zones; + + for ( count = count_top-1; count > 0; count--, zone++ ) + { + FT_Int delta; + + delta = zone[1].org_ref - zone[0].org_ref; + if ( zone->org_delta > delta ) + zone->org_delta = delta; + + zone->org_bottom = zone->org_ref; + zone->org_top = zone->org_delta + zone->org_ref; + } + } + + /* sanitize bottom table */ + { + PSH_Blue_Zone zone = bot_table->zones; + + for ( count = count_bot-1; count > 0; count--, zone++ ) + { + FT_Int delta; + + delta = zone[0].org_ref - zone[1].org_ref; + if ( zone->org_delta < delta ) + zone->org_delta = delta; + + zone->org_top = zone->org_ref; + zone->org_bottom = zone->org_delta + zone->org_ref; + } + } + + /* expand top and bottom tables with blue fuzz */ + { + FT_Int dim, top, bot, delta, fuzz; + PSH_Blue_Zone zone; + + fuzz = source->fuzz; + zone = top_table->zones; + count = count_top; + + for ( dim = 1; dim >= 0; dim-- ) + { + if ( count > 0 ) + { + /* expand the bottom of the lowest zone normally */ + zone->org_bottom -= fuzz; + + /* expand the top and bottom of intermediate zones */ + /* checking that the interval is smaller than the fuzz */ + top = zone->org_top; + + for ( count--; count > 0; count--, zone++ ) + { + bot = zone[1].org_bottom; + delta = bot - top; + if ( delta < 2*fuzz ) + { + zone[0].org_top = zone[1].org_bottom = top + delta/2; + } + else + { + zone[0].org_top = top + fuzz; + zone[1].org_bottom = bot - fuzz; + } + + zone++; + top = zone->org_top; + } + + /* expand the top of the highest zone normally */ + zone->org_top = top + fuzz; + } + zone = bot_table->zones; + count = count_bot; + } + } + } + + + /* reset the blues table */ + static void + psh_blues_scale_zones( PSH_Blues blues, + FT_Fixed scale, + FT_Pos delta ) + { + FT_UInt count; + FT_UInt num; + PSH_Blue_Table table = 0; + + for ( num = 0; num < 4; num++ ) + { + PSH_Blue_Zone zone; + + switch (num) + { + case 0: table = &blues->normal_top; break; + case 1: table = &blues->normal_bottom; break; + case 2: table = &blues->family_top; break; + default: table = &blues->family_bottom; + } + + zone = table->zones; + count = table->count; + for ( ; count > 0; count--, zone++ ) + { + zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; + zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; + zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; + zone->cur_delta = FT_MulFix( zone->org_delta, scale ); + + /* round scaled reference position */ + zone->cur_ref = ( zone->cur_ref + 32 ) & -64; + } + } + + /* XXX: we should process the family / normal tables here !! */ + } + + + FT_LOCAL_DEF void + psh_blues_snap_stem( PSH_Blues blues, + FT_Int stem_top, + FT_Int stem_bot, + PSH_Blue_Alignement alignment ) + { + PSH_Blue_Table table; + FT_UInt count; + PSH_Blue_Zone zone; + + alignment->align = 0; + + /* lookup stem top in top zones table */ + table = &blues->normal_top; + count = table->count; + zone = table->zones; + for ( ; count > 0; count-- ) + { + if ( stem_top < zone->org_bottom ) + break; + + if ( stem_top <= zone->org_top ) + { + alignment->align |= PSH_BLUE_ALIGN_TOP; + alignment->align_top = zone->cur_ref; + break; + } + } + + /* lookup stem bottom in bottom zones table */ + table = &blues->normal_bottom; + count = table->count; + zone = table->zones; + for ( ; count > 0; count-- ) + { + if ( stem_bot < zone->org_bottom ) + break; + + if ( stem_bot <= zone->org_top ) + { + alignment->align |= PSH_BLUE_ALIGN_BOT; + alignment->align_bot = zone->cur_ref; + } + } + } + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GLOBAL HINTS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + psh_globals_destroy( PSH_Globals globals ) + { + if (globals) + { + FT_Memory memory; + + memory = globals->memory; + globals->dimension[0].std.count = 0; + globals->dimension[1].std.count = 0; + + globals->blues.normal_top.count = 0; + globals->blues.normal_bottom.count = 0; + globals->blues.family_top.count = 0; + globals->blues.family_bottom.count = 0; + + FREE( globals ); + } + } + + + static FT_Error + psh_globals_new( FT_Memory memory, PSH_Globals *aglobals ) + { + PSH_Globals globals; + FT_Error error; + + if ( !ALLOC( globals, sizeof(*globals) ) ) + globals->memory = memory; + + *aglobals = globals; return error; } - static void - psh_globals_scale_blues( PSH_Globals globals, - PS_Globals_Blues blues ) + static FT_Error + psh_globals_reset( PSH_Globals globals, + PS_Globals ps_globals ) { - FT_Fixed y_scale = globals->scale[1]; - FT_Fixed y_delta = globals->delta[1]; - FT_Pos prev_top; - PSH_Blue_Zone zone, prev; - FT_UInt count; - - zone = globals->blues.zones; - prev = 0; - prev_top = 0; - for ( count = globals->blues.count; count > 0; count-- ) - { - FT_Pos ref, delta, top, bottom; - - ref = FT_MulFix( zone->org_ref, y_scale ) + y_delta; - delta = FT_MulFix( zone->org_delta, y_scale ); - ref = (ref+32) & -64; - - if ( delta < 0 ) - { - top = ref; - bottom = ref + delta; - } - else - { - bottom = ref; - top = ref + delta; - } - - zone->cur_ref = ref; - zone->cur_delta = delta; - zone->cur_top = top; - zone->cur_bottom = bottom; - - if - prev = zone; - zone++; - } - /* XXXX: test overshoot supression !! */ - } - - FT_LOCAL FT_Error - psh_globals_reset( PSH_Globals globals, - T1_Fitter_Globals public_globals ) - { - psh_globals_reset_widths( globals, 0, &public_globals->horizontal ); - psh_globals_scale_widths( globals, 0 ); - - psh_globals_reset_widths( globals, 1, &public_globals->vertical ); - psh_globals_scale_widths( globals, 1 ); - - psh_globals_reset_blues( globals, public_globals ); - psh_globals_scale_blues( globals ); + psh_globals_reset_widths( globals, 0, &ps_globals->horizontal ); + psh_globals_reset_widths( globals, 1, &ps_globals->vertical ); + psh_blues_reset_zones( &globals->blues, &ps_globals->blues, 0 ); + psh_blues_reset_zones( &globals->blues, &ps_globals->blues, 1 ); + + globals->dimension[0].scale_mult = 0; + globals->dimension[0].scale_delta = 0; + globals->dimension[1].scale_mult = 0; + globals->dimension[1].scale_delta = 0; + + return 0; } - FT_LOCAL void + static FT_Error psh_globals_set_scale( PSH_Globals globals, FT_Fixed x_scale, FT_Fixed x_delta, FT_Fixed y_scale, FT_Fixed y_delta ) { - FT_Memory memory = globals->memory; - - if ( x_scale != globals->scale[0] || - y_scale != globals->scale[1] || - x_delta != globals->delta[0] || - y_delta != globals->delta[1] ) + PSH_Dimension dim = &globals->dimension[0]; + + dim = &globals->dimension[0]; + if ( x_scale != dim->scale_mult || + x_delta != dim->scale_delta ) { - globals->scale[0] = x_scale; - globals->scale[1] = y_scale; - globals->delta[0] = x_delta; - globals->delta[1] = y_delta; - + dim->scale_mult = x_scale; + dim->scale_delta = x_delta; + psh_globals_scale_widths( globals, 0 ); - psh_globals_scale_widths( globals, 1 ); - psh_globals_scale_blues ( globals ); } - } - - FT_LOCAL void - psh_globals_done( PSH_Globals globals ) - { - if (globals) + dim = &globals->dimension[1]; + if ( y_scale != dim->scale_mult || + y_delta != dim->scale_delta ) { - FT_Memory memory = globals->memory; - - FT_FREE( globals->std[0].widths ); - globals->std[0].count = 0; - - FT_FREE( globals->std[1].widths ); - globals->std[1].count = 0; - - FT_FREE( globals->blues.zones ); - globals->blues.count = 0; + psh_globals_scale_widths( globals, 1 ); + psh_blues_scale_zones( &globals->blues, y_scale, y_delta ); } + + return 0; + } + + + FT_LOCAL_DEF void + psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ) + { + funcs->create = psh_globals_new; + funcs->reset = psh_globals_reset; + funcs->set_scale = psh_globals_set_scale; + funcs->destroy = psh_globals_destroy; } diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h index c3594a71a..17a9633a2 100644 --- a/src/pshinter/pshglob.h +++ b/src/pshinter/pshglob.h @@ -1,6 +1,26 @@ +/***************************************************************************/ +/* */ +/* pshglob.h */ +/* */ +/* Postscript hinter globals hints management. */ +/* */ +/* Copyright 2001 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. */ +/* */ +/***************************************************************************/ + #ifndef __PS_HINTER_GLOBALS_H__ #define __PS_HINTER_GLOBALS_H__ +#include FT_FREETYPE_H +#include FT_INTERNAL_POSTSCRIPT_GLOBALS_H + FT_BEGIN_HEADER /**********************************************************************/ @@ -11,37 +31,6 @@ FT_BEGIN_HEADER /**********************************************************************/ /**********************************************************************/ - /* blue zone descriptor */ - typedef struct PSH_Blue_ZoneRec_ - { - FT_Int org_ref; - FT_Int org_delta; - FT_Pos cur_ref; - FT_Pos cur_delta; - FT_Pos cur_bottom; - FT_Pos cur_top; - - } PSH_Blue_ZoneRec, *PSH_Blue_Zone; - - - /* blue zones table */ - typedef struct PSH_BluesRec_ - { - FT_UInt count; - PSH_Blue_ZoneRec zones[ PS_GLOBALS_MAX_BLUE_ZONES ]; - - FT_UInt count_family; - PSH_Blue_ZoneRec zones_family[ PS_GLOBALS_MAX_BLUE_ZONES ]; - - FT_Fixed scale; - FT_Int org_shift; - FT_Int org_fuzz; - FT_Pos cur_shift; - FT_Pos cur_fuzz; - - } PSH_BluesRec, *PSH_Blues; - - /* standard and snap width */ typedef struct PSH_WidthRec_ { @@ -49,7 +38,7 @@ FT_BEGIN_HEADER FT_Pos cur; FT_Pos fit; - } PSH_WidthRec; + } PSH_WidthRec, *PSH_Width; /* standard and snap widths table */ @@ -69,6 +58,44 @@ FT_BEGIN_HEADER } PSH_DimensionRec, *PSH_Dimension; + + + /* blue zone descriptor */ + typedef struct PSH_Blue_ZoneRec_ + { + FT_Int org_ref; + FT_Int org_delta; + FT_Int org_top; + FT_Int org_bottom; + + FT_Pos cur_ref; + FT_Pos cur_delta; + FT_Pos cur_bottom; + FT_Pos cur_top; + + } PSH_Blue_ZoneRec, *PSH_Blue_Zone; + + + typedef struct PSH_Blue_TableRec_ + { + FT_UInt count; + PSH_Blue_ZoneRec zones[ PS_GLOBALS_MAX_BLUE_ZONES ]; + + } PSH_Blue_TableRec, *PSH_Blue_Table; + + + /* blue zones table */ + typedef struct PSH_BluesRec_ + { + PSH_Blue_TableRec normal_top; + PSH_Blue_TableRec normal_bottom; + PSH_Blue_TableRec family_top; + PSH_Blue_TableRec family_bottom; + FT_Fixed blue_scale; + + } PSH_BluesRec, *PSH_Blues; + + /* font globals */ typedef struct PSH_GlobalsRec_ { @@ -78,30 +105,38 @@ FT_BEGIN_HEADER } PSH_GlobalsRec, *PSH_Globals; + + typedef enum + { + PSH_BLUE_ALIGN_TOP = 1, + PSH_BLUE_ALIGN_BOT = 2 + + } PSH_Blue_Align; + + typedef struct + { + PSH_Blue_Align align; + FT_Pos align_top; + FT_Pos align_bot; + + } PSH_Blue_AlignementRec, *PSH_Blue_Alignement; - /* initialise font globals */ FT_LOCAL void - psh_globals_init( PSH_Globals globals, - FT_Memory memory ); + psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ); - /* reset font globals to new values */ - FT_LOCAL FT_Error - psh_globals_reset( PSH_Globals globals_hinter, - PS_Globals globals ); + /* snap a stem width to fitter coordinates */ + FT_LOCAL FT_Pos + psh_dimension_snap_width( PSH_Dimension dimension, + FT_Int org_width ); - /* change current scale transform */ + /* snap a stem to one or two blue zones */ FT_LOCAL void - psh_globals_set_scale( PSH_Globals globals_hinter, - FT_Fixed x_scale, - FT_Fixed x_delta, - FT_Fixed y_scale, - FT_Fixed y_delta ); - - /* finalize font globals */ - FT_LOCAL void - psh_globals_done( PSH_Globals globals ); - - /* */ + psh_blues_snap_stem( PSH_Blues blues, + FT_Int stem_top, + FT_Int stem_bot, + PSH_Blue_Alignement alignment ); + /* */ + FT_END_HEADER diff --git a/src/pshinter/pshinter.c b/src/pshinter/pshinter.c new file mode 100644 index 000000000..826ed69ae --- /dev/null +++ b/src/pshinter/pshinter.c @@ -0,0 +1,27 @@ +/***************************************************************************/ +/* */ +/* pshinter.c */ +/* */ +/* FreeType Postscript Hinting module */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include +#include "pshrec.c" +#include "pshglob.c" +#include "pshfit.c" +#include "pshmod.c" + +/* END */ diff --git a/src/pshinter/pshmod.c b/src/pshinter/pshmod.c new file mode 100644 index 000000000..f62b93cee --- /dev/null +++ b/src/pshinter/pshmod.c @@ -0,0 +1,114 @@ +/***************************************************************************/ +/* */ +/* pshmod.c */ +/* */ +/* FreeType Postscript hinter module implementation (body). */ +/* */ +/* Copyright 2000 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 +#include FT_INTERNAL_OBJECTS_H +#include "pshrec.h" + + typedef struct + { + FT_ModuleRec root; + PS_HintsRec ps_hints; + + PSH_Globals_FuncsRec globals_funcs; + T1_Hints_FuncsRec t1_funcs; + T2_Hints_FuncsRec t2_funcs; + + } PS_Hinter_ModuleRec, *PS_Hinter_Module; + + + /* finalize module */ + FT_CALLBACK_DEF void + ps_hinter_done( PS_Hinter_Module module ) + { + module->t1_funcs.hints = NULL; + module->t2_funcs.hints = NULL; + + ps_hints_done( &module->ps_hints ); + } + + + /* initialise module, create hints recorder and the interface */ + FT_CALLBACK_DEF FT_Error + ps_hinter_init( PS_Hinter_Module module ) + { + FT_Memory memory = module->root.memory; + + ps_hints_init( &module->ps_hints, memory ); + + psh_globals_funcs_init( &module->globals_funcs ); + + t1_hints_funcs_init( &module->t1_funcs ); + module->t1_funcs.hints = (T1_Hints) & module->ps_hints; + /* XXX: module->t1_funcs.apply = .... */ + + t2_hints_funcs_init( &module->t2_funcs ); + module->t2_funcs.hints = (T2_Hints) & module->ps_hints; + /* XXX: module->t2_funcs.apply = .... */ + + return 0; + } + + + /* returns global hints interface */ + FT_CALLBACK_DEF PSH_Globals_Funcs + pshinter_get_globals_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->globals_funcs; + } + + /* return Type 1 hints interface */ + FT_CALLBACK_DEF T1_Hints_Funcs + pshinter_get_t1_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->t1_funcs; + } + + /* return Type 2 hints interface */ + FT_CALLBACK_DEF T2_Hints_Funcs + pshinter_get_t2_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->t2_funcs; + } + + + FT_CALLBACK_DEF + PSHinter_Interface pshinter_interface = + { + pshinter_get_globals_funcs, + pshinter_get_t1_funcs, + pshinter_get_t2_funcs + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class pshinter_module_class = + { + 0, + sizeof( FT_ModuleRec ), + "pshinter", + 0x10000L, + 0x20000L, + + &pshinter_interface, /* module-specific interface */ + + (FT_Module_Constructor) ps_hinter_init, + (FT_Module_Destructor) ps_hinter_done, + (FT_Module_Requester) 0 /* no additional interface for now */ + }; + + \ No newline at end of file diff --git a/src/pshinter/pshmod.h b/src/pshinter/pshmod.h new file mode 100644 index 000000000..6bda325cc --- /dev/null +++ b/src/pshinter/pshmod.h @@ -0,0 +1,37 @@ +/***************************************************************************/ +/* */ +/* pshmod.h */ +/* */ +/* Postscript hinter module interface */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + +#ifndef __PS_HINTER_MODULE_H__ +#define __PS_HINTER_MODULE_H__ + + +#include +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Module_Class ) pshinter_module_class; + + +FT_END_HEADER + +#endif /* __PS_HINTER_MODULE_H__ */ + + +/* END */ diff --git a/src/pshinter/psrecord.c b/src/pshinter/pshrec.c similarity index 86% rename from src/pshinter/psrecord.c rename to src/pshinter/pshrec.c index 6d1b97f4f..fea4ba37a 100644 --- a/src/pshinter/psrecord.c +++ b/src/pshinter/pshrec.c @@ -1,4 +1,8 @@ -#include "psrecord.h" +#include +#include FT_FREETYPE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include "pshrec.h" /***********************************************************************/ /***********************************************************************/ @@ -13,7 +17,7 @@ ps_hint_table_done( PS_Hint_Table table, FT_Memory memory ) { - FT_FREE( table->hints ); + FREE( table->hints ); table->num_hints = 0; table->max_hints = 0; } @@ -33,7 +37,7 @@ { /* try to grow the table */ new_max = ( new_max + 7 ) & -8; - if ( !FT_REALLOC_ARRAY( table->hints, old_max, new_max, PS_HintRec ) ) + if ( !REALLOC_ARRAY( table->hints, old_max, new_max, PS_HintRec ) ) table->max_hints = new_max; } return error; @@ -58,10 +62,10 @@ if (error) goto Exit; } - hint = table->hints + count-1; - hint->org_pos = 0; - hint->org_len = 0; - hint->flags = 0; + hint = table->hints + count-1; + hint->pos = 0; + hint->len = 0; + hint->flags = 0; table->num_hints = count; @@ -84,7 +88,7 @@ ps_mask_done( PS_Mask mask, FT_Memory memory ) { - FT_FREE( mask->bytes ); + FREE( mask->bytes ); mask->num_bits = 0; mask->max_bits = 0; mask->end_point = 0; @@ -104,7 +108,7 @@ if ( new_max > old_max ) { new_max = ( new_max + 7 ) & -8; - if ( !FT_REALLOC_ARRAY( mask->bytes, old_max, new_max, FT_Byte ) ) + if ( !REALLOC_ARRAY( mask->bytes, old_max, new_max, FT_Byte ) ) mask->max_bits = new_max*8; } return error; @@ -117,7 +121,7 @@ ps_mask_test_bit( PS_Mask mask, FT_Int index ) { - if ( index < 0 || index >= mask->num_bits ) + if ( (FT_UInt)index >= mask->num_bits ) return 0; return mask->bytes[index >> 3] & (0x80 >> (index & 7)); @@ -131,7 +135,7 @@ { FT_Byte* p; - if ( index < 0 || index >= mask->num_bits ) + if ( (FT_UInt)index >= mask->num_bits ) return; p = mask->bytes + (index >> 3); @@ -151,7 +155,7 @@ if ( index < 0 ) goto Exit; - if ( index >= mask->num_bits ) + if ( (FT_UInt)index >= mask->num_bits ) { error = ps_mask_ensure( mask, index, memory ); if (error) goto Exit; @@ -176,7 +180,7 @@ for ( ; count > 0; count--, mask++ ) ps_mask_done( mask, memory ); - FT_FREE( table->masks ); + FREE( table->masks ); table->num_masks = 0; table->max_masks = 0; } @@ -195,7 +199,7 @@ if ( new_max > old_max ) { new_max = (new_max+7) & -8; - if ( !FT_REALLOC_ARRAY( table->masks, old_max, new_max, PS_MaskRec ) ) + if ( !REALLOC_ARRAY( table->masks, old_max, new_max, PS_MaskRec ) ) table->max_masks = new_max; } return error; @@ -238,7 +242,7 @@ FT_Memory memory, PS_Mask *amask ) { - FT_Error error; + FT_Error error = 0; FT_UInt count; PS_Mask mask; @@ -267,7 +271,6 @@ { FT_Error error = 0; PS_Mask mask; - FT_UInt count; /* allocate new mask, and grow it to "bit_count" bits */ error = ps_mask_table_alloc( table, memory, &mask ); @@ -286,7 +289,7 @@ FT_Int wmask = 0x80; FT_Int val; - for ( ; source_bits > 0; source_bits-- ) + for ( ; bit_count > 0; bit_count-- ) { val = write[0] & ~wmask; @@ -325,7 +328,7 @@ PS_Mask mask1 = table->masks + index1; PS_Mask mask2 = table->masks + index2; FT_Byte* p1 = mask1->bytes; - FT_Byte* p2 = mask2->bytes, + FT_Byte* p2 = mask2->bytes; FT_UInt count1 = mask1->num_bits; FT_UInt count2 = mask2->num_bits; FT_UInt count; @@ -365,7 +368,7 @@ index2 = index1; } - if ( index1 < index2 && index1 >= 0 && index2 < table->num_masks ) + if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks ) { /* we need to merge the bitsets of index1 and index2 with a */ /* simple union.. */ @@ -406,7 +409,7 @@ /* now, remove "mask2" from the list, we need to keep the masks */ /* sorted in order of importance, so move table elements.. */ - mask2->num_bytes = 0; + mask2->num_bits = 0; mask2->end_point = 0; delta = table->num_masks-1 - index2; /* number of masks to move */ @@ -445,7 +448,7 @@ { if ( ps_mask_table_test_intersect( table, index1, index2 ) ) { - error = ps_mask_table_merge( table, index2, index1, memory ) ); + error = ps_mask_table_merge( table, index2, index1, memory ); if (error) goto Exit; break; @@ -460,7 +463,7 @@ /***********************************************************************/ /***********************************************************************/ /***** *****/ - /***** PS_DIMENSION MANAGEMENT *****/ + /***** PS_DIMENSION MANAGEMENT *****/ /***** *****/ /***********************************************************************/ /***********************************************************************/ @@ -487,6 +490,7 @@ } +#if 0 /* set a bit at a given index in the current hint mask */ static FT_Error ps_dimension_set_mask_bit( PS_Dimension dim, @@ -505,14 +509,14 @@ Exit: return error; } - +#endif /* set the end point in a mask, called from "End" & "Reset" methods */ static void ps_dimension_end_mask( PS_Dimension dim, FT_UInt end_point ) { - FT_UInt count = dimension->masks.num_masks; + FT_UInt count = dim->masks.num_masks; PS_Mask mask; if ( count > 0 ) @@ -536,7 +540,7 @@ ps_dimension_end_mask( dim, end_point ); /* allocate new one */ - return ps_mask_table_alloc( dim->masks, memory, &mask ); + return ps_mask_table_alloc( &dim->masks, memory, &mask ); } @@ -550,7 +554,6 @@ FT_Memory memory ) { FT_Error error = 0; - PS_Mask mask; /* reset current mask, if any */ error = ps_dimension_reset_mask( dim, end_point, memory ); @@ -585,6 +588,7 @@ flags |= PS_HINT_FLAG_BOTTOM; pos += len; } + len = 0; } if (aindex) @@ -599,7 +603,7 @@ for ( index = 0; index < max; index++, hint++ ) { - if ( hint->org_pos == pos && hint->org_len == len ) + if ( hint->pos == pos && hint->len == len ) break; } @@ -609,9 +613,9 @@ error = ps_hint_table_alloc( &dim->hints, memory, &hint ); if (error) goto Exit; - hint->org_pos = pos; - hint->org_len = len; - hint->flags = flags; + hint->pos = pos; + hint->len = len; + hint->flags = flags; } /* now, store the hint in the current mask */ @@ -697,25 +701,36 @@ /* destroy hints */ - static void - ps_hints_done( PS_Hints hints, - FT_Memory memory ) + FT_LOCAL void + ps_hints_done( PS_Hints hints ) { + FT_Memory memory = hints->memory; + ps_dimension_done( &hints->dimension[0], memory ); ps_dimension_done( &hints->dimension[1], memory ); - hints->error = 0; + + hints->error = 0; + hints->memory = 0; } + FT_LOCAL FT_Error + ps_hints_init( PS_Hints hints, + FT_Memory memory ) + { + memset( hints, 0, sizeof(*hints) ); + hints->memory = memory; + return 0; + } /* initialise a hints for a new session */ static void - ps_hints_rewind( PS_Hints hints, - PS_Hint_Type hint_type ) + ps_hints_open( PS_Hints hints, + PS_Hint_Type hint_type ) { switch (hint_type) { - case PS_Hint_Type_1: - case PS_Hint_Type_2: + case PS_HINT_TYPE_1: + case PS_HINT_TYPE_2: { hints->error = 0; hints->hint_type = hint_type; @@ -755,14 +770,15 @@ /* record the stems in the current hints/masks table */ switch ( hints->hint_type ) { - case PS_Hint_Type_1: /* Type 1 "hstem" or "vstem" operator */ - case PS_Hint_Type_2: /* Type 2 "hstem" or "vstem" operator */ + case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */ + case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */ { PS_Dimension dim = &hints->dimension[dimension]; for ( ; count > 0; count--, stems += 2 ) { - FT_Error error; + FT_Error error; + FT_Memory memory = hints->memory; error = ps_dimension_add_t1stem( dim, stems[0], stems[1], memory, NULL ); @@ -782,6 +798,7 @@ FT_ERROR(( "t1f.hints.stem: called with invalid hint type (%d)\n", hints->hint_type )); ; + } } } @@ -792,6 +809,8 @@ FT_Int dimension, FT_Int* stems ) { + FT_Error error = 0; + if (!hints->error) { PS_Dimension dim; @@ -810,13 +829,13 @@ dim = &hints->dimension[dimension]; /* there must be 6 elements in the 'stem' array */ - if ( hints->hint_type == PS_Hint_Type_1 ) + if ( hints->hint_type == PS_HINT_TYPE_1 ) { /* add the three stems to our hints/masks table */ for ( count = 0; count < 3; count++, stems += 2 ) { error = ps_dimension_add_t1stem( dim, stems[0], stems[1], - &index[count], memory ); + memory, &index[count] ); if (error) goto Fail; } @@ -847,11 +866,13 @@ ps_hints_t1reset( PS_Hints hints, FT_UInt end_point ) { + FT_Error error = 0; + if ( !hints->error ) { FT_Memory memory = hints->memory; - if ( hints->hint_type == PS_Hint_Type_1 ) + if ( hints->hint_type == PS_HINT_TYPE_1 ) { error = ps_dimension_reset_mask( &hints->dimension[0], end_point, memory ); @@ -887,12 +908,12 @@ if ( !hints->error ) { PS_Dimension dim = hints->dimension; - FT_Memory memory = hints->memory; - FT_UInt count1 = dim[0].hints.num_hints; - FT_UInt count2 = dim[1].hints.num_hints; + FT_Memory memory = hints->memory; + FT_UInt count1 = dim[0].hints.num_hints; + FT_UInt count2 = dim[1].hints.num_hints; /* check bit count, must be equal to current total hint count */ - if ( (FT_Int)bit_count != count1 + count2 ) + if ( bit_count != count1 + count2 ) { error = FT_Err_Invalid_Argument; FT_ERROR(( "%s: called with invalid bitcount %d (instead of %d)\n", @@ -901,12 +922,12 @@ } /* set-up new horizontal and vertical hint mask now */ - error = ps_dimension_set_mask( &dim[0], mask, 0, count1, - end_point, memory ); + error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, + end_point, memory ); if (error) goto Fail; - error = ps_dimension_set_mask( &dim[1], mask, count1, count2, - end_point, memory ); + error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, + end_point, memory ); if (error) goto Fail; } return; @@ -919,19 +940,19 @@ static void ps_hints_t2counter( PS_Hints hints, FT_UInt bit_count, - const FT_Byte* mask ) + const FT_Byte* bytes ) { FT_Error error; if ( !hints->error ) { PS_Dimension dim = hints->dimension; - FT_Memory memory = hints->memory; - FT_UInt count1 = dim[0].hints.num_hints; - FT_UInt count2 = dim[1].hints.num_hints; + FT_Memory memory = hints->memory; + FT_UInt count1 = dim[0].hints.num_hints; + FT_UInt count2 = dim[1].hints.num_hints; /* check bit count, must be equal to current total hint count */ - if ( (FT_Int)bit_count != count1 + count2 ) + if ( bit_count != count1 + count2 ) { error = FT_Err_Invalid_Argument; FT_ERROR(( "%s: called with invalid bitcount %d (instead of %d)\n", @@ -940,12 +961,12 @@ } /* set-up new horizontal and vertical hint mask now */ - error = ps_dimension_set_mask_bits( &dim[0], mask, 0, count1, - end_point, memory ); + error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, + 0, memory ); if (error) goto Fail; - error = ps_dimension_set_mask_bits( &dim[1], mask, count1, count2, - end_point, memory ); + error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, + 0, memory ); if (error) goto Fail; } return; @@ -990,7 +1011,7 @@ static void t1_hints_open( T1_Hints hints ) { - ps_hints_open( (PS_Hints)hints, ps_hints_type_1 ); + ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); } static void @@ -1002,15 +1023,20 @@ } - - static const T1_Hints_FuncsRec pshinter_t1_hints_funcs = + FT_LOCAL_DEF void + t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) { - (T1_Hints_OpenFunc) t1_hints_open, - (T1_Hints_CloseFunc) ps_hints_close, - (T1_Hints_SetStemFunc) t1_hints_set_stem, - (T1_Hints_SetStem3Func) ps_hints_t1stem3, - (T1_Hints_ResetFunc) ps_hints_t1reset - }; + memset( (char*)funcs, 0, sizeof(*funcs) ); + + funcs->open = (T1_Hints_OpenFunc) t1_hints_open; + funcs->close = (T1_Hints_CloseFunc) ps_hints_close; + funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; + funcs->stem3 = (T1_Hints_SetStem3Func) ps_hints_t1stem3; + funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; + + /* funcs->apply = .... */ + } + /***********************************************************************/ @@ -1024,7 +1050,7 @@ static void t2_hints_open( T2_Hints hints ) { - ps_hints_open( (PS_Hints)hints, ps_hints_type_2 ); + ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 ); } static void @@ -1034,7 +1060,6 @@ FT_Fixed* coords ) { FT_Int stems[32], n, total = count; - FT_Fixed* read; while (total > 0) { @@ -1055,13 +1080,18 @@ } - static const T2_Hints_FuncsRec pshinter_t2_hints_funcs = + FT_LOCAL_DEF void + t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) { - (T2_Hints_OpenFunc) t2_hints_open, - (T2_Hints_CloseFunc) ps_hints_close, - (T2_Hints_StemsFunc) t2_hints_stems, - (T2_Hints_MaskFunc) ps_hints_t2mask, - (T2_Hints_CounterFunc) ps_hints_t2counter - }; + memset( funcs, 0, sizeof(*funcs) ); + + funcs->open = (T2_Hints_OpenFunc) t2_hints_open; + funcs->close = (T2_Hints_CloseFunc) ps_hints_close; + funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; + funcs->hintmask = (T2_Hints_MaskFunc) ps_hints_t2mask; + funcs->counter = ( T2_Hints_CounterFunc) ps_hints_t2counter; + + /* funcs->apply = .... */ + } \ No newline at end of file diff --git a/src/pshinter/pshrec.h b/src/pshinter/pshrec.h new file mode 100644 index 000000000..84c9dfdc1 --- /dev/null +++ b/src/pshinter/pshrec.h @@ -0,0 +1,152 @@ +/***************************************************************************/ +/* */ +/* pshrec.h */ +/* */ +/* Postscript (Type 1/Type 2) hints recorder. */ +/* */ +/* Copyright 2001 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. */ +/* */ +/* */ +/* The functions defined here are called from hte Type 1, CID and CFF */ +/* font drivers to record the hints of a given character/glyph. */ +/* */ +/* The hints are recorded in a unified format, and are later processed */ +/* by the "optimiser" and "fitter" to adjust the outlines to the pixel */ +/* grid. */ +/* */ +/***************************************************************************/ + +#ifndef __PS_HINTER_RECORD_H__ +#define __PS_HINTER_RECORD_H__ + +#include +#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include "pshglob.h" + +FT_BEGIN_HEADER + + /**********************************************************************/ + /**********************************************************************/ + /***** *****/ + /***** GLYPH HINTS RECORDER INTERNALS *****/ + /***** *****/ + /**********************************************************************/ + /**********************************************************************/ + + /* handle to hint record */ + typedef struct PS_HintRec_* PS_Hint; + + /* hint types */ + typedef enum + { + PS_HINT_TYPE_1 = 1, + PS_HINT_TYPE_2 = 2 + + } PS_Hint_Type; + + /* hint flags */ + typedef enum + { + PS_HINT_FLAG_GHOST = 1, + PS_HINT_FLAG_BOTTOM = 2 + + } PS_Hint_Flags; + + /* hint descriptor */ + typedef struct PS_HintRec_ + { + FT_Int pos; + FT_Int len; + FT_UInt flags; + + } PS_HintRec; + + +#define ps_hint_is_active(x) ((x)->flags & PS_HINT_FLAG_ACTIVE) +#define ps_hint_is_ghost(x) ((x)->flags & PS_HINT_FLAG_GHOST) +#define ps_hint_is_bottom(x) ((x)->flags & PS_HINT_FLAG_BOTTOM) + + + /* hints table descriptor */ + typedef struct PS_Hint_TableRec_ + { + FT_UInt num_hints; + FT_UInt max_hints; + PS_Hint hints; + + } PS_Hint_TableRec, *PS_Hint_Table; + + + /* hint and counter mask descriptor */ + typedef struct PS_MaskRec_ + { + FT_UInt num_bits; + FT_UInt max_bits; + FT_Byte* bytes; + FT_UInt end_point; + + } PS_MaskRec, *PS_Mask; + + + /* masks and counters table descriptor */ + typedef struct PS_Mask_TableRec_ + { + FT_UInt num_masks; + FT_UInt max_masks; + PS_Mask masks; + + } PS_Mask_TableRec, *PS_Mask_Table; + + + /* dimension-specific hints descriptor */ + typedef struct PS_DimensionRec_ + { + PS_Hint_TableRec hints; + PS_Mask_TableRec masks; + PS_Mask_TableRec counters; + + } PS_DimensionRec, *PS_Dimension; + + + /* magic value used within PS_HintsRec */ +#define PS_HINTS_MAGIC 0x68696e74 /* "hint" */ + + + /* glyph hints descriptor */ + typedef struct PS_HintsRec_ + { + FT_Memory memory; + FT_Error error; + FT_UInt32 magic; + PS_Hint_Type hint_type; + PS_DimensionRec dimension[2]; + + } PS_HintsRec, *PS_Hints; + + /* */ + + FT_LOCAL void + ps_hints_done( PS_Hints hints ); + + FT_LOCAL FT_Error + ps_hints_init( PS_Hints hints, + FT_Memory memory ); + + FT_LOCAL void + t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ); + + FT_LOCAL void + t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ); + + /* */ + +FT_END_HEADER + +#endif /* __PS_HINTER_RECORD_H__ */ diff --git a/src/pshinter/psrecord.h b/src/pshinter/psrecord.h deleted file mode 100644 index 06abd387e..000000000 --- a/src/pshinter/psrecord.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef __PSRECORD_H_ -#define __PSRECORD_H__ - -#include FT_INTERNAL_POSTSCRIPT_HINTS_H - -FT_BEGIN_HEADER - - /**********************************************************************/ - /**********************************************************************/ - /***** *****/ - /***** GLYPH HINTS RECORDER INTERNALS *****/ - /***** *****/ - /**********************************************************************/ - /**********************************************************************/ - - /* handle to hint record */ - typedef struct PS_HintRec_* PS_Hint; - - /* hint flags */ - typedef enum - { - PS_HINT_FLAG_ACTIVE = 1, - PS_HINT_FLAG_GHOST = 2, - PS_HINT_FLAG_BOTTOM = 4 - - } PS_Hint_Flags; - - /* hint descriptor */ - typedef struct PS_HintRec_ - { - FT_Int org_pos; - FT_Int org_len; - FT_UInt flags; - -#if 0 - FT_Pos cur_pos; - FT_Pos cur_len; - - PS_Hint parent; - - FT_Fixed interp_scale; - FT_Fixed interp_delta; -#endif - - } PS_HintRec; - - -#define ps_hint_is_active(x) ((x)->flags & PS_HINT_FLAG_ACTIVE) -#define ps_hint_is_ghost(x) ((x)->flags & PS_HINT_FLAG_GHOST) -#define ps_hint_is_bottom(x) ((x)->flags & PS_HINT_FLAG_BOTTOM) - - - /* hints table descriptor */ - typedef struct PS_Hint_TableRec_ - { - FT_UInt num_hints; - FT_UInt max_hints; - PS_Hint hints; - - } PS_Hint_TableRec, *PS_Hint_Table; - - - /* hint and counter mask descriptor */ - typedef struct PS_MaskRec_ - { - FT_UInt num_bits; - FT_UInt max_bits; - FT_Byte* bytes; - FT_UInt end_point; - - } PS_MaskRec, *PS_Mask; - - - /* masks and counters table descriptor */ - typedef struct PS_Mask_TableRec_ - { - FT_UInt num_masks; - FT_UInt max_masks; - PS_Mask masks; - - } PS_Mask_TableRec, *PS_Mask_Table; - - - /* dimension-specific hints descriptor */ - typedef struct PS_DimensionRec_ - { - PS_Hint_TableRec hints; - PS_Mask_TableRec masks; - PS_Mask_TableRec counters; - - } PS_DimensionRec, *PS_Dimension; - - - /* magic value used within PS_HintsRec */ -#define PS_HINTS_MAGIC 0x68696e74 /* "hint" */ - - - /* glyph hints descriptor */ - typedef struct PS_HintsRec_ - { - FT_Memory memory; - FT_Error error; - FT_UInt32 magic; - PS_Hint_Type hint_type; - PS_DimensionRec dimension[2]; - - } PS_HintsRec; - - /* */ - -FT_END_HEADER - -#endif /* __T1_FITTER_HINTS_H__ */ diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c index c83a5019f..16e545ff0 100644 --- a/src/type1/t1driver.c +++ b/src/type1/t1driver.c @@ -301,10 +301,10 @@ (FTDriver_initFace) T1_Init_Face, (FTDriver_doneFace) T1_Done_Face, - (FTDriver_initSize) 0, - (FTDriver_doneSize) 0, - (FTDriver_initGlyphSlot)0, - (FTDriver_doneGlyphSlot)0, + (FTDriver_initSize) T1_Init_Size, + (FTDriver_doneSize) T1_Done_Size, + (FTDriver_initGlyphSlot)T1_Init_GlyphSlot, + (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot, (FTDriver_setCharSizes) 0, (FTDriver_setPixelSizes)0, diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c index 1e074450e..5c064e1e2 100644 --- a/src/type1/t1objs.c +++ b/src/type1/t1objs.c @@ -45,6 +45,88 @@ #define FT_COMPONENT trace_t1objs + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + FT_LOCAL_DEF + void T1_Done_Size( T1_Size size ) + { + if ( size->size_hints ) + { + PSHinter_Interface* pshinter; + PSH_Globals_Funcs funcs; + T1_Face face; + + face = (T1_Face) size->root.face; + pshinter = face->pshinter; + funcs = pshinter->get_globals_funcs( (FT_Module) face->root.driver ); + funcs->destroy( (PSH_Globals) size->size_hints ); + + size->size_hints = 0; + } + } + + + FT_LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ) + { + PSHinter_Interface* pshinter; + T1_Face face; + FT_Error error = 0; + + face = (T1_Face) size->root.face; + pshinter = face->pshinter; + if ( pshinter && pshinter->get_globals_funcs ) + { + PSH_Globals_Funcs funcs; + PSH_Globals globals; + + funcs = pshinter->get_globals_funcs( (FT_Module) face->root.driver ); + if (funcs) + { + error = funcs->create( face->root.memory, &globals ); + if (!error) + size->size_hints = globals; + } + } + return error; + } + + /*************************************************************************/ + /* */ + /* SLOT FUNCTIONS */ + /* */ + /*************************************************************************/ + + FT_LOCAL_DEF void + T1_Done_GlyphSlot( T1_GlyphSlot slot ) + { + slot->root.internal->glyph_hints = 0; + } + + + FT_LOCAL_DEF FT_Error + T1_Init_GlyphSlot( T1_GlyphSlot slot ) + { + T1_Face face; + PSHinter_Interface* pshinter; + + face = (T1_Face) slot->root.face; + pshinter = face->pshinter; + if (pshinter) + { + T1_Hints_Funcs funcs; + + funcs = pshinter->get_t1_funcs( (FT_Module)face->root.driver ); + slot->root.internal->glyph_hints = (void*)funcs; + } + return 0; + } + + /*************************************************************************/ /* */ /* FACE FUNCTIONS */ @@ -124,6 +206,7 @@ } + /*************************************************************************/ /* */ /* */ @@ -154,9 +237,10 @@ FT_Int num_params, FT_Parameter* params ) { - FT_Error error; - PSNames_Interface* psnames; - PSAux_Interface* psaux; + FT_Error error; + PSNames_Interface* psnames; + PSAux_Interface* psaux; + PSHinter_Interface* pshinter; FT_UNUSED( num_params ); FT_UNUSED( params ); @@ -184,6 +268,15 @@ face->psaux = psaux; } + pshinter = (PSHinter_Interface*)face->pshinter; + if ( !pshinter ) + { + pshinter = (PSHinter_Interface*) + FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "pshinter" ); + + face->pshinter = pshinter; + } + /* open the tokenizer, this will also check the font format */ error = T1_Open_Face( face ); if ( error ) diff --git a/src/type1/t1objs.h b/src/type1/t1objs.h index 810380a03..c736868bf 100644 --- a/src/type1/t1objs.h +++ b/src/type1/t1objs.h @@ -100,12 +100,9 @@ FT_BEGIN_HEADER /* */ typedef struct T1_SizeRec_ { - FT_SizeRec root; - FT_Bool valid; - T1_Size_Hints* hints; /* defined in the hinter. This allows */ - /* us to experiment with different */ - /* hinting schemes without having to */ - /* change `t1objs' each time. */ + FT_SizeRec root; + void* size_hints; /* defined for hinting engines */ + } T1_SizeRec; @@ -130,8 +127,6 @@ FT_BEGIN_HEADER FT_Fixed x_scale; FT_Fixed y_scale; - T1_Glyph_Hints* hints; /* defined in the hinter */ - } T1_GlyphSlotRec; @@ -145,6 +140,18 @@ FT_BEGIN_HEADER FT_LOCAL void T1_Done_Face( T1_Face face ); + FT_LOCAL + FT_Error T1_Init_Size( T1_Size size ); + + FT_LOCAL + void T1_Done_Size( T1_Size size ); + + FT_LOCAL + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot ); + + FT_LOCAL + void T1_Done_GlyphSlot( T1_GlyphSlot slot ); + FT_LOCAL FT_Error T1_Init_Driver( T1_Driver driver );