[xorg-commit-diffs]
xc/extras/freetype2/src/autofit afangles.c, NONE,
1.1.6.1 afhints.c, NONE, 1.1.6.1 afhints.h, NONE,
1.1.6.1 aflatin.c, NONE, 1.1.6.1 aflatin.h, NONE,
1.1.6.1 aftypes.h, NONE, 1.1.6.1
Egbert Eich
xorg-commit at pdx.freedesktop.org
Thu Apr 15 03:14:33 PDT 2004
- Previous message: [xorg-commit-diffs] xc/extras/freetype2/objs .cvsignore, 1.1.1.1,
1.1.1.1.2.1
- Next message: [xorg-commit-diffs] xc/extras/freetype2/src/autohint ahglobal.c,
1.1.4.1, 1.1.4.2 ahglobal.h, 1.1.4.1, 1.1.4.2 ahglyph.c,
1.1.4.1, 1.1.4.2 ahhint.c, 1.1.4.1, 1.1.4.2 ahloader.h,
1.1.4.1, 1.1.4.2 ahmodule.c, 1.1.4.1, 1.1.4.2 ahtypes.h,
1.1.4.1, 1.1.4.2 rules.mk, 1.1, 1.1.4.1 ahoptim.c, 1.1.4.1,
NONE ahoptim.h, 1.1.4.1, NONE descrip.mms, 1.1, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: eich
Update of /cvs/xorg/xc/extras/freetype2/src/autofit
In directory pdx:/home/eich/tstbuild/xc/extras/freetype2/src/autofit
Added Files:
Tag: XORG-CURRENT
afangles.c afhints.c afhints.h aflatin.c aflatin.h aftypes.h
Log Message:
2004-04-15 Egbert Eich <eich at freedesktop.org>
Merged changes from RELEASE-1 branch
--- NEW FILE: afangles.c ---
#include "aftypes.h"
/* this table was generated for AF_ANGLE_PI = 256 */
#define AF_ANGLE_MAX_ITERS 8
static const FT_Fixed
af_angle_arctan_table[9] =
{
90, 64, 38, 20, 10, 5, 3, 1, 1
};
static FT_Int
af_angle_prenorm( FT_Vector* vec )
{
FT_Fixed x, y, z;
FT_Int shift;
x = vec->x;
y = vec->y;
z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
shift = 0;
if ( z < ( 1L << 27 ) )
{
do
{
shift++;
z <<= 1;
} while ( z < ( 1L << 27 ) );
vec->x = x << shift;
vec->y = y << shift;
}
else if ( z > ( 1L << 28 ) )
{
do
{
shift++;
z >>= 1;
} while ( z > ( 1L << 28 ) );
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
return shift;
}
static void
af_angle_pseudo_polarize( FT_Vector* vec )
{
FT_Fixed theta;
FT_Fixed yi, i;
FT_Fixed x, y;
const FT_Fixed *arctanptr;
x = vec->x;
y = vec->y;
/* Get the vector into the right half plane */
theta = 0;
if ( x < 0 )
{
x = -x;
y = -y;
theta = 2 * AF_ANGLE_PI2;
}
if ( y > 0 )
theta = - theta;
arctanptr = af_angle_arctan_table;
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x << 1 );
x = x - ( y << 1 );
y = yi;
theta -= *arctanptr++; /* Subtract angle */
}
else
{
/* Rotate negative */
yi = y - ( x << 1 );
x = x + ( y << 1 );
y = yi;
theta += *arctanptr++; /* Add angle */
}
i = 0;
do
{
if ( y < 0 )
{
/* Rotate positive */
yi = y + ( x >> i );
x = x - ( y >> i );
y = yi;
theta -= *arctanptr++;
}
else
{
/* Rotate negative */
yi = y - ( x >> i );
x = x + ( y >> i );
y = yi;
theta += *arctanptr++;
}
} while ( ++i < AF_TRIG_MAX_ITERS );
/* round theta */
if ( theta >= 0 )
theta = ( theta + 2 ) & -4;
else
theta = - (( -theta + 2 ) & -4);
vec->x = x;
vec->y = theta;
}
/* documentation is in fttrigon.h */
FT_LOCAL_DEF( AF_Angle )
af_angle_atan( FT_Fixed dx,
FT_Fixed dy )
{
FT_Vector v;
if ( dx == 0 && dy == 0 )
return 0;
v.x = dx;
v.y = dy;
af_angle_prenorm( &v );
af_angle_pseudo_polarize( &v );
return v.y;
}
FT_LOCAL_DEF( AF_Angle )
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 )
{
AF_Angle delta = angle2 - angle1;
delta %= AF_ANGLE_2PI;
if ( delta < 0 )
delta += AF_ANGLE_2PI;
if ( delta > AF_ANGLE_PI )
delta -= AF_ANGLE_2PI;
return delta;
}
--- NEW FILE: afhints.c ---
#include "afhints.h"
#ifdef AF_DEBUG
#include <stdio.h>
void
af_outline_hints_dump_edges( AF_OutlineHints hints )
{
AF_Edge edges;
AF_Edge edge_limit;
AF_Segment segments;
FT_Int dimension;
edges = hints->horz_edges;
edge_limit = edges + hints->num_hedges;
segments = hints->horz_segments;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_Edge edge;
printf ( "Table of %s edges:\n",
!dimension ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
" serif | blue | opos | pos ]\n" );
for ( edge = edges; edge < edge_limit; edge++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n",
edge - edges,
(int)edge->fpos,
edge->dir == AF_DIR_UP
? "up"
: ( edge->dir == AF_DIR_DOWN
? "down"
: ( edge->dir == AF_DIR_LEFT
? "left"
: ( edge->dir == AF_DIR_RIGHT
? "right"
: "none" ) ) ),
edge->link ? ( edge->link - edges ) : -1,
edge->serif ? ( edge->serif - edges ) : -1,
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0 );
}
edges = hints->vert_edges;
edge_limit = edges + hints->num_vedges;
segments = hints->vert_segments;
}
}
/* A function used to dump the array of linked segments */
void
af_outline_hints_dump_segments( AF_OutlineHints hints )
{
AF_Segment segments;
AF_Segment segment_limit;
AF_Point points;
FT_Int dimension;
points = hints->points;
segments = hints->horz_segments;
segment_limit = segments + hints->num_hsegments;
for ( dimension = 1; dimension >= 0; dimension-- )
{
AF_Segment seg;
printf ( "Table of %s segments:\n",
!dimension ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
" numl | first | start ]\n" );
for ( seg = segments; seg < segment_limit; seg++ )
{
printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
seg - segments,
(int)seg->pos,
seg->dir == AF_DIR_UP
? "up"
: ( seg->dir == AF_DIR_DOWN
? "down"
: ( seg->dir == AF_DIR_LEFT
? "left"
: ( seg->dir == AF_DIR_RIGHT
? "right"
: "none" ) ) ),
seg->link ? ( seg->link - segments ) : -1,
seg->serif ? ( seg->serif - segments ) : -1,
(int)seg->num_linked,
seg->first - points,
seg->last - points );
}
segments = hints->vert_segments;
segment_limit = segments + hints->num_vsegments;
}
}
#endif /* AF_DEBUG */
/* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{
AF_Direction dir;
FT_Pos ax = ABS( dx );
FT_Pos ay = ABS( dy );
dir = AF_DIR_NONE;
/* atan(1/12) == 4.7 degrees */
/* test for vertical direction */
if ( ax * 12 < ay )
{
dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
}
/* test for horizontal direction */
else if ( ay * 12 < ax )
{
dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
}
return dir;
}
/* compute all inflex points in a given glyph */
static void
af_outline_hints_compute_inflections( AF_OutlineHints hints )
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
/* load original coordinates in (u,v) */
af_outline_hints_setup_uv( hints, outline, AF_UV_FXY );
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
AF_Point point = contour[0];
AF_Point first = point;
AF_Point start = point;
AF_Point end = point;
AF_Point before;
AF_Point after;
AF_Angle angle_in, angle_seg, angle_out;
AF_Angle diff_in, diff_out;
FT_Int finished = 0;
/* compute first segment in contour */
first = point;
start = end = first;
do
{
end = end->next;
if ( end == first )
goto Skip;
} while ( end->u == first->u && end->v == first->v );
angle_seg = af_angle( end->u - start->u,
end->v - start->v );
/* extend the segment start whenever possible */
before = start;
do
{
do
{
start = before;
before = before->prev;
if ( before == first )
goto Skip;
} while ( before->u == start->u && before->v == start->v );
angle_in = af_angle( start->u - before->u,
start->v - before->v );
} while ( angle_in == angle_seg );
first = start;
diff_in = af_angle_diff( angle_in, angle_seg );
/* now, process all segments in the contour */
do
{
/* first, extend current segment's end whenever possible */
after = end;
do
{
do
{
end = after;
after = after->next;
if ( after == first )
finished = 1;
} while ( end->u == after->u && end->v == after->v );
vec.x = after->u - end->u;
vec.y = after->v - end->v;
angle_out = af_angle( after->u - end->u,
after->v - end->v );
} while ( angle_out == angle_seg );
diff_out = af_angle_diff( angle_seg, angle_out );
if ( ( diff_in ^ diff_out ) < 0 )
{
/* diff_in and diff_out have different signs, we have */
/* inflection points here... */
do
{
start->flags |= AF_FLAG_INFLECTION;
start = start->next;
} while ( start != end );
start->flags |= AF_FLAG_INFLECTION;
}
start = end;
end = after;
angle_seg = angle_out;
diff_in = diff_out;
} while ( !finished );
Skip:
;
}
}
FT_LOCAL_DEF( void )
af_outline_hints_init( AF_OutlineHints hints,
FT_Memory memory )
{
FT_ZERO( hints );
hints->memory = memory;
}
FT_LOCAL_DEF( void )
af_outline_hints_done( AF_OutlineHints hints )
{
if ( hints && hints->memory )
{
FT_Memory memory = hints->memory;
AF_Dimension dim;
/* note that we don't need to free the segment and edge
* buffers, since they're really within the hints->points array
*/
for ( dim = 0; dim < 2; dim++ )
{
AF_AxisHints axis = &hints->axis[ dim ];
axis->num_segments = 0;
axis->num_edges = 0;
axis->segments = NULL;
axis->edges = NULL;
}
FT_FREE( hints->contours );
hints->max_contours = 0;
hints->num_contours = 0;
FT_FREE( hints->points );
hints->num_points = 0;
hints->max_points = 0;
hints->memory = NULL;
}
}
FT_LOCAL_DEF( FT_Error )
af_outline_hints_reset( AF_OutlineHints hints,
FT_Outline* outline,
FT_Fixed x_scale,
FT_Fixed y_scale )
{
FT_Error error = AF_Err_Ok;
FT_UInt old_max, new_max;
hints->num_points = 0;
hints->num_contours = 0;
hints->axis[0].num_segments = 0;
hints->axis[0].num_edges = 0;
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
/* first of all, reallocate the contours array when necessary
*/
new_max = (FT_UInt) outline->n_contours;
old_max = hints->max_contours;
if ( new_max > old_max )
{
new_max = (new_max + 3) & ~3;
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
hints->max_contours = new_max;
}
/* then, reallocate the points, segments & edges arrays if needed --
* note that we reserved two additional point positions, used to
* hint metrics appropriately
*/
new_max = (FT_UInt)( outline->n_points + 2 );
old_max = hints->max_points;
if ( new_max > old_max )
{
FT_Byte* items;
FT_ULong off1, off2, off3;
/* we store in a single buffer the following arrays:
*
* - an array of N AF_PointRec items
* - an array of 2*N AF_SegmentRec items
* - an array of 2*N AF_EdgeRec items
*
*/
new_max = ( new_max + 2 + 7 ) & ~7;
#undef OFF_INCREMENT
#define OFF_INCREMENT( _off, _type, _count ) \
((((_off) + sizeof(_type)) & ~(sizeof(_type)) + ((_count)*sizeof(_type)))
off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max );
off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
FT_FREE( hints->points );
if ( FT_ALLOC( items, off3 ) )
{
hints->max_points = 0;
hints->axis[0].segments = NULL;
hints->axis[0].edges = NULL;
hints->axis[1].segments = NULL;
hints->axis[1].edges = NULL;
goto Exit;
}
/* readjust some pointers
*/
hints->max_points = new_max;
hints->points = (AF_Point) items;
hints->axis[0].segments = (AF_Segment)( items + off1 );
hints->axis[1].segments = hints->axis[0].segments + new_max;
hints->axis[0].edges = (AF_Edge) ( items + off2 );
hints->axis[1].edges = hints->axis[0].edges + new_max;
}
hints->num_points = outline->n_points;
hints->num_contours = outline->n_contours;
/* We can't rely on the value of `FT_Outline.flags' to know the fill */
/* direction used for a glyph, given that some fonts are broken (e.g. */
/* the Arphic ones). We thus recompute it each time we need to. */
/* */
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
{
hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
}
hints->x_scale = x_scale;
hints->y_scale = y_scale;
points = hints->points;
if ( hints->num_points == 0 )
goto Exit;
{
/* do one thing at a time -- it is easier to understand, and */
/* the code is clearer */
AF_Point point;
AF_Point point_limit = points + hints->num_points;
/* compute coordinates & bezier flags */
{
FT_Vector* vec = outline->points;
char* tag = outline->tags;
for ( point = points; point < point_limit; point++, vec++, tag++ )
{
point->fx = vec->x;
point->fy = vec->y;
point->ox = point->x = FT_MulFix( vec->x, x_scale );
point->oy = point->y = FT_MulFix( vec->y, y_scale );
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_CURVE_TAG_CONIC:
point->flags = AF_FLAG_CONIC;
break;
case FT_CURVE_TAG_CUBIC:
point->flags = AF_FLAG_CUBIC;
break;
default:
point->flags = 0;
;
}
}
}
/* compute `next' and `prev' */
{
FT_Int contour_index;
AF_Point prev;
AF_Point first;
AF_Point end;
contour_index = 0;
first = points;
end = points + outline->contours[0];
prev = end;
for ( point = points; point < point_limit; point++ )
{
point->prev = prev;
if ( point < end )
{
point->next = point + 1;
prev = point;
}
else
{
point->next = first;
contour_index++;
if ( point + 1 < point_limit )
{
end = points + source->contours[contour_index];
first = point + 1;
prev = end;
}
}
}
}
/* set-up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
short* end = outline->contours;
short idx = 0;
for ( ; contour < contour_limit; contour++, end++ )
{
contour[0] = points + idx;
idx = (short)( end[0] + 1 );
}
}
/* compute directions of in & out vectors */
{
for ( point = points; point < point_limit; point++ )
{
AF_Point prev;
AF_Point next;
FT_Pos in_x, in_y, out_x, out_y;
prev = point->prev;
in_x = point->fx - prev->fx;
in_y = point->fy - prev->fy;
point->in_dir = af_compute_direction( in_x, in_y );
next = point->next;
out_x = next->fx - point->fx;
out_y = next->fy - point->fy;
point->out_dir = af_compute_direction( out_x, out_y );
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
Is_Weak_Point:
point->flags |= AF_FLAG_WEAK_INTERPOLATION;
}
else if ( point->out_dir == point->in_dir )
{
AF_Angle angle_in, angle_out, delta;
if ( point->out_dir != AF_DIR_NONE )
goto Is_Weak_Point;
angle_in = af_angle( in_x, in_y );
angle_out = af_angle( out_x, out_y );
delta = af_angle_diff( angle_in, angle_out );
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;
}
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
}
}
}
/* compute inflection points
*/
af_outline_hints_compute_inflections( hints );
Exit:
return error;
}
FT_LOCAL_DEF( void )
af_outline_hints_setup_uv( AF_OutlineHints hints,
AF_UV source )
{
AF_Point point = hints->points;
AF_Point point_limit = point + hints->num_points;
switch ( source )
{
case AF_UV_FXY:
for ( ; point < point_limit; point++ )
{
point->u = point->fx;
point->v = point->fy;
}
break;
case AF_UV_FYX:
for ( ; point < point_limit; point++ )
{
point->u = point->fy;
point->v = point->fx;
}
break;
case AF_UV_OXY:
for ( ; point < point_limit; point++ )
{
point->u = point->ox;
point->v = point->oy;
}
break;
case AF_UV_OYX:
for ( ; point < point_limit; point++ )
{
point->u = point->oy;
point->v = point->ox;
}
break;
case AF_UV_YX:
for ( ; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->x;
}
break;
case AF_UV_OX:
for ( ; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->ox;
}
break;
case AF_UV_OY:
for ( ; point < point_limit; point++ )
{
point->u = point->y;
point->v = point->oy;
}
break;
default:
for ( ; point < point_limit; point++ )
{
point->u = point->x;
point->v = point->y;
}
}
}
--- NEW FILE: afhints.h ---
#ifndef __AFHINTS_H__
#define __AFHINTS_H__
#include "aftypes.h"
FT_BEGIN_HEADER
/*
* The definition of outline hints. These are shared by all
* script analysis routines
*
*/
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; /* link segment */
AF_Segment serif; /* primary segment for serifs */
FT_Pos num_linked; /* number of linked segments */
FT_Pos score;
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 */
FT_Pos* 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_OutlineHintsRec_
{
FT_Memory memory;
FT_Fixed x_scale;
FT_Fixed y_scale;
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 ];
} AF_OutlineHintsRec;
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy );
FT_LOCAL( void )
af_outline_hints_init( AF_OutlineHints hints );
/* used to set the (u,v) fields of each AF_Point in a AF_OutlineHints
* object.
*/
typedef enum AH_UV_
{
AH_UV_FXY, /* (u,v) = (fx,fy) */
AH_UV_FYX, /* (u,v) = (fy,fx) */
AH_UV_OXY, /* (u,v) = (ox,oy) */
AH_UV_OYX, /* (u,v) = (oy,ox) */
AH_UV_OX, /* (u,v) = (ox,x) */
AH_UV_OY, /* (u,v) = (oy,y) */
AH_UV_YX, /* (u,v) = (y,x) */
AH_UV_XY /* (u,v) = (x,y) * should always be last! */
} AH_UV;
FT_LOCAL_DEF( void )
af_outline_hints_setup_uv( AF_OutlineHints hints,
AF_UV source );
/* recomputes all AF_Point in a AF_OutlineHints from the definitions
* in a source outline
*/
FT_LOCAL( FT_Error )
af_outline_hints_reset( AF_OutlineHints hints,
FT_Outline* outline,
FT_Fixed x_scale,
FT_Fixed y_scale );
FT_LOCAL( void )
af_outline_hints_done( AF_OutlineHints hints );
/* */
FT_END_HEADER
#endif /* __AFHINTS_H__ */
--- NEW FILE: aflatin.c ---
#include "aflatin.h"
FT_LOCAL_DEF( void )
af_latin_hints_compute_segments( AF_OutlineHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment = segments;
FT_Int num_segments = 0;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
AF_Direction major_dir;
#ifdef AF_HINT_METRICS
AF_Point min_point = 0;
AF_Point max_point = 0;
FT_Pos min_coord = 32000;
FT_Pos max_coord = -32000;
#endif
major_dir = ABS( axis->major_dir );
segment_dir = major_dir;
/* set up (u,v) in each point */
af_setup_uv( outline, (dim == AF_DIMENSION_HORZ)
? AF_UV_FXY,
: AF_UV_FYX );
/* do each contour separately */
for ( ; contour < contour_limit; contour++ )
{
AF_Point point = contour[0];
AF_Point last = point->prev;
int on_edge = 0;
FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */
FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */
FT_Bool passed;
#ifdef AF_HINT_METRICS
if ( point->u < min_coord )
{
min_coord = point->u;
min_point = point;
}
if ( point->u > max_coord )
{
max_coord = point->u;
max_point = point;
}
#endif
if ( point == last ) /* skip singletons -- just in case */
continue;
if ( ABS( last->out_dir ) == major_dir &&
ABS( point->out_dir ) == major_dir )
{
/* we are already on an edge, try to locate its start */
last = point;
for (;;)
{
point = point->prev;
if ( ABS( point->out_dir ) != major_dir )
{
point = point->next;
break;
}
if ( point == last )
break;
}
}
last = point;
passed = 0;
for (;;)
{
FT_Pos u, v;
if ( on_edge )
{
u = point->u;
if ( u < min_pos )
min_pos = u;
if ( u > max_pos )
max_pos = u;
if ( point->out_dir != segment_dir || point == last )
{
/* we are just leaving an edge; record a new segment! */
segment->last = point;
segment->pos = ( min_pos + max_pos ) >> 1;
/* a segment is round if either its first or last point */
/* is a control point */
if ( ( segment->first->flags | point->flags ) &
AF_FLAG_CONTROL )
segment->flags |= AF_EDGE_ROUND;
/* compute segment size */
min_pos = max_pos = point->v;
v = segment->first->v;
if ( v < min_pos )
min_pos = v;
if ( v > max_pos )
max_pos = v;
segment->min_coord = min_pos;
segment->max_coord = max_pos;
on_edge = 0;
num_segments++;
segment++;
/* fallthrough */
}
}
/* now exit if we are at the start/end point */
if ( point == last )
{
if ( passed )
break;
passed = 1;
}
if ( !on_edge && ABS( point->out_dir ) == major_dir )
{
/* this is the start of a new segment! */
segment_dir = point->out_dir;
/* clear all segment fields */
FT_ZERO( segment );
segment->dir = segment_dir;
segment->flags = AF_EDGE_NORMAL;
min_pos = max_pos = point->u;
segment->first = point;
segment->last = point;
segment->contour = contour;
segment->score = 32000;
segment->link = NULL;
on_edge = 1;
#ifdef AF_HINT_METRICS
if ( point == max_point )
max_point = 0;
if ( point == min_point )
min_point = 0;
#endif
}
point = point->next;
}
} /* contours */
#ifdef AF_HINT_METRICS
/* we need to ensure that there are edges on the left-most and */
/* right-most points of the glyph in order to hint the metrics; */
/* we do this by inserting fake segments when needed */
if ( dim == AF_DIMENSION_HORZ )
{
AF_Point point = hints->points;
AF_Point point_limit = point + hints->num_points;
FT_Pos min_pos = 32000;
FT_Pos max_pos = -32000;
min_point = 0;
max_point = 0;
/* compute minimum and maximum points */
for ( ; point < point_limit; point++ )
{
FT_Pos x = point->fx;
if ( x < min_pos )
{
min_pos = x;
min_point = point;
}
if ( x > max_pos )
{
max_pos = x;
max_point = point;
}
}
/* insert minimum segment */
if ( min_point )
{
/* clear all segment fields */
FT_ZERO( segment );
segment->dir = segment_dir;
segment->flags = AF_EDGE_NORMAL;
segment->first = min_point;
segment->last = min_point;
segment->pos = min_pos;
segment->score = 32000;
segment->link = NULL;
num_segments++;
segment++;
}
/* insert maximum segment */
if ( max_point )
{
/* clear all segment fields */
FT_ZERO( segment );
segment->dir = segment_dir;
segment->flags = AF_EDGE_NORMAL;
segment->first = max_point;
segment->last = max_point;
segment->pos = max_pos;
segment->score = 32000;
segment->link = NULL;
num_segments++;
segment++;
}
}
#endif /* AF_HINT_METRICS */
axis->num_segments = num_segments;
}
FT_LOCAL_DEF( void )
af_latin_hints_link_segments( AF_OutlineHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
AF_Direction major_dir = axis->major_dir;
AF_Segment seg1, seg2;
/* now compare each segment to the others */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
/* the fake segments are introduced to hint the metrics -- */
/* we must never link them to anything */
if ( seg1->first == seg1->last || seg1->dir != major_dir )
continue;
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 )
{
FT_Pos pos1 = seg1->pos;
FT_Pos pos2 = seg2->pos;
FT_Pos dist = pos2 - pos1;
if ( dist < 0 )
continue;
{
FT_Pos min = seg1->min_coord;
FT_Pos max = seg1->max_coord;
FT_Pos len, score;
if ( min < seg2->min_coord )
min = seg2->min_coord;
if ( max > seg2->max_coord )
max = seg2->max_coord;
len = max - min;
if ( len >= 8 )
{
score = dist + 3000 / len;
if ( score < seg1->score )
{
seg1->score = score;
seg1->link = seg2;
}
if ( score < seg2->score )
{
seg2->score = score;
seg2->link = seg1;
}
}
}
}
}
/* now, compute the `serif' segments */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
seg2 = seg1->link;
if ( seg2 )
{
seg2->num_linked++;
if ( seg2->link != seg1 )
{
seg1->link = 0;
seg1->serif = seg2->link;
}
}
}
}
FT_LOCAL_DEF( void )
af_latin_hints_compute_edges( AF_OutlineHints hints,
AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
AF_Edge edge, edge_limit;
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
AF_Segment seg;
AF_Direction up_dir;
FT_Fixed scale;
FT_Pos edge_distance_threshold;
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
: hints->y_scale;
up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
: AF_DIR_RIGHT;
/*********************************************************************/
/* */
/* We will begin by generating a sorted table of edges for the */
/* current direction. To do so, we simply scan each segment and try */
/* to find an edge in our table that corresponds to its position. */
/* */
/* If no edge is found, we create and insert a new edge in the */
/* sorted table. Otherwise, we simply add the segment to the edge's */
/* list which will be processed in the second step to compute the */
/* edge's properties. */
/* */
/* Note that the edges table is sorted along the segment/edge */
/* position. */
/* */
/*********************************************************************/
edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold,
scale );
if ( edge_distance_threshold > 64 / 4 )
edge_distance_threshold = 64 / 4;
edge_distance_threshold = FT_DivFix( edge_distance_threshold,
scale );
edge_limit = edges;
for ( seg = segments; seg < segment_limit; seg++ )
{
AF_Edge found = 0;
/* look for an edge corresponding to the segment */
for ( edge = edges; edge < edge_limit; edge++ )
{
FT_Pos dist;
dist = seg->pos - edge->fpos;
if ( dist < 0 )
dist = -dist;
if ( dist < edge_distance_threshold )
{
found = edge;
break;
}
}
if ( !found )
{
/* insert a new edge in the list and */
/* sort according to the position */
while ( edge > edges && edge[-1].fpos > seg->pos )
{
edge[0] = edge[-1];
edge--;
}
edge_limit++;
/* clear all edge fields */
FT_MEM_ZERO( edge, sizeof ( *edge ) );
/* add the segment to the new edge's list */
edge->first = seg;
edge->last = seg;
edge->fpos = seg->pos;
edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
seg->edge_next = seg;
}
else
{
/* if an edge was found, simply add the segment to the edge's */
/* list */
seg->edge_next = edge->first;
edge->last->edge_next = seg;
edge->last = seg;
}
}
*p_num_edges = (FT_Int)( edge_limit - edges );
/*********************************************************************/
/* */
/* Good, we will now compute each edge's properties according to */
/* segments found on its position. Basically, these are: */
/* */
/* - edge's main direction */
/* - stem edge, serif edge or both (which defaults to stem then) */
/* - rounded edge, straight or both (which defaults to straight) */
/* - link for edge */
/* */
/*********************************************************************/
/* first of all, set the `edge' field in each segment -- this is */
/* required in order to compute edge links */
/* Note that I've tried to remove this loop, setting
* the "edge" field of each segment directly in the
* code above. For some reason, it slows down execution
* speed -- on a Sun.
*/
for ( edge = edges; edge < edge_limit; edge++ )
{
seg = edge->first;
if ( seg )
do
{
seg->edge = edge;
seg = seg->edge_next;
}
while ( seg != edge->first );
}
/* now, compute each edge properties */
for ( edge = edges; edge < edge_limit; edge++ )
{
FT_Int is_round = 0; /* does it contain round segments? */
FT_Int is_straight = 0; /* does it contain straight segments? */
FT_Pos ups = 0; /* number of upwards segments */
FT_Pos downs = 0; /* number of downwards segments */
seg = edge->first;
do
{
FT_Bool is_serif;
/* check for roundness of segment */
if ( seg->flags & AF_EDGE_ROUND )
is_round++;
else
is_straight++;
/* check for segment direction */
if ( seg->dir == up_dir )
ups += seg->max_coord-seg->min_coord;
else
downs += seg->max_coord-seg->min_coord;
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );
if ( seg->link || is_serif )
{
AF_Edge edge2;
AF_Segment seg2;
edge2 = edge->link;
seg2 = seg->link;
if ( is_serif )
{
seg2 = seg->serif;
edge2 = edge->serif;
}
if ( edge2 )
{
FT_Pos edge_delta;
FT_Pos seg_delta;
edge_delta = edge->fpos - edge2->fpos;
if ( edge_delta < 0 )
edge_delta = -edge_delta;
seg_delta = seg->pos - seg2->pos;
if ( seg_delta < 0 )
seg_delta = -seg_delta;
if ( seg_delta < edge_delta )
edge2 = seg2->edge;
}
else
edge2 = seg2->edge;
#ifdef FT_CONFIG_CHESTER_SERIF
if ( is_serif )
{
edge->serif = edge2;
edge2->flags |= AF_EDGE_SERIF;
}
else
edge->link = edge2;
#else /* !FT_CONFIG_CHESTER_SERIF */
if ( is_serif )
edge->serif = edge2;
else
edge->link = edge2;
#endif /* !FT_CONFIG_CHESTER_SERIF */
}
seg = seg->edge_next;
} while ( seg != edge->first );
/* set the round/straight flags */
edge->flags = AF_EDGE_NORMAL;
if ( is_round > 0 && is_round >= is_straight )
edge->flags |= AF_EDGE_ROUND;
/* set the edge's main direction */
edge->dir = AF_DIR_NONE;
if ( ups > downs )
edge->dir = up_dir;
else if ( ups < downs )
edge->dir = -up_dir;
else if ( ups == downs )
edge->dir = 0; /* both up and down! */
/* gets rid of serifs if link is set */
/* XXX: This gets rid of many unpleasant artefacts! */
/* Example: the `c' in cour.pfa at size 13 */
if ( edge->serif && edge->link )
edge->serif = 0;
}
}
/*************************************************************************/
/* */
/* <Function> */
/* af_outline_detect_features */
/* */
/* <Description> */
/* Performs feature detection on a given AF_OutlineRec object. */
/* */
FT_LOCAL_DEF( void )
af_latin_hints_detect_features( AF_OutlineHints hints,
AF_Dimension dim )
{
af_latin_hints_compute_segments( hints, dim );
af_latin_hints_link_segments ( hints, dim );
af_latin_hints_compute_edges ( hints dim );
}
/*************************************************************************/
/* */
/* <Function> */
/* af_outline_compute_blue_edges */
/* */
/* <Description> */
/* Computes the `blue edges' in a given outline (i.e. those that must */
/* be snapped to a blue zone edge (top or bottom). */
/* */
FT_LOCAL_DEF( void )
af_latin_hints_compute_blue_edges( AF_OutlineHints outline,
AF_Face_Globals face_globals )
{
AF_Edge edge = outline->horz_edges;
AF_Edge edge_limit = edge + outline->num_hedges;
AF_Globals globals = &face_globals->design;
FT_Fixed y_scale = outline->y_scale;
FT_Bool blue_active[AF_BLUE_MAX];
/* compute which blue zones are active, i.e. have their scaled */
/* size < 3/4 pixels */
{
AF_Blue blue;
FT_Bool check = 0;
for ( blue = AF_BLUE_CAPITAL_TOP; blue < AF_BLUE_MAX; blue++ )
{
FT_Pos ref, shoot, dist;
ref = globals->blue_refs[blue];
shoot = globals->blue_shoots[blue];
dist = ref - shoot;
if ( dist < 0 )
dist = -dist;
blue_active[blue] = 0;
if ( FT_MulFix( dist, y_scale ) < 48 )
{
blue_active[blue] = 1;
check = 1;
}
}
/* return immediately if no blue zone is active */
if ( !check )
return;
}
/* for each horizontal edge search the blue zone which is closest */
for ( ; edge < edge_limit; edge++ )
{
AF_Blue blue;
FT_Pos* best_blue = 0;
FT_Pos best_dist; /* initial threshold */
/* compute the initial threshold as a fraction of the EM size */
best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
#ifdef FT_CONFIG_CHESTER_SMALL_F
if ( best_dist > 64 / 2 )
best_dist = 64 / 2;
#else
if ( best_dist > 64 / 4 )
best_dist = 64 / 4;
#endif
for ( blue = AF_BLUE_CAPITAL_TOP; blue < AF_BLUE_MAX; blue++ )
{
/* if it is a top zone, check for right edges -- if it is a bottom */
/* zone, check for left edges */
/* */
/* of course, that's for TrueType XXX */
FT_Bool is_top_blue =
FT_BOOL( AF_IS_TOP_BLUE( blue ) );
FT_Bool is_major_dir =
FT_BOOL( edge->dir == outline->horz_major_dir );
if ( !blue_active[blue] )
continue;
/* if it is a top zone, the edge must be against the major */
/* direction; if it is a bottom zone, it must be in the major */
/* direction */
if ( is_top_blue ^ is_major_dir )
{
FT_Pos dist;
FT_Pos* blue_pos = globals->blue_refs + blue;
/* first of all, compare it to the reference position */
dist = edge->fpos - *blue_pos;
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, y_scale );
if ( dist < best_dist )
{
best_dist = dist;
best_blue = blue_pos;
}
/* now, compare it to the overshoot position if the edge is */
/* rounded, and if the edge is over the reference position of a */
/* top zone, or under the reference position of a bottom zone */
if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < *blue_pos );
if ( is_top_blue ^ is_under_ref )
{
blue_pos = globals->blue_shoots + blue;
dist = edge->fpos - *blue_pos;
if ( dist < 0 )
dist = -dist;
dist = FT_MulFix( dist, y_scale );
if ( dist < best_dist )
{
best_dist = dist;
best_blue = blue_pos;
}
}
}
}
}
if ( best_blue )
edge->blue_edge = best_blue;
}
}
/*************************************************************************/
/* */
/* <Function> */
/* af_outline_scale_blue_edges */
/* */
/* <Description> */
/* This function must be called before hinting in order to re-adjust */
/* the contents of the detected edges (basically change the `blue */
/* edge' pointer from `design units' to `scaled ones'). */
/* */
FT_LOCAL_DEF( void )
af_outline_hints_scale_blue_edges( AF_OutlineHints hints ) outline,
{
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
AF_Edge edge = axis->edges;
AF_Edge edge_limit = edge + axis->num_edges;
FT_Pos delta;
delta = globals->scaled.blue_refs - globals->design.blue_refs;
for ( ; edge < edge_limit; edge++ )
{
if ( edge->blue_edge )
edge->blue_edge += delta;
}
}
--- NEW FILE: aflatin.h ---
#ifndef __AFLATIN_H__
#define __AFLATIN_H__
#include "afhints.h"
FT_BEGIN_HEADER
/*
* the latin-specific script class
*
*/
FT_LOCAL( const FT_ScriptClassRec ) af_latin_script_class;
/*
* the following declarations could be embedded in the file "aflatin.c"
* they've been made semi-public to allow alternate script hinters to
* re-use some of them
*/
/*
* Latin (global) metrics management
*
*/
#define AF_LATIN_MAX_WIDTHS 16
#define AF_LATIN_MAX_BLUES 32
typedef struct AF_LatinAxisRec_
{
FT_Fixed scale;
FT_Pos delta;
FT_UInt width_count;
AF_WidthRec widths[ AF_LATIN_MAX_WIDTHS ];
/* ignored for horizontal metrics */
FT_Bool control_overshoot;
FT_UInt blue_count;
AF_WidthRec blue_refs [ AF_MAX_BLUES ];
AF_WidthRec blue_shoots[ AF_MAX_BLUES ];
} AF_LatinAxisRec, *AF_LatinAxis;
typedef struct AF_LatinMetricsRec_
{
AF_OutlineMetricsRec root;
AF_LatinAxisRec axis[ AF_DIMENSION_MAX ];
} AF_LatinMetricsRec, *AF_LatinMetrics;
FT_LOCAL( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face );
FT_LOCAL( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler );
/*
* Latin (glyph) hints management
*
*/
FT_LOCAL(
FT_LOCAL( void )
af_latin_hints_compute_segments( AF_OutlineHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_link_segments( AF_OutlineHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_compute_edges( AF_OutlineHints hints,
AF_Dimension dim );
FT_LOCAL( void )
af_latin_hints_init( AF_OutlineHints hints,
AF_Dimension dim );
/* */
FT_END_HEADER
#endif /* __AFLATIN_H__ */
--- NEW FILE: aftypes.h ---
#ifndef __AFTYPES_H__
#define __AFTYPES_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 */
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** 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 afangle.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( 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 *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
typedef struct AF_OutlineHintsRec_* AF_OutlineHints;
typedef struct AF_GlobalHintsRec_* AF_GlobalHints;
typedef struct AF_OutlineRec_
{
FT_Memory memory;
FT_Face face;
FT_OutlineRec outline;
FT_UInt outline_resolution;
FT_Int advance;
FT_UInt metrics_resolution;
AF_OutlineHints hints;
} AF_OutlineRec;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** G L O B A L M E T R I C S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* the following define global metrics in a _single_ dimension
*
* the "blue_refs" and "blue_shoots" arrays are ignored in
* the horizontal dimension
*/
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;
#define AF_MAX_WIDTHS 16
#define AF_MAX_BLUES 32
typedef struct AF_GlobalMetricsRec_
{
FT_Int num_widths;
AF_WidthRec widths[ AF_MAX_WIDTHS ];
FT_Fixed scale; /* used to scale from org to cur with: */
FT_Pos delta; /* x_cur = x_org * scale + delta */
/* ignored for horizontal metrics */
AF_WidthRec blue_refs [ AF_MAX_BLUES ];
AF_WidthRec blue_shoots[ AF_MAX_BLUES ];
FT_Bool control_overshoot;
} AF_GlobalMetricsRec, *AF_GlobalMetrics;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** 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 wether the face supports the
* script
*
* - a specific global analyzer that will compute global metrics
* specific to the script.
*
* - a specific hinting routine
*
* all scripts should share the same analysis routine though
*/
typedef enum
{
AF_SCRIPT_LATIN = 0,
/* add new scripts here */
AF_SCRIPT_MAX /* do not remove */
} AF_Script;
typedef struct AF_ScriptClassRec_ const* AF_ScriptClass;
/*
* root class for script-specific metrics
*/
typedef struct AF_ScriptMetricsRec_
{
AF_ScriptClass script_class;
AF_GlobalMetricsRec horz_metrics;
AF_GlobalMetricsRec vert_metrics;
} 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_OutlineHints hints,
AF_Scaler scaler,
AF_ScriptMetrics metrics );
typedef void (*AF_Script_ApplyHintsFunc)( AF_OutlineHints hints );
typedef struct AF_Script_UniRangeRec_
{
FT_UInt32 first;
FT_UInt32 last;
} AF_Script_UniRangeRec, *AF_Script_UniRange;
typedef struct AF_ScriptClassRec_
{
AF_Script script;
AF_Scipt_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_ScriptClassRec;
/**************************************************************************/
/**************************************************************************/
/***** *****/
/***** F A C E G L O B A L S *****/
/***** *****/
/**************************************************************************/
/**************************************************************************/
/*
* models the global hints data for a given face, decomposed into
* script-specific items..
*
*/
typedef struct AF_FaceGlobalsRec_
{
FT_Face face;
FT_UInt glyph_count; /* same as face->num_glyphs */
FT_Byte* glyph_scripts; /* maps each gindex to a script */
FT_ScriptMetrics metrics[ AF_SCRIPT_MAX ];
} AF_FaceGlobalsRec, *AF_FaceGlobals;
/* */
FT_END_HEADER
#endif /* __AFTYPES_H__ */
- Previous message: [xorg-commit-diffs] xc/extras/freetype2/objs .cvsignore, 1.1.1.1,
1.1.1.1.2.1
- Next message: [xorg-commit-diffs] xc/extras/freetype2/src/autohint ahglobal.c,
1.1.4.1, 1.1.4.2 ahglobal.h, 1.1.4.1, 1.1.4.2 ahglyph.c,
1.1.4.1, 1.1.4.2 ahhint.c, 1.1.4.1, 1.1.4.2 ahloader.h,
1.1.4.1, 1.1.4.2 ahmodule.c, 1.1.4.1, 1.1.4.2 ahtypes.h,
1.1.4.1, 1.1.4.2 rules.mk, 1.1, 1.1.4.1 ahoptim.c, 1.1.4.1,
NONE ahoptim.h, 1.1.4.1, NONE descrip.mms, 1.1, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the xorg-commit-diffs
mailing list