* src/sfnt/Jamfile: removing "ttcmap" from the list of sources

* src/cache/*, include/freetype/cache/*: fixing a bug after heavy
        testing. The current sources are now "release candidates" for the
        final version of the cache sub-system

        * Jamfile: updating "refdoc" target, and adding "autohint" to the
        list of modules to build. Both the autohinter and autofitter will be
        built by default. But which one will be used is determined by
        the content of "ftmodule.h"

        * src/autofit/*: much updates, but the code is still buggy as hell.
        Aargh..
This commit is contained in:
David Turner 2004-02-01 16:59:06 +00:00
parent 5972e9abf8
commit f546bacdcf
23 changed files with 2354 additions and 2727 deletions

View File

@ -1,3 +1,19 @@
2004-02-01 David Turner <david@freetype.org>
* src/sfnt/Jamfile: removing "ttcmap" from the list of sources
* src/cache/*, include/freetype/cache/*: fixing a bug after heavy
testing. The current sources are now "release candidates" for the
final version of the cache sub-system
* Jamfile: updating "refdoc" target, and adding "autohint" to the
list of modules to build. Both the autohinter and autofitter will be
built by default. But which one will be used is determined by
the content of "ftmodule.h"
* src/autofit/*: much updates, but the code is still buggy as hell.
Aargh..
2004-01-31 Werner Lemberg <wl@gnu.org>
* src/cff/cffgload.c (cff_operator_seac): Fix magnitude of

View File

@ -147,7 +147,7 @@ if $(DEBUG_HINTER)
actions RefDoc
{
python $(FT2_SRC)/tools/docmaker/docmaker.py --prefix=ft2 --title=FreeType-2.1.5 --output=$(DOC_DIR) $(FT2_INCLUDE)/freetype/*.h $(FT2_INCLUDE)/freetype/config/*.h $(FT2_INCLUDE)/freetype/cache/*.h
python $(FT2_SRC)/tools/docmaker/docmaker.py --prefix=ft2 --title=FreeType-2.1.8 --output=$(DOC_DIR) $(FT2_INCLUDE)/freetype/*.h $(FT2_INCLUDE)/freetype/config/*.h $(FT2_INCLUDE)/freetype/cache/*.h
}
RefDoc refdoc ;

View File

@ -197,6 +197,7 @@ FT_BEGIN_HEADER
FTC_FaceID face_id );
#ifdef FTC_INLINE
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
FT_BEGIN_STMNT \
@ -249,6 +250,15 @@ FT_BEGIN_HEADER
*(FTC_Node*)&(node) = _node; \
FT_END_STMNT
#else /* !FTC_INLINE */
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
FT_BEGIN_STMNT \
error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query, \
(FTC_Node*)&(node) ); \
FT_END_STMNT
#endif /* !FTC_INLINE */
/* */

View File

@ -255,38 +255,39 @@ FT_BEGIN_HEADER
FTC_Node *anode );
#ifdef FTC_INLINE
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
gindex, query, node, error ) \
FT_BEGIN_STMNT \
FTC_GCache _gcache = FTC_GCACHE( cache ); \
FTC_Family _family; \
FTC_GQuery _gquery = (FTC_GQuery)( query ); \
FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
\
\
_gquery->gindex = (gindex); \
\
FTC_MRULIST_LOOP( &_gcache->families, _family ) \
{ \
if ( _fcompare( (FTC_MruNode)_family, _gquery ) ) \
{ \
_gquery->family = _family; \
goto _FamilyFound; \
} \
} \
FTC_MRULIST_LOOP_END(); \
\
error = FTC_MruList_New( &_gcache->families, \
_gquery, \
(FTC_MruNode*)&_gquery->family ); \
FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \
_gquery->family, error ); \
if ( !error ) \
{ \
_FamilyFound: \
FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \
} \
FT_END_STMNT
/* */
#else /* !FTC_INLINE */
#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \
gindex, query, node, error ) \
FT_BEGIN_STMNT \
error = FTC_GCache_Lookup( FTC_GCACHE(cache), hash, gindex, FTC_GQUERY(query), \
(FTC_Node*) &(node) ); \
FT_END_STMNT
#endif /* !FTC_INLINE */
FT_END_HEADER

View File

