[autofit] Synchronize `cjk' with `latin' module (and vice versa).

* src/autofit/afcjk.c (af_cjk_metrics_init_widths): Add tracing
messages.
(af_cjk_metrics_init_blues): Don't pass blue string array as
argument but use the global array directly.
Use `outline' directly.
Update and add tracing messages.
(af_cjk_metrics_init): Simplify code.
(af_cjk_metrics_scale_dim): Improve tracing message.
(af_cjk_metrics_scale): Synchronize.

* src/autofit/aflatin.c (af_latin_metrics_init_widths,
af_latin_metrics_init_blues): Improve and add tracing messages.
This commit is contained in:
Werner Lemberg 2013-08-25 13:07:08 +02:00
parent 0975d685ed
commit 306f8c5d89
3 changed files with 186 additions and 96 deletions

View File

@ -1,3 +1,20 @@
2013-08-25 Werner Lemberg <wl@gnu.org>
[autofit] Synchronize `cjk' with `latin' module (and vice versa).
* src/autofit/afcjk.c (af_cjk_metrics_init_widths): Add tracing
messages.
(af_cjk_metrics_init_blues): Don't pass blue string array as
argument but use the global array directly.
Use `outline' directly.
Update and add tracing messages.
(af_cjk_metrics_init): Simplify code.
(af_cjk_metrics_scale_dim): Improve tracing message.
(af_cjk_metrics_scale): Synchronize.
* src/autofit/aflatin.c (af_latin_metrics_init_widths,
af_latin_metrics_init_blues): Improve and add tracing messages.
2013-08-25 Werner Lemberg <wl@gnu.org> 2013-08-25 Werner Lemberg <wl@gnu.org>
[autofit] Make `latin' module use blue stringsets. [autofit] Make `latin' module use blue stringsets.

View File

