* 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>
|
2004-06-02 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
* src/truetype/ttgload.c (compute_glyph_metrics): Fix compiler
|
* src/truetype/ttgload.c (compute_glyph_metrics): Fix compiler
|
||||||
|
@ -24,7 +37,7 @@
|
||||||
|
|
||||||
2004-05-17 Werner Lemberg <wl@gnu.org>
|
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>.
|
Reported by Mikey Anbary <manbary@vizrt.com>.
|
||||||
|
|
||||||
2004-05-15 Werner Lemberg <wl@gnu.org>
|
2004-05-15 Werner Lemberg <wl@gnu.org>
|
||||||
|
@ -173,7 +186,7 @@
|
||||||
consistency.
|
consistency.
|
||||||
(pcf_cmap_init, pcf_cmap_done, pcf_cmap_char_index,
|
(pcf_cmap_init, pcf_cmap_done, pcf_cmap_char_index,
|
||||||
pcf_cmap_char_next): Don't use PCF_XXX but FT_XXX arguments which
|
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.
|
Update code accordingly.
|
||||||
(pcf_cmap_class): Remove casts.
|
(pcf_cmap_class): Remove casts.
|
||||||
(PCF_Face_Done, PCF_Face_Init, PCF_Set_Pixel_Size): Don't use
|
(PCF_Face_Done, PCF_Face_Init, PCF_Set_Pixel_Size): Don't use
|
||||||
|
|
|
@ -1,8 +1,57 @@
|
||||||
#include "aftypes.h"
|
#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 */
|
/* this table was generated for AF_ANGLE_PI = 256 */
|
||||||
#define AF_ANGLE_MAX_ITERS 8
|
#define AF_ANGLE_MAX_ITERS 8
|
||||||
#define AF_TRIG_MAX_ITERS 9
|
#define AF_TRIG_MAX_ITERS 8
|
||||||
|
|
||||||
static const FT_Fixed
|
static const FT_Fixed
|
||||||
af_angle_arctan_table[9] =
|
af_angle_arctan_table[9] =
|
||||||
|
@ -69,7 +118,7 @@
|
||||||
{
|
{
|
||||||
x = -x;
|
x = -x;
|
||||||
y = -y;
|
y = -y;
|
||||||
theta = 2 * AF_ANGLE_PI2;
|
theta = AF_ANGLE_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( y > 0 )
|
if ( y > 0 )
|
||||||
|
@ -115,11 +164,13 @@
|
||||||
}
|
}
|
||||||
} while ( ++i < AF_TRIG_MAX_ITERS );
|
} while ( ++i < AF_TRIG_MAX_ITERS );
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* round theta */
|
/* round theta */
|
||||||
if ( theta >= 0 )
|
if ( theta >= 0 )
|
||||||
theta = FT_PAD_ROUND( theta, 4 );
|
theta = FT_PAD_ROUND( theta, 2 );
|
||||||
else
|
else
|
||||||
theta = - FT_PAD_ROUND( theta, 4 );
|
theta = - FT_PAD_ROUND( -theta, 2 );
|
||||||
|
#endif
|
||||||
|
|
||||||
vec->x = x;
|
vec->x = x;
|
||||||
vec->y = theta;
|
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
|
static FT_Error
|
||||||
af_dummy_hints_init( AF_GlyphHints hints,
|
af_dummy_hints_init( AF_GlyphHints hints,
|
||||||
FT_Outline* outline,
|
|
||||||
AF_ScriptMetrics metrics )
|
AF_ScriptMetrics metrics )
|
||||||
{
|
{
|
||||||
return af_glyph_hints_reset( hints,
|
af_glyph_hints_rescale( hints,
|
||||||
&metrics->scaler,
|
metrics );
|
||||||
metrics,
|
return 0;
|
||||||
outline );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
af_dummy_hints_apply( AF_GlyphHints hints,
|
af_dummy_hints_apply( AF_GlyphHints hints,
|
||||||
FT_Outline* outline )
|
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 */
|
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 */
|
#define AF_SCRIPT_LIST_NONE 255 /* indicates an uncovered glyph */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
|
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case AF_DIR_UP: result = "up"; break;
|
case AF_DIR_UP: result = "up"; break;
|
||||||
case AF_DIR_DOWN: result = "down"; break;
|
case AF_DIR_DOWN: result = "down"; break;
|
||||||
case AF_DIR_LEFT: result = "left"; break;
|
case AF_DIR_LEFT: result = "left"; break;
|
||||||
case AF_DIR_RIGHT: result = "right"; break;
|
case AF_DIR_RIGHT: result = "right"; break;
|
||||||
default: result = "none";
|
default: result = "none";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
|
|
||||||
for ( edge = edges; edge < limit; edge++ )
|
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,
|
edge - edges,
|
||||||
(int)edge->fpos,
|
(int)edge->fpos,
|
||||||
af_dir_str( edge->dir ),
|
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 )
|
FT_LOCAL_DEF( FT_Error )
|
||||||
af_glyph_hints_reset( AF_GlyphHints hints,
|
af_glyph_hints_reload( AF_GlyphHints hints,
|
||||||
AF_Scaler scaler,
|
FT_Outline* outline )
|
||||||
AF_ScriptMetrics metrics,
|
|
||||||
FT_Outline* outline )
|
|
||||||
{
|
{
|
||||||
FT_Error error = FT_Err_Ok;
|
FT_Error error = FT_Err_Ok;
|
||||||
AF_Point points;
|
AF_Point points;
|
||||||
FT_UInt old_max, new_max;
|
FT_UInt old_max, new_max;
|
||||||
FT_Fixed x_scale = scaler->x_scale;
|
AF_Scaler scaler = &hints->metrics->scaler;
|
||||||
FT_Fixed y_scale = scaler->y_scale;
|
FT_Fixed x_scale = hints->x_scale;
|
||||||
FT_Pos x_delta = scaler->x_delta;
|
FT_Fixed y_scale = hints->y_scale;
|
||||||
FT_Pos y_delta = scaler->y_delta;
|
FT_Pos x_delta = hints->x_delta;
|
||||||
|
FT_Pos y_delta = hints->y_delta;
|
||||||
FT_Memory memory = hints->memory;
|
FT_Memory memory = hints->memory;
|
||||||
|
|
||||||
hints->metrics = metrics;
|
hints->scaler_flags = scaler->flags;
|
||||||
|
|
||||||
hints->scaler_flags = scaler->flags;
|
|
||||||
hints->other_flags = 0;
|
|
||||||
|
|
||||||
hints->num_points = 0;
|
hints->num_points = 0;
|
||||||
hints->num_contours = 0;
|
hints->num_contours = 0;
|
||||||
|
|
||||||
|
|
|
@ -214,11 +214,13 @@ FT_BEGIN_HEADER
|
||||||
/* recomputes all AF_Point in a AF_GlyphHints from the definitions
|
/* recomputes all AF_Point in a AF_GlyphHints from the definitions
|
||||||
* in a source outline
|
* in a source outline
|
||||||
*/
|
*/
|
||||||
|
FT_LOCAL( void )
|
||||||
|
af_glyph_hints_rescale( AF_GlyphHints hints,
|
||||||
|
AF_ScriptMetrics metrics );
|
||||||
|
|
||||||
FT_LOCAL( FT_Error )
|
FT_LOCAL( FT_Error )
|
||||||
af_glyph_hints_reset( AF_GlyphHints hints,
|
af_glyph_hints_reload( AF_GlyphHints hints,
|
||||||
AF_Scaler scaler,
|
FT_Outline* outline );
|
||||||
AF_ScriptMetrics metrics,
|
|
||||||
FT_Outline* outline );
|
|
||||||
|
|
||||||
FT_LOCAL( void )
|
FT_LOCAL( void )
|
||||||
af_glyph_hints_save( AF_GlyphHints hints,
|
af_glyph_hints_save( AF_GlyphHints hints,
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_UInt glyph_index;
|
FT_UInt glyph_index;
|
||||||
AF_Dimension dim;
|
AF_Dimension dim;
|
||||||
AF_ScalerRec scaler[1];
|
AF_ScriptMetricsRec dummy[1];
|
||||||
|
AF_Scaler scaler = &dummy->scaler;
|
||||||
|
|
||||||
glyph_index = FT_Get_Char_Index( face, 'o' );
|
glyph_index = FT_Get_Char_Index( face, 'o' );
|
||||||
if ( glyph_index == 0 )
|
if ( glyph_index == 0 )
|
||||||
|
@ -36,15 +36,17 @@
|
||||||
if ( error || face->glyph->outline.n_points <= 0 )
|
if ( error || face->glyph->outline.n_points <= 0 )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
FT_ZERO( dummy );
|
||||||
|
|
||||||
scaler->x_scale = scaler->y_scale = 0x10000L;
|
scaler->x_scale = scaler->y_scale = 0x10000L;
|
||||||
scaler->x_delta = scaler->y_delta = 0;
|
scaler->x_delta = scaler->y_delta = 0;
|
||||||
scaler->face = face;
|
scaler->face = face;
|
||||||
scaler->render_mode = 0;
|
scaler->render_mode = 0;
|
||||||
scaler->flags = 0;
|
scaler->flags = 0;
|
||||||
|
|
||||||
error = af_glyph_hints_reset( hints, scaler,
|
af_glyph_hints_rescale( hints, dummy );
|
||||||
(AF_ScriptMetrics) metrics,
|
|
||||||
&face->glyph->outline );
|
error = af_glyph_hints_reload( hints, &face->glyph->outline );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -324,6 +326,13 @@
|
||||||
if ( AF_LATIN_IS_TOP_BLUE(bb) )
|
if ( AF_LATIN_IS_TOP_BLUE(bb) )
|
||||||
blue->flags |= AF_LATIN_BLUE_TOP;
|
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 ));
|
AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,8 +391,44 @@
|
||||||
axis->org_scale = scale;
|
axis->org_scale = scale;
|
||||||
axis->org_delta = delta;
|
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->scale = scale;
|
||||||
axis->delta = delta;
|
axis->delta = delta;
|
||||||
|
|
||||||
|
@ -417,17 +462,41 @@
|
||||||
AF_LatinBlue blue = & axis->blues[nn];
|
AF_LatinBlue blue = & axis->blues[nn];
|
||||||
FT_Pos dist;
|
FT_Pos dist;
|
||||||
|
|
||||||
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
|
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
|
||||||
blue->ref.fit = blue->ref.cur;
|
blue->ref.fit = blue->ref.cur;
|
||||||
|
|
||||||
blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
|
blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
|
||||||
blue->shoot.fit = blue->shoot.cur;
|
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
|
/* 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 );
|
dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
|
||||||
if ( dist >= 48 || dist <= -48 )
|
if ( dist <= 48 && dist >= -48 )
|
||||||
blue->flags |= ~AF_LATIN_BLUE_ACTIVE;
|
{
|
||||||
|
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_latin_metrics_scale( AF_LatinMetrics metrics,
|
||||||
AF_Scaler scaler )
|
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_HORZ );
|
||||||
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
|
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
|
||||||
}
|
}
|
||||||
|
@ -791,6 +863,7 @@
|
||||||
AF_Dimension dim )
|
AF_Dimension dim )
|
||||||
{
|
{
|
||||||
AF_AxisHints axis = &hints->axis[dim];
|
AF_AxisHints axis = &hints->axis[dim];
|
||||||
|
AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
|
||||||
AF_Edge edges = axis->edges;
|
AF_Edge edges = axis->edges;
|
||||||
AF_Edge edge, edge_limit;
|
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 );
|
scale );
|
||||||
if ( edge_distance_threshold > 64 / 4 )
|
if ( edge_distance_threshold > 64 / 4 )
|
||||||
edge_distance_threshold = 64 / 4;
|
edge_distance_threshold = 64 / 4;
|
||||||
|
@ -1138,18 +1211,19 @@
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
af_latin_hints_init( AF_GlyphHints hints,
|
af_latin_hints_init( AF_GlyphHints hints,
|
||||||
FT_Outline* outline,
|
|
||||||
AF_LatinMetrics metrics )
|
AF_LatinMetrics metrics )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
|
||||||
FT_Render_Mode mode;
|
FT_Render_Mode mode;
|
||||||
|
|
||||||
error = af_glyph_hints_reset( hints, &metrics->root.scaler,
|
af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics );
|
||||||
(AF_ScriptMetrics) metrics,
|
|
||||||
outline );
|
|
||||||
if (error)
|
|
||||||
goto Exit;
|
|
||||||
|
|
||||||
|
/* 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...
|
/* compute flags depending on render mode, etc...
|
||||||
*/
|
*/
|
||||||
|
@ -1176,21 +1250,11 @@
|
||||||
if ( mode == FT_RENDER_MODE_MONO )
|
if ( mode == FT_RENDER_MODE_MONO )
|
||||||
hints->other_flags |= AF_LATIN_HINTS_MONO;
|
hints->other_flags |= AF_LATIN_HINTS_MONO;
|
||||||
|
|
||||||
/* analyze glyph outline
|
return 0;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/***** *****/
|
/***** *****/
|
||||||
|
@ -1738,10 +1802,26 @@
|
||||||
FT_Outline* outline,
|
FT_Outline* outline,
|
||||||
AF_LatinMetrics metrics )
|
AF_LatinMetrics metrics )
|
||||||
{
|
{
|
||||||
|
FT_Error error;
|
||||||
AF_Dimension dim;
|
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++ )
|
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
|
||||||
{
|
{
|
||||||
if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) ||
|
if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) ||
|
||||||
|
@ -1755,7 +1835,8 @@
|
||||||
}
|
}
|
||||||
af_glyph_hints_save( hints, outline );
|
af_glyph_hints_save( hints, outline );
|
||||||
|
|
||||||
return 0;
|
Exit:
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
@ -1768,11 +1849,12 @@
|
||||||
|
|
||||||
static const AF_Script_UniRangeRec af_latin_uniranges[] =
|
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 },
|
{ 160, 255 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL_DEF( const AF_ScriptClassRec ) af_latin_script_class =
|
FT_LOCAL_DEF( const AF_ScriptClassRec ) af_latin_script_class =
|
||||||
{
|
{
|
||||||
AF_SCRIPT_LATIN,
|
AF_SCRIPT_LATIN,
|
||||||
|
|
|
@ -51,9 +51,10 @@ FT_BEGIN_HEADER
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
AF_LATIN_BLUE_ACTIVE = (1 << 0),
|
AF_LATIN_BLUE_ACTIVE = (1 << 0),
|
||||||
AF_LATIN_BLUE_TOP = (1 << 1),
|
AF_LATIN_BLUE_TOP = (1 << 1),
|
||||||
|
AF_LATIN_BLUE_ADJUSTMENT = (1 << 2), /* used for scale adjustment */
|
||||||
|
/* optimization */
|
||||||
AF_LATIN_BLUE_FLAG_MAX
|
AF_LATIN_BLUE_FLAG_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -105,16 +105,9 @@
|
||||||
* is needed
|
* is needed
|
||||||
*/
|
*/
|
||||||
if ( loader->transformed )
|
if ( loader->transformed )
|
||||||
{
|
FT_Outline_Translate( &slot->outline,
|
||||||
FT_Vector* point = slot->outline.points;
|
loader->trans_delta.x,
|
||||||
FT_Vector* limit = point + slot->outline.n_points;
|
loader->trans_delta.y );
|
||||||
|
|
||||||
for ( ; point < limit; point++ )
|
|
||||||
{
|
|
||||||
point->x += loader->trans_delta.x;
|
|
||||||
point->y += loader->trans_delta.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the outline points in the loader's current */
|
/* copy the outline points in the loader's current */
|
||||||
/* extra points which is used to keep original glyph coordinates */
|
/* 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 */
|
/* now load the slot image into the auto-outline and run the */
|
||||||
/* automatic hinting process */
|
/* 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,
|
metrics->clazz->script_hints_apply( hints,
|
||||||
&gloader->current.outline,
|
&gloader->current.outline,
|
||||||
metrics );
|
metrics );
|
||||||
|
|
||||||
/* we now need to hint the metrics according to the change in */
|
/* we now need to hint the metrics according to the change in */
|
||||||
/* width/positioning that occured during the hinting process */
|
/* width/positioning that occured during the hinting process */
|
||||||
{
|
{
|
||||||
|
@ -175,20 +162,27 @@
|
||||||
AF_Edge edge1 = axis->edges; /* leftmost edge */
|
AF_Edge edge1 = axis->edges; /* leftmost edge */
|
||||||
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost 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;
|
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
|
||||||
old_rsb = old_advance - edge2->opos;
|
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
|
||||||
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 );
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* try to fix certain bad advance computations */
|
/* try to fix certain bad advance computations */
|
||||||
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
|
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
|
||||||
loader->pp2.x += 64;
|
loader->pp2.x += 64;
|
||||||
#endif
|
#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 */
|
/* good, we simply add the glyph to our loader's base */
|
||||||
|
@ -366,7 +360,13 @@
|
||||||
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
|
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
|
||||||
x_scale );
|
x_scale );
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
|
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_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
|
||||||
load_flags &= ~FT_LOAD_RENDER;
|
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 );
|
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Exit:
|
||||||
return error;
|
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__
|
#ifndef __AFTYPES_H__
|
||||||
#define __AFTYPES_H__
|
#define __AFTYPES_H__
|
||||||
|
|
||||||
|
@ -73,7 +90,7 @@ FT_BEGIN_HEADER
|
||||||
|
|
||||||
typedef FT_Int AF_Angle;
|
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_2PI (AF_ANGLE_PI*2)
|
||||||
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2)
|
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2)
|
||||||
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4)
|
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4)
|
||||||
|
@ -164,6 +181,12 @@ FT_BEGIN_HEADER
|
||||||
} AF_ScalerRec, *AF_Scaler;
|
} 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,
|
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
|
||||||
FT_Outline* outline,
|
|
||||||
AF_ScriptMetrics metrics );
|
AF_ScriptMetrics metrics );
|
||||||
|
|
||||||
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
|
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# compute arctangent table for CORDIC computations in fttrigon.c
|
# compute arctangent table for CORDIC computations in fttrigon.c
|
||||||
import sys, math
|
import sys, math
|
||||||
|
|
||||||
units = 64*65536.0 # don't change !!
|
#units = 64*65536.0 # don't change !!
|
||||||
|
units = 256
|
||||||
scale = units/math.pi
|
scale = units/math.pi
|
||||||
shrink = 1.0
|
shrink = 1.0
|
||||||
comma = ""
|
comma = ""
|
||||||
|
@ -23,7 +24,7 @@ def print_val( n, x ):
|
||||||
|
|
||||||
errlo = abs( alo - ax )
|
errlo = abs( alo - ax )
|
||||||
errhi = abs( ahi - ax )
|
errhi = abs( ahi - ax )
|
||||||
|
|
||||||
if ( errlo < errhi ):
|
if ( errlo < errhi ):
|
||||||
hi = lo
|
hi = lo
|
||||||
|
|
||||||
|
@ -44,8 +45,8 @@ for n in r:
|
||||||
x = 1.0/(2.0**n) # tangent value
|
x = 1.0/(2.0**n) # tangent value
|
||||||
else:
|
else:
|
||||||
x = 2.0**(-n)
|
x = 2.0**(-n)
|
||||||
|
|
||||||
angle = math.atan(x) # arctangent
|
angle = math.atan(x) # arctangent
|
||||||
angle2 = angle*scale # arctangent in FT_Angle units
|
angle2 = angle*scale # arctangent in FT_Angle units
|
||||||
|
|
||||||
# determine which integer value for angle gives the best tangent
|
# determine which integer value for angle gives the best tangent
|
||||||
|
@ -63,12 +64,12 @@ for n in r:
|
||||||
|
|
||||||
if angle2 <= 0:
|
if angle2 <= 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
sys.stdout.write( comma + repr( int(angle2) ) )
|
sys.stdout.write( comma + repr( int(angle2) ) )
|
||||||
comma = ", "
|
comma = ", "
|
||||||
|
|
||||||
shrink = shrink * math.cos( angle2/scale)
|
shrink = shrink * math.cos( angle2/scale)
|
||||||
|
|
||||||
|
|
||||||
print
|
print
|
||||||
print "shrink factor = " + repr( shrink )
|
print "shrink factor = " + repr( shrink )
|
||||||
|
|
Loading…
Reference in New Issue