* include/freetype/fttrigon.h, src/base/fttrigon.c, src/base/ftbase.c,

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:
    formatting
This commit is contained in:
David Turner 2001-05-11 14:25:57 +00:00
parent b3de817acb
commit ebe85f59c9
23 changed files with 1254 additions and 47 deletions

View File

@ -1,3 +1,36 @@
2001-05-11 David Turner <david@freetype.org>
* include/freetype/fttrigon.h, src/base/fttrigon.c, src/base/ftbase.c,
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:
formatting
2001-05-10 David Turner <david@freetype.org>
* src/base/ftobjs.c (FT_Open_Face): fixed a small memory leaked
which happened when trying to open 0-size font files !!
2001-05-09 Werner Lemberg <wl@gnu.org>
* include/freetype/internal/ftcalc.h: Move declaration of
@ -21,8 +54,8 @@
2001-04-27 David Turner <david@freetype.org>
* src/base/ftbbox.c (BBox_Cubic_Check): Fixed the coefficient
normalization algorithm (invalid final bit position, and invalid
* src/base/ftbbox.c (BBox_Cubic_Check): Fixed the coefficient
normalization algorithm (invalid final bit position, and invalid
shift computation).
2001-04-26 Werner Lemberg <wl@gnu.org>
@ -66,7 +99,7 @@
types on platforms where Autoconf is not available). Also removed
FTCALC_USE_LONG_LONG and replaced it with
FT_CONFIG_OPTION_FORCE_INT64.
* builds/win32/freetype.dsp: Updated the Visual C++ project file.
Doesn't create a DLL yet.

View File

@ -131,22 +131,25 @@ std_setup:
@echo ""
@$(COPY) $(CONFIG_RULES) $(CONFIG_MK)
# special case for Dos, Windows, OS/2, where echo "" doesn't work correctly !!
#
dos_setup:
@echo ÿ
@type builds\newline
@echo $(PROJECT_TITLE) build system -- automatic system detection
@echo ÿ
@type builds\newline
@echo The following settings are used:
@echo ÿ
@echo ÿÿplatformÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(PLATFORM)
@echo ÿÿcompilerÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(CC)
@echo ÿÿconfiguration directoryÿÿÿÿÿÿ$(BUILD)
@echo ÿÿconfiguration rulesÿÿÿÿÿÿÿÿÿÿ$(CONFIG_RULES)
@echo ÿ
@type builds\newline
@echo platformÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(PLATFORM)
@echo compilerÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(CC)
@echo configuration directoryÿÿÿÿÿÿ$(BUILD)
@echo configuration rulesÿÿÿÿÿÿÿÿÿÿ$(CONFIG_RULES)
@type builds\newline
@echo If this does not correspond to your system or settings please remove the file
@echo '$(CONFIG_MK)' from this directory then read the INSTALL file for help.
@echo ÿ
@type builds\newline
@echo Otherwise, simply type 'make' again to build the library.
@echo ÿ
@type builds\newline
@$(COPY) $(subst /,\,$(CONFIG_RULES) $(CONFIG_MK)) > nul
# EOF

View File

@ -273,13 +273,14 @@ distclean_project_std: clean_project_std
# The Dos command shell does not support very long list of arguments, so
# we are stuck with wildcards.
#
# don't break the command lines with, this prevents the "del" command from
# working correctly on Win9x
#
clean_project_dos:
-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(OBJ_))*.$O \
$(CLEAN) $(NO_OUTPUT)
-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(OBJ_))*.$O $(CLEAN) $(NO_OUTPUT)
distclean_project_dos: clean_project_dos
-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(PROJECT_LIBRARY)) \
$(DISTCLEAN) $(NO_OUTPUT)
-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(PROJECT_LIBRARY)) $(DISTCLEAN) $(NO_OUTPUT)
.PHONY: remove_config_mk

View File

@ -32,7 +32,7 @@ ifdef BUILD_PROJECT
#
$(PROJECT_LIBRARY): $(OBJECTS_LIST)
ifdef CLEAN_LIBRARY
-$(CLEAN_LIBRARY) $(NO_OUTPUT)
-$(CLEAN_LIBRARY) xx $(NO_OUTPUT)
endif
$(LINK_LIBRARY)

1
builds/newline Normal file
View File

@ -0,0 +1 @@

View File

@ -97,7 +97,12 @@ ifdef check_platform
# GNU make. Similarly, `nul' is created if e.g. `make setup win32' has
# been erroneously used.
#
distclean:
# note: this test is duplicated in "builds/toplevel.mk"
is_unix := $(strip $(wildcard /sbin/init) $(wildcard /hurd/auth))
ifneq ($(is_unix),)
distclean:
$(RM) builds/unix/config.cache
$(RM) builds/unix/config.log
$(RM) builds/unix/config.status
@ -105,6 +110,8 @@ ifdef check_platform
$(RM) builds/unix/unix-cc.mk
$(RM) nul
endif # test is_unix
# IMPORTANT:
#
# `setup' must be defined by the host platform detection rules to create

