mirror of
https://gitlab.freedesktop.org/freetype/freetype.git
synced 2026-05-05 10:08:12 +02:00
[autofit] More tilde stretch support. (3/3)
The auto-hinter now supports up to four tilde glyphs (two above and two below a base character). Note that diacritics above (or below) a tilde are now also ignored by the auto-hinter. * src/autofit/afadjust.h (AF_ADJUST_TILDE_TOP2, AF_ADJUST_TILDE_BOTTOM2): New macros. * src/autofit/afadjust.c (af_reverse_character_map_new): Updated. * src/autofit/aflatin.c (af_remove_top_points_from_edges, af_remove_bottom_points_from_edges): Make functions also handle all contours higher (or lower) of the given one in the argument. (af_touch_top_contours, af_touch_bottom_contours): New functions. (af_latin_stretch_top_tilde, af_latin_stretch_bottom_tilde): Use it to also handle all contours higher (or lower) than the tilde contour. * (af_latin_hints_apply): Handle more tilde glyphs.
This commit is contained in:
parent
c6b45a7646
commit
9eb6548d3d
3 changed files with 167 additions and 25 deletions
|
|
@ -678,8 +678,10 @@
|
|||
|
||||
const char* flag_names[] =
|
||||
{
|
||||
"up", /* AF_ADJUST_UP */
|
||||
"down", /* AF_ADJUST_DOWN */
|
||||
"up", /* AF_ADJUST_UP */
|
||||
"down", /* AF_ADJUST_DOWN */
|
||||
"double up", /* AF_ADJUST_UP2 */
|
||||
"double down", /* AF_ADJUST_DOWN2 */
|
||||
"",
|
||||
"",
|
||||
"top tilde", /* AF_ADJUST_TILDE_TOP */
|
||||
|
|
|
|||
|
|
@ -68,6 +68,16 @@ FT_BEGIN_HEADER
|
|||
/* stays legible at small sizes, not degenerating to a horizontal line. */
|
||||
#define AF_ADJUST_TILDE_BOTTOM 0x20
|
||||
|
||||
/* The contour below the topmost contour is a tilde. Enlarge it */
|
||||
/* vertically so that it stays legible at small sizes, not degenerating */
|
||||
/* to a horizontal line. */
|
||||
#define AF_ADJUST_TILDE_TOP2 0x40
|
||||
|
||||
/* The contour above the bottommost contour is a tilde. Enlarge it */
|
||||
/* vertically so that it stays legible at small sizes, not degenerating */
|
||||
/* to a horizontal line. */
|
||||
#define AF_ADJUST_TILDE_BOTTOM2 0x80
|
||||
|
||||
/* No adjustment, i.e., no flag is set. */
|
||||
#define AF_ADJUST_NONE 0x00
|
||||
|
||||
|
|
|
|||
|
|
@ -3072,38 +3072,71 @@
|
|||
}
|
||||
|
||||
|
||||
/* Remove all segments containing points on `contour`. */
|
||||
/* Remove all segments containing points on `limit_contour` */
|
||||
/* and all higher contours. */
|
||||
static void
|
||||
af_remove_top_points_from_edges( AF_GlyphHints hints,
|
||||
FT_Int contour )
|
||||
FT_Int limit_contour )
|
||||
{
|
||||
AF_Point first_point = hints->contours[contour];
|
||||
AF_Point p = first_point;
|
||||
FT_Pos limit = hints->contour_y_minima[limit_contour];
|
||||
|
||||
FT_Int contour;
|
||||
|
||||
|
||||
do
|
||||
for ( contour = 0; contour < hints->num_contours; contour++ )
|
||||
{
|
||||
p = p->next;
|
||||
af_remove_segments_containing_point( hints, p );
|
||||
FT_Pos min_y = hints->contour_y_minima[contour];
|
||||
FT_Pos max_y = hints->contour_y_maxima[contour];
|
||||
|
||||
} while ( p != first_point );
|
||||
|
||||
if ( min_y < max_y &&
|
||||
min_y >= limit )
|
||||
{
|
||||
AF_Point first_point = hints->contours[contour];
|
||||
AF_Point p = first_point;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
p = p->next;
|
||||
af_remove_segments_containing_point( hints, p );
|
||||
|
||||
} while ( p != first_point );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
af_remove_bottom_points_from_edges( AF_GlyphHints hints,
|
||||
FT_Int contour )
|
||||
FT_Int limit_contour )
|
||||
{
|
||||
AF_Point first_point = hints->contours[contour];
|
||||
AF_Point p = first_point;
|
||||
FT_Pos limit = hints->contour_y_maxima[limit_contour];
|
||||
|
||||
FT_Int contour;
|
||||
|
||||
|
||||
do
|
||||
for ( contour = 0; contour < hints->num_contours; contour++ )
|
||||
{
|
||||
p = p->next;
|
||||
af_remove_segments_containing_point( hints, p );
|
||||
FT_Pos min_y = hints->contour_y_minima[contour];
|
||||
FT_Pos max_y = hints->contour_y_maxima[contour];
|
||||
|
||||
} while ( p != first_point );
|
||||
|
||||
if ( min_y < max_y &&
|
||||
max_y <= limit )
|
||||
{
|
||||
AF_Point first_point = hints->contours[contour];
|
||||
AF_Point p = first_point;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
p = p->next;
|
||||
af_remove_segments_containing_point( hints, p );
|
||||
|
||||
} while ( p != first_point );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3125,6 +3158,50 @@
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
af_touch_top_contours( AF_GlyphHints hints,
|
||||
FT_Int limit_contour )
|
||||
{
|
||||
FT_Pos limit = hints->contour_y_minima[limit_contour];
|
||||
|
||||
FT_Int contour;
|
||||
|
||||
|
||||
for ( contour = 0; contour < hints->num_contours; contour++ )
|
||||
{
|
||||
FT_Pos min_y = hints->contour_y_minima[contour];
|
||||
FT_Pos max_y = hints->contour_y_maxima[contour];
|
||||
|
||||
|
||||
if ( min_y < max_y &&
|
||||
min_y >= limit )
|
||||
af_touch_contour( hints, contour );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
af_touch_bottom_contours( AF_GlyphHints hints,
|
||||
FT_Int limit_contour )
|
||||
{
|
||||
FT_Pos limit = hints->contour_y_minima[limit_contour];
|
||||
|
||||
FT_Int contour;
|
||||
|
||||
|
||||
for ( contour = 0; contour < hints->num_contours; contour++ )
|
||||
{
|
||||
FT_Pos min_y = hints->contour_y_minima[contour];
|
||||
FT_Pos max_y = hints->contour_y_maxima[contour];
|
||||
|
||||
|
||||
if ( min_y < max_y &&
|
||||
max_y <= limit )
|
||||
af_touch_contour( hints, contour );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Stretch tilde vertically, if necessary, and return the height */
|
||||
/* difference between the original and the stretched outline. */
|
||||
static FT_Pos
|
||||
|
|
@ -3211,9 +3288,14 @@
|
|||
min_measurement ));
|
||||
|
||||
/* To preserve the stretched shape we suppress any */
|
||||
/* auto-hinting if the tilde height is less than 4 pixels. */
|
||||
/* auto-hinting if the tilde height is less than 4 pixels; */
|
||||
/* we do this for all contours equal or above the vertical */
|
||||
/* minimum of `tilde_contour`. */
|
||||
/* */
|
||||
/* The second part is to remove the affected points from */
|
||||
/* edges, done in `af_latin_hints_apply`. */
|
||||
if ( height < 64 * 4 )
|
||||
af_touch_contour( hints, tilde_contour );
|
||||
af_touch_top_contours( hints, tilde_contour );
|
||||
|
||||
/* XXX This is an important element of the algorithm; */
|
||||
/* we need a description. */
|
||||
|
|
@ -3308,7 +3390,7 @@
|
|||
min_measurement ));
|
||||
|
||||
if ( height < 64 * 4 )
|
||||
af_touch_contour( hints, tilde_contour );
|
||||
af_touch_bottom_contours( hints, tilde_contour );
|
||||
|
||||
target_height = min_measurement + 64;
|
||||
if ( height >= target_height )
|
||||
|
|
@ -4609,9 +4691,18 @@
|
|||
FT_Int top_tilde_contour = 0;
|
||||
FT_Int bottom_tilde_contour = 0;
|
||||
|
||||
FT_Int below_top_tilde_contour = 0;
|
||||
FT_Int above_bottom_tilde_contour = 0;
|
||||
|
||||
FT_Bool is_top_tilde = FALSE;
|
||||
FT_Bool is_bottom_tilde = FALSE;
|
||||
|
||||
FT_Bool is_below_top_tilde = FALSE;
|
||||
FT_Bool is_above_bottom_tilde = FALSE;
|
||||
|
||||
FT_Pos limit;
|
||||
FT_Pos y_offset;
|
||||
|
||||
|
||||
entry = af_reverse_character_map_lookup( metrics->root.reverse_charmap,
|
||||
glyph_index );
|
||||
|
|
@ -4625,12 +4716,42 @@
|
|||
{
|
||||
is_top_tilde = db_entry->flags & AF_ADJUST_TILDE_TOP;
|
||||
is_bottom_tilde = db_entry->flags & AF_ADJUST_TILDE_BOTTOM;
|
||||
|
||||
is_below_top_tilde = db_entry->flags & AF_ADJUST_TILDE_TOP2;
|
||||
is_above_bottom_tilde = db_entry->flags & AF_ADJUST_TILDE_BOTTOM2;
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_top_tilde || is_bottom_tilde )
|
||||
if ( is_top_tilde || is_bottom_tilde ||
|
||||
is_below_top_tilde || is_above_bottom_tilde )
|
||||
af_compute_vertical_extrema( hints );
|
||||
|
||||
/* Process inner tilde glyphs first. */
|
||||
if ( is_below_top_tilde )
|
||||
{
|
||||
below_top_tilde_contour = af_find_second_highest_contour( hints );
|
||||
|
||||
y_offset = af_latin_stretch_top_tilde(
|
||||
hints, below_top_tilde_contour );
|
||||
y_offset += af_latin_align_top_tilde(
|
||||
hints, below_top_tilde_contour );
|
||||
|
||||
limit = hints->contour_y_minima[below_top_tilde_contour];
|
||||
af_move_contours_up( hints, limit, y_offset );
|
||||
}
|
||||
if ( is_above_bottom_tilde )
|
||||
{
|
||||
above_bottom_tilde_contour = af_find_second_lowest_contour( hints );
|
||||
|
||||
y_offset = af_latin_stretch_bottom_tilde(
|
||||
hints, above_bottom_tilde_contour );
|
||||
y_offset -= af_latin_align_bottom_tilde(
|
||||
hints, above_bottom_tilde_contour );
|
||||
|
||||
limit = hints->contour_y_maxima[above_bottom_tilde_contour];
|
||||
af_move_contours_down( hints, limit, y_offset );
|
||||
}
|
||||
|
||||
if ( is_top_tilde )
|
||||
{
|
||||
top_tilde_contour = af_find_highest_contour( hints );
|
||||
|
|
@ -4651,10 +4772,19 @@
|
|||
axis->width_count,
|
||||
axis->widths,
|
||||
AF_DIMENSION_VERT );
|
||||
if ( is_top_tilde )
|
||||
af_remove_top_points_from_edges( hints, top_tilde_contour );
|
||||
if ( is_bottom_tilde )
|
||||
af_remove_bottom_points_from_edges( hints, bottom_tilde_contour );
|
||||
|
||||
/* Second part of making everything of a top tilde and above (or */
|
||||
/* a bottom tilde and below) be ignored by the auto-hinter. */
|
||||
if ( is_top_tilde || is_below_top_tilde )
|
||||
af_remove_top_points_from_edges( hints,
|
||||
is_top_tilde
|
||||
? top_tilde_contour
|
||||
: below_top_tilde_contour );
|
||||
if ( is_bottom_tilde || is_above_bottom_tilde )
|
||||
af_remove_bottom_points_from_edges( hints,
|
||||
is_bottom_tilde
|
||||
? bottom_tilde_contour
|
||||
: above_bottom_tilde_contour );
|
||||
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue