ref: 2b30c17fd389586fe8955b9346fc665f73accb30
parent: 2f5d1b76ca4d2c6d4b9a814d9261bc634ef3a3ef
author: David Turner <[email protected]>
date: Wed Dec 12 11:07:29 EST 2001
* src/pshint/pshglob.c: adding correct BlueScale/BlueShift support, plus family blues processing * src/cff/cffgload.c: started adding support for the Postscript hinter
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2001-12-12 David Turner <[email protected]>
+
+ * 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 <[email protected]>
* builds/unix/freetype2.m4: Some portability fixes.
--- 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;
@@ -1616,6 +1641,18 @@
error = CFF_Err_Ok;
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 );
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -112,6 +112,9 @@
FT_Error error; /* only used for memory errors */
FT_Bool metrics_only;
+ void* hints_funcs; /* hinter-specific */
+ void* hints_globals; /* hinter-specific */
+
} CFF_Builder;
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -345,7 +345,51 @@
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++ )
{
PSH_Blue_Zone zone;
@@ -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;
}
}
@@ -542,6 +637,11 @@
psh_blues_set_zones( &globals->blues, priv->num_family_blues,
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;
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -120,7 +120,11 @@
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;