@ -73,6 +73,10 @@
AF_GlyphHintsRec hints[1]; AF_GlyphHintsRec hints[1];
FT_TRACE5(( "cjk standard widths computation\n"
"===============================\n"
"\n" ));
af_glyph_hints_init( hints, face->memory ); af_glyph_hints_init( hints, face->memory );
metrics->axis[AF_DIMENSION_HORZ].width_count = 0; metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
@ -92,6 +96,9 @@
if ( glyph_index == 0 ) if ( glyph_index == 0 )
goto Exit; goto Exit;
FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
metrics->root.script_class->standard_char, glyph_index ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || face->glyph->outline.n_points <= 0 ) if ( error || face->glyph->outline.n_points <= 0 )
goto Exit; goto Exit;
@ -123,11 +130,13 @@
FT_UInt num_widths = 0; FT_UInt num_widths = 0;
error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim ); error = af_latin_hints_compute_segments( hints,
(AF_Dimension)dim );
if ( error ) if ( error )
goto Exit; goto Exit;
af_latin_hints_link_segments( hints, (AF_Dimension)dim ); af_latin_hints_link_segments( hints,
(AF_Dimension)dim );
seg = axhints->segments; seg = axhints->segments;
limit = seg + axhints->num_segments; limit = seg + axhints->num_segments;
@ -152,7 +161,7 @@
} }
/* this also replaces multiple almost identical stem widths */ /* this also replaces multiple almost identical stem widths */
/* with a single one (the value 100 is heuristic) */ /* with a single one (the value 100 is heuristic) */
af_sort_and_quantize_widths( &num_widths, axis->widths, af_sort_and_quantize_widths( &num_widths, axis->widths,
dummy->units_per_em / 100 ); dummy->units_per_em / 100 );
axis->width_count = num_widths; axis->width_count = num_widths;
@ -172,9 +181,28 @@
axis->edge_distance_threshold = stdw / 5; axis->edge_distance_threshold = stdw / 5;
axis->standard_width = stdw; axis->standard_width = stdw;
axis->extra_light = 0; axis->extra_light = 0;
#ifdef FT_DEBUG_LEVEL_TRACE
{
FT_UInt i;
FT_TRACE5(( "%s widths:\n",
dim == AF_DIMENSION_VERT ? "horizontal"
: "vertical" ));
FT_TRACE5(( " %d (standard)", axis->standard_width ));
for ( i = 1; i < axis->width_count; i++ )
FT_TRACE5(( " %d", axis->widths[i].org ));
FT_TRACE5(( "\n" ));
}
#endif
} }
} }
FT_TRACE5(( "\n" ));
af_glyph_hints_done( hints ); af_glyph_hints_done( hints );
} }
@ -265,24 +293,20 @@
/* Calculate blue zones for all the CJK_BLUE_XXX's. */ /* Calculate blue zones for all the CJK_BLUE_XXX's. */
static void static void
af_cjk_metrics_init_blues( AF_CJKMetrics metrics, af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
FT_Face face, FT_Face face )
const FT_ULong blue_chars
[AF_CJK_BLUE_MAX]
[AF_CJK_BLUE_TYPE_MAX]
[AF_CJK_MAX_TEST_CHARACTERS] )
{ {
FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS]; FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS]; FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
FT_Int num_fills; FT_Int num_fills;
FT_Int num_flats; FT_Int num_flats;
FT_Int bb; FT_Int bb;
AF_CJKBlue blue; AF_CJKBlue blue;
FT_Error error; FT_Error error;
AF_CJKAxis axis; AF_CJKAxis axis;
FT_GlyphSlot glyph = face->glyph; FT_Outline outline;
#ifdef FT_DEBUG_LEVEL_TRACE #ifdef FT_DEBUG_LEVEL_TRACE
FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = { FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = {
@ -302,8 +326,9 @@
/* `blue_chars[blues]' string, then computing its extreme points */ /* `blue_chars[blues]' string, then computing its extreme points */
/* (depending blue zone type etc.). */ /* (depending blue zone type etc.). */
FT_TRACE5(( "cjk blue zones computation\n" )); FT_TRACE5(( "cjk blue zones computation\n"
FT_TRACE5(( "------------------------------------------------\n" )); "==========================\n"
"\n" ));
for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ ) for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
{ {
@ -317,7 +342,7 @@
for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ ) for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
{ {
const FT_ULong* p = blue_chars[bb][fill_type]; const FT_ULong* p = af_cjk_hani_blue_chars[bb][fill_type];
const FT_ULong* limit = p + AF_CJK_MAX_TEST_CHARACTERS; const FT_ULong* limit = p + AF_CJK_MAX_TEST_CHARACTERS;
FT_Bool fill = FT_BOOL( FT_Bool fill = FT_BOOL(
fill_type == AF_CJK_BLUE_TYPE_FILL ); fill_type == AF_CJK_BLUE_TYPE_FILL );
@ -326,7 +351,6 @@
FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb], FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
cjk_blue_type_name[fill_type] )); cjk_blue_type_name[fill_type] ));
for ( ; p < limit && *p; p++ ) for ( ; p < limit && *p; p++ )
{ {
FT_UInt glyph_index; FT_UInt glyph_index;
@ -335,7 +359,7 @@
FT_Vector* points; FT_Vector* points;
FT_TRACE5(( " U+%lX...", *p )); FT_TRACE5(( " U+%lX... ", *p ));
/* load the character in the face -- skip unknown or empty ones */ /* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, *p ); glyph_index = FT_Get_Char_Index( face, *p );
@ -345,15 +369,16 @@
continue; continue;
} }
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
if ( error || glyph->outline.n_points <= 0 ) outline = face->glyph->outline;
if ( error || outline.n_points <= 0 )
{ {
FT_TRACE5(( "no outline\n" )); FT_TRACE5(( "no outline\n" ));
continue; continue;
} }
/* now compute min or max point indices and coordinates */ /* now compute min or max point indices and coordinates */
points = glyph->outline.points; points = outline.points;
best_point = -1; best_point = -1;
best_pos = 0; /* make compiler happy */ best_pos = 0; /* make compiler happy */
@ -363,14 +388,12 @@
FT_Int last = -1; FT_Int last = -1;
for ( nn = 0; for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
nn < glyph->outline.n_contours;
first = last + 1, nn++ )
{ {
FT_Int pp; FT_Int pp;
last = glyph->outline.contours[nn]; last = outline.contours[nn];
/* Avoid single-point contours since they are never */ /* Avoid single-point contours since they are never */
/* rasterized. In some fonts, they correspond to mark */ /* rasterized. In some fonts, they correspond to mark */
@ -421,7 +444,8 @@
; ;
} }
} }
FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
FT_TRACE5(( "best_pos = %5ld\n", best_pos ));
} }
if ( fill ) if ( fill )
@ -437,12 +461,12 @@
* we couldn't find a single glyph to compute this blue zone, * we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then * we will simply ignore it then
*/ */
FT_TRACE5(( "empty\n" )); FT_TRACE5(( " empty\n" ));
continue; continue;
} }
/* we have computed the contents of the `fill' and `flats' tables, */ /* we have computed the contents of the `fill' and `flats' tables, */
/* now determine the reference position of the blue -- */ /* now determine the reference position of the blue zone -- */
/* we simply take the median value after a simple sort */ /* we simply take the median value after a simple sort */
af_sort_pos( num_flats, flats ); af_sort_pos( num_flats, flats );
af_sort_pos( num_fills, fills ); af_sort_pos( num_fills, fills );
@ -452,19 +476,20 @@
else else
axis = &metrics->axis[AF_DIMENSION_HORZ]; axis = &metrics->axis[AF_DIMENSION_HORZ];
blue = & axis->blues[axis->blue_count]; blue = &axis->blues[axis->blue_count];
blue_ref = & blue->ref.org; blue_ref = &blue->ref.org;
blue_shoot = & blue->shoot.org; blue_shoot = &blue->shoot.org;
axis->blue_count++; axis->blue_count++;
if ( num_flats == 0 ) if ( num_flats == 0 )
{ {
*blue_ref = fills[num_fills / 2]; *blue_ref =
*blue_shoot = fills[num_fills / 2]; *blue_shoot = fills[num_fills / 2];
} }
else if ( num_fills == 0 ) else if ( num_fills == 0 )
{ {
*blue_ref = flats[num_flats / 2]; *blue_ref =
*blue_shoot = flats[num_flats / 2]; *blue_shoot = flats[num_flats / 2];
} }
else else
@ -484,7 +509,13 @@
if ( ( AF_CJK_BLUE_TOP == bb || if ( ( AF_CJK_BLUE_TOP == bb ||
AF_CJK_BLUE_RIGHT == bb ) ^ under_ref ) AF_CJK_BLUE_RIGHT == bb ) ^ under_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; blue->flags = 0;
@ -493,15 +524,20 @@
else if ( AF_CJK_BLUE_RIGHT == bb ) else if ( AF_CJK_BLUE_RIGHT == bb )
blue->flags |= AF_CJK_BLUE_IS_RIGHT; blue->flags |= AF_CJK_BLUE_IS_RIGHT;
FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n", FT_TRACE5(( " cjk %s bluezone\n"
" -> reference = %ld\n"
" overshoot = %ld\n",
cjk_blue_name[bb], *blue_ref, *blue_shoot )); cjk_blue_name[bb], *blue_ref, *blue_shoot ));
} }
FT_TRACE5(( "\n" ));
return; return;
} }
/* Basically the Latin version with type AF_CJKMetrics for metrics. */ /* Basically the Latin version with type AF_CJKMetrics for metrics. */
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_cjk_metrics_check_digits( AF_CJKMetrics metrics, af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face ) FT_Face face )
@ -511,8 +547,7 @@
FT_Fixed advance, old_advance = 0; 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++ ) for ( i = 0x30; i <= 0x39; i++ )
{ {
FT_UInt glyph_index; FT_UInt glyph_index;
@ -548,6 +583,8 @@
} }
/* Initialize global metrics. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics, af_cjk_metrics_init( AF_CJKMetrics metrics,
FT_Face face ) FT_Face face )
@ -557,21 +594,21 @@
metrics->units_per_em = face->units_per_EM; metrics->units_per_em = face->units_per_EM;
if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
face->charmap = NULL;
else
{ {
af_cjk_metrics_init_widths( metrics, face ); af_cjk_metrics_init_widths( metrics, face );
af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars ); af_cjk_metrics_init_blues( metrics, face );
af_cjk_metrics_check_digits( metrics, face ); af_cjk_metrics_check_digits( metrics, face );
} }
FT_Set_Charmap( face, oldmap ); FT_Set_Charmap( face, oldmap );
return FT_Err_Ok; return FT_Err_Ok;
} }
/* Adjust scaling value, then scale and shift widths */
/* and blue zones (if applicable) for given dimension. */
static void static void
af_cjk_metrics_scale_dim( AF_CJKMetrics metrics, af_cjk_metrics_scale_dim( AF_CJKMetrics metrics,
AF_Scaler scaler, AF_Scaler scaler,
@ -583,8 +620,6 @@
FT_UInt nn; FT_UInt nn;
axis = &metrics->axis[dim];
if ( dim == AF_DIMENSION_HORZ ) if ( dim == AF_DIMENSION_HORZ )
{ {
scale = scaler->x_scale; scale = scaler->x_scale;
@ -596,6 +631,8 @@
delta = scaler->y_delta; delta = scaler->y_delta;
} }
axis = &metrics->axis[dim];
if ( axis->org_scale == scale && axis->org_delta == delta ) if ( axis->org_scale == scale && axis->org_delta == delta )
return; return;
@ -651,12 +688,13 @@
blue->shoot.fit = blue->ref.fit - delta2; blue->shoot.fit = blue->ref.fit - delta2;
FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: " FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
"ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n", " ref: cur=%.2f fit=%.2f\n"
( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V', " shoot: cur=%.2f fit=%.2f\n",
nn, blue->ref.org, blue->shoot.org, ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
blue->ref.cur / 64.0, blue->ref.fit / 64.0, nn, blue->ref.org, blue->shoot.org,
blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 )); blue->ref.cur / 64.0, blue->ref.fit / 64.0,
blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
blue->flags |= AF_CJK_BLUE_ACTIVE; blue->flags |= AF_CJK_BLUE_ACTIVE;
} }
@ -664,11 +702,15 @@
} }
/* Scale global values in both directions. */
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics, af_cjk_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler ) AF_Scaler scaler )
{ {
metrics->root.scaler = *scaler; metrics->root.scaler.render_mode = scaler->render_mode;
metrics->root.scaler.face = scaler->face;
metrics->root.scaler.flags = scaler->flags;
af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
@ -683,6 +725,9 @@
/*************************************************************************/ /*************************************************************************/
/*************************************************************************/ /*************************************************************************/
/* Walk over all contours and compute its segments. */
static FT_Error static FT_Error
af_cjk_hints_compute_segments( AF_GlyphHints hints, af_cjk_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim ) AF_Dimension dim )
@ -939,7 +984,7 @@
for ( seg = segments; seg < segment_limit; seg++ ) for ( seg = segments; seg < segment_limit; seg++ )
{ {
AF_Edge found = 0; AF_Edge found = NULL;
FT_Pos best = 0xFFFFU; FT_Pos best = 0xFFFFU;
FT_Int ee; FT_Int ee;
@ -1027,25 +1072,26 @@
} }
} }
/*********************************************************************/ /******************************************************************/
/* */ /* */
/* Good, we now compute each edge's properties according to segments */ /* Good, we now compute each edge's properties according to the */
/* found on its position. Basically, these are as follows. */ /* 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) */ /* - stem edge, serif edge or both (which defaults to stem then) */
/* - rounded edge, straight or both (which defaults to straight) */ /* - rounded edge, straight or both (which defaults to straight) */
/* - link for edge */ /* - link for edge */
/* */ /* */
/*********************************************************************/ /******************************************************************/
/* first of all, set the `edge' field in each segment -- this is */ /* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */ /* required in order to compute edge links */
/* */
/* Note that removing this loop and setting the `edge' field of each */
/* segment directly in the code above slows down execution speed for */
/* some reasons on platforms like the Sun. */
/*
* Note that removing this loop and setting the `edge' field of each
* segment directly in the code above slows down execution speed for
* some reasons on platforms like the Sun.
*/
{ {
AF_Edge edges = axis->edges; AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges; AF_Edge edge_limit = edges + axis->num_edges;
@ -1154,6 +1200,8 @@
} }
/* Detect segments and edges for given dimension. */
static FT_Error static FT_Error
af_cjk_hints_detect_features( AF_GlyphHints hints, af_cjk_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim ) AF_Dimension dim )
@ -1172,6 +1220,8 @@
} }
/* Compute all edges which lie within blue zones. */
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_cjk_hints_compute_blue_edges( AF_GlyphHints hints, af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
AF_CJKMetrics metrics, AF_CJKMetrics metrics,
@ -1259,6 +1309,8 @@
} }
/* Initalize hinting engine. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints, af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics ) AF_CJKMetrics metrics )
@ -1317,7 +1369,7 @@
hints->scaler_flags = scaler_flags; hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags; hints->other_flags = other_flags;
return 0; return FT_Err_Ok;
} }
@ -1329,8 +1381,8 @@
/*************************************************************************/ /*************************************************************************/
/*************************************************************************/ /*************************************************************************/
/* snap a given width in scaled coordinates to one of the */ /* Snap a given width in scaled coordinates to one of the */
/* current standard widths */ /* current standard widths. */
static FT_Pos static FT_Pos
af_cjk_snap_width( AF_Width widths, af_cjk_snap_width( AF_Width widths,
@ -1377,7 +1429,9 @@
} }
/* compute the snapped width of a given stem */ /* Compute the snapped width of a given stem. */
/* There is a lot of voodoo in this function; changing the hard-coded */
/* parameters influence the whole hinting process. */
static FT_Pos static FT_Pos
af_cjk_compute_stem_width( AF_GlyphHints hints, af_cjk_compute_stem_width( AF_GlyphHints hints,
@ -1386,8 +1440,8 @@
AF_Edge_Flags base_flags, AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags ) AF_Edge_Flags stem_flags )
{ {
AF_CJKMetrics metrics = (AF_CJKMetrics) hints->metrics; AF_CJKMetrics metrics = (AF_CJKMetrics)hints->metrics;
AF_CJKAxis axis = & metrics->axis[dim]; AF_CJKAxis axis = &metrics->axis[dim];
FT_Pos dist = width; FT_Pos dist = width;
FT_Int sign = 0; FT_Int sign = 0;
FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT ); FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT );
@ -1498,7 +1552,7 @@
} }
/* align one stem edge relative to the previous stem edge */ /* Align one stem edge relative to the previous stem edge. */
static void static void
af_cjk_align_linked_edge( AF_GlyphHints hints, af_cjk_align_linked_edge( AF_GlyphHints hints,
@ -1518,6 +1572,9 @@
} }
/* Shift the coordinates of the `serif' edge by the same amount */
/* as the corresponding `base' edge has been moved already. */
static void static void
af_cjk_align_serif_edge( AF_GlyphHints hints, af_cjk_align_serif_edge( AF_GlyphHints hints,
AF_Edge base, AF_Edge base,
@ -1671,6 +1728,8 @@
} }
/* The main grid-fitting routine. */
static void static void
af_cjk_hint_edges( AF_GlyphHints hints, af_cjk_hint_edges( AF_GlyphHints hints,
AF_Dimension dim ) AF_Dimension dim )
@ -2105,6 +2164,8 @@
} }
/* Apply the complete hinting algorithm to a CJK glyph. */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_cjk_hints_apply( AF_GlyphHints hints, af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,

View File

@ -60,8 +60,9 @@
AF_GlyphHintsRec hints[1]; AF_GlyphHintsRec hints[1];
FT_TRACE5(( "standard widths computation\n" FT_TRACE5(( "latin standard widths computation\n"
"===========================\n\n" )); "=================================\n"
"\n" ));
af_glyph_hints_init( hints, face->memory ); af_glyph_hints_init( hints, face->memory );
@ -82,7 +83,7 @@
if ( glyph_index == 0 ) if ( glyph_index == 0 )
goto Exit; goto Exit;
FT_TRACE5(( "standard character: 0x%X (glyph index %d)\n", FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n",
metrics->root.script_class->standard_char, glyph_index )); metrics->root.script_class->standard_char, glyph_index ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
@ -147,22 +148,21 @@
} }
/* this also replaces multiple almost identical stem widths */ /* this also replaces multiple almost identical stem widths */
/* with a single one (the value 100 is heuristic) */ /* with a single one (the value 100 is heuristic) */
af_sort_and_quantize_widths( &num_widths, axis->widths, af_sort_and_quantize_widths( &num_widths, axis->widths,
dummy->units_per_em / 100 ); dummy->units_per_em / 100 );
axis->width_count = num_widths; axis->width_count = num_widths;
} }
Exit: Exit:
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{ {
AF_LatinAxis axis = &metrics->axis[dim]; AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos stdw; FT_Pos stdw;
stdw = ( axis->width_count > 0 ) stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
? axis->widths[0].org : AF_LATIN_CONSTANT( metrics, 50 );
: AF_LATIN_CONSTANT( metrics, 50 );
/* let's try 20% of the smallest width */ /* let's try 20% of the smallest width */
axis->edge_distance_threshold = stdw / 5; axis->edge_distance_threshold = stdw / 5;
@ -203,11 +203,13 @@
{ {
FT_Pos flats [AF_BLUE_STRING_MAX_LEN]; FT_Pos flats [AF_BLUE_STRING_MAX_LEN];
FT_Pos rounds[AF_BLUE_STRING_MAX_LEN]; FT_Pos rounds[AF_BLUE_STRING_MAX_LEN];
FT_Int num_flats; FT_Int num_flats;
FT_Int num_rounds; FT_Int num_rounds;
AF_LatinBlue blue; AF_LatinBlue blue;
FT_Error error; FT_Error error;
AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
FT_Outline outline; FT_Outline outline;
AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset; AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset;
@ -219,8 +221,8 @@
/* top-most or bottom-most points (depending on the string */ /* top-most or bottom-most points (depending on the string */
/* properties) */ /* properties) */
FT_TRACE5(( "blue zones computation\n" FT_TRACE5(( "latin blue zones computation\n"
"======================\n" "============================\n"
"\n" )); "\n" ));
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ ) for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
@ -247,15 +249,23 @@
GET_UTF8_CHAR( ch, p ); GET_UTF8_CHAR( ch, p );
FT_TRACE5(( " U+%lX... ", ch ));
/* load the character in the face -- skip unknown or empty ones */ /* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, ch ); glyph_index = FT_Get_Char_Index( face, ch );
if ( glyph_index == 0 ) if ( glyph_index == 0 )
{
FT_TRACE5(( "unavailable\n" ));
continue; continue;
}
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
outline = face->glyph->outline; outline = face->glyph->outline;
if ( error || outline.n_points <= 0 ) if ( error || outline.n_points <= 0 )
{
FT_TRACE5(( "no outline\n" ));
continue; continue;
}
/* now compute min or max point indices and coordinates */ /* now compute min or max point indices and coordinates */
points = outline.points; points = outline.points;
@ -309,7 +319,8 @@
best_contour_last = last; best_contour_last = last;
} }
} }
FT_TRACE5(( " %c %ld", *p, best_y ));
FT_TRACE5(( "best_y = %5ld\n", best_y ));
} }
/* now check whether the point belongs to a straight or round */ /* now check whether the point belongs to a straight or round */
@ -456,7 +467,7 @@
} }
else else
{ {
*blue_ref = flats[num_flats / 2]; *blue_ref = flats [num_flats / 2];
*blue_shoot = rounds[num_rounds / 2]; *blue_shoot = rounds[num_rounds / 2];
} }
@ -1662,8 +1673,8 @@
AF_Edge_Flags base_flags, AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags ) AF_Edge_Flags stem_flags )
{ {
AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics; AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
AF_LatinAxis axis = & metrics->axis[dim]; AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos dist = width; FT_Pos dist = width;
FT_Int sign = 0; FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT ); FT_Int vertical = ( dim == AF_DIMENSION_VERT );
@ -2422,6 +2433,7 @@
af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
} }
} }
af_glyph_hints_save( hints, outline ); af_glyph_hints_save( hints, outline );
Exit: Exit: