Commit fbb76171 authored by David Turner's avatar David Turner
Browse files

updates to the Postscript hinter, some _big_ bugs have been

fixed, and the results are now a bit more decent.., but there
are still problems I can't explain just yet

(I guess some information from the Private dictionary is not
 processed correctly !!)
parent 9f781c41
......@@ -22,143 +22,11 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_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;
/**********************************************************************/
/**********************************************************************/
/***** *****/
......@@ -170,11 +38,9 @@ FT_BEGIN_HEADER
typedef struct PSH_GlobalsRec_* PSH_Globals;
typedef FT_Error (*PSH_Globals_NewFunc)( FT_Memory memory,
T1_Private* private_dict,
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,
......@@ -186,7 +52,6 @@ FT_BEGIN_HEADER
typedef struct
{
PSH_Globals_NewFunc create;
PSH_Globals_ResetFunc reset;
PSH_Globals_SetScaleFunc set_scale;
PSH_Globals_DestroyFunc destroy;
......
......@@ -994,7 +994,10 @@
/* record horizontal hint */
if ( hinter )
{
/* top[0] += builder->left_bearing.y; */
hinter->stem( hinter->hints, 0, top );
}
break;
......@@ -1012,7 +1015,10 @@
/* record vertical hint */
if ( hinter )
{
top[0] += builder->left_bearing.x;
hinter->stem( hinter->hints, 1, top );
}
break;
......
......@@ -481,7 +481,7 @@
{
FT_Pos x, *px;
px = vertical ? &vec->y : &vec->x;
px = vertical ? &vec->x : &vec->y;
x = *px;
*px = psh_hint_table_tune_coord( table, (FT_Int)x );
......@@ -501,12 +501,12 @@
if ( vertical )
{
for ( ; count > 0; count--, vec++ )
vec->y = FT_MulFix( vec->y, scale ) + delta;
vec->x = FT_MulFix( vec->x, scale ) + delta;
}
else
{
for ( ; count > 0; count--, vec++ )
vec->x = FT_MulFix( vec->x, scale ) + delta;
vec->y = FT_MulFix( vec->y, scale ) + delta;
}
}
}
......
......@@ -41,9 +41,11 @@ FT_BEGIN_HEADER
} PSH_Hint_Flags;
#define psh_hint_is_active(x) (((x)->flags & PSH_HINT_FLAG_ACTIVE) != 0)
#define psh_hint_is_ghost(x) (((x)->flags & PSH_HINT_FLAG_GHOST ) != 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;
......@@ -94,6 +96,15 @@ FT_BEGIN_HEADER
PSH_Globals globals );
#ifdef DEBUG_VIEW
extern int ps_debug_no_horz_hints;
extern int ps_debug_no_vert_hints;
extern PSH_Hint_Table ps_debug_hint_table;
typedef void (*PSH_HintFunc)( PSH_Hint hint, FT_Bool vertical );
extern PSH_HintFunc ps_debug_hint_func;
#endif
FT_END_HEADER
#endif /* __PS_HINTER_FITTER_H__ */
......@@ -13,30 +13,6 @@
/*************************************************************************/
/*************************************************************************/
/* reset the widths/heights table */
static void
psh_globals_reset_widths( PSH_Globals globals,
FT_UInt direction,
PS_Globals_Widths widths )
{
PSH_Dimension dim = &globals->dimension[direction];
/* simple copy of the original widths values - no sorting */
{
FT_UInt count = widths->count;
PSH_Width write = dim->std.widths;
FT_Int16* read = widths->widths;
dim->std.count = count;
for ( ; count > 0; count-- )
{
write->org = read[0];
write++;
read++;
}
}
}
/* scale the widths/heights table */
static void
......@@ -109,40 +85,20 @@
/*************************************************************************/
/*************************************************************************/
/* re-read blue zones from the original fonts, and store them into out */
/* private structure. This function re-orders, sanitizes and fuzz-expands */
/* the zones as well.. */
static void
psh_blues_reset_zones( PSH_Blues target,
PS_Globals_Blues source,
FT_Int family )
psh_blues_set_zones_0( PSH_Blues target,
FT_UInt read_count,
FT_Short* read,
PSH_Blue_Table top_table,
PSH_Blue_Table bot_table )
{
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;
}
FT_UInt count_top = top_table->count;
FT_UInt count_bot = bot_table->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-- )
for ( ; read_count > 0; read_count -= 2 )
{
FT_Int reference, delta;
FT_UInt count;
PSH_Blue_Zone zones, zone;
/* read blue zone entry, and select target top/bottom zone */
......@@ -204,8 +160,49 @@
top_table->count = count_top;
bot_table->count = count_bot;
}
/* re-read blue zones from the original fonts, and store them into out */
/* private structure. This function re-orders, sanitizes and fuzz-expands */
/* the zones as well.. */
static void
psh_blues_set_zones( PSH_Blues target,
FT_UInt count,
FT_Short* blues,
FT_UInt count_others,
FT_Short* other_blues,
FT_Int fuzz,
FT_Int family )
{
PSH_Blue_Table top_table, bot_table;
FT_Int count_top, count_bot;
if ( family )
{
top_table = &target->family_top;
bot_table = &target->family_bottom;
}
else
{
top_table = &target->normal_top;
bot_table = &target->normal_bottom;
}
/* read the input blue zones, and build two sorted tables */
/* (one for the top zones, the other for the bottom zones */
top_table->count = 0;
bot_table->count = 0;
/* first, the blues */
psh_blues_set_zones_0( target, count, blues, top_table, bot_table );
psh_blues_set_zones_0( target, count_others, other_blues, top_table, bot_table );
count_top = top_table->count;
count_bot = bot_table->count;
/* sanitize top table */
if ( count_top > 0 )
{
PSH_Blue_Zone zone = top_table->zones;
......@@ -223,6 +220,7 @@
}
/* sanitize bottom table */
if ( count_bot > 0 )
{
PSH_Blue_Zone zone = bot_table->zones;
......@@ -241,10 +239,9 @@
/* expand top and bottom tables with blue fuzz */
{
FT_Int dim, top, bot, delta, fuzz;
FT_Int dim, top, bot, delta;
PSH_Blue_Zone zone;
fuzz = source->fuzz;
zone = top_table->zones;
count = count_top;
......@@ -287,6 +284,7 @@
}
/* reset the blues table when the device transform changes */
static void
psh_blues_scale_zones( PSH_Blues blues,
......@@ -404,36 +402,78 @@
static FT_Error
psh_globals_new( FT_Memory memory, PSH_Globals *aglobals )
psh_globals_new( FT_Memory memory,
T1_Private* priv,
PSH_Globals *aglobals )
{
PSH_Globals globals;
FT_Error error;
if ( !ALLOC( globals, sizeof(*globals) ) )
{
FT_UInt count;
FT_Short* read;
globals->memory = memory;
/* copy standard widths */
{
PSH_Dimension dim = &globals->dimension[1];
PSH_Width write = dim->std.widths;
write->org = priv->standard_width[1];
write++;
read = priv->snap_widths;
for ( count = priv->num_snap_widths; count > 0; count-- )
{
write->org = *read;
write++;
read++;
}
dim->std.count = write - dim->std.widths;
}
/* copy standard heights */
{
PSH_Dimension dim = &globals->dimension[0];
PSH_Width write = dim->std.widths;
write->org = priv->standard_height[1];
write++;
read = priv->snap_heights;
for ( count = priv->num_snap_heights; count > 0; count-- )
{
write->org = *read;
write++;
read++;
}
dim->std.count = write - dim->std.widths;
}
/* copy blue zones */
psh_blues_set_zones( &globals->blues, priv->num_blue_values,
priv->blue_values, priv->num_other_blues,
priv->other_blues, priv->blue_fuzz, 0 );
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->dimension[0].scale_mult = 0;
globals->dimension[0].scale_delta = 0;
globals->dimension[1].scale_mult = 0;
globals->dimension[1].scale_delta = 0;
}
*aglobals = globals;
return error;
}
static FT_Error
psh_globals_reset( PSH_Globals globals,
PS_Globals ps_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;
}
static FT_Error
psh_globals_set_scale( PSH_Globals globals,
......@@ -473,7 +513,6 @@
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;
}
......@@ -31,6 +31,26 @@ FT_BEGIN_HEADER
/***** *****/
/**********************************************************************/
/**********************************************************************/
/****************************************************************
*
* @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
/* standard and snap width */
typedef struct PSH_WidthRec_
......
#include "pshoptim.h"
#ifdef DEBUG_VIEW
void
ps_simple_scale( PSH_Hint_Table table,
FT_Fixed scale,
FT_Fixed delta,
FT_Bool vertical )
{
PSH_Hint hint;
FT_UInt count;
for ( count = 0; count < table->num_hints; count++ )
{
hint = table->sort[count];
if ( psh_hint_is_active(hint) )
{
hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
hint->cur_len = FT_MulFix( hint->org_len, scale );
if (ps_debug_hint_func)
ps_debug_hint_func( hint, vertical );
}
}
}
#endif
FT_LOCAL_DEF FT_Error
psh_hint_table_optimize( PSH_Hint_Table table,
PSH_Globals globals,
......@@ -10,6 +36,20 @@
FT_Fixed scale = dim->scale_mult;
FT_Fixed delta = dim->scale_delta;
#ifdef DEBUG_VIEW
if ( ps_debug_no_vert_hints && vertical )
{
ps_simple_scale( table, scale, delta, vertical );
return 0;
}
if ( ps_debug_no_horz_hints && !vertical )
{
ps_simple_scale( table, scale, delta, vertical );
return 0;
}
#endif
/* XXXX: for now, we only scale the hints to test all other aspects */
/* of the Postscript Hinter.. */
{
......@@ -21,10 +61,85 @@
hint = table->sort[count];
if ( psh_hint_is_active(hint) )
{
hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
hint->cur_len = FT_MulFix( hint->org_len, scale );
# if 1
FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta;
FT_Pos len = FT_MulFix( hint->org_len, scale );
FT_Pos fit_center;
FT_Pos fit_len;
PSH_Blue_AlignementRec align;
/* compute fitted width/height */
fit_len = psh_dimension_snap_width( dim, hint->org_len );
if ( fit_len < 64 )
fit_len = 64;
else
fit_len = (fit_len + 16 ) & -64;
hint->cur_len = fit_len;
/* check blue zones for horizontal stems */
align.align = 0;
if (!vertical)
{
psh_blues_snap_stem( &globals->blues,
hint->org_pos + hint->org_len,
hint->org_pos,
&align );
}
switch (align.align)
{
case PSH_BLUE_ALIGN_TOP:
{
/* the top of the stem is aligned against a blue zone */
hint->cur_pos = align.align_top - fit_len;
break;
}
case PSH_BLUE_ALIGN_BOT:
{
/* the bottom of the stem is aligned against a blue zone */
hint->cur_pos = align.align_bot;
break;