From fbb76171837aa4906d531b6d5610c836e1457f02 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 10 Sep 2001 17:03:37 +0000 Subject: [PATCH] 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 !!) --- include/freetype/internal/pshints.h | 139 +-------------- src/psaux/t1decode.c | 6 + src/pshinter/pshfit.c | 6 +- src/pshinter/pshfit.h | 13 +- src/pshinter/pshglob.c | 187 ++++++++++++-------- src/pshinter/pshglob.h | 20 +++ src/pshinter/pshoptim.c | 119 ++++++++++++- src/pshinter/pshrec.c | 6 + src/pshinter/pshrec.h | 6 + src/type1/t1objs.c | 14 +- tests/gview.c | 265 +++++++++++++++++++++++++++- 11 files changed, 555 insertions(+), 226 deletions(-) diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h index bf9814aef..4384ad791 100644 --- a/include/freetype/internal/pshints.h +++ b/include/freetype/internal/pshints.h @@ -22,143 +22,11 @@ #include #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; diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index a3ec4e36a..d3af4163c 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -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; diff --git a/src/pshinter/pshfit.c b/src/pshinter/pshfit.c index 2ecc8ede0..1f9a70bf0 100644 --- a/src/pshinter/pshfit.c +++ b/src/pshinter/pshfit.c @@ -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; } } } diff --git a/src/pshinter/pshfit.h b/src/pshinter/pshfit.h index f51ec15d5..22b85373e 100644 --- a/src/pshinter/pshfit.h +++ b/src/pshinter/pshfit.h @@ -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__ */ diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c index edbcc627b..02c2e14a2 100644 --- a/src/pshinter/pshglob.c +++ b/src/pshinter/pshglob.c @@ -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; + FT_UInt count_top = top_table->count; + FT_UInt count_bot = bot_table->count; - 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-- ) + 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; } diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h index ce3be476d..6fdda05b0 100644 --- a/src/pshinter/pshglob.h +++ b/src/pshinter/pshglob.h @@ -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_ diff --git a/src/pshinter/pshoptim.c b/src/pshinter/pshoptim.c index ea8dd6037..eef2f846f 100644 --- a/src/pshinter/pshoptim.c +++ b/src/pshinter/pshoptim.c @@ -1,5 +1,31 @@ #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; + } + + case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: + { + /* both edges of the stem are aligned against blue zones */ + hint->cur_pos = align.align_bot; + hint->cur_len = align.align_top - align.align_bot; + } + break; + + default: + /* normal processing */ + if ( (fit_len/64) & 1 ) + { + /* odd number of pixels */ + fit_center = ((pos + (len >> 1)) & -64) + 32; + } + else + { + /* even number of pixels */ + fit_center = (pos + (len >> 1) + 32) & -64; + } + + hint->cur_pos = fit_center - (fit_len >> 1); + } +# else + hint->cur_pos = (FT_MulFix( hint->org_pos, scale ) + delta + 32) & -64; + hint->cur_len = FT_MulFix( hint->org_len, scale ); +# endif + +#ifdef DEBUG_VIEW + if (ps_debug_hint_func) + ps_debug_hint_func( hint, vertical ); +#endif } } } + return 0; } diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c index 67184e403..5c63f68c2 100644 --- a/src/pshinter/pshrec.c +++ b/src/pshinter/pshrec.c @@ -1000,6 +1000,11 @@ error = ps_dimension_end( &dim[1], end_point, memory ); } } + +#ifdef DEBUG_VIEW + if (!error) + the_ps_hints = hints; +#endif return error; } @@ -1095,4 +1100,5 @@ funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; } + \ No newline at end of file diff --git a/src/pshinter/pshrec.h b/src/pshinter/pshrec.h index ae7c2ae0e..fbf7ddbb2 100644 --- a/src/pshinter/pshrec.h +++ b/src/pshinter/pshrec.h @@ -151,6 +151,12 @@ FT_BEGIN_HEADER FT_LOCAL void t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ); +#define xxxDEBUG_VIEW + +#ifdef DEBUG_VIEW + extern PS_Hints the_ps_hints; +#endif + /* */ FT_END_HEADER diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c index 401c7cb96..b81fe3238 100644 --- a/src/type1/t1objs.c +++ b/src/type1/t1objs.c @@ -55,7 +55,7 @@ /*************************************************************************/ static PSH_Globals_Funcs - T1_Size_Get_Globals( T1_Size size ) + T1_Size_Get_Globals_Funcs( T1_Size size ) { T1_Face face = (T1_Face) size->root.face; PSHinter_Interface* pshinter = face->pshinter; @@ -75,7 +75,7 @@ { PSH_Globals_Funcs funcs; - funcs = T1_Size_Get_Globals(size); + funcs = T1_Size_Get_Globals_Funcs(size); if (funcs) funcs->destroy( (PSH_Globals) size->root.internal ); @@ -89,13 +89,15 @@ FT_Error T1_Size_Init( T1_Size size ) { FT_Error error = 0; - PSH_Globals_Funcs funcs = T1_Size_Get_Globals( size ); + PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); if ( funcs ) { - PSH_Globals globals; + PSH_Globals globals; + T1_Face face = (T1_Face) size->root.face; - error = funcs->create( size->root.face->memory, &globals ); + error = funcs->create( size->root.face->memory, + &face->type1.private_dict, &globals ); if (!error) size->root.internal = (FT_Size_Internal)(void*) globals; } @@ -108,7 +110,7 @@ FT_LOCAL_DEF FT_Error T1_Size_Reset( T1_Size size ) { - PSH_Globals_Funcs funcs = T1_Size_Get_Globals(size); + PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs(size); FT_Error error = 0; if (funcs) diff --git a/tests/gview.c b/tests/gview.c index c78184268..b894aa207 100644 --- a/tests/gview.c +++ b/tests/gview.c @@ -5,6 +5,10 @@ #include #include FT_FREETYPE_H +/* include FreeType internals to debug hints */ +#include <../src/pshinter/pshrec.h> +#include <../src/pshinter/pshfit.h> + #include /* for clock() */ /* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include */ @@ -45,8 +49,20 @@ static int option_show_glyph = 1; static int option_show_grid = 1; static int option_show_em = 0; +static int option_show_ps_hints = 1; +static int option_show_horz_hints = 1; +static int option_show_vert_hints = 1; + + static int option_hinting = 1; +static char temp_message[1024]; + +PS_Hints the_ps_hints = 0; +int ps_debug_no_horz_hints = 0; +int ps_debug_no_vert_hints = 0; +PSH_HintFunc ps_debug_hint_func = 0; + #define AXIS_COLOR 0xFFFF0000 #define GRID_COLOR 0xFFD0D0D0 #define ON_COLOR 0xFFFF2000 @@ -55,6 +71,10 @@ static int option_hinting = 1; #define TEXT_COLOR 0xFF000000 #define EM_COLOR 0x80008000 +#define GHOST_HINT_COLOR 0xE00000FF +#define STEM_HINT_COLOR 0xE02020FF +#define STEM_JOIN_COLOR 0xE020FF20 + /* print message and abort program */ static void Panic( const char* message ) @@ -168,11 +188,105 @@ draw_grid( void ) } +static int pshint_cpos = 0; +static int pshint_vertical = -1; + +static void +draw_ps_hint( PSH_Hint hint, FT_Bool vertical ) +{ + int x1, x2; + NV_Vector v; + + + if ( pshint_vertical != vertical ) + { + if (vertical) + pshint_cpos = 40; + else + pshint_cpos = 10; + + pshint_vertical = vertical; + } + + if (vertical) + { + if ( !option_show_vert_hints ) + return; + + v.x = hint->cur_pos; + v.y = 0; + nv_vector_transform( &v, &size_transform ); + x1 = (int)(v.x + 0.5); + + v.x = hint->cur_pos + hint->cur_len; + v.y = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.x + 0.5); + + nv_pixmap_fill_rect( target, x1, 0, 1, target->height, + psh_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh_hint_is_ghost(hint) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, x2, 0, 1, target->height, + psh_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, x1, pshint_cpos, x2+1-x1, 1, + STEM_JOIN_COLOR ); + } + else + { + if (!option_show_horz_hints) + return; + + v.y = hint->cur_pos; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x1 = (int)(v.y + 0.5); + + v.y = hint->cur_pos + hint->cur_len; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.y + 0.5); + + nv_pixmap_fill_rect( target, 0, x1, target->width, 1, + psh_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh_hint_is_ghost(hint) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, 0, x2, target->width, 1, + psh_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1+1-x2, + STEM_JOIN_COLOR ); + } + + printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' ); + + pshint_cpos += 10; +} + + + static void draw_glyph( int glyph_index ) { NV_Path path; - NV_Scale scale; + + pshint_vertical = -1; + ps_debug_hint_func = option_show_ps_hints ? draw_ps_hint : 0; error = FT_Load_Glyph( face, glyph_index, option_hinting ? FT_LOAD_NO_BITMAP @@ -266,10 +380,115 @@ draw_glyph( int glyph_index ) sprintf( temp, "glyph %4d: %s", glyph_index, temp2 ); nv_pixmap_cell_text( target, 0, 8, temp, TEXT_COLOR ); + + if ( temp_message[0] ) + { + nv_pixmap_cell_text( target, 0, 16, temp_message, TEXT_COLOR ); + temp_message[0] = 0; + } } } +#if 0 + +static void +draw_ps_hints( void ) +{ + if ( option_show_ps_hints && the_ps_hints ) + { + PS_Dimension dim; + PS_Hint hint; + NV_UInt count; + NV_Int cpos; + NV_Vector v; + + /* draw vertical stems */ + if ( option_show_vert_hints ) + { + dim = &the_ps_hints->dimension[1]; + hint = dim->hints.hints; + cpos = 40; + for ( count = dim->hints.num_hints; count > 0; count--, hint++ ) + { + NV_Int x1, x2; + + v.x = hint->pos; + v.y = 0; + nv_vector_transform( &v, &glyph_transform ); + x1 = (int)(v.x+0.5); + x1 = glyph_org_x + hint->pos*glyph_scale; + nv_pixmap_fill_rect( target, x1, 0, 1, target->height, + ps_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( !ps_hint_is_ghost(hint) ) + { + v.x = hint->pos + hint->len; + v.y = 0; + nv_vector_transform( &v, &glyph_transform ); + x2 = (int)(v.x+0.5); + x2 = glyph_org_x + (hint->pos + hint->len)*glyph_scale; + nv_pixmap_fill_rect( target, x2, 0, 1, target->height, + STEM_HINT_COLOR ); + } + else + { + x1 -= 1; + x2 = x1 + 2; + } + + nv_pixmap_fill_rect( target, x1, cpos, x2-x1+1, 1, + STEM_JOIN_COLOR ); + cpos += 10; + } + } + + /* draw horizontal stems */ + if ( option_show_horz_hints ) + { + dim = &the_ps_hints->dimension[0]; + hint = dim->hints.hints; + cpos = 10; + for ( count = dim->hints.num_hints; count > 0; count--, hint++ ) + { + NV_Int y1, y2; + + v.x = 0; + v.y = hint->pos; + nv_vector_transform( &v, &glyph_transform ); + y1 = (int)(v.y+0.5); + y1 = glyph_org_y - hint->pos*glyph_scale; + nv_pixmap_fill_rect( target, 0, y1, target->width, 1, + ps_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( !ps_hint_is_ghost(hint) ) + { + v.x = 0; + v.y = hint->pos + hint->len; + nv_vector_transform( &v, &glyph_transform ); + y2 = (int)(v.y+0.5); + y2 = glyph_org_y - (hint->pos + hint->len)*glyph_scale; + nv_pixmap_fill_rect( target, 0, y2, target->width, 1, + STEM_HINT_COLOR ); + } + else + { + y1 -= 1; + y2 = y1 + 2; + } + + nv_pixmap_fill_rect( target, cpos, y2, 1, y1-y2+1, + STEM_JOIN_COLOR ); + cpos += 10; + } + } + } +} + +#endif + static void handle_event( NVV_EventRec* ev ) { @@ -289,7 +508,7 @@ handle_event( NVV_EventRec* ev ) break; } - case NVV_KEY('a'): + case NVV_KEY('x'): { option_show_axis = !option_show_axis; break; @@ -340,6 +559,7 @@ handle_event( NVV_EventRec* ev ) { pixel_size++; reset_size( pixel_size, grid_scale ); + sprintf( temp_message, "pixel size = %d", pixel_size ); break; } @@ -349,14 +569,49 @@ handle_event( NVV_EventRec* ev ) { pixel_size--; reset_size( pixel_size, grid_scale ); + sprintf( temp_message, "pixel size = %d", pixel_size ); } break; } + case NVV_KEY('z'): + { + ps_debug_no_vert_hints = !ps_debug_no_vert_hints; + sprintf( temp_message, "vertical hints processing is now %s", + ps_debug_no_vert_hints ? "off" : "on" ); + break; + } + + case NVV_KEY('a'): + { + ps_debug_no_horz_hints = !ps_debug_no_horz_hints; + sprintf( temp_message, "horizontal hints processing is now %s", + ps_debug_no_horz_hints ? "off" : "on" ); + break; + } + + case NVV_KEY('Z'): + { + option_show_vert_hints = !option_show_vert_hints; + sprintf( temp_message, "vertical hints display is now %s", + option_show_vert_hints ? "off" : "on" ); + break; + } + + case NVV_KEY('A'): + { + option_show_horz_hints = !option_show_horz_hints; + sprintf( temp_message, "horizontal hints display is now %s", + option_show_horz_hints ? "off" : "on" ); + break; + } + case NVV_KEY('h'): { option_hinting = !option_hinting; + sprintf( temp_message, "hinting is now %s", + option_hinting ? "off" : "on" ); break; } } @@ -389,7 +644,7 @@ int main( int argc, char** argv ) error = FT_Init_FreeType( &freetype ); if (error) Panic( "could not initialise FreeType" ); - error = FT_New_Face( freetype, "c:/winnt/fonts/times.ttf", 0, &face ); + error = FT_New_Face( freetype, "h:/fonts/cour.pfa", 0, &face ); if (error) Panic( "could not open font face" ); reset_size( pixel_size, grid_scale ); @@ -405,7 +660,11 @@ int main( int argc, char** argv ) { clear_background(); draw_grid(); + + the_ps_hints = 0; draw_glyph( glyph_index ); + /* draw_ps_hints(); */ + nvv_surface_refresh( surface, NULL ); nvv_surface_listen( surface, 0, &event );