diff --git a/ChangeLog b/ChangeLog index e7abe8b62..e499c511c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2001-05-14 David Turner + + * src/base/ftcalc.c (FT_DivFix): fixed a bug in the 64-bit code that + created incorrect scale factors !! + + * src/autohint/ahglobal.c, src/autohint/ahglyph.c, src/autohint/ahhint.c: + fixed the incorrect blue zone computations, and improved the composite + support. Note that these changes result in improved rendering, while + sometimes introducing their own artefacts. That's probably the last + big change to the autohinter before the introduction of its complete + replacement.. + 2001-05-12 Werner Lemberg * include/freetype/ftbbox.h: FTBBOX_H -> __FTBBOX_H__. diff --git a/src/autohint/ahglobal.c b/src/autohint/ahglobal.c index 68f68c40a..f2ebc6edb 100644 --- a/src/autohint/ahglobal.c +++ b/src/autohint/ahglobal.c @@ -47,7 +47,7 @@ for ( i = 1; i < count; i++ ) { - for ( j = i; j > 1; j-- ) + for ( j = i; j > 0; j-- ) { if ( table[j] > table[j - 1] ) break; diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 252572dfc..6656ba48b 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -28,7 +28,109 @@ #include -#define xxxAH_DEBUG_GLYPH + +#ifdef AH_DEBUG + + void ah_dump_edges( AH_Outline* outline ) + { + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Segment* segments; + FT_Int dimension; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + segments = outline->horz_segments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge* edge; + + + printf ( "Table of %s edges:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos ]\n" ); + + for ( edge = edges; edge < edge_limit; edge++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", + edge - edges, + (int)edge->fpos, + edge->dir == ah_dir_up + ? "up" + : ( edge->dir == ah_dir_down + ? "down" + : ( edge->dir == ah_dir_left + ? "left" + : ( edge->dir == ah_dir_right + ? "right" + : "none" ) ) ), + edge->link ? ( edge->link - edges ) : -1, + edge->serif ? ( edge->serif - edges ) : -1, + edge->blue_edge ? 'y' : 'n', + edge->opos / 64.0, + edge->pos / 64.0 ); + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + segments = outline->vert_segments; + } + } + + + /* A function used to dump the array of linked segments */ + void ah_dump_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* segment_limit; + AH_Point* points; + FT_Int dimension; + + + points = outline->points; + segments = outline->horz_segments; + segment_limit = segments + outline->num_hsegments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment* seg; + + + printf ( "Table of %s segments:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link | serif |" + " numl | first | start ]\n" ); + + for ( seg = segments; seg < segment_limit; seg++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", + seg - segments, + (int)seg->pos, + seg->dir == ah_dir_up + ? "up" + : ( seg->dir == ah_dir_down + ? "down" + : ( seg->dir == ah_dir_left + ? "left" + : ( seg->dir == ah_dir_right + ? "right" + : "none" ) ) ), + seg->link ? (seg->link-segments) : -1, + seg->serif ? (seg->serif-segments) : -1, + (int)seg->num_linked, + seg->first - points, + seg->last - points ); + } + + segments = outline->vert_segments; + segment_limit = segments + outline->num_vsegments; + } + } + +#endif /* AH_DEBUG */ /* compute the direction value of a given vector.. */ @@ -344,8 +446,6 @@ outline->num_hsegments = 0; outline->num_vsegments = 0; -#if 1 - /* We can't rely on the value of `FT_Outline.flags' to know the fill */ /* direction used for a glyph, given that some fonts are broken (e.g. */ /* the Arphic ones). We thus recompute it each time we need to. */ @@ -359,23 +459,6 @@ outline->horz_major_dir = ah_dir_right; } -#else /* !1 */ - - /* Compute the vertical and horizontal major directions; this is */ - /* currently done by inspecting the `ft_outline_reverse_fill' flag. */ - /* However, some fonts have improper glyphs, and it'd be a good idea */ - /* to be able to re-compute these values on the fly. */ - outline->vert_major_dir = ah_dir_up; - outline->horz_major_dir = ah_dir_left; - - if ( source->flags & ft_outline_reverse_fill ) - { - outline->vert_major_dir = ah_dir_down; - outline->horz_major_dir = ah_dir_right; - } - -#endif /* !1 */ - outline->x_scale = face->size->metrics.x_scale; outline->y_scale = face->size->metrics.y_scale; @@ -952,59 +1035,6 @@ } -#ifdef AH_DEBUG_GLYPH - - /* A function used to dump the array of linked segments */ - void ah_dump_segments( AH_Outline* outline ) - { - AH_Segment* segments; - AH_Segment* segment_limit; - AH_Point* points; - FT_Int dimension; - - - points = outline->points; - segments = outline->horz_segments; - segment_limit = segments + outline->num_hsegments; - - for ( dimension = 1; dimension >= 0; dimension-- ) - { - AH_Segment* seg; - - - printf ( "Table of %s segments:\n", - !dimension ? "vertical" : "horizontal" ); - printf ( " [ index | pos | dir | link | serif |" - " numl | first | start ]\n" ); - - for ( seg = segments; seg < segment_limit; seg++ ) - { - printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", - seg - segments, - (int)seg->pos, - seg->dir == ah_dir_up - ? "up" - : ( seg->dir == ah_dir_down - ? "down" - : ( seg->dir == ah_dir_left - ? "left" - : ( seg->dir == ah_dir_right - ? "right" - : "none" ) ) ), - seg->link ? (seg->link-segments) : -1, - seg->serif ? (seg->serif-segments) : -1, - (int)seg->num_linked, - seg->first - points, - seg->last - points ); - } - - segments = outline->vert_segments; - segment_limit = segments + outline->num_vsegments; - } - } - -#endif /* AH_DEBUG_GLYPH */ - static void ah_outline_compute_edges( AH_Outline* outline ) @@ -1218,7 +1248,7 @@ /* set the round/straight flags */ edge->flags = ah_edge_normal; - if ( is_straight == 0 && is_round ) + if ( is_round > 0 && is_round >= is_straight ) edge->flags |= ah_edge_round; /* set the edge's main direction */ @@ -1286,6 +1316,38 @@ AH_Globals* globals = &face_globals->design; FT_Fixed y_scale = outline->y_scale; + FT_Bool blue_active[ ah_blue_max ]; + + + /* compute which blue zones are active, i.e. have their scaled */ + /* size < 3/4 pixels */ + { + AH_Blue blue; + FT_Bool check = 0; + + for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ ) + { + FT_Pos ref, shoot, dist; + + ref = globals->blue_refs[blue]; + shoot = globals->blue_shoots[blue]; + dist = ref-shoot; + if (dist < 0) + dist = -dist; + + blue_active[blue] = 0; + + if ( FT_MulFix( dist, y_scale ) < 48 ) + { + blue_active[blue] = 1; + check = 1; + } + } + + /* return immediately if no blue zone is active */ + if (!check) + return; + } /* compute for each horizontal edge, which blue zone is closer */ for ( ; edge < edge_limit; edge++ ) @@ -1309,6 +1371,8 @@ FT_Bool is_top_blue = AH_IS_TOP_BLUE( blue ); FT_Bool is_major_dir = edge->dir == outline->horz_major_dir; + if ( !blue_active[blue] ) + continue; /* if it is a top zone, the edge must be against the major */ /* direction; if it is a bottom zone, it must be in the major */ @@ -1392,58 +1456,6 @@ } -#ifdef AH_DEBUG_GLYPH - - void ah_dump_edges( AH_Outline* outline ) - { - AH_Edge* edges; - AH_Edge* edge_limit; - AH_Segment* segments; - FT_Int dimension; - - - edges = outline->horz_edges; - edge_limit = edges + outline->num_hedges; - segments = outline->horz_segments; - - for ( dimension = 1; dimension >= 0; dimension-- ) - { - AH_Edge* edge; - - - printf ( "Table of %s edges:\n", - !dimension ? "vertical" : "horizontal" ); - printf ( " [ index | pos | dir | link |" - " serif | blue | opos | pos ]\n" ); - - for ( edge = edges; edge < edge_limit; edge++ ) - { - printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", - edge - edges, - (int)edge->fpos, - edge->dir == ah_dir_up - ? "up" - : ( edge->dir == ah_dir_down - ? "down" - : ( edge->dir == ah_dir_left - ? "left" - : ( edge->dir == ah_dir_right - ? "right" - : "none" ) ) ), - edge->link ? ( edge->link - edges ) : -1, - edge->serif ? ( edge->serif - edges ) : -1, - edge->blue_edge ? 'y' : 'n', - edge->opos / 64.0, - edge->pos / 64.0 ); - } - - edges = outline->vert_edges; - edge_limit = edges + outline->num_vedges; - segments = outline->vert_segments; - } - } - -#endif /* AH_DEBUG_GLYPH */ /* END */ diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c index 754687c3a..ead32fde5 100644 --- a/src/autohint/ahhint.c +++ b/src/autohint/ahhint.c @@ -1051,13 +1051,13 @@ switch ( slot->format ) { case ft_glyph_format_outline: - + /* translate glyph outline if we need to */ if ( hinter->transformed ) { FT_UInt n = slot->outline.n_points; FT_Vector* point = slot->outline.points; - + for ( ; n > 0; point++, n-- ) { @@ -1065,7 +1065,7 @@ point->y += hinter->trans_delta.y; } } - + /* copy the outline points in the loader's current */ /* extra points, which is used to keep original glyph coordinates */ error = ah_loader_check_points( gloader, slot->outline.n_points + 2, @@ -1365,7 +1365,11 @@ ah_loader_rewind( hinter->loader ); +#if 1 + load_flags = FT_LOAD_NO_SCALE; +#else load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; +#endif error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index dfcecc1c5..327b31800 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -55,7 +55,8 @@ FT_EXPORT_DEF( FT_Fixed ) FT_RoundFix( FT_Fixed a ) { - return( ( a + 0x8000L ) & -0x10000L ); + return ( a >= 0 ) ? ( a + 0x8000L ) & -0x10000L + : -((-a + 0x8000L ) & -0x10000L ); } @@ -63,7 +64,8 @@ FT_EXPORT_DEF( FT_Fixed ) FT_CeilFix( FT_Fixed a ) { - return( ( a + 0x10000L - 1 ) & -0x10000L ); + return ( a >= 0 ) ? ( a + 0xFFFFL ) & -0x10000L + : -((-a + 0xFFFFL ) & -0x10000L ); } @@ -71,7 +73,8 @@ FT_EXPORT_DEF( FT_Fixed ) FT_FloorFix( FT_Fixed a ) { - return( a & -0x10000L ); + return ( a >= 0 ) ? a & -0x10000L + : -((-a) & -0x10000L ); } @@ -176,16 +179,16 @@ FT_Int32 s; FT_UInt32 q; - - s = a; a = ABS(a); - s ^= b; b = ABS(b); + s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } if ( b == 0 ) /* check for division by 0 */ q = 0x7FFFFFFFL; else /* compute result directly */ - q = ( ((FT_Int64)a + (b >> 1)) << 16 ) / b; + q = ( ((FT_Int64)a << 16) + (b >> 1)) / b; return (FT_Long)( s < 0 ? -q : q ); }