View File

@ -16,6 +16,7 @@
ifeq ($(PLATFORM),ansi)
# note: this test is duplicated in "builds/toplevel.mk"
is_unix := $(strip $(wildcard /sbin/init) $(wildcard /hurd/auth))
ifneq ($(is_unix),)

View File

@ -127,6 +127,20 @@ FT_BEGIN_HEADER
#error "no 32bit type found -- please check your configuration files"
#endif
/* now, lookup for an integer type that is at least 32 bits */
#if FT_SIZEOF_INT >= 4
typedef int FT_Fast;
typedef unsigned int FT_UFast;
#elif FT_SIZEOF_LONG >= 4
typedef long FT_Fast
typedef unsigned long FT_UFast
#endif
/* determine whether we have a 64-bit int type for platforms without */
/* Autoconf */

View File

@ -436,7 +436,7 @@
/* */
#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>
#define FT_SYNTHESIS_H <freetype/ftsynth.h>
#define FT_CACHE_MANAGER_H <freetype/cache/ftcmanag.h>

213
include/freetype/fttrigon.h Normal file
View File

@ -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__ */

View File

@ -113,8 +113,8 @@ FT_BEGIN_HEADER
FT_Bool force_bold;
FT_Bool round_stem_up;
FT_Short snap_widths [13]; /* reserve one place for the std */
FT_Short snap_heights[13]; /* reserve one place for the std */
FT_Short snap_widths [13]; /* including std width */
FT_Short snap_heights[13]; /* including std height */
FT_Long language_group;
FT_Long password;
@ -136,12 +136,12 @@ FT_BEGIN_HEADER
/* */
typedef enum
{
/* required fields in a FontInfo blend dictionary */
/*# required fields in a FontInfo blend dictionary */
t1_blend_underline_position = 0,
t1_blend_underline_thickness,
t1_blend_italic_angle,
/* required fields in a Private blend dictionary */
/*# required fields in a Private blend dictionary */
t1_blend_blue_values,
t1_blend_other_blues,
t1_blend_standard_width,
@ -154,7 +154,7 @@ FT_BEGIN_HEADER
t1_blend_family_other_blues,
t1_blend_force_bold,
/* never remove */
/*# never remove */
t1_blend_max
} T1_Blend_Flags;

View File

@ -359,7 +359,7 @@
outline->horz_major_dir = ah_dir_right;
}
#else
#else /* !1 */
/* Compute the vertical and horizontal major directions; this is */
/* currently done by inspecting the `ft_outline_reverse_fill' flag. */
@ -374,7 +374,7 @@
outline->horz_major_dir = ah_dir_right;
}
#endif /* 1 */
#endif /* !1 */
outline->x_scale = face->size->metrics.x_scale;
outline->y_scale = face->size->metrics.y_scale;

View File

