updates
This commit is contained in:
parent
75820e2072
commit
8ccb4552a9
18
src/autofit/Jamfile
Normal file
18
src/autofit/Jamfile
Normal file
@ -0,0 +1,18 @@
|
||||
SubDir FT2_TOP src autofit ;
|
||||
|
||||
{
|
||||
local _sources ;
|
||||
|
||||
if $(FT2_MULTI)
|
||||
{
|
||||
_sources = afangles afglobal afhints aflatin ;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sources = autofit ;
|
||||
}
|
||||
|
||||
Library $(FT2_LIB) : $(_sources).c ;
|
||||
}
|
||||
|
||||
# end of src/autofir Jamfile
|
@ -184,11 +184,10 @@
|
||||
FT_UInt gindex,
|
||||
AF_ScriptMetrics *ametrics )
|
||||
{
|
||||
AF_Script script;
|
||||
AF_ScriptMetrics metrics = NULL;
|
||||
FT_UInt index;
|
||||
AF_ScriptClass clazz;
|
||||
FT_Error error;
|
||||
FT_Error error = 0;
|
||||
|
||||
if ( gindex >= globals->glyph_count )
|
||||
{
|
||||
@ -203,6 +202,8 @@
|
||||
{
|
||||
/* create the global metrics object when needed
|
||||
*/
|
||||
FT_Memory memory = globals->face->memory;
|
||||
|
||||
if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
|
||||
goto Exit;
|
||||
|
||||
@ -221,7 +222,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
globals->metrics[ script ] = metrics;
|
||||
globals->metrics[ clazz->script ] = metrics;
|
||||
}
|
||||
|
||||
Exit:
|
||||
|
@ -20,13 +20,12 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
*/
|
||||
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,
|
||||
@ -36,7 +35,7 @@ FT_BEGIN_HEADER
|
||||
af_face_globals_free( AF_FaceGlobals globals );
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __AF_GLOBALS_H__ */
|
||||
|
@ -303,6 +303,7 @@
|
||||
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->scaler_flags = scaler->flags;
|
||||
hints->other_flags = 0;
|
||||
@ -505,13 +506,13 @@
|
||||
in_x = point->fx - prev->fx;
|
||||
in_y = point->fy - prev->fy;
|
||||
|
||||
point->in_dir = af_compute_direction( in_x, in_y );
|
||||
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_compute_direction( out_x, out_y );
|
||||
point->out_dir = af_direction_compute( out_x, out_y );
|
||||
|
||||
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
|
||||
{
|
||||
@ -623,8 +624,6 @@
|
||||
AF_Edge edges = axis->edges;
|
||||
AF_Edge edge_limit = edges + axis->num_edges;
|
||||
AF_Flags touch_flag;
|
||||
AF_Point point;
|
||||
AF_Edge edge;
|
||||
|
||||
|
||||
if ( dim == AF_DIMENSION_HORZ )
|
||||
|
@ -176,7 +176,7 @@
|
||||
extremum = point;
|
||||
point++;
|
||||
|
||||
if ( AF_IS_TOP_BLUE( bb ) )
|
||||
if ( AF_LATIN_IS_TOP_BLUE( bb ) )
|
||||
{
|
||||
for ( ; point < point_limit; point++ )
|
||||
if ( point->y > extremum->y )
|
||||
@ -325,7 +325,6 @@
|
||||
AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
|
||||
}
|
||||
|
||||
Exit:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -398,7 +397,6 @@
|
||||
for ( nn = 0; nn < axis->blue_count; nn++ )
|
||||
{
|
||||
AF_LatinBlue blue = & axis->blues[nn];
|
||||
FT_UInt flags = blue->flags & ~AF_LATIN_BLUE_ACTIVE;
|
||||
FT_Pos dist;
|
||||
|
||||
blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
|
||||
@ -1150,7 +1148,7 @@
|
||||
*/
|
||||
if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
|
||||
hints->other_flags |= AF_LATIN_HINTS_VERT_SNAP;
|
||||
|
||||
|
||||
/* XXX
|
||||
*/
|
||||
if ( mode != FT_RENDER_MODE_LIGHT )
|
||||
@ -1163,7 +1161,7 @@
|
||||
*/
|
||||
if ( AF_HINTS_DO_HORIZONTAL(hints) )
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_HORZ );
|
||||
|
||||
|
||||
if ( AF_HINTS_DO_VERTICAL(hints) )
|
||||
{
|
||||
af_latin_hints_detect_features( hints, AF_DIMENSION_VERT );
|
||||
@ -1243,7 +1241,7 @@
|
||||
FT_Pos dist = width;
|
||||
FT_Int sign = 0;
|
||||
FT_Int vertical = AF_HINTS_DO_VERTICAL( hints );
|
||||
|
||||
|
||||
|
||||
if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) )
|
||||
return width;
|
||||
@ -1254,8 +1252,8 @@
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAPPING( hints ) ) ||
|
||||
( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAPPING( hints ) ) )
|
||||
if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
|
||||
( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
|
||||
{
|
||||
/* smooth hinting process: very lightly quantize the stem width */
|
||||
/* */
|
||||
@ -1282,7 +1280,7 @@
|
||||
if ( axis->width_count > 0 )
|
||||
{
|
||||
delta = dist - axis->widths[0].cur;
|
||||
|
||||
|
||||
if ( delta < 0 )
|
||||
delta = -delta;
|
||||
|
||||
@ -1699,7 +1697,7 @@
|
||||
anchor = edge;
|
||||
}
|
||||
else
|
||||
edge->pos = anchor->pos +
|
||||
edge->pos = anchor->pos +
|
||||
FT_PIX_ROUND( edge->opos - anchor->opos );
|
||||
|
||||
edge->flags |= AF_EDGE_DONE;
|
||||
@ -1722,11 +1720,14 @@
|
||||
AF_LatinMetrics metrics )
|
||||
{
|
||||
AF_Dimension dim;
|
||||
|
||||
|
||||
FT_UNUSED( scaler );
|
||||
FT_UNUSED( metrics );
|
||||
|
||||
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
|
||||
{
|
||||
if ( (dim == AF_DIMENSION_HORZ && AF_LATIN_HINTS_DO_HORIZONTAL(hints)) ||
|
||||
(dim == AF_DIMENSION_VERT && AF_LATIN_HINTS_DO_VERTICAL(hints)) )
|
||||
if ( (dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL(hints)) ||
|
||||
(dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL(hints)) )
|
||||
{
|
||||
af_latin_hint_edges( hints, dim );
|
||||
af_glyph_hints_align_edge_points( hints, dim );
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include "afhints.h"
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* the latin-specific script class
|
||||
*
|
||||
*/
|
||||
@ -38,7 +38,7 @@ FT_BEGIN_HEADER
|
||||
AF_LATIN_BLUE_SMALL_TOP,
|
||||
AF_LATIN_BLUE_SMALL_BOTTOM,
|
||||
AF_LATIN_BLUE_SMALL_MINOR,
|
||||
|
||||
|
||||
AF_LATIN_BLUE_MAX
|
||||
};
|
||||
|
||||
@ -53,7 +53,7 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
AF_LATIN_BLUE_ACTIVE = (1 << 0),
|
||||
AF_LATIN_BLUE_TOP = (1 << 1),
|
||||
|
||||
|
||||
AF_LATIN_BLUE_FLAG_MAX
|
||||
};
|
||||
|
||||
@ -63,7 +63,7 @@ FT_BEGIN_HEADER
|
||||
AF_WidthRec ref;
|
||||
AF_WidthRec shoot;
|
||||
FT_UInt flags;
|
||||
|
||||
|
||||
} AF_LatinBlueRec, *AF_LatinBlue;
|
||||
|
||||
|
||||
@ -71,11 +71,11 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
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;
|
||||
@ -89,7 +89,7 @@ FT_BEGIN_HEADER
|
||||
AF_ScriptMetricsRec root;
|
||||
FT_UInt units_per_em;
|
||||
AF_LatinAxisRec axis[ AF_DIMENSION_MAX ];
|
||||
|
||||
|
||||
} AF_LatinMetricsRec, *AF_LatinMetrics;
|
||||
|
||||
|
||||
@ -117,7 +117,7 @@ FT_BEGIN_HEADER
|
||||
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 */
|
||||
AF_LATIN_HINTS_MONO = (1 << 3) /* indicate monochrome rendering */
|
||||
};
|
||||
|
||||
#define AF_LATIN_HINTS_DO_HORZ_SNAP(h) \
|
||||
|
505
src/autofit/afloader.c
Normal file
505
src/autofit/afloader.c
Normal file
@ -0,0 +1,505 @@
|
||||
#include "afloader.h"
|
||||
#include "afhints.h"
|
||||
#include "afglobal.h"
|
||||
#include "aflatin.h"
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
af_loader_init( AF_Loader loader,
|
||||
FT_Memory memory )
|
||||
{
|
||||
FT_ZERO( loader );
|
||||
|
||||
af_glyph_hints_init( &loader->hints, memory );
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
af_loader_reset( AF_Loader loader,
|
||||
FT_Face face )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
|
||||
FT_ZERO( loader );
|
||||
|
||||
loader->face = face;
|
||||
loader->gloader = face->slot->internal->loader;
|
||||
loader->globals = (AF_FaceGlobals) face->autohint.data;
|
||||
|
||||
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 = face;
|
||||
loader->globals = NULL;
|
||||
loader->gloader = NULL;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
af_hinter_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;
|
||||
AF_FaceGlobals globals = loader->globals;
|
||||
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 + 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 */
|
||||
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, scaler,
|
||||
&gloader->current.outline,
|
||||
metrics );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
/* apply the hints */
|
||||
error = metrics->clazz->script_hints_apply( hints, scaler,
|
||||
&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 */
|
||||
|
||||
|
||||
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 */
|
||||
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 = hinter->pp1;
|
||||
pp2 = hinter->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 = 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 = 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 = 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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_Error error;
|
||||
FT_Face face = scaler->face;
|
||||
|
||||
error = af_loader_reset( loader, face );
|
||||
if ( !error )
|
||||
{
|
||||
AF_ScriptMetrics metrics;
|
||||
|
||||
error = af_face_globals_get_metrics( globals, gindex, &metrics );
|
||||
if ( !error )
|
||||
{
|
||||
metrics->clazz->script_metrics_scale( metrics, scaler );
|
||||
|
||||
error = af_loader_load_g( loader, scaler, metrics, glyph_index,
|
||||
/* load_flags */, 0 );
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
46
src/autofit/afloader.h
Normal file
46
src/autofit/afloader.h
Normal file
@ -0,0 +1,46 @@
|
||||
#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;
|
||||
|
||||
} AF_LoaderRec, *AF_Loader;
|
||||
|
||||
FT_LOCAL( void )
|
||||
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_UInt gindex,
|
||||
FT_UInt32 load_flags,
|
||||
FT_UInt depth );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __AF_LOADER_H__ */
|
||||
|
437
src/autofit/afmodule.c
Normal file
437
src/autofit/afmodule.c
Normal file
@ -0,0 +1,437 @@
|
||||
#include "afmodule.h"
|
||||
#include "afhints.h"
|
||||
#include "afglobal.h"
|
||||
#include "aflatin.h"
|
||||
|
||||
static FT_Error
|
||||
af_hinter_load( AF_Hinter hinter,
|
||||
FT_UInt glyph_index,
|
||||
FT_Int32 load_flags,
|
||||
FT_UInt depth )
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
/* 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_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;
|
||||
}
|
||||
|
||||
|
||||
/* load and hint a given glyph */
|
||||
FT_LOCAL_DEF( FT_Error )
|
||||
af_hinter_load_glyph( 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;
|
||||
}
|
5
src/autofit/afmodule.h
Normal file
5
src/autofit/afmodule.h
Normal file
@ -0,0 +1,5 @@
|
||||
#ifndef __AFMODULE_H__
|
||||
#define __AFMODULE_H__
|
||||
|
||||
#endif /* __AFMODULE_H__ */
|
||||
|
@ -227,10 +227,12 @@ 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 );
|
||||
|
||||
|
||||
|
7
src/autofit/autofit.c
Normal file
7
src/autofit/autofit.c
Normal file
@ -0,0 +1,7 @@
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT
|
||||
|
||||
#include <ft2build.h>
|
||||
#include "afangles.c"
|
||||
#include "afglobal.c"
|
||||
#include "afhints.c"
|
||||
#include "aflatin.c"
|
Loading…
Reference in New Issue
Block a user