experimental changes to debug the auto-hinter. These are not

worthy of a Changelog entry yet..
This commit is contained in:
David Turner 2001-10-29 10:45:57 +00:00
parent 75133bff1d
commit b92479b8c2
7 changed files with 344 additions and 87 deletions

View File

@ -92,7 +92,7 @@ FT_BEGIN_HEADER
/* handle to cache class */
typedef const struct FTC_Cache_ClassRec_* FTC_Cache_Class;
/* handle to cache node */
typedef struct FTC_NodeRec_* FTC_Node;
@ -109,21 +109,17 @@ FT_BEGIN_HEADER
/* <Fields> */
/* library :: A handle to a FreeType library instance. */
/* */
/* faces_lru :: The lru list of FT_Face objects in the cache. */
/* faces_list :: The lru list of FT_Face objects in the cache. */
/* */
/* sizes_lru :: The lru list of FT_Size objects in the cache. */
/* sizes_list :: The lru list of FT_Size objects in the cache. */
/* */
/* max_bytes :: The maximum number of bytes to be allocated in the */
/* cache. This is only related to the byte size of */
/* the nodes cached by the manager. */
/* max_weight :: The maximum cache pool weight.. */
/* */
/* num_bytes :: The current number of bytes allocated in the */
/* cache. Only related to the byte size of cached */
/* nodes. */
/* cur_weight :: The current cache pool weight. */
/* */
/* num_nodes :: The current number of nodes in the manager. */
/* */
/* global_lru :: The global lru list of all cache nodes. */
/* nodes_list :: The global lru list of all cache nodes. */
/* */
/* caches :: A table of installed/registered cache objects. */
/* */
@ -206,7 +202,7 @@ FT_BEGIN_HEADER
FTC_Node mru_prev; /* circular mru list pointer */
FTC_Node link; /* used for hashing.. */
FT_UInt32 hash; /* used for hashing too.. */
FT_UShort cache_index; /* index of cache this node belongs to */
FT_UShort cache_index; /* index of cache the node belongs to */
FT_Short ref_count; /* reference count for this node.. */
} FTC_NodeRec;

View File

