diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index 99e8827b5..310af8d52 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -36,6 +36,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 +73,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 +169,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,7 +188,7 @@ /* 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" )); @@ -199,7 +210,7 @@ for ( ; p < limit && *p; p++ ) { FT_UInt glyph_index; - FT_Pos best_y; /* same as points.y */ + FT_Pos best_y; /* same as points.y */ FT_Int best_point, best_first, best_last; FT_Vector* points; FT_Bool round = 0; @@ -229,7 +240,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; @@ -241,7 +254,7 @@ /* In some fonts, they correspond to mark attachment points */ /* which are way outside of the glyph's real outline. */ if ( last <= first ) - continue; + continue; if ( AF_LATIN_IS_TOP_BLUE( bb ) ) { @@ -311,7 +324,7 @@ } 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 ); @@ -343,9 +356,9 @@ af_sort_pos( num_rounds, rounds ); af_sort_pos( num_flats, flats ); - blue = & axis->blues[axis->blue_count]; - blue_ref = & blue->ref.org; - blue_shoot = & blue->shoot.org; + blue = &axis->blues[axis->blue_count]; + blue_ref = &blue->ref.org; + blue_shoot = &blue->shoot.org; axis->blue_count++; @@ -376,7 +389,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; @@ -398,6 +412,8 @@ } + /* 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,8 +423,7 @@ FT_Fixed advance, old_advance = 0; - /* check whether all ASCII digits have the same advance width; */ - /* digit `0' is 0x30 in all supported charmaps */ + /* digit `0' is 0x30 in all supported charmaps */ for ( i = 0x30; i <= 0x39; i++ ) { FT_UInt glyph_index; @@ -444,6 +459,8 @@ } + /* Initialize global metrics. */ + FT_LOCAL_DEF( FT_Error ) af_latin_metrics_init( AF_LatinMetrics metrics, FT_Face face ) @@ -458,6 +475,7 @@ FT_ENCODING_APPLE_ROMAN, FT_ENCODING_ADOBE_STANDARD, FT_ENCODING_ADOBE_LATIN_1, + FT_ENCODING_NONE /* end of list */ }; @@ -485,6 +503,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 +571,7 @@ else #endif if ( dim == AF_DIMENSION_VERT ) - { scale = FT_MulDiv( scale, fitted, scaled ); - } } } } @@ -571,7 +590,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; @@ -635,6 +654,8 @@ } + /* Scale global values in both directions. */ + FT_LOCAL_DEF( void ) af_latin_metrics_scale( AF_LatinMetrics metrics, AF_Scaler scaler ) @@ -655,18 +676,21 @@ /*************************************************************************/ /*************************************************************************/ + + /* Walk over all contours and compute its segments. */ + FT_LOCAL_DEF( FT_Error ) af_latin_hints_compute_segments( AF_GlyphHints hints, AF_Dimension dim ) { - AF_AxisHints axis = &hints->axis[dim]; - FT_Memory memory = hints->memory; - FT_Error error = AF_Err_Ok; - AF_Segment segment = NULL; - AF_SegmentRec seg0; - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - AF_Direction major_dir, segment_dir; + AF_AxisHints axis = &hints->axis[dim]; + FT_Memory memory = hints->memory; + FT_Error error = AF_Err_Ok; + AF_Segment segment = NULL; + AF_SegmentRec seg0; + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + AF_Direction major_dir, segment_dir; FT_ZERO( &seg0 ); @@ -762,7 +786,7 @@ /* a segment is round if either its first or last point */ /* is a control point */ if ( ( segment->first->flags | point->flags ) & - AF_FLAG_CONTROL ) + AF_FLAG_CONTROL ) segment->flags |= AF_EDGE_ROUND; /* compute segment size */ @@ -874,6 +898,8 @@ } + /* Link segments to form stems and serifs. */ + FT_LOCAL_DEF( void ) af_latin_hints_link_segments( AF_GlyphHints hints, AF_Dimension dim ) @@ -899,6 +925,8 @@ 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++ ) { FT_Pos pos1 = seg1->pos; @@ -907,6 +935,7 @@ 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; @@ -919,11 +948,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; @@ -940,7 +974,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; @@ -957,6 +991,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 ) @@ -985,7 +1021,7 @@ : AF_DIR_RIGHT; /* - * 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. */ @@ -996,20 +1032,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 least 0.25px */ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, scale ); if ( edge_distance_threshold > 64 / 4 ) @@ -1020,7 +1057,7 @@ for ( seg = segments; seg < segment_limit; seg++ ) { - AF_Edge found = 0; + AF_Edge found = NULL; FT_Int ee; @@ -1069,9 +1106,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 @@ -1088,9 +1126,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 */ @@ -1123,7 +1161,7 @@ } 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? */ @@ -1150,9 +1188,9 @@ #if 0 /* check for segment direction */ if ( seg->dir == up_dir ) - ups += seg->max_coord-seg->min_coord; + ups += seg->max_coord - seg->min_coord; else - downs += seg->max_coord-seg->min_coord; + downs += seg->max_coord - seg->min_coord; #endif /* check for links -- if seg->serif is set, then seg->link must */ @@ -1229,7 +1267,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 */ @@ -1243,6 +1281,8 @@ } + /* Detect segments and edges for given dimension. */ + FT_LOCAL_DEF( FT_Error ) af_latin_hints_detect_features( AF_GlyphHints hints, AF_Dimension dim ) @@ -1257,10 +1297,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 ) @@ -1284,8 +1327,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 minumum distance of 0.5px */ if ( best_dist > 64 / 2 ) best_dist = 64 / 2; @@ -1295,7 +1340,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; @@ -1323,12 +1368,13 @@ if ( dist < best_dist ) { best_dist = dist; - best_blue = & blue->ref; + 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 ); @@ -1344,7 +1390,7 @@ if ( dist < best_dist ) { best_dist = dist; - best_blue = & blue->shoot; + best_blue = &blue->shoot; } } } @@ -1357,6 +1403,8 @@ } + /* Initalize hinting engine. */ + static FT_Error af_latin_hints_init( AF_GlyphHints hints, AF_LatinMetrics metrics ) @@ -1370,7 +1418,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; @@ -1417,8 +1465,8 @@ * In `light' hinting mode we disable horizontal hinting completely. * We also do it if the face is italic. */ - if ( mode == FT_RENDER_MODE_LIGHT || - (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 ) + if ( mode == FT_RENDER_MODE_LIGHT || + ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 ) scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL; hints->scaler_flags = scaler_flags; @@ -1436,8 +1484,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 +1532,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, @@ -1501,7 +1551,7 @@ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || - axis->extra_light ) + axis->extra_light ) return width; if ( dist < 0 ) @@ -1516,8 +1566,9 @@ /* 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 ) ) @@ -1572,6 +1623,7 @@ else { /* strong hinting process: snap the stem width to integer pixels */ + FT_Pos org_dist = dist; @@ -1646,7 +1698,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, @@ -1664,13 +1716,16 @@ stem_edge->pos = base_edge->pos + fitted_width; - AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), " - "dist was %.2f, now %.2f\n", + AF_LOG(( "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, @@ -1678,7 +1733,7 @@ { FT_UNUSED( hints ); - serif->pos = base->pos + (serif->opos - base->opos); + serif->pos = base->pos + ( serif->opos - base->opos ); } @@ -1693,6 +1748,8 @@ /*************************************************************************/ + /* The main grid-fitting routine. */ + FT_LOCAL_DEF( void ) af_latin_hint_edges( AF_GlyphHints hints, AF_Dimension dim ) @@ -1702,7 +1759,7 @@ 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; @@ -1725,9 +1782,8 @@ edge2 = edge->link; if ( blue ) - { edge1 = edge; - } + else if ( edge2 && edge2->blue_edge ) { blue = edge2->blue_edge; @@ -1738,9 +1794,9 @@ if ( !edge1 ) continue; - AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), " - "was (%.2f)\n", - edge1-edges, edge1->opos / 64.0, blue->fit / 64.0, + AF_LOG(( "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 )); edge1->pos = blue->fit; @@ -1757,8 +1813,8 @@ } } - /* now we will align all stem edges, trying to maintain the */ - /* relative order of stems in the glyph */ + /* now we align all stem edges, trying to maintain the */ + /* relative order of stems in the glyph */ for ( edge = edges; edge < edge_limit; edge++ ) { AF_Edge edge2; @@ -1798,8 +1854,13 @@ hints, dim, org_len, (AF_Edge_Flags)edge->flags, (AF_Edge_Flags)edge2->flags ); + + /* some voodoo to specially round edges for small stem widths */ if ( cur_len <= 64 ) - u_off = d_off = 32; + { + u_off = 32; + d_off = 32; + } else { u_off = 38; @@ -1809,7 +1870,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 ); @@ -1831,10 +1891,10 @@ else edge->pos = FT_PIX_ROUND( edge->opos ); - AF_LOG(( "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, + AF_LOG(( "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, edge->pos / 64.0, edge2->pos / 64.0 )); anchor = edge; @@ -1853,9 +1913,9 @@ org_center = org_pos + ( org_len >> 1 ); cur_len = af_latin_compute_stem_width( - hints, dim, org_len, - (AF_Edge_Flags)edge->flags, - (AF_Edge_Flags)edge2->flags ); + hints, dim, org_len, + (AF_Edge_Flags)edge->flags, + (AF_Edge_Flags)edge2->flags ); if ( edge2->flags & AF_EDGE_DONE ) edge->pos = edge2->pos - cur_len; @@ -1868,7 +1928,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; @@ -1891,10 +1954,10 @@ edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; - AF_LOG(( "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, + AF_LOG(( "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, edge->pos / 64.0, edge2->pos / 64.0 )); } else @@ -1908,23 +1971,23 @@ (AF_Edge_Flags)edge->flags, (AF_Edge_Flags)edge2->flags ); - cur_pos1 = FT_PIX_ROUND( org_pos ); - delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center; + cur_pos1 = FT_PIX_ROUND( org_pos ); + delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center; if ( delta1 < 0 ) delta1 = -delta1; - cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len; - delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center; + cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - 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; - AF_LOG(( "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, + AF_LOG(( "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, edge->pos / 64.0, edge2->pos / 64.0 )); } @@ -1934,7 +1997,7 @@ if ( edge > edges && edge->pos < edge[-1].pos ) { AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n", - edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 )); + edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 )); edge->pos = edge[-1].pos; } } @@ -2028,9 +2091,9 @@ 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.0, + AF_LOG(( "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, edge->pos / 64.0 )); } @@ -2064,18 +2127,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) " - "from %d (opos=%.2f)\n", - edge-edges, edge->opos / 64.0, - edge->pos / 64.0, before - edges, - before->opos / 64.0 )); + + AF_LOG(( "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 )); } else { edge->pos = anchor->pos + ( ( edge->opos - anchor->opos + 16 ) & ~31 ); + AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n", - edge-edges, edge->opos / 64.0, edge->pos / 64.0 )); + edge - edges, edge->opos / 64.0, edge->pos / 64.0 )); } } @@ -2093,6 +2158,8 @@ } + /* Apply the complete hinting algorithm to a latin glyph. */ + static FT_Error af_latin_hints_apply( AF_GlyphHints hints, FT_Outline* outline, @@ -2109,7 +2176,7 @@ /* analyze glyph outline */ #ifdef AF_USE_WARPER if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT || - AF_HINTS_DO_HORIZONTAL( hints ) ) + AF_HINTS_DO_HORIZONTAL( hints ) ) #else if ( AF_HINTS_DO_HORIZONTAL( hints ) ) #endif @@ -2132,8 +2199,8 @@ 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 ) ) + if ( dim == AF_DIMENSION_HORZ && + metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) { AF_WarperRec warper; FT_Fixed scale; @@ -2206,7 +2273,7 @@ }; - AF_DEFINE_SCRIPT_CLASS(af_latin_script_class, + AF_DEFINE_SCRIPT_CLASS(af_latin_script_class, AF_SCRIPT_LATIN, af_latin_uniranges,