[autofit] Make `cjk' module use blue stringsets.

* src/autofit/afcjk.c (AF_CJK_MAX_TEST_CHARACTERS): Removed.
(af_cjk_hani_blue_chars): Removed.
(AF_CJK_BLUE_TYPE_*): Removed.
(af_cjk_metrics_init_blues): Replace AF_CJK_MAX_TEST_CHARACTERS with
AF_BLUE_STRING_MAX_LEN.
Change loops to use offsets (in file `afblue.h') into the new arrays
`af_blue_stringsets' and `af_blue_strings' (in file `afblue.c').
Instead of three dimensions (as used in the old blue string array)
we now use properties to do the same, saving one loop nesting level.

* src/autofit/afcjk.h: Remove old enumeration values superseded by
the new data in `afblue.h'.
(AF_CJK_IS_TOP_BLUE, AF_CJK_IS_HORIZ_BLUE, AF_CJK_IS_FILLED_BLUE,
AF_CJK_IS_RIGHT_BLUE): New macros, to be used in
`af_cjk_metrics_init_blues'.
(AF_CJK_BLUE_IS_RIGHT): Remove this now redundant enum value.
(AF_CJK_BLUE_IS_TOP): Renamed to...
(AF_CJK_BLUE_TOP): This.
(AF_CJK_MAX_BLUES): Remove.
(AF_CJKAxisRec): Updated.
This commit is contained in:
Werner Lemberg 2013-08-25 19:47:26 +02:00
parent 5c4a23a4e9
commit c1eb445965
4 changed files with 174 additions and 233 deletions

View File

@ -1,3 +1,28 @@
2013-08-25 Werner Lemberg <wl@gnu.org>
[autofit] Make `cjk' module use blue stringsets.
* src/autofit/afcjk.c (AF_CJK_MAX_TEST_CHARACTERS): Removed.
(af_cjk_hani_blue_chars): Removed.
(AF_CJK_BLUE_TYPE_*): Removed.
(af_cjk_metrics_init_blues): Replace AF_CJK_MAX_TEST_CHARACTERS with
AF_BLUE_STRING_MAX_LEN.
Change loops to use offsets (in file `afblue.h') into the new arrays
`af_blue_stringsets' and `af_blue_strings' (in file `afblue.c').
Instead of three dimensions (as used in the old blue string array)
we now use properties to do the same, saving one loop nesting level.
* src/autofit/afcjk.h: Remove old enumeration values superseded by
the new data in `afblue.h'.
(AF_CJK_IS_TOP_BLUE, AF_CJK_IS_HORIZ_BLUE, AF_CJK_IS_FILLED_BLUE,
AF_CJK_IS_RIGHT_BLUE): New macros, to be used in
`af_cjk_metrics_init_blues'.
(AF_CJK_BLUE_IS_RIGHT): Remove this now redundant enum value.
(AF_CJK_BLUE_IS_TOP): Renamed to...
(AF_CJK_BLUE_TOP): This.
(AF_CJK_MAX_BLUES): Remove.
(AF_CJKAxisRec): Updated.
2013-08-25 Werner Lemberg <wl@gnu.org>
[autofit] Typo.

View File

