--- /dev/null
+--- ./src/type1/t1load.c.bluefuzz Mon Jul 8 12:36:24 2002
++++ ./src/type1/t1load.c Mon Jul 8 12:36:47 2002
+@@ -1653,6 +1653,9 @@
+ /* default lenIV */
+ type1->private_dict.lenIV = 4;
+
++ /* default blue_fuzz; we set it here since 0 is a valid value */
++ type1->private_dict.blue_fuzz = 1;
++
+ parser = &loader.parser;
+ error = T1_New_Parser( parser,
+ face->root.stream,
+--- ./src/pshinter/pshglob.c.bluefuzz Mon Jul 8 12:38:09 2002
++++ ./src/pshinter/pshglob.c Mon Jul 8 12:46:27 2002
+@@ -534,10 +534,10 @@
+ for ( ; count > 0; count--, zone++ )
+ {
+ delta = stem_top - zone->org_bottom;
+- if ( delta < 0 )
++ if ( delta < - blues->blue_fuzz )
+ break;
+
+- if ( stem_top <= zone->org_top )
++ if ( stem_top <= zone->org_top + blues->blue_fuzz )
+ {
+ if ( no_shoots || delta <= blues->blue_threshold )
+ {
+@@ -556,10 +556,10 @@
+ for ( ; count > 0; count--, zone-- )
+ {
+ delta = zone->org_top - stem_bot;
+- if ( delta < 0 )
++ if ( delta < - blues->blue_fuzz )
+ break;
+
+- if ( stem_bot >= zone->org_bottom )
++ if ( stem_bot >= zone->org_bottom - blues->blue_fuzz )
+ {
+ if ( no_shoots || delta < blues->blue_shift )
+ {
+@@ -680,6 +680,8 @@
+ ? priv->blue_shift
+ : 7;
+
++ globals->blues.blue_fuzz = priv->blue_fuzz;
++
+ globals->dimension[0].scale_mult = 0;
+ globals->dimension[0].scale_delta = 0;
+ globals->dimension[1].scale_mult = 0;
+--- ./src/pshinter/pshglob.h.bluefuzz Mon Jul 8 12:38:32 2002
++++ ./src/pshinter/pshglob.h Mon Jul 8 12:38:36 2002
+@@ -123,6 +123,7 @@
+ FT_Fixed blue_scale;
+ FT_Int blue_shift;
+ FT_Int blue_threshold;
++ FT_Int blue_fuzz;
+ FT_Bool no_overshoots;
+
+ } PSH_BluesRec, *PSH_Blues;
--- /dev/null
+--- freetype-2.1.2/src/autohint/ahglobal.c.autohint Sat Mar 30 08:16:33 2002
++++ freetype-2.1.2/src/autohint/ahglobal.c Fri Aug 9 13:50:28 2002
+@@ -368,7 +368,6 @@
+ limit = segments + outline->num_vsegments;
+ widths = globals->widths;
+ p_num_widths = &globals->num_widths;
+-
+ }
+
+ /* Now, compute the edge distance threshold as a fraction of the */
+--- freetype-2.1.2/src/autohint/ahglyph.c.autohint Mon Jun 10 19:03:35 2002
++++ freetype-2.1.2/src/autohint/ahglyph.c Fri Aug 9 13:50:28 2002
+@@ -815,7 +815,7 @@
+ segment_dir = point->out_dir;
+
+ /* clear all segment fields */
+- FT_MEM_SET( segment, 0, sizeof ( *segment ) );
++ FT_ZERO( segment );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+@@ -877,7 +877,7 @@
+ if ( min_point )
+ {
+ /* clear all segment fields */
+- FT_MEM_SET( segment, 0, sizeof ( *segment ) );
++ FT_ZERO( segment );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+@@ -893,7 +893,7 @@
+ if ( max_point )
+ {
+ /* clear all segment fields */
+- FT_MEM_SET( segment, 0, sizeof ( *segment ) );
++ FT_ZERO( segment );
+
+ segment->dir = segment_dir;
+ segment->flags = ah_edge_normal;
+@@ -983,20 +983,20 @@
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
+
+- len = max - min;
+- dist = seg2->pos - seg1->pos;
+- if ( dist < 0 )
+- dist = -dist;
+-
+- if ( len < 8 )
+- score = 300*8 + dist - len*3;
+- else
+- score = dist + 300/len;
+-
+- if ( score < best_score )
++ len = max - min;
++ if ( len >= 8 )
+ {
+- best_score = score;
+- best_segment = seg2;
++ dist = seg2->pos - seg1->pos;
++ if ( dist < 0 )
++ dist = -dist;
++
++ score = dist + 3000 / len;
++
++ if ( score < best_score )
++ {
++ best_score = score;
++ best_segment = seg2;
++ }
+ }
+ }
+ }
+@@ -1009,7 +1009,6 @@
+ best_segment->num_linked++;
+ }
+
+-
+ } /* edges 1 */
+
+ /* now, compute the `serif' segments */
+@@ -1116,7 +1115,7 @@
+ edge_limit++;
+
+ /* clear all edge fields */
+- FT_MEM_SET( edge, 0, sizeof ( *edge ) );
++ FT_MEM_ZERO( edge, sizeof ( *edge ) );
+
+ /* add the segment to the new edge's list */
+ edge->first = seg;
+--- freetype-2.1.2/src/autohint/ahhint.c.autohint Sat Mar 30 08:16:33 2002
++++ freetype-2.1.2/src/autohint/ahhint.c Fri Aug 9 13:50:28 2002
+@@ -30,7 +30,7 @@
+ #define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data)
+
+ #define AH_USE_IUP
+-
++#define OPTIM_STEM_SNAP
+
+ /*************************************************************************/
+ /*************************************************************************/
+@@ -40,7 +40,7 @@
+ /*************************************************************************/
+ /*************************************************************************/
+
+-
++#if 0
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+ static FT_Pos
+@@ -51,6 +51,7 @@
+ int n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
++ FT_Pos scaled;
+
+
+ for ( n = 0; n < count; n++ )
+@@ -70,41 +71,79 @@
+ }
+ }
+
++ scaled = (reference+32) & -64;
++
+ if ( width >= reference )
+ {
+- width -= 0x21;
+- if ( width < reference )
++ if ( width < scaled + 48 )
+ width = reference;
+ }
+ else
+ {
+- width += 0x21;
+- if ( width > reference )
++ if ( width > scaled - 48 )
+ width = reference;
+ }
+
+ return width;
+ }
++#endif
+
+-
+- /* align one stem edge relative to the previous stem edge */
+- static void
+- ah_align_linked_edge( AH_Hinter* hinter,
+- AH_Edge* base_edge,
+- AH_Edge* stem_edge,
+- int vertical )
++ /* compute the snapped width of a given stem */
++ static FT_Pos
++ ah_compute_stem_width( AH_Hinter* hinter,
++ int vertical,
++ FT_Pos width )
+ {
+- FT_Pos dist = stem_edge->opos - base_edge->opos;
+ AH_Globals* globals = &hinter->globals->scaled;
+- FT_Pos sign = 1;
++ FT_Pos dist = width;
++ FT_Int sign = 0;
+
+
+ if ( dist < 0 )
+ {
+- dist = -dist;
+- sign = -1;
++ dist = -width;
++ sign = 1;
+ }
+
++#if 1
++ if ( dist < 64 )
++ dist = 64;
++
++ {
++ FT_Pos delta = dist - globals->stds[vertical];
++
++
++ if ( delta < 0 )
++ delta = -delta;
++
++ if ( delta < 40 )
++ {
++ dist = globals->stds[vertical];
++ if ( dist < 32 )
++ dist = 32;
++ }
++
++ if ( dist < 3 * 64 )
++ {
++ delta = ( dist & 63 );
++ dist &= -64;
++
++ if ( delta < 10 )
++ dist += delta;
++
++ else if ( delta < 32 )
++ dist += 10;
++
++ else if ( delta < 54 )
++ dist += 54;
++
++ else
++ dist += delta;
++ }
++ else
++ dist = ( dist + 32 ) & -64;
++ }
++#else
+ if ( vertical )
+ {
+ dist = ah_snap_width( globals->heights, globals->num_heights, dist );
+@@ -138,14 +177,33 @@
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+- dist = ( dist + 42 ) & -64;
++ dist = ( dist + 22 ) & -64;
+ else
+ /* XXX: round otherwise, prevent color fringes in LCD mode */
+ dist = ( dist + 32 ) & -64;
+ }
+ }
++#endif
++
++ if ( sign )
++ dist = -dist;
++
++ return dist;
++ }
+
+- stem_edge->pos = base_edge->pos + sign * dist;
++
++ /* align one stem edge relative to the previous stem edge */
++ static void
++ ah_align_linked_edge( AH_Hinter* hinter,
++ AH_Edge* base_edge,
++ AH_Edge* stem_edge,
++ int vertical )
++ {
++ FT_Pos dist = stem_edge->opos - base_edge->opos;
++
++
++ stem_edge->pos = base_edge->pos +
++ ah_compute_stem_width( hinter, vertical, dist );
+ }
+
+
+@@ -168,6 +226,10 @@
+ sign = -1;
+ }
+
++#if 0
++ if ( dist < 32 )
++ dist = 32;
++#else
+ /* do not strengthen serifs */
+ if ( base->flags & ah_edge_done )
+ {
+@@ -179,6 +241,7 @@
+ else
+ dist = 0;
+ }
++#endif
+
+ serif->pos = base->pos + sign * dist;
+ }
+@@ -286,12 +349,12 @@
+
+ /* now, align the stem */
+
+- /* this should not happen, but it's better to be safe.. */
++ /* this should not happen, but it's better to be safe. */
+ if ( edge2->blue_edge || edge2 < edge )
+ {
+
+ #if 0
+- printf( "strange blue alignement, edge %d to %d\n",
++ printf( "strange blue alignment, edge %d to %d\n",
+ edge - edges, edge2 - edges );
+ #endif
+
+@@ -301,39 +364,66 @@
+ }
+
+ {
++#if 0
+ FT_Bool min = 0;
+- FT_Pos delta;
++#endif
++
+
+ if ( !anchor )
+ {
+ edge->pos = ( edge->opos + 32 ) & -64;
+ anchor = edge;
++
++ edge->flags |= ah_edge_done;
++
++ ah_align_linked_edge( hinter, edge, edge2, dimension );
+ }
+ else
+- edge->pos = anchor->pos +
+- ( ( edge->opos - anchor->opos + 32 ) & -64 );
++ {
++ FT_Pos org_pos, org_len, org_center, cur_len;
++ FT_Pos cur_pos1, cur_pos2, delta1, delta2;
+
+- edge->flags |= ah_edge_done;
+
+- if ( edge > edges && edge->pos < edge[-1].pos )
+- {
+- edge->pos = edge[-1].pos;
+- min = 1;
+- }
++ org_pos = anchor->pos + (edge->opos - anchor->opos);
++ org_len = edge2->opos - edge->opos;
++ org_center = org_pos + ( org_len >> 1 );
+
+- ah_align_linked_edge( hinter, edge, edge2, dimension );
+- delta = 0;
+- if ( edge2 + 1 < edge_limit &&
+- edge2[1].flags & ah_edge_done )
+- delta = edge2[1].pos - edge2->pos;
++ cur_len = ah_compute_stem_width( hinter, dimension, org_len );
+
+- if ( delta < 0 )
+- {
+- edge2->pos += delta;
+- if ( !min )
+- edge->pos += delta;
++ cur_pos1 = ( org_pos + 32 ) & -64;
++ delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
++ if ( delta1 < 0 )
++ delta1 = -delta1;
++
++ cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - cur_len;
++ delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center );
++ if ( delta2 < 0 )
++ delta2 = -delta2;
++
++ edge->pos = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2;
++ edge2->pos = edge->pos + cur_len;
++
++ edge->flags |= ah_edge_done;
++ edge2->flags |= ah_edge_done;
++
++ if ( edge > edges && edge->pos < edge[-1].pos )
++ edge->pos = edge[-1].pos;
++
++#if 0
++ delta = 0;
++ if ( edge2 + 1 < edge_limit &&
++ edge2[1].flags & ah_edge_done )
++ delta = edge2[1].pos - edge2->pos;
++
++ if ( delta < 0 )
++ {
++ edge2->pos += delta;
++ if ( !min )
++ edge->pos += delta;
++ }
++ edge2->flags |= ah_edge_done;
++#endif
+ }
+- edge2->flags |= ah_edge_done;
+ }
+ }
+
+@@ -348,9 +438,7 @@
+ continue;
+
+ if ( edge->serif )
+- {
+ ah_align_serif_edge( hinter, edge->serif, edge, dimension );
+- }
+ else if ( !anchor )
+ {
+ edge->pos = ( edge->opos + 32 ) & -64;
+@@ -855,6 +943,9 @@
+ for ( n = 0; n < design->num_heights; n++ )
+ scaled->heights[n] = FT_MulFix( design->heights[n], y_scale );
+
++ scaled->stds[0] = ( design->num_widths > 0 ) ? scaled->widths[0] : 32000;
++ scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000;
++
+ /* scale the blue zones */
+ for ( n = 0; n < ah_blue_max; n++ )
+ {
+@@ -1030,6 +1121,7 @@
+ {
+ FT_Matrix imatrix;
+
++
+ imatrix = internal->glyph_matrix;
+ hinter->trans_delta = internal->glyph_delta;
+ hinter->trans_matrix = imatrix;
+--- freetype-2.1.2/src/autohint/ahoptim.c.autohint Fri Apr 12 05:31:45 2002
++++ freetype-2.1.2/src/autohint/ahoptim.c Fri Aug 9 13:50:28 2002
+@@ -814,7 +814,7 @@
+ FT_Error error;
+
+
+- FT_MEM_SET( optimizer, 0, sizeof ( *optimizer ) );
++ FT_MEM_ZERO( optimizer, sizeof ( *optimizer ) );
+ optimizer->outline = outline;
+ optimizer->memory = memory;
+
+--- freetype-2.1.2/src/autohint/ahtypes.h.autohint Sat Mar 30 08:16:33 2002
++++ freetype-2.1.2/src/autohint/ahtypes.h Fri Aug 9 13:50:28 2002
+@@ -423,6 +423,8 @@
+ FT_Int num_widths;
+ FT_Int num_heights;
+
++ FT_Pos stds[2];
++
+ FT_Pos widths [AH_MAX_WIDTHS];
+ FT_Pos heights[AH_MAX_HEIGHTS];
+
--- /dev/null
+--- freetype-2.1.2/src/pcf/pcfdriver.c.leftright Wed Aug 28 23:36:54 2002
++++ freetype-2.1.2/src/pcf/pcfdriver.c Wed Aug 28 23:39:26 2002
+@@ -509,9 +509,9 @@
+ slot->bitmap_top = metric->ascent;
+
+ slot->metrics.horiAdvance = metric->characterWidth << 6 ;
+- slot->metrics.horiBearingX = metric->rightSideBearing << 6 ;
++ slot->metrics.horiBearingX = metric->leftSideBearing << 6 ;
+ slot->metrics.horiBearingY = metric->ascent << 6 ;
+- slot->metrics.width = metric->characterWidth << 6 ;
++ slot->metrics.width = (metric->rightSideBearing - metric->leftSideBearing) << 6 ;
+ slot->metrics.height = bitmap->rows << 6;
+
+ slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
--- /dev/null
+diff --speed-large-files --minimal -Nru tmp/freetype-2.1.2/src/sfnt/ttcmap0.c work/freetype-2.1.2/src/sfnt/ttcmap0.c
+--- tmp/freetype-2.1.2/src/sfnt/ttcmap0.c 2002-06-11 09:03:35.000000000 +1000
++++ work/freetype-2.1.2/src/sfnt/ttcmap0.c 2002-10-01 18:12:43.000000000 +1000
+@@ -680,7 +680,7 @@
+ FT_INVALID_DATA;
+ }
+
+- if ( offset )
++ if ( offset && offset != 0xFFFFU )
+ {
+ p += offset; /* start of glyph id array */
+
+@@ -692,10 +692,10 @@
+ /* check glyph indices within the segment range */
+ if ( valid->level >= FT_VALIDATE_TIGHT )
+ {
+- FT_UInt idx;
++ FT_UInt i, idx;
+
+
+- for ( ; start < end; )
++ for ( i = start; i < end; i++ )
+ {
+ idx = FT_NEXT_USHORT( p );
+ if ( idx != 0 )
+@@ -708,6 +708,16 @@
+ }
+ }
+ }
++ /* Some fonts (erroneously?) use a range offset of 0xFFFF */
++ /* to mean missing glyph in cmap table */
++ /* */
++ else if ( offset == 0xFFFFU )
++ {
++ if ( valid->level >= FT_VALIDATE_PARANOID ||
++ n != num_segs - 1 ||
++ !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
++ FT_INVALID_DATA;
++ }
+
+ last = end;
+ }
+@@ -769,6 +779,9 @@
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
++ if ( offset == 0xFFFFU )
++ goto Exit;
++
+ if ( offset != 0 )
+ {
+ p += offset + 2 * ( idx - start );
+@@ -813,6 +826,9 @@
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
++ if ( offset == 0xFFFFU )
++ goto Exit;
++
+ if ( offset != 0 )
+ {
+ p += offset + 2 * ( idx - start );
+@@ -879,6 +895,9 @@
+ p += num_segs2;
+ offset = TT_PEEK_USHORT( p );
+
++ if ( offset == 0xFFFFU )
++ goto Exit;
++
+ if ( offset != 0 )
+ {
+ /* parse the glyph ids array for non-0 index */
--- /dev/null
+--- freetype-2.1.1/src/pshinter/pshalgo2.c.primaryhints Sat Jun 29 14:24:34 2002
++++ freetype-2.1.1/src/pshinter/pshalgo2.c Sat Jun 29 14:48:05 2002
+@@ -1130,6 +1130,7 @@
+ /* process secondary hints to "selected" points */
+ if ( num_masks > 1 )
+ {
++ first = mask->end_point;
+ mask++;
+ for ( ; num_masks > 1; num_masks--, mask++ )
+ {
+--- freetype-2.1.2/src/pshinter/pshglob.c.stdw Tue Jul 9 11:08:25 2002
++++ freetype-2.1.2/src/pshinter/pshglob.c Tue Jul 9 11:25:36 2002
+@@ -629,7 +629,7 @@
+ PSH_Width write = dim->stdw.widths;
+
+
+- write->org = priv->standard_width[1];
++ write->org = priv->standard_width[0];
+ write++;
+
+ read = priv->snap_widths;
+@@ -649,7 +649,7 @@
+ PSH_Width write = dim->stdw.widths;
+
+
+- write->org = priv->standard_height[1];
++ write->org = priv->standard_height[0];
+ write++;
+
+ read = priv->snap_heights;
--- /dev/null
+--- 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 );
+
++
++ /*************************************************************************/
++ /* */
++ /* <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
++
++ /*************************************************************************/
++ /* */
+ /* <Enum> */
+ /* FT_Render_Mode */
+ /* */
--- /dev/null
+--- freetype-2.1.2/src/base/ftoutln.c.transform Thu Jun 20 06:57:04 2002
++++ freetype-2.1.2/src/base/ftoutln.c Tue Jul 23 14:26:11 2002
+@@ -628,9 +628,9 @@
+ return;
+
+ xz = FT_MulFix( vector->x, matrix->xx ) +
+- FT_MulFix( vector->y, matrix->yx );
++ FT_MulFix( vector->y, matrix->xy );
+
+- yz = FT_MulFix( vector->x, matrix->xy ) +
++ yz = FT_MulFix( vector->x, matrix->yx ) +
+ FT_MulFix( vector->y, matrix->yy );
+
+ vector->x = xz;
+--- freetype-2.1.2/src/truetype/ttgload.c.transform Thu Jun 20 06:57:04 2002
++++ freetype-2.1.2/src/truetype/ttgload.c Tue Jul 23 14:26:11 2002
+@@ -544,8 +544,8 @@
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ {
+ xx = (FT_Fixed)FT_GET_SHORT() << 2;
+- xy = (FT_Fixed)FT_GET_SHORT() << 2;
+ yx = (FT_Fixed)FT_GET_SHORT() << 2;
++ xy = (FT_Fixed)FT_GET_SHORT() << 2;
+ yy = (FT_Fixed)FT_GET_SHORT() << 2;
+ }
+