mirror of https://github.com/freetype/freetype
* src/autofit/*: important fixes to the auto-fitter. The output
now seems to be 100% equivalent to the auto-hinter, while being about 2% faster (which proves that script-specific algorithm selection isn't a performance problem). to test it, change "autohint" to "autofit" in <freetype/config/ftmodule.h> and recompile. a few more testing is needed before making this the official auto-hinting module
This commit is contained in:
parent
56a4d87cb2
commit
e664efaddd
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2004-06-04 David Turner <david@freetype.org>
|
||||
|
||||
* src/autofit/*: important fixes to the auto-fitter. The output
|
||||
now seems to be 100% equivalent to the auto-hinter, while being
|
||||
about 2% faster (which proves that script-specific algorithm
|
||||
selection isn't a performance problem).
|
||||
|
||||
to test it, change "autohint" to "autofit" in
|
||||
<freetype/config/ftmodule.h> and recompile.
|
||||
|
||||
a few more testing is needed before making this the official
|
||||
auto-hinting module
|
||||
|
||||
2004-06-02 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/truetype/ttgload.c (compute_glyph_metrics): Fix compiler
|
||||
|
@ -24,7 +37,7 @@
|
|||
|
||||
2004-05-17 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
|
||||
* src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
|
||||
Reported by Mikey Anbary <manbary@vizrt.com>.
|
||||
|
||||
2004-05-15 Werner Lemberg <wl@gnu.org>
|
||||
|
@ -173,7 +186,7 @@
|
|||
consistency.
|
||||
(pcf_cmap_init, pcf_cmap_done, pcf_cmap_char_index,
|
||||
pcf_cmap_char_next): Don't use PCF_XXX but FT_XXX arguments which
|
||||
are typecast to the proper PCF_XXX types within the function.
|
||||
are typecast to the proper PCF_XXX types within the function.
|
||||
Update code accordingly.
|
||||
(pcf_cmap_class): Remove casts.
|
||||
(PCF_Face_Done, PCF_Face_Init, PCF_Set_Pixel_Size): Don't use
|
||||
|
|
|
@ -1,8 +1,57 @@
|
|||
#include "aftypes.h"
|
||||
|
||||
/*
|
||||
* a python script used to generate the following table
|
||||
*
|
||||
|
||||
import sys, math
|
||||
|
||||
units = 256
|
||||
scale = units/math.pi
|
||||
comma = ""
|
||||
|
||||
print ""
|
||||
print "table of arctan( 1/2^n ) for PI = " + repr(units/65536.0) + " units"
|
||||
|
||||
r = [-1] + range(32)
|
||||
|
||||
for n in r:
|
||||
|
||||
if n >= 0:
|
||||
x = 1.0/(2.0**n) # tangent value
|
||||
else:
|
||||
x = 2.0**(-n)
|
||||
|
||||
angle = math.atan(x) # arctangent
|
||||
angle2 = angle*scale # arctangent in FT_Angle units
|
||||
|
||||
# determine which integer value for angle gives the best tangent
|
||||
lo = int(angle2)
|
||||
hi = lo + 1
|
||||
tlo = math.tan(lo/scale)
|
||||
thi = math.tan(hi/scale)
|
||||
|
||||
errlo = abs( tlo - x )
|
||||
errhi = abs( thi - x )
|
||||
|
||||
angle2 = hi
|
||||
if errlo < errhi:
|
||||
angle2 = lo
|
||||
|
||||
if angle2 <= 0:
|
||||
break
|
||||
|
||||
sys.stdout.write( comma + repr( int(angle2) ) )
|
||||
comma = ", "
|
||||
|
||||
*
|
||||
* end of python script
|
||||
*/
|
||||
|
||||
|
||||
/* this table was generated for AF_ANGLE_PI = 256 */
|
||||
#define AF_ANGLE_MAX_ITERS 8
|
||||
#define AF_TRIG_MAX_ITERS 9
|
||||
#define AF_TRIG_MAX_ITERS 8
|
||||
|
||||
static const FT_Fixed
|
||||
af_angle_arctan_table[9] =
|
||||
|
@ -69,7 +118,7 @@
|
|||
{
|
||||
x = -x;
|
||||
y = -y;
|
||||
theta = 2 * AF_ANGLE_PI2;
|
||||
theta = AF_ANGLE_PI;
|
||||
}
|
||||
|
||||
if ( y > 0 )
|
||||
|
@ -115,11 +164,13 @@
|
|||
}
|
||||
} while ( ++i < AF_TRIG_MAX_ITERS );
|
||||
|
||||
#if 0
|
||||
/* round theta */
|
||||
if ( theta >= 0 )
|
||||
theta = FT_PAD_ROUND( theta, 4 );
|
||||
theta = FT_PAD_ROUND( theta, 2 );
|
||||
else
|
||||
theta = - FT_PAD_ROUND( theta, 4 );
|
||||
theta = - FT_PAD_ROUND( -theta, 2 );
|
||||
#endif
|
||||
|
||||
vec->x = x;
|
||||
vec->y = theta;
|
||||
|
@ -212,3 +263,40 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main( void )
|
||||
{
|
||||
int angle;
|
||||
int dist;
|
||||
|
||||
for ( dist = 100; dist < 1000; dist++ )
|
||||
{
|
||||
for ( angle = AF_ANGLE_PI; angle < AF_ANGLE_2PI*4; angle++ )
|
||||
{
|
||||
double a = (angle*3.1415926535)/(1.0*AF_ANGLE_PI);
|
||||
int dx, dy, angle1, angle2, delta;
|
||||
|
||||
dx = dist * cos(a);
|
||||
dy = dist * sin(a);
|
||||
|
||||
angle1 = ((atan2(dy,dx)*AF_ANGLE_PI)/3.1415926535);
|
||||
angle2 = af_angle_atan( dx, dy );
|
||||
delta = (angle2 - angle1) % AF_ANGLE_2PI;
|
||||
if ( delta < 0 )
|
||||
delta = -delta;
|
||||
|
||||
if ( delta >= 2 )
|
||||
{
|
||||
printf( "dist:%4d angle:%4d => (%4d,%4d) angle1:%4d angle2:%4d\n",
|
||||
dist, angle, dx, dy, angle1, angle2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,20 +3,21 @@
|
|||
|
||||
static FT_Error
|
||||
af_dummy_hints_init( AF_GlyphHints hints,
|
||||
FT_Outline* outline,
|
||||
AF_ScriptMetrics metrics )
|
||||
{
|
||||
return af_glyph_hints_reset( hints,
|
||||
&metrics->scaler,
|
||||
metrics,
|
||||
outline );
|
||||
af_glyph_hints_rescale( hints,
|
||||
metrics );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FT_Error
|
||||
af_dummy_hints_apply( AF_GlyphHints hints,
|
||||
FT_Outline* outline )
|
||||
{
|
||||
af_glyph_hints_save( hints, outline );
|
||||
FT_UNUSED( hints );
|
||||
FT_UNUSED( outline );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
NULL /* do not remove */
|
||||
};
|
||||
|
||||
#define AF_SCRIPT_LIST_DEFAULT 0 /* index of default script in 'af_script_classes' */
|
||||
#define AF_SCRIPT_LIST_DEFAULT 1 /* index of default script in 'af_script_classes' */
|
||||
#define AF_SCRIPT_LIST_NONE 255 /* indicates an uncovered glyph */
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
switch (dir)
|
||||
{
|
||||
case AF_DIR_UP: result = "up"; break;
|
||||
case AF_DIR_DOWN: result = "down"; break;
|
||||
case AF_DIR_LEFT: result = "left"; break;
|
||||
case AF_DIR_UP: result = "up"; break;
|
||||
case AF_DIR_DOWN: result = "down"; break;
|
||||
case AF_DIR_LEFT: result = "left"; break;
|
||||
case AF_DIR_RIGHT: result = "right"; break;
|
||||
default: result = "none";
|
||||
default: result = "none";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
|||
|
||||
for ( edge = edges; edge < limit; edge++ )
|
||||
{
|
||||
printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
|
||||
printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
|
||||
edge - edges,
|
||||
(int)edge->fpos,
|
||||
af_dir_str( edge->dir ),
|
||||
|
@ -314,26 +314,29 @@
|
|||
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
af_glyph_hints_rescale( AF_GlyphHints hints,
|
||||
AF_ScriptMetrics metrics )
|
||||
{
|
||||
hints->metrics = metrics;
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
af_glyph_hints_reset( AF_GlyphHints hints,
|
||||
AF_Scaler scaler,
|
||||
AF_ScriptMetrics metrics,
|
||||
FT_Outline* outline )
|
||||
af_glyph_hints_reload( AF_GlyphHints hints,
|
||||
FT_Outline* outline )
|
||||
{
|
||||
FT_Error error = FT_Err_Ok;
|
||||
AF_Point points;
|
||||
FT_UInt old_max, new_max;
|
||||
FT_Fixed x_scale = scaler->x_scale;
|
||||
FT_Fixed y_scale = scaler->y_scale;
|
||||
FT_Pos x_delta = scaler->x_delta;
|
||||
FT_Pos y_delta = scaler->y_delta;
|
||||
AF_Scaler scaler = &hints->metrics->scaler;
|
||||
FT_Fixed x_scale = hints->x_scale;
|
||||
FT_Fixed y_scale = hints->y_scale;
|
||||
FT_Pos x_delta = hints->x_delta;
|
||||
FT_Pos y_delta = hints->y_delta;
|
||||
FT_Memory memory = hints->memory;
|
||||
|
||||
hints->metrics = metrics;
|
||||
|
||||
hints->scaler_flags = scaler->flags;
|
||||
hints->other_flags = 0;
|
||||
|
||||
hints->scaler_flags = scaler->flags;
|
||||
hints->num_points = 0;
|
||||
hints->num_contours = 0;
|
||||
|
||||
|
|
|
@ -214,11 +214,13 @@ FT_BEGIN_HEADER
|
|||
/* recomputes all AF_Point in a AF_GlyphHints from the definitions
|
||||
* in a source outline
|
||||
*/
|
||||
FT_LOCAL( void )
|
||||
af_glyph_hints_rescale( AF_GlyphHints hints,
|
||||
AF_ScriptMetrics metrics );
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
af_glyph_hints_reset( AF_GlyphHints hints,
|
||||
AF_Scaler scaler,
|
||||
AF_ScriptMetrics metrics,
|
||||
FT_Outline* outline );
|
||||
af_glyph_hints_reload( AF_GlyphHints hints,
|
||||
FT_Outline* outline );
|
||||
|
||||
FT_LOCAL( void )
|
||||
af_glyph_hints_save( AF_GlyphHints hints,
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
FT_Error error;
|
||||
FT_UInt glyph_index;
|
||||
AF_Dimension dim;
|
||||
AF_ScalerRec scaler[1];
|
||||
|
||||
AF_ScriptMetricsRec dummy[1];
|
||||
AF_Scaler scaler = &dummy->scaler;
|
||||
|
||||
glyph_index = FT_Get_Char_Index( face, 'o' );
|
||||
if ( glyph_index == 0 )
|
||||
|
@ -36,15 +36,17 @@
|
|||
if ( error || face->glyph->outline.n_points <= 0 )
|
||||
goto Exit;
|
||||
|
||||
FT_ZERO( dummy );
|
||||
|
||||
scaler->x_scale = scaler->y_scale = 0x10000L;
|
||||
scaler->x_delta = scaler->y_delta = 0;
|
||||
scaler->face = face;
|
||||
scaler->render_mode = 0;
|
||||
scaler->flags = 0;
|
||||
|
||||
error = af_glyph_hints_reset( hints, scaler,
|
||||
(AF_ScriptMetrics) metrics,
|
||||
&face->glyph->outline );
|
||||
af_glyph_hints_rescale( hints, dummy );
|
||||
|
||||
error = af_glyph_hints_reload( hints, &face->glyph->outline );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
|
@ -324,6 +326,13 @@
|
|||
if ( AF_LATIN_IS_TOP_BLUE(bb) )
|
||||
blue->flags |= AF_LATIN_BLUE_TOP;
|
||||
|
||||
/* the following flags is used later to adjust the y and x scales
|
||||
* in order to optimize the pixel grid alignment of the top of small
|
||||
* letters.
|
||||
*/
|
||||
if ( bb == AF_LATIN_BLUE_SMALL_TOP )
|
||||
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
|
||||
|
||||
AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
|
||||
}
|
||||
|
||||
|
@ -382,8 +391,44 @@
|
|||
axis->org_scale = scale;
|
||||
axis->org_delta = delta;
|
||||
|
||||
/* XXX: TODO: Correct Y and X scale according to Chester rules
|
||||
/* correct X and Y scale to optimize the alignment of the top of small
|
||||
* letters to the pixel grid
|
||||
*/
|
||||
{
|
||||
AF_LatinAxis axis = &metrics->axis[ AF_DIMENSION_VERT ];
|
||||
AF_LatinBlue blue = NULL;
|
||||
FT_UInt nn;
|
||||
|
||||
for ( nn = 0; nn < axis->blue_count; nn++ )
|
||||
{
|
||||
if ( axis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
|
||||
{
|
||||
blue = &axis->blues[nn];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( blue )
|
||||
{
|
||||
FT_Pos scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
|
||||
FT_Pos fitted = FT_PIX_ROUND( scaled );
|
||||
|
||||
|
||||
if ( scaled != fitted )
|
||||
{
|
||||
if ( dim == AF_DIMENSION_HORZ )
|
||||
{
|
||||
if ( fitted < scaled )
|
||||
scale -= scale/50; /* x_scale = x_scale*0.98 */
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = FT_MulDiv( scale, fitted, scaled );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
axis->scale = scale;
|
||||
axis->delta = delta;
|
||||
|
||||
|
@ -417,17 +462,41 @@
|
|||
AF_LatinBlue blue = & axis->blues[nn];
|
||||
FT_Pos dist;
|
||||
|
||||
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
|
||||
blue->ref.fit = blue->ref.cur;
|
||||
|
||||
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
|
||||
blue->ref.fit = blue->ref.cur;
|
||||
blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
|
||||
blue->shoot.fit = blue->shoot.cur;
|
||||
blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
|
||||
|
||||
/* a blue zone is only active when it is less than 3/4 pixels tall
|
||||
*/
|
||||
dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
|
||||
if ( dist >= 48 || dist <= -48 )
|
||||
blue->flags |= ~AF_LATIN_BLUE_ACTIVE;
|
||||
if ( dist <= 48 && dist >= -48 )
|
||||
{
|
||||
FT_Pos delta, delta2;
|
||||
|
||||
delta = blue->shoot.org - blue->ref.org;
|
||||
delta2 = delta;
|
||||
if ( delta < 0 )
|
||||
delta2 = -delta2;
|
||||
|
||||
delta2 = FT_MulFix( delta2, scale );
|
||||
|
||||
if ( delta2 < 32 )
|
||||
delta2 = 0;
|
||||
else if ( delta2 < 64 )
|
||||
delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
|
||||
else
|
||||
delta2 = FT_PIX_ROUND( delta2 );
|
||||
|
||||
if ( delta < 0 )
|
||||
delta2 = -delta2;
|
||||
|
||||
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
|
||||
blue->shoot.fit = blue->ref.fit + delta2;
|
||||
|
||||
blue->flags |= AF_LATIN_BLUE_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -437,6 +506,9 @@
|
|||
af_latin_metrics_scale( AF_LatinMetrics metrics,
|
||||
AF_Scaler scaler )
|
||||
{
|
||||
if ( AF_SCALER_EQUAL_SCALES( scaler, &metrics->root.scaler ) )
|
||||
return;
|
||||
|
||||
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
|
||||
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
|
||||
}
|
||||
|
@ -791,6 +863,7 @@
|
|||
AF_Dimension dim )
|
||||
{
|
||||
AF_AxisHints axis = &hints->axis[dim];
|
||||
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
|
||||
AF_Edge edges = axis->edges;
|
||||
AF_Edge edge, edge_limit;
|
||||
|
||||
|
@ -825,7 +898,7 @@
|
|||
/* */
|
||||
/*********************************************************************/
|
||||
|
||||
edge_distance_threshold = FT_MulFix( hints->edge_distance_threshold,
|
||||
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
|
||||
scale );
|
||||
if ( edge_distance_threshold > 64 / 4 )
|
||||
edge_distance_threshold = 64 / 4;
|
||||
|
@ -1138,18 +1211,19 @@
|
|||
|
||||
static FT_Error
|
||||
af_latin_hints_init( AF_GlyphHints hints,
|
||||
FT_Outline* outline,
|
||||
AF_LatinMetrics metrics )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Render_Mode mode;
|
||||
|
||||
error = af_glyph_hints_reset( hints, &metrics->root.scaler,
|
||||
(AF_ScriptMetrics) metrics,
|
||||
outline );
|
||||
if (error)
|
||||
goto Exit;
|
||||
af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
|
||||
|
||||
/* correct x_scale and y_scale when needed, since they may have
|
||||
* been modified af_latin_scale_dim above
|
||||
*/
|
||||
hints->x_scale = metrics->axis[ AF_DIMENSION_HORZ ].scale;
|
||||
hints->x_delta = metrics->axis[ AF_DIMENSION_HORZ ].delta;
|
||||
hints->y_scale = metrics->axis[ AF_DIMENSION_VERT ].scale;
|
||||
hints->y_delta = metrics->axis[ AF_DIMENSION_VERT ].delta;
|
||||
|
||||
/* compute flags depending on render mode, etc...
|
||||
*/
|
||||
|
@ -1176,21 +1250,11 @@
|
|||
if ( mode == FT_RENDER_MODE_MONO )
|
||||
hints->other_flags |= AF_LATIN_HINTS_MONO;
|
||||
|
||||
/* analyze glyph outline
|
||||
*/
|
||||
if ( AF_HINTS_DO_HORIZONTAL(hints) )
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
|
||||
|
||||
if ( AF_HINTS_DO_VERTICAL(hints) )
|
||||
{
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
|
||||
af_latin_hints_compute_blue_edges( hints, metrics );
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/***************************************************************************/
|
||||
/***** *****/
|
||||
|
@ -1738,10 +1802,26 @@
|
|||
FT_Outline* outline,
|
||||
AF_LatinMetrics metrics )
|
||||
{
|
||||
FT_Error error;
|
||||
AF_Dimension dim;
|
||||
|
||||
FT_UNUSED( metrics );
|
||||
error = af_glyph_hints_reload( hints, outline );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
/* analyze glyph outline
|
||||
*/
|
||||
if ( AF_HINTS_DO_HORIZONTAL(hints) )
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
|
||||
|
||||
if ( AF_HINTS_DO_VERTICAL(hints) )
|
||||
{
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
|
||||
af_latin_hints_compute_blue_edges( hints, metrics );
|
||||
}
|
||||
|
||||
/* grid-fit the outline
|
||||
*/
|
||||
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
|
||||
{
|
||||
if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) ||
|
||||
|
@ -1755,7 +1835,8 @@
|
|||
}
|
||||
af_glyph_hints_save( hints, outline );
|
||||
|
||||
return 0;
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1768,11 +1849,12 @@
|
|||
|
||||
static const AF_Script_UniRangeRec af_latin_uniranges[] =
|
||||
{
|
||||
{ 32, 127 }, /* XXX: TODO: Add new Unicode ranges here !! */
|
||||
{ 32, 127 }, /* XXX: TODO: Add new Unicode ranges here !! */
|
||||
{ 160, 255 },
|
||||
{ 0, 0 }
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
FT_LOCAL_DEF( const AF_ScriptClassRec ) af_latin_script_class =
|
||||
{
|
||||
AF_SCRIPT_LATIN,
|
||||
|
|
|
@ -51,9 +51,10 @@ FT_BEGIN_HEADER
|
|||
|
||||
enum
|
||||
{
|
||||
AF_LATIN_BLUE_ACTIVE = (1 << 0),
|
||||
AF_LATIN_BLUE_TOP = (1 << 1),
|
||||
|
||||
AF_LATIN_BLUE_ACTIVE = (1 << 0),
|
||||
AF_LATIN_BLUE_TOP = (1 << 1),
|
||||
AF_LATIN_BLUE_ADJUSTMENT = (1 << 2), /* used for scale adjustment */
|
||||
/* optimization */
|
||||
AF_LATIN_BLUE_FLAG_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -105,16 +105,9 @@
|
|||
* is needed
|
||||
*/
|
||||
if ( loader->transformed )
|
||||
{
|
||||
FT_Vector* point = slot->outline.points;
|
||||
FT_Vector* limit = point + slot->outline.n_points;
|
||||
|
||||
for ( ; point < limit; point++ )
|
||||
{
|
||||
point->x += loader->trans_delta.x;
|
||||
point->y += loader->trans_delta.y;
|
||||
}
|
||||
}
|
||||
FT_Outline_Translate( &slot->outline,
|
||||
loader->trans_delta.x,
|
||||
loader->trans_delta.y );
|
||||
|
||||
/* copy the outline points in the loader's current */
|
||||
/* extra points which is used to keep original glyph coordinates */
|
||||
|
@ -157,16 +150,10 @@
|
|||
|
||||
/* now load the slot image into the auto-outline and run the */
|
||||
/* automatic hinting process */
|
||||
error = metrics->clazz->script_hints_init( hints,
|
||||
&gloader->current.outline,
|
||||
metrics );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
/* apply the hints */
|
||||
metrics->clazz->script_hints_apply( hints,
|
||||
&gloader->current.outline,
|
||||
metrics );
|
||||
|
||||
/* we now need to hint the metrics according to the change in */
|
||||
/* width/positioning that occured during the hinting process */
|
||||
{
|
||||
|
@ -175,20 +162,27 @@
|
|||
AF_Edge edge1 = axis->edges; /* leftmost edge */
|
||||
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */
|
||||
|
||||
if ( edge2 > edge1 )
|
||||
{
|
||||
old_advance = loader->pp2.x;
|
||||
old_rsb = old_advance - edge2->opos;
|
||||
old_lsb = edge1->opos;
|
||||
new_lsb = edge1->pos;
|
||||
|
||||
old_advance = loader->pp2.x;
|
||||
old_rsb = old_advance - edge2->opos;
|
||||
old_lsb = edge1->opos;
|
||||
new_lsb = edge1->pos;
|
||||
|
||||
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
|
||||
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
|
||||
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
|
||||
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
|
||||
|
||||
#if 0
|
||||
/* try to fix certain bad advance computations */
|
||||
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
|
||||
loader->pp2.x += 64;
|
||||
/* try to fix certain bad advance computations */
|
||||
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
|
||||
loader->pp2.x += 64;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
loader->pp1.x = FT_PIX_ROUND( loader->pp1.x );
|
||||
loader->pp2.x = FT_PIX_ROUND( loader->pp2.x );
|
||||
}
|
||||
}
|
||||
|
||||
/* good, we simply add the glyph to our loader's base */
|
||||
|
@ -366,7 +360,13 @@
|
|||
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
|
||||
x_scale );
|
||||
#else
|
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
|
||||
/* for mono-width fonts (like Andale, Courier, etc.) we need */
|
||||
/* to keep the original rounded advance width */
|
||||
if ( !FT_IS_FIXED_WIDTH( slot->face ) )
|
||||
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
|
||||
else
|
||||
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
|
||||
metrics->scaler.x_scale );
|
||||
#endif
|
||||
|
||||
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
|
||||
|
@ -434,8 +434,13 @@
|
|||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
|
||||
load_flags &= ~FT_LOAD_RENDER;
|
||||
|
||||
error = metrics->clazz->script_hints_init( &loader->hints, metrics );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
|
||||
}
|
||||
}
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* FreeType auto-fitter
|
||||
*
|
||||
* (c) 2004 David Turner
|
||||
*
|
||||
* The auto-fitter is a complete rewrite of the old auto-hinter.
|
||||
* its main feature is the ability to differentiate between different
|
||||
* scripts in order to apply language-specific rules.
|
||||
*
|
||||
* the code has also been compartimentized into several entities that
|
||||
* should make algorithmic experimentation easier than with the old
|
||||
* code.
|
||||
*
|
||||
* finally, we get rid of the Catharon license, since this code is
|
||||
* released under the FreeType one.
|
||||
*/
|
||||
#ifndef __AFTYPES_H__
|
||||
#define __AFTYPES_H__
|
||||
|
||||
|
@ -73,7 +90,7 @@ FT_BEGIN_HEADER
|
|||
|
||||
typedef FT_Int AF_Angle;
|
||||
|
||||
#define AF_ANGLE_PI 128
|
||||
#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)
|
||||
|
@ -164,6 +181,12 @@ FT_BEGIN_HEADER
|
|||
} AF_ScalerRec, *AF_Scaler;
|
||||
|
||||
|
||||
#define AF_SCALER_EQUAL_SCALES(a,b) \
|
||||
( (a)->x_scale == (b)->x_scale && \
|
||||
(a)->y_scale == (b)->y_scale && \
|
||||
(a)->x_delta == (b)->x_delta && \
|
||||
(a)->y_delta == (b)->y_delta )
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
@ -228,7 +251,6 @@ FT_BEGIN_HEADER
|
|||
|
||||
|
||||
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
|
||||
FT_Outline* outline,
|
||||
AF_ScriptMetrics metrics );
|
||||
|
||||
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# compute arctangent table for CORDIC computations in fttrigon.c
|
||||
import sys, math
|
||||
|
||||
units = 64*65536.0 # don't change !!
|
||||
#units = 64*65536.0 # don't change !!
|
||||
units = 256
|
||||
scale = units/math.pi
|
||||
shrink = 1.0
|
||||
comma = ""
|
||||
|
@ -23,7 +24,7 @@ def print_val( n, x ):
|
|||
|
||||
errlo = abs( alo - ax )
|
||||
errhi = abs( ahi - ax )
|
||||
|
||||
|
||||
if ( errlo < errhi ):
|
||||
hi = lo
|
||||
|
||||
|
@ -44,8 +45,8 @@ for n in r:
|
|||
x = 1.0/(2.0**n) # tangent value
|
||||
else:
|
||||
x = 2.0**(-n)
|
||||
|
||||
angle = math.atan(x) # arctangent
|
||||
|
||||
angle = math.atan(x) # arctangent
|
||||
angle2 = angle*scale # arctangent in FT_Angle units
|
||||
|
||||
# determine which integer value for angle gives the best tangent
|
||||
|
@ -63,12 +64,12 @@ for n in r:
|
|||
|
||||
if angle2 <= 0:
|
||||
break
|
||||
|
||||
|
||||
sys.stdout.write( comma + repr( int(angle2) ) )
|
||||
comma = ", "
|
||||
|
||||
|
||||
shrink = shrink * math.cos( angle2/scale)
|
||||
|
||||
|
||||
|
||||
print
|
||||
print "shrink factor = " + repr( shrink )
|
||||
|
|
Loading…
Reference in New Issue