@ -207,252 +207,172 @@
}
#define AF_CJK_MAX_TEST_CHARACTERS 32
/* 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,
AF_CJK_BLUE_TYPE_UNFILL,
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]
[AF_CJK_MAX_TEST_CHARACTERS] =
{
{
{
0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703,
0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
0x9F4A /* top fill */
},
{
0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F,
0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981,
0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762,
0x987E /* top unfill */
}
},
{
{
0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86,
0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31,
0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA,
0x8BF4 /* bottom fill */
},
{
0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F,
0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1,
0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC,
0x9762 /* bottom unfill */
}
},
#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
{ {0x0000}, {0x0000} },
{ {0x0000}, {0x0000} }
#else
{
{
0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700,
0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
0x901A /* left fill */
},
{
0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE,
0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593,
0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B,
0x96A8 /* left unfill */
}
},
{
{
0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216,
0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1,
0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01,
0x8D77 /* right fill */
},
{
0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE,
0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E,
0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593,
0x95F4 /* right unfill */
}
}
#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
};
/* Calculate blue zones for all the CJK_BLUE_XXX's. */
/* Find all blue zones. */
static void
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_BLUE_STRING_MAX_LEN];
FT_Pos flats[AF_BLUE_STRING_MAX_LEN];
FT_Int num_fills;
FT_Int num_flats;
FT_Int bb;
AF_CJKBlue blue;
FT_Error error;
AF_CJKAxis axis;
FT_Outline outline;
AF_Blue_Stringset bss = metrics->root.script_class->blue_stringset;
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
#ifdef FT_DEBUG_LEVEL_TRACE
FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = {
(FT_String*)"top",
(FT_String*)"bottom",
(FT_String*)"left",
(FT_String*)"right"
FT_String* cjk_blue_name[4] =
{
(FT_String*)"bottom", /* -- , -- */
(FT_String*)"top", /* -- , TOP */
(FT_String*)"left", /* HORIZ, -- */
(FT_String*)"right" /* HORIZ, TOP */
};
FT_String* cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = {
(FT_String*)"filled",
(FT_String*)"unfilled"
FT_String* cjk_blue_type_name[2] =
{
(FT_String*)"unfilled", /* -- */
(FT_String*)"filled" /* FILL */
};
#endif
/* 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.). */
/* we walk over the blue character strings as specified in the */
/* script's entry in the `af_blue_stringset' array, computing its */
/* extremum points (depending on the string properties) */
FT_TRACE5(( "cjk blue zones computation\n"
"==========================\n"
"\n" ));
for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
{
FT_Int fill_type;
FT_Pos* blue_ref;
FT_Pos* blue_shoot;
const char* p = &af_blue_strings[bs->string];
FT_Pos* blue_ref;
FT_Pos* blue_shoot;
FT_TRACE5(( "blue zone %d:\n", axis->blue_count ));
num_fills = 0;
num_flats = 0;
for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
FT_TRACE5(( " cjk blue %s/%s\n",
cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) |
AF_CJK_IS_TOP_BLUE( bs ) ],
cjk_blue_type_name[!!AF_CJK_IS_FILLED_BLUE( bs )] ));
while ( *p )
{
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 );
FT_ULong ch;
FT_UInt glyph_index;
FT_Pos best_pos; /* same as points.y or points.x, resp. */
FT_Int best_point;
FT_Vector* points;
FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
cjk_blue_type_name[fill_type] ));
GET_UTF8_CHAR( ch, p );
for ( ; p < limit && *p; 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_UInt glyph_index;
FT_Pos best_pos; /* same as points.y */
FT_Int best_point;
FT_Vector* points;
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;
best_point = -1;
best_pos = 0; /* make compiler happy */
{
FT_Int nn;
FT_Int first = 0;
FT_Int last = -1;
FT_TRACE5(( " U+%lX... ", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, *p );
if ( glyph_index == 0 )
for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
{
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;
best_point = -1;
best_pos = 0; /* make compiler happy */
{
FT_Int nn;
FT_Int first = 0;
FT_Int last = -1;
FT_Int pp;
for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
last = 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. */
if ( last <= first )
continue;
if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
{
FT_Int pp;
last = 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. */
if ( last <= first )
continue;
switch ( bb )
if ( AF_CJK_IS_RIGHT_BLUE( bs ) )
{
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:
;
}
else
{
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].x < best_pos )
{
best_point = pp;
best_pos = points[pp].x;
}
}
}
else
{
if ( AF_CJK_IS_TOP_BLUE( bs ) )
{
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y > best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
}
else
{
for ( pp = first; pp <= last; pp++ )
if ( best_point < 0 || points[pp].y < best_pos )
{
best_point = pp;
best_pos = points[pp].y;
}
}
}
FT_TRACE5(( "best_pos = %5ld\n", best_pos ));
}
if ( fill )
fills[num_fills++] = best_pos;
else
flats[num_flats++] = best_pos;
FT_TRACE5(( "best_pos = %5ld\n", best_pos ));
}
if ( AF_CJK_IS_FILLED_BLUE( bs ) )
fills[num_fills++] = best_pos;
else
flats[num_flats++] = best_pos;
}
if ( num_flats == 0 && num_fills == 0 )
@ -461,7 +381,7 @@
* 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;
}
@ -471,10 +391,10 @@
af_sort_pos( num_flats, flats );
af_sort_pos( num_fills, fills );
if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb )
axis = &metrics->axis[AF_DIMENSION_VERT];
else
if ( AF_CJK_IS_HORIZ_BLUE( bs ) )
axis = &metrics->axis[AF_DIMENSION_HORZ];
else
axis = &metrics->axis[AF_DIMENSION_VERT];
blue = &axis->blues[axis->blue_count];
blue_ref = &blue->ref.org;
@ -507,8 +427,8 @@
FT_Bool under_ref = FT_BOOL( shoot < ref );
if ( ( AF_CJK_BLUE_TOP == bb ||
AF_CJK_BLUE_RIGHT == bb ) ^ under_ref )
/* AF_CJK_IS_TOP_BLUE covers `right' and `top' */
if ( AF_CJK_IS_TOP_BLUE( bs ) ^ under_ref )
{
*blue_ref =
*blue_shoot = ( shoot + ref ) / 2;
@ -519,15 +439,12 @@
}
blue->flags = 0;
if ( AF_CJK_BLUE_TOP == bb )
blue->flags |= AF_CJK_BLUE_IS_TOP;
else if ( AF_CJK_BLUE_RIGHT == bb )
blue->flags |= AF_CJK_BLUE_IS_RIGHT;
if ( AF_CJK_IS_TOP_BLUE( bs ) )
blue->flags |= AF_CJK_BLUE_TOP;
FT_TRACE5(( " cjk %s bluezone\n"
" -> reference = %ld\n"
FT_TRACE5(( " -> reference = %ld\n"
" overshoot = %ld\n",
cjk_blue_name[bb], *blue_ref, *blue_shoot ));
*blue_ref, *blue_shoot ));
}
FT_TRACE5(( "\n" ));
@ -1269,10 +1186,8 @@
/* 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_major_dir = FT_BOOL( edge->dir == axis->major_dir );
is_top_right_blue = FT_BOOL( blue->flags & AF_CJK_BLUE_TOP );
is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
/* if it is a top zone, the edge must be against the major */
/* direction; if it is a bottom zone, it must be in the major */

