[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:
parent
0975d685ed
commit
306f8c5d89
17
ChangeLog
17
ChangeLog
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue