ref: b92479b8c246e5ed1757d6dff2b5687085e0e451
parent: 75133bff1d216f7f45303a375a4f80e296d11902
author: David Turner <[email protected]>
date: Mon Oct 29 05:45:57 EST 2001
experimental changes to debug the auto-hinter. These are not worthy of a Changelog entry yet..
--- a/include/freetype/cache/ftcmanag.h
+++ b/include/freetype/cache/ftcmanag.h
@@ -92,7 +92,7 @@
/* 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 @@
/* <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 @@
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;
--- 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,48 +570,51 @@
{
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 );
-#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
- point->in_angle = ah_angle( &vec );
-#endif
+ next = point->next;
+ ovec.x = next->fx - point->fx;
+ ovec.y = next->fy - point->fy;
- next = point->next;
- vec.x = next->fx - point->fx;
- vec.y = next->fy - point->fy;
+ point->out_dir = ah_compute_direction( ovec.x, ovec.y );
- 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;
+ else if ( point->in_dir == -point->out_dir )
+ goto Is_Weak_Point;
#endif
-
-#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
-
-#ifdef AH_OPTION_NO_STRONG_INTERPOLATION
- point->flags |= ah_flah_weak_interpolation;
-#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;
--- 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
--- 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_
--- a/src/autohint/ahtypes.h
+++ b/src/autohint/ahtypes.h
@@ -83,7 +83,7 @@
/* 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 @@
/* 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_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
--- 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;
--- a/tests/gview.c
+++ b/tests/gview.c
@@ -63,14 +63,17 @@
/************************************************************************/
/************************************************************************/
-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 @@
#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 @@
/************************************************************************/
/************************************************************************/
+static NV_Path
+ah_link_path( NV_Vector* p1,
+ NV_Vector* p4,
+ NV_Bool vertical )
+{
+ 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( AH_Hinter hinter )
+ah_draw_smooth_points( void )
{
- if ( ah_debug_hinter )
+ 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 @@
}
}
+ ah_draw_smooth_points();
+ ah_draw_edges();
+
nv_path_destroy( path );
/* autre infos */
@@ -908,7 +1152,7 @@
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 @@
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();