ref: e664efadddc49bee32b337571e329f150006a84b
parent: 56a4d87cb2935339e970d0743c250389fc4706c8
author: David Turner <[email protected]>
date: Fri Jun 4 13:41:59 EDT 2004
* 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
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2004-06-04 David Turner <[email protected]>
+
+ * 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 <[email protected]>
* src/truetype/ttgload.c (compute_glyph_metrics): Fix compiler
@@ -24,7 +37,7 @@
2004-05-17 Werner Lemberg <[email protected]>
- * src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
+ * src/base/ftbbox.c (BBox_Conic_Check): Fix boundary cases.
Reported by Mikey Anbary <[email protected]>.
2004-05-15 Werner Lemberg <[email protected]>
@@ -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
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -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
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -3,13 +3,11 @@
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
@@ -16,7 +14,10 @@
af_dummy_hints_apply( AF_GlyphHints hints,
FT_Outline* outline )
{
- af_glyph_hints_save( hints, outline );
+ FT_UNUSED( hints );
+ FT_UNUSED( outline );
+
+ return 0;
}
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -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 */
/*
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -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;
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -214,11 +214,13 @@
/* 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,
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -25,9 +25,9 @@
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 )
goto Exit;
@@ -36,6 +36,8 @@
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;
@@ -42,9 +44,9 @@
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,20 +1250,10 @@
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 );
+ return 0;
+ }
- 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,
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,10 +1849,11 @@
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 =
{
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -51,9 +51,10 @@
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
};
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -105,17 +105,10 @@
* is needed
*/
if ( loader->transformed )
- {
- FT_Vector* point = slot->outline.points;
- FT_Vector* limit = point + slot->outline.n_points;
+ FT_Outline_Translate( &slot->outline,
+ loader->trans_delta.x,
+ 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 */
/* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader,
@@ -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;
}
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -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 @@
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,7 +181,13 @@
} 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 @@
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
- FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
--- a/src/tools/cordic.py
+++ b/src/tools/cordic.py
@@ -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 @@
errlo = abs( alo - ax )
errhi = abs( ahi - ax )
-
+
if ( errlo < errhi ):
hi = lo
@@ -44,8 +45,8 @@
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 @@
if angle2 <= 0:
break
-
+
sys.stdout.write( comma + repr( int(angle2) ) )
comma = ", "
-
+
shrink = shrink * math.cos( angle2/scale)
-
+
print "shrink factor = " + repr( shrink )