Formatting, minor doc improvements.

This commit is contained in:
Werner Lemberg 2011-05-09 09:48:49 +02:00
parent 084abf0469
commit 27b20e9a1e
4 changed files with 171 additions and 151 deletions

View File

@ -16,10 +16,9 @@ CHANGES BETWEEN 2.4.4 and 2.4.5
redundant and is simply ignored; this means that FreeType now
ignores the global advance width value in TrueType fonts.
- Just Fill Bugs contributed an experimental code to compute blue
zones for CJK Ideographs, to improve the alignment of horizontal
stems at the top or bottom edges. Mainly tested with a TrueType
WenQuanYi-ZenHei.
- Just Fill Bugs contributed (experimental) code to compute blue
zones for CJK Ideographs, improving the alignment of horizontal
stems at the top or bottom edges.
III. MISCELLANEOUS

View File

@ -62,7 +62,8 @@
/*************************************************************************/
/* Basically the Latin version with AF_CJKMetrics to replace AF_LatinMetrics */
/* Basically the Latin version with AF_CJKMetrics */
/* to replace AF_LatinMetrics. */
FT_LOCAL_DEF( void )
af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
@ -79,11 +80,11 @@
metrics->axis[AF_DIMENSION_VERT].width_count = 0;
{
FT_Error error;
FT_UInt glyph_index;
int dim;
AF_CJKMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
FT_Error error;
FT_UInt glyph_index;
int dim;
AF_CJKMetricsRec dummy[1];
AF_Scaler scaler = &dummy->root.scaler;
glyph_index = FT_Get_Char_Index( face, charcode );
@ -121,13 +122,11 @@
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;
@ -155,16 +154,15 @@
axis->width_count = num_widths;
}
Exit:
Exit:
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
AF_CJKAxis axis = &metrics->axis[dim];
FT_Pos stdw;
AF_CJKAxis axis = &metrics->axis[dim];
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;
@ -177,13 +175,12 @@
}
#define AF_CJK_MAX_TEST_CHARACTERS 32
/* Every blue zone has 2 types of fill and unfill,
* Which means fill the entire square or not.
* */
/* Each blue zone has two types of fill and unfill, this is, */
/* filling the entire glyph square or not. */
enum
{
AF_CJK_BLUE_TYPE_FILL,
@ -191,6 +188,7 @@
AF_CJK_BLUE_TYPE_MAX
};
/* Put some common and representative Han Ideographs characters here. */
static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX]
[AF_CJK_BLUE_TYPE_MAX]
@ -260,28 +258,32 @@
};
/* Calculate blue zones for all the CJK_BLUE_XXX's */
/* 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] )
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 flats[AF_CJK_MAX_TEST_CHARACTERS];
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;
/* we compute the blues simply by loading each character from the */
/* 'blue_chars[blues]' string, then compute its extreme */
/* points (depending blue zone type etc.) */
/* We compute the blues simply by loading each character from the */
/* `blue_chars[blues]' string, then computing its extreme points */
/* (depending blue zone type etc.). */
FT_TRACE5(( "cjk blue zones computation\n" ));
FT_TRACE5(( "------------------------------------------------\n" ));
@ -293,13 +295,15 @@
FT_Pos* blue_shoot;
num_fills = 0;
num_flats = 0;
for ( fill_type = 0 ; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++)
num_fills = 0;
num_flats = 0;
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* limit = p + AF_CJK_MAX_TEST_CHARACTERS;
FT_Bool fill = FT_BOOL( fill_type == AF_CJK_BLUE_TYPE_FILL );
FT_Bool fill = FT_BOOL(
fill_type == AF_CJK_BLUE_TYPE_FILL );
FT_TRACE5(( "cjk blue %3d/%d: ", bb, fill_type ));
@ -312,6 +316,7 @@
FT_Int best_point, best_first, best_last;
FT_Vector* points;
FT_TRACE5(( "0x%lX", *p ));
/* load the character in the face -- skip unknown or empty ones */
@ -336,7 +341,9 @@
FT_Int last = -1;
for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
for ( nn = 0;
nn < glyph->outline.n_contours;
first = last + 1, nn++ )
{
FT_Int old_best_point = best_point;
FT_Int pp;
@ -344,49 +351,54 @@
last = glyph->outline.contours[nn];
/* Avoid single-point contours since they are never rasterized. */
/* In some fonts, they correspond to mark attachment points */
/* which are way outside of the glyph's real outline. */
/* Avoid single-point contours since they are never */
/* rasterized. In some fonts, they correspond to mark */
/* attachment points which are way outside of the glyph's */
/* real outline. */
if ( last <= first )
continue;
switch (bb)
switch ( bb )
{
case AF_CJK_BLUE_TOP:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y > best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
break;
case AF_CJK_BLUE_BOTTOM:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y < best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
break;
case AF_CJK_BLUE_LEFT:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x < best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
break;
case AF_CJK_BLUE_RIGHT:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x > best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
break;
default:
;
}
case AF_CJK_BLUE_TOP:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y > best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
break;
case AF_CJK_BLUE_BOTTOM:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y < best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
break;
case AF_CJK_BLUE_LEFT:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x < best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
break;
case AF_CJK_BLUE_RIGHT:
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x > best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
break;
default:
;
}
if ( best_point != old_best_point )
{
@ -397,7 +409,7 @@
FT_TRACE5(( "%5ld, ", best_pos ));
}
if (fill)
if ( fill )
fills[num_fills++] = best_pos;
else
flats[num_flats++] = best_pos;
@ -406,7 +418,7 @@
FT_TRACE5(( "\n" ));
}
if ( num_flats == 0 && num_fills == 0)
if ( num_flats == 0 && num_fills == 0 )
{
/*
* we couldn't find a single glyph to compute this blue zone,
@ -417,8 +429,8 @@
}
/* we have computed the contents of the `fill' and `flats' tables, */
/* now determine the reference position of the blue -- */
/* we simply take the median value after a simple sort */
/* now determine the reference position of the blue -- */
/* we simply take the median value after a simple sort */
af_sort_pos( num_flats, flats );
af_sort_pos( num_fills, fills );
@ -448,8 +460,8 @@
*blue_shoot = flats[num_flats / 2];
}
/* make sure blue_ref >= blue_shoot for top/right or
* vis vesa for bottom/left. */
/* make sure blue_ref >= blue_shoot for top/right or */
/* vice versa for bottom/left */
if ( *blue_shoot != *blue_ref )
{
FT_Pos ref = *blue_ref;
@ -467,8 +479,10 @@
else if ( AF_CJK_BLUE_RIGHT == bb )
blue->flags |= AF_CJK_BLUE_IS_RIGHT;
FT_TRACE5(( "-- cjk ref = %ld shoot = %ld\n", *blue_ref, *blue_shoot ));
FT_TRACE5(( "-- cjk ref = %ld shoot = %ld\n",
*blue_ref, *blue_shoot ));
}
return;
}
@ -580,8 +594,8 @@
/* scale the blue zones */
for ( nn = 0; nn < axis->blue_count; nn++ )
{
AF_CJKBlue blue = &axis->blues[nn];
FT_Pos dist;
AF_CJKBlue blue = &axis->blues[nn];
FT_Pos dist;
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
@ -596,10 +610,11 @@
{
FT_Pos delta1, delta2;
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
/* shoot is under shoot for cjk */
delta1 = FT_DivFix(blue->ref.fit, scale) - blue->shoot.org;
delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org;
delta2 = delta1;
if ( delta1 < 0 )
delta2 = -delta2;
@ -609,10 +624,10 @@
FT_TRACE5(( "delta: %d", delta1 ));
if ( delta2 < 32 )
delta2 = 0;
/*
#if 0
else if ( delta2 < 64 )
delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
*/
#endif
else
delta2 = FT_PIX_ROUND( delta2 );
FT_TRACE5(( "/%d\n", delta2 ));
@ -624,10 +639,10 @@
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',
( 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->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;
}
@ -1143,14 +1158,14 @@
FT_LOCAL_DEF( void )
af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
AF_CJKMetrics metrics,
AF_Dimension dim )
af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
AF_CJKMetrics metrics,
AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[ dim ];
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edge = axis->edges;
AF_Edge edge_limit = edge + axis->num_edges;
AF_CJKAxis cjk = &metrics->axis[ dim ];
AF_CJKAxis cjk = &metrics->axis[dim];
FT_Fixed scale = cjk->scale;
FT_Pos best_dist0; /* initial threshold */
@ -1158,15 +1173,16 @@
/* compute the initial threshold as a fraction of the EM size */
best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
if ( best_dist0 > 64 / 2 ) /* Maximum 1/2 pixel */
if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */
best_dist0 = 64 / 2;
/* compute which blue zones are active, i.e. have their scaled */
/* size < 3/4 pixels */
/* If the distant between an edge and a blue zone is shorter than
* best_dist0, set the blue zone for the edge. Then search for
* the blue zone with the smallest best_dist to the edge. */
/* If the distant between an edge and a blue zone is shorter than */
/* best_dist0, set the blue zone for the edge. Then search for */
/* the blue zone with the smallest best_dist to the edge. */
for ( ; edge < edge_limit; edge++ )
{
FT_UInt bb;
@ -1176,8 +1192,9 @@
for ( bb = 0; bb < cjk->blue_count; bb++ )
{
AF_CJKBlue blue = cjk->blues + bb;
FT_Bool is_top_right_blue, is_major_dir;
AF_CJKBlue blue = cjk->blues + bb;
FT_Bool is_top_right_blue, is_major_dir;
/* skip inactive blue zones (i.e., those that are too small) */
if ( !( blue->flags & AF_CJK_BLUE_ACTIVE ) )
@ -1187,8 +1204,9 @@
/* zone, check for left edges */
/* */
/* of course, that's for TrueType */
is_top_right_blue = FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP ) != 0 ) ||
( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) );
is_top_right_blue =
FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP ) != 0 ) ||
( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) );
is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
/* if it is a top zone, the edge must be against the major */
@ -1208,7 +1226,7 @@
compare = &blue->ref;
dist = edge->fpos - compare->org;
if (dist < 0)
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, scale );
@ -1227,8 +1245,8 @@
FT_LOCAL_DEF( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
@ -1353,11 +1371,11 @@
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
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 );
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 );
FT_UNUSED( base_flags );
FT_UNUSED( stem_flags );
@ -2073,9 +2091,9 @@
FT_LOCAL_DEF( FT_Error )
af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
FT_Error error;
int dim;

