Upgrade to version 2.1.8

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8126 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm
2004-06-22 14:03:16 +00:00
parent 196f29a0bd
commit 1754568b9c
427 changed files with 39571 additions and 25363 deletions
+24
View File
@@ -0,0 +1,24 @@
# FreeType 2 src/autofit Jamfile (c) 2001 David Turner
#
SubDir OBOS_TOP src libs freetype2 autofit ;
UseFreeTypeHeaders ;
{
local _sources ;
if $(FT2_MULTI)
{
_sources = autofit afmodule afloader aflatin afhints afglobal afdummy afangles ;
}
else
{
_sources = autofit ;
}
FT2_Library $(FT2_LIB) : $(_sources).c ;
}
# end of src/autofit Jamfile
+214
View File
@@ -0,0 +1,214 @@
#include "aftypes.h"
/* this table was generated for AF_ANGLE_PI = 256 */
#define AF_ANGLE_MAX_ITERS 8
#define AF_TRIG_MAX_ITERS 9
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 = 2 * AF_ANGLE_PI2;
}
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 );
/* round theta */
if ( theta >= 0 )
theta = FT_PAD_ROUND( theta, 4 );
else
theta = - FT_PAD_ROUND( theta, 4 );
vec->x = x;
vec->y = theta;
}
/* documentation is 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;
}
/* well, this needs to be somewhere, right :-)
*/
FT_LOCAL_DEF( void )
af_sort_pos( FT_UInt count,
FT_Pos* table )
{
FT_UInt i, j;
FT_Pos swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j] > table[j - 1] )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
FT_LOCAL_DEF( void )
af_sort_widths( FT_UInt count,
AF_Width table )
{
FT_UInt i, j;
AF_WidthRec swap;
for ( i = 1; i < count; i++ )
{
for ( j = i; j > 0; j-- )
{
if ( table[j].org > table[j - 1].org )
break;
swap = table[j];
table[j] = table[j - 1];
table[j - 1] = swap;
}
}
}
+35
View File
@@ -0,0 +1,35 @@
#include "afdummy.h"
static FT_Error
af_dummy_hints_init( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics )
{
return af_glyph_hints_reset( hints,
&metrics->scaler,
metrics,
outline );
}
static FT_Error
af_dummy_hints_apply( AF_GlyphHints hints,
FT_Outline* outline )
{
af_glyph_hints_save( hints, outline );
}
FT_LOCAL_DEF( const AF_ScriptClassRec ) af_dummy_script_class =
{
AF_SCRIPT_NONE,
NULL,
sizeof( AF_ScriptMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc) NULL,
(AF_Script_DoneMetricsFunc) NULL,
(AF_Script_InitHintsFunc) af_dummy_hints_init,
(AF_Script_ApplyHintsFunc) af_dummy_hints_apply
};
+18
View File
@@ -0,0 +1,18 @@
#ifndef __AFDUMMY_H__
#define __AFDUMMY_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/* a dummy script metrics class used when no hinting should
* be performed. This is the default for non-latin glyphs !
*/
FT_LOCAL( const AF_ScriptClassRec ) af_dummy_script_class;
/* */
FT_END_HEADER
#endif /* __AFDUMMY_H__ */
+236
View File
@@ -0,0 +1,236 @@
#include "afglobal.h"
#include "afdummy.h"
#include "aflatin.h"
/* populate this list when you add new scripts
*/
static AF_ScriptClass const af_script_classes[] =
{
& af_dummy_script_class,
& af_latin_script_class,
NULL /* do not remove */
};
#define AF_SCRIPT_LIST_DEFAULT 0 /* index of default script in 'af_script_classes' */
#define AF_SCRIPT_LIST_NONE 255 /* indicates an uncovered glyph */
/*
* note that glyph_scripts[] is used to map each glyph into
* an index into the 'af_script_classes' array.
*
*/
typedef struct AF_FaceGlobalsRec_
{
FT_Face face;
FT_UInt glyph_count; /* same as face->num_glyphs */
FT_Byte* glyph_scripts;
AF_ScriptMetrics metrics[ AF_SCRIPT_MAX ];
} AF_FaceGlobalsRec;
/* this function is used to compute the script index of each glyph
* within a given face
*/
static FT_Error
af_face_globals_compute_script_coverage( AF_FaceGlobals globals )
{
FT_Error error = 0;
FT_Face face = globals->face;
FT_CharMap old_charmap = face->charmap;
FT_Byte* gscripts = globals->glyph_scripts;
FT_UInt ss;
/* the value 255 means "uncovered glyph"
*/
FT_MEM_SET( globals->glyph_scripts,
AF_SCRIPT_LIST_NONE,
globals->glyph_count );
error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
if ( error )
{
/* ignore this error, we'll simply use Latin as the standard
* script. XXX: Shouldn't we rather disable hinting ??
*/
error = 0;
goto Exit;
}
/* scan each script in a Unicode charmap
*/
for ( ss = 0; af_script_classes[ss]; ss++ )
{
AF_ScriptClass clazz = af_script_classes[ss];
AF_Script_UniRange range;
if ( clazz->script_uni_ranges == NULL )
continue;
/* scan all unicode points in the range, and set the corresponding
* glyph script index
*/
for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
{
FT_ULong charcode = range->first;
FT_UInt gindex;
gindex = FT_Get_Char_Index( face, charcode );
if ( gindex != 0 &&
gindex < globals->glyph_count &&
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
{
gscripts[ gindex ] = (FT_Byte) ss;
}
for (;;)
{
charcode = FT_Get_Next_Char( face, charcode, &gindex );
if ( gindex == 0 || charcode > range->last )
break;
if ( gindex < globals->glyph_count &&
gscripts[ gindex ] == AF_SCRIPT_LIST_NONE )
{
gscripts[ gindex ] = (FT_Byte) ss;
}
}
}
}
Exit:
/* by default, all uncovered glyphs are set to the latin script
* XXX: shouldnt' we disable hinting or do something similar ?
*/
{
FT_UInt nn;
for ( nn = 0; nn < globals->glyph_count; nn++ )
{
if ( gscripts[ nn ] == AF_SCRIPT_LIST_NONE )
gscripts[ nn ] = AF_SCRIPT_LIST_DEFAULT;
}
}
FT_Set_Charmap( face, old_charmap );
return error;
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals )
{
FT_Error error;
FT_Memory memory;
AF_FaceGlobals globals;
memory = face->memory;
if ( !FT_ALLOC( globals, sizeof(*globals) +
face->num_glyphs*sizeof(FT_Byte) ) )
{
globals->face = face;
globals->glyph_count = face->num_glyphs;
globals->glyph_scripts = (FT_Byte*)( globals+1 );
error = af_face_globals_compute_script_coverage( globals );
if ( error )
{
af_face_globals_free( globals );
globals = NULL;
}
}
*aglobals = globals;
return error;
}
FT_LOCAL_DEF( void )
af_face_globals_free( AF_FaceGlobals globals )
{
if ( globals )
{
FT_Memory memory = globals->face->memory;
FT_UInt nn;
for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
{
if ( globals->metrics[nn] )
{
AF_ScriptClass clazz = af_script_classes[nn];
FT_ASSERT( globals->metrics[nn]->clazz == clazz );
if ( clazz->script_metrics_done )
clazz->script_metrics_done( globals->metrics[nn] );
FT_FREE( globals->metrics[nn] );
}
}
globals->glyph_count = 0;
globals->glyph_scripts = NULL; /* no need to free this one !! */
globals->face = NULL;
FT_FREE( globals );
}
}
FT_LOCAL_DEF( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
AF_ScriptMetrics *ametrics )
{
AF_ScriptMetrics metrics = NULL;
FT_UInt index;
AF_ScriptClass clazz;
FT_Error error = 0;
if ( gindex >= globals->glyph_count )
{
error = FT_Err_Invalid_Argument;
goto Exit;
}
index = globals->glyph_scripts[ gindex ];
clazz = af_script_classes[ index ];
metrics = globals->metrics[ clazz->script ];
if ( metrics == NULL )
{
/* create the global metrics object when needed
*/
FT_Memory memory = globals->face->memory;
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
goto Exit;
metrics->clazz = clazz;
if ( clazz->script_metrics_init )
{
error = clazz->script_metrics_init( metrics, globals->face );
if ( error )
{
if ( clazz->script_metrics_done )
clazz->script_metrics_done( metrics );
FT_FREE( metrics );
goto Exit;
}
}
globals->metrics[ clazz->script ] = metrics;
}
Exit:
*ametrics = metrics;
return error;
}
+41
View File
@@ -0,0 +1,41 @@
#ifndef __AF_GLOBAL_H__
#define __AF_GLOBAL_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** F A C E G L O B A L S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* models the global hints data for a given face, decomposed into
* script-specific items..
*
*/
typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals;
FT_LOCAL( FT_Error )
af_face_globals_new( FT_Face face,
AF_FaceGlobals *aglobals );
FT_LOCAL( FT_Error )
af_face_globals_get_metrics( AF_FaceGlobals globals,
FT_UInt gindex,
AF_ScriptMetrics *ametrics );
FT_LOCAL( void )
af_face_globals_free( AF_FaceGlobals globals );
/* */
FT_END_HEADER
#endif /* __AF_GLOBALS_H__ */
+986
View File
@@ -0,0 +1,986 @@
#include "afhints.h"
#ifdef AF_DEBUG
#include <stdio.h>
static const char* af_dir_str( AF_Direction dir )
{
const char* result;
switch (dir)
{
case AF_DIR_UP: result = "up"; break;
case AF_DIR_DOWN: result = "down"; break;
case AF_DIR_LEFT: result = "left"; break;
case AF_DIR_RIGHT: result = "right"; break;
default: result = "none";
}
return result;
}
#define AF_INDEX_NUM(ptr,base) ( (ptr) ? ((ptr)-(base)) : -1 )
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
{
AF_Point points = hints->points;
AF_Point limit = points + hints->num_points;
AF_Point point;
printf( "Table of points:\n" );
printf( " [ index | xorg | yorg | xscale | yscale | xfit | yfit | flags ]\n" );
for ( point = points; point < limit; point++ )
{
printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f | %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
point - points,
point->fx,
point->fy,
point->ox/64.0,
point->oy/64.0,
point->x/64.0,
point->y/64.0,
(point->flags & AF_FLAG_WEAK_INTERPOLATION) ? 'w' : ' ',
(point->flags & AF_FLAG_INFLECTION) ? 'i' : ' ',
(point->flags & AF_FLAG_EXTREMA_X) ? '<' : ' ',
(point->flags & AF_FLAG_EXTREMA_Y) ? 'v' : ' ',
(point->flags & AF_FLAG_ROUND_X) ? '(' : ' ',
(point->flags & AF_FLAG_ROUND_Y) ? 'u' : ' '
);
}
printf( "\n" );
}
/* A function used to dump the array of linked segments */
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
{
AF_Point points = hints->points;
FT_Int dimension;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_AxisHints axis = &hints->axis[dimension];
AF_Segment segments = axis->segments;
AF_Segment limit = segments + axis->num_segments;
AF_Segment seg;
printf ( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
" numl | first | start ]\n" );
for ( seg = segments; seg < limit; seg++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
seg - segments,
(int)seg->pos,
af_dir_str( seg->dir ),
AF_INDEX_NUM( seg->link, segments ),
AF_INDEX_NUM( seg->serif, segments ),
(int)seg->num_linked,
seg->first - points,
seg->last - points );
}
printf( "\n" );
}
}
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
FT_Int dimension;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_AxisHints axis = &hints->axis[ dimension ];
AF_Edge edges = axis->edges;
AF_Edge limit = edges + axis->num_edges;
AF_Edge edge;
/* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
* since they have constant X coordinate
*/
printf ( "Table of %s edges:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
" serif | blue | opos | pos ]\n" );
for ( edge = edges; edge < limit; edge++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
edge - edges,
(int)edge->fpos,
af_dir_str( edge->dir ),
AF_INDEX_NUM( edge->link, edges ),
AF_INDEX_NUM( edge->serif, edges ),
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0 );
}
printf( "\n" );
}
}
#endif /* AF_DEBUG */
/* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{
AF_Direction dir;
FT_Pos ax = FT_ABS( dx );
FT_Pos ay = FT_ABS( dy );
dir = AF_DIR_NONE;
/* atan(1/12) == 4.7 degrees */
/* test for vertical direction */
if ( ax * 12 < ay )
{
dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
}
/* test for horizontal direction */
else if ( ay * 12 < ax )
{
dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
}
return dir;
}
/* compute all inflex points in a given glyph */
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;
AF_Angle angle_in, angle_seg, angle_out;
AF_Angle diff_in, diff_out;
FT_Int finished = 0;
/* compute first segment in contour */
first = point;
start = end = first;
do
{
end = end->next;
if ( end == first )
goto Skip;
} while ( end->fx == first->fx && end->fy == first->fy );
angle_seg = af_angle_atan( end->fx - start->fx,
end->fy - start->fy );
/* extend the segment start whenever possible */
before = start;
do
{
do
{
start = before;
before = before->prev;
if ( before == first )
goto Skip;
} while ( before->fx == start->fx && before->fy == start->fy );
angle_in = af_angle_atan( start->fx - before->fx,
start->fy - before->fy );
} while ( angle_in == angle_seg );
first = start;
diff_in = af_angle_diff( angle_in, angle_seg );
/* 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;
} while ( end->fx == after->fx && end->fy == after->fy );
angle_out = af_angle_atan( after->fx - end->fx,
after->fy - end->fy );
} while ( angle_out == angle_seg );
diff_out = af_angle_diff( angle_seg, angle_out );
if ( ( diff_in ^ diff_out ) < 0 )
{
/* diff_in and diff_out have different signs, we have */
/* inflection points here... */
do
{
start->flags |= AF_FLAG_INFLECTION;
start = start->next;
} while ( start != end );
start->flags |= AF_FLAG_INFLECTION;
}
start = end;
end = after;
angle_seg = angle_out;
diff_in = diff_out;
} while ( !finished );
Skip:
;
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory )
{
FT_ZERO( hints );
hints->memory = memory;
}
FT_LOCAL_DEF( void )
af_glyph_hints_done( AF_GlyphHints hints )
{
if ( hints && hints->memory )
{
FT_Memory memory = hints->memory;
AF_Dimension dim;
/* note that we don't need to free the segment and edge
* buffers, since they're really within the hints->points array
*/
for ( dim = 0; dim < 2; dim++ )
{
AF_AxisHints axis = &hints->axis[ dim ];
axis->num_segments = 0;
axis->num_edges = 0;
axis->segments = NULL;
axis->edges = NULL;
}
FT_FREE( hints->contours );
hints->max_contours = 0;
hints->num_contours = 0;
FT_FREE( hints->points );
hints->num_points = 0;
hints->max_points = 0;
hints->memory = NULL;
}
}
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reset( AF_GlyphHints hints,
AF_Scaler scaler,
AF_ScriptMetrics metrics,
FT_Outline* outline )
{
FT_Error error = FT_Err_Ok;
AF_Point points;
FT_UInt old_max, new_max;
FT_Fixed x_scale = scaler->x_scale;
FT_Fixed y_scale = scaler->y_scale;
FT_Pos x_delta = scaler->x_delta;
FT_Pos y_delta = scaler->y_delta;
FT_Memory memory = hints->memory;
hints->metrics = metrics;
hints->scaler_flags = scaler->flags;
hints->other_flags = 0;
hints->num_points = 0;
hints->num_contours = 0;
hints->axis[0].num_segments = 0;
hints->axis[0].num_edges = 0;
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
/* first of all, reallocate the contours array when necessary
*/
new_max = (FT_UInt) outline->n_contours;
old_max = hints->max_contours;
if ( new_max > old_max )
{
new_max = (new_max + 3) & ~3;
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
hints->max_contours = new_max;
}
/* then, reallocate the points, segments & edges arrays if needed --
* note that we reserved two additional point positions, used to
* hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
old_max = hints->max_points;
if ( new_max > old_max )
{
FT_Byte* items;
FT_ULong off1, off2, off3;
/* we store in a single buffer the following arrays:
*
* - an array of N AF_PointRec items
* - an array of 2*N AF_SegmentRec items
* - an array of 2*N AF_EdgeRec items
*
*/
new_max = ( new_max + 2 + 7 ) & ~7;
#define OFF_PAD2(x,y) (((x)+(y)-1) & ~((y)-1))
#define OFF_PADX(x,y) ((((x)+(y)-1)/(y))*(y))
#define OFF_PAD(x,y) ( ((y) & ((y)-1)) ? OFF_PADX(x,y) : OFF_PAD2(x,y) )
#undef OFF_INCREMENT
#define OFF_INCREMENT( _off, _type, _count ) \
( OFF_PAD( _off, sizeof(_type) ) + (_count)*sizeof(_type))
off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max*2 );
off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
FT_FREE( hints->points );
if ( FT_ALLOC( items, off3 ) )
{
hints->max_points = 0;
hints->axis[0].segments = NULL;
hints->axis[0].edges = NULL;
hints->axis[1].segments = NULL;
hints->axis[1].edges = NULL;
goto Exit;
}
/* readjust some pointers
*/
hints->max_points = new_max;
hints->points = (AF_Point) items;
hints->axis[0].segments = (AF_Segment)( items + off1 );
hints->axis[1].segments = hints->axis[0].segments + new_max;
hints->axis[0].edges = (AF_Edge) ( items + off2 );
hints->axis[1].edges = hints->axis[0].edges + new_max;
}
hints->num_points = outline->n_points;
hints->num_contours = outline->n_contours;
/* We can't rely on the value of `FT_Outline.flags' to know the fill */
/* direction used for a glyph, given that some fonts are broken (e.g. */
/* the Arphic ones). We thus recompute it each time we need to. */
/* */
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
{
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
}
hints->x_scale = x_scale;
hints->y_scale = y_scale;
hints->x_delta = x_delta;
hints->y_delta = y_delta;
points = hints->points;
if ( hints->num_points == 0 )
goto Exit;
{
AF_Point point;
AF_Point point_limit = points + hints->num_points;
/* compute coordinates & bezier flags */
{
FT_Vector* vec = outline->points;
char* tag = outline->tags;
for ( point = points; point < point_limit; point++, vec++, tag++ )
{
point->fx = vec->x;
point->fy = vec->y;
point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_CURVE_TAG_CONIC:
point->flags = AF_FLAG_CONIC;
break;
case FT_CURVE_TAG_CUBIC:
point->flags = AF_FLAG_CUBIC;
break;
default:
point->flags = 0;
;
}
}
}
/* compute `next' and `prev' */
{
FT_Int contour_index;
AF_Point prev;
AF_Point first;
AF_Point end;
contour_index = 0;
first = points;
end = points + outline->contours[0];
prev = end;
for ( point = points; point < point_limit; point++ )
{
point->prev = prev;
if ( point < end )
{
point->next = point + 1;
prev = point;
}
else
{
point->next = first;
contour_index++;
if ( point + 1 < point_limit )
{
end = points + outline->contours[contour_index];
first = point + 1;
prev = end;
}
}
}
}
/* set-up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
short* end = outline->contours;
short idx = 0;
for ( ; contour < contour_limit; contour++, end++ )
{
contour[0] = points + idx;
idx = (short)( end[0] + 1 );
}
}
/* compute directions of in & out vectors */
{
for ( point = points; point < point_limit; point++ )
{
AF_Point prev;
AF_Point next;
FT_Pos in_x, in_y, out_x, out_y;
prev = point->prev;
in_x = point->fx - prev->fx;
in_y = point->fy - prev->fy;
point->in_dir = af_direction_compute( in_x, in_y );
next = point->next;
out_x = next->fx - point->fx;
out_y = next->fy - point->fy;
point->out_dir = af_direction_compute( out_x, out_y );
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
Is_Weak_Point:
point->flags |= AF_FLAG_WEAK_INTERPOLATION;
}
else if ( point->out_dir == point->in_dir )
{
AF_Angle angle_in, angle_out, delta;
if ( point->out_dir != AF_DIR_NONE )
goto Is_Weak_Point;
angle_in = af_angle_atan( in_x, in_y );
angle_out = af_angle_atan( out_x, out_y );
delta = af_angle_diff( angle_in, angle_out );
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;
}
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
}
}
}
/* compute inflection points
*/
af_glyph_hints_compute_inflections( hints );
Exit:
return error;
}
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
{
AF_Point point = hints->points;
AF_Point limit = point + hints->num_points;
FT_Vector* vec = outline->points;
char* tag = outline->tags;
for ( ; point < limit; point++, vec++, tag++ )
{
vec->x = (FT_Pos) point->x;
vec->y = (FT_Pos) point->y;
if ( point->flags & AF_FLAG_CONIC )
tag[0] = FT_CURVE_TAG_CONIC;
else if ( point->flags & AF_FLAG_CUBIC )
tag[0] = FT_CURVE_TAG_CUBIC;
else
tag[0] = FT_CURVE_TAG_ON;
}
}
/*
*
* E D G E P O I N T G R I D - F I T T I N G
*
*/
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = & hints->axis[ dim ];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Edge edge;
for ( edge = edges; edge < edge_limit; edge++ )
{
/* move the points of each segment */
/* in each edge to the edge's position */
AF_Segment seg = edge->first;
do
{
AF_Point point = seg->first;
for (;;)
{
if ( dim == AF_DIMENSION_HORZ )
{
point->x = edge->pos;
point->flags |= AF_FLAG_TOUCH_X;
}
else
{
point->y = edge->pos;
point->flags |= AF_FLAG_TOUCH_Y;
}
if ( point == seg->last )
break;
point = point->next;
}
seg = seg->edge_next;
} while ( seg != edge->first );
}
}
/*
*
* S T R O N G P O I N T I N T E R P O L A T I O N
*
*/
/* hint the strong points -- this is equivalent to the TrueType `IP' */
/* hinting instruction */
FT_LOCAL_DEF( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_Point points = hints->points;
AF_Point point_limit = points + hints->num_points;
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
AF_Edge edge_limit = edges + axis->num_edges;
AF_Flags touch_flag;
if ( dim == AF_DIMENSION_HORZ )
touch_flag = AF_FLAG_TOUCH_X;
else
touch_flag = AF_FLAG_TOUCH_Y;
if ( edges < edge_limit )
{
AF_Point point;
AF_Edge edge;
for ( point = points; point < point_limit; point++ )
{
FT_Pos u, ou, fu; /* point position */
FT_Pos delta;
if ( point->flags & touch_flag )
continue;
/* if this point is candidate to weak interpolation, we will */
/* interpolate it after all strong points have been processed */
if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
!( point->flags & AF_FLAG_INFLECTION ) )
continue;
if ( dim == AF_DIMENSION_VERT )
{
u = point->fy;
ou = point->oy;
}
else
{
u = point->fx;
ou = point->ox;
}
fu = u;
/* is the point before the first edge? */
edge = edges;
delta = edge->fpos - u;
if ( delta >= 0 )
{
u = edge->pos - ( edge->opos - ou );
goto Store_Point;
}
/* is the point after the last edge? */
edge = edge_limit - 1;
delta = u - edge->fpos;
if ( delta >= 0 )
{
u = edge->pos + ( ou - edge->opos );
goto Store_Point;
}
{
FT_UInt min, max, mid;
FT_Pos fpos;
/* find enclosing edges */
min = 0;
max = edge_limit - edges;
while ( min < max )
{
mid = ( max + min ) >> 1;
edge = edges + mid;
fpos = edge->fpos;
if ( u < fpos )
max = mid;
else if ( u > fpos )
min = mid + 1;
else
{
/* we are on the edge */
u = edge->pos;
goto Store_Point;
}
}
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
/* assert( before && after && before != after ) */
if ( before->scale == 0 )
before->scale = FT_DivFix( after->pos - before->pos,
after->fpos - before->fpos );
u = before->pos + FT_MulFix( fu - before->fpos,
before->scale );
}
}
Store_Point:
/* save the point position */
if ( dim == AF_DIMENSION_HORZ )
point->x = u;
else
point->y = u;
point->flags |= touch_flag;
}
}
}
/*
*
* W E A K P O I N T I N T E R P O L A T I O N
*
*/
static void
af_iup_shift( AF_Point p1,
AF_Point p2,
AF_Point ref )
{
AF_Point p;
FT_Pos delta = ref->u - ref->v;
for ( p = p1; p < ref; p++ )
p->u = p->v + delta;
for ( p = ref + 1; p <= p2; p++ )
p->u = p->v + delta;
}
static void
af_iup_interp( AF_Point p1,
AF_Point p2,
AF_Point ref1,
AF_Point ref2 )
{
AF_Point p;
FT_Pos u;
FT_Pos v1 = ref1->v;
FT_Pos v2 = ref2->v;
FT_Pos d1 = ref1->u - v1;
FT_Pos d2 = ref2->u - v2;
if ( p1 > p2 )
return;
if ( v1 == v2 )
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v1 )
u += d1;
else
u += d2;
p->u = u;
}
return;
}
if ( v1 < v2 )
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v1 )
u += d1;
else if ( u >= v2 )
u += d2;
else
u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
p->u = u;
}
}
else
{
for ( p = p1; p <= p2; p++ )
{
u = p->v;
if ( u <= v2 )
u += d2;
else if ( u >= v1 )
u += d1;
else
u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
p->u = u;
}
}
}
FT_LOCAL_DEF( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim )
{
AF_Point points = hints->points;
AF_Point point_limit = points + hints->num_points;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
AF_Flags touch_flag;
AF_Point point;
AF_Point end_point;
AF_Point first_point;
/* PASS 1: Move segment points to edge positions */
if ( dim == AF_DIMENSION_HORZ )
{
touch_flag = AF_FLAG_TOUCH_X;
for ( point = points; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->ox;
}
}
else
{
touch_flag = AF_FLAG_TOUCH_Y;
for ( point = points; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->oy;
}
}
point = points;
for ( ; contour < contour_limit; contour++ )
{
point = *contour;
end_point = point->prev;
first_point = point;
while ( point <= end_point && !( point->flags & touch_flag ) )
point++;
if ( point <= end_point )
{
AF_Point first_touched = point;
AF_Point cur_touched = point;
point++;
while ( point <= end_point )
{
if ( point->flags & touch_flag )
{
/* we found two successive touched points; we interpolate */
/* all contour points between them */
af_iup_interp( cur_touched + 1, point - 1,
cur_touched, point );
cur_touched = point;
}
point++;
}
if ( cur_touched == first_touched )
{
/* this is a special case: only one point was touched in the */
/* contour; we thus simply shift the whole contour */
af_iup_shift( first_point, end_point, cur_touched );
}
else
{
/* now interpolate after the last touched point to the end */
/* of the contour */
af_iup_interp( cur_touched + 1, end_point,
cur_touched, first_touched );
/* if the first contour point isn't touched, interpolate */
/* from the contour start to the first touched point */
if ( first_touched > points )
af_iup_interp( first_point, first_touched - 1,
cur_touched, first_touched );
}
}
}
/* now save the interpolated values back to x/y */
if ( dim == AF_DIMENSION_HORZ )
{
for ( point = points; point < point_limit; point++ )
point->x = point->u;
}
else
{
for ( point = points; point < point_limit; point++ )
point->y = point->u;
}
}
+246
View File
@@ -0,0 +1,246 @@
#ifndef __AFHINTS_H__
#define __AFHINTS_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/*
* The definition of outline glyph hints. These are shared by all
* script analysis routines (until now)
*
*/
typedef enum
{
AF_DIMENSION_HORZ = 0, /* x coordinates, i.e. vertical segments & edges */
AF_DIMENSION_VERT = 1, /* y coordinates, i.e. horizontal segments & edges */
AF_DIMENSION_MAX /* do not remove */
} AF_Dimension;
/* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1+dir2 == 0' */
typedef enum
{
AF_DIR_NONE = 4,
AF_DIR_RIGHT = 1,
AF_DIR_LEFT = -1,
AF_DIR_UP = 2,
AF_DIR_DOWN = -2
} AF_Direction;
/* point hint flags */
typedef enum
{
AF_FLAG_NONE = 0,
/* point type flags */
AF_FLAG_CONIC = (1 << 0),
AF_FLAG_CUBIC = (1 << 1),
AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
/* point extremum flags */
AF_FLAG_EXTREMA_X = (1 << 2),
AF_FLAG_EXTREMA_Y = (1 << 3),
/* point roundness flags */
AF_FLAG_ROUND_X = (1 << 4),
AF_FLAG_ROUND_Y = (1 << 5),
/* point touch flags */
AF_FLAG_TOUCH_X = (1 << 6),
AF_FLAG_TOUCH_Y = (1 << 7),
/* candidates for weak interpolation have this flag set */
AF_FLAG_WEAK_INTERPOLATION = (1 << 8),
/* all inflection points in the outline have this flag set */
AF_FLAG_INFLECTION = (1 << 9)
} AF_Flags;
/* edge hint flags */
typedef enum
{
AF_EDGE_NORMAL = 0,
AF_EDGE_ROUND = (1 << 0),
AF_EDGE_SERIF = (1 << 1),
AF_EDGE_DONE = (1 << 2)
} AF_Edge_Flags;
typedef struct AF_PointRec_* AF_Point;
typedef struct AF_SegmentRec_* AF_Segment;
typedef struct AF_EdgeRec_* AF_Edge;
typedef struct AF_PointRec_
{
AF_Flags flags; /* point flags used by hinter */
FT_Pos ox, oy; /* original, scaled position */
FT_Pos fx, fy; /* original, unscaled position (font units) */
FT_Pos x, y; /* current position */
FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
AF_Direction in_dir; /* direction of inwards vector */
AF_Direction out_dir; /* direction of outwards vector */
AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */
} AF_PointRec;
typedef struct AF_SegmentRec_
{
AF_Edge_Flags flags; /* edge/segment flags for this segment */
AF_Direction dir; /* segment direction */
FT_Pos pos; /* position of segment */
FT_Pos min_coord; /* minimum coordinate of segment */
FT_Pos max_coord; /* maximum coordinate of segment */
AF_Edge edge; /* the segment's parent edge */
AF_Segment edge_next; /* link to next segment in parent edge */
AF_Segment link; /* (stem) link segment */
AF_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */
FT_Pos score; /* used during stem matching */
AF_Point first; /* first point in edge segment */
AF_Point last; /* last point in edge segment */
AF_Point* contour; /* ptr to first point of segment's contour */
} AF_SegmentRec;
typedef struct AF_EdgeRec_
{
FT_Pos fpos; /* original, unscaled position (font units) */
FT_Pos opos; /* original, scaled position */
FT_Pos pos; /* current position */
AF_Edge_Flags flags; /* edge flags */
AF_Direction dir; /* edge direction */
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link;
AF_Edge serif;
FT_Int num_linked;
FT_Int score;
AF_Segment first;
AF_Segment last;
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
FT_Int num_segments;
AF_Segment segments;
FT_Int num_edges;
AF_Edge edges;
AF_Direction major_dir;
} AF_AxisHintsRec, *AF_AxisHints;
typedef struct AF_GlyphHintsRec_
{
FT_Memory memory;
FT_Fixed x_scale;
FT_Pos x_delta;
FT_Fixed y_scale;
FT_Pos y_delta;
FT_Pos edge_distance_threshold;
FT_Int max_points;
FT_Int num_points;
AF_Point points;
FT_Int max_contours;
FT_Int num_contours;
AF_Point* contours;
AF_AxisHintsRec axis[ AF_DIMENSION_MAX ];
FT_UInt32 scaler_flags; /* copy of scaler flags */
FT_UInt32 other_flags; /* free for script-specific implementations */
AF_ScriptMetrics metrics;
} AF_GlyphHintsRec;
#define AF_HINTS_TEST_SCALER(h,f) ( (h)->scaler_flags & (f) )
#define AF_HINTS_TEST_OTHER(h,f) ( (h)->other_flags & (f) )
#define AF_HINTS_DO_HORIZONTAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_HORIZONTAL)
#define AF_HINTS_DO_VERTICAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_VERTICAL)
#define AF_HINTS_DO_ADVANCE(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_ADVANCE)
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
FT_LOCAL( void )
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
/* recomputes all AF_Point in a AF_GlyphHints from the definitions
* in a source outline
*/
FT_LOCAL( FT_Error )
af_glyph_hints_reset( AF_GlyphHints hints,
AF_Scaler scaler,
AF_ScriptMetrics metrics,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline );
FT_LOCAL( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
/* */
FT_END_HEADER
#endif /* __AFHINTS_H__ */
File diff suppressed because it is too large Load Diff
+168
View File
@@ -0,0 +1,168 @@
#ifndef __AFLATIN_H__
#define __AFLATIN_H__
#include "afhints.h"
FT_BEGIN_HEADER
/*
* the latin-specific script class
*
*/
FT_LOCAL( const AF_ScriptClassRec ) af_latin_script_class;
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
/*
* the following declarations could be embedded in the file "aflatin.c"
* they've been made semi-public to allow alternate script hinters to
* re-use some of them
*/
/*
* Latin (global) metrics management
*
*/
enum
{
AF_LATIN_BLUE_CAPITAL_TOP,
AF_LATIN_BLUE_CAPITAL_BOTTOM,
AF_LATIN_BLUE_SMALL_F_TOP,
AF_LATIN_BLUE_SMALL_TOP,
AF_LATIN_BLUE_SMALL_BOTTOM,
AF_LATIN_BLUE_SMALL_MINOR,
AF_LATIN_BLUE_MAX
};
#define AF_LATIN_IS_TOP_BLUE( b ) ( (b) == AF_LATIN_BLUE_CAPITAL_TOP || \
(b) == AF_LATIN_BLUE_SMALL_F_TOP || \
(b) == AF_LATIN_BLUE_SMALL_TOP )
#define AF_LATIN_MAX_WIDTHS 16
#define AF_LATIN_MAX_BLUES AF_LATIN_BLUE_MAX
enum
{
AF_LATIN_BLUE_ACTIVE = (1 << 0),
AF_LATIN_BLUE_TOP = (1 << 1),
AF_LATIN_BLUE_FLAG_MAX
};
typedef struct AF_LatinBlueRec_
{
AF_WidthRec ref;
AF_WidthRec shoot;
FT_UInt flags;
} AF_LatinBlueRec, *AF_LatinBlue;
typedef struct AF_LatinAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count;
AF_WidthRec widths[ AF_LATIN_MAX_WIDTHS ];
FT_Pos edge_distance_threshold;
/* ignored for horizontal metrics */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_LatinBlueRec blues[ AF_LATIN_BLUE_MAX ];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_LatinAxisRec, *AF_LatinAxis;
typedef struct AF_LatinMetricsRec_
{
AF_ScriptMetricsRec root;
FT_UInt units_per_em;
AF_LatinAxisRec axis[ AF_DIMENSION_MAX ];
} AF_LatinMetricsRec, *AF_LatinMetrics;
FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler );
/***************************************************************************/
/***************************************************************************/
/***** *****/
/***** L A T I N G L Y P H A N A L Y S I S *****/
/***** *****/
/***************************************************************************/
/***************************************************************************/
enum
{
AF_LATIN_HINTS_HORZ_SNAP = (1 << 0), /* enable stem width snapping */
AF_LATIN_HINTS_VERT_SNAP = (1 << 1), /* enable stem height snapping */
AF_LATIN_HINTS_STEM_ADJUST = (1 << 2), /* enable stem width/height adjustment */
AF_LATIN_HINTS_MONO = (1 << 3) /* indicate monochrome rendering */
};
#define AF_LATIN_HINTS_DO_HORZ_SNAP(h) \
AF_HINTS_TEST_OTHER(h,AF_LATIN_HINTS_HORZ_SNAP)
#define AF_LATIN_HINTS_DO_VERT_SNAP(h) \
AF_HINTS_TEST_OTHER(h,AF_LATIN_HINTS_VERT_SNAP)
#define AF_LATIN_HINTS_DO_STEM_ADJUST(h) \
AF_HINTS_TEST_OTHER(h,AF_LATIN_HINTS_STEM_ADJUST)
#define AF_LATIN_HINTS_DO_MONO(h) \
AF_HINTS_TEST_OTHER(h,AF_LATIN_HINTS_MONO)
/* this shouldn't normally be exported. However, other scripts might
* like to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim );
/* this shouldn't normally be exported. However, other scripts might
* want to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
AF_Dimension dim );
/* this shouldn't normally be exported. However, other scripts might
* want to use this function as-is
*/
FT_LOCAL( void )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim );
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */
+441
View File
@@ -0,0 +1,441 @@
#include "afloader.h"
#include "afhints.h"
#include "afglobal.h"
#include "aflatin.h"
FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory )
{
FT_Error error;
FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory );
error = FT_GlyphLoader_New( memory, &loader->gloader );
if ( !error )
{
error = FT_GlyphLoader_CreateExtra( loader->gloader );
if ( error )
{
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
}
return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face )
{
FT_Error error = 0;
loader->face = face;
loader->globals = (AF_FaceGlobals) face->autohint.data;
FT_GlyphLoader_Rewind( loader->gloader );
if ( loader->globals == NULL )
{
error = af_face_globals_new( face, &loader->globals );
if ( !error )
{
face->autohint.data = (FT_Pointer) loader->globals;
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free;
}
}
return error;
}
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
loader->face = NULL;
loader->globals = NULL;
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index,
FT_Int32 load_flags,
FT_UInt depth )
{
FT_Error error = 0;
FT_Face face = loader->face;
FT_GlyphLoader gloader = loader->gloader;
AF_ScriptMetrics metrics = loader->metrics;
AF_GlyphHints hints = &loader->hints;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal;
error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error )
goto Exit;
loader->transformed = internal->glyph_transformed;
if ( loader->transformed )
{
FT_Matrix inverse;
loader->trans_matrix = internal->glyph_matrix;
loader->trans_delta = internal->glyph_delta;
inverse = loader->trans_matrix;
FT_Matrix_Invert( &inverse );
FT_Vector_Transform( &loader->trans_delta, &inverse );
}
/* set linear metrics */
slot->linearHoriAdvance = slot->metrics.horiAdvance;
slot->linearVertAdvance = slot->metrics.vertAdvance;
switch ( slot->format )
{
case FT_GLYPH_FORMAT_OUTLINE:
/* translate the loaded glyph when an internal transform
* is needed
*/
if ( loader->transformed )
{
FT_Vector* point = slot->outline.points;
FT_Vector* limit = point + slot->outline.n_points;
for ( ; point < limit; point++ )
{
point->x += loader->trans_delta.x;
point->y += loader->trans_delta.y;
}
}
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader,
slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.outline.points,
slot->outline.points,
slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.extra_points,
slot->outline.points,
slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.outline.contours,
slot->outline.contours,
slot->outline.n_contours );
FT_ARRAY_COPY( gloader->current.outline.tags,
slot->outline.tags,
slot->outline.n_points );
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original horizontal phantom points (and ignore */
/* vertical ones) */
loader->pp1.x = hints->x_delta;
loader->pp1.y = hints->y_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
hints->x_scale ) + hints->x_delta;
loader->pp2.y = hints->y_delta;
/* be sure to check for spacing glyphs */
if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
error = metrics->clazz->script_hints_init( hints,
&gloader->current.outline,
metrics );
if ( error )
goto Exit;
/* apply the hints */
metrics->clazz->script_hints_apply( hints,
&gloader->current.outline,
metrics );
/* we now need to hint the metrics according to the change in */
/* width/positioning that occured during the hinting process */
{
FT_Pos old_advance, old_rsb, old_lsb, new_lsb;
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ];
AF_Edge edge1 = axis->edges; /* leftmost edge */
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */
old_advance = loader->pp2.x;
old_rsb = old_advance - edge2->opos;
old_lsb = edge1->opos;
new_lsb = edge1->pos;
loader->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
#if 0
/* try to fix certain bad advance computations */
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
loader->pp2.x += 64;
#endif
}
/* good, we simply add the glyph to our loader's base */
FT_GlyphLoader_Add( gloader );
break;
case FT_GLYPH_FORMAT_COMPOSITE:
{
FT_UInt nn, num_subglyphs = slot->num_subglyphs;
FT_UInt num_base_subgs, start_point;
FT_SubGlyph subglyph;
start_point = gloader->base.outline.n_points;
/* first of all, copy the subglyph descriptors in the glyph loader */
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.subglyphs,
slot->subglyphs,
num_subglyphs );
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
/* now, read each subglyph independently */
for ( nn = 0; nn < num_subglyphs; nn++ )
{
FT_Vector pp1, pp2;
FT_Pos x, y;
FT_UInt num_points, num_new_points, num_base_points;
/* gloader.current.subglyphs can change during glyph loading due */
/* to re-allocation -- we must recompute the current subglyph on */
/* each iteration */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
pp1 = loader->pp1;
pp2 = loader->pp2;
num_base_points = gloader->base.outline.n_points;
error = af_loader_load_g( loader, scaler, subglyph->index,
load_flags, depth + 1 );
if ( error )
goto Exit;
/* recompute subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
{
pp1 = loader->pp1;
pp2 = loader->pp2;
}
else
{
loader->pp1 = pp1;
loader->pp2 = pp2;
}
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
/* now perform the transform required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE |
FT_SUBGLYPH_FLAG_2X2 ) )
{
FT_Vector* cur = gloader->base.outline.points +
num_base_points;
FT_Vector* org = gloader->base.extra_points +
num_base_points;
FT_Vector* limit = cur + num_new_points;
for ( ; cur < limit; cur++, org++ )
{
FT_Vector_Transform( cur, &subglyph->transform );
FT_Vector_Transform( org, &subglyph->transform );
}
}
/* apply offset */
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
{
FT_Int k = subglyph->arg1;
FT_UInt l = subglyph->arg2;
FT_Vector* p1;
FT_Vector* p2;
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points )
{
error = FT_Err_Invalid_Composite;
goto Exit;
}
l += num_base_points;
/* for now, only use the current point coordinates; */
/* we may consider another approach in the near future */
p1 = gloader->base.outline.points + start_point + k;
p2 = gloader->base.outline.points + start_point + l;
x = p1->x - p2->x;
y = p1->y - p2->y;
}
else
{
x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
x = FT_PIX_ROUND(x);
y = FT_PIX_ROUND(y);
}
{
FT_Outline dummy = gloader->base.outline;
dummy.points += num_base_points;
dummy.n_points = (short)num_new_points;
FT_Outline_Translate( &dummy, x, y );
}
}
}
break;
default:
/* we don't support other formats (yet?) */
error = FT_Err_Unimplemented_Feature;
}
Hint_Metrics:
if ( depth == 0 )
{
FT_BBox bbox;
/* transform the hinted outline if needed */
if ( loader->transformed )
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax );
bbox.yMax = FT_PIX_CEIL( bbox.yMax );
slot->metrics.width = bbox.xMax - bbox.xMin;
slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width */
#if 0
if ( !FT_IS_FIXED_WIDTH( slot->face ) )
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
else
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
x_scale );
#else
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
#endif
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
/* now copy outline into glyph slot */
FT_GlyphLoader_Rewind( internal->loader );
error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
if ( error )
goto Exit;
slot->outline = internal->loader->base.outline;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
#ifdef DEBUG_HINTER
af_debug_hinter = hinter;
#endif
Exit:
return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags )
{
FT_Error error;
FT_Size size = face->size;
AF_ScalerRec scaler;
if ( !size )
return FT_Err_Invalid_Argument;
FT_ZERO( &scaler );
scaler.face = face;
scaler.x_scale = size->metrics.x_scale;
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.y_scale = size->metrics.y_scale;
scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0; /* XXX: fix this */
error = af_loader_reset( loader, face );
if ( !error )
{
AF_ScriptMetrics metrics;
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
if ( !error )
{
loader->metrics = metrics;
metrics->scaler = scaler;
if ( metrics->clazz->script_metrics_scale )
metrics->clazz->script_metrics_scale( metrics, &scaler );
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
}
}
return error;
}
+50
View File
@@ -0,0 +1,50 @@
#ifndef __AF_LOADER_H__
#define __AF_LOADER_H__
#include "afhints.h"
#include "afglobal.h"
FT_BEGIN_HEADER
typedef struct AF_LoaderRec_
{
FT_Face face; /* current face */
AF_FaceGlobals globals; /* current face globals */
FT_GlyphLoader gloader; /* glyph loader */
AF_GlyphHintsRec hints;
AF_ScriptMetrics metrics;
FT_Bool transformed;
FT_Matrix trans_matrix;
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
/* we don't handle vertical phantom points */
} AF_LoaderRec, *AF_Loader;
FT_LOCAL( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory );
FT_LOCAL( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face );
FT_LOCAL( void )
af_loader_done( AF_Loader loader );
FT_LOCAL( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags );
/* */
FT_END_HEADER
#endif /* __AF_LOADER_H__ */
+70
View File
@@ -0,0 +1,70 @@
#include "afmodule.h"
#include "afloader.h"
#include FT_INTERNAL_OBJECTS_H
typedef struct FT_AutofitterRec_
{
FT_ModuleRec root;
AF_LoaderRec loader[1];
} FT_AutofitterRec, *FT_Autofitter;
FT_CALLBACK_DEF( FT_Error )
af_autofitter_init( FT_Autofitter module )
{
return af_loader_init( module->loader, module->root.library->memory );
}
FT_CALLBACK_DEF( void )
af_autofitter_done( FT_Autofitter module )
{
af_loader_done( module->loader );
}
FT_CALLBACK_DEF( FT_Error )
af_autofitter_load_glyph( FT_Autofitter module,
FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_UNUSED(size);
return af_loader_load_glyph( module->loader, slot->face,
glyph_index, load_flags );
}
FT_CALLBACK_TABLE_DEF
const FT_AutoHinter_ServiceRec af_autofitter_service =
{
NULL,
NULL,
NULL,
(FT_AutoHinter_GlyphLoadFunc) af_autofitter_load_glyph
};
FT_CALLBACK_TABLE_DEF
const FT_Module_Class autofit_module_class =
{
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
"autofitter",
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
(const void*) &af_autofitter_service,
(FT_Module_Constructor) af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
(FT_Module_Requester) 0
};
/* END */
+16
View File
@@ -0,0 +1,16 @@
#ifndef __AFMODULE_H__
#define __AFMODULE_H__
#include <ft2build.h>
#include FT_MODULE_H
FT_BEGIN_HEADER
FT_CALLBACK_TABLE
const FT_Module_Class autofit_module_class;
FT_END_HEADER
#endif /* __AFMODULE_H__ */
+268
View File
@@ -0,0 +1,268 @@
#ifndef __AFTYPES_H__
#define __AFTYPES_H__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
FT_BEGIN_HEADER
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** D E B U G G I N G *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
#define xxAF_DEBUG
#ifdef AF_DEBUG
# include <stdio.h>
# define AF_LOG( x ) printf x
#else
# define AF_LOG( x ) do ; while ( 0 ) /* nothing */
#endif /* AF_DEBUG */
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** U T I L I T Y *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
typedef struct AF_WidthRec_
{
FT_Pos org; /* original position/width in font units */
FT_Pos cur; /* current/scaled position/width in device sub-pixels */
FT_Pos fit; /* current/fitted position/width in device sub-pixels */
} AF_WidthRec, *AF_Width;
FT_LOCAL( void )
af_sort_pos( FT_UInt count,
FT_Pos* table );
FT_LOCAL( void )
af_sort_widths( FT_UInt count,
AF_Width widths );
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** A N G L E T Y P E S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* Angle type. The auto-fitter doesn't need a very high angular accuracy,
* and this allows us to speed up some computations considerably with a
* light Cordic algorithm (see afangles.c)
*
*/
typedef FT_Int AF_Angle;
#define AF_ANGLE_PI 128
#define AF_ANGLE_2PI (AF_ANGLE_PI*2)
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2)
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4)
/*
* compute the angle of a given 2-D vector
*
*/
FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx,
FT_Pos dy );
/*
* computes "angle2 - angle1", the result is always within
* the range [ -AF_ANGLE_PI .. AF_ANGLE_PI-1 ]
*
*/
FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 );
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** O U T L I N E S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/* opaque handle to glyph-specific hints. see "afhints.h" for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
/* this structure is used to model an input glyph outline to
* the auto-hinter. The latter will set the "hints" field
* depending on the glyph's script
*/
typedef struct AF_OutlineRec_
{
FT_Face face;
FT_Outline outline;
FT_UInt outline_resolution;
FT_Int advance;
FT_UInt metrics_resolution;
AF_GlyphHints hints;
} AF_OutlineRec;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** S C A L E R S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* A scaler models the target pixel device that will receive the
* auto-hinted glyph image
*
*/
typedef enum
{
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
} AF_ScalerFlags;
typedef struct AF_ScalerRec_
{
FT_Face face; /* source font face */
FT_Fixed x_scale; /* from font units to 1/64th device pixels */
FT_Fixed y_scale; /* from font units to 1/64th device pixels */
FT_Pos x_delta; /* in 1/64th device pixels */
FT_Pos y_delta; /* in 1/64th device pixels */
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc.. */
FT_UInt32 flags; /* additionnal control flags, see above */
} AF_ScalerRec, *AF_Scaler;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** S C R I P T S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* the list of know scripts. Each different script correspond to the
* following information:
*
* - a set of Unicode ranges to test weither the face supports the
* script
*
* - a specific global analyzer that will compute global metrics
* specific to the script.
*
* - a specific glyph analyzer that will compute segments and
* edges for each glyph covered by the script
*
* - a specific grid-fitting algorithm that will distort the
* scaled glyph outline according to the results of the glyph
* analyzer
*
* note that a given analyzer and/or grid-fitting algorithm can be
* used by more than one script
*/
typedef enum
{
AF_SCRIPT_NONE = 0,
AF_SCRIPT_LATIN = 1,
/* add new scripts here. don't forget to update the list in "afglobal.c" */
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
typedef struct AF_ScriptMetricsRec_
{
AF_ScriptClass clazz;
AF_ScalerRec scaler;
} AF_ScriptMetricsRec, *AF_ScriptMetrics;
/* this function parses a FT_Face to compute global metrics for
* a specific script
*/
typedef FT_Error (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
FT_Face face );
typedef void (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
AF_Scaler scaler );
typedef void (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
FT_UInt32 last;
} AF_Script_UniRangeRec;
typedef const AF_Script_UniRangeRec * AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
AF_Script script;
AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
FT_UInt script_metrics_size;
AF_Script_InitMetricsFunc script_metrics_init;
AF_Script_ScaleMetricsFunc script_metrics_scale;
AF_Script_DoneMetricsFunc script_metrics_done;
AF_Script_InitHintsFunc script_hints_init;
AF_Script_ApplyHintsFunc script_hints_apply;
} AF_ScriptClassRec;
/* */
FT_END_HEADER
#endif /* __AFTYPES_H__ */
+9
View File
@@ -0,0 +1,9 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "afangles.c"
#include "afglobal.c"
#include "afhints.c"
#include "afdummy.c"
#include "aflatin.c"
#include "afloader.c"
#include "afmodule.c"
@@ -120,4 +120,4 @@ Legal Terms
Packages, you indicate that you understand and accept all the
terms of this license.
--- end of license.txt ---
--- end of license.txt ---
+1 -1
View File
@@ -144,4 +144,4 @@
return delta;
}
/* END */
/* END */
+1 -1
View File
@@ -61,4 +61,4 @@ FT_END_HEADER
#endif /* __AHANGLES_H__ */
/* END */
/* END */
+1 -1
View File
@@ -37,4 +37,4 @@
#endif /* __AHERRORS_H__ */
/* END */
/* END */
+14 -10
View File
@@ -4,7 +4,7 @@
/* */
/* Routines used to compute global metrics automatically (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -27,8 +27,10 @@
#define MAX_TEST_CHARACTERS 12
/* cf. AH_BLUE_XXX constants in ahtypes.h */
static
const char* blue_chars[AH_BLUE_MAX] =
const char* const blue_chars[AH_BLUE_MAX] =
{
"THEZOCQS",
"HEZLOCUS",
@@ -93,8 +95,8 @@
goto Exit;
/* we compute the blues simply by loading each character from the */
/* 'blue_chars[blues]' string, then compute its top-most and */
/* bottom-most points */
/* `blue_chars[blues]' string, then compute its top-most or */
/* bottom-most points (depending on `AH_IS_TOP_BLUE') */
AH_LOG(( "blue zones computation\n" ));
AH_LOG(( "------------------------------------------------\n" ));
@@ -103,6 +105,7 @@
{
const char* p = blue_chars[blue];
const char* limit = p + MAX_TEST_CHARACTERS;
FT_Pos *blue_ref, *blue_shoot;
@@ -235,8 +238,8 @@
AH_LOG(( "\n" ));
/* we have computed the contents of the `rounds' and `flats' tables, */
/* now determine the reference and overshoot position of the blue; */
/* we simply take the median value after a simple short */
/* now determine the reference and overshoot position of the blue -- */
/* we simply take the median value after a simple sort */
sort_values( num_rounds, rounds );
sort_values( num_flats, flats );
@@ -312,7 +315,7 @@
/* stem height of the "-", but it wasn't too good. Moreover, we now */
/* have a single character that gives us standard width and height. */
{
FT_UInt glyph_index;
FT_UInt glyph_index;
glyph_index = FT_Get_Char_Index( hinter->face, 'o' );
@@ -323,7 +326,8 @@
if ( error )
goto Exit;
error = ah_outline_load( hinter->glyph, 0x10000L, 0x10000L, hinter->face );
error = ah_outline_load( hinter->glyph, 0x10000L, 0x10000L,
hinter->face );
if ( error )
goto Exit;
@@ -375,7 +379,7 @@
}
/* Now, compute the edge distance threshold as a fraction of the */
/* smallest width in the font. Set it in `hinter.glyph' too! */
/* smallest width in the font. Set it in `hinter->glyph' too! */
if ( edge_distance_threshold == 32000 )
edge_distance_threshold = 50;
@@ -395,4 +399,4 @@
}
/* END */
/* END */
+9 -6
View File
@@ -5,7 +5,7 @@
/* Routines used to compute global metrics automatically */
/* (specification). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -34,13 +34,16 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_CHESTER_SMALL_F
# define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || (b) == AH_BLUE_SMALL_F_TOP || (b) == AH_BLUE_SMALL_TOP )
#define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \
(b) == AH_BLUE_SMALL_F_TOP || \
(b) == AH_BLUE_SMALL_TOP )
#else /* !CHESTER_SMALL_F */
#else /* !FT_CONFIG_CHESTER_SMALL_F */
# define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || (b) == AH_BLUE_SMALL_TOP )
#define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \
(b) == AH_BLUE_SMALL_TOP )
#endif /* !CHESTER_SMALL_F */
#endif /* !FT_CONFIG_CHESTER_SMALL_F */
/* compute global metrics automatically */
@@ -53,4 +56,4 @@ FT_END_HEADER
#endif /* __AHGLOBAL_H__ */
/* END */
/* END */
+216 -112
View File
@@ -5,7 +5,7 @@
/* Routines used to load and analyze a given glyph before hinting */
/* (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -120,8 +120,8 @@
: ( seg->dir == AH_DIR_RIGHT
? "right"
: "none" ) ) ),
seg->link ? (seg->link-segments) : -1,
seg->serif ? (seg->serif-segments) : -1,
seg->link ? ( seg->link - segments ) : -1,
seg->serif ? ( seg->serif - segments ) : -1,
(int)seg->num_linked,
seg->first - points,
seg->last - points );
@@ -135,18 +135,20 @@
#endif /* AH_DEBUG */
/* compute the direction value of a given vector.. */
/* compute the direction value of a given vector */
static AH_Direction
ah_compute_direction( FT_Pos dx,
FT_Pos dy )
{
AH_Direction dir;
FT_Pos ax = ABS( dx );
FT_Pos ay = ABS( dy );
FT_Pos ax = FT_ABS( dx );
FT_Pos ay = FT_ABS( dy );
dir = AH_DIR_NONE;
/* atan(1/12) == 4.7 degrees */
/* test for vertical direction */
if ( ax * 12 < ay )
{
@@ -163,10 +165,10 @@
/* this function is used by ah_get_orientation (see below) to test */
/* the fill direction of a given bbox extrema */
/* the fill direction of given bbox extremum */
static FT_Int
ah_test_extrema( FT_Outline* outline,
FT_Int n )
ah_test_extremum( FT_Outline* outline,
FT_Int n )
{
FT_Vector *prev, *cur, *next;
FT_Pos product;
@@ -175,7 +177,9 @@
/* we need to compute the `previous' and `next' point */
/* for these extrema */
/* for this extremum; we check whether the extremum */
/* is start or end of a contour and providing */
/* appropriate values if so */
cur = outline->points + n;
prev = cur - 1;
next = cur + 1;
@@ -183,7 +187,7 @@
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
last = outline->contours[c];
last = outline->contours[c];
if ( n == first )
prev = outline->points + last;
@@ -194,6 +198,10 @@
first = last + 1;
}
/* compute the vectorial product -- since we know that the angle */
/* is <= 180 degrees (otherwise it wouldn't be an extremum) we */
/* can determine the filling orientation if the product is */
/* either positive or negative */
product = FT_MulDiv( cur->x - prev->x, /* in.x */
next->y - cur->y, /* out.y */
0x40 )
@@ -218,7 +226,7 @@
/* We do this by computing bounding box points, and computing their */
/* curvature. */
/* */
/* The function returns either 1 or -1. */
/* The function returns either 1 or 2. */
/* */
static FT_Int
ah_get_orientation( FT_Outline* outline )
@@ -272,20 +280,20 @@
}
}
/* test orientation of the xmin */
n = ah_test_extrema( outline, indices_xMin );
/* test orientation of the extrema */
n = ah_test_extremum( outline, indices_xMin );
if ( n )
goto Exit;
n = ah_test_extrema( outline, indices_yMin );
n = ah_test_extremum( outline, indices_yMin );
if ( n )
goto Exit;
n = ah_test_extrema( outline, indices_xMax );
n = ah_test_extremum( outline, indices_xMax );
if ( n )
goto Exit;
n = ah_test_extrema( outline, indices_yMax );
n = ah_test_extremum( outline, indices_yMax );
if ( !n )
n = 1;
@@ -306,14 +314,14 @@
ah_outline_new( FT_Memory memory,
AH_Outline* aoutline )
{
FT_Error error;
AH_Outline outline;
FT_Error error;
AH_Outline outline;
if ( !FT_NEW( outline ) )
{
outline->memory = memory;
*aoutline = outline;
*aoutline = outline;
}
return error;
@@ -410,7 +418,7 @@
/* first of all, reallocate the contours array if necessary */
if ( num_contours > outline->max_contours )
{
FT_Int new_contours = ( num_contours + 3 ) & -4;
FT_Int new_contours = FT_PAD_CEIL( num_contours, 4 );
if ( FT_RENEW_ARRAY( outline->contours,
@@ -427,7 +435,7 @@
/* */
if ( num_points + 2 > outline->max_points )
{
FT_Int news = ( num_points + 2 + 7 ) & -8;
FT_Int news = FT_PAD_CEIL( num_points + 2, 8 );
FT_Int max = outline->max_points;
@@ -452,7 +460,7 @@
/* We can't rely on the value of `FT_Outline.flags' to know the fill */
/* direction used for a glyph, given that some fonts are broken (e.g. */
/* the Arphic ones). We thus recompute it each time we need to. */
/* the Arphic ones). We thus recompute it each time we need to. */
/* */
outline->vert_major_dir = AH_DIR_UP;
outline->horz_major_dir = AH_DIR_LEFT;
@@ -479,7 +487,7 @@
/* compute coordinates */
{
FT_Vector* vec = source->points;
FT_Vector* vec = source->points;
for ( point = points; point < point_limit; vec++, point++ )
@@ -503,9 +511,11 @@
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_CURVE_TAG_CONIC:
point->flags = AH_FLAG_CONIC; break;
point->flags = AH_FLAG_CONIC;
break;
case FT_CURVE_TAG_CUBIC:
point->flags = AH_FLAG_CUBIC; break;
point->flags = AH_FLAG_CUBIC;
break;
default:
;
}
@@ -585,7 +595,7 @@
point->out_dir = ah_compute_direction( ovec.x, ovec.y );
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
if ( point->flags & (AH_FLAG_CONIC | AH_FLAG_CUBIC) )
if ( point->flags & ( AH_FLAG_CONIC | AH_FLAG_CUBIC ) )
{
Is_Weak_Point:
point->flags |= AH_FLAG_WEAK_INTERPOLATION;
@@ -631,48 +641,70 @@
AH_Point point_limit = point + outline->num_points;
for ( ; point < point_limit; point++ )
switch ( source )
{
FT_Pos u, v;
switch ( source )
case AH_UV_FXY:
for ( ; point < point_limit; point++ )
{
case AH_UV_FXY:
u = point->fx;
v = point->fy;
break;
case AH_UV_FYX:
u = point->fy;
v = point->fx;
break;
case AH_UV_OXY:
u = point->ox;
v = point->oy;
break;
case AH_UV_OYX:
u = point->oy;
v = point->ox;
break;
case AH_UV_YX:
u = point->y;
v = point->x;
break;
case AH_UV_OX:
u = point->x;
v = point->ox;
break;
case AH_UV_OY:
u = point->y;
v = point->oy;
break;
default:
u = point->x;
v = point->y;
break;
point->u = point->fx;
point->v = point->fy;
}
break;
case AH_UV_FYX:
for ( ; point < point_limit; point++ )
{
point->u = point->fy;
point->v = point->fx;
}
break;
case AH_UV_OXY:
for ( ; point < point_limit; point++ )
{
point->u = point->ox;
point->v = point->oy;
}
break;
case AH_UV_OYX:
for ( ; point < point_limit; point++ )
{
point->u = point->oy;
point->v = point->ox;
}
break;
case AH_UV_YX:
for ( ; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->x;
}
break;
case AH_UV_OX:
for ( ; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->ox;
}
break;
case AH_UV_OY:
for ( ; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->oy;
}
break;
default:
for ( ; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->y;
}
point->u = u;
point->v = v;
}
}
@@ -681,8 +713,8 @@
static void
ah_outline_compute_inflections( AH_Outline outline )
{
AH_Point* contour = outline->contours;
AH_Point* contour_limit = contour + outline->num_contours;
AH_Point* contour = outline->contours;
AH_Point* contour_limit = contour + outline->num_contours;
/* load original coordinates in (u,v) */
@@ -692,10 +724,10 @@
for ( ; contour < contour_limit; contour++ )
{
FT_Vector vec;
AH_Point point = contour[0];
AH_Point first = point;
AH_Point start = point;
AH_Point end = point;
AH_Point point = contour[0];
AH_Point first = point;
AH_Point start = point;
AH_Point end = point;
AH_Point before;
AH_Point after;
AH_Angle angle_in, angle_seg, angle_out;
@@ -769,7 +801,6 @@
{
/* diff_in and diff_out have different signs, we have */
/* inflection points here... */
do
{
start->flags |= AH_FLAG_INFLECTION;
@@ -829,10 +860,10 @@
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
AH_Point point = contour[0];
AH_Point last = point->prev;
int on_edge = 0;
FT_Pos min_pos = +32000; /* minimum segment pos != min_coord */
AH_Point point = contour[0];
AH_Point last = point->prev;
int on_edge = 0;
FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
FT_Bool passed;
@@ -850,11 +881,11 @@
}
#endif
if ( point == last ) /* skip singletons -- just in case? */
if ( point == last ) /* skip singletons -- just in case */
continue;
if ( ABS( last->out_dir ) == major_dir &&
ABS( point->out_dir ) == major_dir )
if ( FT_ABS( last->out_dir ) == major_dir &&
FT_ABS( point->out_dir ) == major_dir )
{
/* we are already on an edge, try to locate its start */
last = point;
@@ -862,7 +893,7 @@
for (;;)
{
point = point->prev;
if ( ABS( point->out_dir ) != major_dir )
if ( FT_ABS( point->out_dir ) != major_dir )
{
point = point->next;
break;
@@ -927,7 +958,7 @@
passed = 1;
}
if ( !on_edge && ABS( point->out_dir ) == major_dir )
if ( !on_edge && FT_ABS( point->out_dir ) == major_dir )
{
/* this is the start of a new segment! */
segment_dir = point->out_dir;
@@ -941,6 +972,8 @@
segment->first = point;
segment->last = point;
segment->contour = contour;
segment->score = 32000;
segment->link = NULL;
on_edge = 1;
#ifdef AH_HINT_METRICS
@@ -963,11 +996,11 @@
/* we do this by inserting fake segments when needed */
if ( dimension == 0 )
{
AH_Point point = outline->points;
AH_Point point_limit = point + outline->num_points;
AH_Point point = outline->points;
AH_Point point_limit = point + outline->num_points;
FT_Pos min_pos = 32000;
FT_Pos max_pos = -32000;
FT_Pos min_pos = 32000;
FT_Pos max_pos = -32000;
min_point = 0;
@@ -1002,6 +1035,8 @@
segment->first = min_point;
segment->last = min_point;
segment->pos = min_pos;
segment->score = 32000;
segment->link = NULL;
num_segments++;
segment++;
@@ -1018,6 +1053,8 @@
segment->first = max_point;
segment->last = max_point;
segment->pos = max_pos;
segment->score = 32000;
segment->link = NULL;
num_segments++;
segment++;
@@ -1030,6 +1067,7 @@
segments = outline->vert_segments;
major_dir = AH_DIR_UP;
p_num_segments = &outline->num_vsegments;
ah_setup_uv( outline, AH_UV_FXY );
}
}
@@ -1038,22 +1076,22 @@
FT_LOCAL_DEF( void )
ah_outline_link_segments( AH_Outline outline )
{
AH_Segment segments;
AH_Segment segment_limit;
int dimension;
AH_Segment segments;
AH_Segment segment_limit;
AH_Direction major_dir;
int dimension;
ah_setup_uv( outline, AH_UV_FYX );
segments = outline->horz_segments;
segment_limit = segments + outline->num_hsegments;
major_dir = outline->horz_major_dir;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AH_Segment seg1;
AH_Segment seg2;
#if 0
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
@@ -1070,7 +1108,7 @@
if ( best_segment )
best_score = seg1->score;
else
best_score = 32000;
best_score = +32000;
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 )
@@ -1125,28 +1163,86 @@
{
seg1->link = best_segment;
seg1->score = best_score;
best_segment->num_linked++;
}
}
#endif /* 0 */
} /* edges 1 */
#if 1
/* the following code does the same, but much faster! */
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
/* the fake segments are introduced to hint the metrics -- */
/* we must never link them to anything */
if ( seg1->first == seg1->last || seg1->dir != major_dir )
continue;
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 )
{
FT_Pos pos1 = seg1->pos;
FT_Pos pos2 = seg2->pos;
FT_Pos dist = pos2 - pos1;
if ( dist < 0 )
continue;
{
FT_Pos min = seg1->min_coord;
FT_Pos max = seg1->max_coord;
FT_Pos len, score;
if ( min < seg2->min_coord )
min = seg2->min_coord;
if ( max > seg2->max_coord )
max = seg2->max_coord;
len = max - min;
if ( len >= 8 )
{
score = dist + 3000 / len;
if ( score < seg1->score )
{
seg1->score = score;
seg1->link = seg2;
}
if ( score < seg2->score )
{
seg2->score = score;
seg2->link = seg1;
}
}
}
}
}
#endif /* 1 */
/* now, compute the `serif' segments */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
seg2 = seg1->link;
if ( seg2 && seg2->link != seg1 )
if ( seg2 )
{
seg1->link = 0;
seg1->serif = seg2->link;
seg2->num_linked++;
if ( seg2->link != seg1 )
{
seg1->link = 0;
seg1->serif = seg2->link;
}
}
}
ah_setup_uv( outline, AH_UV_FXY );
segments = outline->vert_segments;
segment_limit = segments + outline->num_vsegments;
major_dir = outline->vert_major_dir;
}
}
@@ -1199,6 +1295,9 @@
if ( edge_distance_threshold > 64 / 4 )
edge_distance_threshold = 64 / 4;
edge_distance_threshold = FT_DivFix( edge_distance_threshold,
scale );
edge_limit = edges;
for ( seg = segments; seg < segment_limit; seg++ )
{
@@ -1215,7 +1314,6 @@
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, scale );
if ( dist < edge_distance_threshold )
{
found = edge;
@@ -1253,7 +1351,6 @@
edge->last = seg;
}
}
*p_num_edges = (FT_Int)( edge_limit - edges );
@@ -1264,13 +1361,19 @@
/* */
/* - edge's main direction */
/* - stem edge, serif edge or both (which defaults to stem then) */
/* - rounded edge, straigth or both (which defaults to straight) */
/* - rounded edge, straight or both (which defaults to straight) */
/* - link for edge */
/* */
/*********************************************************************/
/* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */
/* Note that I've tried to remove this loop, setting
* the "edge" field of each segment directly in the
* code above. For some reason, it slows down execution
* speed -- on a Sun.
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
seg = edge->first;
@@ -1358,12 +1461,12 @@
}
else
edge->link = edge2;
#else /* !CHESTER_SERIF */
#else /* !FT_CONFIG_CHESTER_SERIF */
if ( is_serif )
edge->serif = edge2;
else
edge->link = edge2;
#endif
#endif /* !FT_CONFIG_CHESTER_SERIF */
}
seg = seg->edge_next;
@@ -1383,10 +1486,10 @@
edge->dir = up_dir;
else if ( ups < downs )
edge->dir = - up_dir;
edge->dir = -up_dir;
else if ( ups == downs )
edge->dir = 0; /* both up and down !! */
edge->dir = 0; /* both up and down! */
/* gets rid of serifs if link is set */
/* XXX: This gets rid of many unpleasant artefacts! */
@@ -1459,7 +1562,7 @@
ref = globals->blue_refs[blue];
shoot = globals->blue_shoots[blue];
dist = ref-shoot;
dist = ref - shoot;
if ( dist < 0 )
dist = -dist;
@@ -1477,7 +1580,7 @@
return;
}
/* compute for each horizontal edge, which blue zone is closer */
/* for each horizontal edge search the blue zone which is closest */
for ( ; edge < edge_limit; edge++ )
{
AH_Blue blue;
@@ -1493,7 +1596,7 @@
best_dist = 64 / 2;
#else
if ( best_dist > 64 / 4 )
best_dist = 64 / 4;
best_dist = 64 / 4;
#endif
for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ )
@@ -1507,6 +1610,7 @@
FT_Bool is_major_dir =
FT_BOOL( edge->dir == outline->horz_major_dir );
if ( !blue_active[blue] )
continue;
@@ -1569,7 +1673,7 @@
/* ah_outline_scale_blue_edges */
/* */
/* <Description> */
/* This functions must be called before hinting in order to re-adjust */
/* This function must be called before hinting in order to re-adjust */
/* the contents of the detected edges (basically change the `blue */
/* edge' pointer from `design units' to `scaled ones'). */
/* */
@@ -1592,4 +1696,4 @@
}
/* END */
/* END */
+1 -1
View File
@@ -92,4 +92,4 @@ FT_END_HEADER
#endif /* __AHGLYPH_H__ */
/* END */
/* END */
+277 -142
View File
@@ -4,7 +4,7 @@
/* */
/* Glyph hinter (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -27,11 +27,12 @@
#include FT_OUTLINE_H
#define FACE_GLOBALS( face ) ((AH_Face_Globals)(face)->autohint.data)
#define FACE_GLOBALS( face ) ( (AH_Face_Globals)(face)->autohint.data )
#define AH_USE_IUP
#define OPTIM_STEM_SNAP
/*************************************************************************/
/*************************************************************************/
/**** ****/
@@ -70,7 +71,7 @@
}
}
scaled = (reference+32) & -64;
scaled = FT_PIX_ROUND( reference );
if ( width >= reference )
{
@@ -88,7 +89,9 @@
/* compute the snapped width of a given stem */
#ifdef FT_CONFIG_CHESTER_SERIF
static FT_Pos
ah_compute_stem_width( AH_Hinter hinter,
int vertical,
@@ -114,7 +117,7 @@
else if ( ( vertical && !hinter->do_vert_snapping ) ||
( !vertical && !hinter->do_horz_snapping ) )
{
/* smooth hinting process, very lightly quantize the stem width */
/* smooth hinting process: very lightly quantize the stem width */
/* */
/* leave the widths of serifs alone */
@@ -148,8 +151,8 @@
if ( dist < 3 * 64 )
{
delta = ( dist & 63 );
dist &= -64;
delta = dist & 63;
dist &= -64;
if ( delta < 10 )
dist += delta;
@@ -164,12 +167,12 @@
dist += delta;
}
else
dist = ( dist + 32 ) & -64;
dist = ( dist + 32 ) & ~63;
}
}
else
{
/* strong hinting process, snap the stem width to integer pixels */
/* strong hinting process: snap the stem width to integer pixels */
/* */
if ( vertical )
{
@@ -178,13 +181,13 @@
/* in the case of vertical hinting, always round */
/* the stem heights to integer pixels */
if ( dist >= 64 )
dist = ( dist + 16 ) & -64;
dist = ( dist + 16 ) & ~63;
else
dist = 64;
}
else
{
dist = ah_snap_width( globals->widths, globals->num_widths, dist );
dist = ah_snap_width( globals->widths, globals->num_widths, dist );
if ( hinter->flags & AH_HINTER_MONOCHROME )
{
@@ -193,7 +196,7 @@
if ( dist < 64 )
dist = 64;
else
dist = ( dist + 32 ) & -64;
dist = ( dist + 32 ) & ~63;
}
else
{
@@ -204,10 +207,10 @@
dist = ( dist + 64 ) >> 1;
else if ( dist < 128 )
dist = ( dist + 22 ) & -64;
dist = ( dist + 22 ) & ~63;
else
/* XXX: round otherwise, prevent color fringes in LCD mode */
dist = ( dist + 32 ) & -64;
/* XXX: round otherwise to prevent color fringes in LCD mode */
dist = ( dist + 32 ) & ~63;
}
}
}
@@ -218,7 +221,9 @@
return dist;
}
#else /* !CHESTER_SERIF */
#else /* !FT_CONFIG_CHESTER_SERIF */
static FT_Pos
ah_compute_stem_width( AH_Hinter hinter,
int vertical,
@@ -242,7 +247,7 @@
else if ( ( vertical && !hinter->do_vert_snapping ) ||
( !vertical && !hinter->do_horz_snapping ) )
{
/* smooth hinting process, very lightly quantize the stem width */
/* smooth hinting process: very lightly quantize the stem width */
/* */
if ( dist < 64 )
dist = 64;
@@ -263,8 +268,8 @@
if ( dist < 3 * 64 )
{
delta = ( dist & 63 );
dist &= -64;
delta = dist & 63;
dist &= -64;
if ( delta < 10 )
dist += delta;
@@ -279,12 +284,12 @@
dist += delta;
}
else
dist = ( dist + 32 ) & -64;
dist = ( dist + 32 ) & ~63;
}
}
else
{
/* strong hinting process, snap the stem width to integer pixels */
/* strong hinting process: snap the stem width to integer pixels */
/* */
if ( vertical )
{
@@ -293,13 +298,13 @@
/* in the case of vertical hinting, always round */
/* the stem heights to integer pixels */
if ( dist >= 64 )
dist = ( dist + 16 ) & -64;
dist = ( dist + 16 ) & ~63;
else
dist = 64;
}
else
{
dist = ah_snap_width( globals->widths, globals->num_widths, dist );
dist = ah_snap_width( globals->widths, globals->num_widths, dist );
if ( hinter->flags & AH_HINTER_MONOCHROME )
{
@@ -308,7 +313,7 @@
if ( dist < 64 )
dist = 64;
else
dist = ( dist + 32 ) & -64;
dist = ( dist + 32 ) & ~63;
}
else
{
@@ -319,10 +324,10 @@
dist = ( dist + 64 ) >> 1;
else if ( dist < 128 )
dist = ( dist + 22 ) & -64;
dist = ( dist + 22 ) & ~63;
else
/* XXX: round otherwise, prevent color fringes in LCD mode */
dist = ( dist + 32 ) & -64;
/* XXX: round otherwise to prevent color fringes in LCD mode */
dist = ( dist + 32 ) & ~63;
}
}
}
@@ -332,7 +337,8 @@
return dist;
}
#endif /* !CHESTER_SERIF */
#endif /* !FT_CONFIG_CHESTER_SERIF */
/* align one stem edge relative to the previous stem edge */
@@ -345,17 +351,23 @@
FT_Pos dist = stem_edge->opos - base_edge->opos;
#ifdef FT_CONFIG_CHESTER_SERIF
FT_Pos fitted_width = ah_compute_stem_width( hinter,
vertical,
dist,
base_edge->flags,
stem_edge->flags );
stem_edge->pos = base_edge->pos + fitted_width;
#else
stem_edge->pos = base_edge->pos +
ah_compute_stem_width( hinter, vertical, dist );
#endif
}
@@ -371,6 +383,7 @@
FT_UNUSED( hinter );
FT_UNUSED( vertical );
dist = serif->opos - base->opos;
if ( dist < 0 )
{
@@ -378,15 +391,16 @@
sign = -1;
}
/* do not touch serifs widths !! */
#if 0
/* do not touch serifs widths! */
if ( base->flags & AH_EDGE_DONE )
{
if ( dist >= 64 )
dist = (dist+8) & -64;
dist = ( dist + 8 ) & ~63;
else if ( dist <= 32 && !vertical )
dist = ( dist + 33 ) >> 1;
else
dist = 0;
}
@@ -407,14 +421,14 @@
/*************************************************************************/
/* Another alternative edge hinting algorithm */
static void
ah_hint_edges_3( AH_Hinter hinter )
FT_LOCAL_DEF( void )
ah_hinter_hint_edges( AH_Hinter hinter )
{
AH_Edge edges;
AH_Edge edge_limit;
AH_Outline outline = hinter->glyph;
FT_Int dimension;
FT_Int n_edges;
edges = outline->horz_edges;
@@ -454,7 +468,7 @@
{
edge1 = edge;
}
else if (edge2 && edge2->blue_edge)
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;
edge1 = edge2;
@@ -478,8 +492,8 @@
}
}
/* now, we will align all stem edges, trying to maintain the */
/* relative order of stems in the glyph.. */
/* now we will align all stem edges, trying to maintain the */
/* relative order of stems in the glyph */
for ( edge = edges; edge < edge_limit; edge++ )
{
AH_EdgeRec* edge2;
@@ -496,12 +510,11 @@
continue;
}
/* now, align the stem */
/* now align the stem */
/* this should not happen, but it's better to be safe. */
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge || edge2 < edge )
{
ah_align_linked_edge( hinter, edge2, edge, dimension );
edge->flags |= AH_EDGE_DONE;
continue;
@@ -509,15 +522,18 @@
if ( !anchor )
{
#ifdef FT_CONFIG_CHESTER_STEM
FT_Pos org_len, org_center, cur_len;
FT_Pos cur_pos1, error1, error2, u_off, d_off;
org_len = edge2->opos - edge->opos;
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
edge->flags, edge2->flags );
FT_Pos org_len, org_center, cur_len;
FT_Pos cur_pos1, error1, error2, u_off, d_off;
if (cur_len <= 64 )
org_len = edge2->opos - edge->opos;
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
edge->flags, edge2->flags );
if ( cur_len <= 64 )
u_off = d_off = 32;
else
{
@@ -529,7 +545,7 @@
{
org_center = edge->opos + ( org_len >> 1 );
cur_pos1 = ( org_center + 32 ) & -64;
cur_pos1 = FT_PIX_ROUND( org_center );
error1 = org_center - ( cur_pos1 - u_off );
if ( error1 < 0 )
@@ -549,46 +565,56 @@
}
else
edge->pos = ( edge->opos + 32 ) & -64;
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
edge->flags |= AH_EDGE_DONE;
ah_align_linked_edge( hinter, edge, edge2, dimension );
#else /* !FT_CONFIG_CHESTER_STEM */
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
edge->flags |= AH_EDGE_DONE;
ah_align_linked_edge( hinter, edge, edge2, dimension );
#else /* !CHESTER_STEM */
edge->pos = ( edge->opos + 32 ) & -64;
anchor = edge;
edge->flags |= AH_EDGE_DONE;
#endif /* !FT_CONFIG_CHESTER_STEM */
ah_align_linked_edge( hinter, edge, edge2, dimension );
#endif /* !CHESTER_STEM */
}
else
{
FT_Pos org_pos, org_len, org_center, cur_len;
FT_Pos cur_pos1, cur_pos2, delta1, delta2;
FT_Pos org_pos, org_len, org_center, cur_len;
FT_Pos cur_pos1, cur_pos2, delta1, delta2;
org_pos = anchor->pos + (edge->opos - anchor->opos);
org_pos = anchor->pos + ( edge->opos - anchor->opos );
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
#ifdef FT_CONFIG_CHESTER_SERIF
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
edge->flags, edge2->flags );
#else /* !CHESTER_SERIF */
cur_len = ah_compute_stem_width( hinter, dimension, org_len );
#endif /* !CHESTER_SERIF */
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
edge->flags, edge2->flags );
#else /* !FT_CONFIG_CHESTER_SERIF */
cur_len = ah_compute_stem_width( hinter, dimension, org_len );
#endif /* !FT_CONFIG_CHESTER_SERIF */
#ifdef FT_CONFIG_CHESTER_STEM
if ( cur_len < 96 )
{
FT_Pos u_off, d_off;
cur_pos1 = ( org_center + 32 ) & -64;
cur_pos1 = FT_PIX_ROUND( org_center );
if (cur_len <= 64 )
u_off = d_off = 32;
@@ -598,11 +624,11 @@
d_off = 26;
}
delta1 = org_center - (cur_pos1 - u_off);
delta1 = org_center - ( cur_pos1 - u_off );
if ( delta1 < 0 )
delta1 = -delta1;
delta2 = org_center - (cur_pos1 + d_off);
delta2 = org_center - ( cur_pos1 + d_off );
if ( delta2 < 0 )
delta2 = -delta2;
@@ -616,20 +642,19 @@
}
else
{
org_pos = anchor->pos + (edge->opos - anchor->opos);
org_pos = anchor->pos + ( edge->opos - anchor->opos );
org_len = edge2->opos - edge->opos;
org_center = org_pos + ( org_len >> 1 );
cur_len = ah_compute_stem_width( hinter, dimension, org_len,
edge->flags, edge2->flags );
cur_pos1 = ( org_pos + 32 ) & -64;
cur_pos1 = FT_PIX_ROUND( org_pos );
delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
if ( delta1 < 0 )
delta1 = -delta1;
cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - cur_len;
cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center );
if ( delta2 < 0 )
delta2 = -delta2;
@@ -638,14 +663,14 @@
edge2->pos = edge->pos + cur_len;
}
#else /* !CHESTER_STEM */
#else /* !FT_CONFIG_CHESTER_STEM */
cur_pos1 = ( org_pos + 32 ) & -64;
cur_pos1 = FT_PIX_ROUND( org_pos );
delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center );
if ( delta1 < 0 )
delta1 = -delta1;
cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - cur_len;
cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center );
if ( delta2 < 0 )
delta2 = -delta2;
@@ -653,7 +678,7 @@
edge->pos = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2;
edge2->pos = edge->pos + cur_len;
#endif /* !CHESTER_STEM */
#endif /* !FT_CONFIG_CHESTER_STEM */
edge->flags |= AH_EDGE_DONE;
edge2->flags |= AH_EDGE_DONE;
@@ -663,11 +688,73 @@
}
}
/* make sure that lowercase m's maintain their symmetry */
/* In general, lowercase m's have six vertical edges if they are sans */
/* serif, or twelve if they are avec serif. This implementation is */
/* based on that assumption, and seems to work very well with most */
/* faces. However, if for a certain face this assumption is not */
/* true, the m is just rendered like before. In addition, any stem */
/* correction will only be applied to symmetrical glyphs (even if the */
/* glyph is not an m), so the potential for unwanted distortion is */
/* relatively low. */
/* We don't handle horizontal edges since we can't easily assure that */
/* the third (lowest) stem aligns with the base line; it might end up */
/* one pixel higher or lower. */
n_edges = (FT_Int)( edge_limit - edges );
if ( !dimension && ( n_edges == 6 || n_edges == 12 ) )
{
AH_EdgeRec *edge1, *edge2, *edge3;
FT_Pos dist1, dist2, span, delta;
if ( n_edges == 6 )
{
edge1 = edges;
edge2 = edges + 2;
edge3 = edges + 4;
}
else
{
edge1 = edges + 1;
edge2 = edges + 5;
edge3 = edges + 9;
}
dist1 = edge2->opos - edge1->opos;
dist2 = edge3->opos - edge2->opos;
span = dist1 - dist2;
if ( span < 0 )
span = -span;
if ( span < 8 )
{
delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
edge3->pos -= delta;
if ( edge3->link )
edge3->link->pos -= delta;
/* move the serifs along with the stem */
if ( n_edges == 12 )
{
( edges + 8 )->pos -= delta;
( edges + 11 )->pos -= delta;
}
edge3->flags |= AH_EDGE_DONE;
if ( edge3->link )
edge3->link->flags |= AH_EDGE_DONE;
}
}
if ( !has_serifs )
goto Next_Dimension;
/* now, hint the remaining edges (serifs and single) in order */
/* to complete our processing */
/* now hint the remaining edges (serifs and single) in order */
/* to complete our processing */
for ( edge = edges; edge < edge_limit; edge++ )
{
if ( edge->flags & AH_EDGE_DONE )
@@ -677,12 +764,12 @@
ah_align_serif_edge( hinter, edge->serif, edge, dimension );
else if ( !anchor )
{
edge->pos = ( edge->opos + 32 ) & -64;
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
}
else
edge->pos = anchor->pos +
( ( edge->opos-anchor->opos + 32 ) & -64 );
FT_PIX_ROUND( edge->opos - anchor->opos );
edge->flags |= AH_EDGE_DONE;
@@ -702,18 +789,6 @@
}
FT_LOCAL_DEF( void )
ah_hinter_hint_edges( AH_Hinter hinter )
{
/* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */
/* reduce the problem of the disappearing eye in the `e' of Times... */
/* also, creates some artifacts near the blue zones? */
{
ah_hint_edges_3( hinter );
}
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -785,6 +860,7 @@
/* hint the strong points -- this is equivalent to the TrueType `IP' */
/* hinting instruction */
static void
ah_hinter_align_strong_points( AH_Hinter hinter )
{
@@ -850,7 +926,7 @@
goto Store_Point;
}
/* is the point after the last edge ? */
/* is the point after the last edge? */
edge = edge_limit - 1;
delta = u - edge->fpos;
if ( delta >= 0 )
@@ -859,6 +935,51 @@
goto Store_Point;
}
#if 1
{
FT_UInt min, max, mid;
FT_Pos fpos;
/* find enclosing edges */
min = 0;
max = (FT_UInt)( edge_limit - edges );
while ( min < max )
{
mid = ( max + min ) >> 1;
edge = edges + mid;
fpos = edge->fpos;
if ( u < fpos )
max = mid;
else if ( u > fpos )
min = mid + 1;
else
{
/* we are on the edge */
u = edge->pos;
goto Store_Point;
}
}
{
AH_Edge before = edges + min - 1;
AH_Edge after = edges + min + 0;
/* assert( before && after && before != after ) */
if ( before->scale == 0 )
before->scale = FT_DivFix( after->pos - before->pos,
after->fpos - before->fpos );
u = before->pos + FT_MulFix( fu - before->fpos,
before->scale );
}
}
#else /* !0 */
/* otherwise, interpolate the point in between */
{
AH_Edge before = 0;
@@ -889,12 +1010,16 @@
after = edge;
}
/* assert( before && after && before != after ) */
u = before->pos + FT_MulDiv( fu - before->fpos,
after->pos - before->pos,
after->fpos - before->fpos );
if ( before->scale == 0 )
before->scale = FT_DivFix( after->pos - before->pos,
after->fpos - before->fpos );
u = before->pos + FT_MulFix( fu - before->fpos,
before->scale );
}
#endif /* !0 */
Store_Point:
/* save the point position */
@@ -1001,6 +1126,7 @@
/* interpolate weak points -- this is equivalent to the TrueType `IUP' */
/* hinting instruction */
static void
ah_hinter_align_weak_points( AH_Hinter hinter )
{
@@ -1141,8 +1267,8 @@
{
FT_Int n;
AH_Face_Globals globals = hinter->globals;
AH_Globals design = &globals->design;
AH_Globals scaled = &globals->scaled;
AH_Globals design = &globals->design;
AH_Globals scaled = &globals->scaled;
/* copy content */
@@ -1173,15 +1299,16 @@
if ( delta2 < 32 )
delta2 = 0;
else if ( delta2 < 64 )
delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 );
delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
else
delta2 = ( delta2 + 32 ) & -64;
delta2 = FT_PIX_ROUND( delta2 );
if ( delta < 0 )
delta2 = -delta2;
scaled->blue_refs[n] =
( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64;
FT_PIX_ROUND( FT_MulFix( design->blue_refs[n], y_scale ) );
scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2;
}
@@ -1211,7 +1338,7 @@
ah_outline_done( hinter->glyph );
/* note: the `globals' pointer is _not_ owned by the hinter */
/* but by the current face object, we don't need to */
/* but by the current face object; we don't need to */
/* release it */
hinter->globals = 0;
hinter->face = 0;
@@ -1360,26 +1487,26 @@
}
}
/* copy the outline points in the loader's current */
/* extra points, which is used to keep original glyph coordinates */
error = ah_loader_check_points( gloader, slot->outline.n_points + 2,
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = ah_loader_check_points( gloader, slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
FT_MEM_COPY( gloader->current.extra_points, slot->outline.points,
slot->outline.n_points * sizeof ( FT_Vector ) );
FT_ARRAY_COPY( gloader->current.extra_points, slot->outline.points,
slot->outline.n_points );
FT_MEM_COPY( gloader->current.outline.contours, slot->outline.contours,
slot->outline.n_contours * sizeof ( short ) );
FT_ARRAY_COPY( gloader->current.outline.contours, slot->outline.contours,
slot->outline.n_contours );
FT_MEM_COPY( gloader->current.outline.tags, slot->outline.tags,
slot->outline.n_points * sizeof ( char ) );
FT_ARRAY_COPY( gloader->current.outline.tags, slot->outline.tags,
slot->outline.n_points );
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original phantom points */
/* compute original horizontal phantom points, ignoring vertical ones */
hinter->pp1.x = 0;
hinter->pp1.y = 0;
hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
@@ -1389,8 +1516,8 @@
if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now, load the slot image into the auto-outline, and run the */
/* automatic hinting process */
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
error = ah_outline_load( outline, x_scale, y_scale, face );
if ( error )
goto Exit;
@@ -1413,6 +1540,7 @@
/* we now need to hint the metrics according to the change in */
/* width/positioning that occured during the hinting process */
if ( outline->num_vedges > 0 )
{
FT_Pos old_advance, old_rsb, old_lsb, new_lsb;
AH_Edge edge1 = outline->vert_edges; /* leftmost edge */
@@ -1425,8 +1553,8 @@
old_lsb = edge1->opos;
new_lsb = edge1->pos;
hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64;
hinter->pp2.x = ( ( edge2->pos + old_rsb ) + 32 ) & -64;
hinter->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
hinter->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
#if 0
/* try to fix certain bad advance computations */
@@ -1435,6 +1563,12 @@
#endif
}
else
{
hinter->pp1.x = ( hinter->pp1.x + 32 ) & -64;
hinter->pp2.x = ( hinter->pp2.x + 32 ) & -64;
}
/* good, we simply add the glyph to our loader's base */
ah_loader_add( gloader );
break;
@@ -1446,15 +1580,15 @@
FT_SubGlyph subglyph;
start_point = gloader->base.outline.n_points;
start_point = gloader->base.outline.n_points;
/* first of all, copy the subglyph descriptors in the glyph loader */
error = ah_loader_check_subglyphs( gloader, num_subglyphs );
if ( error )
goto Exit;
FT_MEM_COPY( gloader->current.subglyphs, slot->subglyphs,
num_subglyphs * sizeof ( FT_SubGlyph ) );
FT_ARRAY_COPY( gloader->current.subglyphs, slot->subglyphs,
num_subglyphs );
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
@@ -1529,8 +1663,8 @@
FT_Vector* p2;
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points )
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points )
{
error = AH_Err_Invalid_Composite;
goto Exit;
@@ -1538,7 +1672,7 @@
l += num_base_points;
/* for now, only use the current point coordinates */
/* for now, only use the current point coordinates; */
/* we may consider another approach in the near future */
p1 = gloader->base.outline.points + start_point + k;
p2 = gloader->base.outline.points + start_point + l;
@@ -1551,8 +1685,8 @@
x = FT_MulFix( subglyph->arg1, x_scale );
y = FT_MulFix( subglyph->arg2, y_scale );
x = ( x + 32 ) & -64;
y = ( y + 32 ) & -64;
x = FT_PIX_ROUND(x);
y = FT_PIX_ROUND(y);
}
{
@@ -1583,31 +1717,31 @@
if ( hinter->transformed )
FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix );
/* we must translate our final outline by -pp1.x, and compute */
/* the new metrics */
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */
if ( hinter->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin &= -64;
bbox.yMin &= -64;
bbox.xMax = ( bbox.xMax + 63 ) & -64;
bbox.yMax = ( bbox.yMax + 63 ) & -64;
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax );
bbox.yMax = FT_PIX_CEIL( bbox.yMax );
slot->metrics.width = bbox.xMax - bbox.xMin;
slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
/* for mono-width fonts (like Andale, Courier, etc.), we need */
/* to keep the original rounded advance width */
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width */
if ( !FT_IS_FIXED_WIDTH( slot->face ) )
slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x;
else
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
x_scale );
slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + 32 ) & -64;
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
/* now copy outline into glyph slot */
ah_loader_rewind( slot->internal->loader );
@@ -1641,7 +1775,7 @@
FT_Fixed x_scale = size->metrics.x_scale;
FT_Fixed y_scale = size->metrics.y_scale;
AH_Face_Globals face_globals = FACE_GLOBALS( face );
FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE(load_flags);
FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags );
/* first of all, we need to check that we're using the correct face and */
@@ -1662,19 +1796,22 @@
}
#ifdef FT_CONFIG_CHESTER_BLUE_SCALE
/* try to optimize the y_scale so that the top of non-capital letters
* is aligned on a pixel boundary whenever possible
*/
{
AH_Globals design = &face_globals->design;
FT_Pos shoot = design->blue_shoots[ AH_BLUE_SMALL_TOP ];
FT_Pos shoot = design->blue_shoots[AH_BLUE_SMALL_TOP];
/* the value of 'shoot' will be -1000 if the font doesn't have */
/* small latin letters; we simply check the sign here... */
/* the value of 'shoot' will be -1000 if the font doesn't have */
/* small latin letters; we simply check the sign here... */
if ( shoot > 0 )
{
FT_Pos scaled = FT_MulFix( shoot, y_scale );
FT_Pos fitted = ( scaled + 32 ) & -64;
FT_Pos fitted = FT_PIX_ROUND( scaled );
if ( scaled != fitted )
{
@@ -1685,10 +1822,11 @@
/* adust x_scale
*/
if ( fitted < scaled )
x_scale -= x_scale/50; /* x_scale*0.98 with integers */
x_scale -= x_scale / 50; /* x_scale*0.98 with integers */
}
}
}
#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */
/* now, we must check the current character pixel size to see if we */
@@ -1720,12 +1858,9 @@
hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
#if 1
load_flags = FT_LOAD_NO_SCALE
| FT_LOAD_IGNORE_TRANSFORM ;
#else
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE;
#endif
load_flags |= FT_LOAD_NO_SCALE
| FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
error = ah_hinter_load( hinter, glyph_index, load_flags, 0 );
@@ -1783,4 +1918,4 @@
}
/* END */
/* END */
+1 -1
View File
@@ -72,4 +72,4 @@ FT_END_HEADER
#endif /* __AHHINT_H__ */
/* END */
/* END */
+1 -1
View File
@@ -58,4 +58,4 @@ FT_END_HEADER
#endif /* __AHLOADER_H__ */
/* END */
/* END */
+3 -3
View File
@@ -4,7 +4,7 @@
/* */
/* Auto-hinting module implementation (declaration). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -119,7 +119,7 @@
FT_CALLBACK_TABLE_DEF
const FT_Module_Class autohint_module_class =
{
ft_module_hinter,
FT_MODULE_HINTER,
sizeof ( FT_AutoHinterRec ),
"autohinter",
@@ -134,4 +134,4 @@
};
/* END */
/* END */
+1 -1
View File
@@ -39,4 +39,4 @@ FT_END_HEADER
#endif /* __AHMODULE_H__ */
/* END */
/* END */
-882
View File
@@ -1,882 +0,0 @@
/***************************************************************************/
/* */
/* ahoptim.c */
/* */
/* FreeType auto hinting outline optimization (body). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This module is in charge of optimising the outlines produced by the */
/* auto-hinter in direct mode. This is required at small pixel sizes in */
/* order to ensure coherent spacing, among other things.. */
/* */
/* The technique used in this module is a simplified simulated */
/* annealing. */
/* */
/*************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H /* for FT_ALLOC_ARRAY() and FT_FREE() */
#include "ahoptim.h"
/* define this macro to use brute force optimization -- this is slow, */
/* but a good way to perfect the distortion function `by hand' through */
/* tweaking */
#define AH_BRUTE_FORCE
#define xxxAH_DEBUG_OPTIM
#undef LOG
#ifdef AH_DEBUG_OPTIM
#define LOG( x ) optim_log ## x
#else
#define LOG( x )
#endif /* AH_DEBUG_OPTIM */
#ifdef AH_DEBUG_OPTIM
#include <stdarg.h>
#include <stdlib.h>
#define FLOAT( x ) ( (float)( (x) / 64.0 ) )
static void
optim_log( const char* fmt, ... )
{
va_list ap;
va_start( ap, fmt );
vprintf( fmt, ap );
va_end( ap );
}
static void
AH_Dump_Stems( AH_Optimizer* optimizer )
{
int n;
AH_Stem* stem;
stem = optimizer->stems;
for ( n = 0; n < optimizer->num_stems; n++, stem++ )
{
LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}="
"<%1.f..%1.f> force=%.1f speed=%.1f\n",
optimizer->vertical ? 'V' : 'H', n,
FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ),
FLOAT( stem->edge1->pos ), FLOAT( stem->edge2->pos ),
FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
FLOAT( stem->force ), FLOAT( stem->velocity ) ));
}
}
static void
AH_Dump_Stems2( AH_Optimizer* optimizer )
{
int n;
AH_Stem* stem;
stem = optimizer->stems;
for ( n = 0; n < optimizer->num_stems; n++, stem++ )
{
LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n",
optimizer->vertical ? 'V' : 'H', n,
FLOAT( stem->pos ),
FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
FLOAT( stem->force ), FLOAT( stem->velocity ) ));
}
}
static void
AH_Dump_Springs( AH_Optimizer* optimizer )
{
int n;
AH_Spring* spring;
AH_Stem* stems;
spring = optimizer->springs;
stems = optimizer->stems;
LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' ));
for ( n = 0; n < optimizer->num_springs; n++, spring++ )
{
LOG(( " [%d-%d:%.1f:%1.f:%.1f]",
spring->stem1 - stems, spring->stem2 - stems,
FLOAT( spring->owidth ),
FLOAT( spring->stem2->pos -
( spring->stem1->pos + spring->stem1->width ) ),
FLOAT( spring->tension ) ));
}
LOG(( "\n" ));
}
#endif /* AH_DEBUG_OPTIM */
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** COMPUTE STEMS AND SPRINGS IN AN OUTLINE ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
static int
valid_stem_segments( AH_Segment seg1,
AH_Segment seg2 )
{
return seg1->serif == 0 &&
seg2 &&
seg2->link == seg1 &&
seg1->pos < seg2->pos &&
seg1->min_coord <= seg2->max_coord &&
seg2->min_coord <= seg1->max_coord;
}
/* compute all stems in an outline */
static int
optim_compute_stems( AH_Optimizer* optimizer )
{
AH_Outline outline = optimizer->outline;
FT_Fixed scale;
FT_Memory memory = optimizer->memory;
FT_Error error = 0;
FT_Int dimension;
AH_Edge edges;
AH_Edge edge_limit;
AH_Stem** p_stems;
FT_Int* p_num_stems;
edges = outline->horz_edges;
edge_limit = edges + outline->num_hedges;
scale = outline->y_scale;
p_stems = &optimizer->horz_stems;
p_num_stems = &optimizer->num_hstems;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AH_Stem* stems = 0;
FT_Int num_stems = 0;
AH_Edge edge;
/* first of all, count the number of stems in this direction */
for ( edge = edges; edge < edge_limit; edge++ )
{
AH_Segment seg = edge->first;
do
{
if (valid_stem_segments( seg, seg->link ) )
num_stems++;
seg = seg->edge_next;
} while ( seg != edge->first );
}
/* now allocate the stems and build their table */
if ( num_stems > 0 )
{
AH_Stem* stem;
if ( FT_NEW_ARRAY( stems, num_stems ) )
goto Exit;
stem = stems;
for ( edge = edges; edge < edge_limit; edge++ )
{
AH_Segment seg = edge->first;
AH_Segment seg2;
do
{
seg2 = seg->link;
if ( valid_stem_segments( seg, seg2 ) )
{
AH_Edge edge1 = seg->edge;
AH_Edge edge2 = seg2->edge;
stem->edge1 = edge1;
stem->edge2 = edge2;
stem->opos = edge1->opos;
stem->pos = edge1->pos;
stem->owidth = edge2->opos - edge1->opos;
stem->width = edge2->pos - edge1->pos;
/* compute min_coord and max_coord */
{
FT_Pos min_coord = seg->min_coord;
FT_Pos max_coord = seg->max_coord;
if ( seg2->min_coord > min_coord )
min_coord = seg2->min_coord;
if ( seg2->max_coord < max_coord )
max_coord = seg2->max_coord;
stem->min_coord = min_coord;
stem->max_coord = max_coord;
}
/* compute minimum and maximum positions for stem -- */
/* note that the left-most/bottom-most stem has always */
/* a fixed position */
if ( stem == stems || edge1->blue_edge || edge2->blue_edge )
{
/* this stem cannot move; it is snapped to a blue edge */
stem->min_pos = stem->pos;
stem->max_pos = stem->pos;
}
else
{
/* this edge can move; compute its min and max positions */
FT_Pos pos1 = stem->opos;
FT_Pos pos2 = pos1 + stem->owidth - stem->width;
FT_Pos min1 = pos1 & -64;
FT_Pos min2 = pos2 & -64;
stem->min_pos = min1;
stem->max_pos = min1 + 64;
if ( min2 < min1 )
stem->min_pos = min2;
else
stem->max_pos = min2 + 64;
/* XXX: just to see what it does */
stem->max_pos += 64;
/* just for the case where direct hinting did some */
/* incredible things (e.g. blue edge shifts) */
if ( stem->min_pos > stem->pos )
stem->min_pos = stem->pos;
if ( stem->max_pos < stem->pos )
stem->max_pos = stem->pos;
}
stem->velocity = 0;
stem->force = 0;
stem++;
}
seg = seg->edge_next;
} while ( seg != edge->first );
}
}
*p_stems = stems;
*p_num_stems = num_stems;
edges = outline->vert_edges;
edge_limit = edges + outline->num_vedges;
scale = outline->x_scale;
p_stems = &optimizer->vert_stems;
p_num_stems = &optimizer->num_vstems;
}
Exit:
#ifdef AH_DEBUG_OPTIM
AH_Dump_Stems( optimizer );
#endif
return error;
}
/* returns the spring area between two stems, 0 if none */
static FT_Pos
stem_spring_area( AH_Stem* stem1,
AH_Stem* stem2 )
{
FT_Pos area1 = stem1->max_coord - stem1->min_coord;
FT_Pos area2 = stem2->max_coord - stem2->min_coord;
FT_Pos min = stem1->min_coord;
FT_Pos max = stem1->max_coord;
FT_Pos area;
/* order stems */
if ( stem2->opos <= stem1->opos + stem1->owidth )
return 0;
if ( min < stem2->min_coord )
min = stem2->min_coord;
if ( max < stem2->max_coord )
max = stem2->max_coord;
area = ( max-min );
if ( 2 * area < area1 && 2 * area < area2 )
area = 0;
return area;
}
/* compute all springs in an outline */
static int
optim_compute_springs( AH_Optimizer* optimizer )
{
/* basically, a spring exists between two stems if most of their */
/* surface is aligned */
FT_Memory memory = optimizer->memory;
AH_Stem* stems;
AH_Stem* stem_limit;
AH_Stem* stem;
int dimension;
int error = 0;
FT_Int* p_num_springs;
AH_Spring** p_springs;
stems = optimizer->horz_stems;
stem_limit = stems + optimizer->num_hstems;
p_springs = &optimizer->horz_springs;
p_num_springs = &optimizer->num_hsprings;
for ( dimension = 1; dimension >= 0; dimension-- )
{
FT_Int num_springs = 0;
AH_Spring* springs = 0;
/* first of all, count stem springs */
for ( stem = stems; stem + 1 < stem_limit; stem++ )
{
AH_Stem* stem2;
for ( stem2 = stem+1; stem2 < stem_limit; stem2++ )
if ( stem_spring_area( stem, stem2 ) )
num_springs++;
}
/* then allocate and build the springs table */
if ( num_springs > 0 )
{
AH_Spring* spring;
/* allocate table of springs */
if ( FT_NEW_ARRAY( springs, num_springs ) )
goto Exit;
/* fill the springs table */
spring = springs;
for ( stem = stems; stem+1 < stem_limit; stem++ )
{
AH_Stem* stem2;
FT_Pos area;
for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ )
{
area = stem_spring_area( stem, stem2 );
if ( area )
{
/* add a new spring here */
spring->stem1 = stem;
spring->stem2 = stem2;
spring->owidth = stem2->opos - ( stem->opos + stem->owidth );
spring->tension = 0;
spring++;
}
}
}
}
*p_num_springs = num_springs;
*p_springs = springs;
stems = optimizer->vert_stems;
stem_limit = stems + optimizer->num_vstems;
p_springs = &optimizer->vert_springs;
p_num_springs = &optimizer->num_vsprings;
}
Exit:
#ifdef AH_DEBUG_OPTIM
AH_Dump_Springs( optimizer );
#endif
return error;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#ifndef AH_BRUTE_FORCE
/* compute all spring tensions */
static void
optim_compute_tensions( AH_Optimizer* optimizer )
{
AH_Spring* spring = optimizer->springs;
AH_Spring* limit = spring + optimizer->num_springs;
for ( ; spring < limit; spring++ )
{
AH_Stem* stem1 = spring->stem1;
AH_Stem* stem2 = spring->stem2;
FT_Int status;
FT_Pos width;
FT_Pos tension;
FT_Pos sign;
/* compute the tension; it simply is -K*(new_width-old_width) */
width = stem2->pos - ( stem1->pos + stem1->width );
tension = width - spring->owidth;
sign = 1;
if ( tension < 0 )
{
sign = -1;
tension = -tension;
}
if ( width <= 0 )
tension = 32000;
else
tension = ( tension << 10 ) / width;
tension = -sign * FT_MulFix( tension, optimizer->tension_scale );
spring->tension = tension;
/* now, distribute tension among the englobing stems, if they */
/* are able to move */
status = 0;
if ( stem1->pos <= stem1->min_pos )
status |= 1;
if ( stem2->pos >= stem2->max_pos )
status |= 2;
if ( !status )
tension /= 2;
if ( ( status & 1 ) == 0 )
stem1->force -= tension;
if ( ( status & 2 ) == 0 )
stem2->force += tension;
}
}
/* compute all stem movements -- returns 0 if nothing moved */
static int
optim_compute_stem_movements( AH_Optimizer* optimizer )
{
AH_Stem* stems = optimizer->stems;
AH_Stem* limit = stems + optimizer->num_stems;
AH_Stem* stem = stems;
int moved = 0;
/* set initial forces to velocity */
for ( stem = stems; stem < limit; stem++ )
{
stem->force = stem->velocity;
stem->velocity /= 2; /* XXX: Heuristics */
}
/* compute the sum of forces applied on each stem */
optim_compute_tensions( optimizer );
#ifdef AH_DEBUG_OPTIM
AH_Dump_Springs( optimizer );
AH_Dump_Stems2( optimizer );
#endif
/* now, see whether something can move */
for ( stem = stems; stem < limit; stem++ )
{
if ( stem->force > optimizer->tension_threshold )
{
/* there is enough tension to move the stem to the right */
if ( stem->pos < stem->max_pos )
{
stem->pos += 64;
stem->velocity = stem->force / 2;
moved = 1;
}
else
stem->velocity = 0;
}
else if ( stem->force < optimizer->tension_threshold )
{
/* there is enough tension to move the stem to the left */
if ( stem->pos > stem->min_pos )
{
stem->pos -= 64;
stem->velocity = stem->force / 2;
moved = 1;
}
else
stem->velocity = 0;
}
}
/* return 0 if nothing moved */
return moved;
}
#endif /* AH_BRUTE_FORCE */
/* compute current global distortion from springs */
static FT_Pos
optim_compute_distortion( AH_Optimizer* optimizer )
{
AH_Spring* spring = optimizer->springs;
AH_Spring* limit = spring + optimizer->num_springs;
FT_Pos distortion = 0;
for ( ; spring < limit; spring++ )
{
AH_Stem* stem1 = spring->stem1;
AH_Stem* stem2 = spring->stem2;
FT_Pos width;
width = stem2->pos - ( stem1->pos + stem1->width );
width -= spring->owidth;
if ( width < 0 )
width = -width;
distortion += width;
}
return distortion;
}
/* record stems configuration in `best of' history */
static void
optim_record_configuration( AH_Optimizer* optimizer )
{
FT_Pos distortion;
AH_Configuration* configs = optimizer->configs;
AH_Configuration* limit = configs + optimizer->num_configs;
AH_Configuration* config;
distortion = optim_compute_distortion( optimizer );
LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) ));
/* check that we really need to add this configuration to our */
/* sorted history */
if ( limit > configs && limit[-1].distortion < distortion )
{
LOG(( "ejected\n" ));
return;
}
/* add new configuration at the end of the table */
{
int n;
config = limit;
if ( optimizer->num_configs < AH_MAX_CONFIGS )
optimizer->num_configs++;
else
config--;
config->distortion = distortion;
for ( n = 0; n < optimizer->num_stems; n++ )
config->positions[n] = optimizer->stems[n].pos;
}
/* move the current configuration towards the front of the list */
/* when necessary -- yes this is slow bubble sort ;-) */
while ( config > configs && config[0].distortion < config[-1].distortion )
{
AH_Configuration temp;
config--;
temp = config[0];
config[0] = config[1];
config[1] = temp;
}
LOG(( "recorded!\n" ));
}
#ifdef AH_BRUTE_FORCE
/* optimize outline in a single direction */
static void
optim_compute( AH_Optimizer* optimizer )
{
int n;
FT_Bool moved;
AH_Stem* stem = optimizer->stems;
AH_Stem* limit = stem + optimizer->num_stems;
/* empty, exit */
if ( stem >= limit )
return;
optimizer->num_configs = 0;
stem = optimizer->stems;
for ( ; stem < limit; stem++ )
stem->pos = stem->min_pos;
do
{
/* record current configuration */
optim_record_configuration( optimizer );
/* now change configuration */
moved = 0;
for ( stem = optimizer->stems; stem < limit; stem++ )
{
if ( stem->pos < stem->max_pos )
{
stem->pos += 64;
moved = 1;
break;
}
stem->pos = stem->min_pos;
}
} while ( moved );
/* now, set the best stem positions */
for ( n = 0; n < optimizer->num_stems; n++ )
{
AH_Stem* stem = optimizer->stems + n;
FT_Pos pos = optimizer->configs[0].positions[n];
stem->edge1->pos = pos;
stem->edge2->pos = pos + stem->width;
stem->edge1->flags |= AH_EDGE_DONE;
stem->edge2->flags |= AH_EDGE_DONE;
}
}
#else /* AH_BRUTE_FORCE */
/* optimize outline in a single direction */
static void
optim_compute( AH_Optimizer* optimizer )
{
int n, counter, counter2;
optimizer->num_configs = 0;
optimizer->tension_scale = 0x80000L;
optimizer->tension_threshold = 64;
/* record initial configuration threshold */
optim_record_configuration( optimizer );
counter = 0;
for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- )
{
if ( counter == 0 )
counter = 2 * optimizer->num_stems;
if ( !optim_compute_stem_movements( optimizer ) )
break;
optim_record_configuration( optimizer );
counter--;
if ( counter == 0 )
optimizer->tension_scale /= 2;
}
/* now, set the best stem positions */
for ( n = 0; n < optimizer->num_stems; n++ )
{
AH_Stem* stem = optimizer->stems + n;
FT_Pos pos = optimizer->configs[0].positions[n];
stem->edge1->pos = pos;
stem->edge2->pos = pos + stem->width;
stem->edge1->flags |= AH_EDGE_DONE;
stem->edge2->flags |= AH_EDGE_DONE;
}
}
#endif /* AH_BRUTE_FORCE */
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** HIGH-LEVEL OPTIMIZER API ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* releases the optimization data */
void
AH_Optimizer_Done( AH_Optimizer* optimizer )
{
if ( optimizer )
{
FT_Memory memory = optimizer->memory;
FT_FREE( optimizer->horz_stems );
FT_FREE( optimizer->vert_stems );
FT_FREE( optimizer->horz_springs );
FT_FREE( optimizer->vert_springs );
FT_FREE( optimizer->positions );
}
}
/* loads the outline into the optimizer */
int
AH_Optimizer_Init( AH_Optimizer* optimizer,
AH_Outline outline,
FT_Memory memory )
{
FT_Error error;
FT_MEM_ZERO( optimizer, sizeof ( *optimizer ) );
optimizer->outline = outline;
optimizer->memory = memory;
LOG(( "initializing new optimizer\n" ));
/* compute stems and springs */
error = optim_compute_stems ( optimizer ) ||
optim_compute_springs( optimizer );
if ( error )
goto Fail;
/* allocate stem positions history and configurations */
{
int n, max_stems;
max_stems = optimizer->num_hstems;
if ( max_stems < optimizer->num_vstems )
max_stems = optimizer->num_vstems;
if ( FT_NEW_ARRAY( optimizer->positions, max_stems * AH_MAX_CONFIGS ) )
goto Fail;
optimizer->num_configs = 0;
for ( n = 0; n < AH_MAX_CONFIGS; n++ )
optimizer->configs[n].positions = optimizer->positions +
n * max_stems;
}
return error;
Fail:
AH_Optimizer_Done( optimizer );
return error;
}
/* compute optimal outline */
void
AH_Optimizer_Compute( AH_Optimizer* optimizer )
{
optimizer->num_stems = optimizer->num_hstems;
optimizer->stems = optimizer->horz_stems;
optimizer->num_springs = optimizer->num_hsprings;
optimizer->springs = optimizer->horz_springs;
if ( optimizer->num_springs > 0 )
{
LOG(( "horizontal optimization ------------------------\n" ));
optim_compute( optimizer );
}
optimizer->num_stems = optimizer->num_vstems;
optimizer->stems = optimizer->vert_stems;
optimizer->num_springs = optimizer->num_vsprings;
optimizer->springs = optimizer->vert_springs;
if ( optimizer->num_springs )
{
LOG(( "vertical optimization --------------------------\n" ));
optim_compute( optimizer );
}
}
/* END */
-137
View File
@@ -1,137 +0,0 @@
/***************************************************************************/
/* */
/* ahoptim.h */
/* */
/* FreeType auto hinting outline optimization (declaration). */
/* */
/* Copyright 2000-2001 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
/* be used, modified, and distributed under the terms of the Catharon */
/* Open Source License that should come with this file under the name */
/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/* Note that this license is compatible with the FreeType license. */
/* */
/***************************************************************************/
#ifndef __AHOPTIM_H__
#define __AHOPTIM_H__
#include <ft2build.h>
#include "ahtypes.h"
FT_BEGIN_HEADER
/* the maximal number of stem configurations to record */
/* during optimization */
#define AH_MAX_CONFIGS 8
typedef struct AH_Stem_
{
FT_Pos pos; /* current position */
FT_Pos velocity; /* current velocity */
FT_Pos force; /* sum of current forces */
FT_Pos width; /* normalized width */
FT_Pos min_pos; /* minimum grid position */
FT_Pos max_pos; /* maximum grid position */
AH_Edge edge1; /* left/bottom edge */
AH_Edge edge2; /* right/top edge */
FT_Pos opos; /* original position */
FT_Pos owidth; /* original width */
FT_Pos min_coord; /* minimum coordinate */
FT_Pos max_coord; /* maximum coordinate */
} AH_Stem;
/* A spring between two stems */
typedef struct AH_Spring_
{
AH_Stem* stem1;
AH_Stem* stem2;
FT_Pos owidth; /* original width */
FT_Pos tension; /* current tension */
} AH_Spring;
/* A configuration records the position of each stem at a given time */
/* as well as the associated distortion */
typedef struct AH_Configuration_
{
FT_Pos* positions;
FT_Long distortion;
} AH_Configuration;
typedef struct AH_Optimizer_
{
FT_Memory memory;
AH_Outline outline;
FT_Int num_hstems;
AH_Stem* horz_stems;
FT_Int num_vstems;
AH_Stem* vert_stems;
FT_Int num_hsprings;
FT_Int num_vsprings;
AH_Spring* horz_springs;
AH_Spring* vert_springs;
FT_Int num_configs;
AH_Configuration configs[AH_MAX_CONFIGS];
FT_Pos* positions;
/* during each pass, use these instead */
FT_Int num_stems;
AH_Stem* stems;
FT_Int num_springs;
AH_Spring* springs;
FT_Bool vertical;
FT_Fixed tension_scale;
FT_Pos tension_threshold;
} AH_Optimizer;
/* loads the outline into the optimizer */
int
AH_Optimizer_Init( AH_Optimizer* optimizer,
AH_Outline outline,
FT_Memory memory );
/* compute optimal outline */
void
AH_Optimizer_Compute( AH_Optimizer* optimizer );
/* release the optimization data */
void
AH_Optimizer_Done( AH_Optimizer* optimizer );
FT_END_HEADER
#endif /* __AHOPTIM_H__ */
/* END */
+85 -91
View File
@@ -5,7 +5,7 @@
/* General types and definitions for the auto-hint module */
/* (specification only). */
/* */
/* Copyright 2000-2001, 2002 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@@ -76,16 +76,6 @@ FT_BEGIN_HEADER
#undef AH_OPTION_NO_WEAK_INTERPOLATION
/*************************************************************************/
/* */
/* If this option is defined, only weak interpolation will be used to */
/* place the points between edges. Otherwise, `strong' points are */
/* detected and later hinted through strong interpolation to correct */
/* some unpleasant artefacts. */
/* */
#undef AH_OPTION_NO_STRONG_INTERPOLATION
/*************************************************************************/
/* */
/* Undefine this macro if you don't want to hint the metrics. There is */
@@ -121,7 +111,7 @@ FT_BEGIN_HEADER
/*************************************************************************/
/* see agangles.h */
/* see ahangles.h */
typedef FT_Int AH_Angle;
@@ -201,10 +191,6 @@ FT_BEGIN_HEADER
/* */
/* out_dir :: The direction of the outwards vector (point->next). */
/* */
/* in_angle :: The angle of the inwards vector. */
/* */
/* out_angle :: The angle of the outwards vector. */
/* */
/* next :: The next point in same contour. */
/* */
/* prev :: The previous point in same contour. */
@@ -220,9 +206,6 @@ FT_BEGIN_HEADER
AH_Direction in_dir; /* direction of inwards vector */
AH_Direction out_dir; /* direction of outwards vector */
AH_Angle in_angle;
AH_Angle out_angle;
AH_Point next; /* next point in contour */
AH_Point prev; /* previous point in contour */
@@ -244,16 +227,9 @@ FT_BEGIN_HEADER
/* */
/* dir :: The segment direction. */
/* */
/* first :: The first point in the segment. */
/* min_coord :: The minimum coordinate of the segment. */
/* */
/* last :: The last point in the segment. */
/* */
/* contour :: A pointer to the first point of the segment's */
/* contour. */
/* */
/* pos :: The segment position in font units. */
/* */
/* size :: The segment size. */
/* max_coord :: The maximum coordinate of the segment. */
/* */
/* edge :: The edge of the current segment. */
/* */
@@ -267,15 +243,17 @@ FT_BEGIN_HEADER
/* */
/* score :: Used to score the segment when selecting them. */
/* */
/* first :: The first point in the segment. */
/* */
/* last :: The last point in the segment. */
/* */
/* contour :: A pointer to the first point of the segment's */
/* contour. */
/* */
typedef struct AH_SegmentRec_
{
AH_Edge_Flags flags;
AH_Direction dir;
AH_Point first; /* first point in edge segment */
AH_Point last; /* last point in edge segment */
AH_Point* contour; /* ptr to first point of segment's contour */
FT_Pos pos; /* position of segment */
FT_Pos min_coord; /* minimum coordinate of segment */
FT_Pos max_coord; /* maximum coordinate of segment */
@@ -288,6 +266,10 @@ FT_BEGIN_HEADER
FT_Pos num_linked; /* number of linked segments */
FT_Pos score;
AH_Point first; /* first point in edge segment */
AH_Point last; /* last point in edge segment */
AH_Point* contour; /* ptr to first point of segment's contour */
} AH_SegmentRec;
@@ -302,50 +284,55 @@ FT_BEGIN_HEADER
/* located on it. */
/* */
/* <Fields> */
/* flags :: The segment edge flags (straight, rounded, etc.). */
/* */
/* dir :: The main segment direction on this edge. */
/* */
/* first :: The first edge segment. */
/* */
/* last :: The last edge segment. */
/* */
/* fpos :: The original edge position in font units. */
/* */
/* opos :: The original scaled edge position. */
/* */
/* pos :: The hinted edge position. */
/* */
/* flags :: The segment edge flags (straight, rounded, etc.). */
/* */
/* dir :: The main segment direction on this edge. */
/* */
/* scale :: Scaling factor between original and hinted edge */
/* positions. */
/* */
/* blue_edge :: Indicate the blue zone edge this edge is related to. */
/* Only set for some of the horizontal edges in a latin */
/* font. */
/* */
/* link :: The linked edge. */
/* */
/* serif :: The serif edge. */
/* */
/* num_paired :: The number of other edges that pair to this one. */
/* num_linked :: The number of other edges that pair to this one. */
/* */
/* score :: Used to score the edge when selecting them. */
/* */
/* blue_edge :: Indicate the blue zone edge this edge is related to. */
/* Only set for some of the horizontal edges in a Latin */
/* font. */
/* first :: The first edge segment. */
/* */
/* last :: The last edge segment. */
/* */
typedef struct AH_EdgeRec_
{
AH_Edge_Flags flags;
AH_Direction dir;
AH_Segment first;
AH_Segment last;
FT_Pos fpos;
FT_Pos opos;
FT_Pos pos;
AH_Edge_Flags flags;
AH_Direction dir;
FT_Fixed scale;
FT_Pos* blue_edge;
AH_Edge link;
AH_Edge serif;
FT_Int num_linked;
FT_Int score;
FT_Pos* blue_edge;
AH_Segment first;
AH_Segment last;
} AH_EdgeRec;
@@ -368,7 +355,7 @@ FT_BEGIN_HEADER
FT_Int max_contours;
FT_Int num_contours;
AH_Point * contours;
AH_Point* contours;
FT_Int num_hedges;
AH_Edge horz_edges;
@@ -387,24 +374,24 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_CHESTER_SMALL_F
# define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
# define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
# define AH_BLUE_SMALL_F_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* fijkdbh */
# define AH_BLUE_SMALL_TOP ( AH_BLUE_SMALL_F_TOP + 1 ) /* xzroesc */
# define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
# define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
# define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
#define AH_BLUE_SMALL_F_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* fijkdbh */
#define AH_BLUE_SMALL_TOP ( AH_BLUE_SMALL_F_TOP + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
#else /* !CHESTER_SMALL_F */
#else /* !FT_CONFIG_CHESTER_SMALL_F */
# define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
# define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
# define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1) /* xzroesc */
# define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
# define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
# define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */
#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */
#define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */
#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */
#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 )
#endif /* !CHESTER_SMALL_F */
#endif /* !FT_CONFIG_CHESTER_SMALL_F */
typedef FT_Int AH_Blue;
@@ -429,6 +416,9 @@ FT_BEGIN_HEADER
/* */
/* num_heights :: The number of heights. */
/* */
/* stds :: A two-element array giving the default stem width */
/* and height. */
/* */
/* widths :: Snap widths, including standard one. */
/* */
/* heights :: Snap height, including standard one. */
@@ -474,6 +464,9 @@ FT_BEGIN_HEADER
/* */
/* y_scale :: The current vertical scale. */
/* */
/* control_overshoot :: */
/* Currently unused. */
/* */
typedef struct AH_Face_GlobalsRec_
{
FT_Face face;
@@ -486,39 +479,40 @@ FT_BEGIN_HEADER
} AH_Face_GlobalsRec, *AH_Face_Globals;
typedef struct AH_HinterRec
typedef struct AH_HinterRec_
{
FT_Memory memory;
AH_Hinter_Flags flags;
FT_Memory memory;
AH_Hinter_Flags flags;
FT_Int algorithm;
FT_Face face;
FT_Int algorithm;
FT_Face face;
AH_Face_Globals globals;
AH_Face_Globals globals;
AH_Outline glyph;
AH_Outline glyph;
AH_Loader loader;
FT_Vector pp1;
FT_Vector pp2;
AH_Loader loader;
FT_Vector pp1; /* horizontal phantom points */
FT_Vector pp2;
/* we ignore vertical phantom points */
FT_Bool transformed;
FT_Vector trans_delta;
FT_Matrix trans_matrix;
FT_Bool transformed;
FT_Vector trans_delta;
FT_Matrix trans_matrix;
FT_Bool do_horz_hints; /* disable X hinting */
FT_Bool do_vert_hints; /* disable Y hinting */
FT_Bool do_horz_snapping; /* disable X stem size snapping */
FT_Bool do_vert_snapping; /* disable Y stem size snapping */
FT_Bool do_stem_adjust; /* disable light stem snapping */
FT_Bool do_horz_hints; /* disable X hinting */
FT_Bool do_vert_hints; /* disable Y hinting */
FT_Bool do_horz_snapping; /* disable X stem size snapping */
FT_Bool do_vert_snapping; /* disable Y stem size snapping */
FT_Bool do_stem_adjust; /* disable light stem snapping */
} AH_HinterRec, *AH_Hinter;
#ifdef DEBUG_HINTER
extern AH_Hinter ah_debug_hinter;
extern FT_Bool ah_debug_disable_horz;
extern FT_Bool ah_debug_disable_vert;
#ifdef DEBUG_HINTER
extern AH_Hinter ah_debug_hinter;
extern FT_Bool ah_debug_disable_horz;
extern FT_Bool ah_debug_disable_vert;
#else
#define ah_debug_disable_horz 0
#define ah_debug_disable_vert 0
@@ -530,4 +524,4 @@ FT_END_HEADER
#endif /* __AHTYPES_H__ */
/* END */
/* END */
+1 -1
View File
@@ -29,4 +29,4 @@
#include "ahmodule.c"
/* END */
/* END */
+1 -1
View File
@@ -75,4 +75,4 @@ print_arctan( 8 )
print
# END
# END
+1 -1
View File
@@ -22,4 +22,4 @@ add_autohint_module:
$(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)autohint $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
# EOF
# EOF
+18 -19
View File
@@ -3,7 +3,7 @@
#
# Copyright 2000, 2001 Catharon Productions Inc.
# Copyright 2000, 2001, 2002, 2003 Catharon Productions Inc.
# Author: David Turner
#
# This file is part of the Catharon Typography Project and shall only
@@ -18,29 +18,28 @@
# AUTO driver directory
#
AUTO_DIR := $(SRC_)autohint
AUTO_DIR_ := $(AUTO_DIR)$(SEP)
AUTO_DIR := $(SRC_DIR)/autohint
# compilation flags for the driver
#
AUTO_COMPILE := $(FT_COMPILE) $I$(AUTO_DIR)
AUTO_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(AUTO_DIR))
# AUTO driver sources (i.e., C files)
#
AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \
$(AUTO_DIR_)ahglobal.c \
$(AUTO_DIR_)ahglyph.c \
$(AUTO_DIR_)ahhint.c \
$(AUTO_DIR_)ahmodule.c
AUTO_DRV_SRC := $(AUTO_DIR)/ahangles.c \
$(AUTO_DIR)/ahglobal.c \
$(AUTO_DIR)/ahglyph.c \
$(AUTO_DIR)/ahhint.c \
$(AUTO_DIR)/ahmodule.c
# AUTO driver headers
#
AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \
$(AUTO_DIR_)ahloader.h \
$(AUTO_DIR_)ahtypes.h \
$(AUTO_DIR_)aherrors.h
$(AUTO_DIR)/ahloader.h \
$(AUTO_DIR)/ahtypes.h \
$(AUTO_DIR)/aherrors.h
# AUTO driver object(s)
@@ -48,25 +47,25 @@ AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \
# AUTO_DRV_OBJ_M is used during `multi' builds.
# AUTO_DRV_OBJ_S is used during `single' builds.
#
AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O)
AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O
AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR)/%.c=$(OBJ_DIR)/%.$O)
AUTO_DRV_OBJ_S := $(OBJ_DIR)/autohint.$O
# AUTO driver source file for single build
#
AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c
AUTO_DRV_SRC_S := $(AUTO_DIR)/autohint.c
# AUTO driver - single object
#
$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \
$(FREETYPE_H) $(AUTO_DRV_H)
$(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S)
$(AUTO_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(AUTO_DRV_SRC_S))
# AUTO driver - multiple objects
#
$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H)
$(AUTO_COMPILE) $T$@ $<
$(OBJ_DIR)/%.$O: $(AUTO_DIR)/%.c $(FREETYPE_H) $(AUTO_DRV_H)
$(AUTO_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
@@ -75,4 +74,4 @@ DRV_OBJS_S += $(AUTO_DRV_OBJ_S)
DRV_OBJS_M += $(AUTO_DRV_OBJ_M)
# EOF
# EOF
+5 -5
View File
@@ -11,7 +11,7 @@ UseFreeTypeHeaders ;
if $(FT2_MULTI)
{
_sources = ftutil ftdbgmem ftstream ftcalc fttrigon ftgloadr ftoutln
ftobjs ftnames ;
ftobjs ftnames ftrfork ;
}
else
{
@@ -24,9 +24,8 @@ UseFreeTypeHeaders ;
# Add the optional/replaceable files.
#
FT2_Library $(FT2_LIB) : ftsystem.c ftinit.c ftglyph.c ftmm.c ftbdf.c
ftbbox.c ftdebug.c ftxf86.c fttype1.c ftpfr.c
ftstroker.c ftwinfnt.c
;
ftbbox.c ftdebug.c ftxf86.c fttype1.c ftpfr.c
ftstroke.c ftwinfnt.c ;
# Add Macintosh-specific file to the library when necessary.
#
@@ -35,4 +34,5 @@ if $(MAC)
FT2_Library $(FT2_LIB) : ftmac.c ;
}
# end of src/base Jamfile
# end of src/base Jamfile
+3 -3
View File
@@ -3,7 +3,7 @@
#
# Copyright 2001 by
# Copyright 2001, 2003, 2004 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -15,9 +15,9 @@
CFLAGS=$(COMP_FLAGS)$(DEBUG)/include=([--.builds.vms],[--.include],[--.src.base])
OBJS=ftbase.obj,ftinit.obj,ftglyph.obj,ftdebug.obj,ftbdf.obj,ftmm.obj,fttype1.obj,ftxf86.obj,ftpfr.obj,ftstroker.obj,ftwinfnt.obj
OBJS=ftbase.obj,ftinit.obj,ftglyph.obj,ftdebug.obj,ftbdf.obj,ftmm.obj,fttype1.obj,ftxf86.obj,ftpfr.obj,ftstroke.obj,ftwinfnt.obj,ftbbox.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
# EOF
# EOF
+1 -1
View File
@@ -118,4 +118,4 @@
}
/* END */
/* END */
+6 -2
View File
@@ -4,7 +4,7 @@
/* */
/* Single object library component (body only). */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,6 +29,10 @@
#include "ftgloadr.c"
#include "ftobjs.c"
#include "ftnames.c"
#include "ftrfork.c"
#if defined( __APPLE__ ) && !defined ( DARWIN_NO_CARBON )
#include "ftmac.c"
#endif
/* END */
/* END */
+4 -4
View File
@@ -98,9 +98,9 @@
static void
BBox_Conic_Check( FT_Pos y1,
FT_Pos y2,
FT_Pos y3,
FT_Pos* min,
FT_Pos* max )
FT_Pos y3,
FT_Pos* min,
FT_Pos* max )
{
if ( y1 <= y3 )
{
@@ -650,4 +650,4 @@
}
/* END */
/* END */
+21 -33
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing BDF-specific strings (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,24 +17,8 @@
#include <ft2build.h>
#include FT_INTERNAL_BDF_TYPES_H
#include FT_INTERNAL_OBJECTS_H
static FT_Bool
test_font_type( FT_Face face, const char* name )
{
if ( face && face->driver )
{
FT_Module driver = (FT_Module)face->driver;
if ( driver->clazz && driver->clazz->module_name )
{
if ( ft_strcmp( driver->clazz->module_name, name ) == 0 )
return 1;
}
}
return 0;
}
#include FT_SERVICE_BDF_H
FT_EXPORT_DEF( FT_Error )
@@ -49,14 +33,15 @@
error = FT_Err_Invalid_Argument;
if ( test_font_type( face, "bdf" ) )
if ( face )
{
BDF_Public_Face bdf_face = (BDF_Public_Face)face;
FT_Service_BDF service;
encoding = (const char*) bdf_face->charset_encoding;
registry = (const char*) bdf_face->charset_registry;
error = 0;
FT_FACE_FIND_SERVICE( face, service, BDF );
if ( service && service->get_charset_id )
error = service->get_charset_id( face, &encoding, &registry );
}
if ( acharset_encoding )
@@ -74,23 +59,26 @@
const char* prop_name,
BDF_PropertyRec *aproperty )
{
FT_Error error;
FT_Error error;
error = FT_Err_Invalid_Argument;
aproperty->type = BDF_PROPERTY_TYPE_NONE;
if ( face != NULL && face->driver != NULL )
if ( face )
{
FT_Driver driver = face->driver;
BDF_GetPropertyFunc func;
FT_Service_BDF service;
func = (BDF_GetPropertyFunc) driver->root.clazz->get_interface(
FT_MODULE( driver ), "get_bdf_property" );
if ( func )
error = func( face, prop_name, aproperty );
FT_FACE_FIND_SERVICE( face, service, BDF );
if ( service && service->get_property )
error = service->get_property( face, prop_name, aproperty );
}
return error;
return error;
}
/* END */
/* END */
+88 -25
View File
@@ -4,7 +4,7 @@
/* */
/* Arithmetic computations (body). */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -74,8 +74,8 @@
FT_EXPORT_DEF( FT_Fixed )
FT_RoundFix( FT_Fixed a )
{
return ( a >= 0 ) ? ( a + 0x8000L ) & -0x10000L
: -((-a + 0x8000L ) & -0x10000L );
return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL
: -((-a + 0x8000L ) & ~0xFFFFL );
}
@@ -84,8 +84,8 @@
FT_EXPORT_DEF( FT_Fixed )
FT_CeilFix( FT_Fixed a )
{
return ( a >= 0 ) ? ( a + 0xFFFFL ) & -0x10000L
: -((-a + 0xFFFFL ) & -0x10000L );
return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL
: -((-a + 0xFFFFL ) & ~0xFFFFL );
}
@@ -94,8 +94,8 @@
FT_EXPORT_DEF( FT_Fixed )
FT_FloorFix( FT_Fixed a )
{
return ( a >= 0 ) ? a & -0x10000L
: -((-a) & -0x10000L );
return ( a >= 0 ) ? a & ~0xFFFFL
: -((-a) & ~0xFFFFL );
}
@@ -155,6 +155,33 @@
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
/* documentation is in ftcalc.h */
FT_BASE_DEF( FT_Long )
FT_MulDiv_No_Round( FT_Long a,
FT_Long b,
FT_Long c )
{
FT_Int s;
FT_Long d;
s = 1;
if ( a < 0 ) { a = -a; s = -1; }
if ( b < 0 ) { b = -b; s = -s; }
if ( c < 0 ) { c = -c; s = -s; }
d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
: 0x7FFFFFFFL );
return ( s > 0 ) ? d : -d;
}
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
@@ -168,7 +195,7 @@
if ( a < 0 ) { a = -a; s = -1; }
if ( b < 0 ) { b = -b; s = -s; }
c = (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
return ( s > 0 ) ? c : -c ;
}
@@ -298,14 +325,13 @@
if ( a == 0 || b == c )
return a;
s = a; a = ABS( a );
s ^= b; b = ABS( b );
s ^= c; c = ABS( c );
s = a; a = FT_ABS( a );
s ^= b; b = FT_ABS( b );
s ^= c; c = FT_ABS( c );
if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
{
a = ( a * b + ( c >> 1 ) ) / c;
}
else if ( c > 0 )
{
FT_Int64 temp, temp2;
@@ -325,6 +351,43 @@
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
FT_BASE_DEF( FT_Long )
FT_MulDiv_No_Round( FT_Long a,
FT_Long b,
FT_Long c )
{
long s;
if ( a == 0 || b == c )
return a;
s = a; a = FT_ABS( a );
s ^= b; b = FT_ABS( b );
s ^= c; c = FT_ABS( c );
if ( a <= 46340L && b <= 46340L && c > 0 )
a = a * b / c;
else if ( c > 0 )
{
FT_Int64 temp;
ft_multo64( a, b, &temp );
a = ft_div64by32( temp.hi, temp.lo, c );
}
else
a = 0x7FFFFFFFL;
return ( s < 0 ? -a : a );
}
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
/* documentation is in freetype.h */
FT_EXPORT_DEF( FT_Long )
@@ -338,23 +401,23 @@
if ( a == 0 || b == 0x10000L )
return a;
s = a; a = ABS(a);
s ^= b; b = ABS(b);
s = a; a = FT_ABS(a);
s ^= b; b = FT_ABS(b);
ua = (FT_ULong)a;
ub = (FT_ULong)b;
if ( ua <= 2048 && ub <= 1048576L )
{
ua = ( ua * ub + 0x8000 ) >> 16;
ua = ( ua * ub + 0x8000L ) >> 16;
}
else
{
FT_ULong al = ua & 0xFFFF;
FT_ULong al = ua & 0xFFFFL;
ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
( ( al * ( ub & 0xFFFF ) + 0x8000 ) >> 16 );
( ( al * ( ub & 0xFFFFL ) + 0x8000L ) >> 16 );
}
return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
@@ -371,8 +434,8 @@
FT_UInt32 q;
s = a; a = ABS(a);
s ^= b; b = ABS(b);
s = a; a = FT_ABS(a);
s ^= b; b = FT_ABS(b);
if ( b == 0 )
{
@@ -411,8 +474,8 @@
FT_Int32 s;
s = x; x = ABS( x );
s ^= y; y = ABS( y );
s = x; x = FT_ABS( x );
s ^= y; y = FT_ABS( y );
ft_multo64( x, y, z );
@@ -445,7 +508,7 @@
x->lo = (FT_UInt32)-(FT_Int32)x->lo;
x->hi = ~x->hi + !x->lo;
}
s ^= y; y = ABS( y );
s ^= y; y = FT_ABS( y );
/* Shortcut */
if ( x->hi == 0 )
@@ -499,7 +562,7 @@
x->lo = (FT_UInt32)-(FT_Int32)x->lo;
x->hi = ~x->hi + !x->lo;
}
s ^= y; y = ABS( y );
s ^= y; y = FT_ABS( y );
/* Shortcut */
if ( x->hi == 0 )
@@ -558,4 +621,4 @@
}
/* END */
/* END */
+4 -4
View File
@@ -4,7 +4,7 @@
/* */
/* Memory debugger (body). */
/* */
/* Copyright 2001, 2002 by */
/* Copyright 2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -604,7 +604,7 @@
p = getenv( "FT2_ALLOC_TOTAL_MAX" );
if ( p != NULL )
{
FT_Long total_max = atol(p);
FT_Long total_max = ft_atol(p);
if ( total_max > 0 )
{
@@ -616,7 +616,7 @@
p = getenv( "FT2_ALLOC_COUNT_MAX" );
if ( p != NULL )
{
FT_Long total_count = atol(p);
FT_Long total_count = ft_atol(p);
if ( total_count > 0 )
{
@@ -715,4 +715,4 @@
#endif /* !FT_DEBUG_MEMORY */
/* END */
/* END */
+57 -12
View File
@@ -4,7 +4,7 @@
/* */
/* Debugging and logging component (body). */
/* */
/* Copyright 1996-2001 by */
/* Copyright 1996-2001, 2002, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -82,8 +82,9 @@
/* array of trace levels, initialized to 0 */
int ft_trace_levels[trace_count];
/* define array of trace toggle names */
#define FT_TRACE_DEF(x) #x ,
#define FT_TRACE_DEF( x ) #x ,
static const char* ft_trace_toggles[trace_count + 1] =
{
@@ -94,19 +95,43 @@
#undef FT_TRACE_DEF
/* documentation is in ftdebug.h */
FT_EXPORT_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return trace_count;
}
/* documentation is in ftdebug.h */
FT_EXPORT_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
int max = FT_Trace_Get_Count();
if ( idx < max )
return ft_trace_toggles[idx];
else
return NULL;
}
/*************************************************************************/
/* */
/* Initialize the tracing sub-system. This is done by retrieving the */
/* value of the "FT2_DEBUG" environment variable. It must be a list of */
/* toggles, separated by spaces, `;' or `,'. Example: */
/* value of the `FT2_DEBUG' environment variable. It must be a list of */
/* toggles, separated by spaces, `;', or `,'. Example: */
/* */
/* "any:3 memory:6 stream:5" */
/* export FT2_DEBUG="any:3 memory:6 stream:5" */
/* */
/* This will request that all levels be set to 3, except the trace level */
/* for the memory and stream components which are set to 6 and 5, */
/* This requests that all levels be set to 3, except the trace level for */
/* the memory and stream components which are set to 6 and 5, */
/* respectively. */
/* */
/* See the file <freetype/internal/fttrace.h> for details of the */
/* See the file <include/freetype/internal/fttrace.h> for details of the */
/* available toggle names. */
/* */
/* The level must be between 0 and 6; 0 means quiet (except for serious */
@@ -117,6 +142,7 @@
{
const char* ft2_debug = getenv( "FT2_DEBUG" );
if ( ft2_debug )
{
const char* p = ft2_debug;
@@ -133,10 +159,10 @@
q = p;
while ( *p && *p != ':' )
p++;
if ( *p == ':' && p > q )
{
FT_Int n, i, len = (FT_Int)(p - q);
FT_Int n, i, len = (FT_Int)( p - q );
FT_Int level = -1, found = -1;
@@ -171,7 +197,7 @@
{
if ( found == trace_any )
{
/* special case for "any" */
/* special case for `any' */
for ( n = 0; n < trace_count; n++ )
ft_trace_levels[n] = level;
}
@@ -183,15 +209,34 @@
}
}
#else /* !FT_DEBUG_LEVEL_TRACE */
FT_BASE_DEF( void )
ft_debug_init( void )
{
/* nothing */
}
FT_EXPORT_DEF( FT_Int )
FT_Trace_Get_Count( void )
{
return 0;
}
FT_EXPORT_DEF( const char * )
FT_Trace_Get_Name( FT_Int idx )
{
FT_UNUSED( idx );
return NULL;
}
#endif /* !FT_DEBUG_LEVEL_TRACE */
/* END */
/* END */
+14 -13
View File
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph loader (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,6 +19,7 @@
#include <ft2build.h>
#include FT_INTERNAL_GLYPH_LOADER_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_OBJECTS_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_gloader
@@ -205,7 +206,7 @@
if ( new_max > old_max )
{
new_max = ( new_max + 7 ) & -8;
new_max = FT_PAD_CEIL( new_max, 8 );
if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
FT_RENEW_ARRAY( base->tags, old_max, new_max ) )
@@ -225,7 +226,7 @@
n_contours;
if ( new_max > old_max )
{
new_max = ( new_max + 3 ) & -4;
new_max = FT_PAD_CEIL( new_max, 4 );
if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
goto Exit;
@@ -261,7 +262,7 @@
old_max = loader->max_subglyphs;
if ( new_max > old_max )
{
new_max = ( new_max + 1 ) & -2;
new_max = FT_PAD_CEIL( new_max, 2 );
if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
goto Exit;
@@ -336,17 +337,17 @@
FT_Outline* in = &source->base.outline;
FT_MEM_COPY( out->points, in->points,
num_points * sizeof ( FT_Vector ) );
FT_MEM_COPY( out->tags, in->tags,
num_points * sizeof ( char ) );
FT_MEM_COPY( out->contours, in->contours,
num_contours * sizeof ( short ) );
FT_ARRAY_COPY( out->points, in->points,
num_points );
FT_ARRAY_COPY( out->tags, in->tags,
num_points );
FT_ARRAY_COPY( out->contours, in->contours,
num_contours );
/* do we need to copy the extra points? */
if ( target->use_extra && source->use_extra )
FT_MEM_COPY( target->base.extra_points, source->base.extra_points,
num_points * sizeof ( FT_Vector ) );
FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
num_points );
out->n_points = (short)num_points;
out->n_contours = (short)num_contours;
@@ -358,4 +359,4 @@
}
/* END */
/* END */
+34 -28
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType convenience functions to handle glyphs (body). */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -57,7 +57,7 @@
FT_EXPORT_DEF( void )
FT_Matrix_Multiply( const FT_Matrix* a,
FT_Matrix* b )
FT_Matrix *b )
{
FT_Fixed xx, xy, yx, yy;
@@ -158,8 +158,8 @@
glyph->left = slot->bitmap_left;
glyph->top = slot->bitmap_top;
if ( slot->flags & FT_GLYPH_OWN_BITMAP )
slot->flags &= ~FT_GLYPH_OWN_BITMAP;
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
else
{
/* copy the bitmap into a new buffer */
@@ -206,6 +206,7 @@
}
FT_CALLBACK_TABLE_DEF
const FT_Glyph_Class ft_bitmap_glyph_class =
{
sizeof( FT_BitmapGlyphRec ),
@@ -253,14 +254,11 @@
goto Exit;
/* copy it */
FT_MEM_COPY( target->points, source->points,
source->n_points * sizeof ( FT_Vector ) );
FT_ARRAY_COPY( target->points, source->points, source->n_points );
FT_MEM_COPY( target->tags, source->tags,
source->n_points * sizeof ( FT_Byte ) );
FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
FT_MEM_COPY( target->contours, source->contours,
source->n_contours * sizeof ( FT_Short ) );
FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
/* copy all flags, except the `FT_OUTLINE_OWNER' one */
target->flags = source->flags | FT_OUTLINE_OWNER;
@@ -327,6 +325,7 @@
}
FT_CALLBACK_TABLE_DEF
const FT_Glyph_Class ft_outline_glyph_class =
{
sizeof( FT_OutlineGlyphRec ),
@@ -421,7 +420,7 @@
FT_Get_Glyph( FT_GlyphSlot slot,
FT_Glyph *aglyph )
{
FT_Library library = slot->library;
FT_Library library;
FT_Error error;
FT_Glyph glyph;
@@ -431,6 +430,8 @@
if ( !slot )
return FT_Err_Invalid_Slot_Handle;
library = slot->library;
if ( !aglyph )
return FT_Err_Invalid_Argument;
@@ -541,16 +542,18 @@
clazz->glyph_bbox( glyph, acbox );
/* perform grid fitting if needed */
if ( bbox_mode & ft_glyph_bbox_gridfit )
if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin &= -64;
acbox->yMin &= -64;
acbox->xMax = ( acbox->xMax + 63 ) & -64;
acbox->yMax = ( acbox->yMax + 63 ) & -64;
acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
acbox->xMax = FT_PIX_CEIL( acbox->xMax );
acbox->yMax = FT_PIX_CEIL( acbox->yMax );
}
/* convert to integer pixels if needed */
if ( bbox_mode & ft_glyph_bbox_truncate )
if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
bbox_mode == FT_GLYPH_BBOX_PIXELS )
{
acbox->xMin >>= 6;
acbox->yMin >>= 6;
@@ -571,12 +574,13 @@
FT_Vector* origin,
FT_Bool destroy )
{
FT_GlyphSlotRec dummy;
FT_Error error = FT_Err_Ok;
FT_Glyph glyph;
FT_BitmapGlyph bitmap = NULL;
FT_GlyphSlotRec dummy;
FT_GlyphSlot_InternalRec dummy_internal;
FT_Error error = FT_Err_Ok;
FT_Glyph glyph;
FT_BitmapGlyph bitmap = NULL;
const FT_Glyph_Class* clazz;
const FT_Glyph_Class* clazz;
/* check argument */
@@ -592,7 +596,7 @@
clazz = glyph->clazz;
/* when called with a bitmap glyph, do nothing and return succesfully */
/* when called with a bitmap glyph, do nothing and return successfully */
if ( clazz == &ft_bitmap_glyph_class )
goto Exit;
@@ -600,8 +604,10 @@
goto Bad;
FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
dummy.library = glyph->library;
dummy.format = clazz->glyph_format;
FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
dummy.internal = &dummy_internal;
dummy.library = glyph->library;
dummy.format = clazz->glyph_format;
/* create result bitmap glyph */
error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
@@ -609,7 +615,7 @@
if ( error )
goto Exit;
#if 0
#if 1
/* if `origin' is set, translate the glyph image */
if ( origin )
FT_Glyph_Transform( glyph, 0, origin );
@@ -622,7 +628,7 @@
if ( !error )
error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
#if 0
#if 1
if ( !destroy && origin )
{
FT_Vector v;
@@ -681,4 +687,4 @@
}
/* END */
/* END */
+1 -1
View File
@@ -243,4 +243,4 @@
}
Exit:
return error;
}
}
+1 -1
View File
@@ -158,4 +158,4 @@
}
/* END */
/* END */
+1 -1
View File
@@ -214,4 +214,4 @@
}
/* END */
/* END */
+336 -163
View File
@@ -4,7 +4,7 @@
/* */
/* Mac FOND support. Written by [email protected]. */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -62,15 +62,28 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_STREAM_H
#ifdef __GNUC__
#include "../truetype/ttobjs.h"
#include "../type1/t1objs.h"
/* This is for Mac OS X. Without redefinition, OS_INLINE */
/* expands to `static inline' which doesn't survive the */
/* -ansi compilation flag of GCC. */
#define OS_INLINE static __inline__
#include <Carbon/Carbon.h>
#else
#include "truetype/ttobjs.h"
#include "type1/t1objs.h"
#include <Resources.h>
#include <Fonts.h>
#include <Errors.h>
#include <Files.h>
#include <TextUtils.h>
#endif
#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
#include <FSp_fopen.h>
#endif
#include FT_MAC_H
@@ -82,12 +95,50 @@
#define PREFER_LWFN 1
#endif
#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer )
FT_CALLBACK_DEF( void )
ft_FSp_stream_close( FT_Stream stream )
{
fclose( STREAM_FILE( stream ) );
stream->descriptor.pointer = NULL;
stream->size = 0;
stream->base = 0;
}
FT_CALLBACK_DEF( unsigned long )
ft_FSp_stream_io( FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count )
{
FILE* file;
file = STREAM_FILE( stream );
fseek( file, offset, SEEK_SET );
return (unsigned long)fread( buffer, 1, count, file );
}
#endif /* __MWERKS__ && !TARGET_RT_MAC_MACHO */
/* Given a pathname, fill in a file spec. */
static int
file_spec_from_path( const char* pathname,
FSSpec* spec )
{
#if TARGET_API_MAC_CARBON
#if !TARGET_API_MAC_OS8 && \
!( defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO )
OSErr e;
FSRef ref;
@@ -118,12 +169,13 @@
return 0;
#endif
}
/* Return the file type of the file specified by spec. */
static OSType
get_file_type( FSSpec* spec )
get_file_type( const FSSpec* spec )
{
FInfo finfo;
@@ -135,22 +187,6 @@
}
#if TARGET_API_MAC_CARBON
/* is this a Mac OS X .dfont file */
static Boolean
is_dfont( FSSpec* spec )
{
int nameLen = spec->name[0];
return nameLen >= 6 &&
!memcmp( spec->name + nameLen - 5, ".dfont", 6 );
}
#endif
/* Given a PostScript font name, create the Macintosh LWFN file name. */
static void
create_lwfn_name( char* ps_name,
@@ -165,7 +201,7 @@
while ( *q )
{
if ( isupper( *q ) )
if ( ft_isupper( *q ) )
{
if ( count )
max = 3;
@@ -212,9 +248,9 @@
/* Make a file spec for an LWFN file from a FOND resource and
a file name. */
static FT_Error
make_lwfn_spec( Handle fond,
unsigned char* file_name,
FSSpec* spec )
make_lwfn_spec( Handle fond,
const unsigned char* file_name,
FSSpec* spec )
{
FT_Error error;
short ref_num, v_ref_num;
@@ -235,12 +271,24 @@
}
static short
count_faces_sfnt( char *fond_data )
{
/* The count is 1 greater than the value in the FOND. */
/* Isn't that cute? :-) */
return 1 + *( (short *)( fond_data + sizeof ( FamRec ) ) );
}
/* Look inside the FOND data, answer whether there should be an SFNT
resource, and answer the name of a possible LWFN Type 1 file.
Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
to load a face OTHER than the first one in the FOND!
*/
static void
parse_fond( char* fond_data,
short* have_sfnt,
@@ -260,19 +308,24 @@
fond = (FamRec*)fond_data;
assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
base_assoc = assoc;
assoc += face_index; /* add on the face_index! */
/* if the face at this index is not scalable,
fall back to the first one (old behavior) */
if ( assoc->fontSize == 0 )
/* Let's do a little range checking before we get too excited here */
if ( face_index < count_faces_sfnt( fond_data ) )
{
*have_sfnt = 1;
*sfnt_id = assoc->fontID;
}
else if ( base_assoc->fontSize == 0 )
{
*have_sfnt = 1;
*sfnt_id = base_assoc->fontID;
assoc += face_index; /* add on the face_index! */
/* if the face at this index is not scalable,
fall back to the first one (old behavior) */
if ( assoc->fontSize == 0 )
{
*have_sfnt = 1;
*sfnt_id = assoc->fontID;
}
else if ( base_assoc->fontSize == 0 )
{
*have_sfnt = 1;
*sfnt_id = base_assoc->fontID;
}
}
if ( fond->ffStylOff )
@@ -304,7 +357,7 @@
if ( ps_name_len != 0 )
{
memcpy(ps_name, names[0] + 1, ps_name_len);
ft_memcpy(ps_name, names[0] + 1, ps_name_len);
ps_name[ps_name_len] = 0;
}
if ( style->indexes[0] > 1 )
@@ -312,7 +365,7 @@
unsigned char* suffixes = names[style->indexes[0] - 1];
for ( i = 1; i < suffixes[0]; i++ )
for ( i = 1; i <= suffixes[0]; i++ )
{
unsigned char* s;
size_t j = suffixes[i] - 1;
@@ -325,7 +378,7 @@
if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) )
{
memcpy( ps_name + ps_name_len, s + 1, s_len );
ft_memcpy( ps_name + ps_name_len, s + 1, s_len );
ps_name_len += s_len;
ps_name[ps_name_len] = 0;
}
@@ -339,6 +392,33 @@
}
static short
count_faces( Handle fond )
{
short sfnt_id, have_sfnt, have_lwfn = 0;
Str255 lwfn_file_name;
FSSpec lwfn_spec;
HLock( fond );
parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 );
HUnlock( fond );
if ( lwfn_file_name[0] )
{
if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok )
have_lwfn = 1; /* yeah, we got one! */
else
have_lwfn = 0; /* no LWFN file found */
}
if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
return 1;
else
return count_faces_sfnt( *fond );
}
/* Read Type 1 data from the POST resources inside the LWFN file,
return a PFB buffer. This is somewhat convoluted because the FT2
PFB parser wants the ASCII header as one chunk, and the LWFN
@@ -346,12 +426,12 @@
of the same type together. */
static FT_Error
read_lwfn( FT_Memory memory,
FSSpec* lwfn_spec,
short res_ref,
FT_Byte** pfb_data,
FT_ULong* size )
{
FT_Error error = FT_Err_Ok;
short res_ref, res_id;
short res_id;
unsigned char *buffer, *p, *size_p = NULL;
FT_ULong total_size = 0;
FT_ULong post_size, pfb_chunk_size;
@@ -359,13 +439,10 @@
char code, last_code;
res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
if ( ResError() )
return FT_Err_Out_Of_Memory;
UseResFile( res_ref );
/* First pass: load all POST resources, and determine the size of
the output buffer. */
/* First pass: load all POST resources, and determine the size of */
/* the output buffer. */
res_id = 501;
last_code = -1;
@@ -392,8 +469,8 @@
if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
goto Error;
/* Second pass: append all POST data to the buffer, add PFB fields.
Glue all consecutive chunks of the same type together. */
/* Second pass: append all POST data to the buffer, add PFB fields. */
/* Glue all consecutive chunks of the same type together. */
p = buffer;
res_id = 501;
last_code = -1;
@@ -538,32 +615,75 @@
args.driver = FT_Get_Module( library, driver_name );
}
/* At this point, face_index has served its purpose; */
/* whoever calls this function has already used it to */
/* locate the correct font data. We should not propagate */
/* this index to FT_Open_Face() (unless it is negative). */
if ( face_index > 0 )
face_index = 0;
error = FT_Open_Face( library, &args, face_index, aface );
if ( error == FT_Err_Ok )
(*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
else
{
FT_Stream_CloseFunc( stream );
FT_FREE( stream );
}
return error;
}
static FT_Error
OpenFileAsResource( const FSSpec* spec,
short *p_res_ref )
{
FT_Error error;
#if !TARGET_API_MAC_OS8
FSRef hostContainerRef;
error = FSpMakeFSRef( spec, &hostContainerRef );
if ( error == noErr )
error = FSOpenResourceFile( &hostContainerRef,
0, NULL, fsRdPerm, p_res_ref );
/* If the above fails, then it is probably not a resource file */
/* However, it has been reported that FSOpenResourceFile() sometimes */
/* fails on some old resource-fork files, which FSpOpenResFile() can */
/* open. So, just try again with FSpOpenResFile() and see what */
/* happens :-) */
if ( error != noErr )
#endif /* !TARGET_API_MAC_OS8 */
{
*p_res_ref = FSpOpenResFile( spec, fsRdPerm );
error = ResError();
}
return error ? FT_Err_Cannot_Open_Resource : FT_Err_Ok;
}
/* Create a new FT_Face from a file spec to an LWFN file. */
static FT_Error
FT_New_Face_From_LWFN( FT_Library library,
FSSpec* spec,
FT_Long face_index,
FT_Face *aface )
FT_New_Face_From_LWFN( FT_Library library,
const FSSpec* lwfn_spec,
FT_Long face_index,
FT_Face *aface )
{
FT_Byte* pfb_data;
FT_ULong pfb_size;
FT_Error error;
short res_ref;
error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size );
error = OpenFileAsResource( lwfn_spec, &res_ref );
if ( error )
return error;
error = read_lwfn( library->memory, res_ref, &pfb_data, &pfb_size );
if ( error )
return error;
@@ -588,6 +708,7 @@
size_t sfnt_size;
FT_Error error = 0;
FT_Memory memory = library->memory;
int is_cff;
sfnt = GetResource( 'sfnt', sfnt_id );
@@ -606,11 +727,16 @@
HUnlock( sfnt );
ReleaseResource( sfnt );
is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' &&
sfnt_data[1] == 'T' &&
sfnt_data[2] == 'T' &&
sfnt_data[3] == 'O';
return open_face_from_buffer( library,
sfnt_data,
sfnt_size,
face_index,
"truetype",
is_cff ? "cff" : "truetype",
aface );
}
@@ -618,34 +744,34 @@
/* Create a new FT_Face from a file spec to a suitcase file. */
static FT_Error
FT_New_Face_From_Suitcase( FT_Library library,
FSSpec* spec,
short res_ref,
FT_Long face_index,
FT_Face *aface )
{
FT_Error error = FT_Err_Ok;
short res_ref, res_index;
short res_index;
Handle fond;
short num_faces;
res_ref = FSpOpenResFile( spec, fsRdPerm );
if ( ResError() )
return FT_Err_Cannot_Open_Resource;
UseResFile( res_ref );
/* face_index may be -1, in which case we
just need to do a sanity check */
if ( face_index < 0 )
res_index = 1;
else
for ( res_index = 1; ; ++res_index )
{
res_index = (short)( face_index + 1 );
face_index = 0;
}
fond = Get1IndResource( 'FOND', res_index );
if ( ResError() )
{
error = FT_Err_Cannot_Open_Resource;
goto Error;
fond = Get1IndResource( 'FOND', res_index );
if ( ResError() )
{
error = FT_Err_Cannot_Open_Resource;
goto Error;
}
if ( face_index < 0 )
break;
num_faces = count_faces( fond );
if ( face_index < num_faces )
break;
face_index -= num_faces;
}
error = FT_New_Face_From_FOND( library, fond, face_index, aface );
@@ -656,57 +782,6 @@
}
#if TARGET_API_MAC_CARBON
/* Create a new FT_Face from a file spec to a suitcase file. */
static FT_Error
FT_New_Face_From_dfont( FT_Library library,
FSSpec* spec,
FT_Long face_index,
FT_Face* aface )
{
FT_Error error = FT_Err_Ok;
short res_ref, res_index;
Handle fond;
FSRef hostContainerRef;
error = FSpMakeFSRef( spec, &hostContainerRef );
if ( error == noErr )
error = FSOpenResourceFile( &hostContainerRef,
0, NULL, fsRdPerm, &res_ref );
if ( error != noErr )
return FT_Err_Cannot_Open_Resource;
UseResFile( res_ref );
/* face_index may be -1, in which case we
just need to do a sanity check */
if ( face_index < 0 )
res_index = 1;
else
{
res_index = (short)( face_index + 1 );
face_index = 0;
}
fond = Get1IndResource( 'FOND', res_index );
if ( ResError() )
{
error = FT_Err_Cannot_Open_Resource;
goto Error;
}
error = FT_New_Face_From_FOND( library, fond, face_index, aface );
Error:
CloseResFile( res_ref );
return error;
}
#endif
/* documentation is in ftmac.h */
FT_EXPORT_DEF( FT_Error )
@@ -757,9 +832,9 @@
/* documentation is in ftmac.h */
FT_EXPORT_DEF( FT_Error )
FT_GetFile_From_Mac_Name( char* fontName,
FSSpec* pathSpec,
FT_Long* face_index )
FT_GetFile_From_Mac_Name( const char* fontName,
FSSpec* pathSpec,
FT_Long* face_index )
{
OptionBits options = kFMUseGlobalScopeOption;
@@ -820,7 +895,7 @@
the_font = font;
}
else
++(*face_index);
++(*face_index);
}
}
@@ -839,23 +914,46 @@
return FT_Err_Unknown_File_Format;
}
/* Common function to load a new FT_Face from a resource file. */
static long
ResourceForkSize(FSSpec* spec)
static FT_Error
FT_New_Face_From_Resource( FT_Library library,
const FSSpec *spec,
FT_Long face_index,
FT_Face *aface )
{
long len;
short refNum;
OSErr e;
OSType file_type;
short res_ref;
FT_Error error;
e = FSpOpenRF( spec, fsRdPerm, &refNum ); /* I.M. Files 2-155 */
if ( e == noErr )
if ( OpenFileAsResource( spec, &res_ref ) == FT_Err_Ok )
{
e = GetEOF( refNum, &len );
FSClose( refNum );
/* LWFN is a (very) specific file format, check for it explicitly */
file_type = get_file_type( spec );
if ( file_type == 'LWFN' )
return FT_New_Face_From_LWFN( library, spec, face_index, aface );
/* Otherwise the file type doesn't matter (there are more than */
/* `FFIL' and `tfil'). Just try opening it as a font suitcase; */
/* if it works, fine. */
error = FT_New_Face_From_Suitcase( library, res_ref,
face_index, aface );
if ( error == 0 )
return error;
/* else forget about the resource fork and fall through to */
/* data fork formats */
CloseResFile( res_ref );
}
return ( e == noErr ) ? len : 0;
/* let it fall through to normal loader (.ttf, .otf, etc.); */
/* we signal this by returning no error and no FT_Face */
*aface = NULL;
return 0;
}
@@ -878,7 +976,7 @@
{
FT_Open_Args args;
FSSpec spec;
OSType file_type;
FT_Error error;
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
@@ -888,26 +986,9 @@
if ( file_spec_from_path( pathname, &spec ) )
return FT_Err_Invalid_Argument;
/* Regardless of type, don't try to use the resource fork if it is */
/* empty. Some TTF fonts have type `FFIL', for example, but they */
/* only have data forks. */
if ( ResourceForkSize( &spec ) != 0 )
{
file_type = get_file_type( &spec );
if ( file_type == 'FFIL' || file_type == 'tfil' )
return FT_New_Face_From_Suitcase( library, &spec, face_index, aface );
if ( file_type == 'LWFN' )
return FT_New_Face_From_LWFN( library, &spec, face_index, aface );
}
#if TARGET_API_MAC_CARBON
if ( is_dfont( &spec ) )
return FT_New_Face_From_dfont( library, &spec, face_index, aface );
#endif
error = FT_New_Face_From_Resource( library, &spec, face_index, aface );
if ( error != 0 || *aface != NULL )
return error;
/* let it fall through to normal loader (.ttf, .otf, etc.) */
args.flags = FT_OPEN_PATHNAME;
@@ -916,4 +997,96 @@
}
/* END */
/*************************************************************************/
/* */
/* <Function> */
/* FT_New_Face_From_FSSpec */
/* */
/* <Description> */
/* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */
/* accepts an FSSpec instead of a path. */
/* */
FT_EXPORT_DEF( FT_Error )
FT_New_Face_From_FSSpec( FT_Library library,
const FSSpec *spec,
FT_Long face_index,
FT_Face *aface )
{
FT_Open_Args args;
FT_Error error;
FT_Stream stream;
FILE* file;
FT_Memory memory;
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
if ( !spec )
return FT_Err_Invalid_Argument;
error = FT_New_Face_From_Resource( library, spec, face_index, aface );
if ( error != 0 || *aface != NULL )
return error;
/* let it fall through to normal loader (.ttf, .otf, etc.) */
#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
/* Codewarrior's C library can open a FILE from a FSSpec */
/* but we must compile with FSp_fopen.c in addition to */
/* runtime libraries. */
memory = library->memory;
if ( FT_NEW( stream ) )
return error;
stream->memory = memory;
file = FSp_fopen( spec, "rb" );
if ( !file )
return FT_Err_Cannot_Open_Resource;
fseek( file, 0, SEEK_END );
stream->size = ftell( file );
fseek( file, 0, SEEK_SET );
stream->descriptor.pointer = file;
stream->pathname.pointer = NULL;
stream->pos = 0;
stream->read = ft_FSp_stream_io;
stream->close = ft_FSp_stream_close;
args.flags = FT_OPEN_STREAM;
args.stream = stream;
error = FT_Open_Face( library, &args, face_index, aface );
if ( error == FT_Err_Ok )
(*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
#else /* !(__MWERKS__ && !TARGET_RT_MAC_MACHO) */
{
FSRef ref;
UInt8 path[256];
OSErr err;
err = FSpMakeFSRef(spec, &ref);
if ( !err )
{
err = FSRefMakePath( &ref, path, sizeof ( path ) );
if ( !err )
error = FT_New_Face( library, (const char*)path,
face_index, aface );
}
if ( err )
error = FT_Err_Cannot_Open_Resource;
}
#endif /* !(__MWERKS__ && !TARGET_RT_MAC_MACHO) */
return error;
}
/* END */
+48 -43
View File
@@ -4,7 +4,7 @@
/* */
/* Multiple Master font support (body). */
/* */
/* Copyright 1996-2001 by */
/* Copyright 1996-2001, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,6 +19,7 @@
#include <ft2build.h>
#include FT_MULTIPLE_MASTERS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_MULTIPLE_MASTERS_H
/*************************************************************************/
@@ -31,15 +32,15 @@
#define FT_COMPONENT trace_mm
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Multi_Master( FT_Face face,
FT_Multi_Master *amaster )
static FT_Error
ft_face_get_mm_service( FT_Face face,
FT_Service_MultiMasters *aservice )
{
FT_Error error;
*aservice = NULL;
if ( !face )
return FT_Err_Invalid_Face_Handle;
@@ -47,14 +48,34 @@
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
{
FT_Driver driver = face->driver;
FT_Get_MM_Func func;
FT_FACE_LOOKUP_SERVICE( face,
*aservice,
MULTI_MASTERS );
if ( aservice )
error = FT_Err_Ok;
}
return error;
}
func = (FT_Get_MM_Func)driver->root.clazz->get_interface(
FT_MODULE( driver ), "get_mm" );
if ( func )
error = func( face, amaster );
/* documentation is in ftmm.h */
FT_EXPORT_DEF( FT_Error )
FT_Get_Multi_Master( FT_Face face,
FT_Multi_Master *amaster )
{
FT_Error error;
FT_Service_MultiMasters service;
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
error = FT_Err_Invalid_Argument;
if ( service->get_mm )
error = service->get_mm( face, amaster );
}
return error;
@@ -68,24 +89,16 @@
FT_UInt num_coords,
FT_Long* coords )
{
FT_Error error;
FT_Error error;
FT_Service_MultiMasters service;
if ( !face )
return FT_Err_Invalid_Face_Handle;
error = FT_Err_Invalid_Argument;
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
FT_Driver driver = face->driver;
FT_Set_MM_Design_Func func;
func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface(
FT_MODULE( driver ), "set_mm_design" );
if ( func )
error = func( face, num_coords, coords );
error = FT_Err_Invalid_Argument;
if ( service->set_mm_design )
error = service->set_mm_design( face, num_coords, coords );
}
return error;
@@ -99,28 +112,20 @@
FT_UInt num_coords,
FT_Fixed* coords )
{
FT_Error error;
FT_Error error;
FT_Service_MultiMasters service;
if ( !face )
return FT_Err_Invalid_Face_Handle;
error = FT_Err_Invalid_Argument;
if ( FT_HAS_MULTIPLE_MASTERS( face ) )
error = ft_face_get_mm_service( face, &service );
if ( !error )
{
FT_Driver driver = face->driver;
FT_Set_MM_Blend_Func func;
func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface(
FT_MODULE( driver ), "set_mm_blend" );
if ( func )
error = func( face, num_coords, coords );
error = FT_Err_Invalid_Argument;
if ( service->set_mm_blend )
error = service->set_mm_blend( face, num_coords, coords );
}
return error;
}
/* END */
/* END */
+1 -1
View File
@@ -91,4 +91,4 @@
#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
/* END */
/* END */
+1 -1
View File
@@ -393,4 +393,4 @@
}
return error;
}
}
File diff suppressed because it is too large Load Diff
+145 -8
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType outline management (body). */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,6 +26,7 @@
#include <ft2build.h>
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_TRIGONOMETRY_H
/*************************************************************************/
@@ -357,14 +358,11 @@
source->n_contours != target->n_contours )
return FT_Err_Invalid_Argument;
FT_MEM_COPY( target->points, source->points,
source->n_points * sizeof ( FT_Vector ) );
FT_ARRAY_COPY( target->points, source->points, source->n_points );
FT_MEM_COPY( target->tags, source->tags,
source->n_points * sizeof ( FT_Byte ) );
FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
FT_MEM_COPY( target->contours, source->contours,
source->n_contours * sizeof ( FT_Short ) );
FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
/* copy all flags, except the `FT_OUTLINE_OWNER' one */
is_owner = target->flags & FT_OUTLINE_OWNER;
@@ -655,4 +653,143 @@
}
/* END */
typedef struct FT_OrientationExtremumRec_
{
FT_Int index;
FT_Long pos;
FT_Int first;
FT_Int last;
} FT_OrientationExtremumRec;
static FT_Orientation
ft_orientation_extremum_compute( FT_OrientationExtremumRec* extremum,
FT_Outline* outline )
{
FT_Vector *point, *first, *last, *prev, *next;
FT_Vector* points = outline->points;
FT_Angle angle_in, angle_out;
/* compute the previous and next points in the same contour */
point = points + extremum->index;
first = points + extremum->first;
last = points + extremum->last;
prev = point;
next = point;
do
{
prev = ( prev == first ) ? last : prev - 1;
if ( prev == point )
return FT_ORIENTATION_TRUETYPE; /* degenerate case */
} while ( prev->x != point->x || prev->y != point->y );
do
{
next = ( next == last ) ? first : next + 1;
if ( next == point )
return FT_ORIENTATION_TRUETYPE; /* shouldn't happen */
} while ( next->x != point->x || next->y != point->y );
/* now compute the orientation of the `out' vector relative */
/* to the `in' vector. */
angle_in = FT_Atan2( point->x - prev->x, point->y - prev->y );
angle_out = FT_Atan2( next->x - point->x, next->y - point->y );
return ( FT_Angle_Diff( angle_in, angle_out ) >= 0 )
? FT_ORIENTATION_TRUETYPE
: FT_ORIENTATION_POSTSCRIPT;
}
FT_EXPORT_DEF( FT_Orientation )
FT_Outline_Get_Orientation( FT_Outline* outline )
{
FT_Orientation result = FT_ORIENTATION_TRUETYPE;
if ( outline && outline->n_points > 0 )
{
FT_OrientationExtremumRec xmin, ymin, xmax, ymax;
FT_Int n;
FT_Int first, last;
FT_Vector* points = outline->points;
xmin.pos = ymin.pos = +32768L;
xmax.pos = ymax.pos = -32768L;
xmin.index = ymin.index = xmax.index = ymax.index = -1;
first = 0;
for ( n = 0; n < outline->n_contours; n++, first = last + 1 )
{
last = outline->contours[n];
/* skip single-point contours; these are degenerated cases */
if ( last > first + 1 )
{
FT_Int i;
for ( i = first; i < last; i++ )
{
FT_Pos x = points[i].x;
FT_Pos y = points[i].y;
if ( x < xmin.pos )
{
xmin.pos = x;
xmin.index = i;
xmin.first = first;
xmin.last = last;
}
if ( x > xmax.pos )
{
xmax.pos = x;
xmax.index = i;
xmax.first = first;
xmax.last = last;
}
if ( y < ymin.pos )
{
ymin.pos = y;
ymin.index = i;
ymin.first = first;
ymin.last = last;
}
if ( y > ymax.pos )
{
ymax.pos = y;
ymax.index = i;
ymax.first = first;
ymax.last = last;
}
}
}
if ( xmin.index >= 0 )
result = ft_orientation_extremum_compute( &xmin, outline );
else if ( xmax.index >= 0 )
result = ft_orientation_extremum_compute( &xmax, outline );
else if ( ymin.index >= 0 )
result = ft_orientation_extremum_compute( &ymin, outline );
else if ( ymax.index >= 0 )
result = ft_orientation_extremum_compute( &ymax, outline );
}
}
return result;
}
/* END */
+67 -46
View File
@@ -2,9 +2,9 @@
/* */
/* ftpfr.c */
/* */
/* FreeType API for accessing PFR-specific data */
/* FreeType API for accessing PFR-specific data (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,48 +16,36 @@
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_PFR_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_PFR_H
/* check the format */
static FT_Error
ft_pfr_check( FT_Face face,
FT_PFR_Service *aservice )
/* check the format */
static FT_Service_PfrMetrics
ft_pfr_check( FT_Face face )
{
FT_Error error = FT_Err_Bad_Argument;
FT_Service_PfrMetrics service;
if ( face && face->driver )
{
FT_Module module = (FT_Module) face->driver;
const char* name = module->clazz->module_name;
if ( name[0] == 'p' &&
name[1] == 'f' &&
name[2] == 'r' &&
name[4] == 0 )
{
*aservice = (FT_PFR_Service) module->clazz->module_interface;
error = 0;
}
}
return error;
FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS );
return service;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Metrics( FT_Face face,
FT_UInt *aoutline_resolution,
FT_UInt *ametrics_resolution,
FT_Fixed *ametrics_x_scale,
FT_Fixed *ametrics_y_scale )
FT_Get_PFR_Metrics( FT_Face face,
FT_UInt *aoutline_resolution,
FT_UInt *ametrics_resolution,
FT_Fixed *ametrics_x_scale,
FT_Fixed *ametrics_y_scale )
{
FT_Error error;
FT_PFR_Service service;
FT_Error error = FT_Err_Ok;
FT_Service_PfrMetrics service;
error = ft_pfr_check( face, &service );
if ( !error )
service = ft_pfr_check( face );
if ( service )
{
error = service->get_metrics( face,
aoutline_resolution,
@@ -65,41 +53,74 @@
ametrics_x_scale,
ametrics_y_scale );
}
else if ( face )
{
FT_Fixed x_scale, y_scale;
/* this is not a PFR font */
*aoutline_resolution = face->units_per_EM;
*ametrics_resolution = face->units_per_EM;
x_scale = y_scale = 0x10000L;
if ( face->size )
{
x_scale = face->size->metrics.x_scale;
y_scale = face->size->metrics.y_scale;
}
*ametrics_x_scale = x_scale;
*ametrics_y_scale = y_scale;
}
else
error = FT_Err_Invalid_Argument;
return error;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Kerning( FT_Face face,
FT_UInt left,
FT_UInt right,
FT_Vector *avector )
{
FT_Error error;
FT_PFR_Service service;
FT_Error error;
FT_Service_PfrMetrics service;
error = ft_pfr_check( face, &service );
if ( !error )
{
service = ft_pfr_check( face );
if ( service )
error = service->get_kerning( face, left, right, avector );
}
else if ( face )
error = FT_Get_Kerning( face, left, right,
FT_KERNING_UNSCALED, avector );
else
error = FT_Err_Invalid_Argument;
return error;
}
FT_EXPORT_DEF( FT_Error )
FT_Get_PFR_Advance( FT_Face face,
FT_UInt gindex,
FT_Pos *aadvance )
FT_Get_PFR_Advance( FT_Face face,
FT_UInt gindex,
FT_Pos *aadvance )
{
FT_Error error;
FT_PFR_Service service;
FT_Error error;
FT_Service_PfrMetrics service;
error = ft_pfr_check( face, &service );
if ( !error )
service = ft_pfr_check( face );
if ( service )
{
error = service->get_advance( face, gindex, aadvance );
}
else
/* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */
error = FT_Err_Invalid_Argument;
return error;
}
/* END */
/* END */
+717
View File
@@ -0,0 +1,717 @@
/***************************************************************************/
/* */
/* ftrfork.c */
/* */
/* Embedded resource forks accessor (body). */
/* */
/* Copyright 2004 by */
/* Masatake YAMATO and Redhat K.K. */
/* */
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
/* derived from ftobjs.c. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
/***************************************************************************/
/* Development of the code in this file is support of */
/* Information-technology Promotion Agency, Japan. */
/***************************************************************************/
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_RFORK_H
#undef FT_COMPONENT
#define FT_COMPONENT trace_raccess
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Resource fork directory access ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
FT_Long rfork_offset,
FT_Long *map_offset,
FT_Long *rdata_pos )
{
FT_Error error;
unsigned char head[16], head2[16];
FT_Long map_pos, rdata_len;
int allzeros, allmatch, i;
FT_Long type_list;
FT_UNUSED( library );
error = FT_Stream_Seek( stream, rfork_offset );
if ( error )
return error;
error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
if ( error )
return error;
*rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
( head[1] << 16 ) |
( head[2] << 8 ) |
head[3] );
map_pos = rfork_offset + ( ( head[4] << 24 ) |
( head[5] << 16 ) |
( head[6] << 8 ) |
head[7] );
rdata_len = ( head[ 8] << 24 ) |
( head[ 9] << 16 ) |
( head[10] << 8 ) |
head[11];
/* map_len = head[12] .. head[15] */
if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos );
if ( error )
return error;
head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
if ( error )
return error;
allzeros = 1;
allmatch = 1;
for ( i = 0; i < 16; ++i )
{
if ( head2[i] != 0 )
allzeros = 0;
if ( head2[i] != head[i] )
allmatch = 0;
}
if ( !allzeros && !allmatch )
return FT_Err_Unknown_File_Format;
/* If we have reached this point then it is probably a mac resource */
/* file. Now, does it contain any interesting resources? */
/* Skip handle to next resource map, the file resource number, and */
/* attributes. */
(void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
+ 2 /* skip file resource number */
+ 2 ); /* skip attributes */
if ( FT_READ_USHORT( type_list ) )
return error;
if ( type_list == -1 )
return FT_Err_Unknown_File_Format;
error = FT_Stream_Seek( stream, map_pos + type_list );
if ( error )
return error;
*map_offset = map_pos + type_list;
return FT_Err_Ok;
}
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
FT_Long **offsets,
FT_Long *count )
{
FT_Error error;
int i, j, cnt, subcnt;
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
FT_Long *offsets_internal;
error = FT_Stream_Seek( stream, map_offset );
if ( error )
return error;
if ( FT_READ_USHORT( cnt ) )
return error;
cnt++;
for ( i = 0; i < cnt; ++i )
{
if ( FT_READ_LONG( tag_internal ) ||
FT_READ_USHORT( subcnt ) ||
FT_READ_USHORT( rpos ) )
return error;
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
(char)( 0xff & ( tag_internal >> 24 ) ),
(char)( 0xff & ( tag_internal >> 16 ) ),
(char)( 0xff & ( tag_internal >> 8 ) ),
(char)( 0xff & ( tag_internal >> 0 ) ) ));
if ( tag_internal == tag )
{
*count = subcnt + 1;
rpos += map_offset;
error = FT_Stream_Seek( stream, rpos );
if ( error )
return error;
if ( FT_ALLOC( offsets_internal, *count * sizeof( FT_Long ) ) )
return error;
for ( j = 0; j < *count; ++j )
{
(void)FT_STREAM_SKIP( 2 ); /* resource id */
(void)FT_STREAM_SKIP( 2 ); /* rsource name */
if ( FT_READ_LONG( temp ) )
{
FT_FREE( offsets_internal );
return error;
}
offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
(void)FT_STREAM_SKIP( 4 ); /* mbz */
}
*offsets = offsets_internal;
return FT_Err_Ok;
}
}
return FT_Err_Cannot_Open_Resource;
}
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** Guessing functions ****/
/**** ****/
/**** When you add a new guessing function, ****/
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
typedef FT_Error
(*raccess_guess_func)( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset );
/*************************************************************************/
/**** ****/
/**** Helper functions ****/
/**** ****/
/*************************************************************************/
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char * base_file_name,
FT_Int32 magic,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char * file_name,
FT_Long *result_offset );
static char *
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion );
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Long i;
raccess_guess_func funcs[FT_RACCESS_N_RULES] =
{
raccess_guess_apple_double,
raccess_guess_apple_single,
raccess_guess_darwin_ufs_export,
raccess_guess_darwin_hfsplus,
raccess_guess_vfat,
raccess_guess_linux_cap,
raccess_guess_linux_double,
raccess_guess_linux_netatalk,
};
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
errors[i] = FT_Stream_Seek( stream, 0 );
if ( errors[i] )
continue ;
errors[i] = (funcs[i])( library, stream, base_name,
&(new_names[i]), &(offsets[i]) );
}
return;
}
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
*result_file_name = NULL;
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
*result_file_name = NULL;
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "._" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
/*
Only meaningful on systems with hfs+ drivers (or Macs).
*/
FT_Error error;
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
if ( FT_ALLOC( newpath,
ft_strlen( base_file_name ) + ft_strlen( "/rsrc" ) + 1 ) )
return error;
ft_strcpy( newpath, base_file_name );
ft_strcat( newpath, "/rsrc" );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
"resource.frk/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "%" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char * base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
".AppleDouble/" );
if ( !newpath )
return FT_Err_Out_Of_Memory;
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char * base_file_name,
FT_Int32 magic,
FT_Long *result_offset )
{
FT_Int32 magic_from_stream;
FT_Error error;
FT_Int32 version_number;
FT_UShort n_of_entries;
int i;
FT_UInt32 entry_id, entry_offset, entry_length;
const FT_UInt32 resource_fork_entry_id = 0x2;
FT_UNUSED( library );
FT_UNUSED( base_file_name );
if ( FT_READ_LONG ( magic_from_stream ) )
return error;
if ( magic_from_stream != magic )
return FT_Err_Unknown_File_Format;
if ( FT_READ_LONG( version_number ) )
return error;
/* filler */
error = FT_Stream_Skip( stream, 16 );
if ( error )
return error;
if ( FT_READ_USHORT( n_of_entries ) )
return error;
if ( n_of_entries == 0 )
return FT_Err_Unknown_File_Format;
for ( i = 0; i < n_of_entries; i++ )
{
if ( FT_READ_LONG( entry_id ) )
return error;
if ( entry_id == resource_fork_entry_id )
{
if ( FT_READ_LONG( entry_offset ) ||
FT_READ_LONG( entry_length ) )
continue;
*result_offset = entry_offset;
return FT_Err_Ok;
}
else
FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
}
return FT_Err_Unknown_File_Format;
}
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char * file_name,
FT_Long *result_offset )
{
FT_Memory memory;
FT_Open_Args args2;
FT_Stream stream2;
char * nouse = NULL;
FT_Error error;
memory = library->memory;
args2.flags = FT_OPEN_PATHNAME;
args2.pathname = file_name;
error = FT_Stream_New( library, &args2, &stream2 );
if ( error )
return error;
error = raccess_guess_apple_double( library, stream2, file_name,
&nouse, result_offset );
FT_Stream_Close( stream2 );
return error;
}
static char*
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion )
{
char* new_name;
char* tmp;
const char* slash;
unsigned new_length;
FT_ULong error;
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
if ( FT_ALLOC( new_name, new_length + 1 ) )
return NULL;
tmp = ft_strrchr( original_name, '/' );
if ( tmp )
{
ft_strncpy( new_name, original_name, tmp - original_name + 1 );
new_name[tmp - original_name + 1] = '\0';
slash = tmp + 1;
}
else
{
slash = original_name;
new_name[0] = '\0';
}
ft_strcat( new_name, insertion );
ft_strcat( new_name, slash );
return new_name;
}
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/*************************************************************************/
/* Dummy function; just sets errors */
/*************************************************************************/
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
int i;
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
offsets[i] = 0;
errors[i] = FT_Err_Unimplemented_Feature;
}
}
#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
/* END */
+5 -5
View File
@@ -4,7 +4,7 @@
/* */
/* I/O stream support (body). */
/* */
/* Copyright 2000-2001, 2002 by */
/* Copyright 2000-2001, 2002, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -770,15 +770,15 @@
p = (FT_Byte*)structure + fields->offset;
switch ( fields->size )
{
case 1:
case (8 / FT_CHAR_BIT):
*(FT_Byte*)p = (FT_Byte)value;
break;
case 2:
case (16 / FT_CHAR_BIT):
*(FT_UShort*)p = (FT_UShort)value;
break;
case 4:
case (32 / FT_CHAR_BIT):
*(FT_UInt32*)p = (FT_UInt32)value;
break;
@@ -800,4 +800,4 @@
}
/* END */
/* END */
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType synthesizing code for emboldening and slanting (body). */
/* */
/* Copyright 2000-2001 by */
/* Copyright 2000-2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -82,14 +82,14 @@
/* we need to compute the `previous' and `next' point */
/* for these extrema. */
cur = outline->points + n;
prev = cur - 1;
next = cur + 1;
cur = outline->points + n;
prev = cur - 1;
next = cur + 1;
first = 0;
for ( c = 0; c < outline->n_contours; c++ )
{
last = outline->contours[c];
last = outline->contours[c];
if ( n == first )
prev = outline->points + last;
@@ -279,8 +279,9 @@
first = last + 1;
}
slot->metrics.horiAdvance = ( slot->metrics.horiAdvance + distance*4 ) & -64;
slot->metrics.horiAdvance =
( slot->metrics.horiAdvance + distance*4 ) & ~63;
}
/* END */
/* END */
+1 -1
View File
@@ -128,4 +128,4 @@
ft_object_create( clazz, pathname, FT_OBJECT_P(astream) );
}
+1 -1
View File
@@ -27,4 +27,4 @@
};
FT_APIVAR_DEF( const FT_Memory_Funcs )
ft_memory_funcs_default = &ft_memory_funcs_defaults_rec;
ft_memory_funcs_default = &ft_memory_funcs_defaults_rec;
+1 -1
View File
@@ -300,4 +300,4 @@
}
/* END */
/* END */
+21 -9
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType trigonometric functions (body). */
/* */
/* Copyright 2001 by */
/* Copyright 2001, 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,6 +17,7 @@
#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_TRIGONOMETRY_H
@@ -71,10 +72,10 @@
val = ( val >= 0 ) ? val : -val;
v1 = (FT_UInt32)val >> 16;
v2 = (FT_UInt32)val & 0xFFFF;
v2 = (FT_UInt32)val & 0xFFFFL;
k1 = FT_TRIG_SCALE >> 16; /* constant */
k2 = FT_TRIG_SCALE & 0xFFFF; /* constant */
k2 = FT_TRIG_SCALE & 0xFFFFL; /* constant */
hi = k1 * v1;
lo1 = k1 * v2 + k2 * v1; /* can't overflow */
@@ -271,9 +272,9 @@
/* round theta */
if ( theta >= 0 )
theta = ( theta + 16 ) & -32;
theta = FT_PAD_ROUND( theta, 32 );
else
theta = - (( -theta + 16 ) & -32);
theta = - FT_PAD_ROUND( -theta, 32 );
vec->x = x;
vec->y = theta;
@@ -356,6 +357,14 @@
}
/* these macros return 0 for positive numbers,
and -1 for negative ones */
#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
#define FT_SIGN_INT32( x ) ( (x) >> 31 )
#define FT_SIGN_INT16( x ) ( (x) >> 15 )
/* documentation is in fttrigon.h */
FT_EXPORT_DEF( void )
@@ -376,10 +385,13 @@
v.x = ft_trig_downscale( v.x );
v.y = ft_trig_downscale( v.y );
if ( shift >= 0 )
if ( shift > 0 )
{
vec->x = v.x >> shift;
vec->y = v.y >> shift;
FT_Int32 half = 1L << ( shift - 1 );
vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
}
else
{
@@ -484,4 +496,4 @@
}
/* END */
/* END */
+19 -36
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for PS names support (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,9 +17,9 @@
#include <ft2build.h>
#include FT_INTERNAL_TYPE1_TYPES_H
#include FT_INTERNAL_TYPE42_TYPES_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_SERVICE_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
/* documentation is in t1tables.h */
@@ -28,60 +28,43 @@
FT_Get_PS_Font_Info( FT_Face face,
PS_FontInfoRec* afont_info )
{
PS_FontInfo font_info = NULL;
FT_Error error = FT_Err_Invalid_Argument;
const char* driver_name;
FT_Error error = FT_Err_Invalid_Argument;
if ( face && face->driver && face->driver->root.clazz )
if ( face )
{
driver_name = face->driver->root.clazz->module_name;
if ( ft_strcmp( driver_name, "type1" ) == 0 )
font_info = &((T1_Face)face)->type1.font_info;
else if ( ft_strcmp( driver_name, "t1cid" ) == 0 )
font_info = &((CID_Face)face)->cid.font_info;
else if ( ft_strcmp( driver_name, "type42" ) == 0 )
font_info = &((T42_Face)face)->type1.font_info;
}
if ( font_info != NULL )
{
*afont_info = *font_info;
error = FT_Err_Ok;
FT_Service_PsInfo service = NULL;
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
if ( service && service->ps_get_font_info )
error = service->ps_get_font_info( face, afont_info );
}
return error;
}
/* XXX: Bad hack, but I didn't want to change several drivers here. */
/* documentation is in t1tables.h */
FT_EXPORT_DEF( FT_Int )
FT_Has_PS_Glyph_Names( FT_Face face )
{
FT_Int result = 0;
const char* driver_name;
FT_Int result = 0;
FT_Service_PsInfo service = NULL;
if ( face && face->driver && face->driver->root.clazz )
if ( face )
{
/* Currently, only the type1, type42, and cff drivers provide */
/* reliable glyph names... */
FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO );
/* We could probably hack the TrueType driver to recognize */
/* certain cases where the glyph names are most certainly */
/* correct (e.g. using a 20 or 22 format `post' table), but */
/* this will probably happen later... */
driver_name = face->driver->root.clazz->module_name;
result = ( ft_strcmp( driver_name, "type1" ) == 0 ||
ft_strcmp( driver_name, "type42" ) == 0 ||
ft_strcmp( driver_name, "cff" ) == 0 );
if ( service && service->ps_has_glyph_names )
result = service->ps_has_glyph_names( face );
}
return result;
}
/* END */
/* END */
+1 -1
View File
@@ -327,4 +327,4 @@
}
/* END */
/* END */
+13 -19
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType API for accessing Windows FNT specific info (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,38 +18,32 @@
#include <ft2build.h>
#include FT_WINFONTS_H
#include FT_INTERNAL_FNT_TYPES_H
#include FT_INTERNAL_OBJECTS_H
#include FT_SERVICE_WINFNT_H
FT_EXPORT_DEF( FT_Error )
FT_Get_WinFNT_Header( FT_Face face,
FT_WinFNT_HeaderRec *header )
FT_Get_WinFNT_Header( FT_Face face,
FT_WinFNT_HeaderRec *header )
{
FT_Error error;
FT_Service_WinFnt service;
FT_Error error;
error = FT_Err_Invalid_Argument;
if ( face != NULL && face->driver != NULL )
if ( face != NULL )
{
FT_Module driver = (FT_Module) face->driver;
FT_FACE_LOOKUP_SERVICE( face, service, WINFNT );
if ( driver->clazz && driver->clazz->module_name &&
ft_strcmp( driver->clazz->module_name, "winfonts" ) == 0 )
if ( service != NULL )
{
FNT_Size size = (FNT_Size)face->size;
FNT_Font font = size->font;
if (font)
{
FT_MEM_COPY( header, &font->header, sizeof(*header) );
error = 0;
}
error = service->get_header( face, header );
}
}
return error;
}
/* END */
/* END */
+5 -48
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType utility file for X11 support (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,62 +19,19 @@
#include <ft2build.h>
#include FT_XFREE86_H
#include FT_INTERNAL_OBJECTS_H
/* XXX: This really is a sad hack, but I didn't want to change every */
/* driver just to support this at the moment, since other important */
/* changes are coming anyway. */
typedef struct FT_FontFormatRec_
{
const char* driver_name;
const char* format_name;
} FT_FontFormatRec;
#include FT_SERVICE_XFREE86_NAME_H
FT_EXPORT_DEF( const char* )
FT_Get_X11_Font_Format( FT_Face face )
{
static const FT_FontFormatRec font_formats[] =
{
{ "type1", "Type 1" },
{ "truetype", "TrueType" },
{ "bdf", "BDF" },
{ "pcf", "PCF" },
{ "type42", "Type 42" },
{ "cidtype1", "CID Type 1" },
{ "cff", "CFF" },
{ "pfr", "PFR" },
{ "winfonts", "Windows FNT" }
};
const char* result = NULL;
if ( face && face->driver )
{
FT_Module driver = (FT_Module)face->driver;
if ( driver->clazz && driver->clazz->module_name )
{
FT_Int n;
FT_Int count = sizeof( font_formats ) / sizeof ( font_formats[0] );
result = driver->clazz->module_name;
for ( n = 0; n < count; n++ )
if ( ft_strcmp( result, font_formats[n].driver_name ) == 0 )
{
result = font_formats[n].format_name;
break;
}
}
}
if ( face )
FT_FACE_FIND_SERVICE( face, result, XF86_NAME );
return result;
}
/* END */
/* END */
+31 -29
View File
@@ -3,7 +3,7 @@
#
# Copyright 1996-2000, 2002 by
# Copyright 1996-2000, 2002, 2003, 2004 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,23 +25,24 @@
# BASE_H is defined in freetype.mk to simplify the dependency rules.
BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base
BASE_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(SRC_DIR)/base)
# Base layer sources
#
# ftsystem, ftinit, and ftdebug are handled by freetype.mk
#
BASE_SRC := $(BASE_)ftcalc.c \
$(BASE_)fttrigon.c \
$(BASE_)ftutil.c \
$(BASE_)ftstream.c \
$(BASE_)ftgloadr.c \
$(BASE_)ftoutln.c \
$(BASE_)ftobjs.c \
$(BASE_)ftapi.c \
$(BASE_)ftnames.c \
$(BASE_)ftdbgmem.c
BASE_SRC := $(BASE_DIR)/ftapi.c \
$(BASE_DIR)/ftcalc.c \
$(BASE_DIR)/ftdbgmem.c \
$(BASE_DIR)/ftgloadr.c \
$(BASE_DIR)/ftnames.c \
$(BASE_DIR)/ftobjs.c \
$(BASE_DIR)/ftoutln.c \
$(BASE_DIR)/ftrfork.c \
$(BASE_DIR)/ftstream.c \
$(BASE_DIR)/fttrigon.c \
$(BASE_DIR)/ftutil.c
# Base layer `extensions' sources
#
@@ -49,19 +50,19 @@ BASE_SRC := $(BASE_)ftcalc.c \
# object. It will then be linked to the final executable only if one of its
# symbols is used by the application.
#
BASE_EXT_SRC := $(BASE_)ftglyph.c \
$(BASE_)ftmm.c \
$(BASE_)ftbdf.c \
$(BASE_)fttype1.c \
$(BASE_)ftxf86.c \
$(BASE_)ftpfr.c \
$(BASE_)ftstroker.c \
$(BASE_)ftwinfnt.c \
$(BASE_)ftbbox.c
BASE_EXT_SRC := $(BASE_DIR)/ftbbox.c \
$(BASE_DIR)/ftbdf.c \
$(BASE_DIR)/ftglyph.c \
$(BASE_DIR)/ftmm.c \
$(BASE_DIR)/ftpfr.c \
$(BASE_DIR)/ftstroke.c \
$(BASE_DIR)/fttype1.c \
$(BASE_DIR)/ftwinfnt.c \
$(BASE_DIR)/ftxf86.c
# Default extensions objects
#
BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_DIR)/%.c=$(OBJ_DIR)/%.$O)
# Base layer object(s)
@@ -72,23 +73,24 @@ BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
# BASE_OBJ_S is used during `single' builds (the whole base layer is
# compiled as a single object file using ftbase.c).
#
BASE_OBJ_M := $(BASE_SRC:$(BASE_)%.c=$(OBJ_)%.$O)
BASE_OBJ_S := $(OBJ_)ftbase.$O
BASE_OBJ_M := $(BASE_SRC:$(BASE_DIR)/%.c=$(OBJ_DIR)/%.$O)
BASE_OBJ_S := $(OBJ_DIR)/ftbase.$O
# Base layer root source file for single build
#
BASE_SRC_S := $(BASE_)ftbase.c
BASE_SRC_S := $(BASE_DIR)/ftbase.c
# Base layer - single object build
#
$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H)
$(BASE_COMPILE) $T$@ $(BASE_SRC_S)
$(BASE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(BASE_SRC_S))
# Multiple objects build + extensions
#
$(OBJ_)%.$O: $(BASE_)%.c $(FREETYPE_H)
$(BASE_COMPILE) $T$@ $<
$(OBJ_DIR)/%.$O: $(BASE_DIR)/%.c $(FREETYPE_H)
$(BASE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# EOF
# EOF
+1 -1
View File
@@ -145,4 +145,4 @@ Credits
This driver is based on excellent Mark Leisher's bdf library. If you
find something good in this driver you should probably thank him, not
me.
me.
+1 -1
View File
@@ -31,4 +31,4 @@ THE SOFTWARE.
#include "bdfdrivr.c"
/* END */
/* END */
+5 -5
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
* Copyright 2001, 2002 Francesco Zappa Nardelli
* Copyright 2001, 2002, 2003 Francesco Zappa Nardelli
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -159,8 +159,8 @@ FT_BEGIN_HEADER
typedef struct _hashnode_
{
char* key;
void* data;
const char* key;
void* data;
} _hashnode, *hashnode;
@@ -283,7 +283,7 @@ FT_BEGIN_HEADER
FT_LOCAL( bdf_property_t * )
bdf_get_font_property( bdf_font_t* font,
char* name );
const char* name );
FT_END_HEADER
@@ -292,4 +292,4 @@ FT_END_HEADER
#endif /* __BDF_H__ */
/* END */
/* END */
+260 -113
View File
@@ -2,7 +2,7 @@
FreeType font driver for bdf files
Copyright (C) 2001-2002 by
Copyright (C) 2001, 2002, 2003, 2004 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,6 +31,9 @@ THE SOFTWARE.
#include FT_INTERNAL_OBJECTS_H
#include FT_BDF_H
#include FT_SERVICE_BDF_H
#include FT_SERVICE_XFREE86_NAME_H
#include "bdf.h"
#include "bdfdrivr.h"
@@ -65,7 +68,7 @@ THE SOFTWARE.
cmap->num_encodings = face->bdffont->glyphs_used;
cmap->encodings = face->en_table;
return FT_Err_Ok;
return BDF_Err_Ok;
}
@@ -169,6 +172,116 @@ THE SOFTWARE.
};
static FT_Error
bdf_interpret_style( BDF_Face bdf )
{
FT_Error error = BDF_Err_Ok;
FT_Face face = FT_FACE( bdf );
FT_Memory memory = face->memory;
bdf_font_t* font = bdf->bdffont;
bdf_property_t* prop;
char *istr = NULL, *bstr = NULL;
char *sstr = NULL, *astr = NULL;
int parts = 0, len = 0;
face->style_flags = 0;
prop = bdf_get_font_property( font, (char *)"SLANT" );
if ( prop && prop->format == BDF_ATOM &&
prop->value.atom &&
( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ||
*(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) )
{
face->style_flags |= FT_STYLE_FLAG_ITALIC;
istr = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' )
? (char *)"Oblique"
: (char *)"Italic";
len += ft_strlen( istr );
parts++;
}
prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
if ( prop && prop->format == BDF_ATOM &&
prop->value.atom &&
( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) )
{
face->style_flags |= FT_STYLE_FLAG_BOLD;
bstr = (char *)"Bold";
len += ft_strlen( bstr );
parts++;
}
prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" );
if ( prop && prop->format == BDF_ATOM &&
prop->value.atom && *(prop->value.atom) &&
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
{
sstr = (char *)(prop->value.atom);
len += ft_strlen( sstr );
parts++;
}
prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" );
if ( prop && prop->format == BDF_ATOM &&
prop->value.atom && *(prop->value.atom) &&
!( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) )
{
astr = (char *)(prop->value.atom);
len += ft_strlen( astr );
parts++;
}
if ( !parts || !len )
face->style_name = (char *)"Regular";
else
{
char *style, *s;
unsigned int i;
if ( FT_ALLOC( style, len + parts ) )
return error;
s = style;
if ( astr )
{
ft_strcpy( s, astr );
for ( i = 0; i < ft_strlen( astr ); i++, s++ )
if ( *s == ' ' )
*s = '-'; /* replace spaces with dashes */
*(s++) = ' ';
}
if ( bstr )
{
ft_strcpy( s, bstr );
s += ft_strlen( bstr );
*(s++) = ' ';
}
if ( istr )
{
ft_strcpy( s, istr );
s += ft_strlen( istr );
*(s++) = ' ';
}
if ( sstr )
{
ft_strcpy( s, sstr );
for ( i = 0; i < ft_strlen( sstr ); i++, s++ )
if ( *s == ' ' )
*s = '-'; /* replace spaces with dashes */
*(s++) = ' ';
}
*(--s) = '\0'; /* overwrite last ' ', terminate the string */
face->style_name = style; /* allocated string */
}
return error;
}
FT_CALLBACK_DEF( FT_Error )
@@ -250,35 +363,18 @@ THE SOFTWARE.
FT_FACE_FLAG_HORIZONTAL |
FT_FACE_FLAG_FAST_GLYPHS;
prop = bdf_get_font_property( font, (char *)"SPACING" );
if ( prop != NULL )
if ( prop->format == BDF_ATOM )
if ( prop->value.atom != NULL )
if ( ( *(prop->value.atom) == 'M' ) ||
( *(prop->value.atom) == 'C' ) )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
prop = bdf_get_font_property( font, "SPACING" );
if ( prop && prop->format == BDF_ATOM &&
prop->value.atom &&
( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' ||
*(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) )
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
/* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */
/* FZ XXX: I need a font to implement this */
root->style_flags = 0;
prop = bdf_get_font_property( font, (char *)"SLANT" );
if ( prop != NULL )
if ( prop->format == BDF_ATOM )
if ( prop->value.atom != NULL )
if ( ( *(prop->value.atom) == 'O' ) ||
( *(prop->value.atom) == 'I' ) )
root->style_flags |= FT_STYLE_FLAG_ITALIC;
prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" );
if ( prop != NULL )
if ( prop->format == BDF_ATOM )
if ( prop->value.atom != NULL )
if ( *(prop->value.atom) == 'B' )
root->style_flags |= FT_STYLE_FLAG_BOLD;
prop = bdf_get_font_property( font, (char *)"FAMILY_NAME" );
if ( ( prop != NULL ) && ( prop->value.atom != NULL ) )
prop = bdf_get_font_property( font, "FAMILY_NAME" );
if ( prop && prop->value.atom )
{
int l = ft_strlen( prop->value.atom ) + 1;
@@ -290,16 +386,8 @@ THE SOFTWARE.
else
root->family_name = 0;
root->style_name = (char *)"Regular";
if ( root->style_flags & FT_STYLE_FLAG_BOLD )
{
if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
root->style_name = (char *)"Bold Italic";
else
root->style_name = (char *)"Bold";
}
else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
root->style_name = (char *)"Italic";
if ( ( error = bdf_interpret_style( face ) ) != 0 )
goto Exit;
root->num_glyphs = font->glyphs_size; /* unencoded included */
@@ -307,45 +395,50 @@ THE SOFTWARE.
if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
goto Exit;
prop = bdf_get_font_property( font, (char *)"AVERAGE_WIDTH" );
if ( ( prop != NULL ) && ( prop->value.int32 >= 10 ) )
root->available_sizes->width = (short)( prop->value.int32 / 10 );
prop = bdf_get_font_property( font, (char *)"PIXEL_SIZE" );
if ( prop != NULL )
root->available_sizes->height = (short) prop->value.int32;
else
{
prop = bdf_get_font_property( font, (char *)"POINT_SIZE" );
if ( prop != NULL )
{
bdf_property_t *yres;
FT_Bitmap_Size* bsize = root->available_sizes;
FT_Short resolution_x = 0, resolution_y = 0;
yres = bdf_get_font_property( font, (char *)"RESOLUTION_Y" );
if ( yres != NULL )
{
FT_TRACE4(( "POINT_SIZE: %d RESOLUTION_Y: %d\n",
prop->value.int32, yres->value.int32 ));
root->available_sizes->height =
(FT_Short)( prop->value.int32 * yres->value.int32 / 720 );
}
}
}
FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
if ( root->available_sizes->width == 0 )
{
if ( root->available_sizes->height == 0 )
{
/* some fonts have broken SIZE declaration (jiskan24.bdf) */
FT_ERROR(( "BDF_Face_Init: reading size\n" ));
root->available_sizes->width = (FT_Short)font->point_size;
}
bsize->height = font->font_ascent + font->font_descent;
prop = bdf_get_font_property( font, "AVERAGE_WIDTH" );
if ( prop )
bsize->width = (FT_Short)( ( prop->value.int32 + 5 ) / 10 );
else
root->available_sizes->width = root->available_sizes->height;
bsize->width = bsize->height * 2/3;
prop = bdf_get_font_property( font, "POINT_SIZE" );
if ( prop )
/* convert from 722.7 decipoints to 72 points per inch */
bsize->size =
(FT_Pos)( ( prop->value.int32 * 64 * 7200 + 36135L ) / 72270L );
prop = bdf_get_font_property( font, "PIXEL_SIZE" );
if ( prop )
bsize->y_ppem = (FT_Short)prop->value.int32 << 6;
prop = bdf_get_font_property( font, "RESOLUTION_X" );
if ( prop )
resolution_x = (FT_Short)prop->value.int32;
prop = bdf_get_font_property( font, "RESOLUTION_Y" );
if ( prop )
resolution_y = (FT_Short)prop->value.int32;
if ( bsize->y_ppem == 0 )
{
bsize->y_ppem = bsize->size;
if ( resolution_y )
bsize->y_ppem = bsize->y_ppem * resolution_y / 72;
}
if ( resolution_x && resolution_y )
bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y;
else
bsize->x_ppem = bsize->y_ppem;
}
if ( root->available_sizes->height == 0 )
root->available_sizes->height = root->available_sizes->width;
/* encoding table */
{
@@ -371,28 +464,42 @@ THE SOFTWARE.
charset_registry =
bdf_get_font_property( font, (char *)"CHARSET_REGISTRY" );
bdf_get_font_property( font, "CHARSET_REGISTRY" );
charset_encoding =
bdf_get_font_property( font, (char *)"CHARSET_ENCODING" );
if ( ( charset_registry != NULL ) && ( charset_encoding != NULL ) )
bdf_get_font_property( font, "CHARSET_ENCODING" );
if ( charset_registry && charset_encoding )
{
if ( ( charset_registry->format == BDF_ATOM ) &&
( charset_encoding->format == BDF_ATOM ) &&
( charset_registry->value.atom != NULL ) &&
( charset_encoding->value.atom != NULL ) )
if ( charset_registry->format == BDF_ATOM &&
charset_encoding->format == BDF_ATOM &&
charset_registry->value.atom &&
charset_encoding->value.atom )
{
const char* s;
if ( FT_NEW_ARRAY( face->charset_encoding,
strlen( charset_encoding->value.atom ) + 1 ) )
ft_strlen( charset_encoding->value.atom ) + 1 ) )
goto Exit;
if ( FT_NEW_ARRAY( face->charset_registry,
strlen( charset_registry->value.atom ) + 1 ) )
ft_strlen( charset_registry->value.atom ) + 1 ) )
goto Exit;
ft_strcpy( face->charset_registry, charset_registry->value.atom );
ft_strcpy( face->charset_encoding, charset_encoding->value.atom );
if ( !ft_strcmp( face->charset_registry, "ISO10646" ) ||
( !ft_strcmp( face->charset_registry, "ISO8859" ) &&
!ft_strcmp( face->charset_encoding, "1" ) ) )
/* Uh, oh, compare first letters manually to avoid dependency
on locales. */
s = face->charset_registry;
if ( ( s[0] == 'i' || s[0] == 'I' ) &&
( s[1] == 's' || s[1] == 'S' ) &&
( s[2] == 'o' || s[2] == 'O' ) )
{
s += 3;
if ( !ft_strcmp( s, "10646" ) ||
( !ft_strcmp( s, "8859" ) &&
!ft_strcmp( face->charset_encoding, "1" ) ) )
unicode_charmap = 1;
}
{
FT_CharMapRec charmap;
@@ -460,13 +567,15 @@ THE SOFTWARE.
FT_TRACE4(( "rec %d - pres %d\n",
size->metrics.y_ppem, root->available_sizes->height ));
size->metrics.y_ppem, root->available_sizes->y_ppem ));
if ( size->metrics.y_ppem == root->available_sizes->height )
if ( size->metrics.y_ppem == root->available_sizes->y_ppem >> 6 )
{
size->metrics.ascender = face->bdffont->bbx.ascent << 6;
size->metrics.descender = face->bdffont->bbx.descent * ( -64 );
size->metrics.height = face->bdffont->bbx.height << 6;
size->metrics.ascender = face->bdffont->font_ascent << 6;
size->metrics.descender = -face->bdffont->font_descent << 6;
size->metrics.height = ( face->bdffont->font_ascent +
face->bdffont->font_descent ) << 6;
size->metrics.max_advance = face->bdffont->bbx.width << 6;
return BDF_Err_Ok;
}
@@ -611,14 +720,13 @@ THE SOFTWARE.
}
}
slot->bitmap_left = 0;
slot->bitmap_left = glyph.bbx.x_offset;
slot->bitmap_top = glyph.bbx.ascent;
/* FZ XXX: TODO: vertical metrics */
slot->metrics.horiAdvance = glyph.dwidth << 6;
slot->metrics.horiBearingX = glyph.bbx.x_offset << 6;
slot->metrics.horiBearingY = ( glyph.bbx.y_offset +
glyph.bbx.height ) << 6;
slot->metrics.horiBearingY = glyph.bbx.ascent << 6;
slot->metrics.width = bitmap->width << 6;
slot->metrics.height = bitmap->rows << 6;
@@ -630,6 +738,12 @@ THE SOFTWARE.
}
/*
*
* BDF SERVICE
*
*/
static FT_Error
bdf_get_bdf_property( BDF_Face face,
const char* prop_name,
@@ -637,37 +751,71 @@ THE SOFTWARE.
{
bdf_property_t* prop;
FT_ASSERT( face && face->bdffont );
prop = bdf_get_font_property( face->bdffont, (char*)prop_name );
if ( prop != NULL )
prop = bdf_get_font_property( face->bdffont, prop_name );
if ( prop )
{
switch ( prop->format )
{
case BDF_ATOM:
aproperty->type = BDF_PROPERTY_TYPE_ATOM;
aproperty->u.atom = prop->value.atom;
break;
case BDF_ATOM:
aproperty->type = BDF_PROPERTY_TYPE_ATOM;
aproperty->u.atom = prop->value.atom;
break;
case BDF_INTEGER:
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
aproperty->u.integer = prop->value.int32;
break;
case BDF_INTEGER:
aproperty->type = BDF_PROPERTY_TYPE_INTEGER;
aproperty->u.integer = prop->value.int32;
break;
case BDF_CARDINAL:
aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
aproperty->u.cardinal = prop->value.card32;
break;
case BDF_CARDINAL:
aproperty->type = BDF_PROPERTY_TYPE_CARDINAL;
aproperty->u.cardinal = prop->value.card32;
break;
default:
goto Fail;
default:
goto Fail;
}
return 0;
}
Fail:
return FT_Err_Invalid_Argument;
return BDF_Err_Invalid_Argument;
}
static FT_Error
bdf_get_charset_id( BDF_Face face,
const char* *acharset_encoding,
const char* *acharset_registry )
{
*acharset_encoding = face->charset_encoding;
*acharset_registry = face->charset_registry;
return 0;
}
static const FT_Service_BDFRec bdf_service_bdf =
{
(FT_BDF_GetCharsetIdFunc)bdf_get_charset_id,
(FT_BDF_GetPropertyFunc) bdf_get_bdf_property
};
/*
*
* SERVICES LIST
*
*/
static const FT_ServiceDescRec bdf_services[] =
{
{ FT_SERVICE_ID_BDF, &bdf_service_bdf },
{ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF },
{ NULL, NULL }
};
static FT_Module_Interface
bdf_driver_requester( FT_Module module,
@@ -675,18 +823,17 @@ THE SOFTWARE.
{
FT_UNUSED( module );
if ( name && ft_strcmp( name, "get_bdf_property" ) == 0 )
return (FT_Module_Interface) bdf_get_bdf_property;
return NULL;
return ft_service_list_lookup( bdf_services, name );
}
FT_CALLBACK_TABLE_DEF
const FT_Driver_ClassRec bdf_driver_class =
{
{
ft_module_font_driver,
FT_MODULE_FONT_DRIVER |
FT_MODULE_DRIVER_NO_OUTLINES,
sizeof ( FT_DriverRec ),
"bdf",
@@ -722,4 +869,4 @@ THE SOFTWARE.
};
/* END */
/* END */
+4 -4
View File
@@ -2,7 +2,7 @@
FreeType font driver for bdf fonts
Copyright (C) 2001, 2002 by
Copyright (C) 2001, 2002, 2003 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -39,8 +39,8 @@ FT_BEGIN_HEADER
typedef struct BDF_encoding_el_
{
FT_ULong enc;
FT_Short glyph;
FT_ULong enc;
FT_UShort glyph;
} BDF_encoding_el;
@@ -71,4 +71,4 @@ FT_END_HEADER
#endif /* __BDFDRIVR_H__ */
/* END */
/* END */
+1 -1
View File
@@ -41,4 +41,4 @@
#endif /* __BDFERROR_H__ */
/* END */
/* END */
+23 -24
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2000 Computing Research Labs, New Mexico State University
* Copyright 2001, 2002 Francesco Zappa Nardelli
* Copyright 2001, 2002, 2003, 2004 Francesco Zappa Nardelli
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -163,7 +163,7 @@
{ (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } },
};
static unsigned long
static const unsigned long
_num_bdf_properties = sizeof ( _bdf_properties ) /
sizeof ( _bdf_properties[0] );
@@ -183,10 +183,10 @@
(*hash_free_func)( hashnode node );
static hashnode*
hash_bucket( char* key,
hashtable* ht )
hash_bucket( const char* key,
hashtable* ht )
{
char* kp = key;
const char* kp = key;
unsigned long res = 0;
hashnode* bp = ht->table, *ndp;
@@ -317,7 +317,7 @@
static hashnode
hash_lookup( char* key,
hash_lookup( const char* key,
hashtable* ht )
{
hashnode *np = hash_bucket( key, ht );
@@ -391,7 +391,7 @@
/* An empty string for empty fields. */
static char empty[1] = { 0 }; /* XXX eliminate this */
static const char empty[1] = { 0 }; /* XXX eliminate this */
/* Assume the line is NULL-terminated and that the `list' parameter */
@@ -468,7 +468,7 @@
}
/* Assign the field appropriately. */
list->field[list->used++] = ( ep > sp ) ? sp : empty;
list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty;
sp = ep;
@@ -511,7 +511,7 @@
}
if ( final_empty )
list->field[list->used++] = empty;
list->field[list->used++] = (char*)empty;
if ( list->used == list->size )
{
@@ -641,7 +641,7 @@
{
_bdf_line_func_t cb;
unsigned long lineno;
int n, res, done, refill, bytes, hold;
int n, done, refill, bytes, hold;
char *ls, *le, *pp, *pe, *hp;
char *buf = 0;
FT_Memory memory = stream->memory;
@@ -661,7 +661,7 @@
lineno = 1;
buf[0] = 0;
res = done = 0;
done = 0;
pp = ls = le = buf;
bytes = 65536L;
@@ -696,7 +696,7 @@
le -= n;
n = pe - pp;
FT_MEM_COPY( buf, pp, n );
FT_MEM_MOVE( buf, pp, n );
pp = buf + n;
bytes = 65536L - n;
@@ -1443,7 +1443,6 @@
unsigned char* bp;
unsigned long i, slen, nibbles;
_bdf_line_func_t* next;
_bdf_parse_t* p;
bdf_glyph_t* glyph;
bdf_font_t* font;
@@ -1451,11 +1450,11 @@
FT_Memory memory;
FT_Error error = BDF_Err_Ok;
FT_UNUSED( call_data );
FT_UNUSED( lineno ); /* only used in debug mode */
next = (_bdf_line_func_t *)call_data;
p = (_bdf_parse_t *) client_data;
p = (_bdf_parse_t *)client_data;
font = p->font;
memory = font->memory;
@@ -1771,14 +1770,14 @@
/* Determine the overall font bounding box as the characters are */
/* loaded so corrections can be done later if indicated. */
p->maxas = (short)MAX( glyph->bbx.ascent, p->maxas );
p->maxds = (short)MAX( glyph->bbx.descent, p->maxds );
p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas );
p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds );
p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset );
p->maxrb = (short)MAX( p->rbearing, p->maxrb );
p->minlb = (short)MIN( glyph->bbx.x_offset, p->minlb );
p->maxlb = (short)MAX( glyph->bbx.x_offset, p->maxlb );
p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb );
p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb );
p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb );
if ( !( p->flags & _BDF_DWIDTH ) )
{
@@ -1883,7 +1882,7 @@
/* */
/* This is *always* done regardless of the options, because X11 */
/* requires these two fields to compile fonts. */
if ( bdf_get_font_property( p->font, (char *)"FONT_ASCENT" ) == 0 )
if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 )
{
p->font->font_ascent = p->font->bbx.ascent;
ft_sprintf( nbuf, "%hd", p->font->bbx.ascent );
@@ -1895,7 +1894,7 @@
p->font->modified = 1;
}
if ( bdf_get_font_property( p->font, (char *)"FONT_DESCENT" ) == 0 )
if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 )
{
p->font->font_descent = p->font->bbx.descent;
ft_sprintf( nbuf, "%hd", p->font->bbx.descent );
@@ -2419,7 +2418,7 @@
FT_LOCAL_DEF( bdf_property_t * )
bdf_get_font_property( bdf_font_t* font,
char* name )
const char* name )
{
hashnode hn;
@@ -2433,4 +2432,4 @@
}
/* END */
/* END */
+1 -1
View File
@@ -20,4 +20,4 @@ OBJS=bdf.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
# EOF
# EOF
+1 -1
View File
@@ -28,4 +28,4 @@ make_module_list: add_bdf_driver
add_bdf_driver:
$(OPEN_DRIVER)bdf_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)bdf $(ECHO_DRIVER_DESC)bdf bitmap fonts$(ECHO_DRIVER_DONE)
+15 -14
View File
@@ -3,7 +3,7 @@
#
# Copyright (C) 2001, 2002 by
# Copyright (C) 2001, 2002, 2003 by
# Francesco Zappa Nardelli
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,46 +29,46 @@
# bdf driver directory
#
BDF_DIR := $(SRC_)bdf
BDF_DIR_ := $(BDF_DIR)$(SEP)
BDF_DIR := $(SRC_DIR)/bdf
BDF_COMPILE := $(FT_COMPILE) $I$(BDF_DIR)
BDF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(BDF_DIR))
# bdf driver sources (i.e., C files)
#
BDF_DRV_SRC := $(BDF_DIR_)bdflib.c $(BDF_DIR_)bdfdrivr.c
BDF_DRV_SRC := $(BDF_DIR)/bdflib.c \
$(BDF_DIR)/bdfdrivr.c
# bdf driver headers
#
BDF_DRV_H := $(BDF_DIR_)bdf.h \
$(BDF_DIR_)bdfdrivr.h
BDF_DRV_H := $(BDF_DIR)/bdf.h \
$(BDF_DIR)/bdfdrivr.h
# bdf driver object(s)
#
# BDF_DRV_OBJ_M is used during `multi' builds
# BDF_DRV_OBJ_S is used during `single' builds
#
BDF_DRV_OBJ_M := $(BDF_DRV_SRC:$(BDF_DIR_)%.c=$(OBJ_)%.$O)
BDF_DRV_OBJ_S := $(OBJ_)bdf.$O
BDF_DRV_OBJ_M := $(BDF_DRV_SRC:$(BDF_DIR)/%.c=$(OBJ_DIR)/%.$O)
BDF_DRV_OBJ_S := $(OBJ_DIR)/bdf.$O
# bdf driver source file for single build
#
BDF_DRV_SRC_S := $(BDF_DIR_)bdf.c
BDF_DRV_SRC_S := $(BDF_DIR)/bdf.c
# bdf driver - single object
#
$(BDF_DRV_OBJ_S): $(BDF_DRV_SRC_S) $(BDF_DRV_SRC) $(FREETYPE_H) $(BDF_DRV_H)
$(BDF_COMPILE) $T$@ $(BDF_DRV_SRC_S)
$(BDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(BDF_DRV_SRC_S))
# bdf driver - multiple objects
#
$(OBJ_)%.$O: $(BDF_DIR_)%.c $(FREETYPE_H) $(BDF_DRV_H)
$(BDF_COMPILE) $T$@ $<
$(OBJ_DIR)/%.$O: $(BDF_DIR)/%.c $(FREETYPE_H) $(BDF_DRV_H)
$(BDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
@@ -76,4 +76,5 @@ $(OBJ_)%.$O: $(BDF_DIR_)%.c $(FREETYPE_H) $(BDF_DRV_H)
DRV_OBJS_S += $(BDF_DRV_OBJ_S)
DRV_OBJS_M += $(BDF_DRV_OBJ_M)
# EOF
# EOF
+3 -4
View File
@@ -3,7 +3,7 @@
#
# Copyright 2001, 2002 by
# Copyright 2001, 2002, 2003, 2004 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -20,7 +20,6 @@ OBJS=ftcache.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
ftcache.obj : ftcache.c ftlru.c ftcmanag.c ftccache.c ftcglyph.c ftcimage.c \
ftcsbits.c ftccmap.c
ftcache.obj : ftcache.c
# EOF
# EOF
+5 -5
View File
@@ -4,7 +4,7 @@
/* */
/* The FreeType Caching sub-system (body only). */
/* */
/* Copyright 2000-2001 by */
/* Copyright 2000-2001, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,13 +19,13 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "ftlru.c"
#include "ftcmru.c"
#include "ftcmanag.c"
#include "ftccache.c"
#include "ftccmap.c"
#include "ftcglyph.c"
#include "ftcimage.c"
#include "ftcsbits.c"
#include "ftccmap.c"
#include "ftcbasic.c"
/* END */
/* END */
+425
View File
@@ -0,0 +1,425 @@
/***************************************************************************/
/* */
/* ftcbasic.c */
/* */
/* The FreeType basic cache interface (body). */
/* */
/* Copyright 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_CACHE_INTERNAL_IMAGE_H
#include FT_CACHE_INTERNAL_SBITS_H
#include FT_INTERNAL_MEMORY_H
#include "ftccback.h"
#include "ftcerror.h"
/*
* Basic Families
*
*/
typedef struct FTC_BasicAttrRec_
{
FTC_ScalerRec scaler;
FT_UInt load_flags;
} FTC_BasicAttrRec, *FTC_BasicAttrs;
#define FTC_BASIC_ATTR_COMPARE( a, b ) \
( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
(a)->load_flags == (b)->load_flags )
#define FTC_BASIC_ATTR_HASH( a ) \
( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
typedef struct FTC_BasicQueryRec_
{
FTC_GQueryRec gquery;
FTC_BasicAttrRec attrs;
} FTC_BasicQueryRec, *FTC_BasicQuery;
typedef struct FTC_BasicFamilyRec_
{
FTC_FamilyRec family;
FTC_BasicAttrRec attrs;
} FTC_BasicFamilyRec, *FTC_BasicFamily;
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_family_compare( FTC_BasicFamily family,
FTC_BasicQuery query )
{
return FT_BOOL( FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ) );
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_init( FTC_BasicFamily family,
FTC_BasicQuery query,
FTC_Cache cache )
{
FTC_Family_Init( FTC_FAMILY( family ), cache );
family->attrs = query->attrs;
return 0;
}
FT_CALLBACK_DEF( FT_UInt )
ftc_basic_family_get_count( FTC_BasicFamily family,
FTC_Manager manager )
{
FT_Error error;
FT_Face face;
FT_UInt result = 0;
error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
&face );
if ( !error )
result = face->num_glyphs;
return result;
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_load_bitmap( FTC_BasicFamily family,
FT_UInt gindex,
FTC_Manager manager,
FT_Face *aface )
{
FT_Error error;
FT_Size size;
error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
if ( !error )
{
FT_Face face = size->face;
error = FT_Load_Glyph( face, gindex,
family->attrs.load_flags | FT_LOAD_RENDER );
if ( !error )
*aface = face;
}
return error;
}
FT_CALLBACK_DEF( FT_Error )
ftc_basic_family_load_glyph( FTC_BasicFamily family,
FT_UInt gindex,
FTC_Cache cache,
FT_Glyph *aglyph )
{
FT_Error error;
FTC_Scaler scaler = &family->attrs.scaler;
FT_Face face;
FT_Size size;
/* we will now load the glyph image */
error = FTC_Manager_LookupSize( cache->manager,
scaler,
&size );
if ( !error )
{
face = size->face;
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* ok, copy it */
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
{
*aglyph = glyph;
goto Exit;
}
}
else
error = FTC_Err_Invalid_Argument;
}
}
Exit:
return error;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_gnode_compare_faceid( FTC_GNode gnode,
FTC_FaceID face_id,
FTC_Cache cache )
{
FTC_BasicFamily family = (FTC_BasicFamily)gnode->family;
FT_Bool result;
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
if ( result )
{
/* we must call this function to avoid this node from appearing
* in later lookups with the same face_id!
*/
FTC_GNode_UnselectFamily( gnode, cache );
}
return result;
}
/*
*
* basic image cache
*
*/
FT_CALLBACK_TABLE_DEF
const FTC_IFamilyClassRec ftc_basic_image_family_class =
{
{
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc)ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
(FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_IFamily_LoadGlyphFunc)ftc_basic_family_load_glyph
};
FT_CALLBACK_TABLE_DEF
const FTC_GCacheClassRec ftc_basic_image_cache_class =
{
{
(FTC_Node_NewFunc) ftc_inode_new,
(FTC_Node_WeightFunc) ftc_inode_weight,
(FTC_Node_CompareFunc)ftc_gnode_compare,
(FTC_Node_CompareFunc)ftc_basic_gnode_compare_faceid,
(FTC_Node_FreeFunc) ftc_inode_free,
sizeof( FTC_GCacheRec ),
(FTC_Cache_InitFunc) ftc_gcache_init,
(FTC_Cache_DoneFunc) ftc_gcache_done
},
(FTC_MruListClass)&ftc_basic_image_family_class
};
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_New( FTC_Manager manager,
FTC_ImageCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
(FTC_GCache*)acache );
}
/* documentation is in ftcimage.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_Lookup( FTC_ImageCache cache,
FTC_ImageType type,
FT_UInt gindex,
FT_Glyph *aglyph,
FTC_Node *anode )
{
FTC_BasicQueryRec query;
FTC_INode node;
FT_Error error;
FT_UInt32 hash;
/* some argument checks are delayed to FTC_Cache_Lookup */
if ( !aglyph )
{
error = FTC_Err_Invalid_Argument;
goto Exit;
}
*aglyph = NULL;
if ( anode )
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.scaler.pixel = 1;
query.attrs.load_flags = type->flags;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
#if 1 /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
FTC_GNode_Compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash, gindex,
FTC_GQUERY( &query ),
(FTC_Node*) &node );
#endif
if ( !error )
{
*aglyph = FTC_INODE( node )->glyph;
if ( anode )
{
*anode = FTC_NODE( node );
FTC_NODE( node )->ref_count++;
}
}
Exit:
return error;
}
/*
*
* basic small bitmap cache
*
*/
FT_CALLBACK_TABLE_DEF
const FTC_SFamilyClassRec ftc_basic_sbit_family_class =
{
{
sizeof( FTC_BasicFamilyRec ),
(FTC_MruNode_CompareFunc)ftc_basic_family_compare,
(FTC_MruNode_InitFunc) ftc_basic_family_init,
(FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) NULL
},
(FTC_SFamily_GetCountFunc) ftc_basic_family_get_count,
(FTC_SFamily_LoadGlyphFunc)ftc_basic_family_load_bitmap
};
FT_CALLBACK_TABLE_DEF
const FTC_GCacheClassRec ftc_basic_sbit_cache_class =
{
{
(FTC_Node_NewFunc) ftc_snode_new,
(FTC_Node_WeightFunc) ftc_snode_weight,
(FTC_Node_CompareFunc)ftc_snode_compare,
(FTC_Node_CompareFunc)ftc_basic_gnode_compare_faceid,
(FTC_Node_FreeFunc) ftc_snode_free,
sizeof( FTC_GCacheRec ),
(FTC_Cache_InitFunc) ftc_gcache_init,
(FTC_Cache_DoneFunc) ftc_gcache_done
},
(FTC_MruListClass)&ftc_basic_sbit_family_class
};
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_New( FTC_Manager manager,
FTC_SBitCache *acache )
{
return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
(FTC_GCache*)acache );
}
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_Lookup( FTC_SBitCache cache,
FTC_ImageType type,
FT_UInt gindex,
FTC_SBit *ansbit,
FTC_Node *anode )
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_SNode node;
FT_UInt32 hash;
if ( anode )
*anode = NULL;
/* other argument checks delayed to FTC_Cache_Lookup */
if ( !ansbit )
return FTC_Err_Invalid_Argument;
*ansbit = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.scaler.pixel = 1;
query.attrs.load_flags = type->flags;
query.attrs.scaler.x_res = 0; /* make compilers happy */
query.attrs.scaler.y_res = 0;
/* beware, the hash must be the same for all glyph ranges! */
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
gindex / FTC_SBIT_ITEMS_PER_NODE;
#if 1 /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
FTC_SNode_Compare,
hash, gindex,
&query,
node,
error );
#else
error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
hash,
gindex,
FTC_GQUERY( &query ),
(FTC_Node*)&node );
#endif
if ( error )
goto Exit;
*ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex );
if ( anode )
{
*anode = FTC_NODE( node );
FTC_NODE( node )->ref_count++;
}
Exit:
return error;
}
/* END */
+365 -568
View File
File diff suppressed because it is too large Load Diff
-157
View File
@@ -1,157 +0,0 @@
/***************************************************************************/
/* */
/* ftccache.i */
/* */
/* FreeType template for generic cache. */
/* */
/* Copyright 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef GEN_CACHE_FAMILY_COMPARE
#error "GEN_CACHE_FAMILY_COMPARE not defined in template instantiation"
#endif
#ifndef GEN_CACHE_NODE_COMPARE
#error "GEN_CACHE_NODE_COMPARE not defined in template instantiation"
#endif
static FT_Error
GEN_CACHE_LOOKUP( FTC_Cache cache,
FTC_Query query,
FTC_Node *anode )
{
FT_LruNode lru;
FTC_Family family;
FT_UFast hash;
query->hash = 0;
query->family = NULL;
/* XXX: we break encapsulation for the sake of speed! */
{
/* first of all, find the relevant family */
FT_LruList list = cache->families;
FT_LruNode fam, *pfam;
pfam = &list->nodes;
for (;;)
{
fam = *pfam;
if ( fam == NULL )
goto Normal;
if ( GEN_CACHE_FAMILY_COMPARE( fam, query, list->data ) )
break;
pfam = &fam->next;
}
FT_ASSERT( fam != NULL );
/* move to top of list when needed */
if ( fam != list->nodes )
{
*pfam = fam->next;
fam->next = list->nodes;
list->nodes = fam;
}
lru = fam;
}
{
FTC_Node node, *pnode, *bucket;
family = (FTC_Family)lru;
hash = query->hash;
{
FT_UInt idx;
idx = hash & cache->mask;
if ( idx < cache->p )
idx = hash & ( cache->mask * 2 + 1 );
bucket = cache->buckets + idx;
}
pnode = bucket;
for ( ;; )
{
node = *pnode;
if ( node == NULL )
goto Normal;
if ( node->hash == hash &&
(FT_UInt)node->fam_index == family->fam_index &&
GEN_CACHE_NODE_COMPARE( node, query, cache ) )
{
/* we place the following out of the loop to make it */
/* as small as possible... */
goto Found;
}
pnode = &node->link;
}
Normal:
return ftc_cache_lookup( cache, query, anode );
Found:
/* move to head of bucket list */
if ( pnode != bucket )
{
*pnode = node->link;
node->link = *bucket;
*bucket = node;
}
/* move to head of MRU list */
if ( node != cache->manager->nodes_list )
{
/* XXX: again, this is an inlined version of ftc_node_mru_up */
FTC_Manager manager = cache->manager;
FTC_Node first = manager->nodes_list;
FTC_Node prev = node->mru_prev;
FTC_Node next = node->mru_next;
FTC_Node last;
prev->mru_next = next;
next->mru_prev = prev;
last = first->mru_prev;
node->mru_next = first;
node->mru_prev = last;
first->mru_prev = node;
last->mru_next = node;
manager->nodes_list = node;
}
*anode = node;
return 0;
}
}
#undef GEN_CACHE_NODE_COMPARE
#undef GEN_CACHE_FAMILY_COMPARE
#undef GEN_CACHE_LOOKUP
/* END */
+82
View File
@@ -0,0 +1,82 @@
/***************************************************************************/
/* */
/* ftccback.h */
/* */
/* Callback functions of the caching sub-system (specification only). */
/* */
/* Copyright 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef __FTCCBACK_H__
#define __FTCCBACK_H__
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_MRU_H
#include FT_CACHE_INTERNAL_IMAGE_H
#include FT_CACHE_INTERNAL_MANAGER_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_CACHE_INTERNAL_SBITS_H
FT_LOCAL( void )
ftc_inode_free( FTC_INode inode,
FTC_Cache cache );
FT_LOCAL( FT_Error )
ftc_inode_new( FTC_INode *pinode,
FTC_GQuery gquery,
FTC_Cache cache );
FT_LOCAL( FT_ULong )
ftc_inode_weight( FTC_INode inode );
FT_LOCAL( void )
ftc_snode_free( FTC_SNode snode,
FTC_Cache cache );
FT_LOCAL( FT_Error )
ftc_snode_new( FTC_SNode *psnode,
FTC_GQuery gquery,
FTC_Cache cache );
FT_LOCAL( FT_ULong )
ftc_snode_weight( FTC_SNode snode );
FT_LOCAL( FT_Bool )
ftc_snode_compare( FTC_SNode snode,
FTC_GQuery gquery,
FTC_Cache cache );
FT_LOCAL( FT_Bool )
ftc_gnode_compare( FTC_GNode gnode,
FTC_GQuery gquery );
FT_LOCAL( FT_Error )
ftc_gcache_init( FTC_GCache cache );
FT_LOCAL( void )
ftc_gcache_done( FTC_GCache cache );
FT_LOCAL( FT_Error )
ftc_cache_init( FTC_Cache cache );
FT_LOCAL( void )
ftc_cache_done( FTC_Cache cache );
#endif /* __FTCCBACK_H__ */
/* END */
+119 -291
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType CharMap cache (body) */
/* */
/* Copyright 2000-2001, 2002 by */
/* Copyright 2000-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,17 +19,18 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_CACHE_H
#include FT_CACHE_CHARMAP_H
#include FT_CACHE_MANAGER_H
#include FT_CACHE_INTERNAL_MANAGER_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_DEBUG_H
#include FT_TRUETYPE_IDS_H
#include "ftccback.h"
#include "ftcerror.h"
#undef FT_COMPONENT
#define FT_COMPONENT trace_cache
/*************************************************************************/
/* */
/* Each FTC_CMapNode contains a simple array to map a range of character */
@@ -47,56 +48,44 @@
/* number of glyph indices / character code per node */
#define FTC_CMAP_INDICES_MAX 128
/* compute a query/node hash */
#define FTC_CMAP_HASH( faceid, index, charcode ) \
( FTC_FACE_ID_HASH( faceid ) + 211 * ( index ) + \
( (char_code) / FTC_CMAP_INDICES_MAX ) )
/* the charmap query */
typedef struct FTC_CMapQueryRec_
{
FTC_FaceID face_id;
FT_UInt cmap_index;
FT_UInt32 char_code;
} FTC_CMapQueryRec, *FTC_CMapQuery;
#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x))
#define FTC_CMAP_QUERY_HASH( x ) \
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
/* the cmap cache node */
typedef struct FTC_CMapNodeRec_
{
FTC_NodeRec node;
FTC_FaceID face_id;
FT_UInt cmap_index;
FT_UInt32 first; /* first character in node */
FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */
} FTC_CMapNodeRec, *FTC_CMapNode;
#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
/* compute node hash value from cmap family and "requested" glyph index */
#define FTC_CMAP_HASH( cfam, cquery ) \
( (cfam)->hash + ( (cquery)->char_code / FTC_CMAP_INDICES_MAX ) )
#define FTC_CMAP_NODE_HASH( x ) \
FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
/* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
/* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */
#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 )
/* the charmap query */
typedef struct FTC_CMapQueryRec_
{
FTC_QueryRec query;
FTC_CMapDesc desc;
FT_UInt32 char_code;
} FTC_CMapQueryRec, *FTC_CMapQuery;
#define FTC_CMAP_QUERY( x ) ( (FTC_CMapQuery)( x ) )
/* the charmap family */
typedef struct FTC_CMapFamilyRec_
{
FTC_FamilyRec family;
FT_UInt32 hash;
FTC_CMapDescRec desc;
FT_UInt index;
} FTC_CMapFamilyRec, *FTC_CMapFamily;
#define FTC_CMAP_FAMILY( x ) ( (FTC_CMapFamily)( x ) )
#define FTC_CMAP_FAMILY_MEMORY( x ) FTC_FAMILY( x )->memory
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -106,27 +95,44 @@
/*************************************************************************/
/* no need for specific finalizer; we use "ftc_node_done" directly */
/* no need for specific finalizer; we use `ftc_node_done' directly */
FT_CALLBACK_DEF( void )
ftc_cmap_node_free( FTC_CMapNode node,
FTC_Cache cache )
{
FT_Memory memory = cache->memory;
FT_FREE( node );
}
/* initialize a new cmap node */
FT_CALLBACK_DEF( FT_Error )
ftc_cmap_node_init( FTC_CMapNode cnode,
FTC_CMapQuery cquery,
FTC_Cache cache )
ftc_cmap_node_new( FTC_CMapNode *anode,
FTC_CMapQuery query,
FTC_Cache cache )
{
FT_UInt32 first;
FT_UInt n;
FT_UNUSED( cache );
FT_Error error;
FT_Memory memory = cache->memory;
FTC_CMapNode node;
FT_UInt nn;
first = ( cquery->char_code / FTC_CMAP_INDICES_MAX ) *
FTC_CMAP_INDICES_MAX;
if ( !FT_NEW( node ) )
{
node->face_id = query->face_id;
node->cmap_index = query->cmap_index;
node->first = (query->char_code / FTC_CMAP_INDICES_MAX) *
FTC_CMAP_INDICES_MAX;
cnode->first = first;
for ( n = 0; n < FTC_CMAP_INDICES_MAX; n++ )
cnode->indices[n] = FTC_CMAP_UNKNOWN;
for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
node->indices[nn] = FTC_CMAP_UNKNOWN;
}
return 0;
*anode = node;
return error;
}
@@ -142,184 +148,27 @@
/* compare a cmap node to a given query */
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_compare( FTC_CMapNode cnode,
FTC_CMapQuery cquery )
ftc_cmap_node_compare( FTC_CMapNode node,
FTC_CMapQuery query )
{
FT_UInt32 offset = (FT_UInt32)( cquery->char_code - cnode->first );
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** CHARMAP FAMILY *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ftc_cmap_family_init( FTC_CMapFamily cfam,
FTC_CMapQuery cquery,
FTC_Cache cache )
{
FTC_Manager manager = cache->manager;
FTC_CMapDesc desc = cquery->desc;
FT_UInt32 hash = 0;
FT_Error error;
FT_Face face;
/* setup charmap descriptor */
cfam->desc = *desc;
/* let's see whether the rest is correct too */
error = FTC_Manager_Lookup_Face( manager, desc->face_id, &face );
if ( !error )
if ( node->face_id == query->face_id &&
node->cmap_index == query->cmap_index )
{
FT_UInt count = face->num_charmaps;
FT_UInt idx = count;
FT_CharMap* cur = face->charmaps;
FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first );
switch ( desc->type )
{
case FTC_CMAP_BY_INDEX:
idx = desc->u.index;
hash = idx * 33;
break;
case FTC_CMAP_BY_ENCODING:
if (desc->u.encoding == FT_ENCODING_UNICODE)
{
/* since the `interesting' table, with id's 3,10, is normally the
* last one, we loop backwards. This looses with type1 fonts with
* non-BMP characters (<.0001%), this wins with .ttf with non-BMP
* chars (.01% ?), and this is the same about 99.99% of the time!
*/
FT_UInt unicmap_idx = count; /* some UCS-2 map, if we found it */
cur += count - 1;
for ( idx = 0; idx < count; idx++, cur-- )
{
if ( cur[0]->encoding == FT_ENCODING_UNICODE )
{
unicmap_idx = idx; /* record we found a Unicode charmap */
/* XXX If some new encodings to represent UCS-4 are added,
* they should be added here.
*/
if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT &&
cur[0]->encoding_id == TT_MS_ID_UCS_4 ) ||
( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) )
/* Hurray! We found a UCS-4 charmap. We can stop the scan! */
{
idx = count - 1 - idx;
goto Found_idx_for_FTC_CMAP_BY_ENCODING;
}
}
}
/* We do not have any UCS-4 charmap. Sigh.
* Let's see if we have some other kind of Unicode charmap, though.
*/
if ( unicmap_idx < count )
idx = count - 1 - unicmap_idx;
}
else
{
for ( idx = 0; idx < count; idx++, cur++ )
if ( cur[0]->encoding == desc->u.encoding )
break;
}
Found_idx_for_FTC_CMAP_BY_ENCODING:
hash = idx * 67;
break;
case FTC_CMAP_BY_ID:
for ( idx = 0; idx < count; idx++, cur++ )
{
if ( (FT_UInt)cur[0]->platform_id == desc->u.id.platform &&
(FT_UInt)cur[0]->encoding_id == desc->u.id.encoding )
{
hash = ( ( desc->u.id.platform << 8 ) | desc->u.id.encoding ) * 7;
break;
}
}
break;
default:
;
}
if ( idx >= count )
goto Bad_Descriptor;
/* compute hash value, both in family and query */
cfam->index = idx;
cfam->hash = hash ^ FTC_FACE_ID_HASH( desc->face_id );
FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
error = ftc_family_init( FTC_FAMILY( cfam ),
FTC_QUERY( cquery ), cache );
return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
}
return error;
Bad_Descriptor:
FT_TRACE1(( "ftp_cmap_family_init: invalid charmap descriptor\n" ));
return FTC_Err_Invalid_Argument;
return 0;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_family_compare( FTC_CMapFamily cfam,
FTC_CMapQuery cquery )
ftc_cmap_node_remove_faceid( FTC_CMapNode node,
FTC_FaceID face_id )
{
FT_Int result = 0;
/* first, compare face id and type */
if ( cfam->desc.face_id != cquery->desc->face_id ||
cfam->desc.type != cquery->desc->type )
goto Exit;
switch ( cfam->desc.type )
{
case FTC_CMAP_BY_INDEX:
result = ( cfam->desc.u.index == cquery->desc->u.index );
break;
case FTC_CMAP_BY_ENCODING:
result = ( cfam->desc.u.encoding == cquery->desc->u.encoding );
break;
case FTC_CMAP_BY_ID:
result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform &&
cfam->desc.u.id.encoding == cquery->desc->u.id.encoding );
break;
default:
;
}
if ( result )
{
/* when found, update the 'family' and 'hash' field of the query */
FTC_QUERY( cquery )->family = FTC_FAMILY( cfam );
FTC_QUERY( cquery )->hash = FTC_CMAP_HASH( cfam, cquery );
}
Exit:
return FT_BOOL( result );
return FT_BOOL( node->face_id == face_id );
}
@@ -333,23 +182,17 @@
FT_CALLBACK_TABLE_DEF
const FTC_Cache_ClassRec ftc_cmap_cache_class =
const FTC_CacheClassRec ftc_cmap_cache_class =
{
sizeof ( FTC_CacheRec ),
(FTC_Cache_InitFunc) ftc_cache_init,
(FTC_Cache_ClearFunc)ftc_cache_clear,
(FTC_Cache_DoneFunc) ftc_cache_done,
sizeof ( FTC_CMapFamilyRec ),
(FTC_Family_InitFunc) ftc_cmap_family_init,
(FTC_Family_CompareFunc)ftc_cmap_family_compare,
(FTC_Family_DoneFunc) ftc_family_done,
sizeof ( FTC_CMapNodeRec ),
(FTC_Node_InitFunc) ftc_cmap_node_init,
(FTC_Node_NewFunc) ftc_cmap_node_new,
(FTC_Node_WeightFunc) ftc_cmap_node_weight,
(FTC_Node_CompareFunc)ftc_cmap_node_compare,
(FTC_Node_DoneFunc) ftc_node_done
(FTC_Node_CompareFunc)ftc_cmap_node_remove_faceid,
(FTC_Node_FreeFunc) ftc_cmap_node_free,
sizeof ( FTC_CacheRec ),
(FTC_Cache_InitFunc) ftc_cache_init,
(FTC_Cache_DoneFunc) ftc_cache_done,
};
@@ -359,101 +202,86 @@
FTC_CMapCache_New( FTC_Manager manager,
FTC_CMapCache *acache )
{
return FTC_Manager_Register_Cache(
manager,
(FTC_Cache_Class)&ftc_cmap_cache_class,
FTC_CACHE_P( acache ) );
return FTC_Manager_RegisterCache( manager,
&ftc_cmap_cache_class,
FTC_CACHE_P( acache ) );
}
#ifdef FTC_CACHE_USE_INLINE
#define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
ftc_cmap_family_compare( (FTC_CMapFamily)(f), (FTC_CMapQuery)(q) )
#define GEN_CACHE_NODE_COMPARE( n, q, c ) \
ftc_cmap_node_compare( (FTC_CMapNode)(n), (FTC_CMapQuery)(q) )
#define GEN_CACHE_LOOKUP ftc_cmap_cache_lookup
#include "ftccache.i"
#else /* !FTC_CACHE_USE_INLINE */
#define ftc_cmap_cache_lookup ftc_cache_lookup
#endif /* !FTC_CACHE_USE_INLINE */
/* documentation is in ftccmap.h */
FT_EXPORT_DEF( FT_UInt )
FTC_CMapCache_Lookup( FTC_CMapCache cache,
FTC_CMapDesc desc,
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache,
FTC_FaceID face_id,
FT_Int cmap_index,
FT_UInt32 char_code )
{
FTC_CMapQueryRec cquery;
FTC_Cache cache = FTC_CACHE( cmap_cache );
FTC_CMapQueryRec query;
FTC_CMapNode node;
FT_Error error;
FT_UInt gindex = 0;
FT_UInt32 hash;
if ( !cache || !desc )
if ( !cache )
{
FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" ));
return 0;
}
cquery.desc = desc;
cquery.char_code = char_code;
query.face_id = face_id;
query.cmap_index = (FT_UInt)cmap_index;
query.char_code = char_code;
error = ftc_cmap_cache_lookup( FTC_CACHE( cache ),
FTC_QUERY( &cquery ),
(FTC_Node*)&node );
if ( !error )
hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
#if 1
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
node, error );
#else
error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
#endif
if ( error )
goto Exit;
FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX );
gindex = node->indices[char_code - node->first];
if ( gindex == FTC_CMAP_UNKNOWN )
{
FT_UInt offset = (FT_UInt)( char_code - node->first );
FT_Face face;
FT_ASSERT( offset < FTC_CMAP_INDICES_MAX );
gindex = 0;
gindex = node->indices[offset];
if ( gindex == FTC_CMAP_UNKNOWN )
error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face );
if ( error )
goto Exit;
if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
{
FT_Face face;
FT_CharMap old, cmap = NULL;
/* we need to use FT_Get_Char_Index */
gindex = 0;
error = FTC_Manager_Lookup_Face( FTC_CACHE(cache)->manager,
desc->face_id,
&face );
if ( !error )
{
FT_CharMap old, cmap = NULL;
FT_UInt cmap_index;
/* save old charmap, select new one */
old = face->charmap;
cmap_index = FTC_CMAP_FAMILY( FTC_QUERY( &cquery )->family )->index;
cmap = face->charmaps[cmap_index];
old = face->charmap;
cmap = face->charmaps[cmap_index];
if ( old != cmap )
FT_Set_Charmap( face, cmap );
/* perform lookup */
gindex = FT_Get_Char_Index( face, char_code );
node->indices[offset] = (FT_UInt16)gindex;
gindex = FT_Get_Char_Index( face, char_code );
/* restore old charmap */
if ( old != cmap )
FT_Set_Charmap( face, old );
}
}
node->indices[char_code - node->first] = gindex;
}
Exit:
return gindex;
}
/* END */
/* END */
+1 -1
View File
@@ -37,4 +37,4 @@
#endif /* __FTCERROR_H__ */
/* END */
/* END */
+108 -45
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType Glyph Image (FT_Glyph) cache (body). */
/* */
/* Copyright 2000-2001 by */
/* Copyright 2000-2001, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,54 +20,64 @@
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_ERRORS_H
#include FT_LIST_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftccback.h"
#include "ftcerror.h"
/* create a new chunk node, setting its cache index and ref count */
FT_EXPORT_DEF( void )
ftc_glyph_node_init( FTC_GlyphNode gnode,
FT_UInt gindex,
FTC_GlyphFamily gfam )
FTC_GNode_Init( FTC_GNode gnode,
FT_UInt gindex,
FTC_Family family )
{
FT_UInt len;
FT_UInt start = FTC_GLYPH_FAMILY_START( gfam, gindex );
gnode->item_start = (FT_UShort)start;
len = gfam->item_total - start;
if ( len > gfam->item_count )
len = gfam->item_count;
gnode->item_count = (FT_UShort)len;
gfam->family.num_nodes++;
gnode->family = family;
gnode->gindex = gindex;
family->num_nodes++;
}
FT_EXPORT_DEF( void )
ftc_glyph_node_done( FTC_GlyphNode gnode,
FTC_Cache cache )
FTC_GNode_UnselectFamily( FTC_GNode gnode,
FTC_Cache cache )
{
FTC_Family family = gnode->family;
gnode->family = NULL;
if ( family && --family->num_nodes <= 0 )
FTC_MruList_Remove( &FTC_GCACHE( cache )->families,
(FTC_MruNode)family );
}
FT_EXPORT_DEF( void )
FTC_GNode_Done( FTC_GNode gnode,
FTC_Cache cache )
{
/* finalize the node */
gnode->item_count = 0;
gnode->item_start = 0;
gnode->gindex = 0;
ftc_node_done( FTC_NODE( gnode ), cache );
FTC_GNode_UnselectFamily( gnode, cache );
}
FT_EXPORT_DEF( FT_Bool )
ftc_glyph_node_compare( FTC_GlyphNode gnode,
FTC_GlyphQuery gquery )
FTC_GNode_Compare( FTC_GNode gnode,
FTC_GQuery gquery )
{
FT_UInt start = (FT_UInt)gnode->item_start;
FT_UInt count = (FT_UInt)gnode->item_count;
return FT_BOOL( gnode->family == gquery->family &&
gnode->gindex == gquery->gindex );
}
return FT_BOOL( (FT_UInt)( gquery->gindex - start ) < count );
FT_LOCAL_DEF( FT_Bool )
ftc_gnode_compare( FTC_GNode gnode,
FTC_GQuery gquery )
{
return FTC_GNode_Compare( gnode, gquery );
}
@@ -79,37 +89,90 @@
/*************************************************************************/
/*************************************************************************/
FT_EXPORT_DEF( void )
FTC_Family_Init( FTC_Family family,
FTC_Cache cache )
{
FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS( cache );
family->clazz = clazz->family_class;
family->num_nodes = 0;
family->cache = cache;
}
FT_EXPORT_DEF( FT_Error )
ftc_glyph_family_init( FTC_GlyphFamily gfam,
FT_UInt32 hash,
FT_UInt item_count,
FT_UInt item_total,
FTC_GlyphQuery gquery,
FTC_Cache cache )
FTC_GCache_Init( FTC_GCache cache )
{
FT_Error error;
FT_Error error;
error = ftc_family_init( FTC_FAMILY( gfam ), FTC_QUERY( gquery ), cache );
error = FTC_Cache_Init( FTC_CACHE( cache ) );
if ( !error )
{
gfam->hash = hash;
gfam->item_total = item_total;
gfam->item_count = item_count;
FTC_GLYPH_FAMILY_FOUND( gfam, gquery );
FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class;
FTC_MruList_Init( &cache->families,
clazz->family_class,
0, /* no maximum here! */
cache,
FTC_CACHE( cache )->memory );
}
return error;
}
FT_EXPORT_DEF( void )
ftc_glyph_family_done( FTC_GlyphFamily gfam )
FT_LOCAL_DEF( FT_Error )
ftc_gcache_init( FTC_GCache cache )
{
ftc_family_done( FTC_FAMILY( gfam ) );
return FTC_GCache_Init( cache );
}
/* END */
FT_EXPORT_DEF( void )
FTC_GCache_Done( FTC_GCache cache )
{
FTC_Cache_Done( (FTC_Cache)cache );
FTC_MruList_Done( &cache->families );
}
FT_LOCAL_DEF( void )
ftc_gcache_done( FTC_GCache cache )
{
FTC_GCache_Done( cache );
}
FT_EXPORT_DEF( FT_Error )
FTC_GCache_New( FTC_Manager manager,
FTC_GCacheClass clazz,
FTC_GCache *acache )
{
return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz,
(FTC_Cache*)acache );
}
FT_EXPORT_DEF( FT_Error )
FTC_GCache_Lookup( FTC_GCache cache,
FT_UInt32 hash,
FT_UInt gindex,
FTC_GQuery query,
FTC_Node *anode )
{
FT_Error error;
query->gindex = gindex;
FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
if ( !error )
error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode );
return error;
}
/* END */
+52 -306
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType Image cache (body). */
/* */
/* Copyright 2000-2001 by */
/* Copyright 2000-2001, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,133 +18,83 @@
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_IMAGE_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_CACHE_INTERNAL_IMAGE_H
#include FT_INTERNAL_MEMORY_H
#include "ftccback.h"
#include "ftcerror.h"
/* the FT_Glyph image node type */
typedef struct FTC_ImageNodeRec_
{
FTC_GlyphNodeRec gnode;
FT_Glyph glyph;
} FTC_ImageNodeRec, *FTC_ImageNode;
#define FTC_IMAGE_NODE( x ) ( (FTC_ImageNode)( x ) )
#define FTC_IMAGE_NODE_GINDEX( x ) FTC_GLYPH_NODE_GINDEX( x )
/* the glyph image query */
typedef struct FTC_ImageQueryRec_
{
FTC_GlyphQueryRec gquery;
FTC_ImageTypeRec type;
} FTC_ImageQueryRec, *FTC_ImageQuery;
#define FTC_IMAGE_QUERY( x ) ( (FTC_ImageQuery)( x ) )
/* the glyph image set type */
typedef struct FTC_ImageFamilyRec_
{
FTC_GlyphFamilyRec gfam;
FTC_ImageTypeRec type;
} FTC_ImageFamilyRec, *FTC_ImageFamily;
#define FTC_IMAGE_FAMILY( x ) ( (FTC_ImageFamily)( x ) )
#define FTC_IMAGE_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &(x)->gfam )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLYPH IMAGE NODES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* finalize a given glyph image node */
FT_CALLBACK_DEF( void )
ftc_image_node_done( FTC_ImageNode inode,
FTC_Cache cache )
FT_EXPORT_DEF( void )
FTC_INode_Free( FTC_INode inode,
FTC_Cache cache )
{
FT_Memory memory = cache->memory;
if ( inode->glyph )
{
FT_Done_Glyph( inode->glyph );
inode->glyph = NULL;
}
ftc_glyph_node_done( FTC_GLYPH_NODE( inode ), cache );
FTC_GNode_Done( FTC_GNODE( inode ), cache );
FT_FREE( inode );
}
FT_LOCAL_DEF( void )
ftc_inode_free( FTC_INode inode,
FTC_Cache cache )
{
FTC_INode_Free( inode, cache );
}
/* initialize a new glyph image node */
FT_CALLBACK_DEF( FT_Error )
ftc_image_node_init( FTC_ImageNode inode,
FTC_GlyphQuery gquery,
FTC_Cache cache )
FT_EXPORT_DEF( FT_Error )
FTC_INode_New( FTC_INode *pinode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FTC_ImageFamily ifam = FTC_IMAGE_FAMILY( gquery->query.family );
FT_Error error;
FT_Face face;
FT_Size size;
FT_Memory memory = cache->memory;
FT_Error error;
FTC_INode inode;
/* initialize its inner fields */
ftc_glyph_node_init( FTC_GLYPH_NODE( inode ),
gquery->gindex,
FTC_GLYPH_FAMILY( ifam ) );
/* we will now load the glyph image */
error = FTC_Manager_Lookup_Size( FTC_FAMILY( ifam )->cache->manager,
&ifam->type.font,
&face, &size );
if ( !error )
if ( !FT_NEW( inode ) )
{
FT_UInt gindex = FTC_GLYPH_NODE_GINDEX( inode );
FTC_GNode gnode = FTC_GNODE( inode );
FTC_Family family = gquery->family;
FT_UInt gindex = gquery->gindex;
FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache );
error = FT_Load_Glyph( face, gindex, ifam->type.flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* ok, copy it */
FT_Glyph glyph;
/* initialize its inner fields */
FTC_GNode_Init( gnode, gindex, family );
error = FT_Get_Glyph( face->glyph, &glyph );
if ( !error )
{
inode->glyph = glyph;
goto Exit;
}
}
else
error = FTC_Err_Invalid_Argument;
}
/* we will now load the glyph image */
error = clazz->family_load_glyph( family, gindex, cache,
&inode->glyph );
}
/* in case of error */
ftc_glyph_node_done( FTC_GLYPH_NODE(inode), cache );
Exit:
*pinode = inode;
return error;
}
FT_CALLBACK_DEF( FT_ULong )
ftc_image_node_weight( FTC_ImageNode inode )
FT_LOCAL_DEF( FT_Error )
ftc_inode_new( FTC_INode *pinode,
FTC_GQuery gquery,
FTC_Cache cache )
{
return FTC_INode_New( pinode, gquery, cache );
}
FT_EXPORT_DEF( FT_ULong )
FTC_INode_Weight( FTC_INode inode )
{
FT_ULong size = 0;
FT_Glyph glyph = inode->glyph;
@@ -185,215 +135,11 @@
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLYPH IMAGE SETS *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ftc_image_family_init( FTC_ImageFamily ifam,
FTC_ImageQuery iquery,
FTC_Cache cache )
FT_LOCAL_DEF( FT_ULong )
ftc_inode_weight( FTC_INode inode )
{
FTC_Manager manager = cache->manager;
FT_Error error;
FT_Face face;
ifam->type = iquery->type;
/* we need to compute "iquery.item_total" now */
error = FTC_Manager_Lookup_Face( manager,
iquery->type.font.face_id,
&face );
if ( !error )
{
error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( ifam ),
FTC_IMAGE_TYPE_HASH( &ifam->type ),
1,
face->num_glyphs,
FTC_GLYPH_QUERY( iquery ),
cache );
}
return error;
return FTC_INode_Weight( inode );
}
FT_CALLBACK_DEF( FT_Bool )
ftc_image_family_compare( FTC_ImageFamily ifam,
FTC_ImageQuery iquery )
{
FT_Bool result;
result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) );
if ( result )
FTC_GLYPH_FAMILY_FOUND( ifam, iquery );
return result;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** GLYPH IMAGE CACHE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_TABLE_DEF
const FTC_Cache_ClassRec ftc_image_cache_class =
{
sizeof ( FTC_CacheRec ),
(FTC_Cache_InitFunc) ftc_cache_init,
(FTC_Cache_ClearFunc)ftc_cache_clear,
(FTC_Cache_DoneFunc) ftc_cache_done,
sizeof ( FTC_ImageFamilyRec ),
(FTC_Family_InitFunc) ftc_image_family_init,
(FTC_Family_CompareFunc)ftc_image_family_compare,
(FTC_Family_DoneFunc) ftc_glyph_family_done,
sizeof ( FTC_ImageNodeRec ),
(FTC_Node_InitFunc) ftc_image_node_init,
(FTC_Node_WeightFunc) ftc_image_node_weight,
(FTC_Node_CompareFunc)ftc_glyph_node_compare,
(FTC_Node_DoneFunc) ftc_image_node_done
};
/* documentation is in ftcimage.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_New( FTC_Manager manager,
FTC_ImageCache *acache )
{
return FTC_Manager_Register_Cache(
manager,
(FTC_Cache_Class)&ftc_image_cache_class,
FTC_CACHE_P( acache ) );
}
/* documentation is in ftcimage.h */
FT_EXPORT_DEF( FT_Error )
FTC_ImageCache_Lookup( FTC_ImageCache cache,
FTC_ImageType type,
FT_UInt gindex,
FT_Glyph *aglyph,
FTC_Node *anode )
{
FTC_ImageQueryRec iquery;
FTC_ImageNode node;
FT_Error error;
/* some argument checks are delayed to ftc_cache_lookup */
if ( !aglyph )
return FTC_Err_Invalid_Argument;
if ( anode )
*anode = NULL;
iquery.gquery.gindex = gindex;
iquery.type = *type;
error = ftc_cache_lookup( FTC_CACHE( cache ),
FTC_QUERY( &iquery ),
(FTC_Node*)&node );
if ( !error )
{
*aglyph = node->glyph;
if ( anode )
{
*anode = (FTC_Node)node;
FTC_NODE( node )->ref_count++;
}
}
return error;
}
/* backwards-compatibility functions */
FT_EXPORT_DEF( FT_Error )
FTC_Image_Cache_New( FTC_Manager manager,
FTC_Image_Cache *acache )
{
return FTC_ImageCache_New( manager, (FTC_ImageCache*)acache );
}
FT_EXPORT_DEF( FT_Error )
FTC_Image_Cache_Lookup( FTC_Image_Cache icache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FT_Glyph *aglyph )
{
FTC_ImageTypeRec type0;
if ( !desc )
return FTC_Err_Invalid_Argument;
type0.font = desc->font;
/* convert image type flags to load flags */
{
FT_UInt load_flags = FT_LOAD_DEFAULT;
FT_UInt type = desc->image_type;
/* determine load flags, depending on the font description's */
/* image type */
if ( ftc_image_format( type ) == ftc_image_format_bitmap )
{
if ( type & ftc_image_flag_monochrome )
load_flags |= FT_LOAD_MONOCHROME;
/* disable embedded bitmaps loading if necessary */
if ( type & ftc_image_flag_no_sbits )
load_flags |= FT_LOAD_NO_BITMAP;
}
else
{
/* we want an outline, don't load embedded bitmaps */
load_flags |= FT_LOAD_NO_BITMAP;
if ( type & ftc_image_flag_unscaled )
load_flags |= FT_LOAD_NO_SCALE;
}
/* always render glyphs to bitmaps */
load_flags |= FT_LOAD_RENDER;
if ( type & ftc_image_flag_unhinted )
load_flags |= FT_LOAD_NO_HINTING;
if ( type & ftc_image_flag_autohinted )
load_flags |= FT_LOAD_FORCE_AUTOHINT;
type0.flags = load_flags;
}
return FTC_ImageCache_Lookup( (FTC_ImageCache)icache,
&type0,
gindex,
aglyph,
NULL );
}
/* END */
/* END */
+307 -425
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache Manager (body). */
/* */
/* Copyright 2000-2001, 2002 by */
/* Copyright 2000-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,8 +18,7 @@
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_MANAGER_H
#include FT_CACHE_INTERNAL_LRU_H
#include FT_CACHE_INTERNAL_MANAGER_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_SIZES_H
@@ -33,32 +32,171 @@
#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data )
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FACE LRU IMPLEMENTATION *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct FTC_FaceNodeRec_* FTC_FaceNode;
typedef struct FTC_SizeNodeRec_* FTC_SizeNode;
typedef struct FTC_FaceNodeRec_
static FT_Error
ftc_scaler_lookup_size( FTC_Manager manager,
FTC_Scaler scaler,
FT_Size *asize )
{
FT_LruNodeRec lru;
FT_Face face;
FT_Face face;
FT_Size size = NULL;
FT_Error error;
} FTC_FaceNodeRec;
error = FTC_Manager_LookupFace( manager, scaler->face_id, &face );
if ( error )
goto Exit;
error = FT_New_Size( face, &size );
if ( error )
goto Exit;
FT_Activate_Size( size );
if ( scaler->pixel )
error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height );
else
error = FT_Set_Char_Size( face, scaler->width, scaler->height,
scaler->x_res, scaler->y_res );
if ( error )
{
FT_Done_Size( size );
size = NULL;
}
Exit:
*asize = size;
return error;
}
typedef struct FTC_SizeNodeRec_
{
FT_LruNodeRec lru;
FT_Size size;
FTC_MruNodeRec node;
FT_Size size;
FTC_ScalerRec scaler;
} FTC_SizeNodeRec;
} FTC_SizeNodeRec, *FTC_SizeNode;
FT_CALLBACK_DEF( void )
ftc_size_node_done( FTC_SizeNode node )
{
FT_Size size = node->size;
if ( size )
FT_Done_Size( size );
}
FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_compare( FTC_SizeNode node,
FTC_Scaler scaler )
{
FTC_Scaler scaler0 = &node->scaler;
if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
{
FT_Activate_Size( node->size );
return 1;
}
return 0;
}
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_init( FTC_SizeNode node,
FTC_Scaler scaler,
FTC_Manager manager )
{
node->scaler = scaler[0];
return ftc_scaler_lookup_size( manager, scaler, &node->size );
}
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_reset( FTC_SizeNode node,
FTC_Scaler scaler,
FTC_Manager manager )
{
FT_Done_Size( node->size );
node->scaler = scaler[0];
return ftc_scaler_lookup_size( manager, scaler, &node->size );
}
FT_CALLBACK_TABLE_DEF
const FTC_MruListClassRec ftc_size_list_class =
{
sizeof( FTC_SizeNodeRec ),
(FTC_MruNode_CompareFunc)ftc_size_node_compare,
(FTC_MruNode_InitFunc) ftc_size_node_init,
(FTC_MruNode_ResetFunc) ftc_size_node_reset,
(FTC_MruNode_DoneFunc) ftc_size_node_done
};
/* helper function used by ftc_face_node_done */
static FT_Bool
ftc_size_node_compare_faceid( FTC_SizeNode node,
FTC_FaceID face_id )
{
return FT_BOOL( node->scaler.face_id == face_id );
}
FT_EXPORT_DEF( FT_Error )
FTC_Manager_LookupSize( FTC_Manager manager,
FTC_Scaler scaler,
FT_Size *asize )
{
FT_Error error;
FTC_SizeNode node;
if ( asize == NULL )
return FTC_Err_Bad_Argument;
*asize = NULL;
if ( !manager )
return FTC_Err_Invalid_Cache_Handle;
#ifdef FTC_INLINE
FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
node, error );
#else
error = FTC_MruList_Lookup( &manager->sizes, scaler, (FTC_MruNode*)&node );
#endif
if ( !error )
*asize = node->size;
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FACE MRU IMPLEMENTATION *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct FTC_FaceNodeRec_
{
FTC_MruNodeRec node;
FTC_FaceID face_id;
FT_Face face;
} FTC_FaceNodeRec, *FTC_FaceNode;
FT_CALLBACK_DEF( FT_Error )
@@ -69,6 +207,8 @@
FT_Error error;
node->face_id = face_id;
error = manager->request_face( face_id,
manager->library,
manager->request_data,
@@ -84,55 +224,50 @@
}
/* helper function for ftc_face_node_done() */
FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_select( FTC_SizeNode node,
FT_Face face )
{
return FT_BOOL( node->size->face == face );
}
FT_CALLBACK_DEF( void )
ftc_face_node_done( FTC_FaceNode node,
FTC_Manager manager )
{
FT_Face face = node->face;
/* we must begin by removing all sizes for the target face */
/* from the manager's list */
FT_LruList_Remove_Selection( manager->sizes_list,
(FT_LruNode_SelectFunc)ftc_size_node_select,
face );
/* we must begin by removing all scalers for the target face */
/* from the manager's list */
FTC_MruList_RemoveSelection(
& manager->sizes,
(FTC_MruNode_CompareFunc)ftc_size_node_compare_faceid,
node->face_id );
/* all right, we can discard the face now */
FT_Done_Face( face );
node->face = NULL;
FT_Done_Face( node->face );
node->face = NULL;
node->face_id = NULL;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_face_node_compare( FTC_FaceNode node,
FTC_FaceID face_id )
{
return FT_BOOL( node->face_id == face_id );
}
FT_CALLBACK_TABLE_DEF
const FT_LruList_ClassRec ftc_face_list_class =
const FTC_MruListClassRec ftc_face_list_class =
{
sizeof ( FT_LruListRec ),
(FT_LruList_InitFunc)0,
(FT_LruList_DoneFunc)0,
sizeof( FTC_FaceNodeRec),
sizeof ( FTC_FaceNodeRec ),
(FT_LruNode_InitFunc) ftc_face_node_init,
(FT_LruNode_DoneFunc) ftc_face_node_done,
(FT_LruNode_FlushFunc) 0, /* no flushing needed */
(FT_LruNode_CompareFunc)0, /* direct comparison of FTC_FaceID handles */
(FTC_MruNode_CompareFunc)ftc_face_node_compare,
(FTC_MruNode_InitFunc) ftc_face_node_init,
(FTC_MruNode_ResetFunc) NULL,
(FTC_MruNode_DoneFunc) ftc_face_node_done
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_Lookup_Face( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face *aface )
FTC_Manager_LookupFace( FTC_Manager manager,
FTC_FaceID face_id,
FT_Face *aface )
{
FT_Error error;
FTC_FaceNode node;
@@ -146,9 +281,16 @@
if ( !manager )
return FTC_Err_Invalid_Cache_Handle;
error = FT_LruList_Lookup( manager->faces_list,
(FT_LruKey)face_id,
(FT_LruNode*)&node );
/* we break encapsulation for the sake of speed */
#ifdef FTC_INLINE
FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
node, error );
#else
error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node );
#endif
if ( !error )
*aface = node->face;
@@ -156,283 +298,6 @@
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SIZES LRU IMPLEMENTATION *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct FTC_SizeQueryRec_
{
FT_Face face;
FT_UInt width;
FT_UInt height;
} FTC_SizeQueryRec, *FTC_SizeQuery;
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_init( FTC_SizeNode node,
FTC_SizeQuery query )
{
FT_Face face = query->face;
FT_Size size;
FT_Error error;
node->size = NULL;
error = FT_New_Size( face, &size );
if ( !error )
{
FT_Activate_Size( size );
error = FT_Set_Pixel_Sizes( query->face,
query->width,
query->height );
if ( error )
FT_Done_Size( size );
else
node->size = size;
}
return error;
}
FT_CALLBACK_DEF( void )
ftc_size_node_done( FTC_SizeNode node )
{
if ( node->size )
{
FT_Done_Size( node->size );
node->size = NULL;
}
}
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_flush( FTC_SizeNode node,
FTC_SizeQuery query )
{
FT_Size size = node->size;
FT_Error error;
if ( size->face == query->face )
{
FT_Activate_Size( size );
error = FT_Set_Pixel_Sizes( query->face, query->width, query->height );
if ( error )
{
FT_Done_Size( size );
node->size = NULL;
}
}
else
{
FT_Done_Size( size );
node->size = NULL;
error = ftc_size_node_init( node, query );
}
return error;
}
FT_CALLBACK_DEF( FT_Bool )
ftc_size_node_compare( FTC_SizeNode node,
FTC_SizeQuery query )
{
FT_Size size = node->size;
return FT_BOOL( size->face == query->face &&
(FT_UInt)size->metrics.x_ppem == query->width &&
(FT_UInt)size->metrics.y_ppem == query->height );
}
FT_CALLBACK_TABLE_DEF
const FT_LruList_ClassRec ftc_size_list_class =
{
sizeof ( FT_LruListRec ),
(FT_LruList_InitFunc)0,
(FT_LruList_DoneFunc)0,
sizeof ( FTC_SizeNodeRec ),
(FT_LruNode_InitFunc) ftc_size_node_init,
(FT_LruNode_DoneFunc) ftc_size_node_done,
(FT_LruNode_FlushFunc) ftc_size_node_flush,
(FT_LruNode_CompareFunc)ftc_size_node_compare
};
/* documentation is in ftcache.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_Lookup_Size( FTC_Manager manager,
FTC_Font font,
FT_Face *aface,
FT_Size *asize )
{
FT_Error error;
/* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
if ( aface )
*aface = 0;
if ( asize )
*asize = 0;
error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
if ( !error )
{
FTC_SizeQueryRec query;
FTC_SizeNode node;
query.face = *aface;
query.width = font->pix_width;
query.height = font->pix_height;
error = FT_LruList_Lookup( manager->sizes_list,
(FT_LruKey)&query,
(FT_LruNode*)&node );
if ( !error )
{
/* select the size as the current one for this face */
FT_Activate_Size( node->size );
if ( asize )
*asize = node->size;
}
}
return error;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SET TABLE MANAGEMENT *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static void
ftc_family_table_init( FTC_FamilyTable table )
{
table->count = 0;
table->size = 0;
table->entries = NULL;
table->free = FTC_FAMILY_ENTRY_NONE;
}
static void
ftc_family_table_done( FTC_FamilyTable table,
FT_Memory memory )
{
FT_FREE( table->entries );
table->free = 0;
table->count = 0;
table->size = 0;
}
FT_EXPORT_DEF( FT_Error )
ftc_family_table_alloc( FTC_FamilyTable table,
FT_Memory memory,
FTC_FamilyEntry *aentry )
{
FTC_FamilyEntry entry;
FT_Error error = 0;
/* re-allocate table size when needed */
if ( table->free == FTC_FAMILY_ENTRY_NONE && table->count >= table->size )
{
FT_UInt old_size = table->size;
FT_UInt new_size, idx;
if ( old_size == 0 )
new_size = 8;
else
{
new_size = old_size * 2;
/* check for (unlikely) overflow */
if ( new_size < old_size )
new_size = 65534;
}
if ( FT_RENEW_ARRAY( table->entries, old_size, new_size ) )
return error;
table->size = new_size;
entry = table->entries + old_size;
table->free = old_size;
for ( idx = old_size; idx + 1 < new_size; idx++, entry++ )
{
entry->link = idx + 1;
entry->index = idx;
}
entry->link = FTC_FAMILY_ENTRY_NONE;
entry->index = idx;
}
if ( table->free != FTC_FAMILY_ENTRY_NONE )
{
entry = table->entries + table->free;
table->free = entry->link;
}
else if ( table->count < table->size )
{
entry = table->entries + table->count++;
}
else
{
FT_ERROR(( "ftc_family_table_alloc: internal bug!" ));
return FTC_Err_Invalid_Argument;
}
entry->link = FTC_FAMILY_ENTRY_NONE;
table->count++;
*aentry = entry;
return error;
}
FT_EXPORT_DEF( void )
ftc_family_table_free( FTC_FamilyTable table,
FT_UInt idx )
{
/* simply add it to the linked list of free entries */
if ( idx < table->count )
{
FTC_FamilyEntry entry = table->entries + idx;
if ( entry->link != FTC_FAMILY_ENTRY_NONE )
FT_ERROR(( "ftc_family_table_free: internal bug!\n" ));
else
{
entry->link = table->free;
table->free = entry->index;
table->count--;
}
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -475,41 +340,28 @@
if ( max_bytes == 0 )
max_bytes = FTC_MAX_BYTES_DEFAULT;
error = FT_LruList_New( &ftc_face_list_class,
max_faces,
manager,
memory,
&manager->faces_list );
if ( error )
goto Exit;
error = FT_LruList_New( &ftc_size_list_class,
max_sizes,
manager,
memory,
&manager->sizes_list );
if ( error )
goto Exit;
manager->library = library;
manager->memory = memory;
manager->max_weight = max_bytes;
manager->cur_weight = 0;
manager->request_face = requester;
manager->request_data = req_data;
ftc_family_table_init( &manager->families );
FTC_MruList_Init( &manager->faces,
&ftc_face_list_class,
max_faces,
manager,
memory );
FTC_MruList_Init( &manager->sizes,
&ftc_size_list_class,
max_sizes,
manager,
memory );
*amanager = manager;
Exit:
if ( error && manager )
{
FT_LruList_Destroy( manager->faces_list );
FT_LruList_Destroy( manager->sizes_list );
FT_FREE( manager );
}
return error;
}
@@ -526,31 +378,29 @@
if ( !manager || !manager->library )
return;
memory = manager->library->memory;
memory = manager->memory;
/* now discard all caches */
for (idx = 0; idx < FTC_MAX_CACHES; idx++ )
for (idx = manager->num_caches; idx-- > 0; )
{
FTC_Cache cache = manager->caches[idx];
if ( cache )
{
cache->clazz->cache_done( cache );
cache->clazz.cache_done( cache );
FT_FREE( cache );
manager->caches[idx] = 0;
manager->caches[idx] = NULL;
}
}
/* discard families table */
ftc_family_table_done( &manager->families, memory );
manager->num_caches = 0;
/* discard faces and sizes */
FT_LruList_Destroy( manager->faces_list );
manager->faces_list = 0;
FTC_MruList_Done( &manager->sizes );
FTC_MruList_Done( &manager->faces );
FT_LruList_Destroy( manager->sizes_list );
manager->sizes_list = 0;
manager->library = NULL;
manager->memory = NULL;
FT_FREE( manager );
}
@@ -563,8 +413,8 @@
{
if ( manager )
{
FT_LruList_Reset( manager->sizes_list );
FT_LruList_Reset( manager->faces_list );
FTC_MruList_Reset( &manager->sizes );
FTC_MruList_Reset( &manager->faces );
}
/* XXX: FIXME: flush the caches? */
}
@@ -576,7 +426,7 @@
FTC_Manager_Check( FTC_Manager manager )
{
FTC_Node node, first;
first = manager->nodes_list;
@@ -584,26 +434,22 @@
if ( first )
{
FT_ULong weight = 0;
node = first;
do
{
FTC_FamilyEntry entry = manager->families.entries + node->fam_index;
FTC_Cache cache;
FTC_Cache cache = manager->caches[node->cache_index];
if ( (FT_UInt)node->fam_index >= manager->families.count ||
entry->link != FTC_FAMILY_ENTRY_NONE )
FT_ERROR(( "FTC_Manager_Check: invalid node (family index = %ld\n",
node->fam_index ));
if ( (FT_UInt)node->cache_index >= manager->num_caches )
FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n",
node->cache_index ));
else
{
cache = entry->cache;
weight += cache->clazz->node_weight( node, cache );
}
weight += cache->clazz.node_weight( node, cache );
node = node->mru_next;
node = FTC_NODE__NEXT( node );
} while ( node != first );
@@ -622,7 +468,7 @@
do
{
count++;
node = node->mru_next;
node = FTC_NODE__NEXT( node );
} while ( node != first );
@@ -664,14 +510,14 @@
if ( manager->cur_weight < manager->max_weight || first == NULL )
return;
/* go to last node - it's a circular list */
node = first->mru_prev;
/* go to last node -- it's a circular list */
node = FTC_NODE__PREV( first );
do
{
FTC_Node prev = node->mru_prev;
FTC_Node prev;
prev = ( node == first ) ? NULL : node->mru_prev;
prev = ( node == first ) ? NULL : FTC_NODE__PREV( node );
if ( node->ref_count <= 0 )
ftc_node_destroy( node, manager );
@@ -685,9 +531,9 @@
/* documentation is in ftcmanag.h */
FT_EXPORT_DEF( FT_Error )
FTC_Manager_Register_Cache( FTC_Manager manager,
FTC_Cache_Class clazz,
FTC_Cache *acache )
FTC_Manager_RegisterCache( FTC_Manager manager,
FTC_CacheClass clazz,
FTC_Cache *acache )
{
FT_Error error = FTC_Err_Invalid_Argument;
FTC_Cache cache = NULL;
@@ -695,50 +541,37 @@
if ( manager && clazz && acache )
{
FT_Memory memory = manager->library->memory;
FT_UInt idx = 0;
FT_Memory memory = manager->memory;
/* check for an empty cache slot in the manager's table */
for ( idx = 0; idx < FTC_MAX_CACHES; idx++ )
{
if ( manager->caches[idx] == 0 )
break;
}
/* return an error if there are too many registered caches */
if ( idx >= FTC_MAX_CACHES )
if ( manager->num_caches >= FTC_MAX_CACHES )
{
error = FTC_Err_Too_Many_Caches;
FT_ERROR(( "FTC_Manager_Register_Cache:" ));
FT_ERROR(( " too many registered caches\n" ));
FT_ERROR(( "%s: too many registered caches\n",
"FTC_Manager_Register_Cache" ));
goto Exit;
}
if ( !FT_ALLOC( cache, clazz->cache_size ) )
{
cache->manager = manager;
cache->memory = memory;
cache->clazz = clazz;
cache->manager = manager;
cache->memory = memory;
cache->clazz = clazz[0];
cache->org_class = clazz;
/* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
/* IF IT IS NOT SET CORRECTLY */
cache->cache_index = idx;
cache->index = manager->num_caches;
if ( clazz->cache_init )
error = clazz->cache_init( cache );
if ( error )
{
error = clazz->cache_init( cache );
if ( error )
{
if ( clazz->cache_done )
clazz->cache_done( cache );
FT_FREE( cache );
goto Exit;
}
clazz->cache_done( cache );
FT_FREE( cache );
goto Exit;
}
manager->caches[idx] = cache;
manager->caches[manager->num_caches++] = cache;
}
}
@@ -748,18 +581,67 @@
}
FT_EXPORT_DEF( FT_UInt )
FTC_Manager_FlushN( FTC_Manager manager,
FT_UInt count )
{
FTC_Node first = manager->nodes_list;
FTC_Node node;
FT_UInt result;
/* try to remove `count' nodes from the list */
if ( first == NULL ) /* empty list! */
return 0;
/* go to last node - it's a circular list */
node = FTC_NODE__PREV(first);
for ( result = 0; result < count; )
{
FTC_Node prev = FTC_NODE__PREV( node );
/* don't touch locked nodes */
if ( node->ref_count <= 0 )
{
ftc_node_destroy( node, manager );
result++;
}
if ( prev == manager->nodes_list )
break;
node = prev;
}
return result;
}
FT_EXPORT_DEF( void )
FTC_Manager_RemoveFaceID( FTC_Manager manager,
FTC_FaceID face_id )
{
FT_UInt nn;
/* this will remove all FTC_SizeNode that correspond to
* the face_id as well
*/
FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id );
for ( nn = 0; nn < manager->num_caches; nn++ )
FTC_Cache_RemoveFaceID( manager->caches[nn], face_id );
}
/* documentation is in ftcmanag.h */
FT_EXPORT_DEF( void )
FTC_Node_Unref( FTC_Node node,
FTC_Manager manager )
{
if ( node && (FT_UInt)node->fam_index < manager->families.count &&
manager->families.entries[node->fam_index].cache )
{
if ( node && (FT_UInt)node->cache_index < manager->num_caches )
node->ref_count--;
}
}
/* END */
/* END */
+355
View File
@@ -0,0 +1,355 @@
/***************************************************************************/
/* */
/* ftcmru.c */
/* */
/* FreeType MRU support (body). */
/* */
/* Copyright 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_MRU_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftcerror.h"
FT_EXPORT_DEF( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
if ( first )
{
FTC_MruNode last = first->prev;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
{
fprintf( stderr, "FTC_MruNode_Prepend: invalid action!\n" );
exit( 2 );
}
cnode = cnode->next;
} while ( cnode != first );
}
#endif
first->prev = node;
last->next = node;
node->next = first;
node->prev = last;
}
else
{
node->next = node;
node->prev = node;
}
*plist = node;
}
FT_EXPORT_DEF( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FT_ASSERT( first != NULL );
if ( first != node )
{
FTC_MruNode prev, next, last;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Up: invalid action!\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
last = first->prev;
last->next = node;
first->prev = node;
node->next = first;
node->prev = last;
*plist = node;
}
}
FT_EXPORT_DEF( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FTC_MruNode prev, next;
FT_ASSERT( first != NULL );
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Remove: invalid action!\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
if ( node == next )
{
FT_ASSERT( first == node );
FT_ASSERT( prev == node );
*plist = NULL;
}
else if ( node == first )
*plist = next;
}
FT_EXPORT_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory )
{
list->num_nodes = 0;
list->max_nodes = max_nodes;
list->nodes = NULL;
list->clazz = *clazz;
list->data = data;
list->memory = memory;
}
FT_EXPORT( void )
FTC_MruList_Reset( FTC_MruList list )
{
while ( list->nodes )
FTC_MruList_Remove( list, list->nodes );
FT_ASSERT( list->num_nodes == 0 );
}
FT_EXPORT( void )
FTC_MruList_Done( FTC_MruList list )
{
FTC_MruList_Reset( list );
}
FT_EXPORT_DEF( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key )
{
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
FTC_MruNode first, node;
first = list->nodes;
node = NULL;
if ( first )
{
node = first;
do
{
if ( compare( node, key ) )
{
if ( node != first )
FTC_MruNode_Up( &list->nodes, node );
return node;
}
node = node->next;
} while ( node != first);
}
return NULL;
}
FT_EXPORT_DEF( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FT_Error error;
FTC_MruNode node;
FT_Memory memory = list->memory;
if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
{
node = list->nodes->prev;
FT_ASSERT( node );
if ( list->clazz.node_reset )
{
FTC_MruNode_Up( &list->nodes, node );
error = list->clazz.node_reset( node, key, list->data );
if ( !error )
goto Exit;
}
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
else if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
goto Fail;
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
Exit:
*anode = node;
return error;
Fail:
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
goto Exit;
}
FT_EXPORT( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FTC_MruNode node;
node = FTC_MruList_Find( list, key );
if ( node == NULL )
return FTC_MruList_New( list, key, anode );
*anode = node;
return 0;
}
FT_EXPORT_DEF( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
{
FT_Memory memory = list->memory;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
}
}
FT_EXPORT_DEF( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key )
{
FTC_MruNode first, node, next;
first = list->nodes;
while ( first && ( selection == NULL || selection( first, key ) ) )
{
FTC_MruList_Remove( list, first );
first = list->nodes;
}
if ( first )
{
node = first->next;
while ( node != first )
{
next = node->next;
if ( selection( node, key ) )
FTC_MruList_Remove( list, node );
node = next;
}
}
}
/* END */
+179 -403
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType sbits manager (body). */
/* */
/* Copyright 2000-2001, 2002 by */
/* Copyright 2000-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,57 +18,15 @@
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_SMALL_BITMAPS_H
#include FT_CACHE_INTERNAL_GLYPH_H
#include FT_CACHE_INTERNAL_SBITS_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include FT_ERRORS_H
#include "ftccback.h"
#include "ftcerror.h"
#define FTC_SBIT_ITEMS_PER_NODE 16
typedef struct FTC_SBitNodeRec_* FTC_SBitNode;
typedef struct FTC_SBitNodeRec_
{
FTC_GlyphNodeRec gnode;
FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE];
} FTC_SBitNodeRec;
#define FTC_SBIT_NODE( x ) ( (FTC_SBitNode)( x ) )
typedef struct FTC_SBitQueryRec_
{
FTC_GlyphQueryRec gquery;
FTC_ImageTypeRec type;
} FTC_SBitQueryRec, *FTC_SBitQuery;
#define FTC_SBIT_QUERY( x ) ( (FTC_SBitQuery)( x ) )
typedef struct FTC_SBitFamilyRec_* FTC_SBitFamily;
/* sbit family structure */
typedef struct FTC_SBitFamilyRec_
{
FTC_GlyphFamilyRec gfam;
FTC_ImageTypeRec type;
} FTC_SBitFamilyRec;
#define FTC_SBIT_FAMILY( x ) ( (FTC_SBitFamily)( x ) )
#define FTC_SBIT_FAMILY_MEMORY( x ) FTC_GLYPH_FAMILY_MEMORY( &( x )->cset )
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -100,174 +58,210 @@
}
FT_CALLBACK_DEF( void )
ftc_sbit_node_done( FTC_SBitNode snode,
FTC_Cache cache )
FT_EXPORT_DEF( void )
FTC_SNode_Free( FTC_SNode snode,
FTC_Cache cache )
{
FTC_SBit sbit = snode->sbits;
FT_UInt count = FTC_GLYPH_NODE( snode )->item_count;
FT_UInt count = snode->count;
FT_Memory memory = cache->memory;
for ( ; count > 0; sbit++, count-- )
FT_FREE( sbit->buffer );
ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
FTC_GNode_Done( FTC_GNODE( snode ), cache );
FT_FREE( snode );
}
FT_LOCAL_DEF( void )
ftc_snode_free( FTC_SNode snode,
FTC_Cache cache )
{
FTC_SNode_Free( snode, cache );
}
static FT_Error
ftc_sbit_node_load( FTC_SBitNode snode,
FTC_Manager manager,
FTC_SBitFamily sfam,
FT_UInt gindex,
FT_ULong *asize )
ftc_snode_load( FTC_SNode snode,
FTC_Manager manager,
FT_UInt gindex,
FT_ULong *asize )
{
FT_Error error;
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
FT_Memory memory;
FT_Face face;
FT_Size size;
FTC_SBit sbit;
FT_Error error;
FTC_GNode gnode = FTC_GNODE( snode );
FTC_Family family = gnode->family;
FT_Memory memory = manager->memory;
FT_Face face;
FTC_SBit sbit;
FTC_SFamilyClass clazz;
if ( gindex < (FT_UInt)gnode->item_start ||
gindex >= (FT_UInt)gnode->item_start + gnode->item_count )
if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
{
FT_ERROR(( "ftc_sbit_node_load: invalid glyph index" ));
FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
return FTC_Err_Invalid_Argument;
}
memory = manager->library->memory;
sbit = snode->sbits + ( gindex - gnode->gindex );
clazz = (FTC_SFamilyClass)family->clazz;
sbit = snode->sbits + ( gindex - gnode->item_start );
sbit->buffer = 0;
error = clazz->family_load_glyph( family, gindex, manager, &face );
if ( error )
goto BadGlyph;
error = FTC_Manager_Lookup_Size( manager, &sfam->type.font,
&face, &size );
if ( !error )
{
/* by default, indicates a `missing' glyph */
sbit->buffer = 0;
FT_Int temp;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Int xadvance, yadvance;
error = FT_Load_Glyph( face, gindex, sfam->type.flags | FT_LOAD_RENDER );
if ( !error )
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
{
FT_Int temp;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Int xadvance, yadvance;
FT_ERROR(( "%s: glyph loaded didn't return a bitmap!\n",
"ftc_snode_load" ));
goto BadGlyph;
}
/* check that our values fit into 8-bit containers! */
/* If this is not the case, our bitmap is too large */
/* and we will leave it as `missing' with sbit.buffer = 0 */
/* Check that our values fit into 8-bit containers! */
/* If this is not the case, our bitmap is too large */
/* and we will leave it as `missing' with sbit.buffer = 0 */
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
/* XXX: FIXME: add support for vertical layouts maybe */
/* horizontal advance in pixels */
xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
/* horizontal advance in pixels */
xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
if ( !CHECK_BYTE( bitmap->rows ) ||
!CHECK_BYTE( bitmap->width ) ||
!CHECK_CHAR( bitmap->pitch ) ||
!CHECK_CHAR( slot->bitmap_left ) ||
!CHECK_CHAR( slot->bitmap_top ) ||
!CHECK_CHAR( xadvance ) ||
!CHECK_CHAR( yadvance ) )
goto BadGlyph;
if ( CHECK_BYTE( bitmap->rows ) &&
CHECK_BYTE( bitmap->width ) &&
CHECK_CHAR( bitmap->pitch ) &&
CHECK_CHAR( slot->bitmap_left ) &&
CHECK_CHAR( slot->bitmap_top ) &&
CHECK_CHAR( xadvance ) &&
CHECK_CHAR( yadvance ) )
{
sbit->width = (FT_Byte)bitmap->width;
sbit->height = (FT_Byte)bitmap->rows;
sbit->pitch = (FT_Char)bitmap->pitch;
sbit->left = (FT_Char)slot->bitmap_left;
sbit->top = (FT_Char)slot->bitmap_top;
sbit->xadvance = (FT_Char)xadvance;
sbit->yadvance = (FT_Char)yadvance;
sbit->format = (FT_Byte)bitmap->pixel_mode;
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
sbit->width = (FT_Byte)bitmap->width;
sbit->height = (FT_Byte)bitmap->rows;
sbit->pitch = (FT_Char)bitmap->pitch;
sbit->left = (FT_Char)slot->bitmap_left;
sbit->top = (FT_Char)slot->bitmap_top;
sbit->xadvance = (FT_Char)xadvance;
sbit->yadvance = (FT_Char)yadvance;
sbit->format = (FT_Byte)bitmap->pixel_mode;
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
#if 0 /* this doesn't work well with embedded bitmaps !! */
/* copy the bitmap into a new buffer -- ignore error */
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
/* grab the bitmap when possible - this is a hack! */
if ( slot->flags & FT_GLYPH_OWN_BITMAP )
{
slot->flags &= ~FT_GLYPH_OWN_BITMAP;
sbit->buffer = bitmap->buffer;
}
else
#endif
{
/* copy the bitmap into a new buffer -- ignore error */
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
}
/* now, compute size */
if ( asize )
*asize = FT_ABS( sbit->pitch ) * sbit->height;
/* now, compute size */
if ( asize )
*asize = ABS( sbit->pitch ) * sbit->height;
} /* glyph loading successful */
} /* glyph dimensions ok */
} /* glyph loading successful */
/* ignore the errors that might have occurred -- */
/* we mark unloaded glyphs with `sbit.buffer == 0' */
/* and 'width == 255', 'height == 0' */
/* */
if ( error && error != FT_Err_Out_Of_Memory )
{
sbit->width = 255;
error = 0;
/* sbit->buffer == NULL too! */
}
/* ignore the errors that might have occurred -- */
/* we mark unloaded glyphs with `sbit.buffer == 0' */
/* and `width == 255', `height == 0' */
/* */
if ( error && error != FTC_Err_Out_Of_Memory )
{
BadGlyph:
sbit->width = 255;
sbit->height = 0;
sbit->buffer = NULL;
error = 0;
if ( asize )
*asize = 0;
}
return error;
}
FT_CALLBACK_DEF( FT_Error )
ftc_sbit_node_init( FTC_SBitNode snode,
FTC_GlyphQuery gquery,
FTC_Cache cache )
FT_EXPORT_DEF( FT_Error )
FTC_SNode_New( FTC_SNode *psnode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FT_Error error;
FT_Memory memory = cache->memory;
FT_Error error;
FTC_SNode snode = NULL;
FT_UInt gindex = gquery->gindex;
FTC_Family family = gquery->family;
FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
FT_UInt total;
ftc_glyph_node_init( FTC_GLYPH_NODE( snode ),
gquery->gindex,
FTC_GLYPH_FAMILY( gquery->query.family ) );
total = clazz->family_get_count( family, cache->manager );
if ( total == 0 || gindex >= total )
{
error = FT_Err_Invalid_Argument;
goto Exit;
}
error = ftc_sbit_node_load( snode,
cache->manager,
FTC_SBIT_FAMILY( FTC_QUERY( gquery )->family ),
gquery->gindex,
NULL );
if ( error )
ftc_glyph_node_done( FTC_GLYPH_NODE( snode ), cache );
if ( !FT_NEW( snode ) )
{
FT_UInt count, start;
start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
count = total - start;
if ( count > FTC_SBIT_ITEMS_PER_NODE )
count = FTC_SBIT_ITEMS_PER_NODE;
FTC_GNode_Init( FTC_GNODE( snode ), start, family );
snode->count = count;
error = ftc_snode_load( snode,
cache->manager,
gindex,
NULL );
if ( error )
{
FTC_SNode_Free( snode, cache );
snode = NULL;
}
}
Exit:
*psnode = snode;
return error;
}
FT_CALLBACK_DEF( FT_ULong )
ftc_sbit_node_weight( FTC_SBitNode snode )
FT_LOCAL_DEF( FT_Error )
ftc_snode_new( FTC_SNode *psnode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
FT_UInt count = gnode->item_count;
FTC_SBit sbit = snode->sbits;
FT_Int pitch;
FT_ULong size;
return FTC_SNode_New( psnode, gquery, cache );
}
FT_EXPORT_DEF( FT_ULong )
FTC_SNode_Weight( FTC_SNode snode )
{
FT_UInt count = snode->count;
FTC_SBit sbit = snode->sbits;
FT_Int pitch;
FT_ULong size;
FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
/* the node itself */
size = sizeof ( *snode );
/* the sbit records */
size += FTC_GLYPH_NODE( snode )->item_count * sizeof ( FTC_SBitRec );
for ( ; count > 0; count--, sbit++ )
{
if ( sbit->buffer )
@@ -285,22 +279,29 @@
}
FT_CALLBACK_DEF( FT_Bool )
ftc_sbit_node_compare( FTC_SBitNode snode,
FTC_SBitQuery squery,
FTC_Cache cache )
FT_LOCAL_DEF( FT_ULong )
ftc_snode_weight( FTC_SNode snode )
{
FTC_GlyphQuery gquery = FTC_GLYPH_QUERY( squery );
FTC_GlyphNode gnode = FTC_GLYPH_NODE( snode );
FT_Bool result;
return FTC_SNode_Weight( snode );
}
result = ftc_glyph_node_compare( gnode, gquery );
FT_EXPORT_DEF( FT_Bool )
FTC_SNode_Compare( FTC_SNode snode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FTC_GNode gnode = FTC_GNODE( snode );
FT_UInt gindex = gquery->gindex;
FT_Bool result;
result = FT_BOOL( gnode->family == gquery->family &&
(FT_UInt)( gindex - gnode->gindex ) < snode->count );
if ( result )
{
/* check if we need to load the glyph bitmap now */
FT_UInt gindex = gquery->gindex;
FTC_SBit sbit = snode->sbits + ( gindex - gnode->item_start );
FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex );
if ( sbit->buffer == NULL && sbit->width != 255 )
@@ -308,14 +309,11 @@
FT_ULong size;
/* yes, it's safe to ignore errors here */
ftc_sbit_node_load( snode,
cache->manager,
FTC_SBIT_FAMILY( FTC_QUERY( squery )->family ),
gindex,
&size );
cache->manager->cur_weight += size;
if ( !ftc_snode_load( snode, cache->manager,
gindex, &size ) )
{
cache->manager->cur_weight += size;
}
}
}
@@ -323,235 +321,13 @@
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SBITS FAMILIES *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_DEF( FT_Error )
ftc_sbit_family_init( FTC_SBitFamily sfam,
FTC_SBitQuery squery,
FTC_Cache cache )
FT_LOCAL_DEF( FT_Bool )
ftc_snode_compare( FTC_SNode snode,
FTC_GQuery gquery,
FTC_Cache cache )
{
FTC_Manager manager = cache->manager;
FT_Error error;
FT_Face face;
sfam->type = squery->type;
/* we need to compute "cquery.item_total" now */
error = FTC_Manager_Lookup_Face( manager,
squery->type.font.face_id,
&face );
if ( !error )
{
error = ftc_glyph_family_init( FTC_GLYPH_FAMILY( sfam ),
FTC_IMAGE_TYPE_HASH( &sfam->type ),
FTC_SBIT_ITEMS_PER_NODE,
face->num_glyphs,
FTC_GLYPH_QUERY( squery ),
cache );
}
return error;
return FTC_SNode_Compare( snode, gquery, cache );
}
FT_CALLBACK_DEF( FT_Bool )
ftc_sbit_family_compare( FTC_SBitFamily sfam,
FTC_SBitQuery squery )
{
FT_Bool result;
/* we need to set the "cquery.cset" field or our query for */
/* faster glyph comparisons in ftc_sbit_node_compare */
/* */
result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &sfam->type, &squery->type ) );
if ( result )
FTC_GLYPH_FAMILY_FOUND( sfam, squery );
return result;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** SBITS CACHE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_CALLBACK_TABLE_DEF
const FTC_Cache_ClassRec ftc_sbit_cache_class =
{
sizeof ( FTC_CacheRec ),
(FTC_Cache_InitFunc) ftc_cache_init,
(FTC_Cache_ClearFunc)ftc_cache_clear,
(FTC_Cache_DoneFunc) ftc_cache_done,
sizeof ( FTC_SBitFamilyRec ),
(FTC_Family_InitFunc) ftc_sbit_family_init,
(FTC_Family_CompareFunc)ftc_sbit_family_compare,
(FTC_Family_DoneFunc) ftc_glyph_family_done,
sizeof ( FTC_SBitNodeRec ),
(FTC_Node_InitFunc) ftc_sbit_node_init,
(FTC_Node_WeightFunc) ftc_sbit_node_weight,
(FTC_Node_CompareFunc)ftc_sbit_node_compare,
(FTC_Node_DoneFunc) ftc_sbit_node_done
};
/* documentation is in ftcsbits.h */
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_New( FTC_Manager manager,
FTC_SBitCache *acache )
{
return FTC_Manager_Register_Cache( manager,
&ftc_sbit_cache_class,
(FTC_Cache*)acache );
}
/* documentation is in ftcsbits.h */
#ifdef FTC_CACHE_USE_INLINE
#define GEN_CACHE_FAMILY_COMPARE( f, q, c ) \
ftc_sbit_family_compare( (FTC_SBitFamily)(f), (FTC_SBitQuery)(q) )
#define GEN_CACHE_NODE_COMPARE( n, q, c ) \
ftc_sbit_node_compare( (FTC_SBitNode)(n), (FTC_SBitQuery)(q), c )
#define GEN_CACHE_LOOKUP ftc_sbit_cache_lookup
#include "ftccache.i"
#else /* !FTC_CACHE_USE_INLINE */
#define ftc_sbit_cache_lookup ftc_cache_lookup
#endif /* !FTC_CACHE_USE_INLINE */
FT_EXPORT_DEF( FT_Error )
FTC_SBitCache_Lookup( FTC_SBitCache cache,
FTC_ImageType type,
FT_UInt gindex,
FTC_SBit *ansbit,
FTC_Node *anode )
{
FT_Error error;
FTC_SBitQueryRec squery;
FTC_SBitNode node;
/* other argument checks delayed to ftc_cache_lookup */
if ( !ansbit )
return FTC_Err_Invalid_Argument;
*ansbit = NULL;
if ( anode )
*anode = NULL;
squery.gquery.gindex = gindex;
squery.type = *type;
error = ftc_sbit_cache_lookup( FTC_CACHE( cache ),
FTC_QUERY( &squery ),
(FTC_Node*)&node );
if ( !error )
{
*ansbit = node->sbits + ( gindex - FTC_GLYPH_NODE( node )->item_start );
if ( anode )
{
*anode = FTC_NODE( node );
FTC_NODE( node )->ref_count++;
}
}
return error;
}
/* backwards-compatibility functions */
FT_EXPORT_DEF( FT_Error )
FTC_SBit_Cache_New( FTC_Manager manager,
FTC_SBit_Cache *acache )
{
return FTC_SBitCache_New( manager, (FTC_SBitCache*)acache );
}
FT_EXPORT_DEF( FT_Error )
FTC_SBit_Cache_Lookup( FTC_SBit_Cache cache,
FTC_Image_Desc* desc,
FT_UInt gindex,
FTC_SBit *ansbit )
{
FTC_ImageTypeRec type0;
if ( !desc )
return FTC_Err_Invalid_Argument;
type0.font = desc->font;
type0.flags = 0;
/* convert image type flags to load flags */
{
FT_UInt load_flags = FT_LOAD_DEFAULT;
FT_UInt type = desc->image_type;
/* determine load flags, depending on the font description's */
/* image type */
if ( ftc_image_format( type ) == ftc_image_format_bitmap )
{
if ( type & ftc_image_flag_monochrome )
load_flags |= FT_LOAD_MONOCHROME;
/* disable embedded bitmaps loading if necessary */
if ( type & ftc_image_flag_no_sbits )
load_flags |= FT_LOAD_NO_BITMAP;
}
else
{
/* we want an outline, don't load embedded bitmaps */
load_flags |= FT_LOAD_NO_BITMAP;
if ( type & ftc_image_flag_unscaled )
load_flags |= FT_LOAD_NO_SCALE;
}
/* always render glyphs to bitmaps */
load_flags |= FT_LOAD_RENDER;
if ( type & ftc_image_flag_unhinted )
load_flags |= FT_LOAD_NO_HINTING;
if ( type & ftc_image_flag_autohinted )
load_flags |= FT_LOAD_FORCE_AUTOHINT;
type0.flags = load_flags;
}
return FTC_SBitCache_Lookup( (FTC_SBitCache)cache,
&type0,
gindex,
ansbit,
NULL );
}
/* END */
/* END */
-394
View File
@@ -1,394 +0,0 @@
/***************************************************************************/
/* */
/* ftlru.c */
/* */
/* Simple LRU list-cache (body). */
/* */
/* Copyright 2000-2001, 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_LRU_H
#include FT_LIST_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftcerror.h"
FT_EXPORT_DEF( FT_Error )
FT_LruList_New( FT_LruList_Class clazz,
FT_UInt max_nodes,
FT_Pointer user_data,
FT_Memory memory,
FT_LruList *alist )
{
FT_Error error;
FT_LruList list;
if ( !alist || !clazz )
return FTC_Err_Invalid_Argument;
*alist = NULL;
if ( !FT_ALLOC( list, clazz->list_size ) )
{
/* initialize common fields */
list->clazz = clazz;
list->memory = memory;
list->max_nodes = max_nodes;
list->data = user_data;
if ( clazz->list_init )
{
error = clazz->list_init( list );
if ( error )
{
if ( clazz->list_done )
clazz->list_done( list );
FT_FREE( list );
}
}
*alist = list;
}
return error;
}
FT_EXPORT_DEF( void )
FT_LruList_Destroy( FT_LruList list )
{
FT_Memory memory;
FT_LruList_Class clazz;
if ( !list )
return;
memory = list->memory;
clazz = list->clazz;
FT_LruList_Reset( list );
if ( clazz->list_done )
clazz->list_done( list );
FT_FREE( list );
}
FT_EXPORT_DEF( void )
FT_LruList_Reset( FT_LruList list )
{
FT_LruNode node;
FT_LruList_Class clazz;
FT_Memory memory;
if ( !list )
return;
node = list->nodes;
clazz = list->clazz;
memory = list->memory;
while ( node )
{
FT_LruNode next = node->next;
if ( clazz->node_done )
clazz->node_done( node, list->data );
FT_FREE( node );
node = next;
}
list->nodes = NULL;
list->num_nodes = 0;
}
FT_EXPORT_DEF( FT_Error )
FT_LruList_Lookup( FT_LruList list,
FT_LruKey key,
FT_LruNode *anode )
{
FT_Error error = 0;
FT_LruNode node, *pnode;
FT_LruList_Class clazz;
FT_LruNode* plast;
FT_LruNode result = NULL;
FT_Memory memory;
if ( !list || !key || !anode )
return FTC_Err_Invalid_Argument;
pnode = &list->nodes;
plast = pnode;
node = NULL;
clazz = list->clazz;
memory = list->memory;
if ( clazz->node_compare )
{
for (;;)
{
node = *pnode;
if ( node == NULL )
break;
if ( clazz->node_compare( node, key, list->data ) )
break;
plast = pnode;
pnode = &(*pnode)->next;
}
}
else
{
for (;;)
{
node = *pnode;
if ( node == NULL )
break;
if ( node->key == key )
break;
plast = pnode;
pnode = &(*pnode)->next;
}
}
if ( node )
{
/* move element to top of list */
if ( list->nodes != node )
{
*pnode = node->next;
node->next = list->nodes;
list->nodes = node;
}
result = node;
goto Exit;
}
/* since we haven't found the relevant element in our LRU list,
* we're going to "create" a new one.
*
* the following code is a bit special, because it tries to handle
* out-of-memory conditions (OOM) in an intelligent way.
*
* more precisely, if not enough memory is available to create a
* new node or "flush" an old one, we need to remove the oldest
* elements from our list, and try again. since several tries may
* be necessary, a loop is needed
*
* this loop will only exit when:
*
* - a new node was succesfully created, or an old node flushed
* - an error other than FT_Err_Out_Of_Memory is detected
* - the list of nodes is empty, and it isn't possible to create
* new nodes
*
* on each unsucesful attempt, one node will be removed from the list
*
*/
{
FT_Int drop_last = ( list->max_nodes > 0 &&
list->num_nodes >= list->max_nodes );
for (;;)
{
node = NULL;
/* when "drop_last" is true, we should free the last node in
* the list to make room for a new one. note that we re-use
* its memory block to save allocation calls.
*/
if ( drop_last )
{
/* find the last node in the list
*/
pnode = &list->nodes;
node = *pnode;
if ( node == NULL )
{
FT_ASSERT( list->nodes == 0 );
error = FT_Err_Out_Of_Memory;
goto Exit;
}
FT_ASSERT( list->num_nodes > 0 );
while ( node->next )
{
pnode = &node->next;
node = *pnode;
}
/* remove it from the list, and try to "flush" it. doing this will
* save a significant number of dynamic allocations compared to
* a classic destroy/create cycle
*/
*pnode = NULL;
list->num_nodes -= 1;
if ( clazz->node_flush )
{
error = clazz->node_flush( node, key, list->data );
if ( !error )
goto Success;
/* note that if an error occured during the flush, we need to
* finalize it since it is potentially in incomplete state.
*/
}
/* we finalize, but do not destroy the last node, we
* simply re-use its memory block !
*/
if ( clazz->node_done )
clazz->node_done( node, list->data );
FT_MEM_ZERO( node, clazz->node_size );
}
else
{
/* try to allocate a new node when "drop_last" is not TRUE
* this usually happens on the first pass, when the LRU list
* is not already full.
*/
if ( FT_ALLOC( node, clazz->node_size ) )
goto Fail;
}
FT_ASSERT( node != NULL );
node->key = key;
error = clazz->node_init( node, key, list->data );
if ( error )
{
if ( clazz->node_done )
clazz->node_done( node, list->data );
FT_FREE( node );
goto Fail;
}
Success:
result = node;
node->next = list->nodes;
list->nodes = node;
list->num_nodes++;
goto Exit;
Fail:
if ( error != FT_Err_Out_Of_Memory )
goto Exit;
drop_last = 1;
continue;
}
}
Exit:
*anode = result;
return error;
}
FT_EXPORT_DEF( void )
FT_LruList_Remove( FT_LruList list,
FT_LruNode node )
{
FT_LruNode *pnode;
if ( !list || !node )
return;
pnode = &list->nodes;
for (;;)
{
if ( *pnode == node )
{
FT_Memory memory = list->memory;
FT_LruList_Class clazz = list->clazz;
*pnode = node->next;
node->next = NULL;
if ( clazz->node_done )
clazz->node_done( node, list->data );
FT_FREE( node );
list->num_nodes--;
break;
}
pnode = &(*pnode)->next;
}
}
FT_EXPORT_DEF( void )
FT_LruList_Remove_Selection( FT_LruList list,
FT_LruNode_SelectFunc select_func,
FT_Pointer select_data )
{
FT_LruNode *pnode, node;
FT_LruList_Class clazz;
FT_Memory memory;
if ( !list || !select_func )
return;
memory = list->memory;
clazz = list->clazz;
pnode = &list->nodes;
for (;;)
{
node = *pnode;
if ( node == NULL )
break;
if ( select_func( node, select_data, list->data ) )
{
*pnode = node->next;
node->next = NULL;
if ( clazz->node_done )
clazz->node_done( node, list );
FT_FREE( node );
}
else
pnode = &(*pnode)->next;
}
}
/* END */
+32 -32
View File
@@ -3,7 +3,7 @@
#
# Copyright 2000, 2001 by
# Copyright 2000, 2001, 2003, 2004 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -15,66 +15,66 @@
# Cache driver directory
#
CACHE_DIR := $(SRC_)cache
CACHE_DIR_ := $(CACHE_DIR)$(SEP)
CACHE_H_DIR := $(PUBLIC_)cache
CACHE_H_DIR_ := $(CACHE_H_DIR)$(SEP)
CACHE_DIR := $(SRC_DIR)/cache
CACHE_H_DIR := $(PUBLIC_DIR)/cache
# compilation flags for the driver
#
Cache_COMPILE := $(FT_COMPILE) $I$(CACHE_DIR)
CACHE_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(CACHE_DIR))
# Cache driver sources (i.e., C files)
#
Cache_DRV_SRC := $(CACHE_DIR_)ftlru.c \
$(CACHE_DIR_)ftcmanag.c \
$(CACHE_DIR_)ftccache.c \
$(CACHE_DIR_)ftcglyph.c \
$(CACHE_DIR_)ftcsbits.c \
$(CACHE_DIR_)ftcimage.c \
$(CACHE_DIR_)ftccmap.c
CACHE_DRV_SRC := $(CACHE_DIR)/ftcmru.c \
$(CACHE_DIR)/ftcmanag.c \
$(CACHE_DIR)/ftcbasic.c \
$(CACHE_DIR)/ftccache.c \
$(CACHE_DIR)/ftcglyph.c \
$(CACHE_DIR)/ftcsbits.c \
$(CACHE_DIR)/ftcimage.c \
$(CACHE_DIR)/ftccmap.c
# Cache driver headers
#
Cache_DRV_H := $(CACHE_H_DIR_)ftlru.h \
$(CACHE_H_DIR_)ftcmanag.h \
$(CACHE_H_DIR_)ftcglyph.h \
$(CACHE_H_DIR_)ftcimage.h \
$(CACHE_DIR_)ftcerror.h
CACHE_DRV_H := $(CACHE_H_DIR)/ftcmru.h \
$(CACHE_H_DIR)/ftcmanag.h \
$(CACHE_H_DIR)/ftcglyph.h \
$(CACHE_H_DIR)/ftcimage.h \
$(CACHE_H_DIR)/ftccmap.h \
$(CACHE_DIR)/ftcerror.h \
$(CACHE_DIR)/ftccback.h
# Cache driver object(s)
#
# Cache_DRV_OBJ_M is used during `multi' builds.
# Cache_DRV_OBJ_S is used during `single' builds.
# CACHE_DRV_OBJ_M is used during `multi' builds.
# CACHE_DRV_OBJ_S is used during `single' builds.
#
Cache_DRV_OBJ_M := $(Cache_DRV_SRC:$(CACHE_DIR_)%.c=$(OBJ_)%.$O)
Cache_DRV_OBJ_S := $(OBJ_)ftcache.$O
CACHE_DRV_OBJ_M := $(CACHE_DRV_SRC:$(CACHE_DIR)/%.c=$(OBJ_DIR)/%.$O)
CACHE_DRV_OBJ_S := $(OBJ_DIR)/ftcache.$O
# Cache driver source file for single build
#
Cache_DRV_SRC_S := $(CACHE_DIR_)ftcache.c
CACHE_DRV_SRC_S := $(CACHE_DIR)/ftcache.c
# Cache driver - single object
#
$(Cache_DRV_OBJ_S): $(Cache_DRV_SRC_S) $(Cache_DRV_SRC) \
$(FREETYPE_H) $(Cache_DRV_H)
$(Cache_COMPILE) $T$@ $(Cache_DRV_SRC_S)
$(CACHE_DRV_OBJ_S): $(CACHE_DRV_SRC_S) $(CACHE_DRV_SRC) \
$(FREETYPE_H) $(CACHE_DRV_H)
$(CACHE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(CACHE_DRV_SRC_S))
# Cache driver - multiple objects
#
$(OBJ_)%.$O: $(CACHE_DIR_)%.c $(FREETYPE_H) $(Cache_DRV_H)
$(Cache_COMPILE) $T$@ $<
$(OBJ_DIR)/%.$O: $(CACHE_DIR)/%.c $(FREETYPE_H) $(CACHE_DRV_H)
$(CACHE_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver object lists
#
DRV_OBJS_S += $(Cache_DRV_OBJ_S)
DRV_OBJS_M += $(Cache_DRV_OBJ_M)
DRV_OBJS_S += $(CACHE_DRV_OBJ_S)
DRV_OBJS_M += $(CACHE_DRV_OBJ_M)
# EOF
# EOF
+2 -2
View File
@@ -4,7 +4,7 @@
/* */
/* FreeType OpenType driver component (body only). */
/* */
/* Copyright 1996-2001 by */
/* Copyright 1996-2001, 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -26,4 +26,4 @@
#include "cffgload.c"
#include "cffcmap.c"
/* END */
/* END */
+31 -31
View File
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,6 +19,8 @@
#include "cffcmap.h"
#include "cffload.h"
#include "cfferrs.h"
/*************************************************************************/
/*************************************************************************/
@@ -36,9 +38,8 @@
CFF_Encoding encoding = &cff->encoding;
cmap->count = encoding->count;
cmap->gids = encoding->codes;
return 0;
}
@@ -46,7 +47,6 @@
FT_CALLBACK_DEF( void )
cff_cmap_encoding_done( CFF_CMapStd cmap )
{
cmap->count = 0;
cmap->gids = NULL;
}
@@ -58,9 +58,9 @@
FT_UInt result = 0;
if ( char_code < cmap->count )
if ( char_code < 256 )
result = cmap->gids[char_code];
return result;
}
@@ -71,27 +71,27 @@
{
FT_UInt result = 0;
FT_UInt32 char_code = *pchar_code;
*pchar_code = 0;
if ( char_code < cmap->count )
if ( char_code < 255 )
{
FT_UInt code = (FT_UInt)(char_code + 1);
for (;;)
{
if ( code >= cmap->count )
if ( code >= 256 )
break;
result = cmap->gids[code];
if ( result != 0 )
{
*pchar_code = code;
break;
}
code++;
}
}
@@ -125,34 +125,34 @@
{
FT_UInt32 u1 = ((CFF_CMapUniPair)pair1)->unicode;
FT_UInt32 u2 = ((CFF_CMapUniPair)pair2)->unicode;
if ( u1 < u2 )
return -1;
if ( u1 > u2 )
return +1;
return 0;
}
}
FT_CALLBACK_DEF( FT_Error )
cff_cmap_unicode_init( CFF_CMapUnicode cmap )
{
FT_Error error;
FT_UInt count;
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
FT_Memory memory = FT_FACE_MEMORY( face );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
PSNames_Service psnames = (PSNames_Service)cff->psnames;
FT_Error error;
FT_UInt count;
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap );
FT_Memory memory = FT_FACE_MEMORY( face );
CFF_Font cff = (CFF_Font)face->extra.data;
CFF_Charset charset = &cff->charset;
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames;
cmap->num_pairs = 0;
cmap->pairs = NULL;
count = (FT_UInt)face->root.num_glyphs;
count = cff->num_glyphs;
if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
{
@@ -164,12 +164,12 @@
pair = cmap->pairs;
for ( n = 0; n < count; n++ )
{
FT_UInt sid = charset->sids[n];
FT_UInt sid = charset->sids[n];
const char* gname;
gname = cff_index_get_sid_string( &cff->string_index, sid, psnames );
/* build unsorted pair table by matching glyph names */
if ( gname )
{
@@ -181,7 +181,7 @@
pair->gindex = n;
pair++;
}
FT_FREE( gname );
}
}
@@ -191,7 +191,7 @@
{
/* there are no unicode characters in here! */
FT_FREE( cmap->pairs );
error = FT_Err_Invalid_Argument;
error = CFF_Err_Invalid_Argument;
}
else
{
@@ -200,7 +200,7 @@
if ( new_count != count && new_count < count / 2 )
{
(void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
error = 0;
error = CFF_Err_Ok;
}
/* sort the pairs table to allow efficient binary searches */
@@ -223,7 +223,7 @@
FT_Face face = FT_CMAP_FACE( cmap );
FT_Memory memory = FT_FACE_MEMORY( face );
FT_FREE( cmap->pairs );
cmap->num_pairs = 0;
}
@@ -323,4 +323,4 @@
};
/* END */
/* END */
+2 -3
View File
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
/* Copyright 2002 by */
/* Copyright 2002, 2003 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -38,7 +38,6 @@ FT_BEGIN_HEADER
typedef struct CFF_CMapStdRec_
{
FT_CMapRec cmap;
FT_UInt count;
FT_UShort* gids; /* up to 256 elements */
} CFF_CMapStdRec;
@@ -85,4 +84,4 @@ FT_END_HEADER
#endif /* __CFFCMAP_H__ */
/* END */
/* END */
+128 -71
View File
@@ -4,7 +4,7 @@
/* */
/* OpenType font driver implementation (body). */
/* */
/* Copyright 1996-2001, 2002 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,14 +22,19 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_IDS_H
#include FT_INTERNAL_POSTSCRIPT_NAMES_H
#include FT_SERVICE_POSTSCRIPT_CMAPS_H
#include FT_SERVICE_POSTSCRIPT_INFO_H
#include FT_SERVICE_TT_CMAP_H
#include "cffdrivr.h"
#include "cffgload.h"
#include "cffload.h"
#include "cffcmap.h"
#include "cfferrs.h"
#include FT_SERVICE_XFREE86_NAME_H
#include FT_SERVICE_GLYPH_DICT_H
/*************************************************************************/
/* */
@@ -165,7 +170,7 @@
/* glyph_index :: The index of the glyph in the font file. */
/* */
/* load_flags :: A flag indicating what to load for this glyph. The */
/* FTLOAD_??? constants can be used to control the */
/* FT_LOAD_??? constants can be used to control the */
/* glyph loading process (e.g., whether the outline */
/* should be scaled, whether to load bitmaps or not, */
/* whether to hint the outline, etc). */
@@ -196,7 +201,7 @@
if ( size )
{
/* these two object must have the same parent */
if ( size->face != slot->root.face )
if ( size->root.face != slot->root.face )
return CFF_Err_Invalid_Face_Handle;
}
@@ -210,17 +215,10 @@
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** C H A R A C T E R M A P P I N G S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*
* GLYPH DICT SERVICE
*
*/
static FT_Error
cff_get_glyph_name( CFF_Face face,
@@ -228,21 +226,19 @@
FT_Pointer buffer,
FT_UInt buffer_max )
{
CFF_Font font = (CFF_Font)face->extra.data;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_String* gname;
FT_UShort sid;
PSNames_Service psnames;
FT_Error error;
CFF_Font font = (CFF_Font)face->extra.data;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_String* gname;
FT_UShort sid;
FT_Service_PsCMaps psnames;
FT_Error error;
psnames = (PSNames_Service)FT_Get_Module_Interface(
face->root.driver->root.library, "psnames" );
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
if ( !psnames )
{
FT_ERROR(( "cff_get_glyph_name:" ));
FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" ));
FT_ERROR(( " " ));
FT_ERROR(( " without the `PSNames' module\n" ));
error = CFF_Err_Unknown_File_Format;
@@ -255,7 +251,7 @@
/* now, lookup the name itself */
gname = cff_index_get_sid_string( &font->string_index, sid, psnames );
if ( buffer_max > 0 )
if ( gname && buffer_max > 0 )
{
FT_UInt len = (FT_UInt)ft_strlen( gname );
@@ -267,7 +263,7 @@
((FT_Byte*)buffer)[len] = 0;
}
FT_FREE ( gname );
FT_FREE( gname );
error = CFF_Err_Ok;
Exit:
@@ -275,43 +271,26 @@
}
/*************************************************************************/
/* */
/* <Function> */
/* cff_get_name_index */
/* */
/* <Description> */
/* Uses the psnames module and the CFF font's charset to to return a */
/* a given glyph name's glyph index. */
/* */
/* <Input> */
/* face :: A handle to the source face object. */
/* */
/* glyph_name :: The glyph name. */
/* */
/* <Return> */
/* Glyph index. 0 means `undefined character code'. */
/* */
static FT_UInt
cff_get_name_index( CFF_Face face,
FT_String* glyph_name )
{
CFF_Font cff;
CFF_Charset charset;
PSNames_Service psnames;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_String* name;
FT_UShort sid;
FT_UInt i;
FT_Int result;
CFF_Font cff;
CFF_Charset charset;
FT_Service_PsCMaps psnames;
FT_Memory memory = FT_FACE_MEMORY( face );
FT_String* name;
FT_UShort sid;
FT_UInt i;
FT_Int result;
cff = (CFF_FontRec *)face->extra.data;
charset = &cff->charset;
psnames = (PSNames_Service)FT_Get_Module_Interface(
face->root.driver->root.library, "psnames" );
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
if ( !psnames )
return 0;
for ( i = 0; i < cff->num_glyphs; i++ )
{
@@ -335,6 +314,77 @@
}
static const FT_Service_GlyphDictRec cff_service_glyph_dict =
{
(FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
(FT_GlyphDict_NameIndexFunc)cff_get_name_index,
};
/*
* POSTSCRIPT INFO SERVICE
*
*/
static FT_Int
cff_ps_has_glyph_names( FT_Face face )
{
return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
}
static const FT_Service_PsInfoRec cff_service_ps_info =
{
(PS_GetFontInfoFunc) NULL, /* unsupported with CFF fonts */
(PS_HasGlyphNamesFunc)cff_ps_has_glyph_names
};
/*
* TT CMAP INFO
*
* If the charmap is a synthetic Unicode encoding cmap or
* a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
* service defined in SFNT module.
*
* Otherwise call the service function in the sfnt module.
*
*/
static FT_Error
cff_get_cmap_info( FT_CharMap charmap,
TT_CMapInfo *cmap_info )
{
FT_CMap cmap = FT_CMAP( charmap );
FT_Error error = CFF_Err_Ok;
cmap_info->language = 0;
if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
cmap->clazz != &cff_cmap_unicode_class_rec )
{
FT_Face face = FT_CMAP_FACE( cmap );
FT_Library library = FT_FACE_LIBRARY( face );
FT_Module sfnt = FT_Get_Module( library, "sfnt" );
FT_Service_TTCMaps service =
(FT_Service_TTCMaps)ft_module_get_service( sfnt,
FT_SERVICE_ID_TT_CMAP );
if ( service && service->get_cmap_info )
error = service->get_cmap_info( charmap, cmap_info );
}
return error;
}
static const FT_Service_TTCMapsRec cff_service_get_cmap_info =
{
(TT_CMap_Info_GetFunc)cff_get_cmap_info
};
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
@@ -347,24 +397,31 @@
/*************************************************************************/
/*************************************************************************/
static const FT_ServiceDescRec cff_services[] =
{
{ FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF },
{ FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info },
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
{ FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict },
#endif
{ FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info },
{ NULL, NULL }
};
static FT_Module_Interface
cff_get_interface( CFF_Driver driver,
const char* module_interface )
{
FT_Module sfnt;
FT_Module sfnt;
FT_Module_Interface result;
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
result = ft_service_list_lookup( cff_services, module_interface );
if ( result != NULL )
return result;
if ( ft_strcmp( (const char*)module_interface, "glyph_name" ) == 0 )
return (FT_Module_Interface)cff_get_glyph_name;
if ( ft_strcmp( (const char*)module_interface, "name_index" ) == 0 )
return (FT_Module_Interface)cff_get_name_index;
#endif
/* we simply pass our request to the `sfnt' module */
/* we pass our request to the `sfnt' module */
sfnt = FT_Get_Module( driver->root.root.library, "sfnt" );
return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
@@ -378,9 +435,9 @@
{
/* begin with the FT_Module_Class fields */
{
ft_module_font_driver |
ft_module_driver_scalable |
ft_module_driver_has_hinter,
FT_MODULE_FONT_DRIVER |
FT_MODULE_DRIVER_SCALABLE |
FT_MODULE_DRIVER_HAS_HINTER,
sizeof( CFF_DriverRec ),
"cff",
@@ -396,7 +453,7 @@
/* now the specific driver fields */
sizeof( TT_FaceRec ),
sizeof( FT_SizeRec ),
sizeof( CFF_SizeRec ),
sizeof( CFF_GlyphSlotRec ),
(FT_Face_InitFunc) cff_face_init,
@@ -417,4 +474,4 @@
};
/* END */
/* END */
+1 -1
View File
@@ -36,4 +36,4 @@ FT_END_HEADER
#endif /* __CFFDRIVER_H__ */
/* END */
/* END */

Some files were not shown because too many files have changed in this diff Show More