@ -10,7 +10,7 @@ SubDirHdrs [ FT2_SubDir src base ] ;
if $(FT2_MULTI)
{
_sources = ftcalc ftextend ftlist ftobjs ftstream ftoutln ftnames ;
_sources = ftcalc ftextend ftlist ftobjs ftstream ftoutln ftnames fttrigon ;
}
else
{

View File

@ -21,6 +21,7 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ftcalc.c"
#include "fttrigon.c"
#include "ftobjs.c"
#include "ftstream.c"
#include "ftlist.c"

View File

@ -278,13 +278,13 @@
#else
static void
test_cubic_zero( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos y4,
FT_Fixed u,
FT_Pos* min,
FT_Pos* max )
test_cubic_extrema( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos y4,
FT_Fixed u,
FT_Pos* min,
FT_Pos* max )
{
/* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */
FT_Pos b = y3 - 2*y2 + y1;
@ -373,34 +373,81 @@
int shift = 0;
/* technical explanation of what's happening there */
/* */
/* the following computation is based on the fact that for */
/* any value "y", if "n" is the position of the most */
/* significant bit of "abs(y)" (starting from 0 for the */
/* least significant bit), then y is in the range */
/* */
/* "-2^n..2^n-1" */
/* */
/* we want to shift "a", "b" and "c" concurrently in order */
/* to ensure that they all fit in 8.16 values, which maps */
/* to the integer range "-2^23..2^23-1" */
/* */
/* necessarily, we need to shift "a", "b" and "c" so that */
/* the most significant bit of their absolute values is at */
/* _most_ at position 23 */
/* */
/* we begin by computing "t1" as the bitwise "or" of the */
/* absolute values of "a", "b", "c" */
/* */
t1 = (FT_ULong)((a >= 0) ? a : -a );
t2 = (FT_ULong)((b >= 0) ? b : -b );
t1 |= t2;
t2 = (FT_ULong)((c >= 0) ? c : -c );
t1 |= t2;
/* now, the most significant bit of "t1" is sure to be the */
/* msb of one of "a", "b", "c", depending on which one is */
/* expressed in the greatest integer range.. */
/* */
/* we will now compute the "shift", by shifting "t1" as many */
/* times as necessary to move its msb to position 23. */
/* */
/* this corresponds to a value of t1 that is in the range */
/* 0x40_0000..0x7F_FFFF */
/* */
/* finally, we shift "a", "b" and "c" by the same amount. */
/* this ensure that all values are now in the range */
/* -2^23..2^23, i.e. that they're now expressed as 8.16 */
/* fixed float numbers.. */
/* */
/* this also means that we're using 24 bits of precision */
/* to compute the zeros, independently of the range of */
/* the original polynom coefficients. */
/* */
/* this should ensure reasonably accurate values for the */
/* zeros. Note that the latter are only expressed with */
/* 16 bits when computing the extrema (the zeros need to */
/* be in 0..1 exclusive to be considered part of the arc) */
/* */
if ( t1 == 0 ) /* all coefficients are 0! */
return;
if ( t1 > 0x7FFFFFL )
if ( t1 > 0x7FFFFFUL )
{
do
{
shift++;
t1 >>= 1;
} while ( t1 > 0x7FFFFFL );
} while ( t1 > 0x7FFFFFUL );
/* losing some bits of precision, but we'll use 24 of them */
/* for the computation anyway.. */
a >>= shift;
b >>= shift;
c >>= shift;
}
else if ( t1 < 0x400000L )
else if ( t1 < 0x400000UL )
{
do
{
shift++;
t1 <<= 1;
} while ( t1 < 0x400000L );
} while ( t1 < 0x400000UL );
a <<= shift;
b <<= shift;
@ -414,7 +461,7 @@
if ( b != 0 )
{
t = - FT_DivFix( c, b ) / 2;
test_cubic_zero( y1, y2, y3, y4, t, min, max );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
}
else
@ -428,17 +475,17 @@
{
/* there is a single split point at -b/a */
t = - FT_DivFix( b, a );
test_cubic_zero( y1, y2, y3, y4, t, min, max );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
else
{
/* there are two solutions; we need to filter them though */
d = FT_SqrtFixed( (FT_Int32)d );
t = - FT_DivFix( b - d, a );
test_cubic_zero( y1, y2, y3, y4, t, min, max );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
t = - FT_DivFix( b + d, a );
test_cubic_zero( y1, y2, y3, y4, t, min, max );
test_cubic_extrema( y1, y2, y3, y4, t, min, max );
}
}
}

View File

@ -1240,14 +1240,15 @@
goto Success;
if ( error != FT_Err_Unknown_File_Format )
goto Fail;
goto Fail2;
}
}
ft_done_stream( &stream, external_stream );
/* no driver is able to handle this format */
error = FT_Err_Unknown_File_Format;
Fail2:
ft_done_stream( &stream, external_stream );
goto Fail;
}

404
src/base/fttrigon.c Normal file
View File

@ -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;
}

View File

@ -33,6 +33,7 @@ BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base
# ftsystem, ftinit, and ftdebug are handled by freetype.mk
#
BASE_SRC := $(BASE_)ftcalc.c \
$(BASE_)fttrigon.c \
$(BASE_)ftextend.c \
$(BASE_)ftlist.c \
$(BASE_)ftobjs.c \

78
src/tools/cordic.py Normal file
View File

@ -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 ""

View File

@ -25,7 +25,7 @@
# - David
#
import fileinput, sys, os, string, glob, getopt
import fileinput, sys, os, time, string, glob, getopt
# The Project's title. This can be overridden from the command line with
# the options "-t" or "--title".
@ -216,6 +216,11 @@ def check_output( ):
output_dir = None
def compute_time_html( ):
global html_footer
time_string = time.asctime( time.localtime( time.time() ) )
html_footer = "<p><center><font size=""-2"">generated on " + time_string + "</font></p></center>" + html_footer
# The FreeType 2 reference is extracted from the source files. These
# contain various comment blocks that follow one of the following formats:
#
@ -1628,6 +1633,7 @@ def main( argv ):
html_header = html_header_1 + project_title + html_header_2 + project_title + html_header_3
check_output( )
compute_time_html()
# we begin by simply building a list of DocBlock elements
#

160
src/tools/test_bbox.c Normal file
View File

@ -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;
}

236
src/tools/test_trig.c Normal file
View File

@ -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;
}