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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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 */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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 ---
|
||||
|
||||
@@ -144,4 +144,4 @@
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -61,4 +61,4 @@ FT_END_HEADER
|
||||
#endif /* __AHANGLES_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -37,4 +37,4 @@
|
||||
|
||||
#endif /* __AHERRORS_H__ */
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -92,4 +92,4 @@ FT_END_HEADER
|
||||
#endif /* __AHGLYPH_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -72,4 +72,4 @@ FT_END_HEADER
|
||||
#endif /* __AHHINT_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -58,4 +58,4 @@ FT_END_HEADER
|
||||
#endif /* __AHLOADER_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -39,4 +39,4 @@ FT_END_HEADER
|
||||
#endif /* __AHMODULE_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
#include "ahmodule.c"
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -75,4 +75,4 @@ print_arctan( 8 )
|
||||
print
|
||||
|
||||
|
||||
# END
|
||||
# END
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -118,4 +118,4 @@
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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, ®istry );
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
@@ -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,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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -243,4 +243,4 @@
|
||||
}
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,4 +158,4 @@
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -214,4 +214,4 @@
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
+336
-163
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -91,4 +91,4 @@
|
||||
#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -393,4 +393,4 @@
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
+820
-193
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -128,4 +128,4 @@
|
||||
|
||||
ft_object_create( clazz, pathname, FT_OBJECT_P(astream) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -300,4 +300,4 @@
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -327,4 +327,4 @@
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -31,4 +31,4 @@ THE SOFTWARE.
|
||||
#include "bdfdrivr.c"
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -41,4 +41,4 @@
|
||||
#endif /* __BDFERROR_H__ */
|
||||
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -20,4 +20,4 @@ OBJS=bdf.obj
|
||||
all : $(OBJS)
|
||||
library [--.lib]freetype.olb $(OBJS)
|
||||
|
||||
# EOF
|
||||
# EOF
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
+3
-4
@@ -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
|
||||
|
||||
Vendored
+5
-5
@@ -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 */
|
||||
|
||||
Vendored
+425
@@ -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 */
|
||||
Vendored
+365
-568
File diff suppressed because it is too large
Load Diff
Vendored
-157
@@ -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 */
|
||||
Vendored
+82
@@ -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 */
|
||||
Vendored
+119
-291
@@ -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 */
|
||||
|
||||
Vendored
+1
-1
@@ -37,4 +37,4 @@
|
||||
|
||||
#endif /* __FTCERROR_H__ */
|
||||
|
||||
/* END */
|
||||
/* END */
|
||||
|
||||
Vendored
+108
-45
@@ -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 */
|
||||
|
||||
Vendored
+52
-306
@@ -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 */
|
||||
|
||||
Vendored
+307
-425
@@ -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 */
|
||||
|
||||
Vendored
+355
@@ -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 */
|
||||
Vendored
+179
-403
@@ -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 */
|
||||
|
||||
Vendored
-394
@@ -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 */
|
||||
Vendored
+32
-32
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user