diff options
Diffstat (limited to 'src/autofit/aflatin.c')
-rw-r--r-- | src/autofit/aflatin.c | 312 |
1 files changed, 222 insertions, 90 deletions
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 8c6c430..d5876ff 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin script (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ +/* Copyright 2003-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -18,17 +18,28 @@ #include <ft2build.h> #include FT_ADVANCES_H +#include FT_INTERNAL_DEBUG_H #include "aflatin.h" #include "aferrors.h" -#ifdef AF_USE_WARPER +#ifdef AF_CONFIG_OPTION_USE_WARPER #include "afwarp.h" #endif /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_aflatin + + + /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** L A T I N G L O B A L M E T R I C S *****/ @@ -36,6 +47,10 @@ /*************************************************************************/ /*************************************************************************/ + + /* Find segments and links, compute all stem widths, and initialize */ + /* standard width and height for the glyph with given charcode. */ + FT_LOCAL_DEF( void ) af_latin_metrics_init_widths( AF_LatinMetrics metrics, FT_Face face, @@ -69,8 +84,12 @@ FT_ZERO( dummy ); dummy->units_per_em = metrics->units_per_em; - scaler->x_scale = scaler->y_scale = 0x10000L; - scaler->x_delta = scaler->y_delta = 0; + + scaler->x_scale = 0x10000L; + scaler->y_scale = 0x10000L; + scaler->x_delta = 0; + scaler->y_delta = 0; + scaler->face = face; scaler->render_mode = FT_RENDER_MODE_NORMAL; scaler->flags = 0; @@ -161,6 +180,9 @@ }; + /* Find all blue zones. Flat segments give the reference points, */ + /* round segments the overshoot positions. */ + static void af_latin_metrics_init_blues( AF_LatinMetrics metrics, FT_Face face ) @@ -177,11 +199,11 @@ /* we compute the blues simply by loading each character from the */ - /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */ + /* `af_latin_blue_chars[blues]' string, then finding its top-most or */ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */ - AF_LOG(( "blue zones computation\n" )); - AF_LOG(( "------------------------------------------------\n" )); + FT_TRACE5(( "blue zones computation\n" )); + FT_TRACE5(( "------------------------------------------------\n" )); for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) { @@ -191,7 +213,7 @@ FT_Pos* blue_shoot; - AF_LOG(( "blue %3d: ", bb )); + FT_TRACE5(( "blue %3d: ", bb )); num_flats = 0; num_rounds = 0; @@ -205,7 +227,7 @@ FT_Bool round = 0; - AF_LOG(( "'%c'", *p )); + FT_TRACE5(( "'%c'", *p )); /* load the character in the face -- skip unknown or empty ones */ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); @@ -229,7 +251,9 @@ FT_Int last = -1; - for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ ) + for ( nn = 0; + nn < glyph->outline.n_contours; + first = last + 1, nn++ ) { FT_Int old_best_point = best_point; FT_Int pp; @@ -268,7 +292,7 @@ best_last = last; } } - AF_LOG(( "%5d", best_y )); + FT_TRACE5(( "%5d", best_y )); } /* now check whether the point belongs to a straight or round */ @@ -311,12 +335,12 @@ } while ( next != best_point ); - /* now, set the `round' flag depending on the segment's kind */ + /* now set the `round' flag depending on the segment's kind */ round = FT_BOOL( FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON || FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON ); - AF_LOG(( "%c ", round ? 'r' : 'f' )); + FT_TRACE5(( "%c ", round ? 'r' : 'f' )); } if ( round ) @@ -325,7 +349,7 @@ flats[num_flats++] = best_y; } - AF_LOG(( "\n" )); + FT_TRACE5(( "\n" )); if ( num_flats == 0 && num_rounds == 0 ) { @@ -333,7 +357,7 @@ * we couldn't find a single glyph to compute this blue zone, * we will simply ignore it then */ - AF_LOG(( "empty\n" )); + FT_TRACE5(( "empty\n" )); continue; } @@ -376,7 +400,8 @@ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) - *blue_shoot = *blue_ref = ( shoot + ref ) / 2; + *blue_ref = + *blue_shoot = ( shoot + ref ) / 2; } blue->flags = 0; @@ -391,13 +416,17 @@ if ( bb == AF_LATIN_BLUE_SMALL_TOP ) blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; - AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); + FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); } + FT_TRACE5(( "\n" )); + return; } + /* Check whether all ASCII digits have the same advance width. */ + FT_LOCAL_DEF( void ) af_latin_metrics_check_digits( AF_LatinMetrics metrics, FT_Face face ) @@ -407,7 +436,6 @@ FT_Fixed advance, old_advance = 0; - /* check whether all ASCII digits have the same advance width; */ /* digit `0' is 0x30 in all supported charmaps */ for ( i = 0x30; i <= 0x39; i++ ) { @@ -444,6 +472,8 @@ } + /* Initialize global metrics. */ + FT_LOCAL_DEF( FT_Error ) af_latin_metrics_init( AF_LatinMetrics metrics, FT_Face face ) @@ -458,6 +488,7 @@ FT_ENCODING_APPLE_ROMAN, FT_ENCODING_ADOBE_STANDARD, FT_ENCODING_ADOBE_LATIN_1, + FT_ENCODING_NONE /* end of list */ }; @@ -485,6 +516,9 @@ } + /* Adjust scaling value, then scale and shift widths */ + /* and blue zones (if applicable) for given dimension. */ + static void af_latin_metrics_scale_dim( AF_LatinMetrics metrics, AF_Scaler scaler, @@ -550,9 +584,7 @@ else #endif if ( dim == AF_DIMENSION_VERT ) - { scale = FT_MulDiv( scale, fitted, scaled ); - } } } } @@ -571,7 +603,7 @@ metrics->root.scaler.y_delta = delta; } - /* scale the standard widths */ + /* scale the widths */ for ( nn = 0; nn < axis->width_count; nn++ ) { AF_Width width = axis->widths + nn; @@ -582,7 +614,7 @@ } /* an extra-light axis corresponds to a standard width that is */ - /* smaller than 0.75 pixels */ + /* smaller than 5/8 pixels */ axis->extra_light = (FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 ); @@ -605,9 +637,17 @@ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); if ( dist <= 48 && dist >= -48 ) { - FT_Pos delta1, delta2; +#if 0 + FT_Pos delta1; +#endif + FT_Pos delta2; + /* use discrete values for blue zone widths */ + +#if 0 + + /* generic, original code */ delta1 = blue->shoot.org - blue->ref.org; delta2 = delta1; if ( delta1 < 0 ) @@ -628,6 +668,28 @@ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); blue->shoot.fit = blue->ref.fit + delta2; +#else + + /* simplified version due to abs(dist) <= 48 */ + delta2 = dist; + if ( dist < 0 ) + delta2 = -delta2; + + if ( delta2 < 32 ) + delta2 = 0; + else if ( delta < 48 ) + delta2 = 32; + else + delta2 = 64; + + if ( dist < 0 ) + delta2 = -delta2; + + blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); + blue->shoot.fit = blue->ref.fit - delta2; + +#endif + blue->flags |= AF_LATIN_BLUE_ACTIVE; } } @@ -635,6 +697,8 @@ } + /* Scale global values in both directions. */ + FT_LOCAL_DEF( void ) af_latin_metrics_scale( AF_LatinMetrics metrics, AF_Scaler scaler ) @@ -655,6 +719,9 @@ /*************************************************************************/ /*************************************************************************/ + + /* Walk over all contours and compute its segments. */ + FT_LOCAL_DEF( FT_Error ) af_latin_hints_compute_segments( AF_GlyphHints hints, AF_Dimension dim ) @@ -808,7 +875,6 @@ min_pos = max_pos = point->u; segment->first = point; segment->last = point; - segment->contour = contour; on_edge = 1; } @@ -874,6 +940,8 @@ } + /* Link segments to form stems and serifs. */ + FT_LOCAL_DEF( void ) af_latin_hints_link_segments( AF_GlyphHints hints, AF_Dimension dim ) @@ -899,18 +967,18 @@ if ( seg1->dir != axis->major_dir || seg1->first == seg1->last ) continue; + /* search for stems having opposite directions, */ + /* with seg1 to the `left' of seg2 */ for ( seg2 = segments; seg2 < segment_limit; seg2++ ) - if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos ) { FT_Pos pos1 = seg1->pos; FT_Pos pos2 = seg2->pos; - FT_Pos dist = pos2 - pos1; - - if ( dist < 0 ) - dist = -dist; - { + if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 ) + { + /* compute distance between the two segments */ + FT_Pos dist = pos2 - pos1; FT_Pos min = seg1->min_coord; FT_Pos max = seg1->max_coord; FT_Pos len, score; @@ -922,11 +990,16 @@ if ( max > seg2->max_coord ) max = seg2->max_coord; + /* compute maximum coordinate difference of the two segments */ len = max - min; if ( len >= len_threshold ) { + /* small coordinate differences cause a higher score, and */ + /* segments with a greater distance cause a higher score also */ score = dist + len_score / len; + /* and we search for the smallest score */ + /* of the sum of the two values */ if ( score < seg1->score ) { seg1->score = score; @@ -943,7 +1016,7 @@ } } - /* now, compute the `serif' segments */ + /* now compute the `serif' segments, cf. explanations in `afhints.h' */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) { seg2 = seg1->link; @@ -960,6 +1033,8 @@ } + /* Link segments to edges, using feature analysis for selection. */ + FT_LOCAL_DEF( FT_Error ) af_latin_hints_compute_edges( AF_GlyphHints hints, AF_Dimension dim ) @@ -973,7 +1048,9 @@ AF_Segment segment_limit = segments + axis->num_segments; AF_Segment seg; +#if 0 AF_Direction up_dir; +#endif FT_Fixed scale; FT_Pos edge_distance_threshold; FT_Pos segment_length_threshold; @@ -984,11 +1061,13 @@ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale : hints->y_scale; +#if 0 up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP : AF_DIR_RIGHT; +#endif /* - * We ignore all segments that are less than 1 pixels in length, + * We ignore all segments that are less than 1 pixel in length * to avoid many problems with serif fonts. We compute the * corresponding threshold in font units. */ @@ -999,20 +1078,21 @@ /*********************************************************************/ /* */ - /* We will begin by generating a sorted table of edges for the */ - /* current direction. To do so, we simply scan each segment and try */ - /* to find an edge in our table that corresponds to its position. */ + /* We begin by generating a sorted table of edges for the current */ + /* direction. To do so, we simply scan each segment and try to find */ + /* an edge in our table that corresponds to its position. */ /* */ /* If no edge is found, we create and insert a new edge in the */ /* sorted table. Otherwise, we simply add the segment to the edge's */ - /* list which will be processed in the second step to compute the */ + /* list which gets processed in the second step to compute the */ /* edge's properties. */ /* */ - /* Note that the edges table is sorted along the segment/edge */ + /* Note that the table of edges is sorted along the segment/edge */ /* position. */ /* */ /*********************************************************************/ + /* assure that edge distance threshold is at most 0.25px */ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, scale ); if ( edge_distance_threshold > 64 / 4 ) @@ -1023,7 +1103,7 @@ for ( seg = segments; seg < segment_limit; seg++ ) { - AF_Edge found = 0; + AF_Edge found = NULL; FT_Int ee; @@ -1072,9 +1152,10 @@ edge->first = seg; edge->last = seg; - edge->fpos = seg->pos; edge->dir = seg->dir; - edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); + edge->fpos = seg->pos; + edge->opos = FT_MulFix( seg->pos, scale ); + edge->pos = edge->opos; seg->edge_next = seg; } else @@ -1091,9 +1172,9 @@ /*********************************************************************/ /* */ /* Good, we will now compute each edge's properties according to */ - /* segments found on its position. Basically, these are: */ + /* the segments found on its position. Basically, these are */ /* */ - /* - edge's main direction */ + /* - the edge's main direction */ /* - stem edge, serif edge or both (which defaults to stem then) */ /* - rounded edge, straight or both (which defaults to straight) */ /* - link for edge */ @@ -1126,13 +1207,15 @@ } while ( seg != edge->first ); } - /* now, compute each edge properties */ + /* now compute each edge properties */ for ( edge = edges; edge < edge_limit; edge++ ) { FT_Int is_round = 0; /* does it contain round segments? */ FT_Int is_straight = 0; /* does it contain straight segments? */ +#if 0 FT_Pos ups = 0; /* number of upwards segments */ FT_Pos downs = 0; /* number of downwards segments */ +#endif seg = edge->first; @@ -1148,11 +1231,13 @@ else is_straight++; +#if 0 /* check for segment direction */ if ( seg->dir == up_dir ) ups += seg->max_coord-seg->min_coord; else downs += seg->max_coord-seg->min_coord; +#endif /* check for links -- if seg->serif is set, then seg->link must */ /* be ignored */ @@ -1228,7 +1313,7 @@ edge->dir = 0; /* both up and down! */ #endif - /* gets rid of serifs if link is set */ + /* get rid of serifs if link is set */ /* XXX: This gets rid of many unpleasant artefacts! */ /* Example: the `c' in cour.pfa at size 13 */ @@ -1242,6 +1327,8 @@ } + /* Detect segments and edges for given dimension. */ + FT_LOCAL_DEF( FT_Error ) af_latin_hints_detect_features( AF_GlyphHints hints, AF_Dimension dim ) @@ -1256,10 +1343,13 @@ error = af_latin_hints_compute_edges( hints, dim ); } + return error; } + /* Compute all edges which lie within blue zones. */ + FT_LOCAL_DEF( void ) af_latin_hints_compute_blue_edges( AF_GlyphHints hints, AF_LatinMetrics metrics ) @@ -1283,8 +1373,10 @@ /* compute the initial threshold as a fraction of the EM size */ + /* (the value 40 is heuristic) */ best_dist = FT_MulFix( metrics->units_per_em / 40, scale ); + /* assure a minimum distance of 0.5px */ if ( best_dist > 64 / 2 ) best_dist = 64 / 2; @@ -1294,7 +1386,7 @@ FT_Bool is_top_blue, is_major_dir; - /* skip inactive blue zones (i.e., those that are too small) */ + /* skip inactive blue zones (i.e., those that are too large) */ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) ) continue; @@ -1325,9 +1417,10 @@ best_blue = & blue->ref; } - /* now, compare it to the overshoot position if the edge is */ - /* rounded, and if the edge is over the reference position of a */ - /* top zone, or under the reference position of a bottom zone */ + /* now compare it to the overshoot position and check whether */ + /* the edge is rounded, and whether the edge is over the */ + /* reference position of a top zone, or under the reference */ + /* position of a bottom zone */ if ( edge->flags & AF_EDGE_ROUND && dist != 0 ) { FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org ); @@ -1335,7 +1428,6 @@ if ( is_top_blue ^ is_under_ref ) { - blue = latin->blues + bb; dist = edge->fpos - blue->shoot.org; if ( dist < 0 ) dist = -dist; @@ -1357,6 +1449,8 @@ } + /* Initalize hinting engine. */ + static FT_Error af_latin_hints_init( AF_GlyphHints hints, AF_LatinMetrics metrics ) @@ -1370,7 +1464,7 @@ /* * correct x_scale and y_scale if needed, since they may have - * been modified `af_latin_metrics_scale_dim' above + * been modified by `af_latin_metrics_scale_dim' above */ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale; hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta; @@ -1380,7 +1474,7 @@ /* compute flags depending on render mode, etc. */ mode = metrics->root.scaler.render_mode; -#if 0 /* #ifdef AF_USE_WARPER */ +#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) { metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; @@ -1424,7 +1518,7 @@ hints->scaler_flags = scaler_flags; hints->other_flags = other_flags; - return 0; + return AF_Err_Ok; } @@ -1436,8 +1530,8 @@ /*************************************************************************/ /*************************************************************************/ - /* snap a given width in scaled coordinates to one of the */ - /* current standard widths */ + /* Snap a given width in scaled coordinates to one of the */ + /* current standard widths. */ static FT_Pos af_latin_snap_width( AF_Width widths, @@ -1484,7 +1578,9 @@ } - /* compute the snapped width of a given stem */ + /* Compute the snapped width of a given stem, ignoring very thin ones. */ + /* There is a lot of voodoo in this function; changing the hard-coded */ + /* parameters influence the whole hinting process. */ static FT_Pos af_latin_compute_stem_width( AF_GlyphHints hints, @@ -1516,11 +1612,12 @@ /* smooth hinting process: very lightly quantize the stem width */ /* leave the widths of serifs alone */ - - if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) + if ( ( stem_flags & AF_EDGE_SERIF ) && + vertical && + ( dist < 3 * 64 ) ) goto Done_Width; - else if ( ( base_flags & AF_EDGE_ROUND ) ) + else if ( base_flags & AF_EDGE_ROUND ) { if ( dist < 80 ) dist = 64; @@ -1534,8 +1631,6 @@ /* compare to standard width */ - if ( axis->width_count > 0 ) - { delta = dist - axis->widths[0].cur; if ( delta < 0 ) @@ -1549,7 +1644,6 @@ goto Done_Width; } - } if ( dist < 3 * 64 ) { @@ -1575,6 +1669,7 @@ else { /* strong hinting process: snap the stem width to integer pixels */ + FT_Pos org_dist = dist; @@ -1649,7 +1744,7 @@ } - /* align one stem edge relative to the previous stem edge */ + /* Align one stem edge relative to the previous stem edge. */ static void af_latin_align_linked_edge( AF_GlyphHints hints, @@ -1667,13 +1762,16 @@ stem_edge->pos = base_edge->pos + fitted_width; - AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), " + FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to (%.2f)," "dist was %.2f, now %.2f\n", stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0, stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 )); } + /* Shift the coordinates of the `serif' edge by the same amount */ + /* as the corresponding `base' edge has been moved already. */ + static void af_latin_align_serif_edge( AF_GlyphHints hints, AF_Edge base, @@ -1696,6 +1794,8 @@ /*************************************************************************/ + /* The main grid-fitting routine. */ + FT_LOCAL_DEF( void ) af_latin_hint_edges( AF_GlyphHints hints, AF_Dimension dim ) @@ -1705,10 +1805,13 @@ AF_Edge edge_limit = edges + axis->num_edges; FT_PtrDist n_edges; AF_Edge edge; - AF_Edge anchor = 0; + AF_Edge anchor = NULL; FT_Int has_serifs = 0; + FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal" + : "vertical")); + /* we begin by aligning all stems relative to the blue zone */ /* if needed -- that's only for horizontal edges */ @@ -1717,7 +1820,7 @@ for ( edge = edges; edge < edge_limit; edge++ ) { AF_Width blue; - AF_Edge edge1, edge2; + AF_Edge edge1, edge2; /* these edges form the stem to check */ if ( edge->flags & AF_EDGE_DONE ) @@ -1728,9 +1831,9 @@ edge2 = edge->link; if ( blue ) - { edge1 = edge; - } + + /* flip edges if the other stem is aligned to a blue zone */ else if ( edge2 && edge2->blue_edge ) { blue = edge2->blue_edge; @@ -1741,7 +1844,7 @@ if ( !edge1 ) continue; - AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), " + FT_TRACE5(( " BLUE: edge %d (opos=%.2f) snapped to (%.2f)," "was (%.2f)\n", edge1-edges, edge1->opos / 64.0, blue->fit / 64.0, edge1->pos / 64.0 )); @@ -1760,7 +1863,7 @@ } } - /* now we will align all stem edges, trying to maintain the */ + /* now we align all other stem edges, trying to maintain the */ /* relative order of stems in the glyph */ for ( edge = edges; edge < edge_limit; edge++ ) { @@ -1783,7 +1886,7 @@ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge ) { - AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges )); + FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges )); af_latin_align_linked_edge( hints, dim, edge2, edge ); edge->flags |= AF_EDGE_DONE; @@ -1792,6 +1895,8 @@ if ( !anchor ) { + /* if we reach this if clause, no stem has been aligned yet */ + FT_Pos org_len, org_center, cur_len; FT_Pos cur_pos1, error1, error2, u_off, d_off; @@ -1801,10 +1906,19 @@ hints, dim, org_len, (AF_Edge_Flags)edge->flags, (AF_Edge_Flags)edge2->flags ); + + /* some voodoo to specially round edges for small stem widths; */ + /* the idea is to align the center of a stem, then shifting */ + /* the stem edges to suitable positions */ if ( cur_len <= 64 ) - u_off = d_off = 32; + { + /* width <= 1px */ + u_off = 32; + d_off = 32; + } else { + /* 1px < width < 1.5px */ u_off = 38; d_off = 26; } @@ -1812,7 +1926,6 @@ if ( cur_len < 96 ) { org_center = edge->opos + ( org_len >> 1 ); - cur_pos1 = FT_PIX_ROUND( org_center ); error1 = org_center - ( cur_pos1 - u_off ); @@ -1834,7 +1947,7 @@ else edge->pos = FT_PIX_ROUND( edge->opos ); - AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) " + FT_TRACE5(( " ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)" "snapped to (%.2f) (%.2f)\n", edge-edges, edge->opos / 64.0, edge2-edges, edge2->opos / 64.0, @@ -1861,7 +1974,13 @@ (AF_Edge_Flags)edge2->flags ); if ( edge2->flags & AF_EDGE_DONE ) + { + FT_TRACE5(( " ADJUST: edge %d (pos=%.2f) moved to %.2f\n", + edge - edges, edge->pos / 64.0, + ( edge2->pos - cur_len ) / 64.0 )); + edge->pos = edge2->pos - cur_len; + } else if ( cur_len < 96 ) { @@ -1871,7 +1990,10 @@ cur_pos1 = FT_PIX_ROUND( org_center ); if (cur_len <= 64 ) - u_off = d_off = 32; + { + u_off = 32; + d_off = 32; + } else { u_off = 38; @@ -1894,7 +2016,7 @@ edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; - AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) " + FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)" "snapped to (%.2f) and (%.2f)\n", edge-edges, edge->opos / 64.0, edge2-edges, edge2->opos / 64.0, @@ -1924,7 +2046,7 @@ edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; edge2->pos = edge->pos + cur_len; - AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) " + FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)" "snapped to (%.2f) and (%.2f)\n", edge-edges, edge->opos / 64.0, edge2-edges, edge2->opos / 64.0, @@ -1936,7 +2058,7 @@ if ( edge > edges && edge->pos < edge[-1].pos ) { - AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n", + FT_TRACE5(( " BOUND: %d (pos=%.2f) to (%.2f)\n", edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 )); edge->pos = edge[-1].pos; } @@ -2031,7 +2153,7 @@ 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) " + FT_TRACE5(( " SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)" "aligned to (%.2f)\n", edge-edges, edge->opos / 64.0, edge->serif - edges, edge->serif->opos / 64.0, @@ -2039,10 +2161,11 @@ } else if ( !anchor ) { - AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); edge->pos = FT_PIX_ROUND( edge->opos ); anchor = edge; + FT_TRACE5(( " SERIF_ANCHOR: edge %d (opos=%.2f)" + " snapped to (%.2f)\n", + edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); } else { @@ -2067,17 +2190,20 @@ FT_MulDiv( edge->opos - before->opos, after->pos - before->pos, after->opos - before->opos ); - AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) " + + FT_TRACE5(( " SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)" "from %d (opos=%.2f)\n", edge-edges, edge->opos / 64.0, - edge->pos / 64.0, before - edges, - before->opos / 64.0 )); + edge->pos / 64.0, + before - edges, before->opos / 64.0 )); } else { edge->pos = anchor->pos + ( ( edge->opos - anchor->opos + 16 ) & ~31 ); - AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n", + + FT_TRACE5(( " SERIF_LINK2: edge %d (opos=%.2f)" + " snapped to (%.2f)\n", edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); } } @@ -2093,9 +2219,13 @@ edge->pos = edge[1].pos; } } + + FT_TRACE5(( "\n" )); } + /* Apply the complete hinting algorithm to a latin glyph. */ + static FT_Error af_latin_hints_apply( AF_GlyphHints hints, FT_Outline* outline, @@ -2110,7 +2240,7 @@ goto Exit; /* analyze glyph outline */ -#ifdef AF_USE_WARPER +#ifdef AF_CONFIG_OPTION_USE_WARPER if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT || AF_HINTS_DO_HORIZONTAL( hints ) ) #else @@ -2134,17 +2264,19 @@ /* grid-fit the outline */ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) { -#ifdef AF_USE_WARPER - if ( ( dim == AF_DIMENSION_HORZ && - metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) ) +#ifdef AF_CONFIG_OPTION_USE_WARPER + if ( dim == AF_DIMENSION_HORZ && + metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) { AF_WarperRec warper; FT_Fixed scale; FT_Pos delta; - af_warper_compute( &warper, hints, dim, &scale, &delta ); - af_glyph_hints_scale_dim( hints, dim, scale, delta ); + af_warper_compute( &warper, hints, (AF_Dimension)dim, + &scale, &delta ); + af_glyph_hints_scale_dim( hints, (AF_Dimension)dim, + scale, delta ); continue; } #endif |