@ -367,9 +367,9 @@
vec->x = point->x;
vec->y = point->y;
if ( point->flags & ah_flah_conic )
if ( point->flags & ah_flag_conic )
tag[0] = FT_Curve_Tag_Conic;
else if ( point->flags & ah_flah_cubic )
else if ( point->flags & ah_flag_cubic )
tag[0] = FT_Curve_Tag_Cubic;
else
tag[0] = FT_Curve_Tag_On;
@ -504,9 +504,9 @@
switch ( FT_CURVE_TAG( *tag ) )
{
case FT_Curve_Tag_Conic:
point->flags = ah_flah_conic; break;
point->flags = ah_flag_conic; break;
case FT_Curve_Tag_Cubic:
point->flags = ah_flah_cubic; break;
point->flags = ah_flag_cubic; break;
default:
;
}
@ -570,47 +570,50 @@
{
AH_Point* prev;
AH_Point* next;
FT_Vector vec;
FT_Vector ivec, ovec;
prev = point->prev;
vec.x = point->fx - prev->fx;
vec.y = point->fy - prev->fy;
prev = point->prev;
ivec.x = point->fx - prev->fx;
ivec.y = point->fy - prev->fy;
point->in_dir = ah_compute_direction( vec.x, vec.y );
point->in_dir = ah_compute_direction( ivec.x, ivec.y );
next = point->next;
ovec.x = next->fx - point->fx;
ovec.y = next->fy - point->fy;
point->out_dir = ah_compute_direction( ovec.x, ovec.y );
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
point->in_angle = ah_angle( &vec );
#endif
next = point->next;
vec.x = next->fx - point->fx;
vec.y = next->fy - point->fy;
point->out_dir = ah_compute_direction( vec.x, vec.y );
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
point->out_angle = ah_angle( &vec );
if ( point->flags & (ah_flag_conic | ah_flag_cubic) )
{
AH_Angle delta = point->in_angle - point->out_angle;
Is_Weak_Point:
point->flags |= ah_flag_weak_interpolation;
}
else if ( point->out_dir == point->in_dir )
{
AH_Angle angle_in, angle_out, delta;
if ( point->out_dir != ah_dir_none )
goto Is_Weak_Point;
angle_in = ah_angle( &ivec );
angle_out = ah_angle( &ovec );
delta = angle_in - angle_out;
if ( delta > AH_PI )
delta = AH_2PI - delta;
if ( delta < 0 )
delta = -delta;
if ( delta < 2 )
point->flags |= ah_flah_weak_interpolation;
goto Is_Weak_Point;
}
#if 0
if ( point->flags & ( ah_flah_conic | ah_flah_cubic ) )
point->flags |= ah_flah_weak_interpolation;
#endif
#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
#ifdef AH_OPTION_NO_STRONG_INTERPOLATION
point->flags |= ah_flah_weak_interpolation;
else if ( point->in_dir == -point->out_dir )
goto Is_Weak_Point;
#endif
}
}
@ -779,7 +782,7 @@
/* a segment is round if either its first or last point */
/* is a control point */
if ( ( segment->first->flags | point->flags ) &
ah_flah_control )
ah_flag_control )
segment->flags |= ah_edge_round;
/* compute segment size */
@ -997,7 +1000,7 @@
/* before comparing the scores, take care that the segments */
/* are really facing each other (often not for italics..) */
if ( 4 * len >= size1 && 4 * len >= size2 )
if ( 16 * len >= size1 && 16 * len >= size2 )
if ( score < best_score )
{
best_score = score;

View File

@ -209,10 +209,10 @@
int has_serifs = 0;
if ( hinter->disable_vert_edges && !dimension )
if ( ah_debug_disable_vert && !dimension )
goto Next_Dimension;
if ( hinter->disable_horz_edges && dimension )
if ( ah_debug_disable_horz && dimension )
goto Next_Dimension;
/* we begin by aligning all stems relative to the blue zone */
@ -377,9 +377,10 @@
FT_Bool no_horz_edges,
FT_Bool no_vert_edges )
{
hinter->disable_horz_edges = no_horz_edges;
hinter->disable_vert_edges = no_vert_edges;
#if 0
ah_debug_disable_horz = no_horz_edges;
ah_debug_disable_vert = no_vert_edges;
#endif
/* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */
/* reduce the problem of the disappearing eye in the `e' of Times... */
/* also, creates some artifacts near the blue zones? */
@ -450,12 +451,12 @@
if ( dimension )
{
point->y = edge->pos;
point->flags |= ah_flah_touch_y;
point->flags |= ah_flag_touch_y;
}
else
{
point->x = edge->pos;
point->flags |= ah_flah_touch_x;
point->flags |= ah_flag_touch_x;
}
if ( point == seg->last )
@ -493,7 +494,7 @@
edges = outline->horz_edges;
edge_limit = edges + outline->num_hedges;
touch_flag = ah_flah_touch_y;
touch_flag = ah_flag_touch_y;
for ( dimension = 1; dimension >= 0; dimension-- )
{
@ -514,7 +515,7 @@
#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
/* if this point is candidate to weak interpolation, we will */
/* interpolate it after all strong points have been processed */
if ( point->flags & ah_flah_weak_interpolation )
if ( point->flags & ah_flag_weak_interpolation )
continue;
#endif
@ -598,7 +599,7 @@
edges = outline->vert_edges;
edge_limit = edges + outline->num_vedges;
touch_flag = ah_flah_touch_x;
touch_flag = ah_flag_touch_x;
}
}
@ -707,7 +708,7 @@
/* PASS 1: Move segment points to edge positions */
touch_flag = ah_flah_touch_y;
touch_flag = ah_flag_touch_y;
contour_limit = outline->contours + outline->num_contours;
@ -781,7 +782,7 @@
for ( point = points; point < point_limit; point++ )
point->y = point->u;
touch_flag = ah_flah_touch_x;
touch_flag = ah_flag_touch_x;
ah_setup_uv( outline, ah_uv_ox );
}
else

