Index: src/autofit/aflatin2.c |
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c |
index ea6af8dd9323ca6c00b50c4c06fa168fc9f55c5c..b1e9658d5d701409f6a691a521edc13dd3eee947 100644 |
--- a/src/autofit/aflatin2.c |
+++ b/src/autofit/aflatin2.c |
@@ -4,7 +4,7 @@ |
/* */ |
/* Auto-fitter hinting routines for latin script (body). */ |
/* */ |
-/* Copyright 2003-2011 by */ |
+/* Copyright 2003-2013 by */ |
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
/* */ |
/* This file is part of the FreeType project, and may only be used, */ |
@@ -18,6 +18,7 @@ |
#include FT_ADVANCES_H |
+#include "afglobal.h" |
#include "aflatin.h" |
#include "aflatin2.h" |
#include "aferrors.h" |
@@ -56,8 +57,7 @@ |
FT_LOCAL_DEF( void ) |
af_latin2_metrics_init_widths( AF_LatinMetrics metrics, |
- FT_Face face, |
- FT_ULong charcode ) |
+ FT_Face face ) |
{ |
/* scan the array of segments in each direction */ |
AF_GlyphHintsRec hints[1]; |
@@ -76,7 +76,8 @@ |
AF_Scaler scaler = &dummy->root.scaler; |
- glyph_index = FT_Get_Char_Index( face, charcode ); |
+ glyph_index = FT_Get_Char_Index( face, |
+ metrics->root.clazz->standard_char ); |
if ( glyph_index == 0 ) |
goto Exit; |
@@ -198,8 +199,8 @@ |
/* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */ |
/* bottom-most points (depending on `AF_IS_TOP_BLUE') */ |
- FT_TRACE5(( "blue zones computation\n" )); |
- FT_TRACE5(( "------------------------------------------------\n" )); |
+ FT_TRACE5(( "blue zones computation\n" |
+ "======================\n\n" )); |
for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ ) |
{ |
@@ -209,7 +210,7 @@ |
FT_Pos* blue_shoot; |
- FT_TRACE5(( "blue %3d: ", bb )); |
+ FT_TRACE5(( "blue zone %d:\n", bb )); |
num_flats = 0; |
num_rounds = 0; |
@@ -222,8 +223,6 @@ |
FT_Bool round; |
- 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 ); |
if ( glyph_index == 0 ) |
@@ -285,13 +284,14 @@ |
best_last = last; |
} |
} |
- FT_TRACE5(( "%5d", best_y )); |
+ FT_TRACE5(( " %c %d", *p, best_y )); |
} |
/* now check whether the point belongs to a straight or round */ |
/* segment; we first need to find in which contour the extremum */ |
/* lies, then inspect its previous and next points */ |
{ |
+ FT_Pos best_x = points[best_point].x; |
FT_Int start, end, prev, next; |
FT_Pos dist; |
@@ -302,13 +302,16 @@ |
do |
{ |
- prev = start-1; |
+ prev = start - 1; |
if ( prev < best_first ) |
prev = best_last; |
- dist = points[prev].y - best_y; |
- if ( dist < -5 || dist > 5 ) |
- break; |
+ dist = FT_ABS( points[prev].y - best_y ); |
+ /* accept a small distance or a small angle (both values are */ |
+ /* heuristic; value 20 corresponds to approx. 2.9 degrees) */ |
+ if ( dist > 5 ) |
+ if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist ) |
+ break; |
start = prev; |
@@ -316,13 +319,14 @@ |
do |
{ |
- next = end+1; |
+ next = end + 1; |
if ( next > best_last ) |
next = best_first; |
- dist = points[next].y - best_y; |
- if ( dist < -5 || dist > 5 ) |
- break; |
+ dist = FT_ABS( points[next].y - best_y ); |
+ if ( dist > 5 ) |
+ if ( FT_ABS( points[next].x - best_x ) <= 20 * dist ) |
+ break; |
end = next; |
@@ -333,7 +337,7 @@ |
FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON || |
FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON ); |
- FT_TRACE5(( "%c ", round ? 'r' : 'f' )); |
+ FT_TRACE5(( " (%s)\n", round ? "round" : "flat" )); |
} |
if ( round ) |
@@ -342,15 +346,13 @@ |
flats[num_flats++] = best_y; |
} |
- FT_TRACE5(( "\n" )); |
- |
if ( num_flats == 0 && num_rounds == 0 ) |
{ |
/* |
* we couldn't find a single glyph to compute this blue zone, |
* we will simply ignore it then |
*/ |
- FT_TRACE5(( "empty\n" )); |
+ FT_TRACE5(( " empty\n" )); |
continue; |
} |
@@ -393,7 +395,13 @@ |
if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref ) |
- *blue_shoot = *blue_ref = ( shoot + ref ) / 2; |
+ { |
+ *blue_ref = |
+ *blue_shoot = ( shoot + ref ) / 2; |
+ |
+ FT_TRACE5(( " [overshoot smaller than reference," |
+ " taking mean value]\n" )); |
+ } |
} |
blue->flags = 0; |
@@ -408,7 +416,9 @@ |
if ( bb == AF_LATIN_BLUE_SMALL_TOP ) |
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT; |
- FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); |
+ FT_TRACE5(( " -> reference = %ld\n" |
+ " overshoot = %ld\n", |
+ *blue_ref, *blue_shoot )); |
} |
return; |
@@ -465,7 +475,7 @@ |
af_latin2_metrics_init( AF_LatinMetrics metrics, |
FT_Face face ) |
{ |
- FT_Error error = AF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
FT_CharMap oldmap = face->charmap; |
FT_UInt ee; |
@@ -491,14 +501,13 @@ |
if ( !error ) |
{ |
- /* For now, compute the standard width and height from the `o'. */ |
- af_latin2_metrics_init_widths( metrics, face, 'o' ); |
+ af_latin2_metrics_init_widths( metrics, face ); |
af_latin2_metrics_init_blues( metrics, face ); |
af_latin2_metrics_check_digits( metrics, face ); |
} |
FT_Set_Charmap( face, oldmap ); |
- return AF_Err_Ok; |
+ return FT_Err_Ok; |
} |
@@ -553,8 +562,26 @@ |
if ( blue ) |
{ |
- FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); |
- FT_Pos fitted = ( scaled + 40 ) & ~63; |
+ FT_Pos scaled; |
+ FT_Pos threshold; |
+ FT_Pos fitted; |
+ FT_UInt limit; |
+ FT_UInt ppem; |
+ |
+ |
+ scaled = FT_MulFix( blue->shoot.org, scaler->y_scale ); |
+ ppem = metrics->root.scaler.face->size->metrics.x_ppem; |
+ limit = metrics->root.globals->increase_x_height; |
+ threshold = 40; |
+ |
+ /* if the `increase-x-height' property is active, */ |
+ /* we round up much more often */ |
+ if ( limit && |
+ ppem <= limit && |
+ ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN ) |
+ threshold = 52; |
+ |
+ fitted = ( scaled + threshold ) & ~63; |
#if 1 |
if ( scaled != fitted ) |
@@ -658,6 +685,7 @@ |
{ |
metrics->root.scaler.render_mode = scaler->render_mode; |
metrics->root.scaler.face = scaler->face; |
+ metrics->root.scaler.flags = scaler->flags; |
af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); |
af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); |
@@ -680,7 +708,7 @@ |
{ |
AF_AxisHints axis = &hints->axis[dim]; |
FT_Memory memory = hints->memory; |
- FT_Error error = AF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
AF_Segment segment = NULL; |
AF_SegmentRec seg0; |
AF_Point* contour = hints->contours; |
@@ -796,17 +824,17 @@ |
segment->dir = first->out_dir; |
segment->first = first; |
segment->last = point; |
- segment->pos = (FT_Short)(( min_u + max_u ) >> 1); |
+ segment->pos = (FT_Short)( ( min_u + max_u ) >> 1 ); |
segment->min_coord = (FT_Short) min_v; |
segment->max_coord = (FT_Short) max_v; |
- segment->height = (FT_Short)(max_v - min_v); |
+ segment->height = (FT_Short)( max_v - min_v ); |
/* a segment is round if it doesn't have successive */ |
/* on-curve points. */ |
{ |
AF_Point pt = first; |
AF_Point last = point; |
- AF_Flags f0 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); |
+ AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
AF_Flags f1; |
@@ -815,7 +843,7 @@ |
for ( ; pt != last; f0 = f1 ) |
{ |
pt = pt->next; |
- f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL); |
+ f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); |
if ( !f0 && !f1 ) |
break; |
@@ -832,7 +860,7 @@ |
break; |
/* jump to the start of the next segment, if any */ |
- while ( FT_ABS(point->out_dir) != major_dir ) |
+ while ( FT_ABS( point->out_dir ) != major_dir ) |
{ |
point = point->next; |
@@ -900,16 +928,17 @@ |
FT_UInt count = axis->num_segments; |
FT_UInt ii, jj; |
- for (ii = 0; ii < count; ii++) |
+ for ( ii = 0; ii < count; ii++ ) |
{ |
if ( segments[ii].dir > 0 ) |
{ |
- for (jj = ii+1; jj < count; jj++) |
+ for ( jj = ii + 1; jj < count; jj++ ) |
{ |
if ( segments[jj].dir < 0 ) |
{ |
AF_SegmentRec tmp; |
+ |
tmp = segments[ii]; |
segments[ii] = segments[jj]; |
segments[jj] = tmp; |
@@ -1036,7 +1065,7 @@ |
AF_Dimension dim ) |
{ |
AF_AxisHints axis = &hints->axis[dim]; |
- FT_Error error = AF_Err_Ok; |
+ FT_Error error = FT_Err_Ok; |
FT_Memory memory = hints->memory; |
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim]; |
@@ -1070,7 +1099,7 @@ |
if ( dim == AF_DIMENSION_HORZ ) |
{ |
if ( laxis->width_count > 0 ) |
- segment_length_threshold = (laxis->standard_width * 10 ) >> 4; |
+ segment_length_threshold = ( laxis->standard_width * 10 ) >> 4; |
else |
segment_length_threshold = FT_DivFix( 64, hints->y_scale ); |
} |
@@ -1116,10 +1145,11 @@ |
{ |
FT_Pos dist = seg->serif->pos - seg->pos; |
- if (dist < 0) |
+ |
+ if ( dist < 0 ) |
dist = -dist; |
- if (dist >= laxis->standard_width >> 1) |
+ if ( dist >= laxis->standard_width >> 1 ) |
{ |
/* unlink this serif, it is too distant from its reference stem */ |
seg->serif = NULL; |
@@ -1417,7 +1447,7 @@ |
compare = &blue->ref; |
dist = edge->fpos - compare->org; |
- if (dist < 0) |
+ if ( dist < 0 ) |
dist = -dist; |
dist = FT_MulFix( dist, scale ); |
@@ -1521,8 +1551,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; |
@@ -1603,8 +1633,8 @@ |
FT_Int sign = 0; |
FT_Int vertical = ( dim == AF_DIMENSION_VERT ); |
+ FT_UNUSED( base_flags ); |
- FT_UNUSED(base_flags); |
if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) || |
axis->extra_light ) |
@@ -1734,7 +1764,7 @@ |
if ( delta < 0 ) |
delta = -delta; |
- if (delta >= 16) |
+ if ( delta >= 16 ) |
{ |
dist = org_dist; |
if ( dist < 48 ) |
@@ -1788,7 +1818,7 @@ |
{ |
FT_UNUSED( hints ); |
- serif->pos = base->pos + (serif->opos - base->opos); |
+ serif->pos = base->pos + ( serif->opos - base->opos ); |
} |
@@ -1870,9 +1900,10 @@ |
{ |
anchor = edge; |
- anchor_drift = (anchor->pos - anchor->opos); |
- if (edge2) |
- anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1; |
+ anchor_drift = ( anchor->pos - anchor->opos ); |
+ if ( edge2 ) |
+ anchor_drift = ( anchor_drift + |
+ ( edge2->pos - edge2->opos ) ) >> 1; |
} |
} |
} |
@@ -1964,8 +1995,8 @@ |
edge2->flags |= AF_EDGE_DONE; |
- anchor_drift = ( (anchor->pos - anchor->opos) + |
- (edge2->pos - edge2->opos)) >> 1; |
+ anchor_drift = ( ( anchor->pos - anchor->opos ) + |
+ ( edge2->pos - edge2->opos ) ) >> 1; |
FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 )); |
} |
@@ -1984,8 +2015,8 @@ |
(AF_Edge_Flags)edge->flags, |
(AF_Edge_Flags)edge2->flags ); |
- org_left = org_pos + ((org_len - cur_len) >> 1); |
- org_right = org_pos + ((org_len + cur_len) >> 1); |
+ org_left = org_pos + ( ( org_len - cur_len ) >> 1 ); |
+ org_right = org_pos + ( ( org_len + cur_len ) >> 1 ); |
FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ", |
org_left / 64.0, org_right / 64.0 )); |
@@ -2013,13 +2044,13 @@ |
} |
/* if the span is within a single pixel, don't touch it */ |
- if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) ) |
+ if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) ) |
{ |
FT_TRACE5(( "single pixel stem\n" )); |
goto AlignStem; |
} |
- if (cur_len <= 96) |
+ if ( cur_len <= 96 ) |
{ |
/* we want to avoid the absolute worst case which is |
* when the left and right edges of the span each represent |
@@ -2027,43 +2058,43 @@ |
* to 25/75%, since this is much more pleasant to the eye with |
* very acceptable distortion |
*/ |
- FT_Pos frac_left = (org_left) & 63; |
- FT_Pos frac_right = (org_right) & 63; |
+ FT_Pos frac_left = org_left & 63; |
+ FT_Pos frac_right = org_right & 63; |
if ( frac_left >= 22 && frac_left <= 42 && |
frac_right >= 22 && frac_right <= 42 ) |
{ |
org = frac_left; |
- fit = (org <= 32) ? 16 : 48; |
- delta = FT_ABS(fit - org); |
+ fit = ( org <= 32 ) ? 16 : 48; |
+ delta = FT_ABS( fit - org ); |
displacements[count] = fit - org; |
scores[count++] = delta; |
- FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta )); |
+ FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
org = frac_right; |
- fit = (org <= 32) ? 16 : 48; |
- delta = FT_ABS(fit - org); |
+ fit = ( org <= 32 ) ? 16 : 48; |
+ delta = FT_ABS( fit - org ); |
displacements[count] = fit - org; |
scores[count++] = delta; |
- FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta )); |
+ FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
} |
} |
/* snapping the left edge to the grid */ |
org = org_left; |
- fit = FT_PIX_ROUND(org); |
- delta = FT_ABS(fit - org); |
+ fit = FT_PIX_ROUND( org ); |
+ delta = FT_ABS( fit - org ); |
displacements[count] = fit - org; |
scores[count++] = delta; |
- FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta )); |
+ FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
/* snapping the right edge to the grid */ |
org = org_right; |
- fit = FT_PIX_ROUND(org); |
- delta = FT_ABS(fit - org); |
+ fit = FT_PIX_ROUND( org ); |
+ delta = FT_ABS( fit - org ); |
displacements[count] = fit - org; |
scores[count++] = delta; |
- FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta )); |
+ FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta )); |
/* now find the best displacement */ |
{ |
@@ -2071,9 +2102,9 @@ |
FT_Pos best_disp = displacements[0]; |
FT_UInt nn; |
- for (nn = 1; nn < count; nn++) |
+ for ( nn = 1; nn < count; nn++ ) |
{ |
- if (scores[nn] < best_score) |
+ if ( scores[nn] < best_score ) |
{ |
best_score = scores[nn]; |
best_disp = displacements[nn]; |
@@ -2086,7 +2117,7 @@ |
} |
AlignStem: |
- edge->pos = cur_center - (cur_len >> 1); |
+ edge->pos = cur_center - ( cur_len >> 1 ); |
edge2->pos = edge->pos + cur_len; |
FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)" |
@@ -2359,6 +2390,7 @@ |
AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class, |
AF_SCRIPT_LATIN2, |
af_latin2_uniranges, |
+ 'o', |
sizeof ( AF_LatinMetricsRec ), |