View File

@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK script (specification). */
/* */
/* Copyright 2006, 2007 by */
/* Copyright 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -33,9 +33,9 @@ FT_BEGIN_HEADER
/* CJK (global) metrics management */
/*
* CJK glyphs tend to fill the square. So we have both verticle and
* horizontal blue zones. But some glyphs have flat bounding stroke that
* leave some space between neighbour glyphs.
* CJK glyphs tend to fill the square. So we have both vertical and
* horizontal blue zones. But some glyphs have flat bounding strokes that
* leave some space between neighbour glyphs.
*/
enum
{
@ -58,10 +58,11 @@ FT_BEGIN_HEADER
AF_CJK_BLUE_IS_TOP = 1 << 1,
AF_CJK_BLUE_IS_RIGHT = 1 << 2,
AF_CJK_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */
/* optimization */
/* optimization */
AF_CJK_BLUE_FLAG_MAX
};
typedef struct AF_CJKBlueRec_
{
AF_WidthRec ref;
@ -70,24 +71,25 @@ FT_BEGIN_HEADER
} AF_CJKBlueRec, *AF_CJKBlue;
typedef struct AF_CJKAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count;
AF_WidthRec widths[AF_CJK_MAX_WIDTHS];
FT_Pos edge_distance_threshold;
FT_Pos standard_width;
FT_Bool extra_light;
FT_UInt width_count;
AF_WidthRec widths[AF_CJK_MAX_WIDTHS];
FT_Pos edge_distance_threshold;
FT_Pos standard_width;
FT_Bool extra_light;
/* used for horizontal metrics too for CJK */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
FT_Fixed org_scale;
FT_Pos org_delta;
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_CJKAxisRec, *AF_CJKAxis;
@ -100,22 +102,23 @@ FT_BEGIN_HEADER
} AF_CJKMetricsRec, *AF_CJKMetrics;
FT_LOCAL( FT_Error )
af_cjk_metrics_init( AF_CJKMetrics metrics,
FT_Face face );
af_cjk_metrics_init( AF_CJKMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_cjk_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler );
af_cjk_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler );
FT_LOCAL( FT_Error )
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics );
af_cjk_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics );
FT_LOCAL( FT_Error )
af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics );
af_cjk_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics );
/* Shared. called from afindic.c */
FT_LOCAL( void )

View File

@ -33,8 +33,8 @@
static FT_Error
af_indic_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
af_indic_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
{
/* skip blue zone init in CJK routines */
FT_CharMap oldmap = face->charmap;
@ -48,7 +48,7 @@
{
af_cjk_metrics_init_widths( metrics, face, 0x7530 );
#if 0
/* either need indic specific blue_chars[] or just skip blue zones. */
/* either need indic specific blue_chars[] or just skip blue zones */
af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
#endif
af_cjk_metrics_check_digits( metrics, face );
@ -61,8 +61,8 @@
static void
af_indic_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler )
af_indic_metrics_scale( AF_CJKMetrics metrics,
AF_Scaler scaler )
{
/* use CJK routines */
af_cjk_metrics_scale( metrics, scaler );
@ -70,8 +70,8 @@
static FT_Error
af_indic_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
af_indic_hints_init( AF_GlyphHints hints,
AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_init( hints, metrics );
@ -79,9 +79,9 @@
static FT_Error
af_indic_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics)
af_indic_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_apply( hints, outline, metrics );