View File

@ -26,6 +26,8 @@
#ifdef DEBUG_HINTER
extern AH_Hinter* ah_debug_hinter = NULL;
extern FT_Bool ah_debug_disable_horz = 0;
extern FT_Bool ah_debug_disable_vert = 0;
#endif
typedef struct FT_AutoHinterRec_

View File

@ -83,7 +83,7 @@ FT_BEGIN_HEADER
/* detected and later hinted through strong interpolation to correct */
/* some unpleasant artefacts. */
/* */
#undef AH_OPTION_NO_STRONG_INTERPOLATION
#define AH_OPTION_NO_STRONG_INTERPOLATION
/*************************************************************************/
@ -126,27 +126,27 @@ FT_BEGIN_HEADER
/* hint flags */
#define ah_flah_none 0
#define ah_flag_none 0
/* bezier control points flags */
#define ah_flah_conic 1
#define ah_flah_cubic 2
#define ah_flah_control ( ah_flah_conic | ah_flah_cubic )
#define ah_flag_conic 1
#define ah_flag_cubic 2
#define ah_flag_control ( ah_flag_conic | ah_flag_cubic )
/* extrema flags */
#define ah_flah_extrema_x 4
#define ah_flah_extrema_y 8
#define ah_flag_extrema_x 4
#define ah_flag_extrema_y 8
/* roundness */
#define ah_flah_round_x 16
#define ah_flah_round_y 32
#define ah_flag_round_x 16
#define ah_flag_round_y 32
/* touched */
#define ah_flah_touch_x 64
#define ah_flah_touch_y 128
#define ah_flag_touch_x 64
#define ah_flag_touch_y 128
/* weak interpolation */
#define ah_flah_weak_interpolation 256
#define ah_flag_weak_interpolation 256
typedef FT_Int AH_Flags;
@ -485,13 +485,16 @@ FT_BEGIN_HEADER
FT_Vector trans_delta;
FT_Matrix trans_matrix;
FT_Bool disable_horz_edges;
FT_Bool disable_vert_edges;
} AH_Hinter;
#ifdef DEBUG_HINTER
extern AH_Hinter* ah_debug_hinter;
extern FT_Bool ah_debug_disable_horz;
extern FT_Bool ah_debug_disable_vert;
#else
# define ah_debug_disable_horz 0
# define ah_debug_disable_vert 0
#endif /* DEBUG_HINTER */
FT_END_HEADER

View File

@ -304,9 +304,12 @@
manager->library = library;
manager->max_weight = max_bytes;
manager->cur_weight = 0;
manager->request_face = requester;
manager->request_data = req_data;
*amanager = manager;
Exit:
@ -348,7 +351,7 @@
manager->caches[index] = 0;
}
}
/* discard faces and sizes */
FT_LruList_Destroy( manager->faces_list );
manager->faces_list = 0;

View File

