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> 2004-03-21 Werner Lemberg <wl@gnu.org>
* src/bdf/bdfdrivr.c (BDF_Glyph_Load): Fix left side bearing. * src/bdf/bdfdrivr.c (BDF_Glyph_Load): Fix left side bearing.

View File

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

View File

@ -1,35 +1,35 @@
#include "afdummy.h" #include "afdummy.h"
static FT_Error static FT_Error
af_dummy_hints_init( AF_GlyphHints hints, af_dummy_hints_init( AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_ScriptMetrics metrics ) AF_ScriptMetrics metrics )
{ {
return af_glyph_hints_reset( hints, return af_glyph_hints_reset( hints,
&metrics->scaler, &metrics->scaler,
metrics, metrics,
outline ); outline );
} }
static FT_Error static FT_Error
af_dummy_hints_apply( AF_GlyphHints hints, af_dummy_hints_apply( AF_GlyphHints hints,
FT_Outline* outline ) FT_Outline* outline )
{ {
af_glyph_hints_save( hints, outline ); af_glyph_hints_save( hints, outline );
} }
FT_LOCAL_DEF( const AF_ScriptClassRec ) af_dummy_script_class = FT_LOCAL_DEF( const AF_ScriptClassRec ) af_dummy_script_class =
{ {
AF_SCRIPT_NONE, AF_SCRIPT_NONE,
NULL, NULL,
sizeof( AF_ScriptMetricsRec ), sizeof( AF_ScriptMetricsRec ),
(AF_Script_InitMetricsFunc) NULL, (AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc) NULL, (AF_Script_ScaleMetricsFunc) NULL,
(AF_Script_DoneMetricsFunc) NULL, (AF_Script_DoneMetricsFunc) NULL,
(AF_Script_InitHintsFunc) af_dummy_hints_init, (AF_Script_InitHintsFunc) af_dummy_hints_init,
(AF_Script_ApplyHintsFunc) af_dummy_hints_apply (AF_Script_ApplyHintsFunc) af_dummy_hints_apply
}; };

View File

