Commits (3)
2021-07-12 David Turner <david@freetype.org>
Remove obsolete AF_Angle type and related sources.
Move the af_sort_xxx() functions from afangles.c to afhints.c in
order to get rid of the obsolete angle-related types, macros and
function definitions.
* src/autofit/*: Remove code.
2021-07-12 David Turner <david@freetype.org>
Remove experimental auto-hinting 'warp' mode.
This feature was always experimental, and probably nevery worked
properly. This patch completely removes it from the source code,
except for a documentation block describing it for historical
purpose.
* devel/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
* include/freetype/config/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
* include/freetype/ftdriver.h: Document 'warping' property as obsolete.
* src/autofit/*: Remove any warp mode related code.
2021-07-12 David Turner <david@freetype.org>
Remove experimental "Latin2" writing system (FT_OPTION_AUTOFIT2)
This code has always been experimental and was never compiled anyway
(FT_OPTION_AUTOFIT2 does not appear in ftoption.h or even any of our
build files).
* include/freetype/internal/fttrace.h: Remove 'FT_TRACE_DEF( aflatin2 )'.
* src/autofit/aflatin2.[hc]: Removed.
* src/autofit/afloader.c: Remove undocumented hook to activate Latin2 system.
* src/autofit/afstyles.h: Remove ltn2_dflt style definition.
* src/autofit/afwrtsys.h: Remove LATIN2 writing system definition.
* src/autofit/autofit.c: Updated.
2021-07-05 Werner Lemberg <wl@gnu.org>
* src/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix argument.
......
......@@ -907,24 +907,6 @@ FT_BEGIN_HEADER
#endif
/**************************************************************************
*
* Compile 'autofit' module with warp hinting. The idea of the warping
* code is to slightly scale and shift a glyph within a single dimension so
* that as much of its segments are aligned (more or less) on the grid. To
* find out the optimal scaling and shifting value, various parameter
* combinations are tried and scored.
*
* You can switch warping on and off with the `warping` property of the
* auto-hinter (see file `ftdriver.h` for more information; by default it
* is switched off).
*
* This experimental option is not active if the rendering mode is
* `FT_RENDER_MODE_LIGHT`.
*/
#define AF_CONFIG_OPTION_USE_WARPER
/**************************************************************************
*
* Use TrueType-like size metrics for 'light' auto-hinting.
......
......@@ -909,24 +909,6 @@ FT_BEGIN_HEADER
#endif
/**************************************************************************
*
* Compile 'autofit' module with warp hinting. The idea of the warping
* code is to slightly scale and shift a glyph within a single dimension so
* that as much of its segments are aligned (more or less) on the grid. To
* find out the optimal scaling and shifting value, various parameter
* combinations are tried and scored.
*
* You can switch warping on and off with the `warping` property of the
* auto-hinter (see file `ftdriver.h` for more information; by default it
* is switched off).
*
* This experimental option is not active if the rendering mode is
* `FT_RENDER_MODE_LIGHT`.
*/
#define AF_CONFIG_OPTION_USE_WARPER
/**************************************************************************
*
* Use TrueType-like size metrics for 'light' auto-hinting.
......
......@@ -1162,11 +1162,11 @@ FT_BEGIN_HEADER
* warping
*
* @description:
* **Experimental only**
* **Obsolete**
*
* If FreeType gets compiled with option `AF_CONFIG_OPTION_USE_WARPER` to
* activate the warp hinting code in the auto-hinter, this property
* switches warping on and off.
* This property was always experimental and probably never worked
* correctly. It was entirely removed from the FreeType 2 sources.
* This entry is only here for historical reference.
*
* Warping only works in 'normal' auto-hinting mode replacing it. The
* idea of the code is to slightly scale and shift a glyph along the
......@@ -1175,36 +1175,6 @@ FT_BEGIN_HEADER
* out a glyph's optimal scaling and shifting value, various parameter
* combinations are tried and scored.
*
* By default, warping is off.
*
* @note:
* This property can be used with @FT_Property_Get also.
*
* This property can be set via the `FREETYPE_PROPERTIES` environment
* variable (using values 1 and 0 for 'on' and 'off', respectively).
*
* The warping code can also change advance widths. Have a look at the
* `lsb_delta` and `rsb_delta` fields in the @FT_GlyphSlotRec structure
* for details on improving inter-glyph distances while rendering.
*
* Since warping is a global property of the auto-hinter it is best to
* change its value before rendering any face. Otherwise, you should
* reload all faces that get auto-hinted in 'normal' hinting mode.
*
* @example:
* This example shows how to switch on warping (omitting the error
* handling).
*
* ```
* FT_Library library;
* FT_Bool warping = 1;
*
*
* FT_Init_FreeType( &library );
*
* FT_Property_Set( library, "autofitter", "warping", &warping );
* ```
*
* @since:
* 2.6
*
......
......@@ -159,7 +159,6 @@ FT_TRACE_DEF( afglobal )
FT_TRACE_DEF( afhints )
FT_TRACE_DEF( afmodule )
FT_TRACE_DEF( aflatin )
FT_TRACE_DEF( aflatin2 )
FT_TRACE_DEF( afshaper )
FT_TRACE_DEF( afwarp )
......
/****************************************************************************
*
* afangles.c
*
* Routines used to compute vector angles with limited accuracy
* and very high speed. It also contains sorting routines (body).
*
* Copyright (C) 2003-2021 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#include "aftypes.h"
/*
* We are not using `af_angle_atan' anymore, but we keep the source
* code below just in case...
*/
#if 0
/*
* The trick here is to realize that we don't need a very accurate angle
* approximation. We are going to use the result of `af_angle_atan' to
* only compare the sign of angle differences, or check whether its
* magnitude is very small.
*
* The approximation
*
* dy * PI / (|dx|+|dy|)
*
* should be enough, and much faster to compute.
*/
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
AF_Angle angle;
FT_Fixed ax = dx;
FT_Fixed ay = dy;
if ( ax < 0 )
ax = -ax;
if ( ay < 0 )
ay = -ay;
ax += ay;
if ( ax == 0 )
angle = 0;
else
{
angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
if ( dx < 0 )
{
if ( angle >= 0 )
angle = AF_ANGLE_PI - angle;
else
angle = -AF_ANGLE_PI - angle;
}
}
return angle;
}
#elif 0
/* the following table has been automatically generated with */
/* the `mather.py' Python script */
#define AF_ATAN_BITS 8
static const FT_Byte af_arctan[1L << AF_ATAN_BITS] =
{
0, 0, 1, 1, 1, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 6, 6, 6, 7, 7, 7,
8, 8, 8, 9, 9, 9, 10, 10,
10, 10, 11, 11, 11, 12, 12, 12,
13, 13, 13, 14, 14, 14, 14, 15,
15, 15, 16, 16, 16, 17, 17, 17,
18, 18, 18, 18, 19, 19, 19, 20,
20, 20, 21, 21, 21, 21, 22, 22,
22, 23, 23, 23, 24, 24, 24, 24,
25, 25, 25, 26, 26, 26, 26, 27,
27, 27, 28, 28, 28, 28, 29, 29,
29, 30, 30, 30, 30, 31, 31, 31,
31, 32, 32, 32, 33, 33, 33, 33,
34, 34, 34, 34, 35, 35, 35, 35,
36, 36, 36, 36, 37, 37, 37, 38,
38, 38, 38, 39, 39, 39, 39, 40,
40, 40, 40, 41, 41, 41, 41, 42,
42, 42, 42, 42, 43, 43, 43, 43,
44, 44, 44, 44, 45, 45, 45, 45,
46, 46, 46, 46, 46, 47, 47, 47,
47, 48, 48, 48, 48, 48, 49, 49,
49, 49, 50, 50, 50, 50, 50, 51,
51, 51, 51, 51, 52, 52, 52, 52,
52, 53, 53, 53, 53, 53, 54, 54,
54, 54, 54, 55, 55, 55, 55, 55,
56, 56, 56, 56, 56, 57, 57, 57,
57, 57, 57, 58, 58, 58, 58, 58,
59, 59, 59, 59, 59, 59, 60, 60,
60, 60, 60, 61, 61, 61, 61, 61,
61, 62, 62, 62, 62, 62, 62, 63,
63, 63, 63, 63, 63, 64, 64, 64
};
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
AF_Angle angle;
/* check trivial cases */
if ( dy == 0 )
{
angle = 0;
if ( dx < 0 )
angle = AF_ANGLE_PI;
return angle;
}
else if ( dx == 0 )
{
angle = AF_ANGLE_PI2;
if ( dy < 0 )
angle = -AF_ANGLE_PI2;
return angle;
}
angle = 0;
if ( dx < 0 )
{
dx = -dx;
dy = -dy;
angle = AF_ANGLE_PI;
}
if ( dy < 0 )
{
FT_Pos tmp;
tmp = dx;
dx = -dy;
dy = tmp;
angle -= AF_ANGLE_PI2;
}
if ( dx == 0 && dy == 0 )
return 0;
if ( dx == dy )
angle += AF_ANGLE_PI4;
else if ( dx > dy )
angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
else
angle += AF_ANGLE_PI2 -
af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
if ( angle > AF_ANGLE_PI )
angle -= AF_ANGLE_2PI;
return angle;
}
#endif /* 0 */
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{
FT_UInt i, j;
FT_Pos swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j] >= table[j - 1] )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
FT_LOCAL_DEF( void )
af_sort_and_quantize_widths( FT_UInt* count,
AF_Width table,
FT_Pos threshold )
{
FT_UInt i, j;
FT_UInt cur_idx;
FT_Pos cur_val;
FT_Pos sum;
AF_WidthRec swap;
if ( *count == 1 )
return;
/* sort */
for ( i = 1; i < *count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j].org >= table[j - 1].org )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
cur_idx = 0;
cur_val = table[cur_idx].org;
/* compute and use mean values for clusters not larger than */
/* `threshold'; this is very primitive and might not yield */
/* the best result, but normally, using reference character */
/* `o', `*count' is 2, so the code below is fully sufficient */
for ( i = 1; i < *count; i++ )
{
if ( table[i].org - cur_val > threshold ||
i == *count - 1 )
{
sum = 0;
/* fix loop for end of array */
if ( table[i].org - cur_val <= threshold &&
i == *count - 1 )
i++;
for ( j = cur_idx; j < i; j++ )
{
sum += table[j].org;
table[j].org = 0;
}
table[cur_idx].org = sum / (FT_Pos)j;
if ( i < *count - 1 )
{
cur_idx = i + 1;
cur_val = table[cur_idx].org;
}
}
}
cur_idx = 1;
/* compress array to remove zero values */
for ( i = 1; i < *count; i++ )
{
if ( table[i].org )
table[cur_idx++] = table[i];
}
*count = cur_idx;
}
/* END */
/*
* afangles.h
*
* This is a dummy file, used to please the build system. It is never
* included by the auto-fitter sources.
*
*/
......@@ -37,11 +37,6 @@
#include "aferrors.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
......@@ -1400,11 +1395,6 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
#endif
scaler_flags = hints->scaler_flags;
other_flags = 0;
......@@ -1433,12 +1423,6 @@
scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
#ifdef AF_CONFIG_OPTION_USE_WARPER
/* get (global) warper flag */
if ( !metrics->root.globals->module->warping )
scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
#endif
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
......@@ -2321,25 +2305,6 @@
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
FT_Pos delta;
af_warper_compute( &warper, hints, (AF_Dimension)dim,
&scale, &delta );
af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
scale, delta );
continue;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
af_cjk_hint_edges( hints, (AF_Dimension)dim );
af_cjk_align_edge_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
......
......@@ -32,6 +32,104 @@
#define FT_COMPONENT afhints
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{
FT_UInt i, j;
FT_Pos swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j] >= table[j - 1] )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
FT_LOCAL_DEF( void )
af_sort_and_quantize_widths( FT_UInt* count,
AF_Width table,
FT_Pos threshold )
{
FT_UInt i, j;
FT_UInt cur_idx;
FT_Pos cur_val;
FT_Pos sum;
AF_WidthRec swap;
if ( *count == 1 )
return;
/* sort */
for ( i = 1; i < *count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j].org >= table[j - 1].org )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
cur_idx = 0;
cur_val = table[cur_idx].org;
/* compute and use mean values for clusters not larger than */
/* `threshold'; this is very primitive and might not yield */
/* the best result, but normally, using reference character */
/* `o', `*count' is 2, so the code below is fully sufficient */
for ( i = 1; i < *count; i++ )
{
if ( table[i].org - cur_val > threshold ||
i == *count - 1 )
{
sum = 0;
/* fix loop for end of array */
if ( table[i].org - cur_val <= threshold &&
i == *count - 1 )
i++;
for ( j = cur_idx; j < i; j++ )
{
sum += table[j].org;
table[j].org = 0;
}
table[cur_idx].org = sum / (FT_Pos)j;
if ( i < *count - 1 )
{
cur_idx = i + 1;
cur_val = table[cur_idx].org;
}
}
}
cur_idx = 1;
/* compress array to remove zero values */
for ( i = 1; i < *count; i++ )
{
if ( table[i].org )
table[cur_idx++] = table[i];
}
*count = cur_idx;
}
/* Get new segment for given axis. */
FT_LOCAL_DEF( FT_Error )
......@@ -1688,33 +1786,4 @@
}
#ifdef AF_CONFIG_OPTION_USE_WARPER
/* Apply (small) warp scale and warp delta for given dimension. */
FT_LOCAL_DEF( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed scale,
FT_Pos delta )
{
AF_Point points = hints->points;
AF_Point points_limit = points + hints->num_points;
AF_Point point;
if ( dim == AF_DIMENSION_HORZ )
{
for ( point = points; point < points_limit; point++ )
point->x = FT_MulFix( point->fx, scale ) + delta;
}
else
{
for ( point = points; point < points_limit; point++ )
point->y = FT_MulFix( point->fy, scale ) + delta;
}
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
/* END */
......@@ -408,10 +408,6 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_ADVANCE( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
#define AF_HINTS_DO_WARP( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
......@@ -459,14 +455,6 @@ FT_BEGIN_HEADER
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_LOCAL( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed scale,
FT_Pos delta );
#endif
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
......
......@@ -27,11 +27,6 @@
#include "aferrors.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
static FT_Error
af_indic_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
......
......@@ -24,11 +24,6 @@
#include "aferrors.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
......@@ -2636,11 +2631,6 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
#endif
scaler_flags = hints->scaler_flags;
other_flags = 0;
......@@ -2678,12 +2668,6 @@
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
#ifdef AF_CONFIG_OPTION_USE_WARPER
/* get (global) warper flag */
if ( !metrics->root.globals->module->warping )
scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
#endif
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
......@@ -3600,24 +3584,6 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
AF_HINTS_DO_WARP( hints ) )
{
AF_WarperRec warper;
FT_Fixed scale;
FT_Pos delta;
af_warper_compute( &warper, hints, (AF_Dimension)dim,
&scale, &delta );
af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
scale, delta );
continue;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
......
This diff is collapsed.
/* ATTENTION: This file doesn't compile. It is only here as a reference */
/* of an alternative latin hinting algorithm that was always */
/* marked as experimental. */
/****************************************************************************
*
* aflatin2.h
*
* Auto-fitter hinting routines for latin writing system
* (specification).
*
* Copyright (C) 2003-2021 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
#ifndef AFLATIN2_H_
#define AFLATIN2_H_
#include "afhints.h"
FT_BEGIN_HEADER
/* the `latin' writing system */
AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
/* */
FT_END_HEADER
#endif /* AFLATIN_H_ */
/* END */
......@@ -297,12 +297,6 @@
if ( error )
goto Exit;
#ifdef FT_OPTION_AUTOFIT2
/* XXX: undocumented hook to activate the latin2 writing system. */
if ( load_flags & ( 1UL << 20 ) )
style_options = AF_STYLE_LTN2_DFLT;
#endif
/*
* Glyphs (really code points) are assigned to scripts. Script
* analysis is done lazily: For each glyph that passes through here,
......
......@@ -190,35 +190,6 @@
return error;
}
#ifdef AF_CONFIG_OPTION_USE_WARPER
else if ( !ft_strcmp( property_name, "warping" ) )
{
#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
if ( value_is_string )
{
const char* s = (const char*)value;
long w = ft_strtol( s, NULL, 10 );
if ( w == 0 )
module->warping = 0;
else if ( w == 1 )
module->warping = 1;
else
return FT_THROW( Invalid_Argument );
}
else
#endif
{
FT_Bool* warping = (FT_Bool*)value;
module->warping = *warping;
}
return error;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params;
......@@ -322,9 +293,6 @@
AF_Module module = (AF_Module)ft_module;
FT_UInt fallback_style = module->fallback_style;
FT_UInt default_script = module->default_script;
#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_Bool warping = module->warping;
#endif
if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
......@@ -371,17 +339,6 @@
return error;
}
#ifdef AF_CONFIG_OPTION_USE_WARPER
else if ( !ft_strcmp( property_name, "warping" ) )
{
FT_Bool* val = (FT_Bool*)value;
*val = warping;
return error;
}
#endif /* AF_CONFIG_OPTION_USE_WARPER */
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params = module->darken_params;
......@@ -447,9 +404,6 @@
module->fallback_style = AF_STYLE_FALLBACK;
module->default_script = AF_SCRIPT_DEFAULT;
#ifdef AF_CONFIG_OPTION_USE_WARPER
module->warping = 0;
#endif
module->no_stem_darkening = TRUE;
module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
......
......@@ -37,9 +37,6 @@ FT_BEGIN_HEADER
FT_UInt fallback_style;
FT_UInt default_script;
#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_Bool warping;
#endif
FT_Bool no_stem_darkening;
FT_Int darken_params[8];
......
......@@ -299,15 +299,6 @@
AF_BLUE_STRINGSET_LATP,
AF_COVERAGE_DEFAULT )
#ifdef FT_OPTION_AUTOFIT2
STYLE( ltn2_dflt, LTN2_DFLT,
"Latin 2 default style",
AF_WRITING_SYSTEM_LATIN2,
AF_SCRIPT_LATN,
AF_BLUE_STRINGSET_LATN,
AF_COVERAGE_DEFAULT )
#endif
STYLE( lisu_dflt, LISU_DFLT,
"Lisu default style",
AF_WRITING_SYSTEM_LATIN,
......
......@@ -92,63 +92,6 @@ extern void* _af_debug_hints;
FT_Pos threshold );
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** A N G L E T Y P E S *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*
* The auto-fitter doesn't need a very high angular accuracy;
* this allows us to speed up some computations considerably with a
* light Cordic algorithm (see afangles.c).
*/
typedef FT_Int AF_Angle;
#define AF_ANGLE_PI 256
#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 )
#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 )
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
#if 0
/*
* compute the angle of a given 2-D vector
*/
FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx,
FT_Pos dy );
/*
* compute `angle2 - angle1'; the result is always within
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
*/
FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 );
#endif /* 0 */
#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
FT_BEGIN_STMNT \
AF_Angle _delta = (angle2) - (angle1); \
\
\
while ( _delta <= -AF_ANGLE_PI ) \
_delta += AF_ANGLE_2PI; \
\
while ( _delta > AF_ANGLE_PI ) \
_delta -= AF_ANGLE_2PI; \
\
result = _delta; \
FT_END_STMNT
/*
* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
......@@ -172,7 +115,6 @@ extern void* _af_debug_hints;
#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */
#define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */
#define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */
#define AF_SCALER_FLAG_NO_WARPER 8U /* disable warper */
typedef struct AF_ScalerRec_
......
/****************************************************************************
*
* afwarp.c
*
* Auto-fitter warping algorithm (body).
*
* Copyright (C) 2006-2021 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
* modified, and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*/
/*
* The idea of the warping code is to slightly scale and shift a glyph
* within a single dimension so that as much of its segments are aligned
* (more or less) on the grid. To find out the optimal scaling and
* shifting value, various parameter combinations are tried and scored.
*/
#include "afwarp.h"
#ifdef AF_CONFIG_OPTION_USE_WARPER
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT afwarp
/* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */
/* values around a half pixel (which means exactly between two grid */
/* lines) gets the worst weight. */
#if 1
static const AF_WarpScore
af_warper_weights[64] =
{
35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
-30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32,
};
#else
static const AF_WarpScore
af_warper_weights[64] =
{
30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
-20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20,
};
#endif
/* Score segments for a given `scale' and `delta' in the range */
/* `xx1' to `xx2', and store the best result in `warper'. If */
/* the new best score is equal to the old one, prefer the */
/* value with a smaller distortion (around `base_distort'). */
static void
af_warper_compute_line_best( AF_Warper warper,
FT_Fixed scale,
FT_Pos delta,
FT_Pos xx1,
FT_Pos xx2,
AF_WarpScore base_distort,
AF_Segment segments,
FT_Int num_segments )
{
FT_Int idx_min, idx_max, idx0;
FT_Int nn;
AF_WarpScore scores[65];
for ( nn = 0; nn < 65; nn++ )
scores[nn] = 0;
idx0 = xx1 - warper->t1;
/* compute minimum and maximum indices */
{
FT_Pos xx1min = warper->x1min;
FT_Pos xx1max = warper->x1max;
FT_Pos w = xx2 - xx1;
if ( xx1min + w < warper->x2min )
xx1min = warper->x2min - w;
if ( xx1max + w > warper->x2max )
xx1max = warper->x2max - w;
idx_min = xx1min - warper->t1;
idx_max = xx1max - warper->t1;
if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
{
FT_TRACE5(( "invalid indices:\n" ));
FT_TRACE5(( " min=%d max=%d, xx1=%ld xx2=%ld,\n",
idx_min, idx_max, xx1, xx2 ));
FT_TRACE5(( " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
warper->x1min, warper->x1max,
warper->x2min, warper->x2max ));
return;
}
}
for ( nn = 0; nn < num_segments; nn++ )
{
FT_Pos len = segments[nn].max_coord - segments[nn].min_coord;
FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta;
FT_Pos y = y0 + ( idx_min - idx0 );
FT_Int idx;
/* score the length of the segments for the given range */
for ( idx = idx_min; idx <= idx_max; idx++, y++ )
scores[idx] += af_warper_weights[y & 63] * len;
}
/* find best score */
{
FT_Int idx;
for ( idx = idx_min; idx <= idx_max; idx++ )
{
AF_WarpScore score = scores[idx];
AF_WarpScore distort = base_distort + ( idx - idx0 );
if ( score > warper->best_score ||
( score == warper->best_score &&
distort < warper->best_distort ) )
{
warper->best_score = score;
warper->best_distort = distort;
warper->best_scale = scale;
warper->best_delta = delta + ( idx - idx0 );
}
}
}
}
/* Compute optimal scaling and delta values for a given glyph and */
/* dimension. */
FT_LOCAL_DEF( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
AF_Dimension dim,
FT_Fixed *a_scale,
FT_Pos *a_delta )
{
AF_AxisHints axis;
AF_Point points;
FT_Fixed org_scale;
FT_Pos org_delta;
FT_Int nn, num_points, num_segments;
FT_Int X1, X2;
FT_Int w;
AF_WarpScore base_distort;
AF_Segment segments;
/* get original scaling transformation */
if ( dim == AF_DIMENSION_VERT )
{
org_scale = hints->y_scale;
org_delta = hints->y_delta;
}
else
{
org_scale = hints->x_scale;
org_delta = hints->x_delta;
}
warper->best_scale = org_scale;
warper->best_delta = org_delta;
warper->best_score = FT_INT_MIN;
warper->best_distort = 0;
axis = &hints->axis[dim];
segments = axis->segments;
num_segments = axis->num_segments;
points = hints->points;
num_points = hints->num_points;
*a_scale = org_scale;
*a_delta = org_delta;
/* get X1 and X2, minimum and maximum in original coordinates */
if ( num_segments < 1 )
return;
#if 1
X1 = X2 = points[0].fx;
for ( nn = 1; nn < num_points; nn++ )
{
FT_Int X = points[nn].fx;
if ( X < X1 )
X1 = X;
if ( X > X2 )
X2 = X;
}
#else
X1 = X2 = segments[0].pos;
for ( nn = 1; nn < num_segments; nn++ )
{
FT_Int X = segments[nn].pos;
if ( X < X1 )
X1 = X;
if ( X > X2 )
X2 = X;
}
#endif
if ( X1 >= X2 )
return;
warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
warper->t1 = AF_WARPER_FLOOR( warper->x1 );
warper->t2 = AF_WARPER_CEIL( warper->x2 );
/* examine a half pixel wide range around the maximum coordinates */
warper->x1min = warper->x1 & ~31;
warper->x1max = warper->x1min + 32;
warper->x2min = warper->x2 & ~31;
warper->x2max = warper->x2min + 32;
if ( warper->x1max > warper->x2 )
warper->x1max = warper->x2;
if ( warper->x2min < warper->x1 )
warper->x2min = warper->x1;
warper->w0 = warper->x2 - warper->x1;
if ( warper->w0 <= 64 )
{
warper->x1max = warper->x1;
warper->x2min = warper->x2;
}
/* examine (at most) a pixel wide range around the natural width */
warper->wmin = warper->x2min - warper->x1max;
warper->wmax = warper->x2max - warper->x1min;
#if 1
/* some heuristics to reduce the number of widths to be examined */
{
int margin = 16;
if ( warper->w0 <= 128 )
{
margin = 8;
if ( warper->w0 <= 96 )
margin = 4;
}
if ( warper->wmin < warper->w0 - margin )
warper->wmin = warper->w0 - margin;
if ( warper->wmax > warper->w0 + margin )
warper->wmax = warper->w0 + margin;
}
if ( warper->wmin < warper->w0 * 3 / 4 )
warper->wmin = warper->w0 * 3 / 4;
if ( warper->wmax > warper->w0 * 5 / 4 )
warper->wmax = warper->w0 * 5 / 4;
#else
/* no scaling, just translation */
warper->wmin = warper->wmax = warper->w0;
#endif
for ( w = warper->wmin; w <= warper->wmax; w++ )
{
FT_Fixed new_scale;
FT_Pos new_delta;
FT_Pos xx1, xx2;
/* compute min and max positions for given width, */
/* assuring that they stay within the coordinate ranges */
xx1 = warper->x1;
xx2 = warper->x2;
if ( w >= warper->w0 )
{
xx1 -= w - warper->w0;
if ( xx1 < warper->x1min )
{
xx2 += warper->x1min - xx1;
xx1 = warper->x1min;
}
}
else
{
xx1 -= w - warper->w0;
if ( xx1 > warper->x1max )
{
xx2 -= xx1 - warper->x1max;
xx1 = warper->x1max;
}
}
if ( xx1 < warper->x1 )
base_distort = warper->x1 - xx1;
else
base_distort = xx1 - warper->x1;
if ( xx2 < warper->x2 )
base_distort += warper->x2 - xx2;
else
base_distort += xx2 - warper->x2;
/* give base distortion a greater weight while scoring */
base_distort *= 10;
new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
new_delta = xx1 - FT_MulFix( X1, new_scale );
af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
base_distort,
segments, num_segments );
}
{
FT_Fixed best_scale = warper->best_scale;
FT_Pos best_delta = warper->best_delta;
hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
+ best_delta;
hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
+ best_delta;
*a_scale = best_scale;
*a_delta = best_delta;
}
}
#else /* !AF_CONFIG_OPTION_USE_WARPER */
/* ANSI C doesn't like empty source files */
typedef int _af_warp_dummy;
#endif /* !AF_CONFIG_OPTION_USE_WARPER */
/* END */