* include/freetype/internal/tttypes.h, src/autofit/afangles.c,
src/autofit/afcjk.c, src/autofit/afhints.c, src/autofit/aflatin.c, src/autofit/aftypes.h, src/base/ftcalc.c, src/base/ftoutln.c, src/gzip/ftgzip.c, src/psaux/psconv.c, src/truetype/ttgload.c, src/type1/t1gload.c: this is a major patch used to drastically improve the performance of loading glyphs. This both speeds up loading the glypn vector themselves and the auto-fitter. note that we've started using inline assembler with GCC to implement FT_MulFix, given that this function is so damn important for the engine's performance. the resulting speed-up is about 25%.
This commit is contained in:
parent
dc3ff31c3f
commit
281679de85
23
ChangeLog
23
ChangeLog
|
@ -1,5 +1,22 @@
|
||||||
2006-05-17 David Turner <david@freetype.org>
|
2006-05-17 David Turner <david@freetype.org>
|
||||||
|
|
||||||
|
* include/freetype/internal/tttypes.h, src/autofit/afangles.c,
|
||||||
|
src/autofit/afcjk.c, src/autofit/afhints.c, src/autofit/aflatin.c,
|
||||||
|
src/autofit/aftypes.h, src/base/ftcalc.c, src/base/ftoutln.c,
|
||||||
|
src/gzip/ftgzip.c, src/psaux/psconv.c, src/truetype/ttgload.c,
|
||||||
|
src/type1/t1gload.c:
|
||||||
|
|
||||||
|
this is a major patch used to drastically improve the performance
|
||||||
|
of loading glyphs. This both speeds up loading the glypn vector
|
||||||
|
themselves and the auto-fitter.
|
||||||
|
|
||||||
|
note that we've started using inline assembler with GCC to
|
||||||
|
implement FT_MulFix, given that this function is so damn
|
||||||
|
important for the engine's performance.
|
||||||
|
|
||||||
|
the resulting speed-up is about 25%.
|
||||||
|
|
||||||
|
|
||||||
* src/ftccmap.c (FTC_CMapCache_Lookup): changed the threshold
|
* src/ftccmap.c (FTC_CMapCache_Lookup): changed the threshold
|
||||||
used to detect rogue clients from 4 to 16. This is to prevent
|
used to detect rogue clients from 4 to 16. This is to prevent
|
||||||
some segmentation faults with fonts like KozMinProVI-Regular.otf
|
some segmentation faults with fonts like KozMinProVI-Regular.otf
|
||||||
|
@ -8,7 +25,7 @@
|
||||||
2007-05-17 Werner Lemberg <wl@gnu.org>
|
2007-05-17 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
* src/cff/cffload.c (cff_font_done): Deallocate subfont array. This
|
* src/cff/cffload.c (cff_font_done): Deallocate subfont array. This
|
||||||
fixes the first part of Savannah bug #16590.
|
fixes the first part of Savannah bug #16590.
|
||||||
|
|
||||||
2006-05-16 Werner Lemberg <wl@gnu.org>
|
2006-05-16 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
|
@ -52,8 +69,8 @@
|
||||||
Update handling of re_italic and re_bold.
|
Update handling of re_italic and re_bold.
|
||||||
|
|
||||||
2006-05-11 Masatake YAMATO <jet@gyve.org>
|
2006-05-11 Masatake YAMATO <jet@gyve.org>
|
||||||
|
|
||||||
* builds/unix/ftsystem.c (FT_Stream_Open): Check errno only if
|
* builds/unix/ftsystem.c (FT_Stream_Open): Check errno only if
|
||||||
read system call returns -1.
|
read system call returns -1.
|
||||||
Remove a redundant parenthesis.
|
Remove a redundant parenthesis.
|
||||||
|
|
||||||
|
|
|
@ -1521,6 +1521,10 @@ FT_BEGIN_HEADER
|
||||||
FT_Vector pp3;
|
FT_Vector pp3;
|
||||||
FT_Vector pp4;
|
FT_Vector pp4;
|
||||||
|
|
||||||
|
/* since version 2.2.1 */
|
||||||
|
FT_Byte* cursor;
|
||||||
|
FT_Byte* limit;
|
||||||
|
|
||||||
} TT_LoaderRec;
|
} TT_LoaderRec;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,94 @@
|
||||||
#include "aftypes.h"
|
#include "aftypes.h"
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
FT_LOCAL_DEF( FT_Int )
|
||||||
|
af_corner_is_flat( FT_Pos x_in,
|
||||||
|
FT_Pos y_in,
|
||||||
|
FT_Pos x_out,
|
||||||
|
FT_Pos y_out )
|
||||||
|
{
|
||||||
|
FT_Pos ax = x_in;
|
||||||
|
FT_Pos ay = y_in;
|
||||||
|
|
||||||
|
FT_Pos d_in, d_out, d_corner;
|
||||||
|
|
||||||
|
if ( ax < 0 ) ax = -ax;
|
||||||
|
if ( ay < 0 ) ay = -ay;
|
||||||
|
d_in = ax + ay;
|
||||||
|
|
||||||
|
ax = x_out; if ( ax < 0 ) ax = -ax;
|
||||||
|
ay = y_out; if ( ay < 0 ) ay = -ay;
|
||||||
|
d_out = ax+ay;
|
||||||
|
|
||||||
|
ax = x_out + x_in; if ( ax < 0 ) ax = -ax;
|
||||||
|
ay = y_out + y_in; if ( ay < 0 ) ay = -ay;
|
||||||
|
d_corner = ax+ay;
|
||||||
|
|
||||||
|
return ( d_in + d_out - d_corner ) < (d_corner >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_LOCAL_DEF( FT_Int )
|
||||||
|
af_corner_orientation( FT_Pos x_in,
|
||||||
|
FT_Pos y_in,
|
||||||
|
FT_Pos x_out,
|
||||||
|
FT_Pos y_out )
|
||||||
|
{
|
||||||
|
FT_Pos delta;
|
||||||
|
|
||||||
|
delta = x_in*y_out - y_in*x_out;
|
||||||
|
|
||||||
|
if ( delta == 0 )
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1 - 2*(delta < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* we're not using af_angle_atan anymore, but we keep the source
|
||||||
|
* code below just in case :-)
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
/* the trick here is to realize that we don't need an very accurate
|
||||||
|
* angle approximation. We're going to use the result of af_angle_atan
|
||||||
|
* to only compare the sign of angle differences, or see if its magnitude
|
||||||
|
* is very small.
|
||||||
|
*
|
||||||
|
* the approximation (dy*PI/(|dx|+|dy|))) should be enough, and much
|
||||||
|
* faster to compute.
|
||||||
|
*/
|
||||||
|
FT_LOCAL_DEF( AF_Angle )
|
||||||
|
af_angle_atan( FT_Fixed dx,
|
||||||
|
FT_Fixed dy )
|
||||||
|
{
|
||||||
|
AF_Angle angle;
|
||||||
|
FT_Fixed ax = dx;
|
||||||
|
FT_Fixed ay = dy;
|
||||||
|
|
||||||
|
if ( ax < 0 ) ax = -ax;
|
||||||
|
if ( ay < 0 ) ay = -ay;
|
||||||
|
|
||||||
|
ax += ay;
|
||||||
|
|
||||||
|
if ( ax == 0 )
|
||||||
|
angle = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angle = (AF_ANGLE_PI2*dy)/(ax+ay);
|
||||||
|
if ( dx < 0 )
|
||||||
|
{
|
||||||
|
if ( angle >= 0 )
|
||||||
|
angle = AF_ANGLE_PI - angle;
|
||||||
|
else
|
||||||
|
angle = -AF_ANGLE_PI - angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
/* the following table has been automatically generated with */
|
/* the following table has been automatically generated with */
|
||||||
/* the `mather.py' Python script */
|
/* the `mather.py' Python script */
|
||||||
|
@ -124,224 +211,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else /* 0 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 8
|
|
||||||
|
|
||||||
static const FT_Fixed
|
|
||||||
af_angle_arctan_table[9] =
|
|
||||||
{
|
|
||||||
90, 64, 38, 20, 10, 5, 3, 1, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static FT_Int
|
|
||||||
af_angle_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
|
|
||||||
af_angle_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 = AF_ANGLE_PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( y > 0 )
|
|
||||||
theta = -theta;
|
|
||||||
|
|
||||||
arctanptr = af_angle_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 < AF_TRIG_MAX_ITERS );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* round theta */
|
|
||||||
if ( theta >= 0 )
|
|
||||||
theta = FT_PAD_ROUND( theta, 2 );
|
|
||||||
else
|
|
||||||
theta = -FT_PAD_ROUND( -theta, 2 );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec->x = x;
|
|
||||||
vec->y = theta;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* cf. documentation in fttrigon.h */
|
|
||||||
|
|
||||||
FT_LOCAL_DEF( AF_Angle )
|
|
||||||
af_angle_atan( FT_Fixed dx,
|
|
||||||
FT_Fixed dy )
|
|
||||||
{
|
|
||||||
FT_Vector v;
|
|
||||||
|
|
||||||
|
|
||||||
if ( dx == 0 && dy == 0 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
v.x = dx;
|
|
||||||
v.y = dy;
|
|
||||||
af_angle_prenorm( &v );
|
|
||||||
af_angle_pseudo_polarize( &v );
|
|
||||||
|
|
||||||
return v.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL_DEF( AF_Angle )
|
|
||||||
af_angle_diff( AF_Angle angle1,
|
|
||||||
AF_Angle angle2 )
|
|
||||||
{
|
|
||||||
AF_Angle delta = angle2 - angle1;
|
|
||||||
|
|
||||||
|
|
||||||
delta %= AF_ANGLE_2PI;
|
|
||||||
if ( delta < 0 )
|
|
||||||
delta += AF_ANGLE_2PI;
|
|
||||||
|
|
||||||
if ( delta > AF_ANGLE_PI )
|
|
||||||
delta -= AF_ANGLE_2PI;
|
|
||||||
|
|
||||||
return delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL_DEF( void )
|
FT_LOCAL_DEF( void )
|
||||||
af_sort_pos( FT_UInt count,
|
af_sort_pos( FT_UInt count,
|
||||||
|
@ -389,45 +260,4 @@ for n in r:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#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 /* TEST */
|
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
|
|
@ -1437,7 +1437,9 @@
|
||||||
|
|
||||||
static const AF_Script_UniRangeRec af_cjk_uniranges[] =
|
static const AF_Script_UniRangeRec af_cjk_uniranges[] =
|
||||||
{
|
{
|
||||||
{ 0x0100, 0xFFFF },
|
#if 0
|
||||||
|
{ 0x0100, 0xFFFF }, /* why ?? */
|
||||||
|
#endif
|
||||||
{ 0x2E80, 0x2EFF }, /* CJK Radicals Supplement */
|
{ 0x2E80, 0x2EFF }, /* CJK Radicals Supplement */
|
||||||
{ 0x2F00, 0x2FDF }, /* Kangxi Radicals */
|
{ 0x2F00, 0x2FDF }, /* Kangxi Radicals */
|
||||||
{ 0x3000, 0x303F }, /* CJK Symbols and Punctuation */
|
{ 0x3000, 0x303F }, /* CJK Symbols and Punctuation */
|
||||||
|
|
|
@ -53,7 +53,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
segment = axis->segments + axis->num_segments++;
|
segment = axis->segments + axis->num_segments++;
|
||||||
|
#if 0
|
||||||
FT_ZERO( segment );
|
FT_ZERO( segment );
|
||||||
|
#endif
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
*asegment = segment;
|
*asegment = segment;
|
||||||
|
@ -272,54 +274,46 @@
|
||||||
FT_Pos dy )
|
FT_Pos dy )
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
AF_Direction dir = AF_DIR_NONE;
|
FT_Pos ll, ss; /* long and short arm lengths */
|
||||||
|
AF_Direction dir; /* candidate direction */
|
||||||
|
|
||||||
|
if ( dy >= dx )
|
||||||
/* atan(1/12) == 4.7 degrees */
|
|
||||||
|
|
||||||
if ( dx < 0 )
|
|
||||||
{
|
{
|
||||||
if ( dy < 0 )
|
if ( dy >= -dx )
|
||||||
{
|
{
|
||||||
if ( -dx * 12 < -dy )
|
dir = AF_DIR_UP;
|
||||||
dir = AF_DIR_DOWN;
|
ll = dy;
|
||||||
|
ss = dx;
|
||||||
else if ( -dy * 12 < -dx )
|
|
||||||
dir = AF_DIR_LEFT;
|
|
||||||
}
|
}
|
||||||
else /* dy >= 0 */
|
else
|
||||||
{
|
{
|
||||||
if ( -dx * 12 < dy )
|
dir = AF_DIR_LEFT;
|
||||||
dir = AF_DIR_UP;
|
ll = -dx;
|
||||||
|
ss = dy;
|
||||||
else if ( dy * 12 < -dx )
|
|
||||||
dir = AF_DIR_LEFT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* dx >= 0 */
|
else /* dy < dx */
|
||||||
{
|
{
|
||||||
if ( dy < 0 )
|
if ( dy >= -dx )
|
||||||
{
|
{
|
||||||
if ( dx * 12 < -dy )
|
dir = AF_DIR_RIGHT;
|
||||||
dir = AF_DIR_DOWN;
|
ll = dx;
|
||||||
|
ss = dy;
|
||||||
else if ( -dy * 12 < dx )
|
|
||||||
dir = AF_DIR_RIGHT;
|
|
||||||
}
|
}
|
||||||
else /* dy >= 0 */
|
else
|
||||||
{
|
{
|
||||||
if ( dx * 12 < dy )
|
dir = AF_DIR_DOWN;
|
||||||
dir = AF_DIR_UP;
|
ll = dy;
|
||||||
|
ss = dx;
|
||||||
else if ( dy * 12 < dx )
|
|
||||||
dir = AF_DIR_RIGHT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ss *= 12;
|
||||||
|
if ( ll <= FT_ABS(ss) )
|
||||||
|
dir = AF_DIR_NONE;
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
|
|
||||||
#else /* 0 */
|
#else /* 0 */
|
||||||
|
|
||||||
AF_Direction dir;
|
AF_Direction dir;
|
||||||
FT_Pos ax = FT_ABS( dx );
|
FT_Pos ax = FT_ABS( dx );
|
||||||
FT_Pos ay = FT_ABS( dy );
|
FT_Pos ay = FT_ABS( dy );
|
||||||
|
@ -341,13 +335,125 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
|
|
||||||
#endif /* 0 */
|
#endif /* 0 */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* compute all inflex points in a given glyph */
|
/* compute all inflex points in a given glyph */
|
||||||
|
#if 1
|
||||||
|
static void
|
||||||
|
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
|
||||||
|
{
|
||||||
|
AF_Point* contour = hints->contours;
|
||||||
|
AF_Point* contour_limit = contour + hints->num_contours;
|
||||||
|
|
||||||
|
|
||||||
|
/* do each contour separately */
|
||||||
|
for ( ; contour < contour_limit; contour++ )
|
||||||
|
{
|
||||||
|
AF_Point point = contour[0];
|
||||||
|
AF_Point first = point;
|
||||||
|
AF_Point start = point;
|
||||||
|
AF_Point end = point;
|
||||||
|
AF_Point before;
|
||||||
|
AF_Point after;
|
||||||
|
FT_Pos in_x, in_y, out_x, out_y;
|
||||||
|
AF_Angle orient_prev, orient_cur;
|
||||||
|
FT_Int finished = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* compute first segment in contour */
|
||||||
|
first = point;
|
||||||
|
|
||||||
|
start = end = first;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
end = end->next;
|
||||||
|
if ( end == first )
|
||||||
|
goto Skip;
|
||||||
|
|
||||||
|
in_x = end->fx - start->fx;
|
||||||
|
in_y = end->fy - start->fy;
|
||||||
|
|
||||||
|
} while ( in_x == 0 && in_y == 0 );
|
||||||
|
|
||||||
|
/* extend the segment start whenever possible */
|
||||||
|
before = start;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
start = before;
|
||||||
|
before = before->prev;
|
||||||
|
if ( before == first )
|
||||||
|
goto Skip;
|
||||||
|
|
||||||
|
out_x = start->fx - before->fx;
|
||||||
|
out_y = start->fy - before->fy;
|
||||||
|
|
||||||
|
} while ( out_x == 0 && out_y == 0 );
|
||||||
|
|
||||||
|
orient_prev = af_corner_orientation( in_x, in_y, out_x, out_y );
|
||||||
|
|
||||||
|
} while ( orient_prev == 0 );
|
||||||
|
|
||||||
|
first = start;
|
||||||
|
|
||||||
|
in_x = out_x;
|
||||||
|
in_y = out_y;
|
||||||
|
|
||||||
|
/* now, process all segments in the contour */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* first, extend current segment's end whenever possible */
|
||||||
|
after = end;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
end = after;
|
||||||
|
after = after->next;
|
||||||
|
if ( after == first )
|
||||||
|
finished = 1;
|
||||||
|
|
||||||
|
out_x = after->fx - end->fx;
|
||||||
|
out_y = after->fy - end->fy;
|
||||||
|
|
||||||
|
} while ( out_x == 0 && out_y == 0 );
|
||||||
|
|
||||||
|
orient_cur = af_corner_orientation( in_x, in_y, out_x, out_y );
|
||||||
|
|
||||||
|
} while ( orient_cur == 0 );
|
||||||
|
|
||||||
|
if ( ( orient_prev + orient_cur ) == 0 )
|
||||||
|
{
|
||||||
|
/* we have an inflection point here */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
start->flags |= AF_FLAG_INFLECTION;
|
||||||
|
start = start->next;
|
||||||
|
|
||||||
|
} while ( start != end );
|
||||||
|
|
||||||
|
start->flags |= AF_FLAG_INFLECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = end;
|
||||||
|
end = after;
|
||||||
|
|
||||||
|
orient_prev = orient_cur;
|
||||||
|
in_x = out_x;
|
||||||
|
in_y = out_y;
|
||||||
|
|
||||||
|
} while ( !finished );
|
||||||
|
|
||||||
|
Skip:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* old code */
|
||||||
static void
|
static void
|
||||||
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
|
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
|
||||||
{
|
{
|
||||||
|
@ -454,6 +560,7 @@
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* old code */
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL_DEF( void )
|
FT_LOCAL_DEF( void )
|
||||||
|
@ -702,6 +809,14 @@
|
||||||
}
|
}
|
||||||
else if ( point->out_dir == point->in_dir )
|
else if ( point->out_dir == point->in_dir )
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
if ( point->out_dir != AF_DIR_NONE )
|
||||||
|
goto Is_Weak_Point;
|
||||||
|
|
||||||
|
if ( af_corner_is_flat( in_x, in_y, out_x, out_y ) )
|
||||||
|
goto Is_Weak_Point;
|
||||||
|
|
||||||
|
#else /* old code */
|
||||||
AF_Angle angle_in, angle_out, delta;
|
AF_Angle angle_in, angle_out, delta;
|
||||||
|
|
||||||
|
|
||||||
|
@ -715,6 +830,7 @@
|
||||||
|
|
||||||
if ( delta < 2 && delta > -2 )
|
if ( delta < 2 && delta > -2 )
|
||||||
goto Is_Weak_Point;
|
goto Is_Weak_Point;
|
||||||
|
#endif /* old code */
|
||||||
}
|
}
|
||||||
else if ( point->in_dir == -point->out_dir )
|
else if ( point->in_dir == -point->out_dir )
|
||||||
goto Is_Weak_Point;
|
goto Is_Weak_Point;
|
||||||
|
@ -1152,7 +1268,7 @@
|
||||||
AF_Point points = hints->points;
|
AF_Point points = hints->points;
|
||||||
AF_Point points_limit = points + hints->num_points;
|
AF_Point points_limit = points + hints->num_points;
|
||||||
AF_Point point;
|
AF_Point point;
|
||||||
|
|
||||||
|
|
||||||
if ( dim == AF_DIMENSION_HORZ )
|
if ( dim == AF_DIMENSION_HORZ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -590,6 +590,7 @@
|
||||||
FT_Memory memory = hints->memory;
|
FT_Memory memory = hints->memory;
|
||||||
FT_Error error = AF_Err_Ok;
|
FT_Error error = AF_Err_Ok;
|
||||||
AF_Segment segment = NULL;
|
AF_Segment segment = NULL;
|
||||||
|
AF_SegmentRec seg0;
|
||||||
AF_Point* contour = hints->contours;
|
AF_Point* contour = hints->contours;
|
||||||
AF_Point* contour_limit = contour + hints->num_contours;
|
AF_Point* contour_limit = contour + hints->num_contours;
|
||||||
AF_Direction major_dir, segment_dir;
|
AF_Direction major_dir, segment_dir;
|
||||||
|
@ -601,6 +602,10 @@
|
||||||
FT_Pos max_coord = -32000;
|
FT_Pos max_coord = -32000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FT_ZERO( &seg0 );
|
||||||
|
seg0.score = 32000;
|
||||||
|
seg0.flags = AF_EDGE_NORMAL;
|
||||||
|
|
||||||
major_dir = (AF_Direction)FT_ABS( axis->major_dir );
|
major_dir = (AF_Direction)FT_ABS( axis->major_dir );
|
||||||
segment_dir = major_dir;
|
segment_dir = major_dir;
|
||||||
|
|
||||||
|
@ -742,15 +747,12 @@
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
segment[0] = seg0;
|
||||||
segment->dir = (FT_Char)segment_dir;
|
segment->dir = (FT_Char)segment_dir;
|
||||||
segment->flags = AF_EDGE_NORMAL;
|
|
||||||
min_pos = max_pos = point->u;
|
min_pos = max_pos = point->u;
|
||||||
segment->first = point;
|
segment->first = point;
|
||||||
segment->last = point;
|
segment->last = point;
|
||||||
segment->contour = contour;
|
segment->contour = contour;
|
||||||
segment->score = 32000;
|
|
||||||
segment->len = 0;
|
|
||||||
segment->link = NULL;
|
|
||||||
on_edge = 1;
|
on_edge = 1;
|
||||||
|
|
||||||
#ifdef AF_HINT_METRICS
|
#ifdef AF_HINT_METRICS
|
||||||
|
@ -810,14 +812,11 @@
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
segment[0] = seg0;
|
||||||
segment->dir = segment_dir;
|
segment->dir = segment_dir;
|
||||||
segment->flags = AF_EDGE_NORMAL;
|
|
||||||
segment->first = min_point;
|
segment->first = min_point;
|
||||||
segment->last = min_point;
|
segment->last = min_point;
|
||||||
segment->pos = min_pos;
|
segment->pos = min_pos;
|
||||||
segment->score = 32000;
|
|
||||||
segment->len = 0;
|
|
||||||
segment->link = NULL;
|
|
||||||
|
|
||||||
segment = NULL;
|
segment = NULL;
|
||||||
}
|
}
|
||||||
|
@ -830,14 +829,11 @@
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
segment[0] = seg0;
|
||||||
segment->dir = segment_dir;
|
segment->dir = segment_dir;
|
||||||
segment->flags = AF_EDGE_NORMAL;
|
|
||||||
segment->first = max_point;
|
segment->first = max_point;
|
||||||
segment->last = max_point;
|
segment->last = max_point;
|
||||||
segment->pos = max_pos;
|
segment->pos = max_pos;
|
||||||
segment->score = 32000;
|
|
||||||
segment->len = 0;
|
|
||||||
segment->link = NULL;
|
|
||||||
|
|
||||||
segment = NULL;
|
segment = NULL;
|
||||||
}
|
}
|
||||||
|
@ -926,7 +922,6 @@
|
||||||
|
|
||||||
if ( seg2 )
|
if ( seg2 )
|
||||||
{
|
{
|
||||||
seg2->num_linked++;
|
|
||||||
if ( seg2->link != seg1 )
|
if ( seg2->link != seg1 )
|
||||||
{
|
{
|
||||||
seg1->link = 0;
|
seg1->link = 0;
|
||||||
|
|
|
@ -118,6 +118,7 @@ FT_BEGIN_HEADER
|
||||||
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
|
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
* compute the angle of a given 2-D vector
|
* compute the angle of a given 2-D vector
|
||||||
*/
|
*/
|
||||||
|
@ -126,7 +127,6 @@ FT_BEGIN_HEADER
|
||||||
FT_Pos dy );
|
FT_Pos dy );
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
/*
|
||||||
* compute `angle2 - angle1'; the result is always within
|
* compute `angle2 - angle1'; the result is always within
|
||||||
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
|
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
|
||||||
|
@ -137,6 +137,27 @@ FT_BEGIN_HEADER
|
||||||
#endif /* 0 */
|
#endif /* 0 */
|
||||||
|
|
||||||
|
|
||||||
|
/* return TRUE if a corner is flat, or nearly flat, this is equivalent
|
||||||
|
* to say that the angle difference between the 'in' and 'out' vectors is
|
||||||
|
* very small
|
||||||
|
*/
|
||||||
|
FT_LOCAL( FT_Int )
|
||||||
|
af_corner_is_flat( FT_Pos x_in,
|
||||||
|
FT_Pos y_in,
|
||||||
|
FT_Pos x_out,
|
||||||
|
FT_Pos y_out );
|
||||||
|
|
||||||
|
/* return a value that can be -1, 0 or +1 depending on the orientation
|
||||||
|
* of a given corner. We're using the Cartesian coordinate system,
|
||||||
|
* with positive Ys going upwards. The function returns +1 when
|
||||||
|
* the corner turns to the left, -1 to the right, and 0 for undecided
|
||||||
|
*/
|
||||||
|
FT_LOCAL( FT_Int )
|
||||||
|
af_corner_orientation( FT_Pos x_in,
|
||||||
|
FT_Pos y_in,
|
||||||
|
FT_Pos x_out,
|
||||||
|
FT_Pos y_out );
|
||||||
|
|
||||||
#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
|
#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
|
||||||
FT_BEGIN_STMNT \
|
FT_BEGIN_STMNT \
|
||||||
AF_Angle _delta = (angle2) - (angle1); \
|
AF_Angle _delta = (angle2) - (angle1); \
|
||||||
|
|
|
@ -396,7 +396,29 @@
|
||||||
FT_MulFix( FT_Long a,
|
FT_MulFix( FT_Long a,
|
||||||
FT_Long b )
|
FT_Long b )
|
||||||
{
|
{
|
||||||
#if 1
|
/* let's use inline assembly to speed things a bit */
|
||||||
|
#if defined(__GNUC__) && defined(i386)
|
||||||
|
|
||||||
|
FT_Long result;
|
||||||
|
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"imul %%edx\n"
|
||||||
|
"movl %%edx, %%ecx\n"
|
||||||
|
"sarl $31, %%ecx\n"
|
||||||
|
"addl $0x8000, %%ecx\n"
|
||||||
|
"addl %%ecx, %%eax\n"
|
||||||
|
"adcl $0, %%edx\n"
|
||||||
|
"shrl $16, %%eax\n"
|
||||||
|
"shll $16, %%edx\n"
|
||||||
|
"addl %%edx, %%eax\n"
|
||||||
|
"mov %%eax, %0\n"
|
||||||
|
: "=r"(result)
|
||||||
|
: "a"(a), "d"(b)
|
||||||
|
: "%ecx"
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
#elif 1
|
||||||
FT_Long sa, sb;
|
FT_Long sa, sb;
|
||||||
FT_ULong ua, ub;
|
FT_ULong ua, ub;
|
||||||
|
|
||||||
|
|
|
@ -732,7 +732,7 @@
|
||||||
return ( n % 2 );
|
return ( n % 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static FT_Bool
|
static FT_Bool
|
||||||
ft_contour_enclosed( FT_Outline* outline,
|
ft_contour_enclosed( FT_Outline* outline,
|
||||||
FT_UShort c )
|
FT_UShort c )
|
||||||
|
@ -1012,11 +1012,25 @@
|
||||||
++next;
|
++next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
{
|
||||||
|
FT_Pos dx1 = prev->x - xmin_point->x;
|
||||||
|
FT_Pos dy1 = prev->y - xmin_point->y;
|
||||||
|
FT_Pos dx2 = next->x - xmin_point->x;
|
||||||
|
FT_Pos dy2 = next->y - xmin_point->y;
|
||||||
|
|
||||||
|
if ( dy1*dx2 > dy2*dx1 )
|
||||||
|
return FT_ORIENTATION_POSTSCRIPT;
|
||||||
|
else
|
||||||
|
return FT_ORIENTATION_TRUETYPE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
|
if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
|
||||||
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
|
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
|
||||||
return FT_ORIENTATION_POSTSCRIPT;
|
return FT_ORIENTATION_POSTSCRIPT;
|
||||||
else
|
else
|
||||||
return FT_ORIENTATION_TRUETYPE;
|
return FT_ORIENTATION_TRUETYPE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -554,6 +554,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_ULong
|
||||||
|
ft_gzip_get_uncompressed_size( FT_Stream stream )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
FT_ULong old_pos;
|
||||||
|
FT_ULong result = 0;
|
||||||
|
|
||||||
|
old_pos = stream->pos;
|
||||||
|
if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
|
||||||
|
{
|
||||||
|
result = (FT_ULong)FT_Stream_ReadLong( stream, &error );
|
||||||
|
if ( error )
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
FT_Stream_Seek( stream, old_pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_EXPORT_DEF( FT_Error )
|
FT_EXPORT_DEF( FT_Error )
|
||||||
FT_Stream_OpenGzip( FT_Stream stream,
|
FT_Stream_OpenGzip( FT_Stream stream,
|
||||||
FT_Stream source )
|
FT_Stream source )
|
||||||
|
@ -586,6 +607,47 @@
|
||||||
stream->descriptor.pointer = zip;
|
stream->descriptor.pointer = zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ok, here's a trick to try to dramatically improve the performance
|
||||||
|
* of dealing with small files. If the original stream size is less
|
||||||
|
* than a certain threshold, we try to load the whole font file in
|
||||||
|
* memory. this saves us from the 32KB buffer needed to inflate the
|
||||||
|
* file anyway, plus the two 4KB intermediate input/output buffers
|
||||||
|
* used in the FT_GZipFile structure.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );
|
||||||
|
|
||||||
|
if ( zip_size != 0 && zip_size < 40*1024 )
|
||||||
|
{
|
||||||
|
FT_Byte* zip_buff;
|
||||||
|
|
||||||
|
if ( !FT_ALLOC( zip_buff, zip_size ) )
|
||||||
|
{
|
||||||
|
FT_ULong count;
|
||||||
|
|
||||||
|
count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
|
||||||
|
if ( count == zip_size )
|
||||||
|
{
|
||||||
|
ft_gzip_file_done( zip );
|
||||||
|
FT_FREE( zip );
|
||||||
|
|
||||||
|
stream->descriptor.pointer = NULL;
|
||||||
|
|
||||||
|
stream->size = zip_size;
|
||||||
|
stream->pos = 0;
|
||||||
|
stream->base = zip_buff;
|
||||||
|
stream->read = NULL;
|
||||||
|
stream->close = ft_gzip_stream_close;
|
||||||
|
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
ft_gzip_file_io( zip, 0, NULL, 0 );
|
||||||
|
FT_FREE( zip_buff );
|
||||||
|
}
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stream->size = 0x7FFFFFFFL; /* don't know the real size! */
|
stream->size = 0x7FFFFFFFL; /* don't know the real size! */
|
||||||
stream->pos = 0;
|
stream->pos = 0;
|
||||||
stream->base = 0;
|
stream->base = 0;
|
||||||
|
|
|
@ -331,11 +331,48 @@
|
||||||
FT_UInt n )
|
FT_UInt n )
|
||||||
{
|
{
|
||||||
FT_Byte* p;
|
FT_Byte* p;
|
||||||
FT_UInt r = 0;
|
FT_UInt r = 0;
|
||||||
|
FT_UInt w = 0;
|
||||||
|
FT_UInt pad = 0x01;
|
||||||
|
|
||||||
|
|
||||||
n *= 2;
|
n *= 2;
|
||||||
for ( p = *cursor; r < n && p < limit; p++ )
|
#if 1
|
||||||
|
p = *cursor;
|
||||||
|
if ( n > (FT_UInt)(limit-p) )
|
||||||
|
n = (FT_UInt)(limit - p);
|
||||||
|
|
||||||
|
/* we try to process two nibbles at a time to be as fast as possible
|
||||||
|
*/
|
||||||
|
for ( ; r < n; r++ )
|
||||||
|
{
|
||||||
|
FT_UInt c = p[r];
|
||||||
|
|
||||||
|
if ( IS_PS_SPACE(c) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( c OP 0x80 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
c = ft_char_table[ c & 0x7F ];
|
||||||
|
if ( (unsigned)c >= 16 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
pad = (pad << 4) | c;
|
||||||
|
if ( pad & 0x100 )
|
||||||
|
{
|
||||||
|
buffer[w++] = (FT_Byte)pad;
|
||||||
|
pad = 0x01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pad != 0x01 )
|
||||||
|
buffer[w++] = (FT_Byte)(pad << 4);
|
||||||
|
|
||||||
|
*cursor = p+r;
|
||||||
|
return w;
|
||||||
|
#else
|
||||||
|
for ( r = 0; r < n; r++ )
|
||||||
{
|
{
|
||||||
FT_Char c;
|
FT_Char c;
|
||||||
|
|
||||||
|
@ -348,10 +385,10 @@
|
||||||
|
|
||||||
c = ft_char_table[*p & 0x7f];
|
c = ft_char_table[*p & 0x7f];
|
||||||
|
|
||||||
if ( c < 0 || c >= 16 )
|
if ( (unsigned)c >= 16 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( r % 2 )
|
if ( r & 1 )
|
||||||
{
|
{
|
||||||
*buffer = (FT_Byte)(*buffer + c);
|
*buffer = (FT_Byte)(*buffer + c);
|
||||||
buffer++;
|
buffer++;
|
||||||
|
@ -365,6 +402,7 @@
|
||||||
*cursor = p;
|
*cursor = p;
|
||||||
|
|
||||||
return ( r + 1 ) / 2;
|
return ( r + 1 ) / 2;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -377,9 +415,25 @@
|
||||||
{
|
{
|
||||||
FT_Byte* p;
|
FT_Byte* p;
|
||||||
FT_UInt r;
|
FT_UInt r;
|
||||||
FT_UShort s = *seed;
|
FT_UInt s = *seed;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
p = *cursor;
|
||||||
|
if ( n > (FT_UInt)(limit - p) )
|
||||||
|
n = (FT_UInt)(limit - p);
|
||||||
|
|
||||||
|
for ( r = 0; r < n; r++ )
|
||||||
|
{
|
||||||
|
FT_UInt val = p[r];
|
||||||
|
FT_UInt b = ( val ^ (s >> 8) );
|
||||||
|
|
||||||
|
s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
|
||||||
|
buffer[r] = (FT_Byte) b;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cursor = p + n;
|
||||||
|
*seed = (FT_UShort)s;
|
||||||
|
#else
|
||||||
for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
|
for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
|
||||||
{
|
{
|
||||||
FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
|
FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
|
||||||
|
@ -388,9 +442,9 @@
|
||||||
s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
|
s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
|
||||||
*buffer++ = b;
|
*buffer++ = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cursor = p;
|
*cursor = p;
|
||||||
*seed = s;
|
*seed = s;
|
||||||
|
#endif
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,9 @@
|
||||||
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
|
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
loader->cursor = stream->cursor;
|
||||||
|
loader->limit = stream->limit;
|
||||||
|
|
||||||
return TT_Err_Ok;
|
return TT_Err_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,26 +208,26 @@
|
||||||
FT_CALLBACK_DEF( FT_Error )
|
FT_CALLBACK_DEF( FT_Error )
|
||||||
TT_Load_Glyph_Header( TT_Loader loader )
|
TT_Load_Glyph_Header( TT_Loader loader )
|
||||||
{
|
{
|
||||||
FT_Stream stream = loader->stream;
|
FT_Byte* p = loader->cursor;
|
||||||
FT_Int byte_len = loader->byte_len - 10;
|
FT_Byte* limit = loader->limit;
|
||||||
|
|
||||||
|
|
||||||
if ( byte_len < 0 )
|
if ( p + 10 > limit )
|
||||||
return TT_Err_Invalid_Outline;
|
return TT_Err_Invalid_Outline;
|
||||||
|
|
||||||
loader->n_contours = FT_GET_SHORT();
|
loader->n_contours = FT_NEXT_SHORT(p);
|
||||||
|
|
||||||
loader->bbox.xMin = FT_GET_SHORT();
|
loader->bbox.xMin = FT_NEXT_SHORT(p);
|
||||||
loader->bbox.yMin = FT_GET_SHORT();
|
loader->bbox.yMin = FT_NEXT_SHORT(p);
|
||||||
loader->bbox.xMax = FT_GET_SHORT();
|
loader->bbox.xMax = FT_NEXT_SHORT(p);
|
||||||
loader->bbox.yMax = FT_GET_SHORT();
|
loader->bbox.yMax = FT_NEXT_SHORT(p);
|
||||||
|
|
||||||
FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
|
FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
|
||||||
FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
|
FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
|
||||||
loader->bbox.xMax ));
|
loader->bbox.xMax ));
|
||||||
FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
|
FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
|
||||||
loader->bbox.yMax ));
|
loader->bbox.yMax ));
|
||||||
loader->byte_len = byte_len;
|
loader->cursor = p;
|
||||||
|
|
||||||
return TT_Err_Ok;
|
return TT_Err_Ok;
|
||||||
}
|
}
|
||||||
|
@ -234,14 +237,14 @@
|
||||||
TT_Load_Simple_Glyph( TT_Loader load )
|
TT_Load_Simple_Glyph( TT_Loader load )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Stream stream = load->stream;
|
FT_Byte* p = load->cursor;
|
||||||
|
FT_Byte* limit = load->limit;
|
||||||
FT_GlyphLoader gloader = load->gloader;
|
FT_GlyphLoader gloader = load->gloader;
|
||||||
FT_Int n_contours = load->n_contours;
|
FT_Int n_contours = load->n_contours;
|
||||||
FT_Outline* outline;
|
FT_Outline* outline;
|
||||||
TT_Face face = (TT_Face)load->face;
|
TT_Face face = (TT_Face)load->face;
|
||||||
FT_UShort n_ins;
|
FT_UShort n_ins;
|
||||||
FT_Int n, n_points;
|
FT_Int n, n_points;
|
||||||
FT_Int byte_len = load->byte_len;
|
|
||||||
|
|
||||||
FT_Byte *flag, *flag_limit;
|
FT_Byte *flag, *flag_limit;
|
||||||
FT_Byte c, count;
|
FT_Byte c, count;
|
||||||
|
@ -260,12 +263,11 @@
|
||||||
cont_limit = cont + n_contours;
|
cont_limit = cont + n_contours;
|
||||||
|
|
||||||
/* check space for contours array + instructions count */
|
/* check space for contours array + instructions count */
|
||||||
byte_len -= 2 * ( n_contours + 1 );
|
if ( n_contours >= 0xFFF || p + (n_contours+1)*2 > limit )
|
||||||
if ( byte_len < 0 )
|
|
||||||
goto Invalid_Outline;
|
goto Invalid_Outline;
|
||||||
|
|
||||||
for ( ; cont < cont_limit; cont++ )
|
for ( ; cont < cont_limit; cont++ )
|
||||||
cont[0] = FT_GET_USHORT();
|
cont[0] = FT_NEXT_USHORT(p);
|
||||||
|
|
||||||
n_points = 0;
|
n_points = 0;
|
||||||
if ( n_contours > 0 )
|
if ( n_contours > 0 )
|
||||||
|
@ -287,7 +289,10 @@
|
||||||
load->glyph->control_len = 0;
|
load->glyph->control_len = 0;
|
||||||
load->glyph->control_data = 0;
|
load->glyph->control_data = 0;
|
||||||
|
|
||||||
n_ins = FT_GET_USHORT();
|
if ( p+2 > limit )
|
||||||
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
n_ins = FT_NEXT_USHORT(p);
|
||||||
|
|
||||||
FT_TRACE5(( " Instructions size: %u\n", n_ins ));
|
FT_TRACE5(( " Instructions size: %u\n", n_ins ));
|
||||||
|
|
||||||
|
@ -298,8 +303,7 @@
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte_len -= (FT_Int)n_ins;
|
if ( (limit - p) < n_ins )
|
||||||
if ( byte_len < 0 )
|
|
||||||
{
|
{
|
||||||
FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
|
FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
|
||||||
error = TT_Err_Too_Many_Hints;
|
error = TT_Err_Too_Many_Hints;
|
||||||
|
@ -313,12 +317,12 @@
|
||||||
load->glyph->control_len = n_ins;
|
load->glyph->control_len = n_ins;
|
||||||
load->glyph->control_data = load->exec->glyphIns;
|
load->glyph->control_data = load->exec->glyphIns;
|
||||||
|
|
||||||
FT_MEM_COPY( load->exec->glyphIns, stream->cursor, (FT_Long)n_ins );
|
FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
|
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
|
||||||
|
|
||||||
stream->cursor += (FT_Int)n_ins;
|
p += n_ins;
|
||||||
|
|
||||||
/* reading the point tags */
|
/* reading the point tags */
|
||||||
flag = (FT_Byte*)outline->tags;
|
flag = (FT_Byte*)outline->tags;
|
||||||
|
@ -328,16 +332,16 @@
|
||||||
|
|
||||||
while ( flag < flag_limit )
|
while ( flag < flag_limit )
|
||||||
{
|
{
|
||||||
if ( --byte_len < 0 )
|
if ( p+1 > limit )
|
||||||
goto Invalid_Outline;
|
goto Invalid_Outline;
|
||||||
|
|
||||||
*flag++ = c = FT_GET_BYTE();
|
*flag++ = c = FT_NEXT_BYTE(p);
|
||||||
if ( c & 8 )
|
if ( c & 8 )
|
||||||
{
|
{
|
||||||
if ( --byte_len < 0 )
|
if ( p+1 > limit )
|
||||||
goto Invalid_Outline;
|
goto Invalid_Outline;
|
||||||
|
|
||||||
count = FT_GET_BYTE();
|
count = FT_NEXT_BYTE(p);
|
||||||
if ( flag + (FT_Int)count > flag_limit )
|
if ( flag + (FT_Int)count > flag_limit )
|
||||||
goto Invalid_Outline;
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
@ -346,23 +350,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that there is enough room to load the coordinates */
|
|
||||||
for ( flag = (FT_Byte*)outline->tags; flag < flag_limit; flag++ )
|
|
||||||
{
|
|
||||||
if ( *flag & 2 )
|
|
||||||
byte_len -= 1;
|
|
||||||
else if ( ( *flag & 16 ) == 0 )
|
|
||||||
byte_len -= 2;
|
|
||||||
|
|
||||||
if ( *flag & 4 )
|
|
||||||
byte_len -= 1;
|
|
||||||
else if ( ( *flag & 32 ) == 0 )
|
|
||||||
byte_len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( byte_len < 0 )
|
|
||||||
goto Invalid_Outline;
|
|
||||||
|
|
||||||
/* reading the X coordinates */
|
/* reading the X coordinates */
|
||||||
|
|
||||||
vec = outline->points;
|
vec = outline->points;
|
||||||
|
@ -377,12 +364,20 @@
|
||||||
|
|
||||||
if ( *flag & 2 )
|
if ( *flag & 2 )
|
||||||
{
|
{
|
||||||
y = (FT_Pos)FT_GET_BYTE();
|
if ( p+1 > limit )
|
||||||
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
y = (FT_Pos)FT_NEXT_BYTE(p);
|
||||||
if ( ( *flag & 16 ) == 0 )
|
if ( ( *flag & 16 ) == 0 )
|
||||||
y = -y;
|
y = -y;
|
||||||
}
|
}
|
||||||
else if ( ( *flag & 16 ) == 0 )
|
else if ( ( *flag & 16 ) == 0 )
|
||||||
y = (FT_Pos)FT_GET_SHORT();
|
{
|
||||||
|
if ( p+2 > limit )
|
||||||
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
y = (FT_Pos)FT_NEXT_SHORT(p);
|
||||||
|
}
|
||||||
|
|
||||||
x += y;
|
x += y;
|
||||||
vec->x = x;
|
vec->x = x;
|
||||||
|
@ -402,12 +397,20 @@
|
||||||
|
|
||||||
if ( *flag & 4 )
|
if ( *flag & 4 )
|
||||||
{
|
{
|
||||||
y = (FT_Pos)FT_GET_BYTE();
|
if ( p+1 > limit )
|
||||||
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
y = (FT_Pos)FT_NEXT_BYTE(p);
|
||||||
if ( ( *flag & 32 ) == 0 )
|
if ( ( *flag & 32 ) == 0 )
|
||||||
y = -y;
|
y = -y;
|
||||||
}
|
}
|
||||||
else if ( ( *flag & 32 ) == 0 )
|
else if ( ( *flag & 32 ) == 0 )
|
||||||
y = (FT_Pos)FT_GET_SHORT();
|
{
|
||||||
|
if ( p+2 > limit )
|
||||||
|
goto Invalid_Outline;
|
||||||
|
|
||||||
|
y = (FT_Pos)FT_NEXT_SHORT(p);
|
||||||
|
}
|
||||||
|
|
||||||
x += y;
|
x += y;
|
||||||
vec->y = x;
|
vec->y = x;
|
||||||
|
@ -420,7 +423,7 @@
|
||||||
outline->n_points = (FT_UShort)n_points;
|
outline->n_points = (FT_UShort)n_points;
|
||||||
outline->n_contours = (FT_Short) n_contours;
|
outline->n_contours = (FT_Short) n_contours;
|
||||||
|
|
||||||
load->byte_len = byte_len;
|
load->cursor = p;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
return error;
|
return error;
|
||||||
|
@ -435,11 +438,11 @@
|
||||||
TT_Load_Composite_Glyph( TT_Loader loader )
|
TT_Load_Composite_Glyph( TT_Loader loader )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Stream stream = loader->stream;
|
FT_Byte* p = loader->cursor;
|
||||||
|
FT_Byte* limit = loader->limit;
|
||||||
FT_GlyphLoader gloader = loader->gloader;
|
FT_GlyphLoader gloader = loader->gloader;
|
||||||
FT_SubGlyph subglyph;
|
FT_SubGlyph subglyph;
|
||||||
FT_UInt num_subglyphs;
|
FT_UInt num_subglyphs;
|
||||||
FT_Int byte_len = loader->byte_len;
|
|
||||||
|
|
||||||
|
|
||||||
num_subglyphs = 0;
|
num_subglyphs = 0;
|
||||||
|
@ -447,6 +450,7 @@
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
FT_Fixed xx, xy, yy, yx;
|
FT_Fixed xx, xy, yy, yx;
|
||||||
|
FT_UInt count;
|
||||||
|
|
||||||
|
|
||||||
/* check that we can load a new subglyph */
|
/* check that we can load a new subglyph */
|
||||||
|
@ -455,41 +459,40 @@
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
/* check space */
|
/* check space */
|
||||||
byte_len -= 4;
|
if ( p+4 > limit )
|
||||||
if ( byte_len < 0 )
|
|
||||||
goto Invalid_Composite;
|
goto Invalid_Composite;
|
||||||
|
|
||||||
subglyph = gloader->current.subglyphs + num_subglyphs;
|
subglyph = gloader->current.subglyphs + num_subglyphs;
|
||||||
|
|
||||||
subglyph->arg1 = subglyph->arg2 = 0;
|
subglyph->arg1 = subglyph->arg2 = 0;
|
||||||
|
|
||||||
subglyph->flags = FT_GET_USHORT();
|
subglyph->flags = FT_NEXT_USHORT(p);
|
||||||
subglyph->index = FT_GET_USHORT();
|
subglyph->index = FT_NEXT_USHORT(p);
|
||||||
|
|
||||||
/* check space */
|
/* check space */
|
||||||
byte_len -= 2;
|
count = 2;
|
||||||
if ( subglyph->flags & ARGS_ARE_WORDS )
|
if ( subglyph->flags & ARGS_ARE_WORDS )
|
||||||
byte_len -= 2;
|
count += 2;
|
||||||
if ( subglyph->flags & WE_HAVE_A_SCALE )
|
if ( subglyph->flags & WE_HAVE_A_SCALE )
|
||||||
byte_len -= 2;
|
count += 2;
|
||||||
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
|
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
|
||||||
byte_len -= 4;
|
count += 4;
|
||||||
else if ( subglyph->flags & WE_HAVE_A_2X2 )
|
else if ( subglyph->flags & WE_HAVE_A_2X2 )
|
||||||
byte_len -= 8;
|
count += 8;
|
||||||
|
|
||||||
if ( byte_len < 0 )
|
if ( p + count > limit )
|
||||||
goto Invalid_Composite;
|
goto Invalid_Composite;
|
||||||
|
|
||||||
/* read arguments */
|
/* read arguments */
|
||||||
if ( subglyph->flags & ARGS_ARE_WORDS )
|
if ( subglyph->flags & ARGS_ARE_WORDS )
|
||||||
{
|
{
|
||||||
subglyph->arg1 = FT_GET_SHORT();
|
subglyph->arg1 = FT_NEXT_SHORT(p);
|
||||||
subglyph->arg2 = FT_GET_SHORT();
|
subglyph->arg2 = FT_NEXT_SHORT(p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
subglyph->arg1 = FT_GET_CHAR();
|
subglyph->arg1 = FT_NEXT_CHAR(p);
|
||||||
subglyph->arg2 = FT_GET_CHAR();
|
subglyph->arg2 = FT_NEXT_CHAR(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read transform */
|
/* read transform */
|
||||||
|
@ -498,20 +501,20 @@
|
||||||
|
|
||||||
if ( subglyph->flags & WE_HAVE_A_SCALE )
|
if ( subglyph->flags & WE_HAVE_A_SCALE )
|
||||||
{
|
{
|
||||||
xx = (FT_Fixed)FT_GET_SHORT() << 2;
|
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
yy = xx;
|
yy = xx;
|
||||||
}
|
}
|
||||||
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
|
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
|
||||||
{
|
{
|
||||||
xx = (FT_Fixed)FT_GET_SHORT() << 2;
|
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
yy = (FT_Fixed)FT_GET_SHORT() << 2;
|
yy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
}
|
}
|
||||||
else if ( subglyph->flags & WE_HAVE_A_2X2 )
|
else if ( subglyph->flags & WE_HAVE_A_2X2 )
|
||||||
{
|
{
|
||||||
xx = (FT_Fixed)FT_GET_SHORT() << 2;
|
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
yx = (FT_Fixed)FT_GET_SHORT() << 2;
|
yx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
xy = (FT_Fixed)FT_GET_SHORT() << 2;
|
xy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
yy = (FT_Fixed)FT_GET_SHORT() << 2;
|
yy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
subglyph->transform.xx = xx;
|
subglyph->transform.xx = xx;
|
||||||
|
@ -533,12 +536,12 @@
|
||||||
/* we will process them later... */
|
/* we will process them later... */
|
||||||
/* */
|
/* */
|
||||||
loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
|
loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
|
||||||
stream->cursor - stream->limit );
|
p - limit );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loader->byte_len = byte_len;
|
loader->cursor = p;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -310,11 +310,14 @@
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* apply the font matrix, if any */
|
/* apply the font matrix, if any */
|
||||||
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
|
if ( font_matrix.xx != 0x10000L || font_matrix.yy != font_matrix.xx ||
|
||||||
|
font_matrix.xy != 0 || font_matrix.yx != 0 )
|
||||||
|
FT_Outline_Transform( &glyph->root.outline, &font_matrix );
|
||||||
|
|
||||||
FT_Outline_Translate( &glyph->root.outline,
|
if ( font_offset.x || font_offset.y )
|
||||||
font_offset.x,
|
FT_Outline_Translate( &glyph->root.outline,
|
||||||
font_offset.y );
|
font_offset.x,
|
||||||
|
font_offset.y );
|
||||||
|
|
||||||
advance.x = metrics->horiAdvance;
|
advance.x = metrics->horiAdvance;
|
||||||
advance.y = 0;
|
advance.y = 0;
|
||||||
|
|
Loading…
Reference in New Issue