@ -168,14 +168,15 @@ FT_BEGIN_HEADER
#ifdef FTC_INLINE
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \
FT_BEGIN_STMNT \
FTC_MruNode_CompareFunc _compare = (list)->clazz.node_compare; \
FTC_MruNode* _pfirst = &(list)->nodes; \
FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \
FTC_MruNode _first, _node; \
\
\
error = 0; \
_first = (list)->nodes; \
_first = *(_pfirst); \
_node = NULL; \
\
if ( _first ) \
@ -185,8 +186,11 @@ FT_BEGIN_HEADER
{ \
if ( _compare( _node, (key) ) ) \
{ \
if ( _node != _first ) \
FTC_MruNode_Up( _pfirst, _node ); \
\
*(FTC_MruNode*)&(node) = _node; \
goto _Ok; \
goto _MruOk; \
} \
_node = _node->next; \
\
@ -194,13 +198,16 @@ FT_BEGIN_HEADER
} \
\
error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \
_Ok: \
_MruOk: \
; \
FT_END_STMNT
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
#else /* !FTC_INLINE */
#define FTC_MRULIST_LOOKUP_CMP( list, key, node, error ) \
#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) )
#endif /* !FTC_INLINE */

View File

@ -5,7 +5,7 @@ SubDir FT2_TOP src autofit ;
if $(FT2_MULTI)
{
_sources = afangles afglobal afhints aflatin ;
_sources = afangles afglobal afhints aflatin afloader afmodule ;
}
else
{

View File

@ -860,7 +860,7 @@
{
touch_flag = AF_FLAG_TOUCH_Y;
for ( point = points; point < point_limit; points++ )
for ( point = points; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->oy;

View File

@ -374,12 +374,28 @@
axis = & metrics->axis[ dim ];
if ( axis->scale == scale && axis->delta == delta )
if ( axis->org_scale == scale && axis->org_delta == delta )
return;
axis->org_scale = scale;
axis->org_delta = delta;
/* XXX: TODO: Correct Y and X scale according to Chester rules
*/
axis->scale = scale;
axis->delta = delta;
if ( dim == AF_DIMENSION_HORZ )
{
metrics->scaler.x_scale = scale;
metrics->scaler.x_delta = delta;
}
else
{
metrics->scaler.y_scale = scale;
metrics->scaler.y_delta = delta;
}
/* scale the standard widths
*/
for ( nn = 0; nn < axis->width_count; nn++ )
@ -419,6 +435,8 @@
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler )
{
metrics->scaler = scaler[0];
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
}
@ -1120,14 +1138,13 @@
static FT_Error
af_latin_hints_init( AF_GlyphHints hints,
AF_Scaler scaler,
FT_Outline* outline,
AF_LatinMetrics metrics )
{
FT_Error error;
FT_Render_Mode mode;
error = af_glyph_hints_reset( hints, scaler, outline );
error = af_glyph_hints_reset( hints, &metrics->scaler, outline );
if (error)
goto Exit;
@ -1135,7 +1152,7 @@
/* compute flags depending on render mode, etc...
*/
mode = scaler->render_mode;
mode = metrics->scaler.render_mode;
/* we snap the width of vertical stems for the monochrome and
* horizontal LCD rendering targets only.
@ -1716,12 +1733,10 @@
static FT_Error
af_latin_hints_apply( AF_GlyphHints hints,
AF_Scaler scaler,
AF_LatinMetrics metrics )
{
AF_Dimension dim;
FT_UNUSED( scaler );
FT_UNUSED( metrics );
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )

View File

@ -81,6 +81,9 @@ FT_BEGIN_HEADER
FT_UInt blue_count;
AF_LatinBlueRec blues[ AF_LATIN_BLUE_MAX ];
FT_Fixed org_scale;
FT_Pos org_delta;
} AF_LatinAxisRec, *AF_LatinAxis;
@ -89,6 +92,7 @@ FT_BEGIN_HEADER
AF_ScriptMetricsRec root;
FT_UInt units_per_em;
AF_LatinAxisRec axis[ AF_DIMENSION_MAX ];
AF_ScalerRec scaler;
} AF_LatinMetricsRec, *AF_LatinMetrics;

View File

@ -3,13 +3,27 @@
#include "afglobal.h"
#include "aflatin.h"
FT_LOCAL_DEF( void )
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;
}
@ -19,15 +33,13 @@
{
FT_Error error = 0;
FT_ZERO( loader );
loader->face = face;
loader->gloader = face->slot->internal->loader;
loader->gloader = face->glyph->internal->loader;
loader->globals = (AF_FaceGlobals) face->autohint.data;
if ( loader->globals == NULL )
{
error = af_face_globals_new( &face, &loader->globals );
error = af_face_globals_new( face, &loader->globals );
if ( !error )
{
face->autohint.data = (FT_Pointer) loader->globals;
@ -41,14 +53,16 @@
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
loader->face = face;
loader->face = NULL;
loader->globals = NULL;
FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL;
}
static FT_Error
af_hinter_load_g( AF_Loader loader,
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index,
FT_Int32 load_flags,
@ -138,40 +152,37 @@
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */
error = metrics->clazz->script_hints_init( hints, scaler,
error = metrics->clazz->script_hints_init( hints,
&gloader->current.outline,
metrics );
if ( error )
goto Exit;
/* apply the hints */
error = metrics->clazz->script_hints_apply( hints, scaler,
metrics->clazz->script_hints_apply( hints,
&gloader->current.outline,
metrics );
if ( error )
goto Exit;
/* 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_Edge edge1 = outline->vert_edges; /* leftmost edge */
AF_Edge edge2 = edge1 +
outline->num_vedges - 1; /* rightmost edge */
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 = hinter->pp2.x;
old_advance = loader->pp2.x;
old_rsb = old_advance - edge2->opos;
old_lsb = edge1->opos;
new_lsb = edge1->pos;
hinter->pp1.x = FT_PIX_ROUND( new_lsb - old_lsb );
hinter->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
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 ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 )
hinter->pp2.x += 64;
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
loader->pp2.x += 64;
#endif
}
@ -213,8 +224,8 @@
/* each iteration */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
pp1 = hinter->pp1;
pp2 = hinter->pp2;
pp1 = loader->pp1;
pp2 = loader->pp2;
num_base_points = gloader->base.outline.n_points;
@ -228,13 +239,13 @@
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
{
pp1 = hinter->pp1;
pp2 = hinter->pp2;
pp1 = loader->pp1;
pp2 = loader->pp2;
}
else
{
hinter->pp1 = pp1;
hinter->pp2 = pp2;
loader->pp1 = pp1;
loader->pp2 = pp2;
}
num_points = gloader->base.outline.n_points;
@ -311,7 +322,7 @@
default:
/* we don't support other formats (yet?) */
error = AF_Err_Unimplemented_Feature;
error = FT_Err_Unimplemented_Feature;
}
Hint_Metrics:
@ -321,15 +332,16 @@
/* transform the hinted outline if needed */
if ( hinter->transformed )
FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix );
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 ( hinter->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
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 );
@ -342,17 +354,21 @@
/* 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 = hinter->pp2.x - hinter->pp1.x;
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 */
af_loader_rewind( slot->internal->loader );
error = af_loader_copy_points( slot->internal->loader, gloader );
FT_GlyphLoader_Rewind( loader->gloader );
error = FT_GlyphLoader_CopyPoints( loader->gloader, gloader );
if ( error )
goto Exit;
@ -371,134 +387,44 @@
/* load and hint a given glyph */
FT_LOCAL_DEF( FT_Error )
af_loader_load_g( AF_Hinter hinter,
FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
FT_Int32 load_flags )
{
FT_Face face = slot->face;
FT_Error error;
FT_Fixed x_scale = size->metrics.x_scale;
FT_Fixed y_scale = size->metrics.y_scale;
AF_Face_Globals face_globals = FACE_GLOBALS( face );
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 */
/* global hints to load the glyph */
if ( hinter->face != face || hinter->globals != face_globals )
{
hinter->face = face;
if ( !face_globals )
{
error = af_hinter_new_face_globals( hinter, face, 0 );
if ( error )
goto Exit;
}
hinter->globals = FACE_GLOBALS( face );
face_globals = FACE_GLOBALS( face );
}
#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
*/
{
AF_Globals design = &face_globals->design;
FT_Pos shoot = design->blue_shoots[AF_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... */
if ( shoot > 0 )
{
FT_Pos scaled = FT_MulFix( shoot, y_scale );
FT_Pos fitted = FT_PIX_ROUND( scaled );
if ( scaled != fitted )
{
/* adjust y_scale
*/
y_scale = FT_MulDiv( y_scale, fitted, scaled );
/* adust x_scale
*/
if ( fitted < scaled )
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 */
/* need to rescale the global metrics */
if ( face_globals->x_scale != x_scale ||
face_globals->y_scale != y_scale )
af_hinter_scale_globals( hinter, x_scale, y_scale );
af_loader_rewind( hinter->loader );
/* reset hinting flags according to load flags and current render target */
hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
#ifdef DEBUG_HINTER
hinter->do_horz_hints = !af_debug_disable_vert; /* not a bug, the meaning */
hinter->do_vert_hints = !af_debug_disable_horz; /* of h/v is inverted! */
#endif
/* we snap the width of vertical stems for the monochrome and */
/* horizontal LCD rendering targets only. Corresponds to X snapping. */
hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD );
/* we snap the width of horizontal stems for the monochrome and */
/* vertical LCD rendering targets only. Corresponds to Y snapping. */
hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD_V );
hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
load_flags |= FT_LOAD_NO_SCALE
| FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
error = af_hinter_load( hinter, glyph_index, load_flags, 0 );
Exit:
return error;
}
static FT_Error
af_loader_load_glyph( AF_Loader loader,
AF_Scaler scaler,
FT_UInt glyph_index )
FT_Face face,
FT_UInt gindex,
FT_UInt32 load_flags )
{
FT_Error error;
FT_Face face = scaler->face;
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( globals, gindex, &metrics );
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
if ( !error )
{
metrics->clazz->script_metrics_scale( metrics, scaler );
metrics->clazz->script_metrics_scale( metrics, &scaler );
error = af_loader_load_g( loader, scaler, metrics, glyph_index,
/* load_flags */, 0 );
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;

View File

@ -21,22 +21,26 @@ FT_BEGIN_HEADER
} AF_LoaderRec, *AF_Loader;
FT_LOCAL( void )
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_UInt depth );
FT_UInt32 load_flags );
/* */

View File

@ -1,437 +1,68 @@
#include "afmodule.h"
#include "afhints.h"
#include "afglobal.h"
#include "aflatin.h"
#include "afloader.h"
#include FT_INTERNAL_OBJECTS_H
static FT_Error
af_hinter_load( AF_Hinter hinter,
FT_UInt glyph_index,
FT_Int32 load_flags,
FT_UInt depth )
typedef struct FT_AutofitterRec_
{
FT_Face face = hinter->face;
FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal;
FT_Fixed x_scale = hinter->globals->x_scale;
FT_Fixed y_scale = hinter->globals->y_scale;
FT_Error error;
AF_Outline outline = hinter->glyph;
AF_Loader gloader = hinter->loader;
FT_ModuleRec root;
AF_LoaderRec loader[1];
} FT_AutofitterRec, *FT_Autofitter;
/* load the glyph */
error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error )
goto Exit;
/* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */
hinter->transformed = internal->glyph_transformed;
if ( hinter->transformed )
FT_CALLBACK_DEF( FT_Error )
af_autofitter_init( FT_Autofitter module )
{
FT_Matrix imatrix;
imatrix = internal->glyph_matrix;
hinter->trans_delta = internal->glyph_delta;
hinter->trans_matrix = imatrix;
FT_Matrix_Invert( &imatrix );
FT_Vector_Transform( &hinter->trans_delta, &imatrix );
}
/* set linear horizontal metrics */
slot->linearHoriAdvance = slot->metrics.horiAdvance;
slot->linearVertAdvance = slot->metrics.vertAdvance;
switch ( slot->format )
{
case FT_GLYPH_FORMAT_OUTLINE:
/* translate glyph outline if we need to */
if ( hinter->transformed )
{
FT_UInt n = slot->outline.n_points;
FT_Vector* point = slot->outline.points;
for ( ; n > 0; point++, n-- )
{
point->x += hinter->trans_delta.x;
point->y += hinter->trans_delta.y;
}
}
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = af_loader_check_points( gloader, slot->outline.n_points + 2,
slot->outline.n_contours );
if ( error )
goto Exit;
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 phantom points */
hinter->pp1.x = 0;
hinter->pp1.y = 0;
hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
hinter->pp2.y = 0;
/* 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 = af_outline_load( outline, x_scale, y_scale, face );
if ( error )
goto Exit;
/* perform feature detection */
af_outline_detect_features( outline );
if ( hinter->do_vert_hints )
{
af_outline_compute_blue_edges( outline, hinter->globals );
af_outline_scale_blue_edges( outline, hinter->globals );
}
/* perform alignment control */
af_hinter_hint_edges( hinter );
af_hinter_align( hinter );
/* now save the current outline into the loader's current table */
af_outline_save( outline, gloader );
/* 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_Edge edge1 = outline->vert_edges; /* leftmost edge */
AF_Edge edge2 = edge1 +
outline->num_vedges - 1; /* rightmost edge */
old_advance = hinter->pp2.x;
old_rsb = old_advance - edge2->opos;
old_lsb = edge1->opos;
new_lsb = edge1->pos;
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 */
if ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 )
hinter->pp2.x += 64;
#endif
}
/* good, we simply add the glyph to our loader's base */
af_loader_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 = af_loader_check_subglyphs( 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 = hinter->pp1;
pp2 = hinter->pp2;
num_base_points = gloader->base.outline.n_points;
error = af_hinter_load( hinter, 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 = hinter->pp1;
pp2 = hinter->pp2;
}
else
{
hinter->pp1 = pp1;
hinter->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 = AF_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, x_scale );
y = FT_MulFix( subglyph->arg2, y_scale );
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 = AF_Err_Unimplemented_Feature;
}
Hint_Metrics:
if ( depth == 0 )
{
FT_BBox bbox;
/* transform the hinted outline if needed */
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 */
if ( hinter->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -hinter->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 ( !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 = FT_PIX_ROUND( slot->metrics.horiAdvance );
/* now copy outline into glyph slot */
af_loader_rewind( slot->internal->loader );
error = af_loader_copy_points( slot->internal->loader, gloader );
if ( error )
goto Exit;
slot->outline = slot->internal->loader->base.outline;
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
#ifdef DEBUG_HINTER
af_debug_hinter = hinter;
#endif
Exit:
return error;
return af_loader_init( module->loader, module->root.library->memory );
}
/* load and hint a given glyph */
FT_LOCAL_DEF( FT_Error )
af_hinter_load_glyph( AF_Hinter hinter,
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_Face face = slot->face;
FT_Error error;
FT_Fixed x_scale = size->metrics.x_scale;
FT_Fixed y_scale = size->metrics.y_scale;
AF_Face_Globals face_globals = FACE_GLOBALS( face );
FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags );
return af_loader_load_glyph( module->loader, slot->face,
glyph_index, load_flags );
}
/* first of all, we need to check that we're using the correct face and */
/* global hints to load the glyph */
if ( hinter->face != face || hinter->globals != face_globals )
FT_CALLBACK_TABLE_DEF
const FT_AutoHinter_ServiceRec af_autofitter_service =
{
hinter->face = face;
if ( !face_globals )
NULL,
NULL,
NULL,
(FT_AutoHinter_GlyphLoadFunc) af_autofitter_load_glyph
};
FT_CALLBACK_TABLE_DEF
const FT_Module_Class autofit_module_class =
{
error = af_hinter_new_face_globals( hinter, face, 0 );
if ( error )
goto Exit;
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
}
hinter->globals = FACE_GLOBALS( face );
face_globals = FACE_GLOBALS( face );
"autofitter",
0x10000L, /* version 1.0 of the autofitter */
0x20000L, /* requires FreeType 2.0 or above */
}
(const void*) &af_autofitter_service,
#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
*/
{
AF_Globals design = &face_globals->design;
FT_Pos shoot = design->blue_shoots[AF_BLUE_SMALL_TOP];
(FT_Module_Constructor) af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
(FT_Module_Requester) 0
};
/* 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 = FT_PIX_ROUND( scaled );
if ( scaled != fitted )
{
/* adjust y_scale
*/
y_scale = FT_MulDiv( y_scale, fitted, scaled );
/* adust x_scale
*/
if ( fitted < scaled )
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 */
/* need to rescale the global metrics */
if ( face_globals->x_scale != x_scale ||
face_globals->y_scale != y_scale )
af_hinter_scale_globals( hinter, x_scale, y_scale );
af_loader_rewind( hinter->loader );
/* reset hinting flags according to load flags and current render target */
hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
#ifdef DEBUG_HINTER
hinter->do_horz_hints = !af_debug_disable_vert; /* not a bug, the meaning */
hinter->do_vert_hints = !af_debug_disable_horz; /* of h/v is inverted! */
#endif
/* we snap the width of vertical stems for the monochrome and */
/* horizontal LCD rendering targets only. Corresponds to X snapping. */
hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD );
/* we snap the width of horizontal stems for the monochrome and */
/* vertical LCD rendering targets only. Corresponds to Y snapping. */
hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
hint_mode == FT_RENDER_MODE_LCD_V );
hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
load_flags |= FT_LOAD_NO_SCALE
| FT_LOAD_IGNORE_TRANSFORM;
load_flags &= ~FT_LOAD_RENDER;
error = af_hinter_load( hinter, glyph_index, load_flags, 0 );
Exit:
return error;
}
/* END */

