|
|
|
@ -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,15 +369,16 @@ |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 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 */ |
|
|
|
|
/* */ |
|
|
|
|
/*********************************************************************/ |
|
|
|
|
|
|
|
|
|
/* 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. */ |
|
|
|
|
/******************************************************************/ |
|
|
|
|
/* */ |
|
|
|
|
/* 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. |
|
|
|
|
*/ |
|
|
|
|
{ |
|
|
|
|
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 ) |
|
|
|
@ -2105,6 +2164,8 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Apply the complete hinting algorithm to a CJK glyph. */ |
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( FT_Error ) |
|
|
|
|
af_cjk_hints_apply( AF_GlyphHints hints, |
|
|
|
|
FT_Outline* outline, |
|
|
|
|