@ -1,18 +1,18 @@
#ifndef __AFDUMMY_H__ #ifndef __AFDUMMY_H__
#define __AFDUMMY_H__ #define __AFDUMMY_H__
#include "aftypes.h" #include "aftypes.h"
FT_BEGIN_HEADER FT_BEGIN_HEADER
/* a dummy script metrics class used when no hinting should /* a dummy script metrics class used when no hinting should
* be performed. This is the default for non-latin glyphs ! * be performed. This is the default for non-latin glyphs !
*/ */
FT_LOCAL( const AF_ScriptClassRec ) af_dummy_script_class; FT_LOCAL( const AF_ScriptClassRec ) af_dummy_script_class;
/* */ /* */
FT_END_HEADER FT_END_HEADER
#endif /* __AFDUMMY_H__ */ #endif /* __AFDUMMY_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,246 +1,246 @@
#ifndef __AFHINTS_H__ #ifndef __AFHINTS_H__
#define __AFHINTS_H__ #define __AFHINTS_H__
#include "aftypes.h" #include "aftypes.h"
FT_BEGIN_HEADER FT_BEGIN_HEADER
/* /*
* The definition of outline glyph hints. These are shared by all * The definition of outline glyph hints. These are shared by all
* script analysis routines (until now) * script analysis routines (until now)
* *
*/ */
typedef enum typedef enum
{ {
AF_DIMENSION_HORZ = 0, /* x coordinates, i.e. vertical segments & edges */ AF_DIMENSION_HORZ = 0, /* x coordinates, i.e. vertical segments & edges */
AF_DIMENSION_VERT = 1, /* y coordinates, i.e. horizontal segments & edges */ AF_DIMENSION_VERT = 1, /* y coordinates, i.e. horizontal segments & edges */
AF_DIMENSION_MAX /* do not remove */ AF_DIMENSION_MAX /* do not remove */
} AF_Dimension; } AF_Dimension;
/* hint directions -- the values are computed so that two vectors are */ /* hint directions -- the values are computed so that two vectors are */
/* in opposite directions iff `dir1+dir2 == 0' */ /* in opposite directions iff `dir1+dir2 == 0' */
typedef enum typedef enum
{ {
AF_DIR_NONE = 4, AF_DIR_NONE = 4,
AF_DIR_RIGHT = 1, AF_DIR_RIGHT = 1,
AF_DIR_LEFT = -1, AF_DIR_LEFT = -1,
AF_DIR_UP = 2, AF_DIR_UP = 2,
AF_DIR_DOWN = -2 AF_DIR_DOWN = -2
} AF_Direction; } AF_Direction;
/* point hint flags */ /* point hint flags */
typedef enum typedef enum
{ {
AF_FLAG_NONE = 0, AF_FLAG_NONE = 0,
/* point type flags */ /* point type flags */
AF_FLAG_CONIC = (1 << 0), AF_FLAG_CONIC = (1 << 0),
AF_FLAG_CUBIC = (1 << 1), AF_FLAG_CUBIC = (1 << 1),
AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC, AF_FLAG_CONTROL = AF_FLAG_CONIC | AF_FLAG_CUBIC,
/* point extremum flags */ /* point extremum flags */
AF_FLAG_EXTREMA_X = (1 << 2), AF_FLAG_EXTREMA_X = (1 << 2),
AF_FLAG_EXTREMA_Y = (1 << 3), AF_FLAG_EXTREMA_Y = (1 << 3),
/* point roundness flags */ /* point roundness flags */
AF_FLAG_ROUND_X = (1 << 4), AF_FLAG_ROUND_X = (1 << 4),
AF_FLAG_ROUND_Y = (1 << 5), AF_FLAG_ROUND_Y = (1 << 5),
/* point touch flags */ /* point touch flags */
AF_FLAG_TOUCH_X = (1 << 6), AF_FLAG_TOUCH_X = (1 << 6),
AF_FLAG_TOUCH_Y = (1 << 7), AF_FLAG_TOUCH_Y = (1 << 7),
/* candidates for weak interpolation have this flag set */ /* candidates for weak interpolation have this flag set */
AF_FLAG_WEAK_INTERPOLATION = (1 << 8), AF_FLAG_WEAK_INTERPOLATION = (1 << 8),
/* all inflection points in the outline have this flag set */ /* all inflection points in the outline have this flag set */
AF_FLAG_INFLECTION = (1 << 9) AF_FLAG_INFLECTION = (1 << 9)
} AF_Flags; } AF_Flags;
/* edge hint flags */ /* edge hint flags */
typedef enum typedef enum
{ {
AF_EDGE_NORMAL = 0, AF_EDGE_NORMAL = 0,
AF_EDGE_ROUND = (1 << 0), AF_EDGE_ROUND = (1 << 0),
AF_EDGE_SERIF = (1 << 1), AF_EDGE_SERIF = (1 << 1),
AF_EDGE_DONE = (1 << 2) AF_EDGE_DONE = (1 << 2)
} AF_Edge_Flags; } AF_Edge_Flags;
typedef struct AF_PointRec_* AF_Point; typedef struct AF_PointRec_* AF_Point;
typedef struct AF_SegmentRec_* AF_Segment; typedef struct AF_SegmentRec_* AF_Segment;
typedef struct AF_EdgeRec_* AF_Edge; typedef struct AF_EdgeRec_* AF_Edge;
typedef struct AF_PointRec_ typedef struct AF_PointRec_
{ {
AF_Flags flags; /* point flags used by hinter */ AF_Flags flags; /* point flags used by hinter */
FT_Pos ox, oy; /* original, scaled position */ FT_Pos ox, oy; /* original, scaled position */
FT_Pos fx, fy; /* original, unscaled position (font units) */ FT_Pos fx, fy; /* original, unscaled position (font units) */
FT_Pos x, y; /* current position */ FT_Pos x, y; /* current position */
FT_Pos u, v; /* current (x,y) or (y,x) depending on context */ FT_Pos u, v; /* current (x,y) or (y,x) depending on context */
AF_Direction in_dir; /* direction of inwards vector */ AF_Direction in_dir; /* direction of inwards vector */
AF_Direction out_dir; /* direction of outwards vector */ AF_Direction out_dir; /* direction of outwards vector */
AF_Point next; /* next point in contour */ AF_Point next; /* next point in contour */
AF_Point prev; /* previous point in contour */ AF_Point prev; /* previous point in contour */
} AF_PointRec; } AF_PointRec;
typedef struct AF_SegmentRec_ typedef struct AF_SegmentRec_
{ {
AF_Edge_Flags flags; /* edge/segment flags for this segment */ AF_Edge_Flags flags; /* edge/segment flags for this segment */
AF_Direction dir; /* segment direction */ AF_Direction dir; /* segment direction */
FT_Pos pos; /* position of segment */ FT_Pos pos; /* position of segment */
FT_Pos min_coord; /* minimum coordinate of segment */ FT_Pos min_coord; /* minimum coordinate of segment */
FT_Pos max_coord; /* maximum coordinate of segment */ FT_Pos max_coord; /* maximum coordinate of segment */
AF_Edge edge; /* the segment's parent edge */ AF_Edge edge; /* the segment's parent edge */
AF_Segment edge_next; /* link to next segment in parent edge */ AF_Segment edge_next; /* link to next segment in parent edge */
AF_Segment link; /* (stem) link segment */ AF_Segment link; /* (stem) link segment */
AF_Segment serif; /* primary segment for serifs */ AF_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */ FT_Pos num_linked; /* number of linked segments */
FT_Pos score; /* used during stem matching */ FT_Pos score; /* used during stem matching */
AF_Point first; /* first point in edge segment */ AF_Point first; /* first point in edge segment */
AF_Point last; /* last point in edge segment */ AF_Point last; /* last point in edge segment */
AF_Point* contour; /* ptr to first point of segment's contour */ AF_Point* contour; /* ptr to first point of segment's contour */
} AF_SegmentRec; } AF_SegmentRec;
typedef struct AF_EdgeRec_ typedef struct AF_EdgeRec_
{ {
FT_Pos fpos; /* original, unscaled position (font units) */ FT_Pos fpos; /* original, unscaled position (font units) */
FT_Pos opos; /* original, scaled position */ FT_Pos opos; /* original, scaled position */
FT_Pos pos; /* current position */ FT_Pos pos; /* current position */
AF_Edge_Flags flags; /* edge flags */ AF_Edge_Flags flags; /* edge flags */
AF_Direction dir; /* edge direction */ AF_Direction dir; /* edge direction */
FT_Fixed scale; /* used to speed up interpolation between edges */ FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */ AF_Width blue_edge; /* non-NULL if this is a blue edge */
AF_Edge link; AF_Edge link;
AF_Edge serif; AF_Edge serif;
FT_Int num_linked; FT_Int num_linked;
FT_Int score; FT_Int score;
AF_Segment first; AF_Segment first;
AF_Segment last; AF_Segment last;
} AF_EdgeRec; } AF_EdgeRec;
typedef struct AF_AxisHintsRec_ typedef struct AF_AxisHintsRec_
{ {
FT_Int num_segments; FT_Int num_segments;
AF_Segment segments; AF_Segment segments;
FT_Int num_edges; FT_Int num_edges;
AF_Edge edges; AF_Edge edges;
AF_Direction major_dir; AF_Direction major_dir;
} AF_AxisHintsRec, *AF_AxisHints; } AF_AxisHintsRec, *AF_AxisHints;
typedef struct AF_GlyphHintsRec_ typedef struct AF_GlyphHintsRec_
{ {
FT_Memory memory; FT_Memory memory;
FT_Fixed x_scale; FT_Fixed x_scale;
FT_Pos x_delta; FT_Pos x_delta;
FT_Fixed y_scale; FT_Fixed y_scale;
FT_Pos y_delta; FT_Pos y_delta;
FT_Pos edge_distance_threshold; FT_Pos edge_distance_threshold;
FT_Int max_points; FT_Int max_points;
FT_Int num_points; FT_Int num_points;
AF_Point points; AF_Point points;
FT_Int max_contours; FT_Int max_contours;
FT_Int num_contours; FT_Int num_contours;
AF_Point* contours; AF_Point* contours;
AF_AxisHintsRec axis[ AF_DIMENSION_MAX ]; AF_AxisHintsRec axis[ AF_DIMENSION_MAX ];
FT_UInt32 scaler_flags; /* copy of scaler flags */ FT_UInt32 scaler_flags; /* copy of scaler flags */
FT_UInt32 other_flags; /* free for script-specific implementations */ FT_UInt32 other_flags; /* free for script-specific implementations */
AF_ScriptMetrics metrics; AF_ScriptMetrics metrics;
} AF_GlyphHintsRec; } AF_GlyphHintsRec;
#define AF_HINTS_TEST_SCALER(h,f) ( (h)->scaler_flags & (f) ) #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_TEST_OTHER(h,f) ( (h)->other_flags & (f) )
#define AF_HINTS_DO_HORIZONTAL(h) \ #define AF_HINTS_DO_HORIZONTAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_HORIZONTAL) !AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_HORIZONTAL)
#define AF_HINTS_DO_VERTICAL(h) \ #define AF_HINTS_DO_VERTICAL(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_VERTICAL) !AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_VERTICAL)
#define AF_HINTS_DO_ADVANCE(h) \ #define AF_HINTS_DO_ADVANCE(h) \
!AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_ADVANCE) !AF_HINTS_TEST_SCALER(h,AF_SCALER_FLAG_NO_ADVANCE)
FT_LOCAL( AF_Direction ) FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx, af_direction_compute( FT_Pos dx,
FT_Pos dy ); FT_Pos dy );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_init( AF_GlyphHints hints, af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory ); FT_Memory memory );
/* recomputes all AF_Point in a AF_GlyphHints from the definitions /* recomputes all AF_Point in a AF_GlyphHints from the definitions
* in a source outline * in a source outline
*/ */
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
af_glyph_hints_reset( AF_GlyphHints hints, af_glyph_hints_reset( AF_GlyphHints hints,
AF_Scaler scaler, AF_Scaler scaler,
AF_ScriptMetrics metrics, AF_ScriptMetrics metrics,
FT_Outline* outline ); FT_Outline* outline );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_save( AF_GlyphHints hints, af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline ); FT_Outline* outline );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints, af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim ); AF_Dimension dim );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints, af_glyph_hints_align_strong_points( AF_GlyphHints hints,
AF_Dimension dim ); AF_Dimension dim );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints, af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim ); AF_Dimension dim );
FT_LOCAL( void ) FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints ); af_glyph_hints_done( AF_GlyphHints hints );
/* */ /* */
FT_END_HEADER FT_END_HEADER
#endif /* __AFHINTS_H__ */ #endif /* __AFHINTS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,441 +1,442 @@
#include "afloader.h" #include "afloader.h"
#include "afhints.h" #include "afhints.h"
#include "afglobal.h" #include "afglobal.h"
#include "aflatin.h" #include "aflatin.h"
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader, af_loader_init( AF_Loader loader,
FT_Memory memory ) FT_Memory memory )
{ {
FT_Error error; FT_Error error;
FT_ZERO( loader ); FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory ); af_glyph_hints_init( &loader->hints, memory );
error = FT_GlyphLoader_New( memory, &loader->gloader ); error = FT_GlyphLoader_New( memory, &loader->gloader );
if ( !error ) if ( !error )
{ {
error = FT_GlyphLoader_CreateExtra( loader->gloader ); error = FT_GlyphLoader_CreateExtra( loader->gloader );
if ( error ) if ( error )
{ {
FT_GlyphLoader_Done( loader->gloader ); FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL; loader->gloader = NULL;
} }
} }
return error; return error;
} }
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader, af_loader_reset( AF_Loader loader,
FT_Face face ) FT_Face face )
{ {
FT_Error error = 0; FT_Error error = 0;
loader->face = face; loader->face = face;
loader->globals = (AF_FaceGlobals) face->autohint.data; loader->globals = (AF_FaceGlobals) face->autohint.data;
FT_GlyphLoader_Rewind( loader->gloader ); FT_GlyphLoader_Rewind( loader->gloader );
if ( loader->globals == NULL ) if ( loader->globals == NULL )
{ {
error = af_face_globals_new( face, &loader->globals ); error = af_face_globals_new( face, &loader->globals );
if ( !error ) if ( !error )
{ {
face->autohint.data = (FT_Pointer) loader->globals; face->autohint.data = (FT_Pointer) loader->globals;
face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free; face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free;
} }
} }
return error; return error;
} }
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader ) af_loader_done( AF_Loader loader )
{ {
loader->face = NULL; loader->face = NULL;
loader->globals = NULL; loader->globals = NULL;
FT_GlyphLoader_Done( loader->gloader ); FT_GlyphLoader_Done( loader->gloader );
loader->gloader = NULL; loader->gloader = NULL;
} }
static FT_Error static FT_Error
af_loader_load_g( AF_Loader loader, af_loader_load_g( AF_Loader loader,
AF_Scaler scaler, AF_Scaler scaler,
FT_UInt glyph_index, FT_UInt glyph_index,
FT_Int32 load_flags, FT_Int32 load_flags,
FT_UInt depth ) FT_UInt depth )
{ {
FT_Error error = 0; FT_Error error = 0;
FT_Face face = loader->face; FT_Face face = loader->face;
AF_FaceGlobals globals = loader->globals; AF_FaceGlobals globals = loader->globals;
FT_GlyphLoader gloader = loader->gloader; FT_GlyphLoader gloader = loader->gloader;
AF_ScriptMetrics metrics = loader->metrics; AF_ScriptMetrics metrics = loader->metrics;
AF_GlyphHints hints = &loader->hints; AF_GlyphHints hints = &loader->hints;
FT_GlyphSlot slot = face->glyph; FT_GlyphSlot slot = face->glyph;
FT_Slot_Internal internal = slot->internal; FT_Slot_Internal internal = slot->internal;
error = FT_Load_Glyph( face, glyph_index, load_flags ); error = FT_Load_Glyph( face, glyph_index, load_flags );
if ( error ) if ( error )
goto Exit; goto Exit;
loader->transformed = internal->glyph_transformed; loader->transformed = internal->glyph_transformed;
if ( loader->transformed ) if ( loader->transformed )
{ {
FT_Matrix inverse; FT_Matrix inverse;
loader->trans_matrix = internal->glyph_matrix; loader->trans_matrix = internal->glyph_matrix;
loader->trans_delta = internal->glyph_delta; loader->trans_delta = internal->glyph_delta;
inverse = loader->trans_matrix; inverse = loader->trans_matrix;
FT_Matrix_Invert( &inverse ); FT_Matrix_Invert( &inverse );
FT_Vector_Transform( &loader->trans_delta, &inverse ); FT_Vector_Transform( &loader->trans_delta, &inverse );
} }
/* set linear metrics */ /* set linear metrics */
slot->linearHoriAdvance = slot->metrics.horiAdvance; slot->linearHoriAdvance = slot->metrics.horiAdvance;
slot->linearVertAdvance = slot->metrics.vertAdvance; slot->linearVertAdvance = slot->metrics.vertAdvance;
switch ( slot->format ) switch ( slot->format )
{ {
case FT_GLYPH_FORMAT_OUTLINE: case FT_GLYPH_FORMAT_OUTLINE:
/* translate the loaded glyph when an internal transform /* translate the loaded glyph when an internal transform
* is needed * is needed
*/ */
if ( loader->transformed ) if ( loader->transformed )
{ {
FT_Vector* point = slot->outline.points; FT_Vector* point = slot->outline.points;
FT_Vector* limit = point + slot->outline.n_points; FT_Vector* limit = point + slot->outline.n_points;
for ( ; point < limit; point++ ) for ( ; point < limit; point++ )
{ {
point->x += loader->trans_delta.x; point->x += loader->trans_delta.x;
point->y += loader->trans_delta.y; point->y += loader->trans_delta.y;
} }
} }
/* copy the outline points in the loader's current */ /* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */ /* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader, error = FT_GlyphLoader_CheckPoints( gloader,
slot->outline.n_points + 2, slot->outline.n_points + 4,
slot->outline.n_contours ); slot->outline.n_contours );
if ( error ) if ( error )
goto Exit; goto Exit;
FT_ARRAY_COPY( gloader->current.outline.points, FT_ARRAY_COPY( gloader->current.outline.points,
slot->outline.points, slot->outline.points,
slot->outline.n_points ); slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.extra_points, FT_ARRAY_COPY( gloader->current.extra_points,
slot->outline.points, slot->outline.points,
slot->outline.n_points ); slot->outline.n_points );
FT_ARRAY_COPY( gloader->current.outline.contours, FT_ARRAY_COPY( gloader->current.outline.contours,
slot->outline.contours, slot->outline.contours,
slot->outline.n_contours ); slot->outline.n_contours );
FT_ARRAY_COPY( gloader->current.outline.tags, FT_ARRAY_COPY( gloader->current.outline.tags,
slot->outline.tags, slot->outline.tags,
slot->outline.n_points ); slot->outline.n_points );
gloader->current.outline.n_points = slot->outline.n_points; gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours; gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original phantom points */ /* compute original horizontal phantom points (and ignore */
loader->pp1.x = hints->x_delta; /* vertical ones) */
loader->pp1.y = hints->y_delta; loader->pp1.x = hints->x_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance, loader->pp1.y = hints->y_delta;
hints->x_scale ) + hints->x_delta; loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
loader->pp2.y = hints->y_delta; 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 ) /* be sure to check for spacing glyphs */
goto Hint_Metrics; if ( slot->outline.n_points == 0 )
goto Hint_Metrics;
/* now load the slot image into the auto-outline and run the */
/* automatic hinting process */ /* now load the slot image into the auto-outline and run the */
error = metrics->clazz->script_hints_init( hints, /* automatic hinting process */
&gloader->current.outline, error = metrics->clazz->script_hints_init( hints,
metrics ); &gloader->current.outline,
if ( error ) metrics );
goto Exit; if ( error )
goto Exit;
/* apply the hints */
metrics->clazz->script_hints_apply( hints, /* apply the hints */
&gloader->current.outline, metrics->clazz->script_hints_apply( hints,
metrics ); &gloader->current.outline,
/* we now need to hint the metrics according to the change in */ metrics );
/* width/positioning that occured during the hinting process */ /* 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 ]; FT_Pos old_advance, old_rsb, old_lsb, new_lsb;
AF_Edge edge1 = axis->edges; /* leftmost edge */ AF_AxisHints axis = &hints->axis[ AF_DIMENSION_HORZ ];
AF_Edge edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */ 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_advance = loader->pp2.x;
old_lsb = edge1->opos; old_rsb = old_advance - edge2->opos;
new_lsb = edge1->pos; 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 ); 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 0
if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 ) /* try to fix certain bad advance computations */
loader->pp2.x += 64; if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
#endif loader->pp2.x += 64;
} #endif
}
/* good, we simply add the glyph to our loader's base */
FT_GlyphLoader_Add( gloader ); /* good, we simply add the glyph to our loader's base */
break; FT_GlyphLoader_Add( gloader );
break;
case FT_GLYPH_FORMAT_COMPOSITE:
{ case FT_GLYPH_FORMAT_COMPOSITE:
FT_UInt nn, num_subglyphs = slot->num_subglyphs; {
FT_UInt num_base_subgs, start_point; FT_UInt nn, num_subglyphs = slot->num_subglyphs;
FT_SubGlyph subglyph; FT_UInt num_base_subgs, start_point;
FT_SubGlyph subglyph;
start_point = gloader->base.outline.n_points;
start_point = gloader->base.outline.n_points;
/* first of all, copy the subglyph descriptors in the glyph loader */
error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs ); /* first of all, copy the subglyph descriptors in the glyph loader */
if ( error ) error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
goto Exit; if ( error )
goto Exit;
FT_ARRAY_COPY( gloader->current.subglyphs,
slot->subglyphs, FT_ARRAY_COPY( gloader->current.subglyphs,
num_subglyphs ); slot->subglyphs,
num_subglyphs );
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.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++ ) /* now, read each subglyph independently */
{ for ( nn = 0; nn < num_subglyphs; nn++ )
FT_Vector pp1, pp2; {
FT_Pos x, y; FT_Vector pp1, pp2;
FT_UInt num_points, num_new_points, num_base_points; 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 */ /* gloader.current.subglyphs can change during glyph loading due */
/* each iteration */ /* to re-allocation -- we must recompute the current subglyph on */
subglyph = gloader->base.subglyphs + num_base_subgs + nn; /* each iteration */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
pp1 = loader->pp1;
pp2 = loader->pp2; pp1 = loader->pp1;
pp2 = loader->pp2;
num_base_points = gloader->base.outline.n_points;
num_base_points = gloader->base.outline.n_points;
error = af_loader_load_g( loader, scaler, subglyph->index,
load_flags, depth + 1 ); error = af_loader_load_g( loader, scaler, subglyph->index,
if ( error ) load_flags, depth + 1 );
goto Exit; if ( error )
goto Exit;
/* recompute subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + nn; /* recompute subglyph pointer */
subglyph = gloader->base.subglyphs + num_base_subgs + nn;
if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
{ if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
pp1 = loader->pp1; {
pp2 = loader->pp2; pp1 = loader->pp1;
} pp2 = loader->pp2;
else }
{ else
loader->pp1 = pp1; {
loader->pp2 = pp2; loader->pp1 = pp1;
} loader->pp2 = pp2;
}
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points; num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
/* now perform the transform required for this subglyph */
/* now perform the transform required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE | if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_2X2 ) ) FT_SUBGLYPH_FLAG_XY_SCALE |
{ FT_SUBGLYPH_FLAG_2X2 ) )
FT_Vector* cur = gloader->base.outline.points + {
num_base_points; FT_Vector* cur = gloader->base.outline.points +
FT_Vector* org = gloader->base.extra_points + num_base_points;
num_base_points; FT_Vector* org = gloader->base.extra_points +
FT_Vector* limit = cur + num_new_points; num_base_points;
FT_Vector* limit = cur + num_new_points;
for ( ; cur < limit; cur++, org++ )
{ for ( ; cur < limit; cur++, org++ )
FT_Vector_Transform( cur, &subglyph->transform ); {
FT_Vector_Transform( org, &subglyph->transform ); FT_Vector_Transform( cur, &subglyph->transform );
} FT_Vector_Transform( org, &subglyph->transform );
} }
}
/* apply offset */
/* apply offset */
if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
{ if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
FT_Int k = subglyph->arg1; {
FT_UInt l = subglyph->arg2; FT_Int k = subglyph->arg1;
FT_Vector* p1; FT_UInt l = subglyph->arg2;
FT_Vector* p2; FT_Vector* p1;
FT_Vector* p2;
if ( start_point + k >= num_base_points ||
l >= (FT_UInt)num_new_points ) if ( start_point + k >= num_base_points ||
{ l >= (FT_UInt)num_new_points )
error = FT_Err_Invalid_Composite; {
goto Exit; error = FT_Err_Invalid_Composite;
} goto Exit;
}
l += num_base_points;
l += num_base_points;
/* for now, only use the current point coordinates; */
/* we may consider another approach in the near future */ /* for now, only use the current point coordinates; */
p1 = gloader->base.outline.points + start_point + k; /* we may consider another approach in the near future */
p2 = gloader->base.outline.points + start_point + l; 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; x = p1->x - p2->x;
} y = p1->y - p2->y;
else }
{ 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_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); x = FT_PIX_ROUND(x);
} y = FT_PIX_ROUND(y);
}
{
FT_Outline dummy = gloader->base.outline; {
FT_Outline dummy = gloader->base.outline;
dummy.points += num_base_points;
dummy.n_points = (short)num_new_points; dummy.points += num_base_points;
dummy.n_points = (short)num_new_points;
FT_Outline_Translate( &dummy, x, y );
} FT_Outline_Translate( &dummy, x, y );
} }
} }
break; }
break;
default:
/* we don't support other formats (yet?) */ default:
error = FT_Err_Unimplemented_Feature; /* we don't support other formats (yet?) */
} error = FT_Err_Unimplemented_Feature;
}
Hint_Metrics:
if ( depth == 0 ) Hint_Metrics:
{ if ( depth == 0 )
FT_BBox bbox; {
FT_BBox bbox;
/* transform the hinted outline if needed */
if ( loader->transformed ) /* transform the hinted outline if needed */
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix ); if ( loader->transformed )
FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
/* we must translate our final outline by -pp1.x and compute */
/* the new metrics */ /* we must translate our final outline by -pp1.x and compute */
if ( loader->pp1.x ) /* the new metrics */
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 ); if ( loader->pp1.x )
FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
bbox.xMax = FT_PIX_CEIL( bbox.xMax ); bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
bbox.yMax = FT_PIX_CEIL( bbox.yMax ); 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.width = bbox.xMax - bbox.xMin;
slot->metrics.horiBearingX = bbox.xMin; slot->metrics.height = bbox.yMax - bbox.yMin;
slot->metrics.horiBearingY = bbox.yMax; slot->metrics.horiBearingX = bbox.xMin;
slot->metrics.horiBearingY = bbox.yMax;
/* for mono-width fonts (like Andale, Courier, etc.) we need */
/* to keep the original rounded advance width */ /* for mono-width fonts (like Andale, Courier, etc.) we need */
#if 0 /* to keep the original rounded advance width */
if ( !FT_IS_FIXED_WIDTH( slot->face ) ) #if 0
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; if ( !FT_IS_FIXED_WIDTH( slot->face ) )
else slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, else
x_scale ); slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
#else x_scale );
slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; #else
#endif slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
#endif
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
/* now copy outline into glyph slot */
FT_GlyphLoader_Rewind( internal->loader ); /* now copy outline into glyph slot */
error = FT_GlyphLoader_CopyPoints( internal->loader, gloader ); FT_GlyphLoader_Rewind( internal->loader );
if ( error ) error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
goto Exit; if ( error )
goto Exit;
slot->outline = internal->loader->base.outline;
slot->format = FT_GLYPH_FORMAT_OUTLINE; slot->outline = internal->loader->base.outline;
} slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
#ifdef DEBUG_HINTER
af_debug_hinter = hinter; #ifdef DEBUG_HINTER
#endif af_debug_hinter = hinter;
#endif
Exit:
return error; Exit:
} return error;
}
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader, FT_LOCAL_DEF( FT_Error )
FT_Face face, af_loader_load_glyph( AF_Loader loader,
FT_UInt gindex, FT_Face face,
FT_UInt32 load_flags ) FT_UInt gindex,
{ FT_UInt32 load_flags )
FT_Error error; {
FT_Size size = face->size; FT_Error error;
AF_ScalerRec scaler; FT_Size size = face->size;
AF_ScalerRec scaler;
if ( !size )
return FT_Err_Invalid_Argument; if ( !size )
return FT_Err_Invalid_Argument;
FT_ZERO( &scaler );
FT_ZERO( &scaler );
scaler.face = face;
scaler.x_scale = size->metrics.x_scale; scaler.face = face;
scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */ scaler.x_scale = size->metrics.x_scale;
scaler.y_scale = size->metrics.y_scale; scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
scaler.y_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 */ scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
scaler.flags = 0; /* XXX: fix this */
error = af_loader_reset( loader, face );
if ( !error ) error = af_loader_reset( loader, face );
{ if ( !error )
AF_ScriptMetrics metrics; {
AF_ScriptMetrics metrics;
error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
if ( !error ) error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
{ if ( !error )
loader->metrics = metrics; {
loader->metrics = metrics;
metrics->scaler = scaler;
metrics->scaler = scaler;
if ( metrics->clazz->script_metrics_scale )
metrics->clazz->script_metrics_scale( metrics, &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; 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 );
} error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
} }
return error; }
} return error;
}

