* 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:
David Turner 2006-05-17 13:34:21 +00:00
parent dc3ff31c3f
commit 281679de85
13 changed files with 535 additions and 392 deletions

View File

@ -1,5 +1,22 @@
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
used to detect rogue clients from 4 to 16. This is to prevent
some segmentation faults with fonts like KozMinProVI-Regular.otf
@ -8,7 +25,7 @@
2007-05-17 Werner Lemberg <wl@gnu.org>
* 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>
@ -52,8 +69,8 @@
Update handling of re_italic and re_bold.
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.
Remove a redundant parenthesis.

View File

@ -1521,6 +1521,10 @@ FT_BEGIN_HEADER
FT_Vector pp3;
FT_Vector pp4;
/* since version 2.2.1 */
FT_Byte* cursor;
FT_Byte* limit;
} TT_LoaderRec;

View File

@ -20,7 +20,94 @@
#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 `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
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 )
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 */

View File

@ -1437,7 +1437,9 @@
static const AF_Script_UniRangeRec af_cjk_uniranges[] =
{
{ 0x0100, 0xFFFF },
#if 0
{ 0x0100, 0xFFFF }, /* why ?? */
#endif
{ 0x2E80, 0x2EFF }, /* CJK Radicals Supplement */
{ 0x2F00, 0x2FDF }, /* Kangxi Radicals */
{ 0x3000, 0x303F }, /* CJK Symbols and Punctuation */

View File

@ -53,7 +53,9 @@
}
segment = axis->segments + axis->num_segments++;
#if 0
FT_ZERO( segment );
#endif
Exit:
*asegment = segment;
@ -272,54 +274,46 @@
FT_Pos dy )
{
#if 1
AF_Direction dir = AF_DIR_NONE;
FT_Pos ll, ss; /* long and short arm lengths */
AF_Direction dir; /* candidate direction */
/* atan(1/12) == 4.7 degrees */
if ( dx < 0 )
if ( dy >= dx )
{
if ( dy < 0 )
if ( dy >= -dx )
{
if ( -dx * 12 < -dy )
dir = AF_DIR_DOWN;
else if ( -dy * 12 < -dx )
dir = AF_DIR_LEFT;
dir = AF_DIR_UP;
ll = dy;
ss = dx;
}
else /* dy >= 0 */
else
{
if ( -dx * 12 < dy )
dir = AF_DIR_UP;
else if ( dy * 12 < -dx )
dir = AF_DIR_LEFT;
dir = AF_DIR_LEFT;
ll = -dx;
ss = dy;
}
}
else /* dx >= 0 */
else /* dy < dx */
{
if ( dy < 0 )
if ( dy >= -dx )
{
if ( dx * 12 < -dy )
dir = AF_DIR_DOWN;
else if ( -dy * 12 < dx )
dir = AF_DIR_RIGHT;
dir = AF_DIR_RIGHT;
ll = dx;
ss = dy;
}
else /* dy >= 0 */
else
{
if ( dx * 12 < dy )
dir = AF_DIR_UP;
else if ( dy * 12 < dx )
dir = AF_DIR_RIGHT;
dir = AF_DIR_DOWN;
ll = dy;
ss = dx;
}
}
ss *= 12;
if ( ll <= FT_ABS(ss) )
dir = AF_DIR_NONE;
return dir;
#else /* 0 */
AF_Direction dir;
FT_Pos ax = FT_ABS( dx );
FT_Pos ay = FT_ABS( dy );
@ -341,13 +335,125 @@
}
return dir;
#endif /* 0 */
}
/* 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
af_glyph_hints_compute_inflections( AF_GlyphHints hints )
{
@ -454,6 +560,7 @@
;
}
}
#endif /* old code */
FT_LOCAL_DEF( void )
@ -702,6 +809,14 @@
}
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;
@ -715,6 +830,7 @@
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;
#endif /* old code */
}
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
@ -1152,7 +1268,7 @@
AF_Point points = hints->points;
AF_Point points_limit = points + hints->num_points;
AF_Point point;
if ( dim == AF_DIMENSION_HORZ )
{

View File

@ -590,6 +590,7 @@
FT_Memory memory = hints->memory;
FT_Error error = AF_Err_Ok;
AF_Segment segment = NULL;
AF_SegmentRec seg0;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
AF_Direction major_dir, segment_dir;
@ -601,6 +602,10 @@
FT_Pos max_coord = -32000;
#endif
FT_ZERO( &seg0 );
seg0.score = 32000;
seg0.flags = AF_EDGE_NORMAL;
major_dir = (AF_Direction)FT_ABS( axis->major_dir );
segment_dir = major_dir;
@ -742,15 +747,12 @@
if ( error )
goto Exit;
segment[0] = seg0;
segment->dir = (FT_Char)segment_dir;
segment->flags = AF_EDGE_NORMAL;
min_pos = max_pos = point->u;
segment->first = point;
segment->last = point;
segment->contour = contour;
segment->score = 32000;
segment->len = 0;
segment->link = NULL;
on_edge = 1;
#ifdef AF_HINT_METRICS
@ -810,14 +812,11 @@
if ( error )
goto Exit;
segment[0] = seg0;
segment->dir = segment_dir;
segment->flags = AF_EDGE_NORMAL;
segment->first = min_point;
segment->last = min_point;
segment->pos = min_pos;
segment->score = 32000;
segment->len = 0;
segment->link = NULL;
segment = NULL;
}
@ -830,14 +829,11 @@
if ( error )
goto Exit;
segment[0] = seg0;
segment->dir = segment_dir;
segment->flags = AF_EDGE_NORMAL;
segment->first = max_point;
segment->last = max_point;
segment->pos = max_pos;
segment->score = 32000;
segment->len = 0;
segment->link = NULL;
segment = NULL;
}
@ -926,7 +922,6 @@
if ( seg2 )
{
seg2->num_linked++;
if ( seg2->link != seg1 )
{
seg1->link = 0;

View File

@ -118,6 +118,7 @@ FT_BEGIN_HEADER
#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
#if 0
/*
* compute the angle of a given 2-D vector
*/
@ -126,7 +127,6 @@ FT_BEGIN_HEADER
FT_Pos dy );
#if 0
/*
* compute `angle2 - angle1'; the result is always within
* the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
@ -137,6 +137,27 @@ FT_BEGIN_HEADER
#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 ) \
FT_BEGIN_STMNT \
AF_Angle _delta = (angle2) - (angle1); \

View File

@ -396,7 +396,29 @@
FT_MulFix( FT_Long a,
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_ULong ua, ub;

View File

@ -732,7 +732,7 @@
return ( n % 2 );
}
static FT_Bool
ft_contour_enclosed( FT_Outline* outline,
FT_UShort c )
@ -1012,11 +1012,25 @@
++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 ) >
FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
return FT_ORIENTATION_POSTSCRIPT;
else
return FT_ORIENTATION_TRUETYPE;
#endif
}

View File

@ -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_Stream_OpenGzip( FT_Stream stream,
FT_Stream source )
@ -586,6 +607,47 @@
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->pos = 0;
stream->base = 0;

View File

@ -331,11 +331,48 @@
FT_UInt n )
{
FT_Byte* p;
FT_UInt r = 0;
FT_UInt r = 0;
FT_UInt w = 0;
FT_UInt pad = 0x01;
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;
@ -348,10 +385,10 @@
c = ft_char_table[*p & 0x7f];
if ( c < 0 || c >= 16 )
if ( (unsigned)c >= 16 )
break;
if ( r % 2 )
if ( r & 1 )
{
*buffer = (FT_Byte)(*buffer + c);
buffer++;
@ -365,6 +402,7 @@
*cursor = p;
return ( r + 1 ) / 2;
#endif
}
@ -377,9 +415,25 @@
{
FT_Byte* p;
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++ )
{
FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
@ -388,9 +442,9 @@
s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
*buffer++ = b;
}
*cursor = p;
*seed = s;
#endif
return r;
}

View File

@ -188,6 +188,9 @@
if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
return error;
loader->cursor = stream->cursor;
loader->limit = stream->limit;
return TT_Err_Ok;
}
@ -205,26 +208,26 @@
FT_CALLBACK_DEF( FT_Error )
TT_Load_Glyph_Header( TT_Loader loader )
{
FT_Stream stream = loader->stream;
FT_Int byte_len = loader->byte_len - 10;
FT_Byte* p = loader->cursor;
FT_Byte* limit = loader->limit;
if ( byte_len < 0 )
if ( p + 10 > limit )
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.yMin = FT_GET_SHORT();
loader->bbox.xMax = FT_GET_SHORT();
loader->bbox.yMax = FT_GET_SHORT();
loader->bbox.xMin = FT_NEXT_SHORT(p);
loader->bbox.yMin = FT_NEXT_SHORT(p);
loader->bbox.xMax = FT_NEXT_SHORT(p);
loader->bbox.yMax = FT_NEXT_SHORT(p);
FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
loader->bbox.xMax ));
FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
loader->bbox.yMax ));
loader->byte_len = byte_len;
loader->cursor = p;
return TT_Err_Ok;
}
@ -234,14 +237,14 @@
TT_Load_Simple_Glyph( TT_Loader load )
{
FT_Error error;
FT_Stream stream = load->stream;
FT_Byte* p = load->cursor;
FT_Byte* limit = load->limit;
FT_GlyphLoader gloader = load->gloader;
FT_Int n_contours = load->n_contours;
FT_Outline* outline;
TT_Face face = (TT_Face)load->face;
FT_UShort n_ins;
FT_Int n, n_points;
FT_Int byte_len = load->byte_len;
FT_Byte *flag, *flag_limit;
FT_Byte c, count;
@ -260,12 +263,11 @@
cont_limit = cont + n_contours;
/* check space for contours array + instructions count */
byte_len -= 2 * ( n_contours + 1 );
if ( byte_len < 0 )
if ( n_contours >= 0xFFF || p + (n_contours+1)*2 > limit )
goto Invalid_Outline;
for ( ; cont < cont_limit; cont++ )
cont[0] = FT_GET_USHORT();
cont[0] = FT_NEXT_USHORT(p);
n_points = 0;
if ( n_contours > 0 )
@ -287,7 +289,10 @@
load->glyph->control_len = 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 ));
@ -298,8 +303,7 @@
goto Fail;
}
byte_len -= (FT_Int)n_ins;
if ( byte_len < 0 )
if ( (limit - p) < n_ins )
{
FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
error = TT_Err_Too_Many_Hints;
@ -313,12 +317,12 @@
load->glyph->control_len = n_ins;
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 */
stream->cursor += (FT_Int)n_ins;
p += n_ins;
/* reading the point tags */
flag = (FT_Byte*)outline->tags;
@ -328,16 +332,16 @@
while ( flag < flag_limit )
{
if ( --byte_len < 0 )
if ( p+1 > limit )
goto Invalid_Outline;
*flag++ = c = FT_GET_BYTE();
*flag++ = c = FT_NEXT_BYTE(p);
if ( c & 8 )
{
if ( --byte_len < 0 )
if ( p+1 > limit )
goto Invalid_Outline;
count = FT_GET_BYTE();
count = FT_NEXT_BYTE(p);
if ( flag + (FT_Int)count > flag_limit )
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 */
vec = outline->points;
@ -377,12 +364,20 @@
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 )
y = -y;
}
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;
vec->x = x;
@ -402,12 +397,20 @@
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 )
y = -y;
}
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;
vec->y = x;
@ -420,7 +423,7 @@
outline->n_points = (FT_UShort)n_points;
outline->n_contours = (FT_Short) n_contours;
load->byte_len = byte_len;
load->cursor = p;
Fail:
return error;
@ -435,11 +438,11 @@
TT_Load_Composite_Glyph( TT_Loader loader )
{
FT_Error error;
FT_Stream stream = loader->stream;
FT_Byte* p = loader->cursor;
FT_Byte* limit = loader->limit;
FT_GlyphLoader gloader = loader->gloader;
FT_SubGlyph subglyph;
FT_UInt num_subglyphs;
FT_Int byte_len = loader->byte_len;
num_subglyphs = 0;
@ -447,6 +450,7 @@
do
{
FT_Fixed xx, xy, yy, yx;
FT_UInt count;
/* check that we can load a new subglyph */
@ -455,41 +459,40 @@
goto Fail;
/* check space */
byte_len -= 4;
if ( byte_len < 0 )
if ( p+4 > limit )
goto Invalid_Composite;
subglyph = gloader->current.subglyphs + num_subglyphs;
subglyph->arg1 = subglyph->arg2 = 0;
subglyph->flags = FT_GET_USHORT();
subglyph->index = FT_GET_USHORT();
subglyph->flags = FT_NEXT_USHORT(p);
subglyph->index = FT_NEXT_USHORT(p);
/* check space */
byte_len -= 2;
count = 2;
if ( subglyph->flags & ARGS_ARE_WORDS )
byte_len -= 2;
count += 2;
if ( subglyph->flags & WE_HAVE_A_SCALE )
byte_len -= 2;
count += 2;
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
byte_len -= 4;
count += 4;
else if ( subglyph->flags & WE_HAVE_A_2X2 )
byte_len -= 8;
count += 8;
if ( byte_len < 0 )
if ( p + count > limit )
goto Invalid_Composite;
/* read arguments */
if ( subglyph->flags & ARGS_ARE_WORDS )
{
subglyph->arg1 = FT_GET_SHORT();
subglyph->arg2 = FT_GET_SHORT();
subglyph->arg1 = FT_NEXT_SHORT(p);
subglyph->arg2 = FT_NEXT_SHORT(p);
}
else
{
subglyph->arg1 = FT_GET_CHAR();
subglyph->arg2 = FT_GET_CHAR();
subglyph->arg1 = FT_NEXT_CHAR(p);
subglyph->arg2 = FT_NEXT_CHAR(p);
}
/* read transform */
@ -498,20 +501,20 @@
if ( subglyph->flags & WE_HAVE_A_SCALE )
{
xx = (FT_Fixed)FT_GET_SHORT() << 2;
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
yy = xx;
}
else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
{
xx = (FT_Fixed)FT_GET_SHORT() << 2;
yy = (FT_Fixed)FT_GET_SHORT() << 2;
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
yy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
}
else if ( subglyph->flags & WE_HAVE_A_2X2 )
{
xx = (FT_Fixed)FT_GET_SHORT() << 2;
yx = (FT_Fixed)FT_GET_SHORT() << 2;
xy = (FT_Fixed)FT_GET_SHORT() << 2;
yy = (FT_Fixed)FT_GET_SHORT() << 2;
xx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
yx = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
xy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
yy = (FT_Fixed)FT_NEXT_SHORT(p) << 2;
}
subglyph->transform.xx = xx;
@ -533,12 +536,12 @@
/* we will process them later... */
/* */
loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
stream->cursor - stream->limit );
p - limit );
}
#endif
loader->byte_len = byte_len;
loader->cursor = p;
Fail:
return error;

View File

@ -310,11 +310,14 @@
#if 1
/* 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,
font_offset.x,
font_offset.y );
if ( font_offset.x || font_offset.y )
FT_Outline_Translate( &glyph->root.outline,
font_offset.x,
font_offset.y );
advance.x = metrics->horiAdvance;
advance.y = 0;