--- freetype-2.1.2/src/base/ftobjs.c.slighthint Sat Jun 15 21:14:16 2002 +++ freetype-2.1.2/src/base/ftobjs.c Wed Jul 3 16:40:03 2002 @@ -380,6 +380,22 @@ } + /* 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 ); --- freetype-2.1.2/src/psaux/t1decode.c.slighthint Wed May 22 00:53:25 2002 +++ freetype-2.1.2/src/psaux/t1decode.c Wed Jul 3 17:35:04 2002 @@ -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 */ @@ -1147,10 +1148,13 @@ decoder->num_glyphs = face->num_glyphs; decoder->glyph_names = glyph_names; decoder->blend = blend; + decoder->hint_flags = face->internal->hint_flags; decoder->parse_callback = parse_callback; decoder->funcs = t1_decoder_funcs; + + return 0; } --- freetype-2.1.2/src/pshinter/pshalgo1.c.slighthint Fri Apr 12 05:31:46 2002 +++ freetype-2.1.2/src/pshinter/pshalgo1.c Wed Jul 3 16:40:03 2002 @@ -744,7 +744,8 @@ FT_Error ps1_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ) + PSH_Globals globals, + FT_ULong hint_flags ) { PSH1_Hint_TableRec hints; FT_Error error = 0; --- freetype-2.1.2/src/pshinter/pshalgo1.h.slighthint Tue Dec 4 20:22:05 2001 +++ freetype-2.1.2/src/pshinter/pshalgo1.h Wed Jul 3 16:40:03 2002 @@ -88,7 +88,8 @@ extern FT_Error ps1_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_ULong hint_flags ); #ifdef DEBUG_HINTER --- freetype-2.1.2/src/pshinter/pshalgo2.c.slighthint Wed Jul 3 16:40:03 2002 +++ freetype-2.1.2/src/pshinter/pshalgo2.c Wed Jul 3 18:08:53 2002 @@ -352,10 +352,29 @@ #endif +static FT_Fixed + psh2_hint_snap_stem_side_delta ( FT_Fixed pos, + 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; + } + else + { + return delta2; + } + } + + static void psh2_hint_align( PSH2_Hint hint, PSH_Globals globals, - FT_Int dimension ) + FT_Int dimension, + FT_ULong hint_flags ) { PSH_Dimension dim = &globals->dimension[dimension]; FT_Fixed scale = dim->scale_mult; @@ -372,16 +391,33 @@ PSH_AlignmentRec align; + if ( ( dimension == 0 && ( hint_flags & FT_HINT_NO_VSTEM_ALIGN ) != 0 ) || + ( dimension == 1 && ( hint_flags & FT_HINT_NO_HSTEM_ALIGN ) != 0 ) ) + { + hint->cur_pos = pos; + hint->cur_len = len; + + psh2_hint_set_fitted( hint ); - /* 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; + return; + } + + 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; @@ -427,7 +463,7 @@ /* ensure that parent is already fitted */ if ( !psh2_hint_is_fitted( parent ) ) - psh2_hint_align( parent, globals, dimension ); + psh2_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); @@ -443,22 +479,105 @@ pos = par_cur_center + cur_delta - ( len >> 1 ); } - /* 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 ); - } + if ( ( hint_flags & FT_HINT_NO_INTEGER_STEM ) == 0 ) + { + /* 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 + { + /* 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 += psh2_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 += psh2_hint_snap_stem_side_delta ( pos, len ); + } + else if (frac_len < 48) + { + FT_Fixed side_delta = psh2_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; + } + } } - + psh2_hint_set_fitted( hint ); #ifdef DEBUG_HINTER @@ -472,7 +591,8 @@ static void psh2_hint_table_align_hints( PSH2_Hint_Table table, PSH_Globals globals, - FT_Int dimension ) + FT_Int dimension, + FT_ULong hint_flags ) { PSH2_Hint hint; FT_UInt count; @@ -500,7 +620,7 @@ count = table->max_hints; for ( ; count > 0; count--, hint++ ) - psh2_hint_align( hint, globals, dimension ); + psh2_hint_align( hint, globals, dimension, hint_flags ); } @@ -1494,7 +1614,8 @@ FT_Error ps2_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ) + PSH_Globals globals, + FT_ULong hint_flags ) { PSH2_GlyphRec glyphrec; PSH2_Glyph glyph = &glyphrec; @@ -1532,7 +1653,8 @@ /* compute aligned stem/hints positions */ psh2_hint_table_align_hints( &glyph->hint_tables[dimension], glyph->globals, - dimension ); + dimension, + hint_flags ); /* find strong points, align them, then interpolate others */ psh2_glyph_find_strong_points( glyph, dimension ); --- freetype-2.1.2/src/pshinter/pshalgo2.h.slighthint Tue Dec 4 20:22:05 2001 +++ freetype-2.1.2/src/pshinter/pshalgo2.h Wed Jul 3 16:40:03 2002 @@ -190,7 +190,8 @@ extern FT_Error ps2_hints_apply( PS_Hints ps_hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_ULong hint_flags ); FT_END_HEADER --- freetype-2.1.2/include/freetype/internal/ftobjs.h.slighthint Mon Jun 10 19:03:35 2002 +++ freetype-2.1.2/include/freetype/internal/ftobjs.h Wed Jul 3 16:40:03 2002 @@ -302,6 +302,8 @@ FT_Vector transform_delta; FT_Int transform_flags; + FT_UInt hint_flags; + const char* postscript_name; } FT_Face_InternalRec; --- freetype-2.1.2/include/freetype/internal/pshints.h.slighthint Sat Mar 30 08:16:33 2002 +++ freetype-2.1.2/include/freetype/internal/pshints.h Wed Jul 3 16:40:03 2002 @@ -280,7 +280,8 @@ typedef FT_Error (*T1_Hints_ApplyFunc)( T1_Hints hints, FT_Outline* outline, - PSH_Globals globals ); + PSH_Globals globals, + FT_ULong hint_flags ); /*************************************************************************/ --- freetype-2.1.2/include/freetype/internal/psaux.h.slighthint Fri Mar 29 18:23:28 2002 +++ freetype-2.1.2/include/freetype/internal/psaux.h Wed Jul 3 16:40:03 2002 @@ -644,6 +644,7 @@ FT_Vector flex_vectors[7]; PS_Blend blend; /* for multiple master support */ + FT_ULong hint_flags; T1_Decoder_Callback parse_callback; T1_Decoder_FuncsRec funcs; --- freetype-2.1.2/include/freetype/freetype.h.slighthint Sun Jun 23 06:57:31 2002 +++ freetype-2.1.2/include/freetype/freetype.h Wed Jul 3 16:40:03 2002 @@ -121,6 +121,12 @@ /* FT_Set_Char_Size */ /* FT_Set_Pixel_Sizes */ /* FT_Set_Transform */ + /* FT_Set_Hint_Flags */ + /* */ + /* FT_HINT_NO_INTEGER_STEM */ + /* FT_HINT_NO_HSTEM_ALIGN */ + /* FT_HINT_NO_VSTEM_ALIGN */ + /* */ /* FT_Load_Glyph */ /* FT_Get_Char_Index */ /* FT_Get_Name_Index */ @@ -2181,9 +2187,67 @@ FT_Matrix* matrix, FT_Vector* delta ); + + /*************************************************************************/ + /* */ + /* */ + /* 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_Render_Mode */ /* */