Add vertical phantom points.

* include/freetype/internal/tttypes.h (TT_LoaderRec): Add
`top_bearing', `vadvance', `pp3, and `pp4'.

* src/autofit/afloader.c (af_loader_load_g): Handle two more points.

* src/autohint/ahhint.c (ah_hinter_load): Handle two more points.
* src/truetype/ttgload.c (Get_VMetrics): New function.
(TT_Load_Simple_Glyph, TT_Process_Simple_Glyph): Handle two more
points.
(load_truetype_glyph): Use Get_VMetrics.
Handle two more points.
(compute_glyph_metrics): Thanks to vertical phantom points we now
can always compute `advance_height' and `top_bearing'.
* src/truetype/ttobjs.h (TT_SubglyphRec): Add vertical phantom
points.


* src/autohint/ahglyph.c (ah_outline_load): Fix allocation of
`news'.

Converting some files to Unix end-of-line convention.
This commit is contained in:
Werner Lemberg 2004-03-27 08:43:17 +00:00
parent 60e0a4d5db
commit 8bb07e6386
15 changed files with 3975 additions and 3812 deletions

View File

@ -1,3 +1,27 @@
2004-13-26 George Williams <gww@silcom.com>
Add vertical phantom points.
* include/freetype/internal/tttypes.h (TT_LoaderRec): Add
`top_bearing', `vadvance', `pp3, and `pp4'.
* src/autofit/afloader.c (af_loader_load_g): Handle two more points.
* src/autohint/ahhint.c (ah_hinter_load): Handle two more points.
* src/truetype/ttgload.c (Get_VMetrics): New function.
(TT_Load_Simple_Glyph, TT_Process_Simple_Glyph): Handle two more
points.
(load_truetype_glyph): Use Get_VMetrics.
Handle two more points.
(compute_glyph_metrics): Thanks to vertical phantom points we now
can always compute `advance_height' and `top_bearing'.
* src/truetype/ttobjs.h (TT_SubglyphRec): Add vertical phantom
points.
* src/autohint/ahglyph.c (ah_outline_load): Fix allocation of
`news'.
2004-03-21 Werner Lemberg <wl@gnu.org>
* src/bdf/bdfdrivr.c (BDF_Glyph_Load): Fix left side bearing.

View File

@ -1342,11 +1342,15 @@ FT_BEGIN_HEADER
FT_BBox bbox;
FT_Int left_bearing;
FT_Int advance;
FT_Int top_bearing;
FT_Int vadvance;
FT_Int linear;
FT_Bool linear_def;
FT_Bool preserve_pps;
FT_Vector pp1;
FT_Vector pp2;
FT_Vector pp3;
FT_Vector pp4;
FT_ULong glyf_offset;

View File

@ -1,35 +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
};
#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
};

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,441 +1,442 @@
#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;
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.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 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,
&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;
}
#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;
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 + 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;
}

View File

@ -18,6 +18,7 @@ FT_BEGIN_HEADER
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
/* we don't handle vertical phantom points */
} AF_LoaderRec, *AF_Loader;

View File

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

View File

@ -435,7 +435,7 @@
/* */
if ( num_points + 2 > outline->max_points )
{
FT_Int news = FT_PAD_CEIL( num_points, 8 );
FT_Int news = FT_PAD_CEIL( num_points + 2, 8 );
FT_Int max = outline->max_points;

View File

@ -1489,7 +1489,7 @@
/* 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,
error = ah_loader_check_points( gloader, slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
@ -1506,7 +1506,7 @@
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 );

View File

@ -5,7 +5,7 @@
/* General types and definitions for the auto-hint module */
/* (specification only). */
/* */
/* Copyright 2000-2001, 2002, 2003 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 */
@ -492,8 +492,9 @@ FT_BEGIN_HEADER
AH_Outline glyph;
AH_Loader loader;
FT_Vector pp1;
FT_Vector pp1; /* horizontal phantom points */
FT_Vector pp2;
/* we ignore vertical phantom points */
FT_Bool transformed;
FT_Vector trans_delta;

View File

@ -162,6 +162,57 @@
}
/*************************************************************************/
/* */
/* Returns the vertical metrics in font units for a given glyph. */
/* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
/* table, typoAscender/Descender from the `OS/2' table would be used */
/* instead, and if there were no `OS/2' table, use ascender/descender */
/* from the `hhea' table. But that is not what Microsoft's rasterizer */
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* */
/* The monospace `check' is probably not meaningful here, but we leave */
/* it in for a consistent interface. */
/* */
static void
Get_VMetrics( TT_Face face,
FT_UInt idx,
FT_Bool check,
FT_Short* tsb,
FT_UShort* ah )
{
FT_UNUSED( check );
if ( face->vertical_info )
TT_Get_Metrics( (TT_HoriHeader *)&face->vertical, idx, tsb, ah );
#if 1 /* Emperically determined, at variance with what MS said */
else
{
*tsb = 0;
*ah = face->root.units_per_EM;
}
#else /* This is what MS said to do. It isn't what they do, however. */
else if ( face->os2.version != 0xFFFFU )
{
*tsb = face->os2.sTypoAscender;
*ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
}
else
{
*tsb = face->horizontal.Ascender;
*ah = face->horizontal.Ascender - face->horizontal.Descender;
}
#endif
}
#define cur_to_org( n, zone ) \
FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
@ -317,7 +368,7 @@
if ( n_contours > 0 )
n_points = cont[-1] + 1;
error = FT_GlyphLoader_CheckPoints( gloader, n_points + 2, 0 );
error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
if ( error )
goto Fail;
@ -635,12 +686,16 @@
/* add shadow points */
/* Now add the two shadow points at n and n + 1. */
/* Add two horizontal shadow points at n and n+1. */
/* We need the left side bearing and advance width. */
/* Add two vertical shadow points at n+2 and n+3. */
/* We need the top side bearing and advance height. */
{
FT_Vector* pp1;
FT_Vector* pp2;
FT_Vector* pp3;
FT_Vector* pp4;
/* pp1 = xMin - lsb */
@ -653,14 +708,26 @@
pp2->x = pp1->x + load->advance;
pp2->y = 0;
/* pp3 = top side bearing */
pp3 = pp1 + 2;
pp3->x = 0;
pp3->y = load->top_bearing + load->bbox.yMax;
/* pp4 = pp3 - ah */
pp4 = pp1 + 3;
pp4->x = 0;
pp4->y = pp3->y - load->vadvance;
outline->tags[n_points ] = 0;
outline->tags[n_points + 1] = 0;
outline->tags[n_points + 2] = 0;
outline->tags[n_points + 3] = 0;
}
/* Note that we return two more points that are not */
/* part of the glyph outline. */
n_points += 2;
n_points += 4;
/* set up zone for hinting */
tt_prepare_zone( zone, &gloader->current, 0, 0 );
@ -687,15 +754,18 @@
/* eventually hint the glyph */
if ( IS_HINTED( load->load_flags ) )
{
FT_Pos x = zone->org[n_points-2].x;
FT_Pos x = zone->org[n_points-4].x;
FT_Pos y = zone->org[n_points-2].y;
x = FT_PIX_ROUND( x ) - x;
translate_array( n_points, zone->org, x, 0 );
y = FT_PIX_ROUND( y ) - y;
translate_array( n_points, zone->org, x, y );
org_to_cur( n_points, zone );
zone->cur[n_points - 1].x = FT_PIX_ROUND( zone->cur[n_points - 1].x );
zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -711,7 +781,7 @@
load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
FT_LOAD_PEDANTIC );
load->exec->pts = *zone;
load->exec->pts.n_points += 2;
load->exec->pts.n_points += 4;
error = TT_Run_Context( load->exec, debug );
if ( error && load->exec->pedantic_hinting )
@ -727,8 +797,10 @@
/* save glyph phantom points */
if ( !load->preserve_pps )
{
load->pp1 = zone->cur[n_points - 2];
load->pp2 = zone->cur[n_points - 1];
load->pp1 = zone->cur[n_points - 4];
load->pp2 = zone->cur[n_points - 3];
load->pp3 = zone->cur[n_points - 2];
load->pp4 = zone->cur[n_points - 1];
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -797,16 +869,22 @@
y_scale = loader->size->metrics.y_scale;
}
/* get horizontal metrics */
/* get metrics, horizontal and vertical */
{
FT_Short left_bearing = 0;
FT_UShort advance_width = 0;
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
Get_HMetrics( face, glyph_index,
(FT_Bool)!( loader->load_flags &
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing,
&advance_width );
Get_VMetrics( face, glyph_index,
(FT_Bool)!( loader->load_flags &
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&top_bearing,
&advance_height );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@ -830,10 +908,33 @@
advance_width = (FT_UShort)metrics.advance;
}
# if 0
/* GWW: Do I do the same for vertical metrics ??? */
if ( face->root.internal->incremental_interface &&
face->root.internal->incremental_interface->funcs->get_glyph_metrics )
{
FT_Incremental_MetricsRec metrics;
metrics.bearing_x = 0;
metrics.bearing_y = top_bearing;
metrics.advance = advance_height;
error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
face->root.internal->incremental_interface->object,
glyph_index, TRUE, &metrics );
if ( error )
goto Exit;
top_bearing = (FT_Short)metrics.bearing_y;
advance_height = (FT_UShort)metrics.advance;
}
# endif
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
loader->left_bearing = left_bearing;
loader->advance = advance_width;
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
if ( !loader->linear_def )
{
@ -893,9 +994,14 @@
loader->pp1.x = 0;
loader->pp2.x = loader->advance;
loader->pp3.y = 0;
loader->pp4.y = loader->pp3.y-loader->vadvance;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -933,10 +1039,17 @@
loader->pp2.x = loader->pp1.x + loader->advance;
loader->pp2.y = 0;
loader->pp3.x = 0;
loader->pp3.y = loader->top_bearing + loader->bbox.yMax;
loader->pp4.x = 0;
loader->pp4.y = loader->pp3.y - loader->vadvance;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
/***********************************************************************/
@ -1045,7 +1158,7 @@
for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
{
FT_Vector pp1, pp2;
FT_Vector pp1, pp2, pp3, pp4;
FT_Pos x, y;
@ -1057,6 +1170,8 @@
pp1 = loader->pp1;
pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
num_base_points = gloader->base.outline.n_points;
@ -1072,11 +1187,15 @@
{
pp1 = loader->pp1;
pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
}
else
{
loader->pp1 = pp1;
loader->pp2 = pp2;
loader->pp3 = pp3;
loader->pp4 = pp4;
}
num_points = gloader->base.outline.n_points;
@ -1273,7 +1392,7 @@
if ( error )
goto Fail;
error = FT_GlyphLoader_CheckPoints( gloader, num_points + 2, 0 );
error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
if ( error )
goto Fail;
@ -1282,22 +1401,28 @@
start_point, start_contour );
pts = &exec->pts;
pts->n_points = (short)(num_points + 2);
pts->n_points = (short)( num_points + 4 );
pts->n_contours = gloader->base.outline.n_contours;
/* add phantom points */
pp1 = pts->cur + num_points;
pp1[0] = loader->pp1;
pp1[1] = loader->pp2;
pp1[2] = loader->pp3;
pp1[3] = loader->pp4;
pts->tags[num_points ] = 0;
pts->tags[num_points + 1] = 0;
pts->tags[num_points + 2] = 0;
pts->tags[num_points + 3] = 0;
/* if hinting, round the phantom points */
if ( IS_HINTED( loader->load_flags ) )
{
pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
}
{
@ -1308,7 +1433,7 @@
pts->tags[k] &= FT_CURVE_TAG_ON;
}
cur_to_org( num_points + 2, pts );
cur_to_org( num_points + 4, pts );
/* now consider hinting */
if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
@ -1324,6 +1449,8 @@
/* save glyph origin and advance points */
loader->pp1 = pp1[0];
loader->pp2 = pp1[1];
loader->pp3 = pp1[2];
loader->pp4 = pp1[3];
}
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
@ -1443,13 +1570,9 @@
if ( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 )
{
/* Don't assume that both the vertical header and vertical */
/* metrics are present in the same font :-) */
advance_height = loader->pp4.y - loader->pp3.y;
top_bearing = loader->pp3.y - bbox.yMax;
TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
glyph_index,
&top_bearing,
&advance_height );
}
else
{
@ -1465,6 +1588,12 @@
/* here with: */
/* ascender - descender + linegap */
/* */
/* NOTE3: This is different from what MS's rasterizer */
/* appears to do when getting default values */
/* for the vertical phantom points. We leave */
/* the old code untouched, but relying on */
/* phantom points alone might be reasonable */
/* (i.e., removing the `if' above). */
if ( face->os2.version != 0xFFFFU )
{
top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 );
@ -1507,6 +1636,8 @@
advance_height = (FT_UShort)metrics.advance;
}
/* GWW: Do vertical metrics get loaded incrementally too? */
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
/* We must adjust the top_bearing value from the bounding box given */

View File

@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003 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, */
@ -216,7 +216,8 @@ FT_BEGIN_HEADER
TT_Transform transform; /* transformation matrix */
FT_Vector pp1, pp2; /* phantom points */
FT_Vector pp1, pp2; /* phantom points (horizontal) */
FT_Vector pp3, pp4; /* phantom points (vertical) */
} TT_SubGlyphRec, *TT_SubGlyph_Stack;