View File

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

View File

@ -1,268 +1,268 @@
#ifndef __AFTYPES_H__ #ifndef __AFTYPES_H__
#define __AFTYPES_H__ #define __AFTYPES_H__
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_OUTLINE_H #include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_DEBUG_H
FT_BEGIN_HEADER FT_BEGIN_HEADER
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** D E B U G G I N G *****/ /***** D E B U G G I N G *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
#define AF_DEBUG #define AF_DEBUG
#ifdef AF_DEBUG #ifdef AF_DEBUG
# include <stdio.h> # include <stdio.h>
# define AF_LOG( x ) printf x # define AF_LOG( x ) printf x
#else #else
# define AF_LOG( x ) do ; while ( 0 ) /* nothing */ # define AF_LOG( x ) do ; while ( 0 ) /* nothing */
#endif /* AF_DEBUG */ #endif /* AF_DEBUG */
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** U T I L I T Y *****/ /***** U T I L I T Y *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
typedef struct AF_WidthRec_ typedef struct AF_WidthRec_
{ {
FT_Pos org; /* original position/width in font units */ FT_Pos org; /* original position/width in font units */
FT_Pos cur; /* current/scaled position/width in device sub-pixels */ FT_Pos cur; /* current/scaled position/width in device sub-pixels */
FT_Pos fit; /* current/fitted position/width in device sub-pixels */ FT_Pos fit; /* current/fitted position/width in device sub-pixels */
} AF_WidthRec, *AF_Width; } AF_WidthRec, *AF_Width;
FT_LOCAL( void ) FT_LOCAL( void )
af_sort_pos( FT_UInt count, af_sort_pos( FT_UInt count,
FT_Pos* table ); FT_Pos* table );
FT_LOCAL( void ) FT_LOCAL( void )
af_sort_widths( FT_UInt count, af_sort_widths( FT_UInt count,
AF_Width widths ); AF_Width widths );
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** A N G L E T Y P E S *****/ /***** A N G L E T Y P E S *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* /*
* Angle type. The auto-fitter doesn't need a very high angular accuracy, * 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 * and this allows us to speed up some computations considerably with a
* light Cordic algorithm (see afangles.c) * light Cordic algorithm (see afangles.c)
* *
*/ */
typedef FT_Int AF_Angle; typedef FT_Int AF_Angle;
#define AF_ANGLE_PI 128 #define AF_ANGLE_PI 128
#define AF_ANGLE_2PI (AF_ANGLE_PI*2) #define AF_ANGLE_2PI (AF_ANGLE_PI*2)
#define AF_ANGLE_PI2 (AF_ANGLE_PI/2) #define AF_ANGLE_PI2 (AF_ANGLE_PI/2)
#define AF_ANGLE_PI4 (AF_ANGLE_PI/4) #define AF_ANGLE_PI4 (AF_ANGLE_PI/4)
/* /*
* compute the angle of a given 2-D vector * compute the angle of a given 2-D vector
* *
*/ */
FT_LOCAL( AF_Angle ) FT_LOCAL( AF_Angle )
af_angle_atan( FT_Pos dx, af_angle_atan( FT_Pos dx,
FT_Pos dy ); FT_Pos dy );
/* /*
* computes "angle2 - angle1", the result is always within * computes "angle2 - angle1", the result is always within
* the range [ -AF_ANGLE_PI .. AF_ANGLE_PI-1 ] * the range [ -AF_ANGLE_PI .. AF_ANGLE_PI-1 ]
* *
*/ */
FT_LOCAL( AF_Angle ) FT_LOCAL( AF_Angle )
af_angle_diff( AF_Angle angle1, af_angle_diff( AF_Angle angle1,
AF_Angle angle2 ); AF_Angle angle2 );
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** O U T L I N E S *****/ /***** O U T L I N E S *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* opaque handle to glyph-specific hints. see "afhints.h" for more /* opaque handle to glyph-specific hints. see "afhints.h" for more
* details * details
*/ */
typedef struct AF_GlyphHintsRec_* AF_GlyphHints; typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
/* this structure is used to model an input glyph outline to /* this structure is used to model an input glyph outline to
* the auto-hinter. The latter will set the "hints" field * the auto-hinter. The latter will set the "hints" field
* depending on the glyph's script * depending on the glyph's script
*/ */
typedef struct AF_OutlineRec_ typedef struct AF_OutlineRec_
{ {
FT_Face face; FT_Face face;
FT_Outline outline; FT_Outline outline;
FT_UInt outline_resolution; FT_UInt outline_resolution;
FT_Int advance; FT_Int advance;
FT_UInt metrics_resolution; FT_UInt metrics_resolution;
AF_GlyphHints hints; AF_GlyphHints hints;
} AF_OutlineRec; } AF_OutlineRec;
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** S C A L E R S *****/ /***** S C A L E R S *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* /*
* A scaler models the target pixel device that will receive the * A scaler models the target pixel device that will receive the
* auto-hinted glyph image * auto-hinted glyph image
* *
*/ */
typedef enum typedef enum
{ {
AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */ AF_SCALER_FLAG_NO_HORIZONTAL = 1, /* disable horizontal hinting */
AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */ AF_SCALER_FLAG_NO_VERTICAL = 2, /* disable vertical hinting */
AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */ AF_SCALER_FLAG_NO_ADVANCE = 4 /* disable advance hinting */
} AF_ScalerFlags; } AF_ScalerFlags;
typedef struct AF_ScalerRec_ typedef struct AF_ScalerRec_
{ {
FT_Face face; /* source font face */ FT_Face face; /* source font face */
FT_Fixed x_scale; /* from font units to 1/64th device pixels */ 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_Fixed y_scale; /* from font units to 1/64th device pixels */
FT_Pos x_delta; /* in 1/64th device pixels */ FT_Pos x_delta; /* in 1/64th device pixels */
FT_Pos y_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_Render_Mode render_mode; /* monochrome, anti-aliased, LCD, etc.. */
FT_UInt32 flags; /* additionnal control flags, see above */ FT_UInt32 flags; /* additionnal control flags, see above */
} AF_ScalerRec, *AF_Scaler; } AF_ScalerRec, *AF_Scaler;
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/***** *****/ /***** *****/
/***** S C R I P T S *****/ /***** S C R I P T S *****/
/***** *****/ /***** *****/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* /*
* the list of know scripts. Each different script correspond to the * the list of know scripts. Each different script correspond to the
* following information: * following information:
* *
* - a set of Unicode ranges to test weither the face supports the * - a set of Unicode ranges to test weither the face supports the
* script * script
* *
* - a specific global analyzer that will compute global metrics * - a specific global analyzer that will compute global metrics
* specific to the script. * specific to the script.
* *
* - a specific glyph analyzer that will compute segments and * - a specific glyph analyzer that will compute segments and
* edges for each glyph covered by the script * edges for each glyph covered by the script
* *
* - a specific grid-fitting algorithm that will distort the * - a specific grid-fitting algorithm that will distort the
* scaled glyph outline according to the results of the glyph * scaled glyph outline according to the results of the glyph
* analyzer * analyzer
* *
* note that a given analyzer and/or grid-fitting algorithm can be * note that a given analyzer and/or grid-fitting algorithm can be
* used by more than one script * used by more than one script
*/ */
typedef enum typedef enum
{ {
AF_SCRIPT_NONE = 0, AF_SCRIPT_NONE = 0,
AF_SCRIPT_LATIN = 1, AF_SCRIPT_LATIN = 1,
/* add new scripts here. don't forget to update the list in "afglobal.c" */ /* add new scripts here. don't forget to update the list in "afglobal.c" */
AF_SCRIPT_MAX /* do not remove */ AF_SCRIPT_MAX /* do not remove */
} AF_Script; } AF_Script;
typedef struct AF_ScriptClassRec_ const* AF_ScriptClass; typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
typedef struct AF_ScriptMetricsRec_ typedef struct AF_ScriptMetricsRec_
{ {
AF_ScriptClass clazz; AF_ScriptClass clazz;
AF_ScalerRec scaler; AF_ScalerRec scaler;
} AF_ScriptMetricsRec, *AF_ScriptMetrics; } AF_ScriptMetricsRec, *AF_ScriptMetrics;
/* this function parses a FT_Face to compute global metrics for /* this function parses a FT_Face to compute global metrics for
* a specific script * a specific script
*/ */
typedef FT_Error (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics, typedef FT_Error (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics metrics,
FT_Face face ); FT_Face face );
typedef void (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics, typedef void (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics metrics,
AF_Scaler scaler ); AF_Scaler scaler );
typedef void (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics ); typedef void (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics metrics );
typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints, typedef FT_Error (*AF_Script_InitHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_ScriptMetrics metrics ); AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints, typedef void (*AF_Script_ApplyHintsFunc)( AF_GlyphHints hints,
FT_Outline* outline, FT_Outline* outline,
AF_ScriptMetrics metrics ); AF_ScriptMetrics metrics );
typedef struct AF_Script_UniRangeRec_ typedef struct AF_Script_UniRangeRec_
{ {
FT_UInt32 first; FT_UInt32 first;
FT_UInt32 last; FT_UInt32 last;
} AF_Script_UniRangeRec; } AF_Script_UniRangeRec;
typedef const AF_Script_UniRangeRec * AF_Script_UniRange; typedef const AF_Script_UniRangeRec * AF_Script_UniRange;
typedef struct AF_ScriptClassRec_ typedef struct AF_ScriptClassRec_
{ {
AF_Script script; AF_Script script;
AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */ AF_Script_UniRange script_uni_ranges; /* last must be { 0, 0 } */
FT_UInt script_metrics_size; FT_UInt script_metrics_size;
AF_Script_InitMetricsFunc script_metrics_init; AF_Script_InitMetricsFunc script_metrics_init;
AF_Script_ScaleMetricsFunc script_metrics_scale; AF_Script_ScaleMetricsFunc script_metrics_scale;
AF_Script_DoneMetricsFunc script_metrics_done; AF_Script_DoneMetricsFunc script_metrics_done;
AF_Script_InitHintsFunc script_hints_init; AF_Script_InitHintsFunc script_hints_init;
AF_Script_ApplyHintsFunc script_hints_apply; AF_Script_ApplyHintsFunc script_hints_apply;
} AF_ScriptClassRec; } AF_ScriptClassRec;
/* */ /* */
FT_END_HEADER FT_END_HEADER
#endif /* __AFTYPES_H__ */ #endif /* __AFTYPES_H__ */