View File

@ -36,35 +36,38 @@ FT_BEGIN_HEADER
AF_DECLARE_SCRIPT_CLASS( af_hani_script_class )
/* CJK (global) metrics management */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** C J K G L O B A L M E T R I C S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* 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
{
AF_CJK_BLUE_TOP,
AF_CJK_BLUE_BOTTOM,
AF_CJK_BLUE_LEFT,
AF_CJK_BLUE_RIGHT,
AF_CJK_BLUE_MAX
};
#define AF_CJK_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_CJK_TOP )
#define AF_CJK_IS_HORIZ_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_CJK_HORIZ )
#define AF_CJK_IS_FILLED_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_CJK_FILL )
#define AF_CJK_IS_RIGHT_BLUE AF_CJK_IS_TOP_BLUE
#define AF_CJK_MAX_WIDTHS 16
#define AF_CJK_MAX_BLUES AF_CJK_BLUE_MAX
enum
{
AF_CJK_BLUE_ACTIVE = 1 << 0,
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 */
AF_CJK_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
AF_CJK_BLUE_TOP = 1 << 1, /* result of AF_CJK_IS_TOP_BLUE */
AF_CJK_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
/* optimization */
AF_CJK_BLUE_FLAG_MAX
};
@ -83,16 +86,16 @@ FT_BEGIN_HEADER
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; /* number of used widths */
AF_WidthRec widths[AF_CJK_MAX_WIDTHS]; /* widths array */
FT_Pos edge_distance_threshold; /* used for creating edges */
FT_Pos standard_width; /* the default stem thickness */
FT_Bool extra_light; /* is standard width very light? */
/* used for horizontal metrics too for CJK */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
AF_CJKBlueRec blues[AF_BLUE_STRINGSET_MAX];
FT_Fixed org_scale;
FT_Pos org_delta;

View File

@ -61,8 +61,6 @@ FT_BEGIN_HEADER
*/
/* Latin (global) metrics management */
#define AF_LATIN_IS_TOP_BLUE( b ) \
( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
#define AF_LATIN_IS_SMALL_TOP_BLUE( b ) \