View File

@ -1,5 +1,17 @@
#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__ */

View File

@ -226,12 +226,10 @@ FT_BEGIN_HEADER
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
AF_Scaler scaler,
FT_Outline* outline,
AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
AF_Scaler scaler,
FT_Outline* outline,
AF_ScriptMetrics metrics );

View File

@ -1,7 +1,10 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "afangles.c"
#include "afglobal.c"
#include "afhints.c"
#include "aflatin.c"
#include "afloader.c"
#include "afmodule.c"

View File

@ -117,7 +117,7 @@
FT_CALLBACK_TABLE_DEF
const FT_Module_Class autohint_module_class =
const FT_Module_Class autofit_module_class =
{
FT_MODULE_HINTER,
sizeof ( FT_AutoHinterRec ),

2
src/cache/Jamfile vendored
View File

@ -14,7 +14,7 @@ HDRMACRO [ FT2_SubDir include ftcache.h ] ;
if $(FT2_MULTI)
{
_sources = ftmru
_sources = ftcmru
ftcmanag
ftccache
ftcglyph

View File

@ -20,7 +20,6 @@ OBJS=ftcache.obj
all : $(OBJS)
library [--.lib]freetype.olb $(OBJS)
ftcache.obj : ftcache.c ftcmru.c ftcmanag.c ftccache.c ftcglyph.c ftcimage.c \
ftcsbits.c ftccmap.c ftcbasic.c
ftcache.obj : ftcache.c
# EOF

View File

@ -269,6 +269,9 @@
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! */
@ -376,6 +379,9 @@
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;

34
src/cache/ftcmanag.c vendored
View File

@ -165,22 +165,15 @@
if ( !manager )
return FTC_Err_Invalid_Cache_Handle;
/* we break encapsulation for the sake of speed */
#ifdef FTC_INLINE
error = 0;
FTC_MRULIST_LOOP( &manager->sizes, node )
{
FTC_Scaler scaler0 = &node->scaler;
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 ( FTC_SCALER_COMPARE( scaler0, scaler ) )
goto Found;
}
FTC_MRULIST_LOOP_END();
error = FTC_MruList_New( &manager->sizes, scaler, (FTC_MruNode*)&node );
Found:
if ( !error )
*asize = node->size;
@ -287,18 +280,15 @@
return FTC_Err_Invalid_Cache_Handle;
/* we break encapsulation for the sake of speed */
#ifdef FTC_INLINE
error = 0;
FTC_MRULIST_LOOP( &manager->faces, node )
{
if ( node->face_id == face_id )
goto Found;
}
FTC_MRULIST_LOOP_END();
FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
node, error );
error = FTC_MruList_New( &manager->faces, face_id, (FTC_MruNode*)&node );
#else
error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node );
#endif
Found:
if ( !error )
*aface = node->face;

5
src/cache/ftcmru.c vendored
View File

@ -215,7 +215,12 @@
do
{
if ( compare( node, key ) )
{
if ( node != first )
FTC_MruNode_Up( &list->nodes, node );
return node;
}
node = node->next;

View File

@ -8,7 +8,7 @@ SubDir FT2_TOP $(FT2_SRC_DIR) sfnt ;
if $(FT2_MULTI)
{
_sources = sfobjs sfdriver ttcmap ttcmap0 ttpost ttload ttsbit ;
_sources = sfobjs sfdriver ttcmap0 ttpost ttload ttsbit ;
}
else
{