View File

@ -435,7 +435,7 @@
/* */ /* */
if ( num_points + 2 > outline->max_points ) 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; FT_Int max = outline->max_points;

View File

@ -1489,7 +1489,7 @@
/* copy the outline points in the loader's current */ /* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */ /* 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 ); slot->outline.n_contours );
if ( error ) if ( error )
goto Exit; goto Exit;
@ -1506,7 +1506,7 @@
gloader->current.outline.n_points = slot->outline.n_points; gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours; 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.x = 0;
hinter->pp1.y = 0; hinter->pp1.y = 0;
hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); 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 */ /* General types and definitions for the auto-hint module */
/* (specification only). */ /* (specification only). */
/* */ /* */
/* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. */ /* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */ /* Author: David Turner */
/* */ /* */
/* This file is part of the Catharon Typography Project and shall only */ /* This file is part of the Catharon Typography Project and shall only */
@ -492,8 +492,9 @@ FT_BEGIN_HEADER
AH_Outline glyph; AH_Outline glyph;
AH_Loader loader; AH_Loader loader;
FT_Vector pp1; FT_Vector pp1; /* horizontal phantom points */
FT_Vector pp2; FT_Vector pp2;
/* we ignore vertical phantom points */
FT_Bool transformed; FT_Bool transformed;
FT_Vector trans_delta; 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 ) \ #define cur_to_org( n, zone ) \
FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) ) FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
@ -317,7 +368,7 @@
if ( n_contours > 0 ) if ( n_contours > 0 )
n_points = cont[-1] + 1; 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 ) if ( error )
goto Fail; goto Fail;
@ -635,12 +686,16 @@
/* add shadow points */ /* 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. */ /* 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* pp1;
FT_Vector* pp2; FT_Vector* pp2;
FT_Vector* pp3;
FT_Vector* pp4;
/* pp1 = xMin - lsb */ /* pp1 = xMin - lsb */
@ -653,14 +708,26 @@
pp2->x = pp1->x + load->advance; pp2->x = pp1->x + load->advance;
pp2->y = 0; 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 ] = 0;
outline->tags[n_points + 1] = 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 */ /* Note that we return two more points that are not */
/* part of the glyph outline. */ /* part of the glyph outline. */
n_points += 2; n_points += 4;
/* set up zone for hinting */ /* set up zone for hinting */
tt_prepare_zone( zone, &gloader->current, 0, 0 ); tt_prepare_zone( zone, &gloader->current, 0, 0 );
@ -687,15 +754,18 @@
/* eventually hint the glyph */ /* eventually hint the glyph */
if ( IS_HINTED( load->load_flags ) ) 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; 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 ); 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 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -711,7 +781,7 @@
load->exec->pedantic_hinting = (FT_Bool)( load->load_flags & load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
FT_LOAD_PEDANTIC ); FT_LOAD_PEDANTIC );
load->exec->pts = *zone; load->exec->pts = *zone;
load->exec->pts.n_points += 2; load->exec->pts.n_points += 4;
error = TT_Run_Context( load->exec, debug ); error = TT_Run_Context( load->exec, debug );
if ( error && load->exec->pedantic_hinting ) if ( error && load->exec->pedantic_hinting )
@ -727,8 +797,10 @@
/* save glyph phantom points */ /* save glyph phantom points */
if ( !load->preserve_pps ) if ( !load->preserve_pps )
{ {
load->pp1 = zone->cur[n_points - 2]; load->pp1 = zone->cur[n_points - 4];
load->pp2 = zone->cur[n_points - 1]; 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 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -797,16 +869,22 @@
y_scale = loader->size->metrics.y_scale; y_scale = loader->size->metrics.y_scale;
} }
/* get horizontal metrics */ /* get metrics, horizontal and vertical */
{ {
FT_Short left_bearing = 0; FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0; FT_UShort advance_width = 0, advance_height = 0;
Get_HMetrics( face, glyph_index, Get_HMetrics( face, glyph_index,
(FT_Bool)!( loader->load_flags & (FT_Bool)!( loader->load_flags &
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing, &left_bearing,
&advance_width ); &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 #ifdef FT_CONFIG_OPTION_INCREMENTAL
@ -830,10 +908,33 @@
advance_width = (FT_UShort)metrics.advance; 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 */ #endif /* FT_CONFIG_OPTION_INCREMENTAL */
loader->left_bearing = left_bearing; loader->left_bearing = left_bearing;
loader->advance = advance_width; loader->advance = advance_width;
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
if ( !loader->linear_def ) if ( !loader->linear_def )
{ {
@ -893,9 +994,14 @@
loader->pp1.x = 0; loader->pp1.x = 0;
loader->pp2.x = loader->advance; 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 ) if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 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 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -933,10 +1039,17 @@
loader->pp2.x = loader->pp1.x + loader->advance; loader->pp2.x = loader->pp1.x + loader->advance;
loader->pp2.y = 0; 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 ) if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{ {
loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
loader->pp2.x = FT_MulFix( loader->pp2.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++ ) for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
{ {
FT_Vector pp1, pp2; FT_Vector pp1, pp2, pp3, pp4;
FT_Pos x, y; FT_Pos x, y;
@ -1057,6 +1170,8 @@
pp1 = loader->pp1; pp1 = loader->pp1;
pp2 = loader->pp2; pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
num_base_points = gloader->base.outline.n_points; num_base_points = gloader->base.outline.n_points;
@ -1072,11 +1187,15 @@
{ {
pp1 = loader->pp1; pp1 = loader->pp1;
pp2 = loader->pp2; pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
} }
else else
{ {
loader->pp1 = pp1; loader->pp1 = pp1;
loader->pp2 = pp2; loader->pp2 = pp2;
loader->pp3 = pp3;
loader->pp4 = pp4;
} }
num_points = gloader->base.outline.n_points; num_points = gloader->base.outline.n_points;
@ -1273,7 +1392,7 @@
if ( error ) if ( error )
goto Fail; goto Fail;
error = FT_GlyphLoader_CheckPoints( gloader, num_points + 2, 0 ); error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
if ( error ) if ( error )
goto Fail; goto Fail;
@ -1282,22 +1401,28 @@
start_point, start_contour ); start_point, start_contour );
pts = &exec->pts; 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; pts->n_contours = gloader->base.outline.n_contours;
/* add phantom points */ /* add phantom points */
pp1 = pts->cur + num_points; pp1 = pts->cur + num_points;
pp1[0] = loader->pp1; pp1[0] = loader->pp1;
pp1[1] = loader->pp2; pp1[1] = loader->pp2;
pp1[2] = loader->pp3;
pp1[3] = loader->pp4;
pts->tags[num_points ] = 0; pts->tags[num_points ] = 0;
pts->tags[num_points + 1] = 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 hinting, round the phantom points */
if ( IS_HINTED( loader->load_flags ) ) if ( IS_HINTED( loader->load_flags ) )
{ {
pp1[0].x = FT_PIX_ROUND( loader->pp1.x ); pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
pp1[1].x = FT_PIX_ROUND( loader->pp2.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; pts->tags[k] &= FT_CURVE_TAG_ON;
} }
cur_to_org( num_points + 2, pts ); cur_to_org( num_points + 4, pts );
/* now consider hinting */ /* now consider hinting */
if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
@ -1324,6 +1449,8 @@
/* save glyph origin and advance points */ /* save glyph origin and advance points */
loader->pp1 = pp1[0]; loader->pp1 = pp1[0];
loader->pp2 = pp1[1]; loader->pp2 = pp1[1];
loader->pp3 = pp1[2];
loader->pp4 = pp1[3];
} }
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
@ -1443,13 +1570,9 @@
if ( face->vertical_info && if ( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 ) face->vertical.number_Of_VMetrics > 0 )
{ {
/* Don't assume that both the vertical header and vertical */ advance_height = loader->pp4.y - loader->pp3.y;
/* metrics are present in the same font :-) */ top_bearing = loader->pp3.y - bbox.yMax;
TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
glyph_index,
&top_bearing,
&advance_height );
} }
else else
{ {
@ -1465,6 +1588,12 @@
/* here with: */ /* here with: */
/* ascender - descender + linegap */ /* 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 ) if ( face->os2.version != 0xFFFFU )
{ {
top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 ); top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 );
@ -1507,6 +1636,8 @@
advance_height = (FT_UShort)metrics.advance; advance_height = (FT_UShort)metrics.advance;
} }
/* GWW: Do vertical metrics get loaded incrementally too? */
#endif /* FT_CONFIG_OPTION_INCREMENTAL */ #endif /* FT_CONFIG_OPTION_INCREMENTAL */
/* We must adjust the top_bearing value from the bounding box given */ /* We must adjust the top_bearing value from the bounding box given */

View File

@ -4,7 +4,7 @@
/* */ /* */
/* Objects manager (specification). */ /* Objects manager (specification). */
/* */ /* */
/* Copyright 1996-2001, 2002, 2003 by */ /* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */ /* */
/* This file is part of the FreeType project, and may only be used, */ /* 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 */ 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; } TT_SubGlyphRec, *TT_SubGlyph_Stack;