* 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
This commit is contained in:
David Turner 2002-07-08 22:26:11 +00:00
parent cb818320b8
commit 32e50721bd
15 changed files with 262 additions and 422 deletions

View File

@ -1,3 +1,13 @@
2002-07-07 Owen Taylor <owen@redhat.com>
* 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 <david@freetype.org>
* 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..

View File

@ -2775,6 +2775,65 @@ FT_BEGIN_HEADER
FT_Matrix* matrix );
/*@***********************************************************************/
/* */
/* <Function> */
/* FT_Set_Hint_Flags */
/* */
/* <Description> */
/* A function used to set a number of flags that are used to control */
/* the hinting process when glyphs are loaded. */
/* */
/* <InOut> */
/* face :: A handle to the source face object. */
/* */
/* <Input> */
/* flags :: A set of bit flags that control the hinting process */
/* see the FT_HINT_XXX constants for details. */
/* */
/* <Note> */
/* 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 );
/*@***********************************************************************/
/* */
/* <Constant> */
/* FT_HINT_NO_INTEGER_STEM */
/* */
/* <Description> */
/* 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
/*@***********************************************************************/
/* */
/* <Constant> */
/* FT_HINT_NO_HSTEM_ALIGN */
/* */
/* <Description> */
/* 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
/*@***********************************************************************/
/* */
/* <Constant> */
/* FT_HINT_NO_VSTEM_ALIGN */
/* */
/* <Description> */
/* 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

View File

@ -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;

View File

@ -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;
/*************************************************************************/
/*************************************************************************/

View File

@ -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 );
/*************************************************************************/

View File

@ -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 );

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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];

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 );

View File

@ -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