@ -63,14 +63,17 @@ static int pixel_size = 12;
/************************************************************************/
/************************************************************************/
static int option_show_axis = 1;
static int option_show_dots = 1;
static int option_show_stroke = 0;
static int option_show_glyph = 1;
static int option_show_grid = 1;
static int option_show_em = 0;
static int option_show_smooth = 1;
static int option_show_blues = 0;
static int option_show_axis = 1;
static int option_show_dots = 1;
static int option_show_stroke = 0;
static int option_show_glyph = 1;
static int option_show_grid = 1;
static int option_show_em = 0;
static int option_show_smooth = 1;
static int option_show_blues = 0;
static int option_show_edges = 0;
static int option_show_segments = 1;
static int option_show_links = 1;
static int option_show_ps_hints = 1;
static int option_show_horz_hints = 1;
@ -106,6 +109,11 @@ static NV_Path symbol_rect_v = NULL;
#define STEM_HINT_COLOR 0xE02020FF
#define STEM_JOIN_COLOR 0xE020FF20
#define EDGE_COLOR 0xF0704070
#define SEGMENT_COLOR 0xF0206040
#define LINK_COLOR 0xF0FFFF00
#define SERIF_LINK_COLOR 0xF0FF808F
/* print message and abort program */
static void
Panic( const char* message )
@ -607,18 +615,251 @@ ps2_draw_control_points( void )
/************************************************************************/
/************************************************************************/
static void
ah_draw_smooth_points( AH_Hinter hinter )
static NV_Path
ah_link_path( NV_Vector* p1,
NV_Vector* p4,
NV_Bool vertical )
{
if ( ah_debug_hinter )
NV_PathWriter writer;
NV_Vector p2, p3;
NV_Path path, stroke;
if ( vertical )
{
p2.x = p4->x;
p2.y = p1->y;
p3.x = p1->x;
p3.y = p4->y;
}
else
{
p2.x = p1->x;
p2.y = p4->y;
p3.x = p4->x;
p3.y = p1->y;
}
nv_path_writer_new( renderer, &writer );
nv_path_writer_moveto( writer, p1 );
nv_path_writer_cubicto( writer, &p2, &p3, p4 );
nv_path_writer_end( writer );
path = nv_path_writer_get_path( writer );
nv_path_writer_destroy( writer );
nv_path_stroke( path, 1., nv_path_linecap_butt, nv_path_linejoin_round, 1., &stroke );
nv_path_destroy( path );
return stroke;
}
static void
ah_draw_smooth_points( void )
{
if ( ah_debug_hinter && option_show_smooth )
{
AH_Outline* glyph = ah_debug_hinter->glyph;
FT_UInt count = glyph->num_points;
AH_Point* point = glyph->points;
nv_painter_set_color( painter, SMOOTH_COLOR, 256 );
for ( ; count > 0; count--, point++ )
{
if ( !( point->flags & ah_flag_weak_interpolation ) )
{
NV_Transform transform, *trans = &transform;
NV_Vector vec;
vec.x = point->x - ah_debug_hinter->pp1.x;
vec.y = point->y;
nv_vector_transform( &vec, &size_transform );
nv_transform_set_translate( &transform, vec.x, vec.y );
nv_painter_fill_path( painter, trans, 0, symbol_circle );
}
}
}
}
static void
ah_draw_edges( AH_Hinter hinter )
ah_draw_edges( void )
{
if ( ah_debug_hinter )
{
AH_Outline* glyph = ah_debug_hinter->glyph;
FT_UInt count;
AH_Edge* edge;
FT_Pos pp1 = ah_debug_hinter->pp1.x;
nv_painter_set_color( painter, EDGE_COLOR, 256 );
if ( option_show_edges )
{
/* draw verticla edges */
if ( option_show_vert_hints )
{
count = glyph->num_vedges;
edge = glyph->vert_edges;
for ( ; count > 0; count--, edge++ )
{
NV_Vector vec;
NV_Pos x;
vec.x = edge->pos - pp1;
vec.y = 0;
nv_vector_transform( &vec, &size_transform );
x = (FT_Pos)( vec.x + 0.5 );
nv_pixmap_fill_rect( target, x, 0, 1, target->height, EDGE_COLOR );
}
}
/* draw horizontal edges */
if ( option_show_horz_hints )
{
count = glyph->num_hedges;
edge = glyph->horz_edges;
for ( ; count > 0; count--, edge++ )
{
NV_Vector vec;
NV_Pos x;
vec.x = 0;
vec.y = edge->pos;
nv_vector_transform( &vec, &size_transform );
x = (FT_Pos)( vec.y + 0.5 );
nv_pixmap_fill_rect( target, 0, x, target->width, 1, EDGE_COLOR );
}
}
}
if ( option_show_segments )
{
/* draw vertical segments */
if ( option_show_vert_hints )
{
AH_Segment* seg = glyph->vert_segments;
FT_UInt count = glyph->num_vsegments;
for ( ; count > 0; count--, seg++ )
{
AH_Point *first, *last;
NV_Vector v1, v2;
NV_Pos y1, y2, x;
first = seg->first;
last = seg->last;
v1.x = v2.x = first->x - pp1;
if ( first->y <= last->y )
{
v1.y = first->y;
v2.y = last->y;
}
else
{
v1.y = last->y;
v2.y = first->y;
}
nv_vector_transform( &v1, &size_transform );
nv_vector_transform( &v2, &size_transform );
y1 = (NV_Pos)( v1.y + 0.5 );
y2 = (NV_Pos)( v2.y + 0.5 );
x = (NV_Pos)( v1.x + 0.5 );
nv_pixmap_fill_rect( target, x-1, y2, 3, ABS(y1-y2)+1, SEGMENT_COLOR );
}
}
/* draw horizontal segments */
if ( option_show_horz_hints )
{
AH_Segment* seg = glyph->horz_segments;
FT_UInt count = glyph->num_hsegments;
for ( ; count > 0; count--, seg++ )
{
AH_Point *first, *last;
NV_Vector v1, v2;
NV_Pos y1, y2, x;
first = seg->first;
last = seg->last;
v1.y = v2.y = first->y;
if ( first->x <= last->x )
{
v1.x = first->x - pp1;
v2.x = last->x - pp1;
}
else
{
v1.x = last->x - pp1;
v2.x = first->x - pp1;
}
nv_vector_transform( &v1, &size_transform );
nv_vector_transform( &v2, &size_transform );
y1 = (NV_Pos)( v1.x + 0.5 );
y2 = (NV_Pos)( v2.x + 0.5 );
x = (NV_Pos)( v1.y + 0.5 );
nv_pixmap_fill_rect( target, y1, x-1, ABS(y1-y2)+1, 3, SEGMENT_COLOR );
}
}
if ( option_show_vert_hints && option_show_links )
{
AH_Segment* seg = glyph->vert_segments;
FT_UInt count = glyph->num_vsegments;
for ( ; count > 0; count--, seg++ )
{
AH_Segment* seg2 = NULL;
NV_Path link;
NV_Vector v1, v2;
if ( seg->link )
{
if ( seg->link > seg )
seg2 = seg->link;
}
else if ( seg->serif )
seg2 = seg->serif;
if ( seg2 )
{
v1.x = seg->first->x - pp1;
v2.x = seg2->first->x - pp1;
v1.y = (seg->first->y + seg->last->y)/2;
v2.y = (seg2->first->y + seg2->last->y)/2;
link = ah_link_path( &v1, &v2, 1 );
nv_painter_set_color( painter, seg->serif ? SERIF_LINK_COLOR : LINK_COLOR, 256 );
nv_painter_fill_path( painter, &size_transform, 0, link );
nv_path_destroy( link );
}
}
}
}
}
}
/************************************************************************/
@ -717,6 +958,9 @@ draw_glyph( int glyph_index )
}
}
ah_draw_smooth_points();
ah_draw_edges();
nv_path_destroy( path );
/* autre infos */
@ -908,7 +1152,7 @@ parse_options( int* argc_p, char*** argv_p )
int main( int argc, char** argv )
{
char* filename = "/fonts/lcdxsr.pfa";
char* filename = "/winnt/fonts/arial.ttf";
parse_options( &argc, &argv );
@ -958,7 +1202,12 @@ int main( int argc, char** argv )
clear_background();
draw_grid();
ps_debug_hints = 0;
ps_debug_hints = 0;
ah_debug_hinter = 0;
ah_debug_disable_vert = ps_debug_no_vert_hints;
ah_debug_disable_horz = ps_debug_no_horz_hints;
draw_ps_blue_zones();
draw_glyph( glyph_index );
ps2_draw_control_points();