diff --git a/ChangeLog b/ChangeLog index 40e12f5b9..fcd8ddad1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2001-12-12 David Turner + + * src/pshint/pshglob.c: adding correct BlueScale/BlueShift support, + plus family blues processing + + * src/cff/cffgload.c: started adding support for the Postscript hinter + 2001-12-12 Werner Lemberg * builds/unix/freetype2.m4: Some portability fixes. diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 508f2fadf..2e8c55aaf 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -23,6 +23,7 @@ #include FT_INTERNAL_SFNT_H #include FT_OUTLINE_H #include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H #include "cffload.h" #include "cffgload.h" @@ -701,6 +702,7 @@ FT_Fixed seed; FT_Fixed* stack; + T2_Hints_Funcs hinter; /* set default width */ decoder->num_hints = 0; @@ -720,6 +722,8 @@ zone = decoder->zones; stack = decoder->top; + hinter = (T2_Hints_Funcs) builder->hints_funcs; + builder->path_begun = 0; zone->base = charstring_base; @@ -731,6 +735,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 ) { @@ -1053,24 +1061,41 @@ case cff_op_vstem: case cff_op_hstemhm: case cff_op_vstemhm: - /* if the number of arguments is not even, the first one */ - /* is simply the glyph width, encoded as the difference */ - /* to nominalWidthX */ + /* the number of arguments is always even here */ FT_TRACE4(( op == cff_op_hstem ? " hstem" : - op == cff_op_vstem ? " vstem" : - op == cff_op_hstemhm ? " hstemhm" : - " vstemhm" )); + ( op == cff_op_vstem ? " vstem" : + ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" )) )); + + if ( hinter ) + hinter->stems( hinter->hints, + ( op == cff_op_vstem || op == cff_op_vstemhm ), + num_args/2, + args ); + decoder->num_hints += num_args / 2; args = stack; break; + case cff_op_hintmask: case cff_op_cntrmask: - FT_TRACE4(( op == cff_op_hintmask ? " hintmask" - : " cntrmask" )); + FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); decoder->num_hints += num_args / 2; + if ( hinter ) + { + if ( op == cff_op_hintmask ) + hinter->hintmask( hinter->hints, + builder->current->n_points, + (decoder->num_hints+7) >> 3, + ip ); + else + hinter->counter( hinter->hints, + (decoder->num_hints+7) >> 3, + ip ); + } + #ifdef FT_DEBUG_LEVEL_TRACE { FT_UInt maskbyte; @@ -1617,6 +1642,18 @@ close_contour( builder ); + /* close hints recording session */ + if ( hinter ) + { + if (hinter->close( hinter->hints, builder->current->n_points )) + goto Syntax_Error; + + /* apply hints to the loaded glyph outline now */ + hinter->apply( hinter->hints, + builder->current, + (PSH_Globals)builder->hints_globals ); + } + /* add current outline to the glyph slot */ FT_GlyphLoader_Add( builder->loader ); diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h index 187ed707b..d100bd02e 100644 --- a/src/cff/cffgload.h +++ b/src/cff/cffgload.h @@ -112,6 +112,9 @@ FT_BEGIN_HEADER FT_Error error; /* only used for memory errors */ FT_Bool metrics_only; + void* hints_funcs; /* hinter-specific */ + void* hints_globals; /* hinter-specific */ + } CFF_Builder; diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c index 7162d0aec..406ca11e4 100644 --- a/src/pshinter/pshglob.c +++ b/src/pshinter/pshglob.c @@ -345,6 +345,50 @@ FT_UInt num; PSH_Blue_Table table = 0; + /* */ + /* determine wether we need to suppress overshoots or not */ + /* we simply need to compare the vertical scale parameter */ + /* to the raw bluescale value. Here's why */ + /* */ + /* we need to suppress overshoots for all pointsizes */ + /* at 300dpi that satisfy: */ + /* */ + /* pointsize < 240*bluescale + 0.49 */ + /* */ + /* this corresponds to: */ + /* */ + /* pixelsize < 1000*bluescale + 49/24 */ + /* */ + /* scale*EM_Size < 1000*bluescale + 49/24 */ + /* */ + /* however, for normal Type 1 fonts, EM_Size is 1000 !! */ + /* we thus only check: */ + /* */ + /* scale < bluescale + 49/24000 */ + /* */ + /* which we shorten to */ + /* */ + /* "scale < bluescale" */ + /* */ + blues->no_overshoots = FT_BOOL( scale < blues->blue_scale ); + + /* */ + /* the blue threshold is the font units distance under */ + /* which overshoots are suppressed due to the BlueShift */ + /* even if the scale is greater than BlueScale */ + /* */ + /* it's the smallest distance such that */ + /* */ + /* dist <= BlueShift && dist*scale <= 0.5 pixels */ + /* */ + { + FT_Int threshold = blues->blue_shift; + + while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) + threshold --; + + blues->blue_threshold = threshold; + } for ( num = 0; num < 4; num++ ) { @@ -388,7 +432,46 @@ } } - /* XXX: we should process the family / normal tables here! */ + /* process the families now */ + for ( num = 0; num < 2; num++ ) + { + PSH_Blue_Zone zone1, zone2; + FT_UInt count1, count2; + PSH_Blue_Table normal, family; + + switch (num) + { + case 0: + normal = &blues->normal_top; + family = &blues->family_top; + break; + + default: + normal = &blues->normal_bottom; + family = &blues->family_bottom; + } + + zone1 = normal->zones; + count1 = normal->count; + for ( ; count1 > 0; count1--, zone1++ ) + { + /* try to find a family zone whose reference position is less */ + /* than 1 pixel far from the current zone.. */ + zone2 = family->zones; + count2 = family->count; + for ( ; count2 > 0; count2--, zone2++ ) + { + if ( FT_MulFix( zone1->org_ref - zone2->org_ref, scale ) < 64 ) + { + zone1->cur_top = zone2->cur_top; + zone1->cur_bottom = zone2->cur_bottom; + zone1->cur_ref = zone2->cur_ref; + zone1->cur_delta = zone2->cur_delta; + break; + } + } + } + } } @@ -400,11 +483,15 @@ { PSH_Blue_Table table; FT_UInt count; + FT_Pos delta; PSH_Blue_Zone zone; + FT_Int no_shoots; alignment->align = 0; + no_shoots = blues->no_overshoots; + /* lookup stem top in top zones table */ table = &blues->normal_top; count = table->count; @@ -412,13 +499,17 @@ for ( ; count > 0; count--, zone++ ) { - if ( stem_top < zone->org_bottom ) + delta = stem_top - zone->org_bottom; + if ( delta < 0 ) break; if ( stem_top <= zone->org_top ) { - alignment->align |= PSH_BLUE_ALIGN_TOP; - alignment->align_top = zone->cur_ref; + if ( no_shoots || delta <= blues->blue_threshold ) + { + alignment->align |= PSH_BLUE_ALIGN_TOP; + alignment->align_top = zone->cur_ref; + } break; } } @@ -426,17 +517,21 @@ /* look up stem bottom in bottom zones table */ table = &blues->normal_bottom; count = table->count; - zone = table->zones; + zone = table->zones + count-1; - for ( ; count > 0; count--, zone++ ) + for ( ; count > 0; count--, zone-- ) { - if ( stem_bot < zone->org_bottom ) + delta = zone->org_top - stem_bot; + if ( delta < 0 ) break; - if ( stem_bot <= zone->org_top ) + if ( stem_bot >= zone->org_bottom ) { - alignment->align |= PSH_BLUE_ALIGN_BOT; - alignment->align_bot = zone->cur_ref; + if ( no_shoots || delta < blues->blue_shift ) + { + alignment->align |= PSH_BLUE_ALIGN_BOT; + alignment->align_bot = zone->cur_ref; + } break; } } @@ -543,6 +638,11 @@ priv->family_blues, priv->num_family_other_blues, priv->family_other_blues, priv->blue_fuzz, 1 ); + globals->blues.blue_scale = priv->blue_scale ? priv->blue_scale + : (0.039625*0x400000L); + + globals->blues.blue_shift = priv->blue_shift; + globals->dimension[0].scale_mult = 0; globals->dimension[0].scale_delta = 0; globals->dimension[1].scale_mult = 0; diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h index b34f32f79..569e6e7c2 100644 --- a/src/pshinter/pshglob.h +++ b/src/pshinter/pshglob.h @@ -120,7 +120,11 @@ FT_BEGIN_HEADER PSH_Blue_TableRec normal_bottom; PSH_Blue_TableRec family_top; PSH_Blue_TableRec family_bottom; + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_threshold; + FT_Bool no_overshoots; } PSH_BluesRec, *PSH_Blues;