From b92479b8c246e5ed1757d6dff2b5687085e0e451 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 29 Oct 2001 10:45:57 +0000 Subject: [PATCH] experimental changes to debug the auto-hinter. These are not worthy of a Changelog entry yet.. --- include/freetype/cache/ftcmanag.h | 18 +- src/autohint/ahglyph.c | 73 ++++---- src/autohint/ahhint.c | 25 +-- src/autohint/ahmodule.c | 2 + src/autohint/ahtypes.h | 31 ++-- src/cache/ftcmanag.c | 5 +- tests/gview.c | 277 ++++++++++++++++++++++++++++-- 7 files changed, 344 insertions(+), 87 deletions(-) diff --git a/include/freetype/cache/ftcmanag.h b/include/freetype/cache/ftcmanag.h index 0aa1086db..6355a5d32 100644 --- a/include/freetype/cache/ftcmanag.h +++ b/include/freetype/cache/ftcmanag.h @@ -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 /* */ /* 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; diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 16af5452e..f809d7e00 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -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; diff --git a/src/autohint/ahhint.c b/src/autohint/ahhint.c index 63a5d3492..1e2ebdbac 100644 --- a/src/autohint/ahhint.c +++ b/src/autohint/ahhint.c @@ -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 diff --git a/src/autohint/ahmodule.c b/src/autohint/ahmodule.c index c506bf85a..1b9b1881a 100644 --- a/src/autohint/ahmodule.c +++ b/src/autohint/ahmodule.c @@ -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_ diff --git a/src/autohint/ahtypes.h b/src/autohint/ahtypes.h index 941563b5c..ad12372b5 100644 --- a/src/autohint/ahtypes.h +++ b/src/autohint/ahtypes.h @@ -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 diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c index 08fe20270..4dffd246f 100644 --- a/src/cache/ftcmanag.c +++ b/src/cache/ftcmanag.c @@ -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; diff --git a/tests/gview.c b/tests/gview.c index d1cddcf9a..3bc214fc6 100644 --- a/tests/gview.c +++ b/tests/gview.c @@ -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();