src/base/Jamfile, src/base/rules.mk: adding trigonometric functions to the core API (using Cordic algorithms). * builds/top_level.mk, builds/newline, builds/detect.mk: fixed problems with Make on Windows 2000, as well as problems when "make distclean" is invoked on a non-Unix platform when there is no "config.mk" in the current directory.. * builds/freetype.mk: fixed a problem with object deletions under Dos/Windows/OS/2 systems * src/tools: added new directory to hold tools and test programs moved docmaker.py, glnames.py to it.. * src/tools/docmaker.py: improved the script to add the current date at the footer of each web page (useful to distinguish between versions) * Jamfile: fixed incorrect HDRMACRO argument. * TODO: removed the cubic arc bbox computation note, since it has been fixed recently.. * include/freetype/t1tables.h, include/freetype/config/ftoption.h: formattingdavid-pic-changes
parent
b3de817acb
commit
ebe85f59c9
23 changed files with 1254 additions and 47 deletions
@ -0,0 +1 @@ |
||||
|
@ -0,0 +1,213 @@ |
||||
#ifndef __FT_TRIGONOMETRY_H__ |
||||
#define __FT_TRIGONOMETRY_H__ |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @section: computations |
||||
* |
||||
*/ |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @type: FT_Angle |
||||
* |
||||
* @description: |
||||
* this type is used to model angle values in FreeType. Note that |
||||
* the angle is a 16.16 fixed float value expressed in _degrees_ |
||||
*/ |
||||
typedef FT_Fixed FT_Angle; |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @macro: FT_ANGLE_PI |
||||
* |
||||
* @description: |
||||
* the angle pi expressed in @FT_Angle units |
||||
*/ |
||||
#define FT_ANGLE_PI (180L << 16) |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @macro: FT_ANGLE_2PI |
||||
* |
||||
* @description: |
||||
* the angle 2pi expressed in @FT_Angle units |
||||
*/ |
||||
#define FT_ANGLE_2PI (FT_ANGLE_PI*2) |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @macro: FT_ANGLE_PI2 |
||||
* |
||||
* @description: |
||||
* the angle pi/2 expressed in @FT_Angle units |
||||
*/ |
||||
#define FT_ANGLE_PI2 (FT_ANGLE_PI/2) |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @macro: FT_ANGLE_PI4 |
||||
* |
||||
* @description: |
||||
* the angle pi/4 expressed in @FT_Angle units |
||||
*/ |
||||
#define FT_ANGLE_PI4 (FT_ANGLE_PI/4) |
||||
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Sin |
||||
* |
||||
* @description: |
||||
* return the sinus of a given angle in fixed point format |
||||
* |
||||
* @input: |
||||
* angle :: input angle |
||||
* |
||||
* @return: |
||||
* sinus value |
||||
* |
||||
* @note: |
||||
* if you need both the sinus and cosinus for a given angle, you'd |
||||
* better use the function @FT_Vector_Unit |
||||
*/ |
||||
FT_EXPORT(FT_Fixed) FT_Sin( FT_Angle angle ); |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Cos |
||||
* |
||||
* @description: |
||||
* return the cosinus of a given angle in fixed point format |
||||
* |
||||
* @input: |
||||
* angle :: input angle |
||||
* |
||||
* @return: |
||||
* cosinus value |
||||
* |
||||
* @note: |
||||
* if you need both the sinus and cosinus for a given angle, you'd |
||||
* better use the function @FT_Vector_Unit |
||||
*/ |
||||
FT_EXPORT(FT_Fixed) FT_Cos( FT_Angle angle );
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Tan |
||||
* |
||||
* @description: |
||||
* return the tangent of a given angle in fixed point format |
||||
* |
||||
* @input: |
||||
* angle :: input angle |
||||
* |
||||
* @return: |
||||
* tangent value |
||||
*/ |
||||
FT_EXPORT(FT_Fixed) FT_Tan( FT_Angle angle ); |
||||
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Atan2 |
||||
* |
||||
* @description: |
||||
* return the arc-tangent corresponding to a given vector (x,y) in |
||||
* the 2d plane |
||||
* |
||||
* @input: |
||||
* x :: horizontal vector coordinate |
||||
* y :: vertical vector coordinate |
||||
* |
||||
* @return: |
||||
* arc-tangent value (i.e. angle) |
||||
*/ |
||||
FT_EXPORT(FT_Angle) FT_Atan2( FT_Fixed x, FT_Fixed y ); |
||||
|
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Vector_Unit |
||||
* |
||||
* @description: |
||||
* return the unit vector corresponding to a given angle. After the call, |
||||
* the value of "vec.x" will be "sin(theta)", and the value of "vec.y" |
||||
* will be "cos(angle)" |
||||
* |
||||
* this function is useful to retrieve both the sinus and cosinus |
||||
* of a given angle quickly |
||||
* |
||||
* @input: |
||||
* vec :: address of target vector |
||||
* angle :: address of angle |
||||
*/ |
||||
FT_EXPORT(void) FT_Vector_Unit( FT_Vector* vec, |
||||
FT_Angle angle ); |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Vector_Rotate |
||||
* |
||||
* @description: |
||||
* rotate a given vector by a given angle |
||||
* |
||||
* @input: |
||||
* vec :: address of target vector |
||||
* angle :: address of angle |
||||
*/ |
||||
FT_EXPORT(void) FT_Vector_Rotate( FT_Vector* vec, |
||||
FT_Angle angle ); |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Vector_Length |
||||
* |
||||
* @description: |
||||
* returns the length of a given vector |
||||
* |
||||
* @input: |
||||
* vec :: address of target vector |
||||
* |
||||
* @return: |
||||
* vector length, expressed in the same units that the original |
||||
* vector coordinates !! |
||||
*/ |
||||
FT_EXPORT(FT_Fixed) FT_Vector_Length( FT_Vector* vec ); |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Vector_Normalize |
||||
* |
||||
* @description: |
||||
* normalize a given vector (i.e. compute the equivalent unit vector) |
||||
* |
||||
* @input: |
||||
* vec :: address of target vector |
||||
*/ |
||||
FT_EXPORT(void) FT_Vector_Normalize( FT_Vector* vec ); |
||||
|
||||
/***************************************************************************
|
||||
* |
||||
* @function: FT_Vector_Polarize |
||||
* |
||||
* @description: |
||||
* compute both the length and angle of a given vector |
||||
* |
||||
* @input: |
||||
* vec :: address of source vector |
||||
* |
||||
* @output: |
||||
* length :: vector length |
||||
* angle :: vector angle |
||||
*/ |
||||
FT_EXPORT(void) FT_Vector_Polarize( FT_Vector* vec, |
||||
FT_Fixed *length, |
||||
FT_Angle *angle ); |
||||
/* */ |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __FT_TRIGONOMETRY_H__ */ |
@ -0,0 +1,404 @@ |
||||
#include <ft2build.h> |
||||
#include FT_TRIGONOMETRY_H |
||||
|
||||
/* the following is 0.2715717684432231 * 2^30 */ |
||||
#define FT_TRIG_COSCALE 0x11616E8E /* 291597966 = 0.2715717684432241 * 2^30, valid for j>13 */ |
||||
|
||||
/* this table was generated for FT_PI = 180L << 16, i.e. degrees */ |
||||
#define FT_TRIG_MAX_ITERS 23 |
||||
|
||||
static const FT_Fixed |
||||
ft_trig_arctan_table[ 24 ] = |
||||
{ |
||||
4157273, 2949120, 1740967, 919879, 466945, 234379, 117304, 58666, |
||||
29335, 14668, 7334, 3667, 1833, 917, 458, 229, 115, 57, 29, 14, 7, |
||||
4, 2, 1 |
||||
}; |
||||
|
||||
|
||||
/* the Cordic shrink factor, multiplied by 2^32 */ |
||||
#define FT_TRIG_SCALE 1166391785 /* 0x4585BA38U */ |
||||
|
||||
#ifdef FT_CONFIG_HAS_INT64 |
||||
|
||||
/* multiply a given value by the CORDIC shrink factor */ |
||||
static FT_Fixed |
||||
ft_trig_downscale( FT_Fixed val ) |
||||
{ |
||||
FT_Fixed s; |
||||
FT_Int64 v; |
||||
|
||||
s = val; |
||||
val = (val >= 0) ? val : -val; |
||||
|
||||
v = (val * (FT_Int64)FT_TRIG_SCALE) + 0x100000000L; |
||||
val = (FT_Fixed)(v >> 32); |
||||
|
||||
return ( s >= 0 ) ? val : -val; |
||||
} |
||||
|
||||
#else /* !FT_CONFIG_HAS_INT64 */ |
||||
|
||||
/* multiply a given value by the CORDIC shrink factor */ |
||||
static FT_Fixed |
||||
ft_trig_downscale( FT_Fixed val ) |
||||
{ |
||||
FT_Fixed s; |
||||
FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3; |
||||
|
||||
s = val; |
||||
val = ( val >= 0 ) ? val : -val; |
||||
|
||||
v1 = (FT_UInt32)val >> 16; |
||||
v2 = (FT_UInt32)val & 0xFFFF; |
||||
|
||||
k1 = FT_TRIG_SCALE >> 16; /* constant */ |
||||
k2 = FT_TRIG_SCALE & 0xFFFF; /* constant */ |
||||
|
||||
hi = k1*v1; |
||||
lo1 = k1*v2 + k2*v1; /* can't overflow */ |
||||
|
||||
lo2 = k2*v2 >> 16; |
||||
lo3 = ( lo1 >= lo2 ) ? lo1 : lo2; |
||||
lo1 += lo2; |
||||
|
||||
hi += lo1 >> 16; |
||||
if (lo1 < lo3) |
||||
hi += 0x10000U; |
||||
|
||||
val = (FT_Fixed)hi; |
||||
|
||||
return ( s >= 0 ) ? val : -val; |
||||
} |
||||
|
||||
#endif /* !FT_CONFIG_HAS_INT64 */ |
||||
|
||||
|
||||
static FT_Int |
||||
ft_trig_prenorm( FT_Vector* vec ) |
||||
{ |
||||
FT_Fixed x, y, z; |
||||
FT_Int shift; |
||||
|
||||
x = vec->x; |
||||
y = vec->y; |
||||
|
||||
z = (( x >= 0 ) ? x : - x) | ((y >= 0) ? y : -y); |
||||
shift = 0; |
||||
|
||||
if ( z < (1L << 27) ) |
||||
{ |
||||
do |
||||
{ |
||||
shift++; |
||||
z <<= 1; |
||||
} |
||||
while ( z < (1L << 27) ); |
||||
|
||||
vec->x = (x << shift); |
||||
vec->y = (y << shift); |
||||
} |
||||
else if ( z > (1L << 28 ) ) |
||||
{ |
||||
do |
||||
{ |
||||
shift++; |
||||
z >>= 1; |
||||
} |
||||
while ( z > (1L << 28) ); |
||||
|
||||
vec->x = (x >> shift); |
||||
vec->y = (y >> shift); |
||||
shift = -shift; |
||||
} |
||||
return shift; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
static void |
||||
ft_trig_pseudo_rotate( FT_Vector* vec, FT_Angle theta ) |
||||
{ |
||||
FT_Int i; |
||||
FT_Fixed x, y, xtemp; |
||||
const FT_Fixed *arctanptr; |
||||
|
||||
x = vec->x; |
||||
y = vec->y; |
||||
|
||||
/* Get angle between -90 and 90 degrees */ |
||||
while (theta <= -FT_ANGLE_PI2) |
||||
{ |
||||
x = -x; |
||||
y = -y; |
||||
theta += FT_ANGLE_PI; |
||||
} |
||||
while (theta > FT_ANGLE_PI2) |
||||
{ |
||||
x = -x; |
||||
y = -y;
|
||||
theta -= FT_ANGLE_PI; |
||||
} |
||||
|
||||
/* Initial pseudorotation, with left shift */ |
||||
arctanptr = ft_trig_arctan_table; |
||||
if (theta < 0) |
||||
{ |
||||
xtemp = x + (y << 1); |
||||
y = y - (x << 1); |
||||
x = xtemp; |
||||
theta += *arctanptr++; |
||||
} |
||||
else |
||||
{ |
||||
xtemp = x - (y << 1); |
||||
y = y + (x << 1); |
||||
x = xtemp; |
||||
theta -= *arctanptr++; |
||||
} |
||||
|
||||
/* Subsequent pseudorotations, with right shifts */ |
||||
i = 0; |
||||
do |
||||
{ |
||||
if (theta < 0) |
||||
{ |
||||
xtemp = x + (y >> i); |
||||
y = y - (x >> i); |
||||
x = xtemp; |
||||
theta += *arctanptr++; |
||||
} |
||||
else |
||||
{ |
||||
xtemp = x - (y >> i); |
||||
y = y + (x >> i); |
||||
x = xtemp; |
||||
theta -= *arctanptr++; |
||||
} |
||||
} |
||||
while ( ++i < FT_TRIG_MAX_ITERS ); |
||||
|
||||
vec->x = x; |
||||
vec->y = y; |
||||
} |
||||
|
||||
|
||||
static void |
||||
ft_trig_pseudo_polarize( FT_Vector* vec ) |
||||
{ |
||||
FT_Fixed theta; |
||||
FT_Fixed yi, i; |
||||
FT_Fixed x, y; |
||||
const FT_Fixed *arctanptr; |
||||
|
||||
x = vec->x; |
||||
y = vec->y; |
||||
|
||||
/* Get the vector into the right half plane */ |
||||
theta = 0; |
||||
if (x < 0) |
||||
{ |
||||
x = -x; |
||||
y = -y; |
||||
theta = 2 * FT_ANGLE_PI2; |
||||
} |
||||
|
||||
if (y > 0) |
||||
theta = - theta; |
||||
|
||||
arctanptr = ft_trig_arctan_table; |
||||
if (y < 0) |
||||
{ |
||||
/* Rotate positive */ |
||||
yi = y + (x << 1); |
||||
x = x - (y << 1); |
||||
y = yi; |
||||
theta -= *arctanptr++; /* Subtract angle */ |
||||
} |
||||
else |
||||
{ |
||||
/* Rotate negative */ |
||||
yi = y - (x << 1); |
||||
x = x + (y << 1); |
||||
y = yi; |
||||
theta += *arctanptr++; /* Add angle */ |
||||
} |
||||
|
||||
i = 0; |
||||
do |
||||
{ |
||||
if (y < 0) |
||||
{ |
||||
/* Rotate positive */ |
||||
yi = y + (x >> i); |
||||
x = x - (y >> i); |
||||
y = yi; |
||||
theta -= *arctanptr++; |
||||
} |
||||
else |
||||
{ |
||||
/* Rotate negative */ |
||||
yi = y - (x >> i); |
||||
x = x + (y >> i); |
||||
y = yi; |
||||
theta += *arctanptr++; |
||||
} |
||||
} |
||||
while (++i < FT_TRIG_MAX_ITERS); |
||||
|
||||
/* round theta */ |
||||
if ( theta >= 0 ) |
||||
theta = ( theta + 16 ) & -32; |
||||
else |
||||
theta = - (( -theta + 16 ) & -32); |
||||
|
||||
vec->x = x; |
||||
vec->y = theta; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(FT_Fixed) |
||||
FT_Cos( FT_Angle angle ) |
||||
{ |
||||
FT_Vector v; |
||||
|
||||
v.x = FT_TRIG_COSCALE >> 2; |
||||
v.y = 0; |
||||
ft_trig_pseudo_rotate( &v, angle ); |
||||
|
||||
return v.x >> 12; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(FT_Fixed) |
||||
FT_Sin( FT_Angle angle ) |
||||
{ |
||||
return FT_Cos( FT_ANGLE_PI2-angle ); |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(FT_Fixed) |
||||
FT_Tan( FT_Angle angle ) |
||||
{ |
||||
FT_Vector v; |
||||
|
||||
v.x = FT_TRIG_COSCALE >> 2; |
||||
v.y = 0; |
||||
ft_trig_pseudo_rotate( &v, angle ); |
||||
|
||||
return FT_DivFix( v.y, v.x ); |
||||
} |
||||
|
||||
|
||||
|
||||
FT_EXPORT_DEF(FT_Angle) |
||||
FT_Atan2( FT_Fixed dx, |
||||
FT_Fixed dy ) |
||||
{ |
||||
FT_Vector v; |
||||
|
||||
if ( dx == 0 && dy == 0 ) |
||||
return 0; |
||||
|
||||
v.x = dx; |
||||
v.y = dy;
|
||||
ft_trig_prenorm( &v ); |
||||
ft_trig_pseudo_polarize( &v ); |
||||
return v.y; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(void) |
||||
FT_Vector_Unit( FT_Vector* vec, |
||||
FT_Angle angle ) |
||||
{ |
||||
vec->x = FT_TRIG_COSCALE >> 2; |
||||
vec->y = 0; |
||||
ft_trig_pseudo_rotate( vec, angle ); |
||||
vec->x >>= 12; |
||||
vec->y >>= 12; |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(void) |
||||
FT_Vector_Rotate( FT_Vector* vec, |
||||
FT_Angle angle ) |
||||
{ |
||||
FT_Int shift; |
||||
FT_Vector v; |
||||
|
||||
v.x = vec->x; |
||||
v.y = vec->y; |
||||
if ( angle && ( v.x != 0 || v.y != 0 ) ) |
||||
{ |
||||
shift = ft_trig_prenorm( &v ); |
||||
ft_trig_pseudo_rotate( &v, angle ); |
||||
v.x = ft_trig_downscale( v.x ); |
||||
v.y = ft_trig_downscale( v.y ); |
||||
|
||||
if ( shift >= 0 ) |
||||
{ |
||||
vec->x = v.x >> shift; |
||||
vec->y = v.y >> shift; |
||||
} |
||||
else |
||||
{ |
||||
shift = -shift; |
||||
vec->x = v.x << shift; |
||||
vec->y = v.y << shift; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
FT_EXPORT_DEF(FT_Fixed) |
||||
FT_Vector_Length( FT_Vector* vec ) |
||||
{ |
||||
FT_Int shift; |
||||
FT_Vector v; |
||||
|
||||
v = *vec; |
||||
|
||||
/* handle trivial cases */
|
||||
if ( v.x == 0 ) |
||||
{ |
||||
return ( v.y >= 0 ) ? v.y : -v.y; |
||||
} |
||||
else if ( v.y == 0 ) |
||||
{ |
||||
return ( v.x >= 0 ) ? v.x : -v.x; |
||||
} |
||||
|
||||
/* general case */ |
||||
shift = ft_trig_prenorm( &v ); |
||||
ft_trig_pseudo_polarize( &v ); |
||||
|
||||
v.x = ft_trig_downscale( v.x ); |
||||
return ( shift >= 0 ) ? (v.x >> shift) : (v.x << -shift); |
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF(void) |
||||
FT_Vector_Polarize( FT_Vector* vec, |
||||
FT_Fixed *length, |
||||
FT_Angle *angle ) |
||||
{ |
||||
FT_Int shift; |
||||
FT_Vector v; |
||||
|
||||
v = *vec; |
||||
|
||||
if ( v.x == 0 && v.y == 0 ) |
||||
return; |
||||
|
||||
shift = ft_trig_prenorm( &v ); |
||||
ft_trig_pseudo_polarize( &v ); |
||||
|
||||
v.x = ft_trig_downscale( v.x ); |
||||
|
||||
*length = ( shift >= 0 ) ? (v.x >> shift) : (v.x << -shift); |
||||
*angle = v.y; |
||||
}
|
||||
|
||||
|
@ -0,0 +1,78 @@ |
||||
# compute arctangent table for CORDIC computations in fttrigon.c |
||||
import sys, math |
||||
|
||||
units = 180*65536 # don't change !! |
||||
scale = units/math.pi |
||||
shrink = 1.0 |
||||
comma = "" |
||||
|
||||
def calc_val( x ): |
||||
global units, shrink |
||||
angle = math.atan(x) |
||||
shrink = shrink * math.cos(angle) |
||||
return angle/math.pi * units |
||||
|
||||
def print_val( n, x ): |
||||
global comma |
||||
|
||||
lo = int(x) |
||||
hi = lo + 1 |
||||
alo = math.atan(lo) |
||||
ahi = math.atan(hi) |
||||
ax = math.atan(2.0**n) |
||||
|
||||
errlo = abs( alo - ax ) |
||||
errhi = abs( ahi - ax ) |
||||
|
||||
if ( errlo < errhi ): |
||||
hi = lo |
||||
|
||||
sys.stdout.write( comma + repr( int(hi) ) ) |
||||
comma = ", " |
||||
|
||||
|
||||
print "" |
||||
print "table of arctan( 1/2^n ) for PI = " + repr(units/65536.0) + " units" |
||||
|
||||
# compute range of "i" |
||||
r = [-1] |
||||
r = r + 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 = ", " |
||||
|
||||
shrink = shrink * math.cos( angle2/scale) |
||||
|
||||
|
||||
print |
||||
print "shrink factor = " + repr( shrink ) |
||||
print "shrink factor 2 = " + repr( shrink * (2.0**32) ) |
||||
print "expansion factor = " + repr(1/shrink) |
||||
print "" |
||||
|
@ -0,0 +1,160 @@ |
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
#include FT_BBOX_H |
||||
|
||||
|
||||
#include <time.h> /* for clock() */ |
||||
|
||||
/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */ |
||||
/* to get the HZ macro which is the equivalent. */ |
||||
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4) |
||||
#include <sys/param.h> |
||||
#define CLOCKS_PER_SEC HZ |
||||
#endif |
||||
|
||||
static long |
||||
get_time( void ) |
||||
{ |
||||
return clock() * 10000L / CLOCKS_PER_SEC; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
/* test bbox computations */ |
||||
|
||||
#define XSCALE 65536 |
||||
#define XX(x) ((FT_Pos)(x*XSCALE)) |
||||
#define XVEC(x,y) { XX(x), XX(y) } |
||||
#define XVAL(x) ((x)/(1.0*XSCALE)) |
||||
|
||||
/* dummy outline #1 */ |
||||
static FT_Vector dummy_vec_1[4] = |
||||
{ |
||||
#if 1 |
||||
XVEC( 408.9111, 535.3164 ), |
||||
XVEC( 455.8887, 634.396 ), |
||||
XVEC( -37.8765, 786.2207 ), |
||||
XVEC( 164.6074, 535.3164 ) |
||||
#else |
||||
{ (FT_Int32)0x0198E93DL , (FT_Int32)0x021750FFL }, /* 408.9111, 535.3164 */ |
||||
{ (FT_Int32)0x01C7E312L , (FT_Int32)0x027A6560L }, /* 455.8887, 634.3960 */ |
||||
{ (FT_Int32)0xFFDA1F9EL , (FT_Int32)0x0312387FL }, /* -37.8765, 786.2207 */ |
||||
{ (FT_Int32)0x00A49B7EL , (FT_Int32)0x021750FFL } /* 164.6074, 535.3164 */ |
||||
#endif |
||||
}; |
||||
|
||||
static char dummy_tag_1[4] = |
||||
{ |
||||
FT_Curve_Tag_On, |
||||
FT_Curve_Tag_Cubic, |
||||
FT_Curve_Tag_Cubic, |
||||
FT_Curve_Tag_On |
||||
}; |
||||
|
||||
static short dummy_contour_1[1] = |
||||
{ |
||||
3 |
||||
}; |
||||
|
||||
static FT_Outline dummy_outline_1 = |
||||
{ |
||||
1, |
||||
4, |
||||
dummy_vec_1, |
||||
dummy_tag_1, |
||||
dummy_contour_1, |
||||
0 |
||||
}; |
||||
|
||||
|
||||
/* dummy outline #2 */ |
||||
static FT_Vector dummy_vec_2[4] = |
||||
{ |
||||
XVEC( 100.0, 100.0 ), |
||||
XVEC( 100.0, 200.0 ), |
||||
XVEC( 200.0, 200.0 ), |
||||
XVEC( 200.0, 133.0 ) |
||||
}; |
||||
|
||||
static FT_Outline dummy_outline_2 = |
||||
{ |
||||
1, |
||||
4, |
||||
dummy_vec_2, |
||||
dummy_tag_1, |
||||
dummy_contour_1, |
||||
0 |
||||
}; |
||||
|
||||
|
||||
static void |
||||
dump_outline( FT_Outline* outline ) |
||||
{ |
||||
FT_BBox bbox; |
||||
|
||||
/* compute and display cbox */ |
||||
FT_Outline_Get_CBox( outline, &bbox ); |
||||
printf( "cbox = [%.2f %.2f %.2f %.2f]\n", |
||||
XVAL( bbox.xMin ), |
||||
XVAL( bbox.yMin ), |
||||
XVAL( bbox.xMax ), |
||||
XVAL( bbox.yMax ) ); |
||||
|
||||
/* compute and display bbox */ |
||||
FT_Outline_Get_BBox( outline, &bbox ); |
||||
printf( "bbox = [%.2f %.2f %.2f %.2f]\n", |
||||
XVAL( bbox.xMin ), |
||||
XVAL( bbox.yMin ), |
||||
XVAL( bbox.xMax ), |
||||
XVAL( bbox.yMax ) ); |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
profile_outline( FT_Outline* outline, |
||||
long repeat ) |
||||
{ |
||||
FT_BBox bbox; |
||||
long count; |
||||
long time0; |
||||
|
||||
time0 = get_time(); |
||||
for ( count = repeat; count > 0; count-- ) |
||||
FT_Outline_Get_CBox( outline, &bbox ); |
||||
|
||||
time0 = get_time() - time0;
|
||||
printf( "time = %5.2f cbox = [%.2f %.2f %.2f %.2f]\n", |
||||
((double)time0/10000.0), |
||||
XVAL( bbox.xMin ), |
||||
XVAL( bbox.yMin ), |
||||
XVAL( bbox.xMax ), |
||||
XVAL( bbox.yMax ) ); |
||||
|
||||
|
||||
time0 = get_time(); |
||||
for ( count = repeat; count > 0; count-- ) |
||||
FT_Outline_Get_BBox( outline, &bbox ); |
||||
|
||||
time0 = get_time() - time0; |
||||
printf( "time = %5.2f bbox = [%.2f %.2f %.2f %.2f]\n", |
||||
((double)time0/10000.0), |
||||
XVAL( bbox.xMin ), |
||||
XVAL( bbox.yMin ), |
||||
XVAL( bbox.xMax ), |
||||
XVAL( bbox.yMax ) ); |
||||
} |
||||
|
||||
#define REPEAT 100000L |
||||
|
||||
int main( int argc, char** argv ) |
||||
{ |
||||
printf( "outline #1\n" ); |
||||
profile_outline( &dummy_outline_1, REPEAT ); |
||||
|
||||
printf( "outline #2\n" ); |
||||
profile_outline( &dummy_outline_2, REPEAT ); |
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,236 @@ |
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
#include FT_TRIGONOMETRY_H |
||||
|
||||
#include <math.h> |
||||
#include <stdio.h> |
||||
|
||||
#define PI 3.14159265358979323846 |
||||
#define SPI (PI/FT_ANGLE_PI) |
||||
|
||||
/* the precision in 16.16 fixed float points of the checks. Expect */ |
||||
/* between 2 and 5 noise LSB bits during operations, due to */ |
||||
/* rounding errors.. */ |
||||
#define THRESHOLD 64 |
||||
|
||||
static error = 0; |
||||
|
||||
static void |
||||
test_cos( void ) |
||||
{ |
||||
FT_Fixed f1, f2; |
||||
double d1, d2; |
||||
int i; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
f1 = FT_Cos(i); |
||||
d1 = f1/65536.0; |
||||
d2 = cos( i*SPI ); |
||||
f2 = (FT_Fixed)(d2*65536.0); |
||||
|
||||
if ( abs( f2-f1 ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Cos[%3d] = %.7f cos[%3d] = %.7f\n", |
||||
(i >> 16), f1/65536.0, (i >> 16), d2 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
static void |
||||
test_sin( void ) |
||||
{ |
||||
FT_Fixed f1, f2; |
||||
double d1, d2; |
||||
int i; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
f1 = FT_Sin(i); |
||||
d1 = f1/65536.0; |
||||
d2 = sin( i*SPI ); |
||||
f2 = (FT_Fixed)(d2*65536.0); |
||||
|
||||
if ( abs( f2-f1 ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Sin[%3d] = %.7f sin[%3d] = %.7f\n", |
||||
(i >> 16), f1/65536.0, (i >> 16), d2 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
test_tan( void ) |
||||
{ |
||||
FT_Fixed f1, f2; |
||||
double d1, d2; |
||||
int i; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_PI2-0x2000000; i += 0x10000 ) |
||||
{ |
||||
f1 = FT_Tan(i); |
||||
d1 = f1/65536.0; |
||||
d2 = tan( i*SPI ); |
||||
f2 = (FT_Fixed)(d2*65536.0); |
||||
|
||||
if ( abs( f2-f1 ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Tan[%3d] = %.7f tan[%3d] = %.7f\n", |
||||
(i >> 16), f1/65536.0, (i >> 16), d2 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
test_atan2( void ) |
||||
{ |
||||
FT_Fixed c2, s2; |
||||
double l, a, c1, s1; |
||||
int i, j; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
l = 5.0; |
||||
a = i*SPI; |
||||
|
||||
c1 = l * cos(a); |
||||
s1 = l * sin(a); |
||||
|
||||
c2 = (FT_Fixed)(c1*65536.0); |
||||
s2 = (FT_Fixed)(s1*65536.0); |
||||
|
||||
j = FT_Atan2( c2, s2 ); |
||||
if ( j < 0 ) |
||||
j += FT_ANGLE_2PI; |
||||
|
||||
if ( abs( i - j ) > 1 ) |
||||
{ |
||||
printf( "FT_Atan2( %.7f, %.7f ) = %.5f, atan = %.5f\n", |
||||
c2/65536.0, s2/65536.0, j/65536.0, i/65536.0 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void |
||||
test_unit( void ) |
||||
{ |
||||
FT_Vector v; |
||||
double a, c1, s1; |
||||
FT_Fixed c2, s2; |
||||
int i; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
FT_Vector_Unit( &v, i ); |
||||
a = ( i*SPI ); |
||||
c1 = cos(a); |
||||
s1 = sin(a); |
||||
c2 = (FT_Fixed)(c1*65536.0); |
||||
s2 = (FT_Fixed)(s1*65536.0); |
||||
|
||||
if ( abs( v.x-c2 ) > THRESHOLD || |
||||
abs( v.y-s2 ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Vector_Unit[%3d] = ( %.7f, %.7f ) vec = ( %.7f, %.7f )\n", |
||||
(i >> 16), |
||||
v.x/65536.0, v.y/65536.0, |
||||
c1, s1 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
test_length( void ) |
||||
{ |
||||
FT_Vector v; |
||||
FT_Fixed l, l2; |
||||
int i; |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
l = (FT_Fixed)(500.0*65536.0); |
||||
v.x = (FT_Fixed)( l * cos( i*SPI ) ); |
||||
v.y = (FT_Fixed)( l * sin( i*SPI ) ); |
||||
l2 = FT_Vector_Length( &v ); |
||||
|
||||
if ( abs( l2-l ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Length( %.7f, %.7f ) = %.5f, length = %.5f\n", |
||||
v.x/65536.0, v.y/65536.0, l2/65536.0, l/65536.0 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
static void |
||||
test_rotate( void ) |
||||
{ |
||||
FT_Fixed c2, s2, c4, s4; |
||||
FT_Vector v; |
||||
double l, ra, a, c1, s1, cra, sra, c3, s3; |
||||
int i, j, rotate; |
||||
|
||||
for ( rotate = 0; rotate < FT_ANGLE_2PI; rotate += 0x10000 ) |
||||
{ |
||||
ra = rotate*SPI; |
||||
cra = cos( ra ); |
||||
sra = sin( ra ); |
||||
|
||||
for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 ) |
||||
{ |
||||
l = 500.0; |
||||
a = i*SPI; |
||||
|
||||
c1 = l * cos(a); |
||||
s1 = l * sin(a); |
||||
|
||||
v.x = c2 = (FT_Fixed)(c1*65536.0); |
||||
v.y = s2 = (FT_Fixed)(s1*65536.0); |
||||
|
||||
FT_Vector_Rotate( &v, rotate ); |
||||
|
||||
c3 = c1 * cra - s1 * sra; |
||||
s3 = c1 * sra + s1 * cra; |
||||
|
||||
c4 = (FT_Fixed)(c3*65536.0); |
||||
s4 = (FT_Fixed)(s3*65536.0); |
||||
|
||||
if ( abs( c4 - v.x ) > THRESHOLD || |
||||
abs( s4 - v.y ) > THRESHOLD ) |
||||
{ |
||||
error = 1; |
||||
printf( "FT_Rotate( (%.7f,%.7f), %.5f ) = ( %.7f, %.7f ), rot = ( %.7f, %.7f )\n", |
||||
c1, s1, ra, |
||||
c2/65536.0, s2/65536.0, |
||||
c4/65536.0, s4/65536.0 ); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
int main( void ) |
||||
{ |
||||
test_cos(); |
||||
test_sin(); |
||||
test_tan(); |
||||
test_atan2(); |
||||
test_unit(); |
||||
test_length(); |
||||
test_rotate(); |
||||
|
||||
if (!error) |
||||
printf( "trigonometry test ok !\n" ); |
||||
|
||||
return !error; |
||||
} |
Loading…
Reference in new issue