diff --git a/ChangeLog b/ChangeLog index 17b832914..18bf6a6cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-11-23 David Turner + + * src/autofit/afhints.c, src/autofit/afhints.h, src/autofit/aflatin.c, + src/autofit/aftypes.h: Misc. auto-hinter improvements + 2006-11-22 Werner Lemberg Fix Savannah bug #15553. @@ -9,7 +14,7 @@ 2006-11-18 Werner Lemberg Because FT_Load_Glyph expects CID values for CID-keyed fonts, the - test for a valid glyph index must be deferred to the font drivers. + test for a valid glyph index must be deferred to the font drivers. This patch fixes Savannah bug #18301. * src/base/ftobjs.c (FT_Load_Glyph): Don't check `glyph_index'. diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index 94692f50e..7335a0076 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -206,19 +206,18 @@ printf ( "Table of %s segments:\n", dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); printf ( " [ index | pos | dir | link | serif |" - " numl | first | start ]\n" ); + " height | extra ]\n" ); for ( seg = segments; seg < limit; seg++ ) { - printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", + printf ( " [ %5d | %4d | %5s | %4d | %5d | %5d | %5d ]\n", seg - segments, (int)seg->pos, af_dir_str( seg->dir ), AF_INDEX_NUM( seg->link, segments ), AF_INDEX_NUM( seg->serif, segments ), - (int)seg->num_linked, - seg->first - points, - seg->last - points ); + seg->height, + seg->height - (seg->max_coord - seg->min_coord) ); } printf( "\n" ); } diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h index b6d8896f7..3bde12fc9 100644 --- a/src/autofit/afhints.h +++ b/src/autofit/afhints.h @@ -125,6 +125,7 @@ FT_BEGIN_HEADER FT_Short pos; /* position of segment */ FT_Short min_coord; /* minimum coordinate of segment */ FT_Short max_coord; /* maximum coordinate of segment */ + FT_Short height; AF_Edge edge; /* the segment's parent edge */ AF_Segment edge_next; /* link to next segment in parent edge */ diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index b6d859fa7..91391fc6b 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -471,7 +471,7 @@ if ( blue ) { FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); - FT_Pos fitted = FT_PIX_ROUND( scaled ); + FT_Pos fitted = (scaled + 40) & ~63; if ( scaled != fitted ) @@ -723,6 +723,7 @@ segment->min_coord = (FT_Short)min_pos; segment->max_coord = (FT_Short)max_pos; + segment->height = segment->max_coord - segment->min_coord; on_edge = 0; segment = NULL; @@ -770,6 +771,51 @@ } /* contours */ + + /* now slightly increase the height of segments when this makes sense + * this is used to better detect and ignore serifs + */ + { + AF_Segment segments = axis->segments; + AF_Segment segments_end = segments + axis->num_segments; + + for ( segment = segments; segment < segments_end; segment++ ) + { + AF_Point first = segment->first; + AF_Point last = segment->last; + FT_Pos first_v = first->v; + FT_Pos last_v = last->v; + + if ( first == last ) + continue; + + if ( first_v < last_v ) + { + AF_Point p; + + p = first->prev; + if ( p->v < first_v ) + segment->height += (first_v - p->v) >> 1; + + p = last->next; + if ( p->v > last_v ) + segment->height += (p->v - last_v) >> 1; + } + else + { + AF_Point p; + + p = first->prev; + if ( p->v > first_v ) + segment->height += (p->v - first_v) >> 1; + + p = last->next; + if ( p->v < last_v ) + segment->height += (last_v - p->v) >> 1; + } + } + } + #ifdef AF_HINT_METRICS /* we need to ensure that there are edges on the left-most and */ /* right-most points of the glyph in order to hint the metrics; */ @@ -862,7 +908,7 @@ if ( len_threshold == 0 ) len_threshold = 1; - len_score = AF_LATIN_CONSTANT( hints->metrics, 3000 ); + len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 ); /* now compare each segment to the others */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) @@ -961,12 +1007,12 @@ : AF_DIR_RIGHT; /* - * We ignore all segments that are less than 1.5 pixels in length, + * We ignore all segments that are less than 1 pixels in length, * to avoid many problems with serif fonts. We compute the * corresponding threshold in font units. */ if ( dim == AF_DIMENSION_HORZ ) - segment_length_threshold = FT_DivFix( 64, hints->y_scale ); + segment_length_threshold = FT_DivFix( 96, hints->y_scale ); else segment_length_threshold = 0; @@ -1000,7 +1046,7 @@ FT_Int ee; - if ( seg->max_coord - seg->min_coord < segment_length_threshold ) + if ( seg->height < segment_length_threshold ) continue; /* look for an edge corresponding to the segment */ @@ -1742,7 +1788,7 @@ /* now align the stem */ /* this should not happen, but it's better to be safe */ - if ( edge2->blue_edge || edge2 < edge ) + if ( edge2->blue_edge ) { AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges )); @@ -1790,14 +1836,14 @@ cur_pos1 += d_off; edge->pos = cur_pos1 - cur_len / 2; - edge2->pos = cur_pos1 + cur_len / 2; - + edge2->pos = edge->pos + cur_len; } else edge->pos = FT_PIX_ROUND( edge->opos ); - AF_LOG(( "ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); + AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) snapped to (%.2f) (%.2f)\n", + edge-edges, edge->opos / 64., edge2-edges, edge2->opos/64., + edge->pos / 64., edge2->pos / 64. )); anchor = edge; edge->flags |= AF_EDGE_DONE; @@ -1859,7 +1905,6 @@ edge2-edges, edge2->opos / 64.0, edge->pos / 64.0, edge2->pos / 64.0 )); } - else { org_pos = anchor->pos + ( edge->opos - anchor->opos ); @@ -1973,20 +2018,58 @@ */ for ( edge = edges; edge < edge_limit; edge++ ) { + FT_Pos delta; + if ( edge->flags & AF_EDGE_DONE ) continue; + delta = 1000; if ( edge->serif ) + { + delta = edge->serif->opos - edge->opos; + if ( delta < 0 ) + delta = -delta; + } + + if ( delta < 64+16 ) + { af_latin_align_serif_edge( hints, edge->serif, edge ); + AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) aligned to (%.2f)\n", edge-edges, + edge->opos/64., edge->serif - edges, edge->serif->opos/64., edge->pos/64.0 )); + } else if ( !anchor ) { + AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n", + edge-edges, edge->opos/64., edge->pos/64. )); edge->pos = FT_PIX_ROUND( edge->opos ); anchor = edge; } else - edge->pos = anchor->pos + - FT_PIX_ROUND( edge->opos - anchor->opos ); + { + AF_Edge before, after; + for ( before = edge-1; before >= edges; before-- ) + if ( before->flags & AF_EDGE_DONE ) + break; + + for ( after = edge+1; after < edge_limit; after++ ) + if ( after->flags & AF_EDGE_DONE ) + break; + + if ( before >= edges && before < edge && + after < edge_limit && after > edge ) + { + edge->pos = before->pos + FT_MulDiv( edge->opos - before->opos, + after->pos - before->pos, + after->opos - before->opos ); + } + else + edge->pos = anchor->pos + + FT_PIX_ROUND( edge->opos - anchor->opos ); + + AF_LOG(( "SERIF_LINK: edge %d (opos=%.2f) snapped to (%.2f)\n", + edge-edges, edge->opos/64., edge->pos/64. )); + } edge->flags |= AF_EDGE_DONE; if ( edge > edges && edge->pos < edge[-1].pos ) diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h index d1459a420..a94c7ee51 100644 --- a/src/autofit/aftypes.h +++ b/src/autofit/aftypes.h @@ -54,7 +54,7 @@ FT_BEGIN_HEADER /*************************************************************************/ #define xxAF_USE_WARPER /* only define to use warp hinting */ -#define AF_DEBUG +#define xxAF_DEBUG #ifdef AF_DEBUG