From 27c322e9835b8fec7e5f65a012f56e1c64fc9879 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 8 Jul 2002 22:26:11 +0000 Subject: [PATCH] * include/freetype/freetype.h, src/base/ftobjs.h, freetype/internal/ftobjs.h, freetype/internal/psaux.h, freetype/internal/pshints.h, src/psaux/t1decode.c, src/cff/cffgload.h, src/cff/cffgload.c, src/pshinter/pshalgo1.h, src/pshinter/pshalgo1.c, src/pshinter/pshalgo2.h, src/pshinter/pshalgo2.c, src/pshinter/pshalgo3.h, src/pshinter/pshalgo3.c: Adding support for hinter-specific bit flags, and the new FT_Set_Hint_Flags high-level API --- ChangeLog | 12 +- include/freetype/freetype.h | 59 +++ include/freetype/internal/ftobjs.h | 5 + include/freetype/internal/psaux.h | 18 +- include/freetype/internal/pshints.h | 10 +- src/base/ftobjs.c | 17 + src/cff/cffgload.c | 4 +- src/cff/cffgload.h | 2 + src/psaux/t1decode.c | 4 +- src/pshinter/pshalgo1.c | 5 +- src/pshinter/pshalgo1.h | 3 +- src/pshinter/pshalgo2.c | 4 +- src/pshinter/pshalgo2.h | 3 +- src/pshinter/pshalgo3.c | 535 +++++++--------------------- src/pshinter/pshalgo3.h | 3 +- 15 files changed, 262 insertions(+), 422 deletions(-) diff --git a/ChangeLog b/ChangeLog index cefe6429a..0be5f229f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2002-07-07 Owen Taylor + + * include/freetype/freetype.h, src/base/ftobjs.h, + freetype/internal/ftobjs.h, freetype/internal/psaux.h, + freetype/internal/pshints.h, src/psaux/t1decode.c, src/cff/cffgload.h, + src/cff/cffgload.c, src/pshinter/pshalgo1.h, src/pshinter/pshalgo1.c, + src/pshinter/pshalgo2.h, src/pshinter/pshalgo2.c, src/pshinter/pshalgo3.h, + src/pshinter/pshalgo3.c: Adding support for hinter-specific bit flags, + and the new FT_Set_Hint_Flags high-level API + 2002-07-04 David Turner * src/pfr/pfrobjs.c (pfr_slot_load): fixed a small bug that returned @@ -5,7 +15,7 @@ metrics resolution * src/autohint/ahhint.c: removing compiler warnings - + * src/autohint/ahglyph.c: slight improvements to the serif detection code. More work is needed though.. diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 57c0fcbee..18659dbc6 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -2775,6 +2775,65 @@ FT_BEGIN_HEADER FT_Matrix* matrix ); + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_Set_Hint_Flags */ + /* */ + /* */ + /* A function used to set a number of flags that are used to control */ + /* the hinting process when glyphs are loaded. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* flags :: A set of bit flags that control the hinting process */ + /* see the FT_HINT_XXX constants for details. */ + /* */ + /* */ + /* The interpretation of the flags depends on the hinter module in */ + /* use. Not all modules will support all flags */ + /* */ + FT_EXPORT( void ) + FT_Set_Hint_Flags( FT_Face face, + FT_ULong hint_flags ); + + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_HINT_NO_INTEGER_STEM */ + /* */ + /* */ + /* A bit-field constant, used with FT_Set_Hint_Flags() to to suppress */ + /* snapping of stem widths to integer values */ + /* */ +#define FT_HINT_NO_INTEGER_STEM 1 + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_HINT_NO_HSTEM_ALIGN */ + /* */ + /* */ + /* A bit-field constant, used with FT_Set_Hint_Flags() to to suppress */ + /* alignment of horizontal stems with the pixel grid. */ + /* */ +#define FT_HINT_NO_HSTEM_ALIGN 2 + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_HINT_NO_VSTEM_ALIGN */ + /* */ + /* */ + /* A bit-field constant, used with FT_Set_Hint_Flags() to to suppress */ + /* alignment of vertical stems with the pixel grid */ + /* */ +#define FT_HINT_NO_VSTEM_ALIGN 4 + /* */ FT_END_HEADER diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index f92115c6a..015349ab0 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -291,6 +291,9 @@ FT_BEGIN_HEADER /* transform_flags :: Some flags used to classify the transform. */ /* Only used by the convenience functions. */ /* */ + /* hint_flags :: Some flags used to change the hinters' */ + /* behaviour. Only used for debugging for now */ + /* */ /* postscript_name :: Postscript font name for this face. */ /* */ typedef struct FT_Face_InternalRec_ @@ -302,6 +305,8 @@ FT_BEGIN_HEADER FT_Vector transform_delta; FT_Int transform_flags; + FT_UInt32 hint_flags; + const char* postscript_name; } FT_Face_InternalRec; diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h index a2cf527a8..2f1557d6b 100644 --- a/include/freetype/internal/psaux.h +++ b/include/freetype/internal/psaux.h @@ -142,10 +142,10 @@ FT_BEGIN_HEADER typedef struct PS_ParserRec_* PS_Parser; typedef struct T1_TokenRec_* T1_Token; - + typedef struct T1_FieldRec_* T1_Field; - + /* simple enumeration type used to identify token types */ typedef enum T1_TokenType_ { @@ -388,7 +388,7 @@ FT_BEGIN_HEADER FT_Memory memory; PS_Parser_FuncsRec funcs; - + } PS_ParserRec; @@ -544,7 +544,7 @@ FT_BEGIN_HEADER void* hints_globals; /* hinter-specific */ T1_Builder_FuncsRec funcs; - + } T1_BuilderRec; @@ -613,7 +613,7 @@ FT_BEGIN_HEADER (*parse_charstrings)( T1_Decoder decoder, FT_Byte* base, FT_UInt len ); - + } T1_Decoder_FuncsRec; @@ -645,9 +645,11 @@ FT_BEGIN_HEADER PS_Blend blend; /* for multiple master support */ + FT_UInt32 hint_flags; + T1_Decoder_Callback parse_callback; T1_Decoder_FuncsRec funcs; - + } T1_DecoderRec; @@ -667,9 +669,9 @@ FT_BEGIN_HEADER FT_CMap_Class expert; FT_CMap_Class custom; FT_CMap_Class unicode; - + } T1_CMap_ClassesRec; - + /*************************************************************************/ /*************************************************************************/ diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h index 9b85065b9..e7fd76faa 100644 --- a/include/freetype/internal/pshints.h +++ b/include/freetype/internal/pshints.h @@ -267,6 +267,8 @@ FT_BEGIN_HEADER /* */ /* globals :: The hinter globals for this font. */ /* */ + /* hint_flags :: hinter bit flags */ + /* */ /* @return: */ /* FreeType error code. 0 means success. */ /* */ @@ -280,7 +282,8 @@ FT_BEGIN_HEADER typedef FT_Error (*T1_Hints_ApplyFunc)( T1_Hints hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_UInt32 hint_flags ); /*************************************************************************/ @@ -545,6 +548,8 @@ FT_BEGIN_HEADER /* */ /* globals :: The hinter globals for this font. */ /* */ + /* hint_flags :: hinter bit flags */ + /* */ /* @return: */ /* FreeType error code. 0 means success. */ /* */ @@ -558,7 +563,8 @@ FT_BEGIN_HEADER typedef FT_Error (*T2_Hints_ApplyFunc)( T2_Hints hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_UInt32 hint_flags ); /*************************************************************************/ diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 0fce50cd7..c37072db3 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -380,6 +380,23 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Hint_Flags( FT_Face face, + FT_ULong flags ) + { + FT_Face_Internal internal; + + if ( !face ) + return; + + internal = face->internal; + + internal->hint_flags = (FT_UInt)flags; + } + + static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ); diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 07a137c44..519346d76 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -246,6 +246,7 @@ builder->current = &loader->current.outline; FT_GlyphLoader_Rewind( loader ); + builder->hint_flags = FT_FACE(face)->internal->hint_flags; builder->hints_globals = 0; builder->hints_funcs = 0; @@ -1676,7 +1677,8 @@ /* apply hints to the loaded glyph outline now */ hinter->apply( hinter->hints, builder->current, - (PSH_Globals)builder->hints_globals ); + (PSH_Globals)builder->hints_globals, + builder->hint_flags ); } /* add current outline to the glyph slot */ diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h index b749d1d97..15182fe01 100644 --- a/src/cff/cffgload.h +++ b/src/cff/cffgload.h @@ -114,6 +114,8 @@ FT_BEGIN_HEADER FT_Error error; /* only used for memory errors */ FT_Bool metrics_only; + FT_UInt32 hint_flags; + void* hints_funcs; /* hinter-specific */ void* hints_globals; /* hinter-specific */ diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index 4544ad1fb..91220fc33 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -752,7 +752,8 @@ /* apply hints to the loaded glyph outline now */ hinter->apply( hinter->hints, builder->current, - (PSH_Globals)builder->hints_globals ); + (PSH_Globals)builder->hints_globals, + decoder->hint_flags ); } /* add current outline to the glyph slot */ @@ -1146,6 +1147,7 @@ decoder->num_glyphs = face->num_glyphs; decoder->glyph_names = glyph_names; + decoder->hint_flags = face->internal->hint_flags; decoder->blend = blend; decoder->parse_callback = parse_callback; diff --git a/src/pshinter/pshalgo1.c b/src/pshinter/pshalgo1.c index 8fa03256e..25e343317 100644 --- a/src/pshinter/pshalgo1.c +++ b/src/pshinter/pshalgo1.c @@ -744,13 +744,16 @@ FT_Error ps1_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ) + PSH_Globals globals, + FT_UInt32 hint_flags ) { PSH1_Hint_TableRec hints; FT_Error error = 0; FT_Int dimension; + FT_UNUSED( hint_flags ); + for ( dimension = 1; dimension >= 0; dimension-- ) { PS_Dimension dim = &ps_hints->dimension[dimension]; diff --git a/src/pshinter/pshalgo1.h b/src/pshinter/pshalgo1.h index ed1031fd6..1eae160b7 100644 --- a/src/pshinter/pshalgo1.h +++ b/src/pshinter/pshalgo1.h @@ -88,7 +88,8 @@ FT_BEGIN_HEADER extern FT_Error ps1_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_UInt32 hint_flags ); #ifdef DEBUG_HINTER diff --git a/src/pshinter/pshalgo2.c b/src/pshinter/pshalgo2.c index 2eb8b8caf..b8ece3cf2 100644 --- a/src/pshinter/pshalgo2.c +++ b/src/pshinter/pshalgo2.c @@ -1494,7 +1494,8 @@ FT_Error ps2_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ) + PSH_Globals globals, + FT_UInt32 hint_flags ) { PSH2_GlyphRec glyphrec; PSH2_Glyph glyph = &glyphrec; @@ -1504,6 +1505,7 @@ #endif FT_Int dimension; + FT_UNUSED( hint_flags ); #ifdef DEBUG_HINTER memory = globals->memory; diff --git a/src/pshinter/pshalgo2.h b/src/pshinter/pshalgo2.h index 5d6a61ee7..408cd951a 100644 --- a/src/pshinter/pshalgo2.h +++ b/src/pshinter/pshalgo2.h @@ -190,7 +190,8 @@ FT_BEGIN_HEADER extern FT_Error ps2_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_UInt32 hint_flags ); FT_END_HEADER diff --git a/src/pshinter/pshalgo3.c b/src/pshinter/pshalgo3.c index afc357ecf..35b8ad05e 100644 --- a/src/pshinter/pshalgo3.c +++ b/src/pshinter/pshalgo3.c @@ -34,7 +34,7 @@ #undef SNAP_STEMS #undef ONLY_ALIGN_Y - + /*************************************************************************/ @@ -359,11 +359,11 @@ static FT_Fixed psh3_hint_snap_stem_side_delta ( FT_Fixed pos, - FT_Fixed len ) + FT_Fixed len ) { FT_Fixed delta1 = ( ( pos + 32 ) & -64 ) - pos; FT_Fixed delta2 = ( ( pos + len + 32 ) & -64 ) - pos - len; - + if ( ABS( delta1 ) <= ABS( delta2 ) ) { return delta1; @@ -378,7 +378,8 @@ static void psh3_hint_align( PSH3_Hint hint, PSH_Globals globals, - FT_Int dimension ) + FT_Int dimension, + FT_UInt32 hint_flags ) { PSH_Dimension dim = &globals->dimension[dimension]; FT_Fixed scale = dim->scale_mult; @@ -390,22 +391,38 @@ FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; FT_Pos len = FT_MulFix( hint->org_len, scale ); -#ifdef SNAP_STEMS - FT_Pos fit_center; - FT_Pos fit_len; - + FT_Pos fit_center; + FT_Pos fit_len; PSH_AlignmentRec align; - /* compute fitted width/height */ - fit_len = 0; - if ( hint->org_len ) + + /* ignore stem alignments when requested through the hint flags */ + if ( ( dimension == 0 && ( hint_flags & FT_HINT_NO_VSTEM_ALIGN ) != 0 ) || + ( dimension == 1 && ( hint_flags & FT_HINT_NO_HSTEM_ALIGN ) != 0 ) ) { - fit_len = psh_dimension_snap_width( dim, hint->org_len ); - if ( fit_len < 64 ) - fit_len = 64; - else - fit_len = ( fit_len + 32 ) & -64; + hint->cur_pos = pos; + hint->cur_len = len; + + psh3_hint_set_fitted( hint ); + return; + } + + /* perform stem snapping when requested */ + if ( ( hint_flags & FT_HINT_NO_INTEGER_STEM ) == 0 ) + { + /* compute fitted width/height */ + fit_len = 0; + if ( hint->org_len ) + { + fit_len = psh_dimension_snap_width( dim, hint->org_len ); + if ( fit_len < 64 ) + fit_len = 64; + else + fit_len = ( fit_len + 32 ) & -64; + } } + else + fit_len = len; hint->cur_len = fit_len; @@ -450,182 +467,113 @@ /* ensure that parent is already fitted */ if ( !psh3_hint_is_fitted( parent ) ) - psh3_hint_align( parent, globals, dimension ); + psh3_hint_align( parent, globals, dimension, hint_flags ); par_org_center = parent->org_pos + ( parent->org_len / 2); par_cur_center = parent->cur_pos + ( parent->cur_len / 2); cur_org_center = hint->org_pos + ( hint->org_len / 2); cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); -#if 0 - if ( cur_delta >= 0 ) - cur_delta = ( cur_delta + 16 ) & -64; - else - cur_delta = -( (-cur_delta + 16 ) & -64 ); -#endif - pos = par_cur_center + cur_delta - ( len >> 1 ); + pos = par_cur_center + cur_delta - ( len >> 1 ); } - /* normal processing */ - if ( ( fit_len / 64 ) & 1 ) + if ( ( hint_flags & FT_HINT_NO_INTEGER_STEM ) == 0 ) { - /* odd number of pixels */ - fit_center = ( ( pos + ( len >> 1 ) ) & -64 ) + 32; + /* 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 { - /* even number of pixels */ - fit_center = ( pos + ( len >> 1 ) + 32 ) & -64; - } + /* Stems less than one pixel wide are easy - we want to + * make them as dark as possible, so they must fall within + * one pixel. If the stem is split between two pixels + * then snap the edge that is nearer to the pixel boundary + * to the pixel boundary + */ + if (len <= 64) + { + if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) + pos += psh3_hint_snap_stem_side_delta ( pos, len ); + } + /* Position stems other to minimize the amount of mid-grays. + * There are, in general, two positions that do this, + * illustrated as A) and B) below. + * + * + + + + + * + * A) |--------------------------------| + * B) |--------------------------------| + * C) |--------------------------------| + * + * Position A) (split the excess stem equally) should be better + * for stems of width N + f where f < 0.5 + * + * Position B) (split the deficiency equally) should be better + * for stems of width N + f where f > 0.5 + * + * It turns out though that minimizing the total number of touched + * pixels is also important, so position C), with one edge + * aligned with a pixel boundary is actually preferable + * to A). There are also more possible positions for C) than + * for A) or B), so there will be less distortion of the overall + * character shape. + */ + else + { + FT_Fixed frac_len = len & 63; + FT_Fixed center = pos + ( len >> 1 ); - hint->cur_pos = fit_center - ( fit_len >> 1 ); + FT_Fixed delta_a, delta_b; + + if ( ( len / 64 ) & 1 ) + { + delta_a = ( center & -64 ) + 32 - center; + delta_b = ( ( center + 32 ) & - 64 ) - center; + } + else + { + delta_a = ( ( center + 32 ) & - 64 ) - center; + delta_b = ( center & -64 ) + 32 - center; + } + + /* We choose between B) and C) above based on the amount + * of fractional stem width: for small amounts, choose + * C) always; for large amounts, B) always; inbetween, + * pick whichever one involves less stem movement. + */ + if (frac_len < 32) + { + pos += psh3_hint_snap_stem_side_delta ( pos, len ); + } + else if (frac_len < 48) + { + FT_Fixed side_delta = psh3_hint_snap_stem_side_delta ( pos, len ); + + if ( ABS( side_delta ) < ABS( delta_b ) ) + pos += side_delta; + else + pos += delta_b; + } + else + { + pos += delta_b; + } + } + hint->cur_pos = pos; + } } } -#else - PSH_AlignmentRec align; - hint->cur_len = len; - - /* check blue zones for horizontal stems */ - align.align = PSH_BLUE_ALIGN_NONE; - align.align_bot = align.align_top = 0; - - if ( dimension == 1 ) - psh_blues_snap_stem( &globals->blues, - hint->org_pos + hint->org_len, - hint->org_pos, - &align ); -#ifdef ONLY_ALIGN_Y - else - { - hint->cur_pos = pos; - return; - } -#endif - - 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 - 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: - { - PSH3_Hint parent = hint->parent; - - if ( parent ) - { - FT_Pos par_org_center, par_cur_center; - FT_Pos cur_org_center, cur_delta; - - - /* ensure that parent is already fitted */ - if ( !psh3_hint_is_fitted( parent ) ) - psh3_hint_align( parent, globals, dimension ); - - par_org_center = parent->org_pos + ( parent->org_len / 2); - par_cur_center = parent->cur_pos + ( parent->cur_len / 2); - cur_org_center = hint->org_pos + ( hint->org_len / 2); - - cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); - pos = par_cur_center + cur_delta - ( len >> 1 ); - } - - { - /* Stems less than one pixel wide are easy - we want to - * make them as dark as possible, so they must fall within - * one pixel. If the stem is split between two pixels - * then snap the edge that is nearer to the pixel boundary - * to the pixel boundary - */ - if (len <= 64) - { - if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) - pos += psh3_hint_snap_stem_side_delta ( pos, len ); - } - /* Position stems other to minimize the amount of mid-grays. - * There are, in general, two positions that do this, - * illustrated as A) and B) below. - * - * + + + + - * - * A) |--------------------------------| - * B) |--------------------------------| - * C) |--------------------------------| - * - * Position A) (split the excess stem equally) should be better - * for stems of width N + f where f < 0.5 - * - * Position B) (split the deficiency equally) should be better - * for stems of width N + f where f > 0.5 - * - * It turns out though that minimizing the total number of lit - * pixels is also important, so position C), with one edge - * aligned with a pixel boundary is actually preferable - * to A). There are also more possibile positions for C) than - * for A) or B), so it involves less distortion of the overall - * character shape. - */ - else - { - FT_Fixed frac_len = len & 63; - FT_Fixed center = pos + ( len >> 1 ); - - FT_Fixed delta_a, delta_b; - - if ( ( len / 64 ) & 1 ) - { - delta_a = ( center & -64 ) + 32 - center; - delta_b = ( ( center + 32 ) & - 64 ) - center; - } - else - { - delta_a = ( ( center + 32 ) & - 64 ) - center; - delta_b = ( center & -64 ) + 32 - center; - } - - /* We choose between B) and C) above based on the amount - * of fractinal stem width; for small amounts, choose - * C) always, for large amounts, B) always, and inbetween, - * pick whichever one involves less stem movement. - */ - if (frac_len < 32) - { - pos += psh3_hint_snap_stem_side_delta ( pos, len ); - } - else if (frac_len < 48) - { - FT_Fixed side_delta = psh3_hint_snap_stem_side_delta ( pos, len ); - - if ( ABS( side_delta ) < ABS( delta_b ) ) - pos += side_delta; - else - pos += delta_b; - } - else - { - pos += delta_b; - } - } - } - - hint->cur_pos = pos; - } - } -#endif - psh3_hint_set_fitted( hint ); #ifdef DEBUG_HINTER @@ -639,7 +587,8 @@ static void psh3_hint_table_align_hints( PSH3_Hint_Table table, PSH_Globals globals, - FT_Int dimension ) + FT_Int dimension, + FT_UInt32 hint_flags ) { PSH3_Hint hint; FT_UInt count; @@ -667,7 +616,7 @@ count = table->max_hints; for ( ; count > 0; count--, hint++ ) - psh3_hint_align( hint, globals, dimension ); + psh3_hint_align( hint, globals, dimension, hint_flags ); } @@ -705,230 +654,6 @@ #endif -#if 0 - /* setup interpolation zones once the hints have been grid-fitted */ - /* by the optimizer */ - static void - psh3_hint_table_setup_zones( PSH3_Hint_Table table, - FT_Fixed scale, - FT_Fixed delta ) - { - FT_UInt count; - PSH3_Zone zone; - PSH3_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 = PSH3_ZONE_MIN; - zone->max = PSH3_ZONE_MAX; - - table->num_zones = 1; - table->zone = zone; - 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 = PSH3_ZONE_MIN; - zone->max = hint->org_pos; - - psh3_print_zone( zone ); - - zone++; - - for ( count = table->num_hints; count > 0; 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 ); - - psh3_print_zone( zone ); - - zone++; - } - - if ( count == 1 ) - break; - - 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 - (hint->org_pos + hint->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 ); - - psh3_print_zone( zone ); - - zone++; - - hint = hint2; - } - - /* the last zone */ - zone->scale = scale; - zone->min = hint->org_pos + hint->org_len; - zone->max = PSH3_ZONE_MAX; - zone->delta = hint->cur_pos + hint->cur_len - - FT_MulFix( zone->min, scale ); - - psh3_print_zone( zone ); - - zone++; - - table->num_zones = zone - table->zones; - table->zone = table->zones; - } -#endif - -#if 0 - /* tune a single coordinate with the current interpolation zones */ - static FT_Pos - psh3_hint_table_tune_coord( PSH3_Hint_Table table, - FT_Int coord ) - { - PSH3_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 FT_MulFix( coord, zone->scale ) + zone->delta; - } -#endif - -#if 0 - /* tune a given outline with current interpolation zones */ - /* the function only works in a single dimension.. */ - static void - psh3_hint_table_tune_outline( PSH3_Hint_Table table, - FT_Outline* outline, - PSH_Globals globals, - FT_Int dimension ) - - { - FT_UInt count, first, last; - PS_Mask_Table hint_masks = table->hint_masks; - PS_Mask mask; - PSH_Dimension dim = &globals->dimension[dimension]; - FT_Fixed scale = dim->scale_mult; - FT_Fixed delta = dim->scale_delta; - - - if ( hint_masks && hint_masks->num_masks > 0 ) - { - first = 0; - mask = hint_masks->masks; - count = hint_masks->num_masks; - - for ( ; count > 0; count--, mask++ ) - { - last = mask->end_point; - - if ( last > first ) - { - FT_Vector* vec; - FT_Int count2; - - - psh3_hint_table_activate_mask( table, mask ); - psh3_hint_table_optimize( table, globals, outline, dimension ); - psh3_hint_table_setup_zones( table, scale, delta ); - last = mask->end_point; - - vec = outline->points + first; - count2 = last - first; - - for ( ; count2 > 0; count2--, vec++ ) - { - FT_Pos x, *px; - - - px = dimension ? &vec->y : &vec->x; - x = *px; - - *px = psh3_hint_table_tune_coord( table, (FT_Int)x ); - } - } - - first = last; - } - } - else /* no hints in this glyph, simply scale the outline */ - { - FT_Vector* vec; - - - vec = outline->points; - count = outline->n_points; - - if ( dimension == 0 ) - { - for ( ; count > 0; count--, vec++ ) - vec->x = FT_MulFix( vec->x, scale ) + delta; - } - else - { - for ( ; count > 0; count--, vec++ ) - vec->y = FT_MulFix( vec->y, scale ) + delta; - } - } - } -#endif - /*************************************************************************/ /*************************************************************************/ @@ -1661,7 +1386,8 @@ FT_Error ps3_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ) + PSH_Globals globals, + FT_UInt32 hint_flags ) { PSH3_GlyphRec glyphrec; PSH3_Glyph glyph = &glyphrec; @@ -1699,7 +1425,8 @@ /* compute aligned stem/hints positions */ psh3_hint_table_align_hints( &glyph->hint_tables[dimension], glyph->globals, - dimension ); + dimension, + hint_flags ); /* find strong points, align them, then interpolate others */ psh3_glyph_find_strong_points( glyph, dimension ); diff --git a/src/pshinter/pshalgo3.h b/src/pshinter/pshalgo3.h index 4d4abb733..6ad637185 100644 --- a/src/pshinter/pshalgo3.h +++ b/src/pshinter/pshalgo3.h @@ -190,7 +190,8 @@ FT_BEGIN_HEADER extern FT_Error ps3_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_UInt32 hint_flags ); FT_END_HEADER