ref: 306f8c5d89979e83c884ba7a902d9971111b772a
parent: 0975d685ed32225e37068d38f3c8bf66e26d0843
author: Werner Lemberg <[email protected]>
date: Sun Aug 25 09:07:08 EDT 2013
[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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2013-08-25 Werner Lemberg <[email protected]>
+ [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 <[email protected]>
+
[autofit] Make `latin' module use blue stringsets.
* src/autofit/aflatin.c (AF_LATIN_MAX_TEST_CHARACTERS): Removed.
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -73,6 +73,10 @@
AF_GlyphHintsRec hints[1];
+ FT_TRACE5(( "cjk standard widths computation\n"
+ "===============================\n"
+ "\n" ));
+
af_glyph_hints_init( hints, face->memory );
metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
@@ -92,6 +96,9 @@
if ( glyph_index == 0 )
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 );
if ( error || face->glyph->outline.n_points <= 0 )
goto Exit;
@@ -123,11 +130,13 @@
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 )
goto Exit;
- af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+ af_latin_hints_link_segments( hints,
+ (AF_Dimension)dim );
seg = axhints->segments;
limit = seg + axhints->num_segments;
@@ -152,7 +161,7 @@
}
/* 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,
dummy->units_per_em / 100 );
axis->width_count = num_widths;
@@ -172,9 +181,28 @@
axis->edge_distance_threshold = stdw / 5;
axis->standard_width = stdw;
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 );
}
@@ -265,24 +293,20 @@
/* Calculate blue zones for all the CJK_BLUE_XXX's. */
static void
- af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
- FT_Face face,
- const FT_ULong blue_chars
- [AF_CJK_BLUE_MAX]
- [AF_CJK_BLUE_TYPE_MAX]
- [AF_CJK_MAX_TEST_CHARACTERS] )
+ af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
+ FT_Face face )
{
- FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
- FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
+ FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
+ FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
- FT_Int num_fills;
- FT_Int num_flats;
+ FT_Int num_fills;
+ FT_Int num_flats;
- FT_Int bb;
- AF_CJKBlue blue;
- FT_Error error;
- AF_CJKAxis axis;
- FT_GlyphSlot glyph = face->glyph;
+ FT_Int bb;
+ AF_CJKBlue blue;
+ FT_Error error;
+ AF_CJKAxis axis;
+ FT_Outline outline;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = {
@@ -302,8 +326,9 @@
/* `blue_chars[blues]' string, then computing its extreme points */
/* (depending blue zone type etc.). */
- FT_TRACE5(( "cjk blue zones computation\n" ));
- FT_TRACE5(( "------------------------------------------------\n" ));
+ FT_TRACE5(( "cjk blue zones computation\n"
+ "==========================\n"
+ "\n" ));
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++ )
{
- 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;
FT_Bool fill = FT_BOOL(
fill_type == AF_CJK_BLUE_TYPE_FILL );
@@ -326,7 +351,6 @@
FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
cjk_blue_type_name[fill_type] ));
-
for ( ; p < limit && *p; p++ )
{
FT_UInt glyph_index;
@@ -335,7 +359,7 @@
FT_Vector* points;
- FT_TRACE5(( " U+%lX...", *p ));
+ FT_TRACE5(( " U+%lX... ", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, *p );
@@ -345,8 +369,9 @@
continue;
}
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
- if ( error || glyph->outline.n_points <= 0 )
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ outline = face->glyph->outline;
+ if ( error || outline.n_points <= 0 )
{
FT_TRACE5(( "no outline\n" ));
continue;
@@ -353,7 +378,7 @@
}
/* now compute min or max point indices and coordinates */
- points = glyph->outline.points;
+ points = outline.points;
best_point = -1;
best_pos = 0; /* make compiler happy */
@@ -363,14 +388,12 @@
FT_Int last = -1;
- for ( nn = 0;
- nn < glyph->outline.n_contours;
- first = last + 1, nn++ )
+ for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
{
FT_Int pp;
- last = glyph->outline.contours[nn];
+ last = outline.contours[nn];
/* Avoid single-point contours since they are never */
/* 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 )
@@ -437,12 +461,12 @@
* 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;
}
/* 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 */
af_sort_pos( num_flats, flats );
af_sort_pos( num_fills, fills );
@@ -452,19 +476,20 @@
else
axis = &metrics->axis[AF_DIMENSION_HORZ];
- 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++;
+
if ( num_flats == 0 )
{
- *blue_ref = fills[num_fills / 2];
+ *blue_ref =
*blue_shoot = fills[num_fills / 2];
}
else if ( num_fills == 0 )
{
- *blue_ref = flats[num_flats / 2];
+ *blue_ref =
*blue_shoot = flats[num_flats / 2];
}
else
@@ -484,7 +509,13 @@
if ( ( AF_CJK_BLUE_TOP == bb ||
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;
@@ -493,15 +524,20 @@
else if ( AF_CJK_BLUE_RIGHT == bb )
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 ));
}
+ FT_TRACE5(( "\n" ));
+
return;
}
/* Basically the Latin version with type AF_CJKMetrics for metrics. */
+
FT_LOCAL_DEF( void )
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
FT_Face face )
@@ -511,8 +547,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;
@@ -548,6 +583,8 @@
}
+ /* Initialize global metrics. */
+
FT_LOCAL_DEF( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
@@ -557,21 +594,21 @@
metrics->units_per_em = face->units_per_EM;
- if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
- face->charmap = NULL;
- else
+ if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
{
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 );
}
FT_Set_Charmap( face, oldmap );
-
return FT_Err_Ok;
}
+ /* Adjust scaling value, then scale and shift widths */
+ /* and blue zones (if applicable) for given dimension. */
+
static void
af_cjk_metrics_scale_dim( AF_CJKMetrics metrics,
AF_Scaler scaler,
@@ -583,8 +620,6 @@
FT_UInt nn;
- axis = &metrics->axis[dim];
-
if ( dim == AF_DIMENSION_HORZ )
{
scale = scaler->x_scale;
@@ -596,6 +631,8 @@
delta = scaler->y_delta;
}
+ axis = &metrics->axis[dim];
+
if ( axis->org_scale == scale && axis->org_delta == delta )
return;
@@ -651,12 +688,13 @@
blue->shoot.fit = blue->ref.fit - delta2;
- FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: "
- "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n",
- ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
- nn, blue->ref.org, blue->shoot.org,
- blue->ref.cur / 64.0, blue->ref.fit / 64.0,
- blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+ FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
+ " ref: cur=%.2f fit=%.2f\n"
+ " shoot: cur=%.2f fit=%.2f\n",
+ ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
+ nn, blue->ref.org, blue->shoot.org,
+ 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;
}
@@ -664,11 +702,15 @@
}
+ /* Scale global values in both directions. */
+
FT_LOCAL_DEF( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics,
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_VERT );
@@ -683,6 +725,9 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Walk over all contours and compute its segments. */
+
static FT_Error
af_cjk_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim )
@@ -939,7 +984,7 @@
for ( seg = segments; seg < segment_limit; seg++ )
{
- AF_Edge found = 0;
+ AF_Edge found = NULL;
FT_Pos best = 0xFFFFU;
FT_Int ee;
@@ -1027,25 +1072,26 @@
}
}
- /*********************************************************************/
- /* */
- /* Good, we now compute each edge's properties according to segments */
- /* found on its position. Basically, these are as follows. */
- /* */
- /* - 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 */
- /* */
- /*********************************************************************/
+ /******************************************************************/
+ /* */
+ /* Good, we now compute each edge's properties according to the */
+ /* segments found on its position. Basically, these are */
+ /* */
+ /* - 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 */
+ /* */
+ /******************************************************************/
- /* first of all, set the `edge' field in each segment -- this is */
- /* 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. */
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* 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.
+ */
{
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
@@ -1154,6 +1200,8 @@
}
+ /* Detect segments and edges for given dimension. */
+
static FT_Error
af_cjk_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1172,6 +1220,8 @@
}
+ /* Compute all edges which lie within blue zones. */
+
FT_LOCAL_DEF( void )
af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
AF_CJKMetrics metrics,
@@ -1259,6 +1309,8 @@
}
+ /* Initalize hinting engine. */
+
FT_LOCAL_DEF( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
@@ -1317,7 +1369,7 @@
hints->scaler_flags = scaler_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 */
- /* current standard widths */
+ /* Snap a given width in scaled coordinates to one of the */
+ /* current standard widths. */
static FT_Pos
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
af_cjk_compute_stem_width( AF_GlyphHints hints,
@@ -1386,8 +1440,8 @@
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
- AF_CJKMetrics metrics = (AF_CJKMetrics) hints->metrics;
- AF_CJKAxis axis = & metrics->axis[dim];
+ AF_CJKMetrics metrics = (AF_CJKMetrics)hints->metrics;
+ AF_CJKAxis axis = &metrics->axis[dim];
FT_Pos dist = width;
FT_Int sign = 0;
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
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
af_cjk_align_serif_edge( AF_GlyphHints hints,
AF_Edge base,
@@ -1671,6 +1728,8 @@
}
+ /* The main grid-fitting routine. */
+
static void
af_cjk_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -2104,6 +2163,8 @@
}
}
+
+ /* Apply the complete hinting algorithm to a CJK glyph. */
FT_LOCAL_DEF( FT_Error )
af_cjk_hints_apply( AF_GlyphHints hints,
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -60,8 +60,9 @@
AF_GlyphHintsRec hints[1];
- FT_TRACE5(( "standard widths computation\n"
- "===========================\n\n" ));
+ FT_TRACE5(( "latin standard widths computation\n"
+ "=================================\n"
+ "\n" ));
af_glyph_hints_init( hints, face->memory );
@@ -82,7 +83,7 @@
if ( glyph_index == 0 )
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 ));
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
@@ -147,13 +148,13 @@
}
/* 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,
dummy->units_per_em / 100 );
axis->width_count = num_widths;
}
- Exit:
+ Exit:
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
AF_LatinAxis axis = &metrics->axis[dim];
@@ -160,9 +161,8 @@
FT_Pos stdw;
- stdw = ( axis->width_count > 0 )
- ? axis->widths[0].org
- : AF_LATIN_CONSTANT( metrics, 50 );
+ stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
/* let's try 20% of the smallest width */
axis->edge_distance_threshold = stdw / 5;
@@ -203,11 +203,13 @@
{
FT_Pos flats [AF_BLUE_STRING_MAX_LEN];
FT_Pos rounds[AF_BLUE_STRING_MAX_LEN];
+
FT_Int num_flats;
FT_Int num_rounds;
+
AF_LatinBlue blue;
FT_Error error;
- AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
FT_Outline outline;
AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset;
@@ -219,8 +221,8 @@
/* top-most or bottom-most points (depending on the string */
/* properties) */
- FT_TRACE5(( "blue zones computation\n"
- "======================\n"
+ FT_TRACE5(( "latin blue zones computation\n"
+ "============================\n"
"\n" ));
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
@@ -247,15 +249,23 @@
GET_UTF8_CHAR( ch, p );
+ FT_TRACE5(( " U+%lX... ", ch ));
+
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, ch );
if ( glyph_index == 0 )
+ {
+ FT_TRACE5(( "unavailable\n" ));
continue;
+ }
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
outline = face->glyph->outline;
if ( error || outline.n_points <= 0 )
+ {
+ FT_TRACE5(( "no outline\n" ));
continue;
+ }
/* now compute min or max point indices and coordinates */
points = outline.points;
@@ -309,7 +319,8 @@
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 */
@@ -456,7 +467,7 @@
}
else
{
- *blue_ref = flats[num_flats / 2];
+ *blue_ref = flats [num_flats / 2];
*blue_shoot = rounds[num_rounds / 2];
}
@@ -1662,8 +1673,8 @@
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
- AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
- AF_LatinAxis axis = & metrics->axis[dim];
+ AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics;
+ AF_LatinAxis axis = &metrics->axis[dim];
FT_Pos dist = width;
FT_Int sign = 0;
FT_Int vertical = ( dim == AF_DIMENSION_VERT );
@@ -2422,6 +2433,7 @@
af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
}
}
+
af_glyph_hints_save( hints, outline );
Exit: