src/autofit/afloader.c, src/types.h: grave bugs were fixed. The auto-fitter works, doesn't crashes, but still produces unexpected results !!LAYOUT
parent
849b62bf38
commit
648dd5acea
5 changed files with 3727 additions and 3656 deletions
File diff suppressed because it is too large
Load Diff
@ -1,241 +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, |
||||
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
@ -1,431 +1,438 @@ |
||||
#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->gloader = face->glyph->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 = 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.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( loader->gloader ); |
||||
error = FT_GlyphLoader_CopyPoints( loader->gloader, 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; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
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 ) |
||||
{ |
||||
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 + 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->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; |
||||
} |
||||
|
@ -1,266 +1,266 @@ |
||||
#ifndef __AFTYPES_H__ |
||||
#define __AFTYPES_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
#include FT_OUTLINE_H |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
#include FT_INTERNAL_DEBUG_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** D E B U G G I N G *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
#define xxAF_DEBUG |
||||
|
||||
#ifdef AF_DEBUG |
||||
|
||||
# include <stdio.h> |
||||
# define AF_LOG( x ) printf ## x |
||||
|
||||
#else |
||||
|
||||
# define AF_LOG( x ) do ; while ( 0 ) /* nothing */ |
||||
|
||||
#endif /* AF_DEBUG */ |
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** U T I L I T Y *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
typedef struct AF_WidthRec_ |
||||
{ |
||||
FT_Pos org; /* original position/width in font units */ |
||||
FT_Pos cur; /* current/scaled position/width in device sub-pixels */ |
||||
FT_Pos fit; /* current/fitted position/width in device sub-pixels */ |
||||
|
||||
} AF_WidthRec, *AF_Width; |
||||
|
||||
|
||||
FT_LOCAL( void ) |
||||
af_sort_pos( FT_UInt count, |
||||
FT_Pos* table ); |
||||
|
||||
FT_LOCAL( void ) |
||||
af_sort_widths( FT_UInt count, |
||||
AF_Width widths ); |
||||
|
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** A N G L E T Y P E S *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
/*
|
||||
* Angle type. The auto-fitter doesn't need a very high angular accuracy, |
||||
* and this allows us to speed up some computations considerably with a |
||||
* light Cordic algorithm (see afangles.c) |
||||
* |
||||
*/ |
||||
|
||||
typedef FT_Int AF_Angle; |
||||
|
||||
#define AF_ANGLE_PI 128 |
||||
#define AF_ANGLE_2PI (AF_ANGLE_PI*2) |
||||
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2) |
||||
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4) |
||||
|
||||
/*
|
||||
* compute the angle of a given 2-D vector |
||||
* |
||||
*/ |
||||
FT_LOCAL( AF_Angle ) |
||||
af_angle_atan( FT_Pos dx, |
||||
FT_Pos dy ); |
||||
|
||||
|
||||
/*
|
||||
* computes "angle2 - angle1", the result is always within |
||||
* the range [ -AF_ANGLE_PI .. AF_ANGLE_PI-1 ] |
||||
* |
||||
*/ |
||||
FT_LOCAL( AF_Angle ) |
||||
af_angle_diff( AF_Angle angle1, |
||||
AF_Angle angle2 ); |
||||
|
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** O U T L I N E S *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
/* opaque handle to glyph-specific hints. see "afhints.h" for more
|
||||
* details |
||||
*/ |
||||
typedef struct AF_GlyphHintsRec_* AF_GlyphHints; |
||||
|
||||
/* this structure is used to model an input glyph outline to
|
||||
* the auto-hinter. The latter will set the "hints" field |
||||
* depending on the glyph's script |
||||
*/ |
||||
typedef struct AF_OutlineRec_ |
||||
{ |
||||
FT_Face face; |
||||
FT_Outline outline; |
||||
FT_UInt outline_resolution; |
||||
|
||||
FT_Int advance; |
||||
FT_UInt metrics_resolution; |
||||
|
||||
AF_GlyphHints hints; |
||||
|
||||
} AF_OutlineRec; |
||||
|
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** S C A L E R S *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
/*
|
||||
* A scaler models the target pixel device that will receive the |
||||
* auto-hinted glyph image |
||||
* |
||||
*/ |
||||
|
||||
typedef enum |
||||
{ |
||||
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */ |
||||
AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */ |
||||
AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */ |
||||
|
||||
} AF_ScalerFlags; |
||||
|
||||
|
||||
typedef struct AF_ScalerRec_ |
||||
{ |
||||
FT_Face face; /* source font face */ |
||||
FT_Fixed x_scale; /* from font units to 1/64th device pixels */ |
||||
FT_Fixed y_scale; /* from font units to 1/64th device pixels */ |
||||
FT_Pos x_delta; /* in 1/64th device pixels */ |
||||
FT_Pos y_delta; /* in 1/64th device pixels */ |
||||
FT_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc.. */ |
||||
FT_UInt32 flags; /* additionnal control flags, see above */ |
||||
|
||||
} AF_ScalerRec, *AF_Scaler; |
||||
|
||||
|
||||
|
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
/***** *****/ |
||||
/***** S C R I P T S *****/ |
||||
/***** *****/ |
||||
/**************************************************************************/ |
||||
/**************************************************************************/ |
||||
|
||||
/*
|
||||
* the list of know scripts. Each different script correspond to the |
||||
* following information: |
||||
* |
||||
* - a set of Unicode ranges to test weither the face supports the |
||||
* script |
||||
* |
||||
* - a specific global analyzer that will compute global metrics |
||||
* specific to the script. |
||||
* |
||||
* - a specific glyph analyzer that will compute segments and |
||||
* edges for each glyph covered by the script |
||||
* |
||||
* - a specific grid-fitting algorithm that will distort the |
||||
* scaled glyph outline according to the results of the glyph |
||||
* analyzer |
||||
* |
||||
* note that a given analyzer and/or grid-fitting algorithm can be |
||||
* used by more than one script |
||||
*/ |
||||
typedef enum |
||||
{ |
||||
AF_SCRIPT_LATIN = 0, |
||||
/* 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_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_LATIN = 0, |
||||
/* 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_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__ */ |
||||
|
Loading…
Reference in new issue